multicodec/
lib.rs

1extern crate unsigned_varint;
2#[macro_use] extern crate failure;
3extern crate serde;
4
5
6use unsigned_varint::{decode::u16 as decode_varint,
7                      encode::u16 as encode_varint,
8                      decode::Error as VarintError};
9
10use serde::{Serialize, Serializer};
11
12#[derive(Debug, Fail)]
13pub enum Error {
14    #[fail(display = "Codec {} unknown", _0)]
15    InvalidCodec(u16),
16    #[fail(display = "Can't parse varint: {}", _0)]
17    VarintFailed(VarintError)
18
19}
20
21macro_rules! build_codec_enum {
22    {$( $val:expr => $var:ident, )*} => {
23        #[allow(non_camel_case_types)]
24        #[derive(PartialEq, Eq, Clone, Copy, Debug)]
25        pub enum Codec {
26            $( $var, )*
27        }
28
29        use Codec::*;
30
31        impl Codec {
32            /// Get the base code.
33            pub fn code(&self) -> u16 {
34                match *self {
35                    $( $var => $val, )*
36                }
37            }
38
39            /// Convert a code to a base.
40            pub fn from_code(code: u16) -> Result<Codec, Error> {
41                match code {
42                    $( $val => Ok($var), )*
43                    _ => Err(Error::InvalidCodec(code)),
44                }
45            }
46        }
47    }
48}
49
50// SOURCE: https://github.com/multiformats/multicodec/blob/master/table.csv
51build_codec_enum! {
52	0x55 => Bin,
53    // bases encodings
54    0x01 => Base1,
55    0x07 => Base8,
56    0x09 => Base10, 
57
58    // serialization formats
59    0x51 => Cbor,
60    0x50 => Protobuf,
61    0x60 => Rlp,
62    0x63 => Bencode,
63
64    // multiformats
65    0x30 => Multicodec,
66    0x31 => Multihash,
67    0x32 => Multiaddr,
68    0x33 => Multibase,
69
70    // multihashes
71    0x11 => Sha1,
72    0x12 => Sha2_256,
73    0x13 => Sha2_512,
74    0x56 => Dbl_Sha2_256,
75    0x17 => Sha3_224,
76    0x16 => Sha3_256,
77    0x15 => Sha3_384,
78    0x14 => Sha3_512,
79    0x18 => Shake_128,
80    0x19 => Shake_256,
81    0x1A => Keccak_224,
82    0x1B => Keccak_256,
83    0x1C => Keccak_384,
84    0x1D => Keccak_512,
85    0x22 => Murmur3,
86    0xb201 => Blake2b_8,
87    0xb202 => Blake2b_16,
88    0xb203 => Blake2b_24,
89    0xb204 => Blake2b_32,
90    0xb205 => Blake2b_40,
91    0xb206 => Blake2b_48,
92    0xb207 => Blake2b_56,
93    0xb208 => Blake2b_64,
94    0xb209 => Blake2b_72,
95    0xb20a => Blake2b_80,
96    0xb20b => Blake2b_88,
97    0xb20c => Blake2b_96,
98    0xb20d => Blake2b_104,
99    0xb20e => Blake2b_112,
100    0xb20f => Blake2b_120,
101    0xb210 => Blake2b_128,
102    0xb211 => Blake2b_136,
103    0xb212 => Blake2b_144,
104    0xb213 => Blake2b_152,
105    0xb214 => Blake2b_160,
106    0xb215 => Blake2b_168,
107    0xb216 => Blake2b_176,
108    0xb217 => Blake2b_184,
109    0xb218 => Blake2b_192,
110    0xb219 => Blake2b_200,
111    0xb21a => Blake2b_208,
112    0xb21b => Blake2b_216,
113    0xb21c => Blake2b_224,
114    0xb21d => Blake2b_232,
115    0xb21e => Blake2b_240,
116    0xb21f => Blake2b_248,
117    0xb220 => Blake2b_256,
118    0xb221 => Blake2b_264,
119    0xb222 => Blake2b_272,
120    0xb223 => Blake2b_280,
121    0xb224 => Blake2b_288,
122    0xb225 => Blake2b_296,
123    0xb226 => Blake2b_304,
124    0xb227 => Blake2b_312,
125    0xb228 => Blake2b_320,
126    0xb229 => Blake2b_328,
127    0xb22a => Blake2b_336,
128    0xb22b => Blake2b_344,
129    0xb22c => Blake2b_352,
130    0xb22d => Blake2b_360,
131    0xb22e => Blake2b_368,
132    0xb22f => Blake2b_376,
133    0xb230 => Blake2b_384,
134    0xb231 => Blake2b_392,
135    0xb232 => Blake2b_400,
136    0xb233 => Blake2b_408,
137    0xb234 => Blake2b_416,
138    0xb235 => Blake2b_424,
139    0xb236 => Blake2b_432,
140    0xb237 => Blake2b_440,
141    0xb238 => Blake2b_448,
142    0xb239 => Blake2b_456,
143    0xb23a => Blake2b_464,
144    0xb23b => Blake2b_472,
145    0xb23c => Blake2b_480,
146    0xb23d => Blake2b_488,
147    0xb23e => Blake2b_496,
148    0xb23f => Blake2b_504,
149    0xb240 => Blake2b_512,
150    0xb241 => Blake2s_8,
151    0xb242 => Blake2s_16,
152    0xb243 => Blake2s_24,
153    0xb244 => Blake2s_32,
154    0xb245 => Blake2s_40,
155    0xb246 => Blake2s_48,
156    0xb247 => Blake2s_56,
157    0xb248 => Blake2s_64,
158    0xb249 => Blake2s_72,
159    0xb24a => Blake2s_80,
160    0xb24b => Blake2s_88,
161    0xb24c => Blake2s_96,
162    0xb24d => Blake2s_104,
163    0xb24e => Blake2s_112,
164    0xb24f => Blake2s_120,
165    0xb250 => Blake2s_128,
166    0xb251 => Blake2s_136,
167    0xb252 => Blake2s_144,
168    0xb253 => Blake2s_152,
169    0xb254 => Blake2s_160,
170    0xb255 => Blake2s_168,
171    0xb256 => Blake2s_176,
172    0xb257 => Blake2s_184,
173    0xb258 => Blake2s_192,
174    0xb259 => Blake2s_200,
175    0xb25a => Blake2s_208,
176    0xb25b => Blake2s_216,
177    0xb25c => Blake2s_224,
178    0xb25d => Blake2s_232,
179    0xb25e => Blake2s_240,
180    0xb25f => Blake2s_248,
181    0xb260 => Blake2s_256,
182
183    // multiaddrs
184    0x04 => Ip4,
185    0x29 => Ip6,
186    0x06 => Tcp,
187    0x0111 => Udp,
188    0x21 => Dccp,
189    0x84 => Sctp,
190    0x012D => Udt,
191    0x012E => Utp,
192    0x01A5 => Ipfs,
193    0x01E0 => Http,
194    0x01BB => Https,
195    0x01CC => Quic,
196    0x01DD => Ws,
197    0x01BC => Onion,
198    0x0122 => P2p_Circuit,
199
200    // IPLD formats
201    0x70 => Dag_Pb, 
202    0x71 => Dag_Cbor,
203
204    0x78 => Git_Raw,
205
206    0x90 => Eth_Block,
207    0x91 => Eth_Block_List,
208    0x92 => Eth_Tx_Trie,
209    0x93 => Eth_Tx, 
210    0x94 => Eth_Tx_Receipt_Trie,
211    0x95 => Eth_Tx_Receipt,
212    0x96 => Eth_State_Trie,
213    0x97 => Eth_Account_Snapshot, 
214    0x98 => Eth_Storage_Trie,
215
216    0xb0 => Bitcoin_Block,
217    0xb1 => Bitcoin_Tx,
218
219    0xc0 => Zcash_Block,
220    0xc1 => Zcash_Tx,
221
222    0xd0 => Stellar_Block,
223    0xd1 => Stellar_Tx,
224
225    0x7b => Torrent_Info,
226    0x7c => Torrent_File,
227    0xed => Ed25519_Pub,
228}
229
230
231#[derive(PartialEq, Eq, Clone, Copy, Debug)]
232pub struct MultiCodec<'a> {
233	codec: Codec,
234	data: &'a [u8]
235}
236
237impl<'a> MultiCodec<'a> {
238	/// create a new MultiCodec
239	pub fn new(codec: Codec, data: &'a [u8]) -> MultiCodec {
240		MultiCodec { codec, data }
241	}
242	/// try to parse a MultiCodec from a packed bytestring
243	pub fn from(packed: &'a [u8]) -> Result<MultiCodec, Error> {
244		let (code, data) = decode_varint(packed).map_err(|e| Error::VarintFailed(e))?;
245		let codec = Codec::from_code(code)?;
246		Ok(MultiCodec { codec, data })
247	}
248
249    pub fn pack(&self) -> Vec<u8> {
250        let mut buf = [0u8; 3];
251        encode_varint(self.codec.code(), &mut buf);
252        let mut v : Vec<u8> = Vec::new();
253        for b in &buf {
254            v.push(*b);
255            // varint uses first bit to indicate another byte follows, stop if not the case
256            if *b <= 127 { break }
257        }
258        v.extend(self.data);
259        v
260    }
261}
262
263impl<'a> Serialize for MultiCodec<'a> {
264    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
265    where
266        S: Serializer,
267    {
268        serializer.serialize_bytes(&self.pack())
269    }
270}
271
272
273
274#[cfg(test)]
275mod tests {
276	use super::*;
277    #[test]
278    fn it_works() {
279        let codec = MultiCodec::new(Codec::Sha2_256, b"EiC5TSe5k00");
280        let packed = codec.pack();
281        let redo = MultiCodec::from(&packed).unwrap();
282        assert_eq!(packed, "\x12EiC5TSe5k00".as_bytes());
283        assert_eq!(redo, codec);
284    }
285}