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 pub fn code(&self) -> u16 {
34 match *self {
35 $( $var => $val, )*
36 }
37 }
38
39 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
50build_codec_enum! {
52 0x55 => Bin,
53 0x01 => Base1,
55 0x07 => Base8,
56 0x09 => Base10,
57
58 0x51 => Cbor,
60 0x50 => Protobuf,
61 0x60 => Rlp,
62 0x63 => Bencode,
63
64 0x30 => Multicodec,
66 0x31 => Multihash,
67 0x32 => Multiaddr,
68 0x33 => Multibase,
69
70 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 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 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 pub fn new(codec: Codec, data: &'a [u8]) -> MultiCodec {
240 MultiCodec { codec, data }
241 }
242 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 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}