-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchunk.go
68 lines (57 loc) · 1.6 KB
/
chunk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package gouch
import (
//"hash/crc32"
)
// ChunkLengthSize 32 bits long
const ChunkLengthSize int64 = 4
//ChunkCRCSize 32 bits long
const ChunkCRCSize int64 = 4
// attempt to read a chunk at the specified location
func (g *Gouch) readChunkAt(pos int64, header bool) ([]byte, error) {
var size uint32
var n int64
var err error
// chunk starts with 8 bytes (32bit length, 32bit crc)
if chunkPrefix, ok := eightByte.Get().([]byte); ok {
n, err = g.readAt(chunkPrefix, pos)
if err != nil {
return nil, err
}
if n < ChunkLengthSize+ChunkCRCSize {
return nil, nil
}
size = decodeRaw31(chunkPrefix[0:ChunkLengthSize])
//crc := decodeRaw32(chunkPrefix[ChunkLengthSize : ChunkLengthSize+ChunkCRCSize])
eightByte.Put(chunkPrefix)
}
// size should at least be the size of the length field + 1 (for headers)
if header && size < uint32(ChunkLengthSize+1) {
return nil, nil
}
if header {
size -= uint32(ChunkLengthSize) // headers include the length of the hash, data does not
}
data := make([]byte, size)
pos += n // skip the actual number of bytes read for the header (may be more than header size if we crossed a block boundary)
n, err = g.readAt(data, pos)
if uint32(n) < size {
return nil, nil
}
// validate crc
/*actualCRC := crc32.ChecksumIEEE(data)
if actualCRC != crc {
return nil, nil
}*/
return data, nil
}
func (g *Gouch) readCompressedDataChunkAt(pos int64) ([]byte, error) {
chunk, err := g.readChunkAt(pos, false)
if err != nil {
return nil, err
}
decompressedChunk, err := SnappyDecode(nil, chunk)
if err != nil {
return nil, err
}
return decompressedChunk, nil
}