Skip to content

Commit c1a1949

Browse files
committed
First version
0 parents  commit c1a1949

File tree

5 files changed

+324
-0
lines changed

5 files changed

+324
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
**/*.rs.bk
3+
Cargo.lock

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
language: rust
2+
3+
rust:
4+
- beta
5+
- stable

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "multicodec"
3+
version = "0.1.0"
4+
authors = ["Benjamin Kampmann <[email protected]>"]
5+
license = "MIT OR Apache-2.0"
6+
7+
[dependencies]
8+
unsigned-varint = "0.2"
9+
failure = "0.1"
10+
serde = "1.0"

Readme.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Multicodec in Rust
2+
3+
[![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
4+
5+
> rust implementation of the [multicodec specs](https://github.com/multiformats/multicodec)
6+
7+
8+
9+
## ToDo's
10+
11+
12+
### Coding
13+
14+
- [ ] automatic deserialisation through external serdes (JSON, CBOR, ...)
15+
- [ ] Integrate with Multihash & Multiaddr
16+
- [ ] no-std/Wasm-support
17+
18+
### Mgmnt
19+
- [ ] Publish on crates.io
20+
- [ ] Add proper License Files
21+
- [ ] Activate travis-ci

src/lib.rs

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
extern crate unsigned_varint;
2+
#[macro_use] extern crate failure;
3+
extern crate serde;
4+
5+
6+
use unsigned_varint::{decode::u16 as decode_varint,
7+
encode::u16 as encode_varint,
8+
decode::Error as VarintError};
9+
10+
use serde::{Serialize, Serializer, ser::SerializeSeq};
11+
12+
#[derive(Debug, Fail)]
13+
pub 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+
21+
macro_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
51+
build_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)]
232+
pub struct MultiCodec<'a> {
233+
codec: Codec,
234+
data: &'a [u8]
235+
}
236+
237+
impl<'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+
263+
impl<'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)]
275+
mod 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+
}

0 commit comments

Comments
 (0)