@@ -26,38 +26,60 @@ type IpldBlockstore interface {
26
26
Put (block.Block ) error
27
27
}
28
28
29
+ // IpldBlockstoreViewer is a trait that enables zero-copy access to blocks in
30
+ // a blockstore.
31
+ type IpldBlockstoreViewer interface {
32
+ // View provides zero-copy access to blocks in a blockstore. The callback
33
+ // function will be invoked with the value for the key. The user MUST not
34
+ // modify the byte array, as it could be memory-mapped.
35
+ View (cid.Cid , func ([]byte ) error ) error
36
+ }
37
+
29
38
// BasicIpldStore wraps and IpldBlockstore and implements the IpldStore interface.
30
39
type BasicIpldStore struct {
31
40
Blocks IpldBlockstore
32
- Atlas * atlas.Atlas
41
+ Viewer IpldBlockstoreViewer
42
+
43
+ Atlas * atlas.Atlas
33
44
}
34
45
35
46
var _ IpldStore = & BasicIpldStore {}
36
47
37
48
// NewCborStore returns an IpldStore implementation backed by the provided IpldBlockstore.
38
49
func NewCborStore (bs IpldBlockstore ) * BasicIpldStore {
39
- return & BasicIpldStore {Blocks : bs }
50
+ viewer , _ := bs .(IpldBlockstoreViewer )
51
+ return & BasicIpldStore {Blocks : bs , Viewer : viewer }
40
52
}
41
53
42
54
// Get reads and unmarshals the content at `c` into `out`.
43
55
func (s * BasicIpldStore ) Get (ctx context.Context , c cid.Cid , out interface {}) error {
56
+ if s .Viewer != nil {
57
+ // zero-copy path.
58
+ return s .Viewer .View (c , func (b []byte ) error {
59
+ return s .decode (b , out )
60
+ })
61
+ }
62
+
44
63
blk , err := s .Blocks .Get (c )
45
64
if err != nil {
46
65
return err
47
66
}
67
+ return s .decode (blk .RawData (), out )
68
+ }
48
69
70
+ func (s * BasicIpldStore ) decode (b []byte , out interface {}) error {
49
71
cu , ok := out .(cbg.CBORUnmarshaler )
50
72
if ok {
51
- if err := cu .UnmarshalCBOR (bytes .NewReader (blk . RawData () )); err != nil {
73
+ if err := cu .UnmarshalCBOR (bytes .NewReader (b )); err != nil {
52
74
return NewSerializationError (err )
53
75
}
54
76
return nil
55
77
}
56
78
57
79
if s .Atlas == nil {
58
- return DecodeInto (blk . RawData () , out )
80
+ return DecodeInto (b , out )
59
81
} else {
60
- return recbor .UnmarshalAtlased (recbor.DecodeOptions {}, blk . RawData () , out , * s .Atlas )
82
+ return recbor .UnmarshalAtlased (recbor.DecodeOptions {}, b , out , * s .Atlas )
61
83
}
62
84
}
63
85
0 commit comments