enum.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. use const_serialize::{deserialize_const, serialize_const, ConstVec, SerializeConst};
  2. use std::mem::MaybeUninit;
  3. #[test]
  4. fn test_transmute_bytes_to_enum() {
  5. #[derive(Clone, Copy, Debug, PartialEq)]
  6. #[repr(C, u8)]
  7. enum Enum<T> {
  8. A { one: u32, two: u16 },
  9. B { one: u8, two: T } = 15,
  10. }
  11. #[repr(C)]
  12. #[derive(Debug, PartialEq)]
  13. struct A {
  14. one: u32,
  15. two: u16,
  16. }
  17. #[repr(C)]
  18. #[derive(Debug, PartialEq)]
  19. struct B<T> {
  20. one: u8,
  21. two: T,
  22. }
  23. const SIZE: usize = std::mem::size_of::<Enum<u16>>();
  24. let mut out = [MaybeUninit::uninit(); SIZE];
  25. let discriminate_size = std::mem::size_of::<u8>();
  26. let tag_align = 0;
  27. let union_alignment = std::mem::align_of::<A>().max(std::mem::align_of::<B<u16>>());
  28. let data_align = (discriminate_size / union_alignment) + union_alignment;
  29. let a_one_align = std::mem::offset_of!(A, one);
  30. let a_two_align = std::mem::offset_of!(A, two);
  31. let b_one_align = std::mem::offset_of!(B<u16>, one);
  32. let b_two_align = std::mem::offset_of!(B<u16>, two);
  33. let one = 1234u32;
  34. let two = 5678u16;
  35. let first = Enum::A { one, two };
  36. for (i, byte) in one.to_le_bytes().iter().enumerate() {
  37. out[data_align + i + a_one_align] = MaybeUninit::new(*byte);
  38. }
  39. for (i, byte) in two.to_le_bytes().iter().enumerate() {
  40. out[data_align + i + a_two_align] = MaybeUninit::new(*byte);
  41. }
  42. out[tag_align] = MaybeUninit::new(0);
  43. let out = unsafe { std::mem::transmute_copy::<[MaybeUninit<u8>; SIZE], Enum<u16>>(&out) };
  44. assert_eq!(out, first);
  45. let mut out = [MaybeUninit::uninit(); SIZE];
  46. let one = 123u8;
  47. let two = 58u16;
  48. let second = Enum::B { one, two };
  49. for (i, byte) in one.to_le_bytes().iter().enumerate() {
  50. out[data_align + i + b_one_align] = MaybeUninit::new(*byte);
  51. }
  52. for (i, byte) in two.to_le_bytes().iter().enumerate() {
  53. out[data_align + i + b_two_align] = MaybeUninit::new(*byte);
  54. }
  55. out[tag_align] = MaybeUninit::new(15);
  56. let out = unsafe { std::mem::transmute_copy::<[MaybeUninit<u8>; SIZE], Enum<u16>>(&out) };
  57. assert_eq!(out, second);
  58. }
  59. #[test]
  60. fn test_serialize_enum() {
  61. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  62. #[repr(C, u8)]
  63. enum Enum {
  64. A { one: u32, two: u16 },
  65. B { one: u8, two: u16 } = 15,
  66. }
  67. println!("{:#?}", Enum::MEMORY_LAYOUT);
  68. let data = Enum::A {
  69. one: 0x11111111,
  70. two: 0x22,
  71. };
  72. let mut buf = ConstVec::new();
  73. buf = serialize_const(&data, buf);
  74. println!("{:?}", buf.as_ref());
  75. let buf = buf.read();
  76. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  77. let data = Enum::B {
  78. one: 0x11,
  79. two: 0x2233,
  80. };
  81. let mut buf = ConstVec::new();
  82. buf = serialize_const(&data, buf);
  83. println!("{:?}", buf.as_ref());
  84. let buf = buf.read();
  85. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  86. }
  87. #[test]
  88. fn test_serialize_u8_enum() {
  89. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  90. #[repr(u8)]
  91. enum Enum {
  92. A,
  93. B,
  94. }
  95. println!("{:#?}", Enum::MEMORY_LAYOUT);
  96. let data = Enum::A;
  97. let mut buf = ConstVec::new();
  98. buf = serialize_const(&data, buf);
  99. println!("{:?}", buf.as_ref());
  100. let buf = buf.read();
  101. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  102. let data = Enum::B;
  103. let mut buf = ConstVec::new();
  104. buf = serialize_const(&data, buf);
  105. println!("{:?}", buf.as_ref());
  106. let buf = buf.read();
  107. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  108. }
  109. #[test]
  110. fn test_serialize_corrupted_enum() {
  111. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  112. #[repr(C, u8)]
  113. enum Enum {
  114. A { one: u32, two: u16 },
  115. }
  116. let data = Enum::A {
  117. one: 0x11111111,
  118. two: 0x22,
  119. };
  120. let mut buf = ConstVec::new();
  121. buf = serialize_const(&data, buf);
  122. buf = buf.set(0, 2);
  123. println!("{:?}", buf.as_ref());
  124. let buf = buf.read();
  125. assert_eq!(deserialize_const!(Enum, buf), None);
  126. }
  127. #[test]
  128. fn test_serialize_nested_enum() {
  129. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  130. #[repr(C, u8)]
  131. enum Enum {
  132. A { one: u32, two: u16 },
  133. B { one: u8, two: InnerEnum } = 15,
  134. }
  135. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  136. #[repr(C, u16)]
  137. enum InnerEnum {
  138. A(u8),
  139. B { one: u64, two: f64 } = 1000,
  140. C { one: u32, two: u16 },
  141. }
  142. let data = Enum::A {
  143. one: 0x11111111,
  144. two: 0x22,
  145. };
  146. let mut buf = ConstVec::new();
  147. buf = serialize_const(&data, buf);
  148. println!("{:?}", buf.as_ref());
  149. let buf = buf.read();
  150. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  151. let data = Enum::B {
  152. one: 0x11,
  153. two: InnerEnum::A(0x22),
  154. };
  155. let mut buf = ConstVec::new();
  156. buf = serialize_const(&data, buf);
  157. println!("{:?}", buf.as_ref());
  158. let buf = buf.read();
  159. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  160. let data = Enum::B {
  161. one: 0x11,
  162. two: InnerEnum::B {
  163. one: 0x2233,
  164. two: 0.123456789,
  165. },
  166. };
  167. let mut buf = ConstVec::new();
  168. buf = serialize_const(&data, buf);
  169. println!("{:?}", buf.as_ref());
  170. let buf = buf.read();
  171. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  172. let data = Enum::B {
  173. one: 0x11,
  174. two: InnerEnum::C {
  175. one: 0x2233,
  176. two: 56789,
  177. },
  178. };
  179. let mut buf = ConstVec::new();
  180. buf = serialize_const(&data, buf);
  181. println!("{:?}", buf.as_ref());
  182. let buf = buf.read();
  183. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  184. }