github.com/ipld/go-ipld-prime@v0.21.0/codec/api.go (about) 1 package codec 2 3 import ( 4 "io" 5 6 "github.com/ipld/go-ipld-prime/datamodel" 7 ) 8 9 // The following two types define the two directions of transform that a codec can be expected to perform: 10 // from Node to serial stream (aka "encoding", sometimes also described as "marshalling"), 11 // and from serial stream to Node (via a NodeAssembler) (aka "decoding", sometimes also described as "unmarshalling"). 12 // 13 // You'll find a couple of implementations matching this shape in subpackages of 'codec'. 14 // (These are the handful of encoders and decoders we ship as "batteries included".) 15 // Other encoder and decoder implementations can be found in other repositories/modules. 16 // It should also be easy to implement encodecs and decoders of your own! 17 // 18 // Encoder and Decoder functions can be used on their own, but are also often used via the `ipld/linking.LinkSystem` construction, 19 // which handles all the other related operations necessary for a content-addressed storage system at once. 20 // 21 // Encoder and Decoder functions can be registered in the multicodec table in the `ipld/multicodec` package 22 // if they're providing functionality that matches the expectations for a multicodec identifier. 23 // This table will be used by some common EncoderChooser and DecoderChooser implementations 24 // (namely, the ones in LinkSystems produced by the `linking/cid` package). 25 // It's not strictly necessary to register functions there, though; you can also just use them directly. 26 // 27 // There are furthermore several conventions that codec packages are recommended to follow, but are only conventions: 28 // 29 // Most codec packages should have a ReusableEncoder and ResuableDecoder type, 30 // which contain any working memory needed by the implementation, as well as any configuration options, 31 // and those types should have an Encode and Decode function respectively which match these function types. 32 // They may alternatively have EncoderConfig and DecoderConfig types, which have similar purpose, 33 // but aren't promising memory reuse if kept around. 34 // 35 // By convention, a codec package that expects to fulfill a multicodec contract will also have 36 // a package-scope exported function called Encode or Decode which also matches this interface, 37 // and is the equivalent of creating a zero-value ReusableEncoder or ReusableDecoder (aka, default config) 38 // and using its Encode or Decode methods. 39 // This package-scope function may also internally use a sync.Pool 40 // to keep some ReusableEncoder values on hand to avoid unnecesary allocations. 41 // 42 // Note that an EncoderConfig or DecoderConfig type that supports configuration options 43 // does not functionally expose those options when invoked by the multicodec system -- 44 // multicodec indicator codes do not provide room for extended configuration info. 45 // Codecs that expose configuration options are doing so for library users to enjoy; 46 // it does not mean those non-default configurations will necessarly be available 47 // in all scenarios that use codecs indirectly. 48 // There is also no standard interface for such configurations: by nature, 49 // if they exist at all, they tend to vary per codec. 50 type ( 51 // Encoder defines the shape of a function which traverses a Node tree 52 // and emits its data in a serialized form into an io.Writer. 53 // 54 // The dual of Encoder is a Decoder, which takes a NodeAssembler 55 // and fills it with deserialized data consumed from an io.Reader. 56 // Typically, Decoder and Encoder functions will be found in pairs, 57 // and will be expected to be able to round-trip each other's data. 58 // 59 // Encoder functions can be used directly. 60 // Encoder functions are also often used via a LinkSystem when working with content-addressed storage. 61 // LinkSystem methods will helpfully handle the entire process of traversing a Node tree, 62 // encoding this data, hashing it, streaming it to the writer, and committing it -- all as one step. 63 // 64 // An Encoder works with Nodes. 65 // If you have a native golang structure, and want to serialize it using an Encoder, 66 // you'll need to figure out how to transform that golang structure into an ipld.Node tree first. 67 // 68 // It may be useful to understand "multicodecs" when working with Encoders. 69 // In IPLD, a system called "multicodecs" is typically used to describe encoding foramts. 70 // A "multicodec indicator" is a number which describes an encoding; 71 // the Link implementations used in IPLD (CIDs) store a multicodec indicator in the Link; 72 // and in this library, a multicodec registry exists in the `codec` package, 73 // and can be used to associate a multicodec indicator number with an Encoder function. 74 // The default EncoderChooser in a LinkSystem will use this multicodec registry to select Encoder functions. 75 // However, you can construct a LinkSystem that uses any EncoderChooser you want. 76 // It is also possible to have and use Encoder functions that aren't registered as a multicodec at all... 77 // we just recommend being cautious of this, because it may make your data less recognizable 78 // when working with other systems that use multicodec indicators as part of their communication. 79 Encoder func(datamodel.Node, io.Writer) error 80 81 // Decoder defines the shape of a function which produces a Node tree 82 // by reading serialized data from an io.Reader. 83 // (Decoder doesn't itself return a Node directly, but rather takes a NodeAssembler as an argument, 84 // because this allows the caller more control over the Node implementation, 85 // as well as some control over allocations.) 86 // 87 // The dual of Decoder is an Encoder, which takes a Node and 88 // emits its data in a serialized form into an io.Writer. 89 // Typically, Decoder and Encoder functions will be found in pairs, 90 // and will be expected to be able to round-trip each other's data. 91 // 92 // Decoder functions can be used directly. 93 // Decoder functions are also often used via a LinkSystem when working with content-addressed storage. 94 // LinkSystem methods will helpfully handle the entire process of opening block readers, 95 // verifying the hash of the data stream, and applying a Decoder to build Nodes -- all as one step. 96 // 97 // A Decoder works with Nodes. 98 // If you have a native golang structure, and want to populate it with data using a Decoder, 99 // you'll need to either get a NodeAssembler which proxies data into that structure directly, 100 // or assemble a Node as intermediate storage and copy the data to the native structure as a separate step. 101 // 102 // It may be useful to understand "multicodecs" when working with Decoders. 103 // See the documentation on the Encoder function interface for more discussion of multicodecs, 104 // the multicodec table, and how this is typically connected to linking. 105 Decoder func(datamodel.NodeAssembler, io.Reader) error 106 ) 107 108 // ------------------- 109 // Errors 110 // 111 112 type ErrBudgetExhausted struct{} 113 114 func (e ErrBudgetExhausted) Error() string { 115 return "decoder resource budget exhausted (message too long or too complex)" 116 } 117 118 // --------------------- 119 // Other valuable and reused constants 120 // 121 122 type MapSortMode uint8 123 124 const ( 125 MapSortMode_None MapSortMode = iota 126 MapSortMode_Lexical 127 MapSortMode_RFC7049 128 )