github.com/ipld/go-ipld-prime@v0.21.0/multicodec/registry.go (about)

     1  package multicodec
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/ipld/go-ipld-prime/codec"
     7  )
     8  
     9  // Registry is a structure for storing mappings of multicodec indicator numbers to codec.Encoder and codec.Decoder functions.
    10  //
    11  // The most typical usage of this structure is in combination with a codec.LinkSystem.
    12  // For example, a linksystem using CIDs and a custom multicodec registry can be constructed
    13  // using cidlink.LinkSystemUsingMulticodecRegistry.
    14  //
    15  // Registry includes no mutexing.  If using Registry in a concurrent context, you must handle synchronization yourself.
    16  // (Typically, it is recommended to do initialization earlier in a program, before fanning out goroutines;
    17  // this avoids the need for mutexing overhead.)
    18  //
    19  // go-ipld also has a default registry, which has the same methods as this structure, but are at package scope.
    20  // Some systems, like cidlink.DefaultLinkSystem, will use this default registry.
    21  // However, this default registry is global to the entire program.
    22  // This Registry type is for helping if you wish to make your own registry which does not share that global state.
    23  //
    24  // Multicodec indicator numbers are specified in
    25  // https://github.com/multiformats/multicodec/blob/master/table.csv .
    26  // You should not use indicator numbers which are not specified in that table
    27  // (however, there is nothing in this implementation that will attempt to stop you, either; please behave).
    28  type Registry struct {
    29  	encoders map[uint64]codec.Encoder
    30  	decoders map[uint64]codec.Decoder
    31  }
    32  
    33  func (r *Registry) ensureInit() {
    34  	if r.encoders != nil {
    35  		return
    36  	}
    37  	r.encoders = make(map[uint64]codec.Encoder)
    38  	r.decoders = make(map[uint64]codec.Decoder)
    39  }
    40  
    41  // RegisterEncoder updates a simple map of multicodec indicator number to codec.Encoder function.
    42  // The encoder functions registered can be subsequently looked up using LookupEncoder.
    43  func (r *Registry) RegisterEncoder(indicator uint64, encodeFunc codec.Encoder) {
    44  	r.ensureInit()
    45  	if encodeFunc == nil {
    46  		panic("not sensible to attempt to register a nil function")
    47  	}
    48  	r.encoders[indicator] = encodeFunc
    49  }
    50  
    51  // LookupEncoder yields a codec.Encoder function matching a multicodec indicator code number.
    52  //
    53  // To be available from this lookup function, an encoder must have been registered
    54  // for this indicator number by an earlier call to the RegisterEncoder function.
    55  func (r *Registry) LookupEncoder(indicator uint64) (codec.Encoder, error) {
    56  	encodeFunc, exists := r.encoders[indicator]
    57  	if !exists {
    58  		return nil, fmt.Errorf("no encoder registered for multicodec code %d (0x%x)", indicator, indicator)
    59  	}
    60  	return encodeFunc, nil
    61  }
    62  
    63  // ListEncoders returns a list of multicodec indicators for which a codec.Encoder is registered.
    64  // The list is in no particular order.
    65  func (r *Registry) ListEncoders() []uint64 {
    66  	encoders := make([]uint64, 0, len(r.encoders))
    67  	for e := range r.encoders {
    68  		encoders = append(encoders, e)
    69  	}
    70  	return encoders
    71  }
    72  
    73  // TODO(mvdan): turn most of these uint64s into multicodec.Code
    74  
    75  // RegisterDecoder updates a simple map of multicodec indicator number to codec.Decoder function.
    76  // The decoder functions registered can be subsequently looked up using LookupDecoder.
    77  func (r *Registry) RegisterDecoder(indicator uint64, decodeFunc codec.Decoder) {
    78  	r.ensureInit()
    79  	if decodeFunc == nil {
    80  		panic("not sensible to attempt to register a nil function")
    81  	}
    82  	r.decoders[indicator] = decodeFunc
    83  }
    84  
    85  // LookupDecoder yields a codec.Decoder function matching a multicodec indicator code number.
    86  //
    87  // To be available from this lookup function, an decoder must have been registered
    88  // for this indicator number by an earlier call to the RegisterDecoder function.
    89  func (r *Registry) LookupDecoder(indicator uint64) (codec.Decoder, error) {
    90  	decodeFunc, exists := r.decoders[indicator]
    91  	if !exists {
    92  		return nil, fmt.Errorf("no decoder registered for multicodec code %d (0x%x)", indicator, indicator)
    93  	}
    94  	return decodeFunc, nil
    95  }
    96  
    97  // ListDecoders returns a list of multicodec indicators for which a codec.Decoder is registered.
    98  // The list is in no particular order.
    99  func (r *Registry) ListDecoders() []uint64 {
   100  	decoders := make([]uint64, 0, len(r.decoders))
   101  	for d := range r.decoders {
   102  		decoders = append(decoders, d)
   103  	}
   104  	return decoders
   105  }