use crate::chia_error::{Error, Result};
use chia_sha2::Sha256;
use std::io::Cursor;
use std::mem;
pub fn read_bytes<'a>(input: &'a mut Cursor<&[u8]>, len: usize) -> Result<&'a [u8]> {
let pos = input.position();
let buf: &'a [u8] = &input.get_ref()[pos as usize..];
if buf.len() < len {
Err(Error::EndOfBuffer)
} else {
let ret = &buf[..len];
input.set_position(pos + len as u64);
Ok(ret)
}
}
#[test]
fn test_read_bytes() {
let mut input = Cursor::<&[u8]>::new(&[0_u8, 1, 2, 3, 4]);
assert_eq!(read_bytes(&mut input, 1).unwrap(), [0_u8]);
assert_eq!(read_bytes(&mut input, 1).unwrap(), [1_u8]);
assert_eq!(read_bytes(&mut input, 1).unwrap(), [2_u8]);
assert_eq!(read_bytes(&mut input, 1).unwrap(), [3_u8]);
assert_eq!(read_bytes(&mut input, 1).unwrap(), [4_u8]);
assert_eq!(read_bytes(&mut input, 1).unwrap_err(), Error::EndOfBuffer);
}
pub trait Streamable {
fn update_digest(&self, digest: &mut Sha256);
fn stream(&self, out: &mut Vec<u8>) -> Result<()>;
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self>
where
Self: Sized;
fn to_bytes(&self) -> Result<Vec<u8>> {
let mut ret = Vec::<u8>::new();
self.stream(&mut ret)?;
Ok(ret)
}
fn from_bytes(bytes: &[u8]) -> Result<Self>
where
Self: Sized,
{
let mut cursor = Cursor::new(bytes);
let ret = Self::parse::<false>(&mut cursor)?;
if cursor.position() == bytes.len() as u64 {
Ok(ret)
} else {
Err(Error::InputTooLarge)
}
}
fn from_bytes_unchecked(bytes: &[u8]) -> Result<Self>
where
Self: Sized,
{
let mut cursor = Cursor::new(bytes);
let ret = Self::parse::<true>(&mut cursor)?;
if cursor.position() == bytes.len() as u64 {
Ok(ret)
} else {
Err(Error::InputTooLarge)
}
}
fn hash(&self) -> [u8; 32] {
let mut ctx = Sha256::new();
self.update_digest(&mut ctx);
ctx.finalize()
}
}
macro_rules! streamable_primitive {
($t:ty) => {
impl Streamable for $t {
fn update_digest(&self, digest: &mut Sha256) {
digest.update(&self.to_be_bytes());
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
Ok(out.extend_from_slice(&self.to_be_bytes()))
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
let sz = mem::size_of::<$t>();
Ok(<$t>::from_be_bytes(
read_bytes(input, sz)?.try_into().unwrap(),
))
}
}
};
}
streamable_primitive!(u8);
streamable_primitive!(i8);
streamable_primitive!(u16);
streamable_primitive!(i16);
streamable_primitive!(u32);
streamable_primitive!(i32);
streamable_primitive!(u64);
streamable_primitive!(i64);
streamable_primitive!(u128);
streamable_primitive!(i128);
impl<T: Streamable> Streamable for Vec<T> {
fn update_digest(&self, digest: &mut Sha256) {
(self.len() as u32).update_digest(digest);
for e in self {
e.update_digest(digest);
}
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
if self.len() > u32::MAX as usize {
Err(Error::InputTooLarge)
} else {
(self.len() as u32).stream(out)?;
for e in self {
e.stream(out)?;
}
Ok(())
}
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
let len = u32::parse::<TRUSTED>(input)?;
let mut ret = if mem::size_of::<T>() == 0 {
Vec::<T>::new()
} else {
let limit = 2 * 1024 * 1024 / mem::size_of::<T>();
Vec::<T>::with_capacity(std::cmp::min(limit, len as usize))
};
for _ in 0..len {
ret.push(T::parse::<TRUSTED>(input)?);
}
Ok(ret)
}
}
impl Streamable for String {
fn update_digest(&self, digest: &mut Sha256) {
let bytes = self.as_bytes();
(bytes.len() as u32).update_digest(digest);
digest.update(bytes);
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
let bytes = self.bytes();
if bytes.len() > u32::MAX as usize {
Err(Error::InputTooLarge)
} else {
(bytes.len() as u32).stream(out)?;
out.extend(bytes);
Ok(())
}
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
let len = u32::parse::<TRUSTED>(input)?;
Ok(String::from(
std::str::from_utf8(read_bytes(input, len as usize)?)
.map_err(|_| Error::InvalidString)?,
))
}
}
impl Streamable for bool {
fn update_digest(&self, digest: &mut Sha256) {
digest.update(if *self { [1] } else { [0] });
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
out.extend_from_slice(if *self { &[1] } else { &[0] });
Ok(())
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
let val = read_bytes(input, 1)?[0];
match val {
0 => Ok(false),
1 => Ok(true),
_ => Err(Error::InvalidBool),
}
}
}
impl Streamable for () {
fn update_digest(&self, _digest: &mut Sha256) {}
fn stream(&self, _out: &mut Vec<u8>) -> Result<()> {
Ok(())
}
fn parse<const TRUSTED: bool>(_input: &mut Cursor<&[u8]>) -> Result<Self> {
Ok(())
}
}
impl<T: Streamable> Streamable for Option<T> {
fn update_digest(&self, digest: &mut Sha256) {
match self {
None => {
digest.update([0]);
}
Some(v) => {
digest.update([1]);
v.update_digest(digest);
}
}
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
match self {
None => {
out.push(0);
}
Some(v) => {
out.push(1);
v.stream(out)?;
}
}
Ok(())
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
let val = read_bytes(input, 1)?[0];
match val {
0 => Ok(None),
1 => Ok(Some(T::parse::<TRUSTED>(input)?)),
_ => Err(Error::InvalidOptional),
}
}
}
impl<T: Streamable, U: Streamable> Streamable for (T, U) {
fn update_digest(&self, digest: &mut Sha256) {
self.0.update_digest(digest);
self.1.update_digest(digest);
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
self.0.stream(out)?;
self.1.stream(out)?;
Ok(())
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
Ok((T::parse::<TRUSTED>(input)?, U::parse::<TRUSTED>(input)?))
}
}
impl<T: Streamable, U: Streamable, V: Streamable> Streamable for (T, U, V) {
fn update_digest(&self, digest: &mut Sha256) {
self.0.update_digest(digest);
self.1.update_digest(digest);
self.2.update_digest(digest);
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
self.0.stream(out)?;
self.1.stream(out)?;
self.2.stream(out)?;
Ok(())
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
Ok((
T::parse::<TRUSTED>(input)?,
U::parse::<TRUSTED>(input)?,
V::parse::<TRUSTED>(input)?,
))
}
}
impl<T: Streamable, U: Streamable, V: Streamable, W: Streamable> Streamable for (T, U, V, W) {
fn update_digest(&self, digest: &mut Sha256) {
self.0.update_digest(digest);
self.1.update_digest(digest);
self.2.update_digest(digest);
self.3.update_digest(digest);
}
fn stream(&self, out: &mut Vec<u8>) -> Result<()> {
self.0.stream(out)?;
self.1.stream(out)?;
self.2.stream(out)?;
self.3.stream(out)?;
Ok(())
}
fn parse<const TRUSTED: bool>(input: &mut Cursor<&[u8]>) -> Result<Self> {
Ok((
T::parse::<TRUSTED>(input)?,
U::parse::<TRUSTED>(input)?,
V::parse::<TRUSTED>(input)?,
W::parse::<TRUSTED>(input)?,
))
}
}
#[cfg(test)]
#[allow(clippy::needless_pass_by_value)]
fn from_bytes<T: Streamable + std::fmt::Debug + PartialEq>(buf: &[u8], expected: T) {
let mut input = Cursor::<&[u8]>::new(buf);
assert_eq!(T::parse::<false>(&mut input).unwrap(), expected);
}
#[cfg(test)]
#[allow(clippy::needless_pass_by_value)]
fn from_bytes_fail<T: Streamable + std::fmt::Debug + PartialEq>(buf: &[u8], expected: Error) {
let mut input = Cursor::<&[u8]>::new(buf);
assert_eq!(T::parse::<false>(&mut input).unwrap_err(), expected);
}
#[test]
fn test_parse_u64() {
from_bytes::<u64>(&[0, 0, 0, 0, 0, 0, 0, 0], 0);
from_bytes::<u64>(&[0, 0, 0, 0, 0, 0, 0, 1], 1);
from_bytes::<u64>(&[0x80, 0, 0, 0, 0, 0, 0, 0], 0x8000_0000_0000_0000);
from_bytes::<u64>(
&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
0xffff_ffff_ffff_ffff,
);
from_bytes_fail::<u64>(&[0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u64>(&[0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u64>(&[0, 0, 0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u64>(&[0, 0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u64>(&[0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u64>(&[0, 0], Error::EndOfBuffer);
}
#[test]
fn test_parse_u128() {
from_bytes::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0);
from_bytes::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 1);
from_bytes::<u128>(
&[0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
0x8000_0000_0000_0000_0000_0000_0000_0000,
);
from_bytes::<u128>(
&[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff,
],
0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff,
);
from_bytes_fail::<u128>(
&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
Error::EndOfBuffer,
);
from_bytes_fail::<u128>(
&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
Error::EndOfBuffer,
);
from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
from_bytes_fail::<u128>(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Error::EndOfBuffer);
}
#[test]
fn test_parse_empty_list() {
let buf: &[u8] = &[0, 0, 0, 0];
from_bytes::<Vec<u32>>(buf, vec![]);
}
#[test]
fn test_parse_list_1() {
let buf: &[u8] = &[0, 0, 0, 1, 1, 2, 3, 4];
from_bytes::<Vec<u32>>(buf, vec![0x0102_0304]);
}
#[test]
fn test_parse_list_3() {
let buf: &[u8] = &[0, 0, 0, 3, 1, 2, 3, 4, 1, 3, 3, 7, 0, 0, 4, 2];
from_bytes::<Vec<u32>>(buf, vec![0x0102_0304, 0x0103_0307, 0x402]);
}
#[test]
fn test_parse_list_list_3() {
let buf: &[u8] = &[
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,
];
from_bytes::<Vec<Vec<u32>>>(buf, vec![vec![0x0102_0304], vec![0x0103_0307], vec![0x402]]);
}
#[test]
fn test_parse_list_empty() {
let buf: &[u8] = &[0, 0, 0, 3];
from_bytes::<Vec<()>>(buf, vec![(), (), ()]);
}
#[test]
fn test_parse_long_list() {
let buf: &[u8] = &[0xff, 0xff, 0xff, 0xff, 0, 0, 0];
from_bytes_fail::<Vec<u32>>(buf, Error::EndOfBuffer);
}
#[test]
fn test_parse_tuple() {
let buf: &[u8] = &[0, 0, 0, 3, 42, 0xff];
from_bytes::<(u32, u8, i8)>(buf, (3, 42, -1));
}
#[test]
fn test_parse_nested_tuple() {
let buf: &[u8] = &[0, 0, 0, 3, 42, 43, 44, 0xff, 0xff, 0xff, 0xff];
from_bytes::<(u32, (u8, u8, u8), i32)>(buf, (3, (42, 43, 44), -1));
}
#[test]
fn test_parse_optional_clear() {
let buf: &[u8] = &[0];
from_bytes::<Option<u32>>(buf, None);
}
#[test]
fn test_parse_optional_zero() {
let buf: &[u8] = &[1, 0];
from_bytes::<Option<u8>>(buf, Some(0));
}
#[test]
fn test_parse_optional_u32() {
let buf: &[u8] = &[1, 0, 0, 0x13, 0x37];
from_bytes::<Option<u32>>(buf, Some(0x1337));
}
#[test]
fn test_parse_optional_str() {
let buf: &[u8] = &[1, 0, 0, 0, 3, b'f', b'o', b'o'];
from_bytes::<Option<String>>(buf, Some("foo".to_string()));
}
#[test]
fn test_parse_invalid_optional() {
let buf: &[u8] = &[2, 0, 0, 0, 0];
from_bytes_fail::<Option<u32>>(buf, Error::InvalidOptional);
}
#[test]
fn test_parse_true() {
let buf: &[u8] = &[1];
from_bytes::<bool>(buf, true);
}
#[test]
fn test_parse_false() {
let buf: &[u8] = &[0];
from_bytes::<bool>(buf, false);
}
#[test]
fn test_parse_invalid_bool() {
let buf: &[u8] = &[2];
from_bytes_fail::<bool>(buf, Error::InvalidBool);
}
#[test]
fn test_parse_str() {
let buf: &[u8] = &[0, 0, 0, 3, b'f', b'o', b'o'];
from_bytes::<String>(buf, "foo".to_string());
}
#[test]
fn test_parse_invalid_utf8_str() {
let buf: &[u8] = &[
0, 0, 0, 11, 195, 165, 195, 0, 164, 195, 182, 195, 188, 195, 174,
];
from_bytes_fail::<String>(buf, Error::InvalidString);
}
#[test]
fn test_parse_empty_str() {
let buf: &[u8] = &[0, 0, 0, 0];
from_bytes::<String>(buf, String::new());
}
#[test]
fn test_parse_truncated_str() {
let buf: &[u8] = &[0, 0, 0, 10, b'f', b'o', b'o'];
from_bytes_fail::<String>(buf, Error::EndOfBuffer);
}
#[cfg(test)]
use chia_streamable_macro::Streamable;
#[cfg(test)]
#[derive(Streamable, PartialEq, Debug)]
struct TestStruct {
a: Vec<i8>,
b: String,
c: (u32, u32),
}
#[test]
fn test_parse_struct() {
let buf: &[u8] = &[
0, 0, 0, 2, 42, 0xff, 0, 0, 0, 3, b'b', b'a', b'z', 0xff, 0xff, 0xff, 0xff, 0, 0, 0x13,
0x37,
];
from_bytes::<TestStruct>(
buf,
TestStruct {
a: vec![42_i8, -1],
b: "baz".to_string(),
c: (0xffff_ffff, 0x1337),
},
);
}
#[cfg(test)]
#[derive(Streamable, PartialEq, Debug)]
struct TestTuple(String, u32);
#[test]
fn test_parse_custom_tuple() {
let buf: &[u8] = &[0, 0, 0, 3, b'b', b'a', b'z', 0, 0, 0, 42];
from_bytes::<TestTuple>(buf, TestTuple("baz".to_string(), 42));
}
#[cfg(test)]
fn stream<T: Streamable>(v: &T) -> Vec<u8> {
let mut buf = Vec::<u8>::new();
v.stream(&mut buf).unwrap();
let mut ctx1 = Sha256::new();
let mut ctx2 = Sha256::new();
v.update_digest(&mut ctx1);
ctx2.update(&buf);
assert_eq!(&ctx1.finalize(), &ctx2.finalize());
buf
}
#[test]
fn test_stream_i32() {
let b: i32 = 0x0102_0304;
let buf = stream(&b);
assert_eq!(&buf[..], [1, 2, 3, 4]);
}
#[test]
fn test_stream_sequence() {
let b: Vec<u8> = vec![1, 2, 3, 4, 5, 42, 127];
let buf = stream(&b);
assert_eq!(&buf[..], [0, 0, 0, 7, 1, 2, 3, 4, 5, 42, 127]);
}
#[test]
fn test_stream_empty_sequence() {
let b: Vec<u8> = vec![];
let buf = stream(&b);
assert_eq!(&buf[..], [0, 0, 0, 0]);
}
#[test]
fn test_stream_none() {
let b: Option<u8> = None;
let buf = stream(&b);
assert_eq!(&buf[..], [0]);
}
#[test]
fn test_stream_optional() {
let b: Option<u32> = Some(0x1337);
let buf = stream(&b);
assert_eq!(&buf[..], [1, 0, 0, 0x13, 0x37]);
}
#[test]
fn test_stream_optional_zero() {
let b: Option<u32> = Some(0);
let buf = stream(&b);
assert_eq!(&buf[..], [1, 0, 0, 0, 0]);
}
#[test]
fn test_stream_optional_set1() {
let out = stream(&Some(42_u32));
assert_eq!(&out, &[1, 0, 0, 0, 42]);
}
#[test]
fn test_stream_optional_set2() {
let out = stream(&Some("foobar".to_string()));
assert_eq!(&out, &[1, 0, 0, 0, 6, b'f', b'o', b'o', b'b', b'a', b'r']);
}
#[test]
fn test_stream_tuple() {
let b: (u8, u32, u64, bool) = (42, 0x1337, 0x0102_0304_0506_0708, true);
let buf = stream(&b);
assert_eq!(&buf[..], [42, 0, 0, 0x13, 0x37, 1, 2, 3, 4, 5, 6, 7, 8, 1]);
}
#[test]
fn test_stream_tuple_of_lists() {
let b: (Vec<u8>, Vec<u8>) = (vec![0, 1, 2, 3], vec![4, 5, 6, 7, 8, 9]);
let buf = stream(&b);
assert_eq!(
&buf[..],
[0, 0, 0, 4, 0, 1, 2, 3, 0, 0, 0, 6, 4, 5, 6, 7, 8, 9]
);
}
#[test]
fn test_stream_tuple1() {
let out = stream(&(42_u32));
assert_eq!(&out, &[0, 0, 0, 42]);
}
#[test]
fn test_stream_tuple2() {
let out = stream(&("test".to_string(), 42_u32));
assert_eq!(&out, &[0, 0, 0, 4, b't', b'e', b's', b't', 0, 0, 0, 42]);
}
#[test]
fn test_stream_tuple_of_tuples() {
let out = stream(&((0x1337_u32, 42_u32), ("foo".to_string(), "bar".to_string())));
assert_eq!(
&out,
&[
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',
b'r'
]
);
}
#[test]
fn test_stream_false() {
let b = false;
let buf = stream(&b);
assert_eq!(&buf[..], [0]);
}
#[test]
fn test_stream_true() {
let b = true;
let buf = stream(&b);
assert_eq!(&buf[..], [1]);
}
#[test]
fn test_stream_string() {
let b = "abc".to_string();
let buf = stream(&b);
assert_eq!(&buf[..], [0, 0, 0, 3, b'a', b'b', b'c']);
}
#[test]
fn test_stream_empty_string() {
let b = String::new();
let buf = stream(&b);
assert_eq!(&buf[..], [0, 0, 0, 0]);
}
#[test]
fn test_stream_utf8_string() {
let b = "åäöüî".to_string();
let buf = stream(&b);
assert_eq!(
&buf[..],
[0, 0, 0, 10, 195, 165, 195, 164, 195, 182, 195, 188, 195, 174]
);
}
#[test]
fn test_stream_struct() {
let b = TestStruct {
a: [1, 2, 3].to_vec(),
b: "abc".to_string(),
c: (0x1337, 42),
};
let buf = stream(&b);
assert_eq!(
&buf[..],
[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]
);
}
#[test]
fn test_stream_custom_tuple() {
let b = TestTuple("abc".to_string(), 1337);
let buf = stream(&b);
assert_eq!(&buf[..], [0, 0, 0, 3, b'a', b'b', b'c', 0, 0, 0x05, 0x39]);
}
#[test]
fn test_stream_list() {
let out = stream(&vec![0x0103_0307_u32, 42, 0xffff_ffff]);
assert_eq!(
&out,
&[0, 0, 0, 3, 1, 3, 3, 7, 0, 0, 0, 42, 0xff, 0xff, 0xff, 0xff]
);
}
#[test]
fn test_stream_list_of_empty() {
let out = stream(&vec![(), (), ()]);
assert_eq!(&out, &[0, 0, 0, 3]);
}
#[test]
fn test_stream_list_list() {
let out = stream(&vec![
vec![0x0103_0307_u32],
vec![42_u32],
vec![0xffff_ffff_u32],
]);
assert_eq!(
&out,
&[
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,
0xff, 0xff
]
);
}
#[test]
fn test_stream_u128() {
let out = stream(&(1337_u128, -1337_i128));
assert_eq!(
&out,
&[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x05, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xc7
]
);
}
#[cfg(test)]
#[derive(Streamable, Hash, Copy, Debug, Clone, Eq, PartialEq)]
enum TestEnum {
A = 0,
B = 1,
C = 255,
}
#[test]
fn test_parse_enum() {
from_bytes::<TestEnum>(&[0], TestEnum::A);
from_bytes::<TestEnum>(&[1], TestEnum::B);
from_bytes::<TestEnum>(&[255], TestEnum::C);
from_bytes_fail::<TestEnum>(&[3], Error::InvalidEnum);
from_bytes_fail::<TestEnum>(&[254], Error::InvalidEnum);
from_bytes_fail::<TestEnum>(&[128], Error::InvalidEnum);
}
#[test]
fn test_stream_enum() {
assert_eq!(stream::<TestEnum>(&TestEnum::A), &[0_u8]);
assert_eq!(stream::<TestEnum>(&TestEnum::B), &[1_u8]);
assert_eq!(stream::<TestEnum>(&TestEnum::C), &[255_u8]);
}