chia_traits/
streamable.rs

1use crate::chia_error::{Error, Result};
2use chia_sha2::Sha256;
3use std::io::Cursor;
4use std::mem;
5
6pub fn read_bytes<'a>(input: &'a mut Cursor<&[u8]>, len: usize) -> Result<&'a [u8]> {
7    let pos = input.position();
8    let buf: &'a [u8] = &input.get_ref()[pos as usize..];
9    if buf.len() < len {
10        Err(Error::EndOfBuffer)
11    } else {
12        let ret = &buf[..len];
13        input.set_position(pos + len as u64);
14        Ok(ret)
15    }
16}
17
18#[test]
19fn test_read_bytes() {
20    let mut input = Cursor::<&[u8]>::new(&[0_u8, 1, 2, 3, 4]);
21    assert_eq!(read_bytes(&mut input, 1).unwrap(), [0_u8]);
22    assert_eq!(read_bytes(&mut input, 1).unwrap(), [1_u8]);
23    assert_eq!(read_bytes(&mut input, 1).unwrap(), [2_u8]);
24    assert_eq!(read_bytes(&mut input, 1).unwrap(), [3_u8]);
25    assert_eq!(read_bytes(&mut input, 1).unwrap(), [4_u8]);
26    assert_eq!(read_bytes(&mut input, 1).unwrap_err(), Error::EndOfBuffer);
27}
28
29pub trait Streamable {
30    fn update_digest(&self, digest: &mut Sha256);
31    fn stream(&self, out: &mut Vec<u8>) -> Result<()>;
32    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self>
33    where
34        Self: Sized;
35
36    // convenience functions for the top-level Streamable object
37    // these are meant to be used by *users* of streamable objects
38    // whereas the above functions are meant to be implemented by *implementers*
39    // of streamable types
40    fn to_bytes(&self) -> Result<Vec<u8>> {
41        let mut ret = Vec::<u8>::new();
42        self.stream(&mut ret)?;
43        Ok(ret)
44    }
45    fn from_bytes(bytes: &[u8]) -> Result<Self>
46    where
47        Self: Sized,
48    {
49        let mut cursor = Cursor::new(bytes);
50        let ret = Self::parse::<false>(&mut cursor)?;
51        if cursor.position() == bytes.len() as u64 {
52            Ok(ret)
53        } else {
54            Err(Error::InputTooLarge)
55        }
56    }
57    fn from_bytes_unchecked(bytes: &[u8]) -> Result<Self>
58    where
59        Self: Sized,
60    {
61        let mut cursor = Cursor::new(bytes);
62        let ret = Self::parse::<true>(&mut cursor)?;
63        if cursor.position() == bytes.len() as u64 {
64            Ok(ret)
65        } else {
66            Err(Error::InputTooLarge)
67        }
68    }
69    fn hash(&self) -> [u8; 32] {
70        let mut ctx = Sha256::new();
71        self.update_digest(&mut ctx);
72        ctx.finalize()
73    }
74}
75
76macro_rules! streamable_primitive {
77    ($t:ty) => {
78        impl Streamable for $t {
79            fn update_digest(&self, digest: &mut Sha256) {
80                digest.update(&self.to_be_bytes());
81            }
82            fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
83                Ok(out.extend_from_slice(&self.to_be_bytes()))
84            }
85            fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
86                let sz = mem::size_of::<$t>();
87                Ok(<$t>::from_be_bytes(
88                    read_bytes(input, sz)?.try_into().unwrap(),
89                ))
90            }
91        }
92    };
93}
94
95streamable_primitive!(u8);
96streamable_primitive!(i8);
97streamable_primitive!(u16);
98streamable_primitive!(i16);
99streamable_primitive!(u32);
100streamable_primitive!(i32);
101streamable_primitive!(u64);
102streamable_primitive!(i64);
103streamable_primitive!(u128);
104streamable_primitive!(i128);
105
106impl<T: Streamable> Streamable for Vec<T> {
107    fn update_digest(&self, digest: &mut Sha256) {
108        (self.len() as u32).update_digest(digest);
109        for e in self {
110            e.update_digest(digest);
111        }
112    }
113
114    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
115        if self.len() > u32::MAX as usize {
116            Err(Error::InputTooLarge)
117        } else {
118            (self.len() as u32).stream(out)?;
119            for e in self {
120                e.stream(out)?;
121            }
122            Ok(())
123        }
124    }
125
126    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
127        let len = u32::parse::<TRUSTED>(input)?;
128
129        let mut ret = if mem::size_of::<T>() == 0 {
130            Vec::<T>::new()
131        } else {
132            let limit = 2 * 1024 * 1024 / mem::size_of::<T>();
133            Vec::<T>::with_capacity(std::cmp::min(limit, len as usize))
134        };
135        for _ in 0..len {
136            ret.push(T::parse::<TRUSTED>(input)?);
137        }
138        Ok(ret)
139    }
140}
141
142impl Streamable for String {
143    fn update_digest(&self, digest: &mut Sha256) {
144        let bytes = self.as_bytes();
145        (bytes.len() as u32).update_digest(digest);
146        digest.update(bytes);
147    }
148
149    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
150        // bytes is the UTF-8 sequence
151        let bytes = self.bytes();
152        if bytes.len() > u32::MAX as usize {
153            Err(Error::InputTooLarge)
154        } else {
155            (bytes.len() as u32).stream(out)?;
156            out.extend(bytes);
157            Ok(())
158        }
159    }
160
161    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
162        let len = u32::parse::<TRUSTED>(input)?;
163        Ok(String::from(
164            std::str::from_utf8(read_bytes(input, len as usize)?)
165                .map_err(|_| Error::InvalidString)?,
166        ))
167    }
168}
169
170impl Streamable for bool {
171    fn update_digest(&self, digest: &mut Sha256) {
172        digest.update(if *self { [1] } else { [0] });
173    }
174
175    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
176        out.extend_from_slice(if *self { &[1] } else { &[0] });
177        Ok(())
178    }
179    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
180        let val = read_bytes(input, 1)?[0];
181        match val {
182            0 => Ok(false),
183            1 => Ok(true),
184            _ => Err(Error::InvalidBool),
185        }
186    }
187}
188
189impl Streamable for () {
190    fn update_digest(&self, _digest: &mut Sha256) {}
191    fn stream(&self, _out: &mut Vec<u8>) -> Result<()> {
192        Ok(())
193    }
194    fn parse<const TRUSTED: bool>(_input: &mut Cursor<&[u8]>) -> Result<Self> {
195        Ok(())
196    }
197}
198
199impl<T: Streamable> Streamable for Option<T> {
200    fn update_digest(&self, digest: &mut Sha256) {
201        match self {
202            None => {
203                digest.update([0]);
204            }
205            Some(v) => {
206                digest.update([1]);
207                v.update_digest(digest);
208            }
209        }
210    }
211
212    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
213        match self {
214            None => {
215                out.push(0);
216            }
217            Some(v) => {
218                out.push(1);
219                v.stream(out)?;
220            }
221        }
222        Ok(())
223    }
224    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
225        let val = read_bytes(input, 1)?[0];
226        match val {
227            0 => Ok(None),
228            1 => Ok(Some(T::parse::<TRUSTED>(input)?)),
229            _ => Err(Error::InvalidOptional),
230        }
231    }
232}
233
234impl<T: Streamable, U: Streamable> Streamable for (T, U) {
235    fn update_digest(&self, digest: &mut Sha256) {
236        self.0.update_digest(digest);
237        self.1.update_digest(digest);
238    }
239    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
240        self.0.stream(out)?;
241        self.1.stream(out)?;
242        Ok(())
243    }
244    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
245        Ok((T::parse::<TRUSTED>(input)?, U::parse::<TRUSTED>(input)?))
246    }
247}
248
249impl<T: Streamable, U: Streamable, V: Streamable> Streamable for (T, U, V) {
250    fn update_digest(&self, digest: &mut Sha256) {
251        self.0.update_digest(digest);
252        self.1.update_digest(digest);
253        self.2.update_digest(digest);
254    }
255    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
256        self.0.stream(out)?;
257        self.1.stream(out)?;
258        self.2.stream(out)?;
259        Ok(())
260    }
261    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
262        Ok((
263            T::parse::<TRUSTED>(input)?,
264            U::parse::<TRUSTED>(input)?,
265            V::parse::<TRUSTED>(input)?,
266        ))
267    }
268}
269
270impl<T: Streamable, U: Streamable, V: Streamable, W: Streamable> Streamable for (T, U, V, W) {
271    fn update_digest(&self, digest: &mut Sha256) {
272        self.0.update_digest(digest);
273        self.1.update_digest(digest);
274        self.2.update_digest(digest);
275        self.3.update_digest(digest);
276    }
277    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
278        self.0.stream(out)?;
279        self.1.stream(out)?;
280        self.2.stream(out)?;
281        self.3.stream(out)?;
282        Ok(())
283    }
284    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
285        Ok((
286            T::parse::<TRUSTED>(input)?,
287            U::parse::<TRUSTED>(input)?,
288            V::parse::<TRUSTED>(input)?,
289            W::parse::<TRUSTED>(input)?,
290        ))
291    }
292}
293
294impl<T, const N: usize> Streamable for [T; N]
295where
296    T: Streamable + std::marker::Copy + Default,
297{
298    fn update_digest(&self, digest: &mut Sha256) {
299        for val in self {
300            val.update_digest(digest);
301        }
302    }
303    fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
304        for val in self {
305            val.stream(out)?;
306        }
307        Ok(())
308    }
309    fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
310        let mut ret = [<T as Default>::default(); N];
311        for v in &mut ret {
312            *v = T::parse::<TRUSTED>(input)?;
313        }
314        Ok(ret)
315    }
316}
317
318// ===== TESTS ====
319
320#[cfg(test)]
321#[allow(clippy::needless_pass_by_value)]
322fn from_bytes<T: Streamable + std::fmt::Debug + PartialEq>(buf: &[u8], expected: T) {
323    let mut input = Cursor::<&[u8]>::new(buf);
324    assert_eq!(T::parse::<false>(&mut input).unwrap(), expected);
325}
326
327#[cfg(test)]
328#[allow(clippy::needless_pass_by_value)]
329fn from_bytes_fail<T: Streamable + std::fmt::Debug + PartialEq>(buf: &[u8], expected: Error) {
330    let mut input = Cursor::<&[u8]>::new(buf);
331    assert_eq!(T::parse::<false>(&mut input).unwrap_err(), expected);
332}
333
334#[test]
335fn test_parse_u64() {
336    from_bytes::<u64>(&[0, 0, 0, 0, 0, 0, 0, 0], 0);
337    from_bytes::<u64>(&[0, 0, 0, 0, 0, 0, 0, 1], 1);
338    from_bytes::<u64>(&[0x80, 0, 0, 0, 0, 0, 0, 0], 0x8000_0000_0000_0000);
339    from_bytes::<u64>(
340        &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
341        0xffff_ffff_ffff_ffff,
342    );
343
344    // truncated
345    from_bytes_fail::<u64>(&[0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
346    from_bytes_fail::<u64>(&[0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
347    from_bytes_fail::<u64>(&[0, 0, 0, 0, 0], Error::EndOfBuffer);
348    from_bytes_fail::<u64>(&[0, 0, 0, 0], Error::EndOfBuffer);
349    from_bytes_fail::<u64>(&[0, 0, 0], Error::EndOfBuffer);
350    from_bytes_fail::<u64>(&[0, 0], Error::EndOfBuffer);
351}
352
353#[test]
354fn test_parse_u128() {
355    from_bytes::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0);
356    from_bytes::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 1);
357    from_bytes::<u128>(
358        &[0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
359        0x8000_0000_0000_0000_0000_0000_0000_0000,
360    );
361    from_bytes::<u128>(
362        &[
363            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
364            0xff, 0xff,
365        ],
366        0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff,
367    );
368
369    // truncated
370    from_bytes_fail::<u128>(
371        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
372        Error::EndOfBuffer,
373    );
374    from_bytes_fail::<u128>(
375        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
376        Error::EndOfBuffer,
377    );
378    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
379    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
380    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
381    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
382}
383
384#[test]
385fn test_parse_empty_list() {
386    let buf: &[u8] = &[0, 0, 0, 0];
387    from_bytes::<Vec<u32>>(buf, vec![]);
388}
389
390#[test]
391fn test_parse_list_1() {
392    let buf: &[u8] = &[0, 0, 0, 1, 1, 2, 3, 4];
393    from_bytes::<Vec<u32>>(buf, vec![0x0102_0304]);
394}
395
396#[test]
397fn test_parse_list_3() {
398    let buf: &[u8] = &[0, 0, 0, 3, 1, 2, 3, 4, 1, 3, 3, 7, 0, 0, 4, 2];
399    from_bytes::<Vec<u32>>(buf, vec![0x0102_0304, 0x0103_0307, 0x402]);
400}
401
402#[test]
403fn test_parse_list_list_3() {
404    let buf: &[u8] = &[
405        0, 0, 0, 3, 0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 1, 1, 3, 3, 7, 0, 0, 0, 1, 0, 0, 4, 2,
406    ];
407    from_bytes::<Vec<Vec<u32>>>(buf, vec![vec![0x0102_0304], vec![0x0103_0307], vec![0x402]]);
408}
409
410#[test]
411fn test_parse_list_empty() {
412    let buf: &[u8] = &[0, 0, 0, 3];
413    from_bytes::<Vec<()>>(buf, vec![(), (), ()]);
414}
415
416#[test]
417fn test_parse_long_list() {
418    let buf: &[u8] = &[0xff, 0xff, 0xff, 0xff, 0, 0, 0];
419    from_bytes_fail::<Vec<u32>>(buf, Error::EndOfBuffer);
420}
421
422#[test]
423fn test_parse_tuple() {
424    let buf: &[u8] = &[0, 0, 0, 3, 42, 0xff];
425    from_bytes::<(u32, u8, i8)>(buf, (3, 42, -1));
426}
427
428#[test]
429fn test_parse_nested_tuple() {
430    let buf: &[u8] = &[0, 0, 0, 3, 42, 43, 44, 0xff, 0xff, 0xff, 0xff];
431    from_bytes::<(u32, (u8, u8, u8), i32)>(buf, (3, (42, 43, 44), -1));
432}
433
434#[test]
435fn test_parse_optional_clear() {
436    let buf: &[u8] = &[0];
437    from_bytes::<Option<u32>>(buf, None);
438}
439
440#[test]
441fn test_parse_optional_zero() {
442    let buf: &[u8] = &[1, 0];
443    from_bytes::<Option<u8>>(buf, Some(0));
444}
445
446#[test]
447fn test_parse_optional_u32() {
448    let buf: &[u8] = &[1, 0, 0, 0x13, 0x37];
449    from_bytes::<Option<u32>>(buf, Some(0x1337));
450}
451
452#[test]
453fn test_parse_optional_str() {
454    let buf: &[u8] = &[1, 0, 0, 0, 3, b'f', b'o', b'o'];
455    from_bytes::<Option<String>>(buf, Some("foo".to_string()));
456}
457
458#[test]
459fn test_parse_invalid_optional() {
460    // the prefix has to be 0 or 1
461    // 2 is invalid
462    let buf: &[u8] = &[2, 0, 0, 0, 0];
463    from_bytes_fail::<Option<u32>>(buf, Error::InvalidOptional);
464}
465
466#[test]
467fn test_parse_true() {
468    let buf: &[u8] = &[1];
469    from_bytes::<bool>(buf, true);
470}
471
472#[test]
473fn test_parse_false() {
474    let buf: &[u8] = &[0];
475    from_bytes::<bool>(buf, false);
476}
477
478#[test]
479fn test_parse_invalid_bool() {
480    // the bool has to be 0 or 1
481    // 2 is invalid
482    let buf: &[u8] = &[2];
483    from_bytes_fail::<bool>(buf, Error::InvalidBool);
484}
485
486#[test]
487fn test_parse_str() {
488    let buf: &[u8] = &[0, 0, 0, 3, b'f', b'o', b'o'];
489    from_bytes::<String>(buf, "foo".to_string());
490}
491
492#[test]
493fn test_parse_invalid_utf8_str() {
494    let buf: &[u8] = &[
495        0, 0, 0, 11, 195, 165, 195, 0, 164, 195, 182, 195, 188, 195, 174,
496    ];
497    from_bytes_fail::<String>(buf, Error::InvalidString);
498}
499
500#[test]
501fn test_parse_empty_str() {
502    let buf: &[u8] = &[0, 0, 0, 0];
503    from_bytes::<String>(buf, String::new());
504}
505
506#[test]
507fn test_parse_truncated_str() {
508    let buf: &[u8] = &[0, 0, 0, 10, b'f', b'o', b'o'];
509    from_bytes_fail::<String>(buf, Error::EndOfBuffer);
510}
511
512#[cfg(test)]
513use chia_streamable_macro::Streamable;
514
515#[cfg(test)]
516#[derive(Streamable, PartialEq, Debug)]
517struct TestStruct {
518    a: Vec<i8>,
519    b: String,
520    c: (u32, u32),
521}
522
523#[test]
524fn test_parse_struct() {
525    let buf: &[u8] = &[
526        0, 0, 0, 2, 42, 0xff, 0, 0, 0, 3, b'b', b'a', b'z', 0xff, 0xff, 0xff, 0xff, 0, 0, 0x13,
527        0x37,
528    ];
529    from_bytes::<TestStruct>(
530        buf,
531        TestStruct {
532            a: vec![42_i8, -1],
533            b: "baz".to_string(),
534            c: (0xffff_ffff, 0x1337),
535        },
536    );
537}
538
539#[cfg(test)]
540#[derive(Streamable, PartialEq, Debug)]
541struct TestTuple(String, u32);
542
543#[test]
544fn test_parse_custom_tuple() {
545    let buf: &[u8] = &[0, 0, 0, 3, b'b', b'a', b'z', 0, 0, 0, 42];
546    from_bytes::<TestTuple>(buf, TestTuple("baz".to_string(), 42));
547}
548
549#[cfg(test)]
550fn stream<T: Streamable>(v: &T) -> Vec<u8> {
551    let mut buf = Vec::<u8>::new();
552    v.stream(&mut buf).unwrap();
553    let mut ctx1 = Sha256::new();
554    let mut ctx2 = Sha256::new();
555    v.update_digest(&mut ctx1);
556    ctx2.update(&buf);
557    assert_eq!(&ctx1.finalize(), &ctx2.finalize());
558    buf
559}
560
561#[test]
562fn test_stream_i32() {
563    let b: i32 = 0x0102_0304;
564    let buf = stream(&b);
565    assert_eq!(&buf[..], [1, 2, 3, 4]);
566}
567
568#[test]
569fn test_stream_sequence() {
570    let b: Vec<u8> = vec![1, 2, 3, 4, 5, 42, 127];
571    let buf = stream(&b);
572    // 4 byte length prefix
573    assert_eq!(&buf[..], [0, 0, 0, 7, 1, 2, 3, 4, 5, 42, 127]);
574}
575
576#[test]
577fn test_stream_empty_sequence() {
578    let b: Vec<u8> = vec![];
579    let buf = stream(&b);
580    // 4 byte length prefix
581    assert_eq!(&buf[..], [0, 0, 0, 0]);
582}
583
584#[test]
585fn test_stream_none() {
586    let b: Option<u8> = None;
587    let buf = stream(&b);
588    assert_eq!(&buf[..], [0]);
589}
590
591#[test]
592fn test_stream_optional() {
593    let b: Option<u32> = Some(0x1337);
594    let buf = stream(&b);
595    assert_eq!(&buf[..], [1, 0, 0, 0x13, 0x37]);
596}
597
598#[test]
599fn test_stream_optional_zero() {
600    let b: Option<u32> = Some(0);
601    let buf = stream(&b);
602    assert_eq!(&buf[..], [1, 0, 0, 0, 0]);
603}
604
605#[test]
606fn test_stream_optional_set1() {
607    let out = stream(&Some(42_u32));
608    assert_eq!(&out, &[1, 0, 0, 0, 42]);
609}
610
611#[test]
612fn test_stream_optional_set2() {
613    let out = stream(&Some("foobar".to_string()));
614    assert_eq!(&out, &[1, 0, 0, 0, 6, b'f', b'o', b'o', b'b', b'a', b'r']);
615}
616
617#[test]
618fn test_stream_tuple() {
619    let b: (u8, u32, u64, bool) = (42, 0x1337, 0x0102_0304_0506_0708, true);
620    let buf = stream(&b);
621    assert_eq!(&buf[..], [42, 0, 0, 0x13, 0x37, 1, 2, 3, 4, 5, 6, 7, 8, 1]);
622}
623
624#[test]
625fn test_stream_tuple_of_lists() {
626    let b: (Vec<u8>, Vec<u8>) = (vec![0, 1, 2, 3], vec![4, 5, 6, 7, 8, 9]);
627    let buf = stream(&b);
628    assert_eq!(
629        &buf[..],
630        [0, 0, 0, 4, 0, 1, 2, 3, 0, 0, 0, 6, 4, 5, 6, 7, 8, 9]
631    );
632}
633
634#[test]
635fn test_stream_tuple1() {
636    let out = stream(&(42_u32));
637    assert_eq!(&out, &[0, 0, 0, 42]);
638}
639#[test]
640fn test_stream_tuple2() {
641    let out = stream(&("test".to_string(), 42_u32));
642    assert_eq!(&out, &[0, 0, 0, 4, b't', b'e', b's', b't', 0, 0, 0, 42]);
643}
644
645#[test]
646fn test_stream_tuple_of_tuples() {
647    let out = stream(&((0x1337_u32, 42_u32), ("foo".to_string(), "bar".to_string())));
648    assert_eq!(
649        &out,
650        &[
651            0, 0, 0x13, 0x37, 0, 0, 0, 42, 0, 0, 0, 3, b'f', b'o', b'o', 0, 0, 0, 3, b'b', b'a',
652            b'r'
653        ]
654    );
655}
656
657#[test]
658fn test_stream_false() {
659    let b = false;
660    let buf = stream(&b);
661    assert_eq!(&buf[..], [0]);
662}
663
664#[test]
665fn test_stream_true() {
666    let b = true;
667    let buf = stream(&b);
668    assert_eq!(&buf[..], [1]);
669}
670
671#[test]
672fn test_stream_string() {
673    let b = "abc".to_string();
674    let buf = stream(&b);
675    assert_eq!(&buf[..], [0, 0, 0, 3, b'a', b'b', b'c']);
676}
677
678#[test]
679fn test_stream_empty_string() {
680    let b = String::new();
681    let buf = stream(&b);
682    assert_eq!(&buf[..], [0, 0, 0, 0]);
683}
684
685#[test]
686fn test_stream_utf8_string() {
687    let b = "åäöüî".to_string();
688    let buf = stream(&b);
689    assert_eq!(
690        &buf[..],
691        [
692            0, 0, 0, 10, 195, 165, 195, 164, 195, 182, 195, 188, 195, 174
693        ]
694    );
695}
696
697#[test]
698fn test_stream_struct() {
699    let b = TestStruct {
700        a: [1, 2, 3].to_vec(),
701        b: "abc".to_string(),
702        c: (0x1337, 42),
703    };
704    let buf = stream(&b);
705    assert_eq!(
706        &buf[..],
707        [
708            0, 0, 0, 3, 1, 2, 3, 0, 0, 0, 3, b'a', b'b', b'c', 0, 0, 0x13, 0x37, 0, 0, 0, 42
709        ]
710    );
711}
712
713#[test]
714fn test_stream_custom_tuple() {
715    let b = TestTuple("abc".to_string(), 1337);
716    let buf = stream(&b);
717    assert_eq!(&buf[..], [0, 0, 0, 3, b'a', b'b', b'c', 0, 0, 0x05, 0x39]);
718}
719
720#[test]
721fn test_stream_list() {
722    let out = stream(&vec![0x0103_0307_u32, 42, 0xffff_ffff]);
723    assert_eq!(
724        &out,
725        &[0, 0, 0, 3, 1, 3, 3, 7, 0, 0, 0, 42, 0xff, 0xff, 0xff, 0xff]
726    );
727}
728
729#[test]
730fn test_stream_list_of_empty() {
731    let out = stream(&vec![(), (), ()]);
732    assert_eq!(&out, &[0, 0, 0, 3]);
733}
734
735#[test]
736fn test_stream_list_list() {
737    let out = stream(&vec![
738        vec![0x0103_0307_u32],
739        vec![42_u32],
740        vec![0xffff_ffff_u32],
741    ]);
742    assert_eq!(
743        &out,
744        &[
745            0, 0, 0, 3, 0, 0, 0, 1, 1, 3, 3, 7, 0, 0, 0, 1, 0, 0, 0, 42, 0, 0, 0, 1, 0xff, 0xff,
746            0xff, 0xff
747        ]
748    );
749}
750
751#[test]
752fn test_stream_u128() {
753    let out = stream(&(1337_u128, -1337_i128));
754    assert_eq!(
755        &out,
756        &[
757            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x05, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff,
758            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xc7
759        ]
760    );
761}
762
763#[cfg(test)]
764#[derive(Streamable, Hash, Copy, Debug, Clone, Eq, PartialEq)]
765enum TestEnum {
766    A = 0,
767    B = 1,
768    C = 255,
769}
770
771#[test]
772fn test_parse_enum() {
773    from_bytes::<TestEnum>(&[0], TestEnum::A);
774    from_bytes::<TestEnum>(&[1], TestEnum::B);
775    from_bytes::<TestEnum>(&[255], TestEnum::C);
776    from_bytes_fail::<TestEnum>(&[3], Error::InvalidEnum);
777    from_bytes_fail::<TestEnum>(&[254], Error::InvalidEnum);
778    from_bytes_fail::<TestEnum>(&[128], Error::InvalidEnum);
779}
780
781#[test]
782fn test_stream_enum() {
783    assert_eq!(stream::<TestEnum>(&TestEnum::A), &[0_u8]);
784    assert_eq!(stream::<TestEnum>(&TestEnum::B), &[1_u8]);
785    assert_eq!(stream::<TestEnum>(&TestEnum::C), &[255_u8]);
786}