1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::num::NonZeroUsize;
5
6use crate::codec_err::EncodeError;
7use crate::nested_ser::{dep_encode_slice_contents, NestedEncode};
8use crate::nested_ser_output::NestedEncodeOutput;
9use crate::top_ser_output::TopEncodeOutput;
10use crate::TypeInfo;
11
12pub trait TopEncodeNoErr: Sized {
16 fn top_encode_no_err<O: TopEncodeOutput>(&self, output: O);
17}
18
19pub fn top_encode_no_err<T: TopEncodeNoErr>(obj: &T) -> Vec<u8> {
21 let mut bytes = Vec::<u8>::new();
22 obj.top_encode_no_err(&mut bytes);
23 bytes
24}
25
26pub trait TopEncode: Sized {
27 #[doc(hidden)]
29 const TYPE_INFO: TypeInfo = TypeInfo::Unknown;
30
31 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError>;
33
34 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
38 &self,
39 output: O,
40 c: ExitCtx,
41 exit: fn(ExitCtx, EncodeError) -> !,
42 ) {
43 match self.top_encode(output) {
44 Ok(v) => v,
45 Err(e) => exit(c, e),
46 }
47 }
48}
49
50pub fn top_encode_from_nested<T, O>(obj: &T, output: O) -> Result<(), EncodeError>
51where
52 O: TopEncodeOutput,
53 T: NestedEncode,
54{
55 let mut bytes = Vec::<u8>::new();
56 obj.dep_encode(&mut bytes)?;
57 output.set_slice_u8(&bytes[..]);
58 Ok(())
59}
60
61pub fn top_encode_from_nested_or_exit<T, O, ExitCtx>(
62 obj: &T,
63 output: O,
64 c: ExitCtx,
65 exit: fn(ExitCtx, EncodeError) -> !,
66) where
67 O: TopEncodeOutput,
68 T: NestedEncode,
69 ExitCtx: Clone,
70{
71 let mut bytes = Vec::<u8>::new();
72 obj.dep_encode_or_exit(&mut bytes, c, exit);
73 output.set_slice_u8(&bytes[..]);
74}
75
76macro_rules! top_encode_from_no_err {
77 ($type:ty, $type_info:expr) => {
78 impl TopEncode for $type {
79 const TYPE_INFO: TypeInfo = $type_info;
80
81 #[inline]
82 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
83 self.top_encode_no_err(output);
84 Ok(())
85 }
86
87 #[inline]
88 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
89 &self,
90 output: O,
91 _: ExitCtx,
92 _: fn(ExitCtx, EncodeError) -> !,
93 ) {
94 self.top_encode_no_err(output);
95 }
96 }
97 };
98}
99
100pub fn top_encode_to_vec<T: TopEncode>(obj: &T) -> Result<Vec<u8>, EncodeError> {
101 let mut bytes = Vec::<u8>::new();
102 obj.top_encode(&mut bytes)?;
103 Ok(bytes)
104}
105
106impl TopEncodeNoErr for () {
107 #[inline]
108 fn top_encode_no_err<O: TopEncodeOutput>(&self, output: O) {
109 output.set_unit();
110 }
111}
112
113top_encode_from_no_err! {(), TypeInfo::Unit}
114
115impl<T: NestedEncode> TopEncode for &[T] {
116 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
117 match T::TYPE_INFO {
118 TypeInfo::U8 => {
119 let slice: &[u8] =
122 unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
123 output.set_slice_u8(slice);
124 },
125 _ => {
126 let mut buffer = Vec::<u8>::new();
130 dep_encode_slice_contents(self, &mut buffer)?;
131 output.set_slice_u8(&buffer[..]);
132 },
133 }
134 Ok(())
135 }
136
137 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
138 &self,
139 output: O,
140 c: ExitCtx,
141 exit: fn(ExitCtx, EncodeError) -> !,
142 ) {
143 match T::TYPE_INFO {
144 TypeInfo::U8 => {
145 let slice: &[u8] =
148 unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
149 output.set_slice_u8(slice);
150 },
151 _ => {
152 let mut buffer = Vec::<u8>::new();
156 for x in *self {
157 x.dep_encode_or_exit(&mut buffer, c.clone(), exit);
158 }
159 output.set_slice_u8(&buffer[..]);
160 },
161 }
162 }
163}
164
165impl<T: TopEncode> TopEncode for &T {
166 #[inline]
167 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
168 (*self).top_encode(output)
169 }
170
171 #[inline]
172 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
173 &self,
174 output: O,
175 c: ExitCtx,
176 exit: fn(ExitCtx, EncodeError) -> !,
177 ) {
178 (*self).top_encode_or_exit(output, c, exit);
179 }
180}
181
182impl TopEncode for &str {
183 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
184 output.set_slice_u8(self.as_bytes());
185 Ok(())
186 }
187
188 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
189 &self,
190 output: O,
191 _: ExitCtx,
192 _: fn(ExitCtx, EncodeError) -> !,
193 ) {
194 output.set_slice_u8(self.as_bytes());
195 }
196}
197
198impl<T: NestedEncode> TopEncode for Vec<T> {
199 #[inline]
200 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
201 self.as_slice().top_encode(output)
202 }
203
204 #[inline]
205 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
206 &self,
207 output: O,
208 c: ExitCtx,
209 exit: fn(ExitCtx, EncodeError) -> !,
210 ) {
211 self.as_slice().top_encode_or_exit(output, c, exit);
212 }
213}
214
215impl TopEncode for String {
216 #[inline]
217 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
218 self.as_bytes().top_encode(output)
219 }
220
221 #[inline]
222 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
223 &self,
224 output: O,
225 c: ExitCtx,
226 exit: fn(ExitCtx, EncodeError) -> !,
227 ) {
228 self.as_bytes().top_encode_or_exit(output, c, exit);
229 }
230}
231
232impl TopEncode for Box<str> {
233 #[inline]
234 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
235 self.as_ref().as_bytes().top_encode(output)
236 }
237
238 #[inline]
239 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
240 &self,
241 output: O,
242 c: ExitCtx,
243 exit: fn(ExitCtx, EncodeError) -> !,
244 ) {
245 self.as_ref().as_bytes().top_encode_or_exit(output, c, exit);
246 }
247}
248
249macro_rules! encode_num_unsigned {
250 ($num_type:ty, $size_in_bits:expr, $type_info:expr) => {
251 impl TopEncodeNoErr for $num_type {
252 #[inline]
253 fn top_encode_no_err<O: TopEncodeOutput>(&self, output: O) {
254 output.set_u64(*self as u64);
255 }
256 }
257
258 top_encode_from_no_err! {$num_type, $type_info}
259 };
260}
261
262encode_num_unsigned! {u64, 64, TypeInfo::U64}
263encode_num_unsigned! {u32, 32, TypeInfo::U32}
264encode_num_unsigned! {usize, 32, TypeInfo::USIZE}
265encode_num_unsigned! {u16, 16, TypeInfo::U16}
266encode_num_unsigned! {u8, 8, TypeInfo::U8}
267
268macro_rules! encode_num_signed {
269 ($num_type:ty, $size_in_bits:expr, $type_info:expr) => {
270 impl TopEncodeNoErr for $num_type {
271 #[inline]
272 fn top_encode_no_err<O: TopEncodeOutput>(&self, output: O) {
273 output.set_i64(*self as i64);
274 }
275 }
276
277 top_encode_from_no_err! {$num_type, $type_info}
278 };
279}
280
281encode_num_signed! {i64, 64, TypeInfo::I64}
282encode_num_signed! {i32, 32, TypeInfo::I32}
283encode_num_signed! {isize, 32, TypeInfo::ISIZE}
284encode_num_signed! {i16, 16, TypeInfo::I16}
285encode_num_signed! {i8, 8, TypeInfo::I8}
286
287impl TopEncodeNoErr for bool {
288 fn top_encode_no_err<O: TopEncodeOutput>(&self, output: O) {
289 output.set_i64(if *self { 1i64 } else { 0i64 });
292 }
293}
294
295top_encode_from_no_err! {bool, TypeInfo::Bool}
296
297impl<T: NestedEncode> TopEncode for Option<T> {
298 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
301 match self {
302 Some(v) => {
303 let mut buffer = Vec::<u8>::new();
304 buffer.push_byte(1u8);
305 v.dep_encode(&mut buffer)?;
306 output.set_slice_u8(&buffer[..]);
307 },
308 None => {
309 output.set_slice_u8(&[]);
310 },
311 }
312 Ok(())
313 }
314
315 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
318 &self,
319 output: O,
320 c: ExitCtx,
321 exit: fn(ExitCtx, EncodeError) -> !,
322 ) {
323 match self {
324 Some(v) => {
325 let mut buffer = Vec::<u8>::new();
326 buffer.push_byte(1u8);
327 v.dep_encode_or_exit(&mut buffer, c, exit);
328 output.set_slice_u8(&buffer[..]);
329 },
330 None => {
331 output.set_slice_u8(&[]);
332 },
333 }
334 }
335}
336
337impl<T: TopEncode> TopEncode for Box<T> {
338 #[inline]
339 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
340 self.as_ref().top_encode(output)
341 }
342
343 #[inline]
344 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
345 &self,
346 output: O,
347 c: ExitCtx,
348 exit: fn(ExitCtx, EncodeError) -> !,
349 ) {
350 self.as_ref().top_encode_or_exit(output, c, exit);
351 }
352}
353
354impl<T: NestedEncode> TopEncode for Box<[T]> {
355 #[inline]
356 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
357 self.as_ref().top_encode(output)
358 }
359
360 #[inline]
361 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
362 &self,
363 output: O,
364 c: ExitCtx,
365 exit: fn(ExitCtx, EncodeError) -> !,
366 ) {
367 self.as_ref().top_encode_or_exit(output, c, exit);
368 }
369}
370
371macro_rules! tuple_impls {
372 ($(($($n:tt $name:ident)+))+) => {
373 $(
374 impl<$($name),+> TopEncode for ($($name,)+)
375 where
376 $($name: NestedEncode,)+
377 {
378 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
379 let mut buffer = Vec::<u8>::new();
380 $(
381 self.$n.dep_encode(&mut buffer)?;
382 )+
383 output.set_slice_u8(&buffer[..]);
384 Ok(())
385 }
386
387 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(&self, output: O, c: ExitCtx, exit: fn(ExitCtx, EncodeError) -> !) {
388 let mut buffer = Vec::<u8>::new();
389 $(
390 self.$n.dep_encode_or_exit(&mut buffer, c.clone(), exit);
391 )+
392 output.set_slice_u8(&buffer[..]);
393 }
394 }
395 )+
396 }
397}
398
399tuple_impls! {
400 (0 T0)
401 (0 T0 1 T1)
402 (0 T0 1 T1 2 T2)
403 (0 T0 1 T1 2 T2 3 T3)
404 (0 T0 1 T1 2 T2 3 T3 4 T4)
405 (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
406 (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
407 (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
408 (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
409 (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
410 (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
411 (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
412 (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)
413 (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)
414 (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)
415 (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)
416}
417
418impl TopEncode for NonZeroUsize {
419 fn top_encode<O: TopEncodeOutput>(&self, output: O) -> Result<(), EncodeError> {
420 self.get().top_encode(output)
421 }
422
423 fn top_encode_or_exit<O: TopEncodeOutput, ExitCtx: Clone>(
424 &self,
425 output: O,
426 c: ExitCtx,
427 exit: fn(ExitCtx, EncodeError) -> !,
428 ) {
429 self.get().top_encode_or_exit(output, c, exit);
430 }
431}
432
433#[cfg(test)]
436mod tests {
437 use super::super::test_struct::*;
438 use super::*;
439 use crate::test_util::check_top_encode;
440 use core::fmt::Debug;
441
442 fn ser_ok<V>(element: V, expected_bytes: &[u8])
443 where
444 V: TopEncode + PartialEq + Debug + 'static,
445 {
446 let bytes = check_top_encode(&element);
447 assert_eq!(bytes.as_slice(), expected_bytes);
448 }
449
450 #[test]
451 fn test_serialize_top_compacted_numbers() {
452 ser_ok(5u8, &[5]);
454 ser_ok(5u16, &[5]);
455 ser_ok(5u32, &[5]);
456 ser_ok(5u64, &[5]);
457 ser_ok(5usize, &[5]);
458 ser_ok(5i8, &[5]);
460 ser_ok(5i16, &[5]);
461 ser_ok(5i32, &[5]);
462 ser_ok(5i64, &[5]);
463 ser_ok(5isize, &[5]);
464 ser_ok(-5i8, &[251]);
466 ser_ok(-5i16, &[251]);
467 ser_ok(-5i32, &[251]);
468 ser_ok(-5i64, &[251]);
469 ser_ok(-5isize, &[251]);
470 ser_ok(NonZeroUsize::new(5).unwrap(), &[5]);
472 }
473
474 #[test]
475 fn test_serialize_top_compacted_numbers_msb_ok() {
476 ser_ok(127i32, &[127]);
477 ser_ok(128i32, &[0, 128]);
478 ser_ok(255i32, &[0, 255]);
479
480 ser_ok(-1i32, &[255]);
481 ser_ok(-128i32, &[128]);
482 ser_ok(-129i32, &[255, 127]);
483 ser_ok(-256i32, &[255, 0]);
484 ser_ok(-257i32, &[254, 255]);
485 }
486
487 #[test]
488 fn test_top_compacted_bool() {
489 ser_ok(true, &[1]);
490 ser_ok(false, &[]);
491 }
492
493 #[test]
494 fn test_top_compacted_empty_bytes() {
495 let empty_byte_slice: &[u8] = &[];
496 ser_ok(empty_byte_slice, empty_byte_slice);
497 }
498
499 #[test]
500 fn test_top_compacted_bytes() {
501 ser_ok(&[1u8, 2u8, 3u8][..], &[1u8, 2u8, 3u8]);
502 }
503
504 #[test]
505 fn test_top_compacted_vec_u8() {
506 let some_vec = [1u8, 2u8, 3u8].to_vec();
507 ser_ok(some_vec, &[1u8, 2u8, 3u8]);
508 }
509
510 #[test]
511 fn test_top_encode_str() {
512 let s = "abc";
513 ser_ok(s, &[b'a', b'b', b'c']);
514 ser_ok(String::from(s), &[b'a', b'b', b'c']);
515 ser_ok(String::from(s).into_boxed_str(), &[b'a', b'b', b'c']);
516 }
517
518 #[test]
519 fn test_top_compacted_vec_i32() {
520 let some_vec = [1i32, 2i32, 3i32].to_vec();
521 let expected: &[u8] = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
522 ser_ok(some_vec, expected);
523 }
524
525 #[test]
526 fn test_struct() {
527 let test = Test {
528 int: 1,
529 seq: [5, 6].to_vec(),
530 another_byte: 7,
531 };
532
533 ser_ok(test, &[0, 1, 0, 0, 0, 2, 5, 6, 7]);
534 }
535
536 #[test]
537 fn test_tuple() {
538 ser_ok((7u32, -2i16), &[0, 0, 0, 7, 255, 254]);
539 }
540
541 #[test]
542 fn test_unit() {
543 ser_ok((), &[]);
544 }
545
546 #[test]
547 fn test_enum() {
548 let u = E::Unit;
549 let expected: &[u8] = &[0, 0, 0, 0];
550 ser_ok(u, expected);
551
552 let n = E::Newtype(1);
553 let expected: &[u8] = &[0, 0, 0, 1, 0, 0, 0, 1];
554 ser_ok(n, expected);
555
556 let t = E::Tuple(1, 2);
557 let expected: &[u8] = &[
558 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0,
559 2, ];
561 ser_ok(t, expected);
562
563 let s = E::Struct { a: 1 };
564 let expected: &[u8] = &[0, 0, 0, 3, 0, 0, 0, 1];
565 ser_ok(s, expected);
566 }
567}