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