chik_traits/
streamable.rs

1use crate::chik_error::{Error, Result};
2use chik_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
294// ===== TESTS ====
295
296#[cfg(test)]
297#[allow(clippy::needless_pass_by_value)]
298fn from_bytes<T: Streamable + std::fmt::Debug + PartialEq>(buf: &[u8], expected: T) {
299    let mut input = Cursor::<&[u8]>::new(buf);
300    assert_eq!(T::parse::<false>(&mut input).unwrap(), expected);
301}
302
303#[cfg(test)]
304#[allow(clippy::needless_pass_by_value)]
305fn from_bytes_fail<T: Streamable + std::fmt::Debug + PartialEq>(buf: &[u8], expected: Error) {
306    let mut input = Cursor::<&[u8]>::new(buf);
307    assert_eq!(T::parse::<false>(&mut input).unwrap_err(), expected);
308}
309
310#[test]
311fn test_parse_u64() {
312    from_bytes::<u64>(&[0, 0, 0, 0, 0, 0, 0, 0], 0);
313    from_bytes::<u64>(&[0, 0, 0, 0, 0, 0, 0, 1], 1);
314    from_bytes::<u64>(&[0x80, 0, 0, 0, 0, 0, 0, 0], 0x8000_0000_0000_0000);
315    from_bytes::<u64>(
316        &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
317        0xffff_ffff_ffff_ffff,
318    );
319
320    // truncated
321    from_bytes_fail::<u64>(&[0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
322    from_bytes_fail::<u64>(&[0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
323    from_bytes_fail::<u64>(&[0, 0, 0, 0, 0], Error::EndOfBuffer);
324    from_bytes_fail::<u64>(&[0, 0, 0, 0], Error::EndOfBuffer);
325    from_bytes_fail::<u64>(&[0, 0, 0], Error::EndOfBuffer);
326    from_bytes_fail::<u64>(&[0, 0], Error::EndOfBuffer);
327}
328
329#[test]
330fn test_parse_u128() {
331    from_bytes::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0);
332    from_bytes::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 1);
333    from_bytes::<u128>(
334        &[0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
335        0x8000_0000_0000_0000_0000_0000_0000_0000,
336    );
337    from_bytes::<u128>(
338        &[
339            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
340            0xff, 0xff,
341        ],
342        0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff,
343    );
344
345    // truncated
346    from_bytes_fail::<u128>(
347        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
348        Error::EndOfBuffer,
349    );
350    from_bytes_fail::<u128>(
351        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
352        Error::EndOfBuffer,
353    );
354    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
355    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
356    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
357    from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
358}
359
360#[test]
361fn test_parse_empty_list() {
362    let buf: &[u8] = &[0, 0, 0, 0];
363    from_bytes::<Vec<u32>>(buf, vec![]);
364}
365
366#[test]
367fn test_parse_list_1() {
368    let buf: &[u8] = &[0, 0, 0, 1, 1, 2, 3, 4];
369    from_bytes::<Vec<u32>>(buf, vec![0x0102_0304]);
370}
371
372#[test]
373fn test_parse_list_3() {
374    let buf: &[u8] = &[0, 0, 0, 3, 1, 2, 3, 4, 1, 3, 3, 7, 0, 0, 4, 2];
375    from_bytes::<Vec<u32>>(buf, vec![0x0102_0304, 0x0103_0307, 0x402]);
376}
377
378#[test]
379fn test_parse_list_list_3() {
380    let buf: &[u8] = &[
381        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,
382    ];
383    from_bytes::<Vec<Vec<u32>>>(buf, vec![vec![0x0102_0304], vec![0x0103_0307], vec![0x402]]);
384}
385
386#[test]
387fn test_parse_list_empty() {
388    let buf: &[u8] = &[0, 0, 0, 3];
389    from_bytes::<Vec<()>>(buf, vec![(), (), ()]);
390}
391
392#[test]
393fn test_parse_long_list() {
394    let buf: &[u8] = &[0xff, 0xff, 0xff, 0xff, 0, 0, 0];
395    from_bytes_fail::<Vec<u32>>(buf, Error::EndOfBuffer);
396}
397
398#[test]
399fn test_parse_tuple() {
400    let buf: &[u8] = &[0, 0, 0, 3, 42, 0xff];
401    from_bytes::<(u32, u8, i8)>(buf, (3, 42, -1));
402}
403
404#[test]
405fn test_parse_nested_tuple() {
406    let buf: &[u8] = &[0, 0, 0, 3, 42, 43, 44, 0xff, 0xff, 0xff, 0xff];
407    from_bytes::<(u32, (u8, u8, u8), i32)>(buf, (3, (42, 43, 44), -1));
408}
409
410#[test]
411fn test_parse_optional_clear() {
412    let buf: &[u8] = &[0];
413    from_bytes::<Option<u32>>(buf, None);
414}
415
416#[test]
417fn test_parse_optional_zero() {
418    let buf: &[u8] = &[1, 0];
419    from_bytes::<Option<u8>>(buf, Some(0));
420}
421
422#[test]
423fn test_parse_optional_u32() {
424    let buf: &[u8] = &[1, 0, 0, 0x13, 0x37];
425    from_bytes::<Option<u32>>(buf, Some(0x1337));
426}
427
428#[test]
429fn test_parse_optional_str() {
430    let buf: &[u8] = &[1, 0, 0, 0, 3, b'f', b'o', b'o'];
431    from_bytes::<Option<String>>(buf, Some("foo".to_string()));
432}
433
434#[test]
435fn test_parse_invalid_optional() {
436    // the prefix has to be 0 or 1
437    // 2 is invalid
438    let buf: &[u8] = &[2, 0, 0, 0, 0];
439    from_bytes_fail::<Option<u32>>(buf, Error::InvalidOptional);
440}
441
442#[test]
443fn test_parse_true() {
444    let buf: &[u8] = &[1];
445    from_bytes::<bool>(buf, true);
446}
447
448#[test]
449fn test_parse_false() {
450    let buf: &[u8] = &[0];
451    from_bytes::<bool>(buf, false);
452}
453
454#[test]
455fn test_parse_invalid_bool() {
456    // the bool has to be 0 or 1
457    // 2 is invalid
458    let buf: &[u8] = &[2];
459    from_bytes_fail::<bool>(buf, Error::InvalidBool);
460}
461
462#[test]
463fn test_parse_str() {
464    let buf: &[u8] = &[0, 0, 0, 3, b'f', b'o', b'o'];
465    from_bytes::<String>(buf, "foo".to_string());
466}
467
468#[test]
469fn test_parse_invalid_utf8_str() {
470    let buf: &[u8] = &[
471        0, 0, 0, 11, 195, 165, 195, 0, 164, 195, 182, 195, 188, 195, 174,
472    ];
473    from_bytes_fail::<String>(buf, Error::InvalidString);
474}
475
476#[test]
477fn test_parse_empty_str() {
478    let buf: &[u8] = &[0, 0, 0, 0];
479    from_bytes::<String>(buf, String::new());
480}
481
482#[test]
483fn test_parse_truncated_str() {
484    let buf: &[u8] = &[0, 0, 0, 10, b'f', b'o', b'o'];
485    from_bytes_fail::<String>(buf, Error::EndOfBuffer);
486}
487
488#[cfg(test)]
489use chik_streamable_macro::Streamable;
490
491#[cfg(test)]
492#[derive(Streamable, PartialEq, Debug)]
493struct TestStruct {
494    a: Vec<i8>,
495    b: String,
496    c: (u32, u32),
497}
498
499#[test]
500fn test_parse_struct() {
501    let buf: &[u8] = &[
502        0, 0, 0, 2, 42, 0xff, 0, 0, 0, 3, b'b', b'a', b'z', 0xff, 0xff, 0xff, 0xff, 0, 0, 0x13,
503        0x37,
504    ];
505    from_bytes::<TestStruct>(
506        buf,
507        TestStruct {
508            a: vec![42_i8, -1],
509            b: "baz".to_string(),
510            c: (0xffff_ffff, 0x1337),
511        },
512    );
513}
514
515#[cfg(test)]
516#[derive(Streamable, PartialEq, Debug)]
517struct TestTuple(String, u32);
518
519#[test]
520fn test_parse_custom_tuple() {
521    let buf: &[u8] = &[0, 0, 0, 3, b'b', b'a', b'z', 0, 0, 0, 42];
522    from_bytes::<TestTuple>(buf, TestTuple("baz".to_string(), 42));
523}
524
525#[cfg(test)]
526fn stream<T: Streamable>(v: &T) -> Vec<u8> {
527    let mut buf = Vec::<u8>::new();
528    v.stream(&mut buf).unwrap();
529    let mut ctx1 = Sha256::new();
530    let mut ctx2 = Sha256::new();
531    v.update_digest(&mut ctx1);
532    ctx2.update(&buf);
533    assert_eq!(&ctx1.finalize(), &ctx2.finalize());
534    buf
535}
536
537#[test]
538fn test_stream_i32() {
539    let b: i32 = 0x0102_0304;
540    let buf = stream(&b);
541    assert_eq!(&buf[..], [1, 2, 3, 4]);
542}
543
544#[test]
545fn test_stream_sequence() {
546    let b: Vec<u8> = vec![1, 2, 3, 4, 5, 42, 127];
547    let buf = stream(&b);
548    // 4 byte length prefix
549    assert_eq!(&buf[..], [0, 0, 0, 7, 1, 2, 3, 4, 5, 42, 127]);
550}
551
552#[test]
553fn test_stream_empty_sequence() {
554    let b: Vec<u8> = vec![];
555    let buf = stream(&b);
556    // 4 byte length prefix
557    assert_eq!(&buf[..], [0, 0, 0, 0]);
558}
559
560#[test]
561fn test_stream_none() {
562    let b: Option<u8> = None;
563    let buf = stream(&b);
564    assert_eq!(&buf[..], [0]);
565}
566
567#[test]
568fn test_stream_optional() {
569    let b: Option<u32> = Some(0x1337);
570    let buf = stream(&b);
571    assert_eq!(&buf[..], [1, 0, 0, 0x13, 0x37]);
572}
573
574#[test]
575fn test_stream_optional_zero() {
576    let b: Option<u32> = Some(0);
577    let buf = stream(&b);
578    assert_eq!(&buf[..], [1, 0, 0, 0, 0]);
579}
580
581#[test]
582fn test_stream_optional_set1() {
583    let out = stream(&Some(42_u32));
584    assert_eq!(&out, &[1, 0, 0, 0, 42]);
585}
586
587#[test]
588fn test_stream_optional_set2() {
589    let out = stream(&Some("foobar".to_string()));
590    assert_eq!(&out, &[1, 0, 0, 0, 6, b'f', b'o', b'o', b'b', b'a', b'r']);
591}
592
593#[test]
594fn test_stream_tuple() {
595    let b: (u8, u32, u64, bool) = (42, 0x1337, 0x0102_0304_0506_0708, true);
596    let buf = stream(&b);
597    assert_eq!(&buf[..], [42, 0, 0, 0x13, 0x37, 1, 2, 3, 4, 5, 6, 7, 8, 1]);
598}
599
600#[test]
601fn test_stream_tuple_of_lists() {
602    let b: (Vec<u8>, Vec<u8>) = (vec![0, 1, 2, 3], vec![4, 5, 6, 7, 8, 9]);
603    let buf = stream(&b);
604    assert_eq!(
605        &buf[..],
606        [0, 0, 0, 4, 0, 1, 2, 3, 0, 0, 0, 6, 4, 5, 6, 7, 8, 9]
607    );
608}
609
610#[test]
611fn test_stream_tuple1() {
612    let out = stream(&(42_u32));
613    assert_eq!(&out, &[0, 0, 0, 42]);
614}
615#[test]
616fn test_stream_tuple2() {
617    let out = stream(&("test".to_string(), 42_u32));
618    assert_eq!(&out, &[0, 0, 0, 4, b't', b'e', b's', b't', 0, 0, 0, 42]);
619}
620
621#[test]
622fn test_stream_tuple_of_tuples() {
623    let out = stream(&((0x1337_u32, 42_u32), ("foo".to_string(), "bar".to_string())));
624    assert_eq!(
625        &out,
626        &[
627            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',
628            b'r'
629        ]
630    );
631}
632
633#[test]
634fn test_stream_false() {
635    let b = false;
636    let buf = stream(&b);
637    assert_eq!(&buf[..], [0]);
638}
639
640#[test]
641fn test_stream_true() {
642    let b = true;
643    let buf = stream(&b);
644    assert_eq!(&buf[..], [1]);
645}
646
647#[test]
648fn test_stream_string() {
649    let b = "abc".to_string();
650    let buf = stream(&b);
651    assert_eq!(&buf[..], [0, 0, 0, 3, b'a', b'b', b'c']);
652}
653
654#[test]
655fn test_stream_empty_string() {
656    let b = String::new();
657    let buf = stream(&b);
658    assert_eq!(&buf[..], [0, 0, 0, 0]);
659}
660
661#[test]
662fn test_stream_utf8_string() {
663    let b = "åäöüî".to_string();
664    let buf = stream(&b);
665    assert_eq!(
666        &buf[..],
667        [0, 0, 0, 10, 195, 165, 195, 164, 195, 182, 195, 188, 195, 174]
668    );
669}
670
671#[test]
672fn test_stream_struct() {
673    let b = TestStruct {
674        a: [1, 2, 3].to_vec(),
675        b: "abc".to_string(),
676        c: (0x1337, 42),
677    };
678    let buf = stream(&b);
679    assert_eq!(
680        &buf[..],
681        [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]
682    );
683}
684
685#[test]
686fn test_stream_custom_tuple() {
687    let b = TestTuple("abc".to_string(), 1337);
688    let buf = stream(&b);
689    assert_eq!(&buf[..], [0, 0, 0, 3, b'a', b'b', b'c', 0, 0, 0x05, 0x39]);
690}
691
692#[test]
693fn test_stream_list() {
694    let out = stream(&vec![0x0103_0307_u32, 42, 0xffff_ffff]);
695    assert_eq!(
696        &out,
697        &[0, 0, 0, 3, 1, 3, 3, 7, 0, 0, 0, 42, 0xff, 0xff, 0xff, 0xff]
698    );
699}
700
701#[test]
702fn test_stream_list_of_empty() {
703    let out = stream(&vec![(), (), ()]);
704    assert_eq!(&out, &[0, 0, 0, 3]);
705}
706
707#[test]
708fn test_stream_list_list() {
709    let out = stream(&vec![
710        vec![0x0103_0307_u32],
711        vec![42_u32],
712        vec![0xffff_ffff_u32],
713    ]);
714    assert_eq!(
715        &out,
716        &[
717            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,
718            0xff, 0xff
719        ]
720    );
721}
722
723#[test]
724fn test_stream_u128() {
725    let out = stream(&(1337_u128, -1337_i128));
726    assert_eq!(
727        &out,
728        &[
729            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x05, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff,
730            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xc7
731        ]
732    );
733}
734
735#[cfg(test)]
736#[derive(Streamable, Hash, Copy, Debug, Clone, Eq, PartialEq)]
737enum TestEnum {
738    A = 0,
739    B = 1,
740    C = 255,
741}
742
743#[test]
744fn test_parse_enum() {
745    from_bytes::<TestEnum>(&[0], TestEnum::A);
746    from_bytes::<TestEnum>(&[1], TestEnum::B);
747    from_bytes::<TestEnum>(&[255], TestEnum::C);
748    from_bytes_fail::<TestEnum>(&[3], Error::InvalidEnum);
749    from_bytes_fail::<TestEnum>(&[254], Error::InvalidEnum);
750    from_bytes_fail::<TestEnum>(&[128], Error::InvalidEnum);
751}
752
753#[test]
754fn test_stream_enum() {
755    assert_eq!(stream::<TestEnum>(&TestEnum::A), &[0_u8]);
756    assert_eq!(stream::<TestEnum>(&TestEnum::B), &[1_u8]);
757    assert_eq!(stream::<TestEnum>(&TestEnum::C), &[255_u8]);
758}