-
Notifications
You must be signed in to change notification settings - Fork 4
/
decoder.go
89 lines (70 loc) · 2.3 KB
/
decoder.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package seekable
import "github.com/google/btree"
// Decoder is a byte-oriented API that is useful for cases where wrapping io.ReadSeeker is not desirable.
type Decoder interface {
// GetIndexByDecompOffset returns FrameOffsetEntry for an offset in the decompressed stream.
// Will return nil if offset is greater or equal than Size().
GetIndexByDecompOffset(off uint64) *FrameOffsetEntry
// GetIndexByID returns FrameOffsetEntry for a given frame id.
// Will return nil if offset is greater or equal than NumFrames() or less than 0.
GetIndexByID(id int64) *FrameOffsetEntry
// Size returns the size of the uncompressed stream.
Size() int64
// NumFrames returns number of frames in the compressed stream.
NumFrames() int64
}
// NewDecoder creates a byte-oriented Decode interface from a given seektable index.
// This index can either be produced by either Writer's WriteSeekTable or Encoder's EndStream.
// Decoder can be used concurrently.
func NewDecoder(seekTable []byte, decoder ZSTDDecoder, opts ...ROption) (Decoder, error) {
opts = append(opts, WithREnvironment(&decoderEnv{seekTable: seekTable}))
sr, err := NewReader(nil, decoder, opts...)
if err != nil {
return nil, err
}
// Release seekTable reference to not leak memory.
sr.(*ReaderImpl).o.env = nil
return sr.(*ReaderImpl), err
}
type decoderEnv struct {
seekTable []byte
}
func (d *decoderEnv) GetFrameByIndex(index FrameOffsetEntry) (p []byte, err error) {
panic("should not be used")
}
func (d *decoderEnv) ReadFooter() ([]byte, error) {
return d.seekTable, nil
}
func (d *decoderEnv) ReadSkipFrame(skippableFrameOffset int64) ([]byte, error) {
return d.seekTable, nil
}
func (s *ReaderImpl) Size() int64 {
return s.endOffset
}
func (s *ReaderImpl) NumFrames() int64 {
return s.numFrames
}
func (s *ReaderImpl) GetIndexByDecompOffset(off uint64) (found *FrameOffsetEntry) {
if off >= uint64(s.endOffset) {
return nil
}
s.index.DescendLessOrEqual(&FrameOffsetEntry{DecompOffset: off}, func(i btree.Item) bool {
found = i.(*FrameOffsetEntry)
return false
})
return
}
func (s *ReaderImpl) GetIndexByID(id int64) (found *FrameOffsetEntry) {
if id < 0 {
return nil
}
s.index.Descend(func(i btree.Item) bool {
index := i.(*FrameOffsetEntry)
if index.ID == id {
found = index
return false
}
return true
})
return
}