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 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 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#[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 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 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 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 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 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 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}