/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerovec-0.11.8/src/ule/plain.rs
Line | Count | Source |
1 | | // This file is part of ICU4X. For terms of use, please see the file |
2 | | // called LICENSE at the top level of the ICU4X source tree |
3 | | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | | |
5 | | #![allow(clippy::upper_case_acronyms)] |
6 | | //! ULE implementation for Plain Old Data types, including all sized integers. |
7 | | |
8 | | use super::*; |
9 | | use crate::impl_ule_from_array; |
10 | | use crate::ZeroSlice; |
11 | | use core::num::{NonZeroI8, NonZeroU8}; |
12 | | |
13 | | /// A u8 array of little-endian data with infallible conversions to and from &[u8]. |
14 | | #[repr(transparent)] |
15 | | #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)] |
16 | | #[allow(clippy::exhaustive_structs)] // newtype |
17 | | pub struct RawBytesULE<const N: usize>(pub [u8; N]); |
18 | | |
19 | | impl<const N: usize> RawBytesULE<N> { |
20 | | #[inline] |
21 | 0 | pub fn as_bytes(&self) -> &[u8] { |
22 | 0 | &self.0 |
23 | 0 | } |
24 | | |
25 | | #[inline] |
26 | 0 | pub fn from_bytes_unchecked_mut(bytes: &mut [u8]) -> &mut [Self] { |
27 | 0 | let data = bytes.as_mut_ptr(); |
28 | 0 | let len = bytes.len() / N; |
29 | | // Safe because Self is transparent over [u8; N] |
30 | 0 | unsafe { slice::from_raw_parts_mut(data as *mut Self, len) } |
31 | 0 | } |
32 | | } |
33 | | |
34 | | // Safety (based on the safety checklist on the ULE trait): |
35 | | // 1. RawBytesULE does not include any uninitialized or padding bytes. |
36 | | // (achieved by `#[repr(transparent)]` on a type that satisfies this invariant) |
37 | | // 2. RawBytesULE is aligned to 1 byte. |
38 | | // (achieved by `#[repr(transparent)]` on a type that satisfies this invariant) |
39 | | // 3. The impl of validate_bytes() returns an error if any byte is not valid (never). |
40 | | // 4. The impl of validate_bytes() returns an error if there are leftover bytes. |
41 | | // 5. The other ULE methods use the default impl. |
42 | | // 6. RawBytesULE byte equality is semantic equality |
43 | | unsafe impl<const N: usize> ULE for RawBytesULE<N> { |
44 | | #[inline] |
45 | 0 | fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> { |
46 | 0 | if bytes.len() % N == 0 { |
47 | | // Safe because Self is transparent over [u8; N] |
48 | 0 | Ok(()) |
49 | | } else { |
50 | 0 | Err(UleError::length::<Self>(bytes.len())) |
51 | | } |
52 | 0 | } Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2> as zerovec::ule::ULE>::validate_bytes Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<_> as zerovec::ule::ULE>::validate_bytes |
53 | | } |
54 | | |
55 | | impl<const N: usize> From<[u8; N]> for RawBytesULE<N> { |
56 | | #[inline] |
57 | 0 | fn from(le_bytes: [u8; N]) -> Self { |
58 | 0 | Self(le_bytes) |
59 | 0 | } |
60 | | } |
61 | | |
62 | | macro_rules! impl_numbers_with_raw_bytes_ule { |
63 | | ($unsigned:ty, $signed:ty $(, $float:ty)?) => { |
64 | | const _: () = assert!(size_of::<$unsigned>() == size_of::<$signed>() $(&& size_of::<$unsigned>() == size_of::<$float>())?); |
65 | | |
66 | | impl RawBytesULE<{ size_of::<$unsigned>() }> { |
67 | | #[doc = concat!("Gets this `RawBytesULE` as a `", stringify!($unsigned), "`. This is equivalent to calling [`AsULE::from_unaligned()`] on [`", stringify!($unsigned), "`].")] |
68 | | #[inline] |
69 | 0 | pub const fn as_unsigned_int(&self) -> $unsigned { |
70 | 0 | <$unsigned>::from_le_bytes(self.0) |
71 | 0 | } Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2>>::as_unsigned_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2>>::as_unsigned_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<16>>::as_unsigned_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4>>::as_unsigned_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8>>::as_unsigned_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2>>::as_unsigned_int |
72 | | |
73 | | #[doc = concat!("Gets this `RawBytesULE` as a `", stringify!($unsigned), "`. This is equivalent to calling [`AsULE::from_unaligned()`] on [`", stringify!($signed), "`].")] |
74 | | #[inline] |
75 | 0 | pub const fn as_signed_int(&self) -> $signed { |
76 | 0 | <$signed>::from_le_bytes(self.0) |
77 | 0 | } Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<16>>::as_signed_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4>>::as_signed_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8>>::as_signed_int Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2>>::as_signed_int |
78 | | |
79 | | $( |
80 | | #[doc = concat!("Gets this `RawBytesULE` as a `", stringify!($float), "`. This is equivalent to calling [`AsULE::from_unaligned()`] on [`", stringify!($float), "`].")] |
81 | | #[inline] |
82 | 0 | pub const fn as_float(&self) -> $float { |
83 | 0 | <$float>::from_le_bytes(self.0) |
84 | 0 | } Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4>>::as_float Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8>>::as_float |
85 | | )? |
86 | | |
87 | | #[doc = concat!("Converts a `", stringify!($unsigned), "` to a `RawBytesULE`. This is equivalent to calling [`AsULE::to_unaligned()`] on [`", stringify!($unsigned), "`].")] |
88 | | #[inline] |
89 | 0 | pub const fn from_aligned(value: $unsigned) -> Self { |
90 | 0 | Self(value.to_le_bytes()) |
91 | 0 | } Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<16>>::from_aligned Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4>>::from_aligned Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8>>::from_aligned Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2>>::from_aligned |
92 | | |
93 | | impl_ule_from_array!( |
94 | | $unsigned, |
95 | | RawBytesULE<{ size_of::<$unsigned>() }>, |
96 | | RawBytesULE([0; { size_of::<$unsigned>() }]) |
97 | | ); |
98 | | } |
99 | | |
100 | | impl_byte_slice_type!(from_unsigned, $unsigned); |
101 | | impl_const_constructors!($unsigned); |
102 | | |
103 | | impl_byte_slice_type!(from_signed, $signed); |
104 | | impl_const_constructors!($signed); |
105 | | |
106 | | $( |
107 | | // These impls are actually safe and portable due to Rust always using IEEE 754, see the documentation |
108 | | // on f32::from_le_bytes: https://doc.rust-lang.org/stable/std/primitive.f32.html#method.from_le_bytes |
109 | | // |
110 | | // The only potential problem is that some older platforms treat signaling NaNs differently. This is |
111 | | // still quite portable, signalingness is not typically super important. |
112 | | |
113 | | // The from_bits documentation mentions that they have identical byte representations to integers |
114 | | // and EqULE only cares about LE systems |
115 | | impl_byte_slice_type!(from_float, $float); |
116 | | impl_const_constructors!($float); |
117 | | )? |
118 | | }; |
119 | | } |
120 | | |
121 | | macro_rules! impl_const_constructors { |
122 | | ($base:ty) => { |
123 | | impl ZeroSlice<$base> { |
124 | | /// This function can be used for constructing [`ZeroVec`](crate::ZeroVec)s in a `const` context, avoiding |
125 | | /// parsing checks. |
126 | | /// |
127 | | /// This cannot be generic over `T` because of current limitations in `const`, but if |
128 | | /// this method is needed in a non-`const` context, check out [`ZeroSlice::parse_bytes()`] |
129 | | /// instead. |
130 | | /// |
131 | | /// See [`ZeroSlice::cast()`] for an example. |
132 | 0 | pub const fn try_from_bytes(bytes: &[u8]) -> Result<&Self, UleError> { |
133 | 0 | let len = bytes.len(); |
134 | | const STRIDE: usize = size_of::<$base>(); |
135 | | #[allow(clippy::modulo_one)] |
136 | 0 | if (if STRIDE <= 1 { len } else { len % STRIDE }) == 0 { |
137 | 0 | Ok(unsafe { Self::from_bytes_unchecked(bytes) }) |
138 | | } else { |
139 | 0 | Err(UleError::InvalidLength { |
140 | 0 | ty: concat!("<const construct: ", stringify!($base), ">"), |
141 | 0 | len, |
142 | 0 | }) |
143 | | } |
144 | 0 | } Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<i64>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<f64>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<u128>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<i128>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<u8>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<bool>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<()>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<i16>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<u32>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<i32>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<f32>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<u64>>::try_from_bytes Unexecuted instantiation: <zerovec::zerovec::slice::ZeroSlice<u16>>::try_from_bytes |
145 | | } |
146 | | }; |
147 | | } |
148 | | |
149 | | macro_rules! impl_byte_slice_type { |
150 | | ($single_fn:ident, $type:ty) => { |
151 | | impl From<$type> for RawBytesULE<{ size_of::<$type>() }> { |
152 | | #[inline] |
153 | 0 | fn from(value: $type) -> Self { |
154 | 0 | Self(value.to_le_bytes()) |
155 | 0 | } Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8> as core::convert::From<f64>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<16> as core::convert::From<u128>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<16> as core::convert::From<i128>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4> as core::convert::From<u32>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4> as core::convert::From<i32>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4> as core::convert::From<f32>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8> as core::convert::From<u64>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8> as core::convert::From<i64>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2> as core::convert::From<u16>>::from Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2> as core::convert::From<i16>>::from |
156 | | } |
157 | | impl AsULE for $type { |
158 | | type ULE = RawBytesULE<{ size_of::<$type>() }>; |
159 | | #[inline] |
160 | 0 | fn to_unaligned(self) -> Self::ULE { |
161 | 0 | RawBytesULE(self.to_le_bytes()) |
162 | 0 | } Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <u32 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <f64 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <u128 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <i128 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <u32 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <i32 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <f32 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <u64 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <i64 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <i16 as zerovec::ule::AsULE>::to_unaligned |
163 | | #[inline] |
164 | 0 | fn from_unaligned(unaligned: Self::ULE) -> Self { |
165 | 0 | <$type>::from_le_bytes(unaligned.0) |
166 | 0 | } Unexecuted instantiation: <u32 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u32 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u32 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <f64 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u128 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <i128 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u32 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <i32 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <f32 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u64 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <i64 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u16 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <i16 as zerovec::ule::AsULE>::from_unaligned |
167 | | } |
168 | | // EqULE is true because $type and RawBytesULE<{ size_of::<$type> }> |
169 | | // have the same byte sequence on little-endian |
170 | | unsafe impl EqULE for $type {} |
171 | | |
172 | | impl RawBytesULE<{ size_of::<$type>() }> { |
173 | 0 | pub const fn $single_fn(v: $type) -> Self { |
174 | 0 | RawBytesULE(v.to_le_bytes()) |
175 | 0 | } Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8>>::from_signed Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8>>::from_float Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<16>>::from_unsigned Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<16>>::from_signed Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2>>::from_signed Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4>>::from_unsigned Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4>>::from_signed Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<4>>::from_float Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<8>>::from_unsigned Unexecuted instantiation: <zerovec::ule::plain::RawBytesULE<2>>::from_unsigned |
176 | | } |
177 | | }; |
178 | | } |
179 | | |
180 | | impl_numbers_with_raw_bytes_ule!(u16, i16); |
181 | | impl_numbers_with_raw_bytes_ule!(u32, i32, f32); |
182 | | impl_numbers_with_raw_bytes_ule!(u64, i64, f64); |
183 | | impl_numbers_with_raw_bytes_ule!(u128, i128); |
184 | | |
185 | | // Safety (based on the safety checklist on the ULE trait): |
186 | | // 1. u8 does not include any uninitialized or padding bytes. |
187 | | // 2. u8 is aligned to 1 byte. |
188 | | // 3. The impl of validate_bytes() returns an error if any byte is not valid (never). |
189 | | // 4. The impl of validate_bytes() returns an error if there are leftover bytes (never). |
190 | | // 5. The other ULE methods use the default impl. |
191 | | // 6. u8 byte equality is semantic equality |
192 | | unsafe impl ULE for u8 { |
193 | | #[inline] |
194 | 0 | fn validate_bytes(_bytes: &[u8]) -> Result<(), UleError> { |
195 | 0 | Ok(()) |
196 | 0 | } Unexecuted instantiation: <u8 as zerovec::ule::ULE>::validate_bytes Unexecuted instantiation: <u8 as zerovec::ule::ULE>::validate_bytes |
197 | | } |
198 | | |
199 | | impl AsULE for u8 { |
200 | | type ULE = Self; |
201 | | #[inline] |
202 | 0 | fn to_unaligned(self) -> Self::ULE { |
203 | 0 | self |
204 | 0 | } Unexecuted instantiation: <u8 as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <u8 as zerovec::ule::AsULE>::to_unaligned |
205 | | #[inline] |
206 | 0 | fn from_unaligned(unaligned: Self::ULE) -> Self { |
207 | 0 | unaligned |
208 | 0 | } Unexecuted instantiation: <u8 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u8 as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <u8 as zerovec::ule::AsULE>::from_unaligned |
209 | | } |
210 | | |
211 | | // EqULE is true because u8 is its own ULE. |
212 | | unsafe impl EqULE for u8 {} |
213 | | |
214 | | impl_const_constructors!(u8); |
215 | | |
216 | | // Safety (based on the safety checklist on the ULE trait): |
217 | | // 1. NonZeroU8 does not include any uninitialized or padding bytes. |
218 | | // 2. NonZeroU8 is aligned to 1 byte. |
219 | | // 3. The impl of validate_bytes() returns an error if any byte is not valid (0x00). |
220 | | // 4. The impl of validate_bytes() returns an error if there are leftover bytes (never). |
221 | | // 5. The other ULE methods use the default impl. |
222 | | // 6. NonZeroU8 byte equality is semantic equality |
223 | | unsafe impl ULE for NonZeroU8 { |
224 | | #[inline] |
225 | 0 | fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> { |
226 | 0 | bytes.iter().try_for_each(|b| { |
227 | 0 | if *b == 0x00 { |
228 | 0 | Err(UleError::parse::<Self>()) |
229 | | } else { |
230 | 0 | Ok(()) |
231 | | } |
232 | 0 | }) |
233 | 0 | } |
234 | | } |
235 | | |
236 | | impl AsULE for NonZeroU8 { |
237 | | type ULE = Self; |
238 | | #[inline] |
239 | 0 | fn to_unaligned(self) -> Self::ULE { |
240 | 0 | self |
241 | 0 | } |
242 | | #[inline] |
243 | 0 | fn from_unaligned(unaligned: Self::ULE) -> Self { |
244 | 0 | unaligned |
245 | 0 | } |
246 | | } |
247 | | |
248 | | unsafe impl EqULE for NonZeroU8 {} |
249 | | |
250 | | impl NicheBytes<1> for NonZeroU8 { |
251 | | const NICHE_BIT_PATTERN: [u8; 1] = [0x00]; |
252 | | } |
253 | | |
254 | | // Safety (based on the safety checklist on the ULE trait): |
255 | | // 1. i8 does not include any uninitialized or padding bytes. |
256 | | // 2. i8 is aligned to 1 byte. |
257 | | // 3. The impl of validate_bytes() returns an error if any byte is not valid (never). |
258 | | // 4. The impl of validate_bytes() returns an error if there are leftover bytes (never). |
259 | | // 5. The other ULE methods use the default impl. |
260 | | // 6. i8 byte equality is semantic equality |
261 | | unsafe impl ULE for i8 { |
262 | | #[inline] |
263 | 0 | fn validate_bytes(_bytes: &[u8]) -> Result<(), UleError> { |
264 | 0 | Ok(()) |
265 | 0 | } |
266 | | } |
267 | | |
268 | | impl AsULE for i8 { |
269 | | type ULE = Self; |
270 | | #[inline] |
271 | 0 | fn to_unaligned(self) -> Self::ULE { |
272 | 0 | self |
273 | 0 | } |
274 | | #[inline] |
275 | 0 | fn from_unaligned(unaligned: Self::ULE) -> Self { |
276 | 0 | unaligned |
277 | 0 | } |
278 | | } |
279 | | |
280 | | // EqULE is true because i8 is its own ULE. |
281 | | unsafe impl EqULE for i8 {} |
282 | | |
283 | | impl AsULE for NonZeroI8 { |
284 | | type ULE = NonZeroU8; |
285 | | #[inline] |
286 | 0 | fn to_unaligned(self) -> Self::ULE { |
287 | | // TODO: use cast_signed at 1.87 MSRV |
288 | | // Safety: .get() is non-zero |
289 | 0 | unsafe { NonZeroU8::new_unchecked(self.get() as u8) } |
290 | 0 | } |
291 | | |
292 | | #[inline] |
293 | 0 | fn from_unaligned(unaligned: Self::ULE) -> Self { |
294 | | // TODO: use cast_unsigned at 1.87 MSRV |
295 | | // Safety: .get() is non-zero |
296 | 0 | unsafe { NonZeroI8::new_unchecked(unaligned.get() as i8) } |
297 | 0 | } |
298 | | } |
299 | | |
300 | | // The bool impl is not as efficient as it could be |
301 | | // We can, in the future, have https://github.com/unicode-org/icu4x/blob/main/utils/zerovec/design_doc.md#bitpacking |
302 | | // for better bitpacking |
303 | | |
304 | | // Safety (based on the safety checklist on the ULE trait): |
305 | | // 1. bool does not include any uninitialized or padding bytes (the remaining 7 bytes in bool are by definition zero) |
306 | | // 2. bool is aligned to 1 byte. |
307 | | // 3. The impl of validate_bytes() returns an error if any byte is not valid (bytes that are not 0 or 1). |
308 | | // 4. The impl of validate_bytes() returns an error if there are leftover bytes (never). |
309 | | // 5. The other ULE methods use the default impl. |
310 | | // 6. bool byte equality is semantic equality |
311 | | unsafe impl ULE for bool { |
312 | | #[inline] |
313 | 0 | fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> { |
314 | 0 | for byte in bytes { |
315 | | // https://doc.rust-lang.org/reference/types/boolean.html |
316 | | // Rust booleans are always size 1, align 1 values with valid bit patterns 0x0 or 0x1 |
317 | 0 | if *byte > 1 { |
318 | 0 | return Err(UleError::parse::<Self>()); |
319 | 0 | } |
320 | | } |
321 | 0 | Ok(()) |
322 | 0 | } |
323 | | } |
324 | | |
325 | | impl AsULE for bool { |
326 | | type ULE = Self; |
327 | | #[inline] |
328 | 0 | fn to_unaligned(self) -> Self::ULE { |
329 | 0 | self |
330 | 0 | } |
331 | | #[inline] |
332 | 0 | fn from_unaligned(unaligned: Self::ULE) -> Self { |
333 | 0 | unaligned |
334 | 0 | } |
335 | | } |
336 | | |
337 | | // EqULE is true because bool is its own ULE. |
338 | | unsafe impl EqULE for bool {} |
339 | | |
340 | | impl_const_constructors!(bool); |
341 | | |
342 | | // Safety (based on the safety checklist on the ULE trait): |
343 | | // 1. () does not include any uninitialized or padding bytes (it has no bytes) |
344 | | // 2. () is a ZST that is safe to construct |
345 | | // 3. The impl of validate_bytes() returns an error if any byte is not valid (any byte). |
346 | | // 4. The impl of validate_bytes() returns an error if there are leftover bytes (always). |
347 | | // 5. The other ULE methods use the default impl. |
348 | | // 6. () byte equality is semantic equality |
349 | | unsafe impl ULE for () { |
350 | | #[inline] |
351 | 0 | fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> { |
352 | 0 | if bytes.is_empty() { |
353 | 0 | Ok(()) |
354 | | } else { |
355 | 0 | Err(UleError::length::<Self>(bytes.len())) |
356 | | } |
357 | 0 | } |
358 | | } |
359 | | |
360 | | impl AsULE for () { |
361 | | type ULE = Self; |
362 | | #[inline] |
363 | 0 | fn to_unaligned(self) -> Self::ULE { |
364 | 0 | self |
365 | 0 | } |
366 | | #[inline] |
367 | 0 | fn from_unaligned(unaligned: Self::ULE) -> Self { |
368 | 0 | unaligned |
369 | 0 | } |
370 | | } |
371 | | |
372 | | // EqULE is true because () is its own ULE. |
373 | | unsafe impl EqULE for () {} |
374 | | |
375 | | impl_const_constructors!(()); |