1#[cfg(feature = "borsh")]
3use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
4use bytemuck::{Pod, Zeroable};
5#[cfg(feature = "serde-traits")]
6use serde::{Deserialize, Serialize};
7
8#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
10#[cfg_attr(feature = "serde-traits", serde(from = "bool", into = "bool"))]
11#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
12#[repr(transparent)]
13pub struct PodBool(pub u8);
14impl PodBool {
15 pub const fn from_bool(b: bool) -> Self {
16 Self(if b { 1 } else { 0 })
17 }
18}
19
20impl From<bool> for PodBool {
21 fn from(b: bool) -> Self {
22 Self::from_bool(b)
23 }
24}
25
26impl From<&bool> for PodBool {
27 fn from(b: &bool) -> Self {
28 Self(if *b { 1 } else { 0 })
29 }
30}
31
32impl From<&PodBool> for bool {
33 fn from(b: &PodBool) -> Self {
34 b.0 != 0
35 }
36}
37
38impl From<PodBool> for bool {
39 fn from(b: PodBool) -> Self {
40 b.0 != 0
41 }
42}
43
44#[macro_export]
50macro_rules! impl_int_conversion {
51 ($P:ty, $I:ty) => {
52 impl $P {
53 pub const fn from_primitive(n: $I) -> Self {
54 Self(n.to_le_bytes())
55 }
56 }
57 impl From<$I> for $P {
58 fn from(n: $I) -> Self {
59 Self::from_primitive(n)
60 }
61 }
62 impl From<$P> for $I {
63 fn from(pod: $P) -> Self {
64 Self::from_le_bytes(pod.0)
65 }
66 }
67 };
68}
69
70#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
72#[cfg_attr(feature = "serde-traits", serde(from = "u16", into = "u16"))]
73#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
74#[repr(transparent)]
75pub struct PodU16(pub [u8; 2]);
76impl_int_conversion!(PodU16, u16);
77
78#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
80#[cfg_attr(feature = "serde-traits", serde(from = "i16", into = "i16"))]
81#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
82#[repr(transparent)]
83pub struct PodI16(pub [u8; 2]);
84impl_int_conversion!(PodI16, i16);
85
86#[cfg_attr(
88 feature = "borsh",
89 derive(BorshDeserialize, BorshSerialize, BorshSchema)
90)]
91#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
92#[cfg_attr(feature = "serde-traits", serde(from = "u32", into = "u32"))]
93#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
94#[repr(transparent)]
95pub struct PodU32(pub [u8; 4]);
96impl_int_conversion!(PodU32, u32);
97
98#[cfg_attr(
100 feature = "borsh",
101 derive(BorshDeserialize, BorshSerialize, BorshSchema)
102)]
103#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
104#[cfg_attr(feature = "serde-traits", serde(from = "u64", into = "u64"))]
105#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
106#[repr(transparent)]
107pub struct PodU64(pub [u8; 8]);
108impl_int_conversion!(PodU64, u64);
109
110#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
112#[cfg_attr(feature = "serde-traits", serde(from = "i64", into = "i64"))]
113#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
114#[repr(transparent)]
115pub struct PodI64([u8; 8]);
116impl_int_conversion!(PodI64, i64);
117
118#[cfg(test)]
119mod tests {
120 use {super::*, crate::bytemuck::pod_from_bytes};
121
122 #[test]
123 fn test_pod_bool() {
124 assert!(pod_from_bytes::<PodBool>(&[]).is_err());
125 assert!(pod_from_bytes::<PodBool>(&[0, 0]).is_err());
126
127 for i in 0..=u8::MAX {
128 assert_eq!(i != 0, bool::from(pod_from_bytes::<PodBool>(&[i]).unwrap()));
129 }
130 }
131
132 #[cfg(feature = "serde-traits")]
133 #[test]
134 fn test_pod_bool_serde() {
135 let pod_false: PodBool = false.into();
136 let pod_true: PodBool = true.into();
137
138 let serialized_false = serde_json::to_string(&pod_false).unwrap();
139 let serialized_true = serde_json::to_string(&pod_true).unwrap();
140 assert_eq!(&serialized_false, "false");
141 assert_eq!(&serialized_true, "true");
142
143 let deserialized_false = serde_json::from_str::<PodBool>(&serialized_false).unwrap();
144 let deserialized_true = serde_json::from_str::<PodBool>(&serialized_true).unwrap();
145 assert_eq!(pod_false, deserialized_false);
146 assert_eq!(pod_true, deserialized_true);
147 }
148
149 #[test]
150 fn test_pod_u16() {
151 assert!(pod_from_bytes::<PodU16>(&[]).is_err());
152 assert_eq!(1u16, u16::from(*pod_from_bytes::<PodU16>(&[1, 0]).unwrap()));
153 }
154
155 #[cfg(feature = "serde-traits")]
156 #[test]
157 fn test_pod_u16_serde() {
158 let pod_u16: PodU16 = u16::MAX.into();
159
160 let serialized = serde_json::to_string(&pod_u16).unwrap();
161 assert_eq!(&serialized, "65535");
162
163 let deserialized = serde_json::from_str::<PodU16>(&serialized).unwrap();
164 assert_eq!(pod_u16, deserialized);
165 }
166
167 #[test]
168 fn test_pod_i16() {
169 assert!(pod_from_bytes::<PodI16>(&[]).is_err());
170 assert_eq!(
171 -1i16,
172 i16::from(*pod_from_bytes::<PodI16>(&[255, 255]).unwrap())
173 );
174 }
175
176 #[cfg(feature = "serde-traits")]
177 #[test]
178 fn test_pod_i16_serde() {
179 let pod_i16: PodI16 = i16::MAX.into();
180
181 println!("pod_i16 {:?}", pod_i16);
182
183 let serialized = serde_json::to_string(&pod_i16).unwrap();
184 assert_eq!(&serialized, "32767");
185
186 let deserialized = serde_json::from_str::<PodI16>(&serialized).unwrap();
187 assert_eq!(pod_i16, deserialized);
188 }
189
190 #[test]
191 fn test_pod_u64() {
192 assert!(pod_from_bytes::<PodU64>(&[]).is_err());
193 assert_eq!(
194 1u64,
195 u64::from(*pod_from_bytes::<PodU64>(&[1, 0, 0, 0, 0, 0, 0, 0]).unwrap())
196 );
197 }
198
199 #[cfg(feature = "serde-traits")]
200 #[test]
201 fn test_pod_u64_serde() {
202 let pod_u64: PodU64 = u64::MAX.into();
203
204 let serialized = serde_json::to_string(&pod_u64).unwrap();
205 assert_eq!(&serialized, "18446744073709551615");
206
207 let deserialized = serde_json::from_str::<PodU64>(&serialized).unwrap();
208 assert_eq!(pod_u64, deserialized);
209 }
210
211 #[test]
212 fn test_pod_i64() {
213 assert!(pod_from_bytes::<PodI64>(&[]).is_err());
214 assert_eq!(
215 -1i64,
216 i64::from(
217 *pod_from_bytes::<PodI64>(&[255, 255, 255, 255, 255, 255, 255, 255]).unwrap()
218 )
219 );
220 }
221
222 #[cfg(feature = "serde-traits")]
223 #[test]
224 fn test_pod_i64_serde() {
225 let pod_i64: PodI64 = i64::MAX.into();
226
227 let serialized = serde_json::to_string(&pod_i64).unwrap();
228 assert_eq!(&serialized, "9223372036854775807");
229
230 let deserialized = serde_json::from_str::<PodI64>(&serialized).unwrap();
231 assert_eq!(pod_i64, deserialized);
232 }
233}