numbat_codec/
codec_ser.rs

1use alloc::vec::Vec;
2use crate::codec_err::EncodeError;
3use crate::TypeInfo;
4
5/// Trait that allows writing of data.
6pub trait Output {
7	/// Write to the output.
8	fn write(&mut self, bytes: &[u8]);
9
10	/// Write a single byte to the output.
11	fn push_byte(&mut self, byte: u8) {
12		self.write(&[byte]);
13	}
14}
15
16impl Output for Vec<u8> {
17	fn write(&mut self, bytes: &[u8]) {
18		self.extend_from_slice(bytes)
19	}
20}
21
22/// Trait that allows zero-copy write of value-references to slices in LE format.
23///
24/// Implementations should override `using_top_encoded` for value types and `dep_encode_to` and `size_hint` for allocating types.
25/// Wrapper types should override all methods.
26pub trait Encode: Sized {
27	// !INTERNAL USE ONLY!
28	// This const helps SCALE to optimize the encoding/decoding by doing fake specialization.
29	#[doc(hidden)]
30	const TYPE_INFO: TypeInfo = TypeInfo::Unknown;
31
32	/// Encode to output, using the format of an object nested inside another structure.
33	/// Does not provide compact version.
34	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
35		self.using_top_encoded(|buf| dest.write(buf))
36	}
37
38	/// Convert self to an owned vector.
39	/// Allowed to provide compact version.
40	/// Do not call for nested objects.
41	fn top_encode(&self) -> Result<Vec<u8>, EncodeError> {
42		let mut dest = Vec::new();
43		self.using_top_encoded(|buf| dest.write(buf))?;
44		Ok(dest)
45	}
46
47	/// Convert self to a slice and then invoke the given closure with it.
48	/// Allowed to provide compact version.
49	/// Do not call for nested objects.
50	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
51		// default implementation simply use dep_encode_to
52		let mut dest: Vec<u8> = Vec::new();
53		self.dep_encode_to(&mut dest)?;
54		f(dest.as_slice());
55		Ok(())
56	}
57}
58
59// TODO: consider removing altogether when possible
60impl Encode for () {
61	const TYPE_INFO: TypeInfo = TypeInfo::Unit;
62
63	fn dep_encode_to<O: Output>(&self, _dest: &mut O) -> Result<(), EncodeError> {
64		Ok(())
65	}
66
67	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
68		f(&[]);
69		Ok(())
70	}
71
72	fn top_encode(&self) -> Result<Vec<u8>, EncodeError> {
73		Ok(Vec::with_capacity(0))
74	}
75}
76
77impl Encode for u8 {
78	const TYPE_INFO: TypeInfo = TypeInfo::U8;
79
80	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
81		dest.write(&[*self as u8][..]);
82		Ok(())
83	}
84
85	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
86		if *self == 0u8 {
87			f(&[]);
88		} else {
89			f(&[*self][..]);
90		}
91		Ok(())
92	}
93}
94
95impl<T: Encode> Encode for &[T] {
96	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
97		// push size
98		using_encoded_number(self.len() as u64, 32, false, false, |buf| dest.write(buf));
99		// actual data
100		match T::TYPE_INFO {
101			TypeInfo::U8 => {
102				// cast &[T] to &[u8]
103				let slice: &[u8] = unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
104				dest.write(slice);
105			},
106			_ => {
107				for x in *self {
108					x.dep_encode_to(dest)?;
109				}
110			}
111		}
112		Ok(())
113	}
114
115	#[inline]
116	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
117		match T::TYPE_INFO {
118			TypeInfo::U8 => {
119				// cast Vec<T> to &[u8]
120				let slice: &[u8] = unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
121				f(slice);
122			},
123			_ => {
124				let mut result: Vec<u8> = Vec::new();
125				for x in *self {
126					x.dep_encode_to(&mut result)?;
127				}
128				f(result.as_slice());
129			}
130		}
131		Ok(())
132	}
133}
134
135impl<T: Encode> Encode for &T {
136	#[inline]
137	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
138		(*self).dep_encode_to(dest)
139	}
140
141	#[inline]
142	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
143		(*self).using_top_encoded(f)
144	}
145}
146
147impl Encode for &str {
148	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
149		// push size
150		using_encoded_number(self.len() as u64, 32, false, false, |buf| dest.write(buf));
151		// actual data
152		dest.write(self.as_bytes());
153		Ok(())
154	}
155
156	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
157		f(self.as_bytes());
158		Ok(())
159	}
160}
161
162impl<T: Encode> Encode for Vec<T> {
163	#[inline]
164	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
165		self.as_slice().dep_encode_to(dest)
166	}
167
168	#[inline]
169	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
170		self.as_slice().using_top_encoded(f)
171	}
172}
173
174
175/// Adds number to output buffer.
176/// No argument generics here, because we want the executable binary as small as possible.
177/// Smaller types need to be converted to u64 before using this function.
178/// TODO: there might be a quicker version of this using transmute + reverse bytes.
179pub fn using_encoded_number<F: FnOnce(&[u8])>(x: u64, size_in_bits: usize, signed: bool, mut compact: bool, f: F) {
180	let mut result = [0u8; 8];
181	let mut result_size = 0usize;
182	let negative = 
183		compact && // only relevant when compact flag
184		signed &&  // only possible when signed flag
185		x >> (size_in_bits - 1) & 1 == 1; // compute by checking first bit
186	
187	let irrelevant_byte = if negative { 0xffu8 } else { 0x00u8 };
188	let mut bit_offset = size_in_bits as isize - 8;
189	while bit_offset >= 0 {
190		// going byte by byte from most to least significant
191		let byte = (x >> (bit_offset as usize) & 0xffu64) as u8;
192		
193		if compact {
194			// compact means ignoring irrelvant leading bytes
195			// that is 000... for positives and fff... for negatives
196			if byte != irrelevant_byte {
197				result[result_size] = byte;
198				result_size += 1;
199				compact = false;
200			}
201		} else {
202			result[result_size] = byte;
203			result_size += 1;
204		}
205		
206		bit_offset -= 8;
207	}
208
209	f(&result[0..result_size])
210}
211
212macro_rules! encode_num {
213    ($num_type:ident, $size_in_bits:expr, $signed:expr, $type_info:expr) => {
214		impl Encode for $num_type {
215			const TYPE_INFO: TypeInfo = $type_info;
216
217			#[inline]
218            fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
219				using_encoded_number(*self as u64, $size_in_bits, $signed, false, |buf| dest.write(buf));
220				Ok(())
221			}
222		
223			#[inline]
224            fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
225				using_encoded_number(*self as u64, $size_in_bits, $signed, true, f);
226				Ok(())
227			}
228		}
229    }
230}
231
232encode_num!{u64, 64, false, TypeInfo::U64}
233encode_num!{i64, 64, true, TypeInfo::I64}
234encode_num!{u32, 32, false, TypeInfo::U32}
235encode_num!{i32, 32, true, TypeInfo::I32}
236encode_num!{usize, 32, false, TypeInfo::U32}
237encode_num!{isize, 32, true, TypeInfo::I32}
238encode_num!{u16, 16, false, TypeInfo::U16}
239encode_num!{i16, 16, true, TypeInfo::I16}
240encode_num!{i8, 8, true, TypeInfo::I8}
241
242impl Encode for bool {
243	const TYPE_INFO: TypeInfo = TypeInfo::Bool;
244
245	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
246		dest.write(&[*self as u8][..]);
247		Ok(())
248	}
249
250	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
251		if *self {
252			f(&[1u8][..]);
253		} else {
254			f(&[]);
255		}
256		Ok(())
257	}
258}
259
260impl<T: Encode> Encode for Option<T> {
261	fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
262		match self {
263			Some(v) => {
264				using_encoded_number(1u64, 8, false, false, |buf| dest.write(buf));
265				v.dep_encode_to(dest)
266			},
267			None => {
268				using_encoded_number(0u64, 8, false, false, |buf| dest.write(buf));
269				Ok(())
270			}
271		}
272	}
273
274	/// Allow None to be serialized to empty bytes, but leave the leading "1" for Some,
275	/// to allow disambiguation between e.g. Some(0) and None.
276	fn using_top_encoded<F: FnOnce(&[u8])>(&self, f: F) -> Result<(), EncodeError> {
277		match self {
278			Some(v) => {
279				let mut dest: Vec<u8> = Vec::new();
280				dest.push(1u8);
281				v.dep_encode_to(&mut dest)?;
282				f(dest.as_slice());
283			},
284			None => {
285				f(&[]);
286			}
287		}
288		Ok(())
289	}
290}
291
292macro_rules! tuple_impls {
293    ($(($($n:tt $name:ident)+))+) => {
294        $(
295            impl<$($name),+> Encode for ($($name,)+)
296            where
297                $($name: Encode,)+
298            {
299				#[inline]
300				fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
301					$(
302                        self.$n.dep_encode_to(dest)?;
303                    )+
304					Ok(())
305				}
306            }
307        )+
308    }
309}
310
311tuple_impls! {
312    (0 T0)
313    (0 T0 1 T1)
314    (0 T0 1 T1 2 T2)
315    (0 T0 1 T1 2 T2 3 T3)
316    (0 T0 1 T1 2 T2 3 T3 4 T4)
317    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
318    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
319    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
320    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
321    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
322    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
323    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
324    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
325    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
326    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
327    (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
328}
329
330macro_rules! array_impls {
331    ($($n: tt,)+) => {
332        $(
333            impl<T: Encode> Encode for [T; $n] {
334				#[inline]
335				fn dep_encode_to<O: Output>(&self, dest: &mut O) -> Result<(), EncodeError> {
336					// the top encoded slice does not serialize its length, so just like the array
337					(&self[..]).using_top_encoded(|buf| dest.write(buf))
338				}
339            }
340        )+
341    }
342}
343
344array_impls!(
345	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
346	17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
347	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
348	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
349	72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
350	92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
351	109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
352	125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
353	141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
354	157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
355	173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
356	189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
357	205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
358	221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
359	237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
360	253, 254, 255, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,
361);
362
363////////////////////////////////////////////////////////////////////////////////
364
365#[cfg(test)]
366mod tests {
367	use super::*;
368	use super::super::test_struct::*;
369    use core::fmt::Debug;
370
371    fn ser_ok<V>(element: V, expected_bytes: &[u8])
372    where
373        V: Encode + PartialEq + Debug + 'static,
374    {
375		V::using_top_encoded(&element, |bytes| {
376			assert_eq!(bytes, expected_bytes);
377		}).unwrap();
378        
379    }
380
381    #[test]
382    fn test_top_compacted_numbers() {
383        // unsigned positive
384        ser_ok(5u8, &[5]);
385        ser_ok(5u16, &[5]);
386        ser_ok(5u32, &[5]);
387        ser_ok(5u64, &[5]);
388        ser_ok(5usize, &[5]);
389        // signed positive
390        ser_ok(5i8, &[5]);
391        ser_ok(5i16, &[5]);
392        ser_ok(5i32, &[5]);
393        ser_ok(5i64, &[5]);
394        ser_ok(5isize, &[5]);
395        // signed negative
396        ser_ok(-5i8, &[251]);
397        ser_ok(-5i16, &[251]);
398        ser_ok(-5i32, &[251]);
399        ser_ok(-5i64, &[251]);
400        ser_ok(-5isize, &[251]);
401    }
402
403    #[test]
404    fn test_top_compacted_bool() {
405        ser_ok(true,    &[1]);
406        ser_ok(false,   &[]);
407    }
408
409    #[test]
410    fn test_top_compacted_empty_bytes() {
411        let empty_byte_slice: &[u8] = &[];
412        ser_ok(empty_byte_slice, empty_byte_slice);
413    }
414
415    #[test]
416    fn test_top_compacted_bytes() {
417        ser_ok(&[1u8, 2u8, 3u8][..], &[1u8, 2u8, 3u8]);
418    }
419
420    #[test]
421    fn test_top_compacted_vec_u8() {
422        let some_vec = [1u8, 2u8, 3u8].to_vec();
423        ser_ok(some_vec, &[1u8, 2u8, 3u8]);
424    }
425
426    #[test]
427    fn test_top_compacted_vec_i32() {
428        let some_vec = [1i32, 2i32, 3i32].to_vec();
429        let expected: &[u8] = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
430        ser_ok(some_vec, expected);
431	}
432
433    #[test]
434    fn test_struct() {
435		let test = Test {
436            int: 1,
437            seq: [5, 6].to_vec(),
438            another_byte: 7,
439        };
440
441        ser_ok(test, &[0, 1, 0, 0, 0, 2, 5, 6, 7]);
442    }
443
444    #[test]
445    fn test_tuple() {
446        ser_ok((7u32, -2i16), &[0, 0, 0, 7, 255, 254]);
447    }
448
449    #[test]
450    fn test_unit() {
451        ser_ok((), &[]);
452    }
453
454    #[test]
455    fn test_enum() {
456        let u = E::Unit;
457        let expected: &[u8] = &[/*variant index*/ 0, 0, 0, 0];
458        ser_ok(u, expected);
459
460        let n = E::Newtype(1);
461        let expected: &[u8] = &[/*variant index*/ 0, 0, 0, 1, /*data*/ 0, 0, 0, 1];
462        ser_ok(n, expected);
463
464        let t = E::Tuple(1, 2);
465        let expected: &[u8] = &[/*variant index*/ 0, 0, 0, 2, /*(*/ 0, 0, 0, 1, /*,*/ 0, 0, 0, 2 /*)*/];
466        ser_ok(t, expected);
467
468        let s = E::Struct { a: 1 };
469        let expected: &[u8] = &[/*variant index*/ 0, 0, 0, 3, /*data*/ 0, 0, 0, 1];
470        ser_ok(s, expected);
471    }
472}