enum.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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_list_of_lopsided_enums() {
  89. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  90. #[repr(C, u8)]
  91. enum Enum {
  92. A,
  93. B { one: u8, two: u16 } = 15,
  94. }
  95. println!("{:#?}", Enum::MEMORY_LAYOUT);
  96. let data = [Enum::A, 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; 2], buf).unwrap().1, data);
  102. let data = [
  103. Enum::B {
  104. one: 0x11,
  105. two: 0x2233,
  106. },
  107. Enum::B {
  108. one: 0x12,
  109. two: 0x2244,
  110. },
  111. ];
  112. let mut buf = ConstVec::new();
  113. buf = serialize_const(&data, buf);
  114. println!("{:?}", buf.as_ref());
  115. let buf = buf.read();
  116. assert_eq!(deserialize_const!([Enum; 2], buf).unwrap().1, data);
  117. let data = [
  118. Enum::A,
  119. Enum::B {
  120. one: 0x11,
  121. two: 0x2233,
  122. },
  123. ];
  124. let mut buf = ConstVec::new();
  125. buf = serialize_const(&data, buf);
  126. println!("{:?}", buf.as_ref());
  127. let buf = buf.read();
  128. assert_eq!(deserialize_const!([Enum; 2], buf).unwrap().1, data);
  129. let data = [
  130. Enum::B {
  131. one: 0x11,
  132. two: 0x2233,
  133. },
  134. Enum::A,
  135. ];
  136. let mut buf = ConstVec::new();
  137. buf = serialize_const(&data, buf);
  138. println!("{:?}", buf.as_ref());
  139. let buf = buf.read();
  140. assert_eq!(deserialize_const!([Enum; 2], buf).unwrap().1, data);
  141. }
  142. #[test]
  143. fn test_serialize_u8_enum() {
  144. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  145. #[repr(u8)]
  146. enum Enum {
  147. A,
  148. B,
  149. }
  150. println!("{:#?}", Enum::MEMORY_LAYOUT);
  151. let data = Enum::A;
  152. let mut buf = ConstVec::new();
  153. buf = serialize_const(&data, buf);
  154. println!("{:?}", buf.as_ref());
  155. let buf = buf.read();
  156. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  157. let data = Enum::B;
  158. let mut buf = ConstVec::new();
  159. buf = serialize_const(&data, buf);
  160. println!("{:?}", buf.as_ref());
  161. let buf = buf.read();
  162. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  163. }
  164. #[test]
  165. fn test_serialize_corrupted_enum() {
  166. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  167. #[repr(C, u8)]
  168. enum Enum {
  169. A { one: u32, two: u16 },
  170. }
  171. let data = Enum::A {
  172. one: 0x11111111,
  173. two: 0x22,
  174. };
  175. let mut buf = ConstVec::new();
  176. buf = serialize_const(&data, buf);
  177. buf = buf.set(0, 2);
  178. println!("{:?}", buf.as_ref());
  179. let buf = buf.read();
  180. assert_eq!(deserialize_const!(Enum, buf), None);
  181. }
  182. #[test]
  183. fn test_serialize_nested_enum() {
  184. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  185. #[repr(C, u8)]
  186. enum Enum {
  187. A { one: u32, two: u16 },
  188. B { one: u8, two: InnerEnum } = 15,
  189. }
  190. #[derive(Clone, Copy, Debug, PartialEq, SerializeConst)]
  191. #[repr(C, u16)]
  192. enum InnerEnum {
  193. A(u8),
  194. B { one: u64, two: f64 } = 1000,
  195. C { one: u32, two: u16 },
  196. }
  197. let data = Enum::A {
  198. one: 0x11111111,
  199. two: 0x22,
  200. };
  201. let mut buf = ConstVec::new();
  202. buf = serialize_const(&data, buf);
  203. println!("{:?}", buf.as_ref());
  204. let buf = buf.read();
  205. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  206. let data = Enum::B {
  207. one: 0x11,
  208. two: InnerEnum::A(0x22),
  209. };
  210. let mut buf = ConstVec::new();
  211. buf = serialize_const(&data, buf);
  212. println!("{:?}", buf.as_ref());
  213. let buf = buf.read();
  214. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  215. let data = Enum::B {
  216. one: 0x11,
  217. two: InnerEnum::B {
  218. one: 0x2233,
  219. two: 0.123456789,
  220. },
  221. };
  222. let mut buf = ConstVec::new();
  223. buf = serialize_const(&data, buf);
  224. println!("{:?}", buf.as_ref());
  225. let buf = buf.read();
  226. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  227. let data = Enum::B {
  228. one: 0x11,
  229. two: InnerEnum::C {
  230. one: 0x2233,
  231. two: 56789,
  232. },
  233. };
  234. let mut buf = ConstVec::new();
  235. buf = serialize_const(&data, buf);
  236. println!("{:?}", buf.as_ref());
  237. let buf = buf.read();
  238. assert_eq!(deserialize_const!(Enum, buf).unwrap().1, data);
  239. }