rlp/
impls.rs

1// Copyright 2015-2017 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#[cfg(not(feature = "std"))]
10use alloc::{String, Vec};
11
12#[cfg(feature = "std")] use std::{cmp, mem, str};
13#[cfg(not(feature = "std"))] use core::{cmp, mem, str};
14use byteorder::{ByteOrder, BigEndian};
15use traits::{Encodable, Decodable};
16use stream::RlpStream;
17use {UntrustedRlp, DecoderError};
18
19pub fn decode_usize(bytes: &[u8]) -> Result<usize, DecoderError> {
20	match bytes.len() {
21		l if l <= mem::size_of::<usize>() => {
22			if bytes[0] == 0 {
23				return Err(DecoderError::RlpInvalidIndirection);
24			}
25			let mut res = 0usize;
26			for i in 0..l {
27				let shift = (l - 1 - i) * 8;
28				res = res + ((bytes[i] as usize) << shift);
29			}
30			Ok(res)
31		}
32		_ => Err(DecoderError::RlpIsTooBig),
33	}
34}
35
36impl Encodable for bool {
37	fn rlp_append(&self, s: &mut RlpStream) {
38		if *self {
39			s.encoder().encode_value(&[1]);
40		} else {
41			s.encoder().encode_value(&[0]);
42		}
43	}
44}
45
46impl Decodable for bool {
47	fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
48		rlp.decoder().decode_value(|bytes| {
49			match bytes.len() {
50				0 => Ok(false),
51				1 => Ok(bytes[0] != 0),
52				_ => Err(DecoderError::RlpIsTooBig),
53			}
54		})
55	}
56}
57
58impl<'a> Encodable for &'a [u8] {
59	fn rlp_append(&self, s: &mut RlpStream) {
60		s.encoder().encode_value(self);
61	}
62}
63
64impl Encodable for Vec<u8> {
65	fn rlp_append(&self, s: &mut RlpStream) {
66		s.encoder().encode_value(self);
67	}
68}
69
70impl Decodable for Vec<u8> {
71	fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
72		rlp.decoder().decode_value(|bytes| {
73			Ok(bytes.to_vec())
74		})
75	}
76}
77
78impl<T> Encodable for Option<T> where T: Encodable {
79	fn rlp_append(&self, s: &mut RlpStream) {
80		match *self {
81			None => {
82				s.begin_list(0);
83			},
84			Some(ref value) => {
85				s.begin_list(1);
86				s.append(value);
87			}
88		}
89	}
90}
91
92impl<T> Decodable for Option<T> where T: Decodable {
93	fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
94		let items = rlp.item_count()?;
95		match items {
96			1 => rlp.val_at(0).map(Some),
97			0 => Ok(None),
98			_ => Err(DecoderError::RlpIncorrectListLen),
99		}
100	}
101}
102
103impl Encodable for u8 {
104	fn rlp_append(&self, s: &mut RlpStream) {
105		if *self != 0 {
106			s.encoder().encode_value(&[*self]);
107		} else {
108			s.encoder().encode_value(&[]);
109		}
110	}
111}
112
113impl Decodable for u8 {
114	fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
115		rlp.decoder().decode_value(|bytes| {
116			match bytes.len() {
117				1 if bytes[0] != 0 => Ok(bytes[0]),
118				0 => Ok(0),
119				1 => Err(DecoderError::RlpInvalidIndirection),
120				_ => Err(DecoderError::RlpIsTooBig),
121			}
122		})
123	}
124}
125
126macro_rules! impl_encodable_for_u {
127	($name: ident, $func: ident, $size: expr) => {
128		impl Encodable for $name {
129			fn rlp_append(&self, s: &mut RlpStream) {
130				let leading_empty_bytes = self.leading_zeros() as usize / 8;
131				let mut buffer = [0u8; $size];
132				BigEndian::$func(&mut buffer, *self);
133				s.encoder().encode_value(&buffer[leading_empty_bytes..]);
134			}
135		}
136	}
137}
138
139macro_rules! impl_decodable_for_u {
140	($name: ident) => {
141		impl Decodable for $name {
142			fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
143				rlp.decoder().decode_value(|bytes| {
144					match bytes.len() {
145						0 | 1 => u8::decode(rlp).map(|v| v as $name),
146						l if l <= mem::size_of::<$name>() => {
147							if bytes[0] == 0 {
148								return Err(DecoderError::RlpInvalidIndirection);
149							}
150							let mut res = 0 as $name;
151							for i in 0..l {
152								let shift = (l - 1 - i) * 8;
153								res = res + ((bytes[i] as $name) << shift);
154							}
155							Ok(res)
156						}
157						_ => Err(DecoderError::RlpIsTooBig),
158					}
159				})
160			}
161		}
162	}
163}
164
165impl_encodable_for_u!(u16, write_u16, 2);
166impl_encodable_for_u!(u32, write_u32, 4);
167impl_encodable_for_u!(u64, write_u64, 8);
168
169impl_decodable_for_u!(u16);
170impl_decodable_for_u!(u32);
171impl_decodable_for_u!(u64);
172
173impl Encodable for usize {
174	fn rlp_append(&self, s: &mut RlpStream) {
175		(*self as u64).rlp_append(s);
176	}
177}
178
179impl Decodable for usize {
180	fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
181		u64::decode(rlp).map(|value| value as usize)
182	}
183}
184
185macro_rules! impl_encodable_for_hash {
186	($name: ident) => {
187		impl Encodable for $name {
188			fn rlp_append(&self, s: &mut RlpStream) {
189				s.encoder().encode_value(self);
190			}
191		}
192	}
193}
194
195macro_rules! impl_decodable_for_hash {
196	($name: ident, $size: expr) => {
197		impl Decodable for $name {
198			fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
199				rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) {
200					cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort),
201					cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig),
202					cmp::Ordering::Equal => {
203						let mut t = [0u8; $size];
204						t.copy_from_slice(bytes);
205						Ok($name(t))
206					}
207				})
208			}
209		}
210	}
211}
212
213impl<'a> Encodable for &'a str {
214	fn rlp_append(&self, s: &mut RlpStream) {
215		s.encoder().encode_value(self.as_bytes());
216	}
217}
218
219impl Encodable for String {
220	fn rlp_append(&self, s: &mut RlpStream) {
221		s.encoder().encode_value(self.as_bytes());
222	}
223}
224
225impl Decodable for String {
226	fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
227        #[cfg(not(feature = "std"))]
228        use alloc::borrow::ToOwned;
229
230		rlp.decoder().decode_value(|bytes| {
231			match str::from_utf8(bytes) {
232				Ok(s) => Ok(s.to_owned()),
233				// consider better error type here
234				Err(_err) => Err(DecoderError::RlpExpectedToBeData),
235			}
236		})
237	}
238}