package format import ( "fmt" "sync" blocks "github.com/ipfs/go-block-format" ) // DecodeBlockFunc functions decode blocks into nodes. type DecodeBlockFunc func(block blocks.Block) (Node, error) type BlockDecoder interface { Register(codec uint64, decoder DecodeBlockFunc) Decode(blocks.Block) (Node, error) } type safeBlockDecoder struct { // Can be replaced with an RCU if necessary. lock sync.RWMutex decoders map[uint64]DecodeBlockFunc } // Register registers decoder for all blocks with the passed codec. // // This will silently replace any existing registered block decoders. func (d *safeBlockDecoder) Register(codec uint64, decoder DecodeBlockFunc) { d.lock.Lock() defer d.lock.Unlock() d.decoders[codec] = decoder } func (d *safeBlockDecoder) Decode(block blocks.Block) (Node, error) { // Short-circuit by cast if we already have a Node. if node, ok := block.(Node); ok { return node, nil } ty := block.Cid().Type() d.lock.RLock() decoder, ok := d.decoders[ty] d.lock.RUnlock() if ok { return decoder(block) } else { // TODO: get the *long* name for this format return nil, fmt.Errorf("unrecognized object type: %d", ty) } } var DefaultBlockDecoder BlockDecoder = &safeBlockDecoder{decoders: make(map[uint64]DecodeBlockFunc)} // Decode decodes the given block using the default BlockDecoder. func Decode(block blocks.Block) (Node, error) { return DefaultBlockDecoder.Decode(block) } // Register registers block decoders with the default BlockDecoder. func Register(codec uint64, decoder DecodeBlockFunc) { DefaultBlockDecoder.Register(codec, decoder) }