use const_serialize::{deserialize_const, serialize_const, ConstVec, SerializeConst}; use std::mem::MaybeUninit; #[test] fn test_transmute_bytes_to_enum() { #[derive(Clone, Copy, Debug, PartialEq)] #[repr(C, u8)] enum Enum { A { one: u32, two: u16 }, B { one: u8, two: T } = 15, } #[repr(C)] #[derive(Debug, PartialEq)] struct A { one: u32, two: u16, } #[repr(C)] #[derive(Debug, PartialEq)] struct B { one: u8, two: T, } const SIZE: usize = std::mem::size_of::>(); let mut out = [MaybeUninit::uninit(); SIZE]; let discriminate_size = std::mem::size_of::(); let tag_align = 0; let union_alignment = std::mem::align_of::().max(std::mem::align_of::>()); let data_align = (discriminate_size / union_alignment) + union_alignment; let a_one_align = std::mem::offset_of!(A, one); let a_two_align = std::mem::offset_of!(A, two); let b_one_align = std::mem::offset_of!(B, one); let b_two_align = std::mem::offset_of!(B, two); let one = 1234u32; let two = 5678u16; let first = Enum::A { one, two }; for (i, byte) in one.to_le_bytes().iter().enumerate() { out[data_align + i + a_one_align] = MaybeUninit::new(*byte); } for (i, byte) in two.to_le_bytes().iter().enumerate() { out[data_align + i + a_two_align] = MaybeUninit::new(*byte); } out[tag_align] = MaybeUninit::new(0); let out = unsafe { std::mem::transmute_copy::<[MaybeUninit; SIZE], Enum>(&out) }; assert_eq!(out, first); let mut out = [MaybeUninit::uninit(); SIZE]; let one = 123u8; let two = 58u16; let second = Enum::B { one, two }; for (i, byte) in one.to_le_bytes().iter().enumerate() { out[data_align + i + b_one_align] = MaybeUninit::new(*byte); } for (i, byte) in two.to_le_bytes().iter().enumerate() { out[data_align + i + b_two_align] = MaybeUninit::new(*byte); } out[tag_align] = MaybeUninit::new(15); let out = unsafe { std::mem::transmute_copy::<[MaybeUninit; SIZE], Enum>(&out) }; assert_eq!(out, second); } #[test] fn test_serialize_enum() { #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)] #[repr(C, u8)] enum Enum { A { one: u32, two: u16 }, B { one: u8, two: u16 } = 15, } println!("{:#?}", Enum::MEMORY_LAYOUT); let data = Enum::A { one: 0x11111111, two: 0x22, }; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); let data = Enum::B { one: 0x11, two: 0x2233, }; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); } #[test] fn test_serialize_list_of_lopsided_enums() { #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)] #[repr(C, u8)] enum Enum { A, B { one: u8, two: u16 } = 15, } println!("{:#?}", Enum::MEMORY_LAYOUT); let data = [Enum::A, Enum::A]; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!([Enum; 2], buf).unwrap().1, data); let data = [ Enum::B { one: 0x11, two: 0x2233, }, Enum::B { one: 0x12, two: 0x2244, }, ]; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!([Enum; 2], buf).unwrap().1, data); let data = [ Enum::A, Enum::B { one: 0x11, two: 0x2233, }, ]; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!([Enum; 2], buf).unwrap().1, data); let data = [ Enum::B { one: 0x11, two: 0x2233, }, Enum::A, ]; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!([Enum; 2], buf).unwrap().1, data); } #[test] fn test_serialize_u8_enum() { #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)] #[repr(u8)] enum Enum { A, B, } println!("{:#?}", Enum::MEMORY_LAYOUT); let data = Enum::A; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); let data = Enum::B; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); } #[test] fn test_serialize_corrupted_enum() { #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)] #[repr(C, u8)] enum Enum { A { one: u32, two: u16 }, } let data = Enum::A { one: 0x11111111, two: 0x22, }; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); buf = buf.set(0, 2); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf), None); } #[test] fn test_serialize_nested_enum() { #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)] #[repr(C, u8)] enum Enum { A { one: u32, two: u16 }, B { one: u8, two: InnerEnum } = 15, } #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)] #[repr(C, u16)] enum InnerEnum { A(u8), B { one: u64, two: f64 } = 1000, C { one: u32, two: u16 }, } let data = Enum::A { one: 0x11111111, two: 0x22, }; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); let data = Enum::B { one: 0x11, two: InnerEnum::A(0x22), }; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); let data = Enum::B { one: 0x11, two: InnerEnum::B { one: 0x2233, two: 0.123456789, }, }; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); let data = Enum::B { one: 0x11, two: InnerEnum::C { one: 0x2233, two: 56789, }, }; let mut buf = ConstVec::new(); buf = serialize_const(&data, buf); println!("{:?}", buf.as_ref()); let buf = buf.read(); assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data); }