forked from cerc-io/ipld-eth-server
63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
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)
|
|
}
|