@@ -2,44 +2,53 @@ package format
2
2
3
3
import (
4
4
"fmt"
5
- "sync"
6
-
7
5
blocks "github.com/ipfs/go-block-format"
8
6
)
9
7
10
8
// DecodeBlockFunc functions decode blocks into nodes.
11
9
type DecodeBlockFunc func (block blocks.Block ) (Node , error )
12
10
13
- type BlockDecoder interface {
14
- Register (codec uint64 , decoder DecodeBlockFunc )
15
- Decode (blocks.Block ) (Node , error )
16
- }
17
- type safeBlockDecoder struct {
18
- // Can be replaced with an RCU if necessary.
19
- lock sync.RWMutex
11
+ // Registry is a structure for storing mappings of multicodec IPLD codec numbers to DecodeBlockFunc functions.
12
+ //
13
+ // Registry includes no mutexing. If using Registry in a concurrent context, you must handle synchronization yourself.
14
+ // (Typically, it is recommended to do initialization earlier in a program, before fanning out goroutines;
15
+ // this avoids the need for mutexing overhead.)
16
+ //
17
+ // Multicodec indicator numbers are specified in
18
+ // https://github.com/multiformats/multicodec/blob/master/table.csv .
19
+ // You should not use indicator numbers which are not specified in that table
20
+ // (however, there is nothing in this implementation that will attempt to stop you, either).
21
+ type Registry struct {
20
22
decoders map [uint64 ]DecodeBlockFunc
21
23
}
22
24
25
+ func (r * Registry ) ensureInit () {
26
+ if r .decoders != nil {
27
+ return
28
+ }
29
+ r .decoders = make (map [uint64 ]DecodeBlockFunc )
30
+ }
31
+
23
32
// Register registers decoder for all blocks with the passed codec.
24
33
//
25
34
// This will silently replace any existing registered block decoders.
26
- func (d * safeBlockDecoder ) Register (codec uint64 , decoder DecodeBlockFunc ) {
27
- d .lock .Lock ()
28
- defer d .lock .Unlock ()
29
- d .decoders [codec ] = decoder
35
+ func (r * Registry ) Register (codec uint64 , decoder DecodeBlockFunc ) {
36
+ r .ensureInit ()
37
+ if decoder == nil {
38
+ panic ("not sensible to attempt to register a nil function" )
39
+ }
40
+ r .decoders [codec ] = decoder
30
41
}
31
42
32
- func (d * safeBlockDecoder ) Decode (block blocks.Block ) (Node , error ) {
43
+ func (r * Registry ) Decode (block blocks.Block ) (Node , error ) {
33
44
// Short-circuit by cast if we already have a Node.
34
45
if node , ok := block .(Node ); ok {
35
46
return node , nil
36
47
}
37
48
38
49
ty := block .Cid ().Type ()
39
-
40
- d .lock .RLock ()
41
- decoder , ok := d .decoders [ty ]
42
- d .lock .RUnlock ()
50
+ r .ensureInit ()
51
+ decoder , ok := r .decoders [ty ]
43
52
44
53
if ok {
45
54
return decoder (block )
@@ -49,14 +58,13 @@ func (d *safeBlockDecoder) Decode(block blocks.Block) (Node, error) {
49
58
}
50
59
}
51
60
52
- var DefaultBlockDecoder BlockDecoder = & safeBlockDecoder {decoders : make (map [uint64 ]DecodeBlockFunc )}
53
-
54
- // Decode decodes the given block using the default BlockDecoder.
55
- func Decode (block blocks.Block ) (Node , error ) {
56
- return DefaultBlockDecoder .Decode (block )
57
- }
61
+ // Decode decodes the given block using passed DecodeBlockFunc.
62
+ // Note: this is just a helper function, consider using the DecodeBlockFunc itself rather than this helper
63
+ func Decode (block blocks.Block , decoder DecodeBlockFunc ) (Node , error ) {
64
+ // Short-circuit by cast if we already have a Node.
65
+ if node , ok := block .(Node ); ok {
66
+ return node , nil
67
+ }
58
68
59
- // Register registers block decoders with the default BlockDecoder.
60
- func Register (codec uint64 , decoder DecodeBlockFunc ) {
61
- DefaultBlockDecoder .Register (codec , decoder )
69
+ return decoder (block )
62
70
}
0 commit comments