/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerocopy-0.8.55/src/error.rs
Line | Count | Source |
1 | | // SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0 OR MIT |
2 | | // |
3 | | // Copyright 2024 The Fuchsia Authors |
4 | | // |
5 | | // Licensed under the 2-Clause BSD License <LICENSE-BSD or |
6 | | // https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0 |
7 | | // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT |
8 | | // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. |
9 | | // This file may not be copied, modified, or distributed except according to |
10 | | // those terms. |
11 | | |
12 | | //! Types related to error reporting. |
13 | | //! |
14 | | //! ## Single failure mode errors |
15 | | //! |
16 | | //! Generally speaking, zerocopy's conversions may fail for one of up to three |
17 | | //! reasons: |
18 | | //! - [`AlignmentError`]: the conversion source was improperly aligned |
19 | | //! - [`SizeError`]: the conversion source was of incorrect size |
20 | | //! - [`ValidityError`]: the conversion source contained invalid data |
21 | | //! |
22 | | //! Methods that only have one failure mode, like |
23 | | //! [`FromBytes::read_from_bytes`], return that mode's corresponding error type |
24 | | //! directly. |
25 | | //! |
26 | | //! ## Compound errors |
27 | | //! |
28 | | //! Conversion methods that have either two or three possible failure modes |
29 | | //! return one of these error types: |
30 | | //! - [`CastError`]: the error type of reference conversions |
31 | | //! - [`TryCastError`]: the error type of fallible reference conversions |
32 | | //! - [`TryReadError`]: the error type of fallible read conversions |
33 | | //! |
34 | | //! ## [`Unaligned`] destination types |
35 | | //! |
36 | | //! For [`Unaligned`] destination types, alignment errors are impossible. All |
37 | | //! compound error types support infallibly discarding the alignment error via |
38 | | //! [`From`] so long as `Dst: Unaligned`. For example, see [`<SizeError as |
39 | | //! From<ConvertError>>::from`][size-error-from]. |
40 | | //! |
41 | | //! [size-error-from]: struct.SizeError.html#method.from-1 |
42 | | //! |
43 | | //! ## Accessing the conversion source |
44 | | //! |
45 | | //! All error types provide an `into_src` method that converts the error into |
46 | | //! the source value underlying the failed conversion. |
47 | | //! |
48 | | //! ## Display formatting |
49 | | //! |
50 | | //! All error types provide a `Display` implementation that produces a |
51 | | //! human-readable error message. When `debug_assertions` are enabled, these |
52 | | //! error messages are verbose and may include potentially sensitive |
53 | | //! information, including: |
54 | | //! |
55 | | //! - the names of the involved types |
56 | | //! - the sizes of the involved types |
57 | | //! - the addresses of the involved types |
58 | | //! - the contents of the involved types |
59 | | //! |
60 | | //! When `debug_assertions` are disabled (as is default for `release` builds), |
61 | | //! such potentially sensitive information is excluded. |
62 | | //! |
63 | | //! In the future, we may support manually configuring this behavior. If you are |
64 | | //! interested in this feature, [let us know on GitHub][issue-1457] so we know |
65 | | //! to prioritize it. |
66 | | //! |
67 | | //! [issue-1457]: https://github.com/google/zerocopy/issues/1457 |
68 | | //! |
69 | | //! ## Validation order |
70 | | //! |
71 | | //! Our conversion methods typically check alignment, then size, then bit |
72 | | //! validity. However, we do not guarantee that this is always the case, and |
73 | | //! this behavior may change between releases. |
74 | | //! |
75 | | //! ## `Send`, `Sync`, and `'static` |
76 | | //! |
77 | | //! Our error types are `Send`, `Sync`, and `'static` when their `Src` parameter |
78 | | //! is `Send`, `Sync`, or `'static`, respectively. This can cause issues when an |
79 | | //! error is sent or synchronized across threads; e.g.: |
80 | | //! |
81 | | //! ```compile_fail,E0515 |
82 | | //! use zerocopy::*; |
83 | | //! |
84 | | //! let result: SizeError<&[u8], u32> = std::thread::spawn(|| { |
85 | | //! let source = &mut [0u8, 1, 2][..]; |
86 | | //! // Try (and fail) to read a `u32` from `source`. |
87 | | //! u32::read_from_bytes(source).unwrap_err() |
88 | | //! }).join().unwrap(); |
89 | | //! ``` |
90 | | //! |
91 | | //! To work around this, use [`map_src`][CastError::map_src] to convert the |
92 | | //! source parameter to an unproblematic type; e.g.: |
93 | | //! |
94 | | //! ``` |
95 | | //! use zerocopy::*; |
96 | | //! |
97 | | //! let result: SizeError<(), u32> = std::thread::spawn(|| { |
98 | | //! let source = &mut [0u8, 1, 2][..]; |
99 | | //! // Try (and fail) to read a `u32` from `source`. |
100 | | //! u32::read_from_bytes(source).unwrap_err() |
101 | | //! // Erase the error source. |
102 | | //! .map_src(drop) |
103 | | //! }).join().unwrap(); |
104 | | //! ``` |
105 | | //! |
106 | | //! Alternatively, use `.to_string()` to eagerly convert the error into a |
107 | | //! human-readable message; e.g.: |
108 | | //! |
109 | | //! ``` |
110 | | //! use zerocopy::*; |
111 | | //! |
112 | | //! let result: Result<u32, String> = std::thread::spawn(|| { |
113 | | //! let source = &mut [0u8, 1, 2][..]; |
114 | | //! // Try (and fail) to read a `u32` from `source`. |
115 | | //! u32::read_from_bytes(source) |
116 | | //! // Eagerly render the error message. |
117 | | //! .map_err(|err| err.to_string()) |
118 | | //! }).join().unwrap(); |
119 | | //! ``` |
120 | | #[cfg(not(no_zerocopy_core_error_1_81_0))] |
121 | | use core::error::Error; |
122 | | use core::{ |
123 | | convert::Infallible, |
124 | | fmt::{self, Debug, Write}, |
125 | | ops::Deref, |
126 | | }; |
127 | | #[cfg(all(no_zerocopy_core_error_1_81_0, any(feature = "std", test)))] |
128 | | use std::error::Error; |
129 | | |
130 | | use crate::{util::SendSyncPhantomData, KnownLayout, TryFromBytes, Unaligned}; |
131 | | #[cfg(doc)] |
132 | | use crate::{FromBytes, Ref}; |
133 | | |
134 | | /// Zerocopy's generic error type. |
135 | | /// |
136 | | /// Generally speaking, zerocopy's conversions may fail for one of up to three |
137 | | /// reasons: |
138 | | /// - [`AlignmentError`]: the conversion source was improperly aligned |
139 | | /// - [`SizeError`]: the conversion source was of incorrect size |
140 | | /// - [`ValidityError`]: the conversion source contained invalid data |
141 | | /// |
142 | | /// However, not all conversions produce all errors. For instance, |
143 | | /// [`FromBytes::ref_from_bytes`] may fail due to alignment or size issues, but |
144 | | /// not validity issues. This generic error type captures these |
145 | | /// (im)possibilities via parameterization: `A` is parameterized with |
146 | | /// [`AlignmentError`], `S` is parameterized with [`SizeError`], and `V` is |
147 | | /// parameterized with [`Infallible`]. |
148 | | /// |
149 | | /// Zerocopy never uses this type directly in its API. Rather, we provide three |
150 | | /// pre-parameterized aliases: |
151 | | /// - [`CastError`]: the error type of reference conversions |
152 | | /// - [`TryCastError`]: the error type of fallible reference conversions |
153 | | /// - [`TryReadError`]: the error type of fallible read conversions |
154 | | #[derive(PartialEq, Eq, Clone)] |
155 | | pub enum ConvertError<A, S, V> { |
156 | | /// The conversion source was improperly aligned. |
157 | | Alignment(A), |
158 | | /// The conversion source was of incorrect size. |
159 | | Size(S), |
160 | | /// The conversion source contained invalid data. |
161 | | Validity(V), |
162 | | } |
163 | | |
164 | | impl<Src, Dst: ?Sized + Unaligned, S, V> From<ConvertError<AlignmentError<Src, Dst>, S, V>> |
165 | | for ConvertError<Infallible, S, V> |
166 | | { |
167 | | /// Infallibly discards the alignment error from this `ConvertError` since |
168 | | /// `Dst` is unaligned. |
169 | | /// |
170 | | /// Since [`Dst: Unaligned`], it is impossible to encounter an alignment |
171 | | /// error. This method permits discarding that alignment error infallibly |
172 | | /// and replacing it with [`Infallible`]. |
173 | | /// |
174 | | /// [`Dst: Unaligned`]: crate::Unaligned |
175 | | /// |
176 | | /// # Examples |
177 | | /// |
178 | | /// ``` |
179 | | /// use core::convert::Infallible; |
180 | | /// use zerocopy::*; |
181 | | /// # use zerocopy_derive::*; |
182 | | /// |
183 | | /// #[derive(TryFromBytes, KnownLayout, Unaligned, Immutable)] |
184 | | /// #[repr(C, packed)] |
185 | | /// struct Bools { |
186 | | /// one: bool, |
187 | | /// two: bool, |
188 | | /// many: [bool], |
189 | | /// } |
190 | | /// |
191 | | /// impl Bools { |
192 | | /// fn parse(bytes: &[u8]) -> Result<&Bools, AlignedTryCastError<&[u8], Bools>> { |
193 | | /// // Since `Bools: Unaligned`, we can infallibly discard |
194 | | /// // the alignment error. |
195 | | /// Bools::try_ref_from_bytes(bytes).map_err(Into::into) |
196 | | /// } |
197 | | /// } |
198 | | /// ``` |
199 | | #[inline] |
200 | | fn from(err: ConvertError<AlignmentError<Src, Dst>, S, V>) -> ConvertError<Infallible, S, V> { |
201 | | match err { |
202 | | ConvertError::Alignment(e) => { |
203 | | #[allow(unreachable_code)] |
204 | | return ConvertError::Alignment(Infallible::from(e)); |
205 | | } |
206 | | ConvertError::Size(e) => ConvertError::Size(e), |
207 | | ConvertError::Validity(e) => ConvertError::Validity(e), |
208 | | } |
209 | | } |
210 | | } |
211 | | |
212 | | impl<A: fmt::Debug, S: fmt::Debug, V: fmt::Debug> fmt::Debug for ConvertError<A, S, V> { |
213 | | #[inline] |
214 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
215 | 0 | match self { |
216 | 0 | Self::Alignment(e) => f.debug_tuple("Alignment").field(e).finish(), |
217 | 0 | Self::Size(e) => f.debug_tuple("Size").field(e).finish(), |
218 | 0 | Self::Validity(e) => f.debug_tuple("Validity").field(e).finish(), |
219 | | } |
220 | 0 | } Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>, core::convert::Infallible> as core::fmt::Debug>::fmt |
221 | | } |
222 | | |
223 | | /// Produces a human-readable error message. |
224 | | /// |
225 | | /// The message differs between debug and release builds. When |
226 | | /// `debug_assertions` are enabled, this message is verbose and includes |
227 | | /// potentially sensitive information. |
228 | | impl<A: fmt::Display, S: fmt::Display, V: fmt::Display> fmt::Display for ConvertError<A, S, V> { |
229 | | #[inline] |
230 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
231 | | match self { |
232 | | Self::Alignment(e) => e.fmt(f), |
233 | | Self::Size(e) => e.fmt(f), |
234 | | Self::Validity(e) => e.fmt(f), |
235 | | } |
236 | | } |
237 | | } |
238 | | |
239 | | #[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))] |
240 | | #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] |
241 | | impl<A, S, V> Error for ConvertError<A, S, V> |
242 | | where |
243 | | A: fmt::Display + fmt::Debug, |
244 | | S: fmt::Display + fmt::Debug, |
245 | | V: fmt::Display + fmt::Debug, |
246 | | { |
247 | | } |
248 | | |
249 | | /// The error emitted if the conversion source is improperly aligned. |
250 | | pub struct AlignmentError<Src, Dst: ?Sized> { |
251 | | /// The source value involved in the conversion. |
252 | | src: Src, |
253 | | /// The inner destination type involved in the conversion. |
254 | | /// |
255 | | /// INVARIANT: An `AlignmentError` may only be constructed if `Dst`'s |
256 | | /// alignment requirement is greater than one. |
257 | | _dst: SendSyncPhantomData<Dst>, |
258 | | } |
259 | | |
260 | | impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> { |
261 | | /// # Safety |
262 | | /// |
263 | | /// The caller must ensure that `Dst`'s alignment requirement is greater |
264 | | /// than one. |
265 | 0 | pub(crate) unsafe fn new_unchecked(src: Src) -> Self { |
266 | | // INVARIANT: The caller guarantees that `Dst`'s alignment requirement |
267 | | // is greater than one. |
268 | 0 | Self { src, _dst: SendSyncPhantomData::default() } |
269 | 0 | } Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::pck::BPCSummaryRecord]>>::new_unchecked Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::spk::summary::SPKSummaryRecord]>>::new_unchecked Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [f64]>>::new_unchecked Unexecuted instantiation: <zerocopy::error::AlignmentError<(), zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>>::new_unchecked Unexecuted instantiation: <zerocopy::error::AlignmentError<(), zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>>::new_unchecked Unexecuted instantiation: <zerocopy::error::AlignmentError<(), zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>>::new_unchecked |
270 | | |
271 | | /// Produces the source underlying the failed conversion. |
272 | | #[inline] |
273 | | pub fn into_src(self) -> Src { |
274 | | self.src |
275 | | } |
276 | | |
277 | 0 | pub(crate) fn with_src<NewSrc>(self, new_src: NewSrc) -> AlignmentError<NewSrc, Dst> { |
278 | | // INVARIANT: `with_src` doesn't change the type of `Dst`, so the |
279 | | // invariant that `Dst`'s alignment requirement is greater than one is |
280 | | // preserved. |
281 | 0 | AlignmentError { src: new_src, _dst: SendSyncPhantomData::default() } |
282 | 0 | } Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::AlignmentError<(), zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::AlignmentError<(), zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::AlignmentError<(), zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::AlignmentError<(), [f64]>>::with_src::<&[u8]> |
283 | | |
284 | | /// Maps the source value associated with the conversion error. |
285 | | /// |
286 | | /// This can help mitigate [issues with `Send`, `Sync` and `'static` |
287 | | /// bounds][self#send-sync-and-static]. |
288 | | /// |
289 | | /// # Examples |
290 | | /// |
291 | | /// ``` |
292 | | /// use zerocopy::*; |
293 | | /// |
294 | | /// let unaligned = Unalign::new(0u16); |
295 | | /// |
296 | | /// // Attempt to deref `unaligned`. This might fail with an alignment error. |
297 | | /// let maybe_n: Result<&u16, AlignmentError<&Unalign<u16>, u16>> = unaligned.try_deref(); |
298 | | /// |
299 | | /// // Map the error's source to its address as a usize. |
300 | | /// let maybe_n: Result<&u16, AlignmentError<usize, u16>> = maybe_n.map_err(|err| { |
301 | | /// err.map_src(|src| src as *const _ as usize) |
302 | | /// }); |
303 | | /// ``` |
304 | | #[inline] |
305 | 0 | pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> AlignmentError<NewSrc, Dst> { |
306 | 0 | AlignmentError { src: f(self.src), _dst: SendSyncPhantomData::default() } |
307 | 0 | } Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::pck::BPCSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::spk::summary::SPKSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [f64]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::pck::BPCSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::spk::summary::SPKSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::AlignmentError<(), [f64]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[f64], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [f64]>, zerocopy::error::SizeError<(), [f64]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}> |
308 | | |
309 | 0 | pub(crate) fn into<S, V>(self) -> ConvertError<Self, S, V> { |
310 | 0 | ConvertError::Alignment(self) |
311 | 0 | } Unexecuted instantiation: <zerocopy::error::AlignmentError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>>::into::<zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>, core::convert::Infallible> Unexecuted instantiation: <zerocopy::error::AlignmentError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>>::into::<zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>, core::convert::Infallible> Unexecuted instantiation: <zerocopy::error::AlignmentError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>>::into::<zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>, core::convert::Infallible> |
312 | | |
313 | | /// Format extra details for a verbose, human-readable error message. |
314 | | /// |
315 | | /// This formatting may include potentially sensitive information. |
316 | | fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result |
317 | | where |
318 | | Src: Deref, |
319 | | Dst: KnownLayout, |
320 | | { |
321 | | #[allow(clippy::as_conversions)] |
322 | | let addr = self.src.deref() as *const _ as *const (); |
323 | | let addr_align = 2usize.pow((crate::util::AsAddress::addr(addr)).trailing_zeros()); |
324 | | |
325 | | f.write_str("\n\nSource type: ")?; |
326 | | f.write_str(core::any::type_name::<Src>())?; |
327 | | |
328 | | f.write_str("\nSource address: ")?; |
329 | | addr.fmt(f)?; |
330 | | f.write_str(" (a multiple of ")?; |
331 | | addr_align.fmt(f)?; |
332 | | f.write_str(")")?; |
333 | | |
334 | | f.write_str("\nDestination type: ")?; |
335 | | f.write_str(core::any::type_name::<Dst>())?; |
336 | | |
337 | | f.write_str("\nDestination alignment: ")?; |
338 | | <Dst as KnownLayout>::LAYOUT.align.get().fmt(f)?; |
339 | | |
340 | | Ok(()) |
341 | | } |
342 | | } |
343 | | |
344 | | impl<Src: Clone, Dst: ?Sized> Clone for AlignmentError<Src, Dst> { |
345 | | #[inline] |
346 | | fn clone(&self) -> Self { |
347 | | Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() } |
348 | | } |
349 | | } |
350 | | |
351 | | impl<Src: PartialEq, Dst: ?Sized> PartialEq for AlignmentError<Src, Dst> { |
352 | | #[inline] |
353 | | fn eq(&self, other: &Self) -> bool { |
354 | | self.src == other.src |
355 | | } |
356 | | } |
357 | | |
358 | | impl<Src: Eq, Dst: ?Sized> Eq for AlignmentError<Src, Dst> {} |
359 | | |
360 | | impl<Src, Dst: ?Sized + Unaligned> From<AlignmentError<Src, Dst>> for Infallible { |
361 | | #[inline(always)] |
362 | | fn from(_: AlignmentError<Src, Dst>) -> Infallible { |
363 | | // SAFETY: `AlignmentError`s can only be constructed when `Dst`'s |
364 | | // alignment requirement is greater than one. In this block, `Dst: |
365 | | // Unaligned`, which means that its alignment requirement is equal to |
366 | | // one. Thus, it's not possible to reach here at runtime. |
367 | | unsafe { core::hint::unreachable_unchecked() } |
368 | | } |
369 | | } |
370 | | |
371 | | #[cfg(test)] |
372 | | impl<Src, Dst> AlignmentError<Src, Dst> { |
373 | | // A convenience constructor so that test code doesn't need to write |
374 | | // `unsafe`. |
375 | | fn new_checked(src: Src) -> AlignmentError<Src, Dst> { |
376 | | assert_ne!(core::mem::align_of::<Dst>(), 1); |
377 | | // SAFETY: The preceding assertion guarantees that `Dst`'s alignment |
378 | | // requirement is greater than one. |
379 | | unsafe { AlignmentError::new_unchecked(src) } |
380 | | } |
381 | | } |
382 | | |
383 | | impl<Src, Dst: ?Sized> fmt::Debug for AlignmentError<Src, Dst> { |
384 | | #[inline] |
385 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
386 | 0 | f.debug_struct("AlignmentError").finish() |
387 | 0 | } Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]> as core::fmt::Debug>::fmt |
388 | | } |
389 | | |
390 | | /// Produces a human-readable error message. |
391 | | /// |
392 | | /// The message differs between debug and release builds. When |
393 | | /// `debug_assertions` are enabled, this message is verbose and includes |
394 | | /// potentially sensitive information. |
395 | | impl<Src, Dst: ?Sized> fmt::Display for AlignmentError<Src, Dst> |
396 | | where |
397 | | Src: Deref, |
398 | | Dst: KnownLayout, |
399 | | { |
400 | | #[inline] |
401 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
402 | | f.write_str("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.")?; |
403 | | |
404 | | if cfg!(debug_assertions) { |
405 | | self.display_verbose_extras(f) |
406 | | } else { |
407 | | Ok(()) |
408 | | } |
409 | | } |
410 | | } |
411 | | |
412 | | #[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))] |
413 | | #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] |
414 | | impl<Src, Dst: ?Sized> Error for AlignmentError<Src, Dst> |
415 | | where |
416 | | Src: Deref, |
417 | | Dst: KnownLayout, |
418 | | { |
419 | | } |
420 | | |
421 | | impl<Src, Dst: ?Sized, S, V> From<AlignmentError<Src, Dst>> |
422 | | for ConvertError<AlignmentError<Src, Dst>, S, V> |
423 | | { |
424 | | #[inline(always)] |
425 | | fn from(err: AlignmentError<Src, Dst>) -> Self { |
426 | | Self::Alignment(err) |
427 | | } |
428 | | } |
429 | | |
430 | | /// The error emitted if the conversion source is of incorrect size. |
431 | | pub struct SizeError<Src, Dst: ?Sized> { |
432 | | /// The source value involved in the conversion. |
433 | | src: Src, |
434 | | /// The inner destination type involved in the conversion. |
435 | | _dst: SendSyncPhantomData<Dst>, |
436 | | } |
437 | | |
438 | | impl<Src, Dst: ?Sized> SizeError<Src, Dst> { |
439 | 0 | pub(crate) fn new(src: Src) -> Self { |
440 | 0 | Self { src, _dst: SendSyncPhantomData::default() } |
441 | 0 | } Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::pck::BPCSummaryRecord]>>::new Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::spk::summary::SPKSummaryRecord]>>::new Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [f64]>>::new Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>>::new Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>>::new Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>>::new Unexecuted instantiation: <zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>>::new Unexecuted instantiation: <zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>>::new Unexecuted instantiation: <zerocopy::error::SizeError<(), [f64]>>::new |
442 | | |
443 | | /// Produces the source underlying the failed conversion. |
444 | | #[inline] |
445 | | pub fn into_src(self) -> Src { |
446 | | self.src |
447 | | } |
448 | | |
449 | | /// Sets the source value associated with the conversion error. |
450 | 0 | pub(crate) fn with_src<NewSrc>(self, new_src: NewSrc) -> SizeError<NewSrc, Dst> { |
451 | 0 | SizeError { src: new_src, _dst: SendSyncPhantomData::default() } |
452 | 0 | } Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::SizeError<(), [f64]>>::with_src::<&[u8]> |
453 | | |
454 | | /// Maps the source value associated with the conversion error. |
455 | | /// |
456 | | /// This can help mitigate [issues with `Send`, `Sync` and `'static` |
457 | | /// bounds][self#send-sync-and-static]. |
458 | | /// |
459 | | /// # Examples |
460 | | /// |
461 | | /// ``` |
462 | | /// use zerocopy::*; |
463 | | /// |
464 | | /// let source: [u8; 3] = [0, 1, 2]; |
465 | | /// |
466 | | /// // Try to read a `u32` from `source`. This will fail because there are insufficient |
467 | | /// // bytes in `source`. |
468 | | /// let maybe_u32: Result<u32, SizeError<&[u8], u32>> = u32::read_from_bytes(&source[..]); |
469 | | /// |
470 | | /// // Map the error's source to its size. |
471 | | /// let maybe_u32: Result<u32, SizeError<usize, u32>> = maybe_u32.map_err(|err| { |
472 | | /// err.map_src(|src| src.len()) |
473 | | /// }); |
474 | | /// ``` |
475 | | #[inline] |
476 | 0 | pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> SizeError<NewSrc, Dst> { |
477 | 0 | SizeError { src: f(self.src), _dst: SendSyncPhantomData::default() } |
478 | 0 | } Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::pck::BPCSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::spk::summary::SPKSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [f64]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::pck::BPCSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::spk::summary::SPKSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::SizeError<(), [f64]>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[f64], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [f64]>, zerocopy::error::SizeError<(), [f64]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}> |
479 | | |
480 | | /// Sets the destination type associated with the conversion error. |
481 | 0 | pub(crate) fn with_dst<NewDst: ?Sized>(self) -> SizeError<Src, NewDst> { |
482 | 0 | SizeError { src: self.src, _dst: SendSyncPhantomData::default() } |
483 | 0 | } Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>>::with_dst::<anise::naif::daf::file_record::FileRecord> Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>>::with_dst::<anise::naif::daf::name_record::NameRecord> Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>>::with_dst::<anise::naif::daf::summary_record::SummaryRecord> |
484 | | |
485 | | /// Converts the error into a general [`ConvertError`]. |
486 | 0 | pub(crate) fn into<A, V>(self) -> ConvertError<A, Self, V> { |
487 | 0 | ConvertError::Size(self) |
488 | 0 | } Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>>::into::<zerocopy::error::AlignmentError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::file_record::FileRecord>>, core::convert::Infallible> Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>>::into::<zerocopy::error::AlignmentError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::name_record::NameRecord>>, core::convert::Infallible> Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>>::into::<zerocopy::error::AlignmentError<&[u8], zerocopy::wrappers::Unalign<anise::naif::daf::summary_record::SummaryRecord>>, core::convert::Infallible> |
489 | | |
490 | | /// Format extra details for a verbose, human-readable error message. |
491 | | /// |
492 | | /// This formatting may include potentially sensitive information. |
493 | | fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result |
494 | | where |
495 | | Src: Deref, |
496 | | Dst: KnownLayout, |
497 | | { |
498 | | // include the source type |
499 | | f.write_str("\nSource type: ")?; |
500 | | f.write_str(core::any::type_name::<Src>())?; |
501 | | |
502 | | // include the source.deref() size |
503 | | let src_size = core::mem::size_of_val(&*self.src); |
504 | | f.write_str("\nSource size: ")?; |
505 | | src_size.fmt(f)?; |
506 | | f.write_str(" byte")?; |
507 | | if src_size != 1 { |
508 | | f.write_char('s')?; |
509 | | } |
510 | | |
511 | | // if `Dst` is `Sized`, include the `Dst` size |
512 | | if let crate::SizeInfo::Sized { size } = Dst::LAYOUT.size_info { |
513 | | f.write_str("\nDestination size: ")?; |
514 | | size.fmt(f)?; |
515 | | f.write_str(" byte")?; |
516 | | if size != 1 { |
517 | | f.write_char('s')?; |
518 | | } |
519 | | } |
520 | | |
521 | | // include the destination type |
522 | | f.write_str("\nDestination type: ")?; |
523 | | f.write_str(core::any::type_name::<Dst>())?; |
524 | | |
525 | | Ok(()) |
526 | | } |
527 | | } |
528 | | |
529 | | impl<Src: Clone, Dst: ?Sized> Clone for SizeError<Src, Dst> { |
530 | | #[inline] |
531 | | fn clone(&self) -> Self { |
532 | | Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() } |
533 | | } |
534 | | } |
535 | | |
536 | | impl<Src: PartialEq, Dst: ?Sized> PartialEq for SizeError<Src, Dst> { |
537 | | #[inline] |
538 | | fn eq(&self, other: &Self) -> bool { |
539 | | self.src == other.src |
540 | | } |
541 | | } |
542 | | |
543 | | impl<Src: Eq, Dst: ?Sized> Eq for SizeError<Src, Dst> {} |
544 | | |
545 | | impl<Src, Dst: ?Sized> fmt::Debug for SizeError<Src, Dst> { |
546 | | #[inline] |
547 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
548 | 0 | f.debug_struct("SizeError").finish() |
549 | 0 | } Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]> as core::fmt::Debug>::fmt Unexecuted instantiation: <zerocopy::error::SizeError<&[u8], anise::naif::daf::file_record::FileRecord> as core::fmt::Debug>::fmt |
550 | | } |
551 | | |
552 | | /// Produces a human-readable error message. |
553 | | /// |
554 | | /// The message differs between debug and release builds. When |
555 | | /// `debug_assertions` are enabled, this message is verbose and includes |
556 | | /// potentially sensitive information. |
557 | | impl<Src, Dst: ?Sized> fmt::Display for SizeError<Src, Dst> |
558 | | where |
559 | | Src: Deref, |
560 | | Dst: KnownLayout, |
561 | | { |
562 | | #[inline] |
563 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
564 | | f.write_str("The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.")?; |
565 | | if cfg!(debug_assertions) { |
566 | | f.write_str("\n")?; |
567 | | self.display_verbose_extras(f)?; |
568 | | } |
569 | | Ok(()) |
570 | | } |
571 | | } |
572 | | |
573 | | #[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))] |
574 | | #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] |
575 | | impl<Src, Dst: ?Sized> Error for SizeError<Src, Dst> |
576 | | where |
577 | | Src: Deref, |
578 | | Dst: KnownLayout, |
579 | | { |
580 | | } |
581 | | |
582 | | impl<Src, Dst: ?Sized, A, V> From<SizeError<Src, Dst>> for ConvertError<A, SizeError<Src, Dst>, V> { |
583 | | #[inline(always)] |
584 | | fn from(err: SizeError<Src, Dst>) -> Self { |
585 | | Self::Size(err) |
586 | | } |
587 | | } |
588 | | |
589 | | /// The error emitted if the conversion source contains invalid data. |
590 | | pub struct ValidityError<Src, Dst: ?Sized + TryFromBytes> { |
591 | | /// The source value involved in the conversion. |
592 | | pub(crate) src: Src, |
593 | | /// The inner destination type involved in the conversion. |
594 | | _dst: SendSyncPhantomData<Dst>, |
595 | | } |
596 | | |
597 | | impl<Src, Dst: ?Sized + TryFromBytes> ValidityError<Src, Dst> { |
598 | | pub(crate) fn new(src: Src) -> Self { |
599 | | Self { src, _dst: SendSyncPhantomData::default() } |
600 | | } |
601 | | |
602 | | /// Produces the source underlying the failed conversion. |
603 | | #[inline] |
604 | | pub fn into_src(self) -> Src { |
605 | | self.src |
606 | | } |
607 | | |
608 | | /// Maps the source value associated with the conversion error. |
609 | | /// |
610 | | /// This can help mitigate [issues with `Send`, `Sync` and `'static` |
611 | | /// bounds][self#send-sync-and-static]. |
612 | | /// |
613 | | /// # Examples |
614 | | /// |
615 | | /// ``` |
616 | | /// use zerocopy::*; |
617 | | /// |
618 | | /// let source: u8 = 42; |
619 | | /// |
620 | | /// // Try to transmute the `source` to a `bool`. This will fail. |
621 | | /// let maybe_bool: Result<bool, ValidityError<u8, bool>> = try_transmute!(source); |
622 | | /// |
623 | | /// // Drop the error's source. |
624 | | /// let maybe_bool: Result<bool, ValidityError<(), bool>> = maybe_bool.map_err(|err| { |
625 | | /// err.map_src(drop) |
626 | | /// }); |
627 | | /// ``` |
628 | | #[inline] |
629 | | pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> ValidityError<NewSrc, Dst> { |
630 | | ValidityError { src: f(self.src), _dst: SendSyncPhantomData::default() } |
631 | | } |
632 | | |
633 | | /// Converts the error into a general [`ConvertError`]. |
634 | | pub(crate) fn into<A, S>(self) -> ConvertError<A, S, Self> { |
635 | | ConvertError::Validity(self) |
636 | | } |
637 | | |
638 | | /// Format extra details for a verbose, human-readable error message. |
639 | | /// |
640 | | /// This formatting may include potentially sensitive information. |
641 | | fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result |
642 | | where |
643 | | Dst: KnownLayout, |
644 | | { |
645 | | f.write_str("Destination type: ")?; |
646 | | f.write_str(core::any::type_name::<Dst>())?; |
647 | | Ok(()) |
648 | | } |
649 | | } |
650 | | |
651 | | impl<Src: Clone, Dst: ?Sized + TryFromBytes> Clone for ValidityError<Src, Dst> { |
652 | | #[inline] |
653 | | fn clone(&self) -> Self { |
654 | | Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() } |
655 | | } |
656 | | } |
657 | | |
658 | | // SAFETY: `ValidityError` contains a single `Self::Inner = Src`, and no other |
659 | | // non-ZST fields. `map` passes ownership of `self`'s sole `Self::Inner` to `f`. |
660 | | unsafe impl<Src, NewSrc, Dst> crate::pointer::TryWithError<NewSrc> |
661 | | for crate::ValidityError<Src, Dst> |
662 | | where |
663 | | Dst: TryFromBytes + ?Sized, |
664 | | { |
665 | | type Inner = Src; |
666 | | type Mapped = crate::ValidityError<NewSrc, Dst>; |
667 | | #[inline] |
668 | | fn map<F: FnOnce(Src) -> NewSrc>(self, f: F) -> Self::Mapped { |
669 | | self.map_src(f) |
670 | | } |
671 | | } |
672 | | |
673 | | impl<Src: PartialEq, Dst: ?Sized + TryFromBytes> PartialEq for ValidityError<Src, Dst> { |
674 | | #[inline] |
675 | | fn eq(&self, other: &Self) -> bool { |
676 | | self.src == other.src |
677 | | } |
678 | | } |
679 | | |
680 | | impl<Src: Eq, Dst: ?Sized + TryFromBytes> Eq for ValidityError<Src, Dst> {} |
681 | | |
682 | | impl<Src, Dst: ?Sized + TryFromBytes> fmt::Debug for ValidityError<Src, Dst> { |
683 | | #[inline] |
684 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
685 | | f.debug_struct("ValidityError").finish() |
686 | | } |
687 | | } |
688 | | |
689 | | /// Produces a human-readable error message. |
690 | | /// |
691 | | /// The message differs between debug and release builds. When |
692 | | /// `debug_assertions` are enabled, this message is verbose and includes |
693 | | /// potentially sensitive information. |
694 | | impl<Src, Dst: ?Sized> fmt::Display for ValidityError<Src, Dst> |
695 | | where |
696 | | Dst: KnownLayout + TryFromBytes, |
697 | | { |
698 | | #[inline] |
699 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
700 | | f.write_str("The conversion failed because the source bytes are not a valid value of the destination type.")?; |
701 | | if cfg!(debug_assertions) { |
702 | | f.write_str("\n\n")?; |
703 | | self.display_verbose_extras(f)?; |
704 | | } |
705 | | Ok(()) |
706 | | } |
707 | | } |
708 | | |
709 | | #[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))] |
710 | | #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))] |
711 | | impl<Src, Dst: ?Sized> Error for ValidityError<Src, Dst> where Dst: KnownLayout + TryFromBytes {} |
712 | | |
713 | | impl<Src, Dst: ?Sized + TryFromBytes, A, S> From<ValidityError<Src, Dst>> |
714 | | for ConvertError<A, S, ValidityError<Src, Dst>> |
715 | | { |
716 | | #[inline(always)] |
717 | | fn from(err: ValidityError<Src, Dst>) -> Self { |
718 | | Self::Validity(err) |
719 | | } |
720 | | } |
721 | | |
722 | | /// The error type of reference conversions. |
723 | | /// |
724 | | /// Reference conversions, like [`FromBytes::ref_from_bytes`] may emit |
725 | | /// [alignment](AlignmentError) and [size](SizeError) errors. |
726 | | // Bounds on generic parameters are not enforced in type aliases, but they do |
727 | | // appear in rustdoc. |
728 | | #[allow(type_alias_bounds)] |
729 | | pub type CastError<Src, Dst: ?Sized> = |
730 | | ConvertError<AlignmentError<Src, Dst>, SizeError<Src, Dst>, Infallible>; |
731 | | |
732 | | impl<Src, Dst: ?Sized> CastError<Src, Dst> { |
733 | | /// Produces the source underlying the failed conversion. |
734 | | #[inline] |
735 | | pub fn into_src(self) -> Src { |
736 | | match self { |
737 | | Self::Alignment(e) => e.src, |
738 | | Self::Size(e) => e.src, |
739 | | Self::Validity(i) => match i {}, |
740 | | } |
741 | | } |
742 | | |
743 | | /// Sets the source value associated with the conversion error. |
744 | 0 | pub(crate) fn with_src<NewSrc>(self, new_src: NewSrc) -> CastError<NewSrc, Dst> { |
745 | 0 | match self { |
746 | 0 | Self::Alignment(e) => CastError::Alignment(e.with_src(new_src)), |
747 | 0 | Self::Size(e) => CastError::Size(e.with_src(new_src)), |
748 | | Self::Validity(i) => match i {}, |
749 | | } |
750 | 0 | } Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>, core::convert::Infallible>>::with_src::<()> Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>>::with_src::<&[u8]> Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [f64]>, zerocopy::error::SizeError<(), [f64]>, core::convert::Infallible>>::with_src::<&[u8]> |
751 | | |
752 | | /// Maps the source value associated with the conversion error. |
753 | | /// |
754 | | /// This can help mitigate [issues with `Send`, `Sync` and `'static` |
755 | | /// bounds][self#send-sync-and-static]. |
756 | | /// |
757 | | /// # Examples |
758 | | /// |
759 | | /// ``` |
760 | | /// use zerocopy::*; |
761 | | /// |
762 | | /// let source: [u8; 3] = [0, 1, 2]; |
763 | | /// |
764 | | /// // Try to read a `u32` from `source`. This will fail because there are insufficient |
765 | | /// // bytes in `source`. |
766 | | /// let maybe_u32: Result<&u32, CastError<&[u8], u32>> = u32::ref_from_bytes(&source[..]); |
767 | | /// |
768 | | /// // Map the error's source to its size and address. |
769 | | /// let maybe_u32: Result<&u32, CastError<(usize, usize), u32>> = maybe_u32.map_err(|err| { |
770 | | /// err.map_src(|src| (src.len(), src.as_ptr() as usize)) |
771 | | /// }); |
772 | | /// ``` |
773 | | #[inline] |
774 | 0 | pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> CastError<NewSrc, Dst> { |
775 | 0 | match self { |
776 | 0 | Self::Alignment(e) => CastError::Alignment(e.map_src(f)), |
777 | 0 | Self::Size(e) => CastError::Size(e.map_src(f)), |
778 | | Self::Validity(i) => match i {}, |
779 | | } |
780 | 0 | } Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>, zerocopy::error::SizeError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, [f64]>, core::convert::Infallible>>::map_src::<(), <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [f64]>, zerocopy::error::SizeError<zerocopy::pointer::inner::_def::PtrInner<[u8]>, [f64]>, core::convert::Infallible>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::pck::BPCSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::spk::summary::SPKSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [f64]>, zerocopy::error::SizeError<(), [f64]>, core::convert::Infallible>>::map_src::<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[f64], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [f64]>, zerocopy::error::SizeError<(), [f64]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}> |
781 | | |
782 | | /// Converts the error into a general [`ConvertError`]. |
783 | | pub(crate) fn into(self) -> TryCastError<Src, Dst> |
784 | | where |
785 | | Dst: TryFromBytes, |
786 | | { |
787 | | match self { |
788 | | Self::Alignment(e) => TryCastError::Alignment(e), |
789 | | Self::Size(e) => TryCastError::Size(e), |
790 | | Self::Validity(i) => match i {}, |
791 | | } |
792 | | } |
793 | | } |
794 | | |
795 | | // SAFETY: `CastError` is either a single `AlignmentError` or a single |
796 | | // `SizeError`. In either case, it contains a single `Self::Inner = Src`, and no |
797 | | // other non-ZST fields. `map` passes ownership of `self`'s sole `Self::Inner` |
798 | | // to `f`. |
799 | | unsafe impl<Src, NewSrc, Dst> crate::pointer::TryWithError<NewSrc> for crate::CastError<Src, Dst> |
800 | | where |
801 | | Dst: ?Sized, |
802 | | { |
803 | | type Inner = Src; |
804 | | type Mapped = crate::CastError<NewSrc, Dst>; |
805 | | |
806 | | #[inline] |
807 | 0 | fn map<F: FnOnce(Src) -> NewSrc>(self, f: F) -> Self::Mapped { |
808 | 0 | self.map_src(f) |
809 | 0 | } Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible> as zerocopy::pointer::ptr::_casts::TryWithError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>>::map::<<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::pck::BPCSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::pck::BPCSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::pck::BPCSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::pck::BPCSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible> as zerocopy::pointer::ptr::_casts::TryWithError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>>::map::<<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[anise::naif::spk::summary::SPKSummaryRecord], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, zerocopy::error::SizeError<(), [anise::naif::spk::summary::SPKSummaryRecord]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[anise::naif::spk::summary::SPKSummaryRecord], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}>Unexecuted instantiation: <zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [f64]>, zerocopy::error::SizeError<(), [f64]>, core::convert::Infallible> as zerocopy::pointer::ptr::_casts::TryWithError<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>>::map::<<zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_with_unchecked<[f64], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Initialized), zerocopy::error::ConvertError<zerocopy::error::AlignmentError<(), [f64]>, zerocopy::error::SizeError<(), [f64]>, core::convert::Infallible>, <zerocopy::pointer::ptr::def::Ptr<[u8], (zerocopy::pointer::invariant::Shared, zerocopy::pointer::invariant::Aligned, zerocopy::pointer::invariant::Valid)>>::try_cast_into_no_leftover<[f64], zerocopy::pointer::invariant::BecauseImmutable>::{closure#0}>::{closure#0}::{closure#0}> |
810 | | } |
811 | | |
812 | | impl<Src, Dst: ?Sized + Unaligned> From<CastError<Src, Dst>> for SizeError<Src, Dst> { |
813 | | /// Infallibly extracts the [`SizeError`] from this `CastError` since `Dst` |
814 | | /// is unaligned. |
815 | | /// |
816 | | /// Since [`Dst: Unaligned`], it is impossible to encounter an alignment |
817 | | /// error, and so the only error that can be encountered at runtime is a |
818 | | /// [`SizeError`]. This method permits extracting that `SizeError` |
819 | | /// infallibly. |
820 | | /// |
821 | | /// [`Dst: Unaligned`]: crate::Unaligned |
822 | | /// |
823 | | /// # Examples |
824 | | /// |
825 | | /// ```rust |
826 | | /// use zerocopy::*; |
827 | | /// # use zerocopy_derive::*; |
828 | | /// |
829 | | /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] |
830 | | /// #[repr(C)] |
831 | | /// struct UdpHeader { |
832 | | /// src_port: [u8; 2], |
833 | | /// dst_port: [u8; 2], |
834 | | /// length: [u8; 2], |
835 | | /// checksum: [u8; 2], |
836 | | /// } |
837 | | /// |
838 | | /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] |
839 | | /// #[repr(C, packed)] |
840 | | /// struct UdpPacket { |
841 | | /// header: UdpHeader, |
842 | | /// body: [u8], |
843 | | /// } |
844 | | /// |
845 | | /// impl UdpPacket { |
846 | | /// pub fn parse(bytes: &[u8]) -> Result<&UdpPacket, SizeError<&[u8], UdpPacket>> { |
847 | | /// // Since `UdpPacket: Unaligned`, we can map the `CastError` to a `SizeError`. |
848 | | /// UdpPacket::ref_from_bytes(bytes).map_err(Into::into) |
849 | | /// } |
850 | | /// } |
851 | | /// ``` |
852 | | #[inline(always)] |
853 | | fn from(err: CastError<Src, Dst>) -> SizeError<Src, Dst> { |
854 | | match err { |
855 | | #[allow(unreachable_code)] |
856 | | CastError::Alignment(e) => match Infallible::from(e) {}, |
857 | | CastError::Size(e) => e, |
858 | | CastError::Validity(i) => match i {}, |
859 | | } |
860 | | } |
861 | | } |
862 | | |
863 | | /// The error type of fallible reference conversions. |
864 | | /// |
865 | | /// Fallible reference conversions, like [`TryFromBytes::try_ref_from_bytes`] |
866 | | /// may emit [alignment](AlignmentError), [size](SizeError), and |
867 | | /// [validity](ValidityError) errors. |
868 | | // Bounds on generic parameters are not enforced in type aliases, but they do |
869 | | // appear in rustdoc. |
870 | | #[allow(type_alias_bounds)] |
871 | | pub type TryCastError<Src, Dst: ?Sized + TryFromBytes> = |
872 | | ConvertError<AlignmentError<Src, Dst>, SizeError<Src, Dst>, ValidityError<Src, Dst>>; |
873 | | |
874 | | // FIXME(#1139): Remove the `TryFromBytes` here and in other downstream |
875 | | // locations (all the way to `ValidityError`) if we determine it's not necessary |
876 | | // for rich validity errors. |
877 | | impl<Src, Dst: ?Sized + TryFromBytes> TryCastError<Src, Dst> { |
878 | | /// Produces the source underlying the failed conversion. |
879 | | #[inline] |
880 | | pub fn into_src(self) -> Src { |
881 | | match self { |
882 | | Self::Alignment(e) => e.src, |
883 | | Self::Size(e) => e.src, |
884 | | Self::Validity(e) => e.src, |
885 | | } |
886 | | } |
887 | | |
888 | | /// Maps the source value associated with the conversion error. |
889 | | /// |
890 | | /// This can help mitigate [issues with `Send`, `Sync` and `'static` |
891 | | /// bounds][self#send-sync-and-static]. |
892 | | /// |
893 | | /// # Examples |
894 | | /// |
895 | | /// ``` |
896 | | /// use core::num::NonZeroU32; |
897 | | /// use zerocopy::*; |
898 | | /// |
899 | | /// let source: [u8; 3] = [0, 0, 0]; |
900 | | /// |
901 | | /// // Try to read a `NonZeroU32` from `source`. |
902 | | /// let maybe_u32: Result<&NonZeroU32, TryCastError<&[u8], NonZeroU32>> |
903 | | /// = NonZeroU32::try_ref_from_bytes(&source[..]); |
904 | | /// |
905 | | /// // Map the error's source to its size and address. |
906 | | /// let maybe_u32: Result<&NonZeroU32, TryCastError<(usize, usize), NonZeroU32>> = |
907 | | /// maybe_u32.map_err(|err| { |
908 | | /// err.map_src(|src| (src.len(), src.as_ptr() as usize)) |
909 | | /// }); |
910 | | /// ``` |
911 | | #[inline] |
912 | | pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> TryCastError<NewSrc, Dst> { |
913 | | match self { |
914 | | Self::Alignment(e) => TryCastError::Alignment(e.map_src(f)), |
915 | | Self::Size(e) => TryCastError::Size(e.map_src(f)), |
916 | | Self::Validity(e) => TryCastError::Validity(e.map_src(f)), |
917 | | } |
918 | | } |
919 | | } |
920 | | |
921 | | impl<Src, Dst: ?Sized + TryFromBytes> From<CastError<Src, Dst>> for TryCastError<Src, Dst> { |
922 | | #[inline] |
923 | | fn from(value: CastError<Src, Dst>) -> Self { |
924 | | match value { |
925 | | CastError::Alignment(e) => Self::Alignment(e), |
926 | | CastError::Size(e) => Self::Size(e), |
927 | | CastError::Validity(i) => match i {}, |
928 | | } |
929 | | } |
930 | | } |
931 | | |
932 | | /// The error type of fallible read-conversions. |
933 | | /// |
934 | | /// Fallible read-conversions, like [`TryFromBytes::try_read_from_bytes`] may |
935 | | /// emit [size](SizeError) and [validity](ValidityError) errors, but not |
936 | | /// alignment errors. |
937 | | // Bounds on generic parameters are not enforced in type aliases, but they do |
938 | | // appear in rustdoc. |
939 | | #[allow(type_alias_bounds)] |
940 | | pub type TryReadError<Src, Dst: ?Sized + TryFromBytes> = |
941 | | ConvertError<Infallible, SizeError<Src, Dst>, ValidityError<Src, Dst>>; |
942 | | |
943 | | impl<Src, Dst: ?Sized + TryFromBytes> TryReadError<Src, Dst> { |
944 | | /// Produces the source underlying the failed conversion. |
945 | | #[inline] |
946 | | pub fn into_src(self) -> Src { |
947 | | match self { |
948 | | Self::Alignment(i) => match i {}, |
949 | | Self::Size(e) => e.src, |
950 | | Self::Validity(e) => e.src, |
951 | | } |
952 | | } |
953 | | |
954 | | /// Maps the source value associated with the conversion error. |
955 | | /// |
956 | | /// This can help mitigate [issues with `Send`, `Sync` and `'static` |
957 | | /// bounds][self#send-sync-and-static]. |
958 | | /// |
959 | | /// # Examples |
960 | | /// |
961 | | /// ``` |
962 | | /// use core::num::NonZeroU32; |
963 | | /// use zerocopy::*; |
964 | | /// |
965 | | /// let source: [u8; 3] = [0, 0, 0]; |
966 | | /// |
967 | | /// // Try to read a `NonZeroU32` from `source`. |
968 | | /// let maybe_u32: Result<NonZeroU32, TryReadError<&[u8], NonZeroU32>> |
969 | | /// = NonZeroU32::try_read_from_bytes(&source[..]); |
970 | | /// |
971 | | /// // Map the error's source to its size. |
972 | | /// let maybe_u32: Result<NonZeroU32, TryReadError<usize, NonZeroU32>> = |
973 | | /// maybe_u32.map_err(|err| { |
974 | | /// err.map_src(|src| src.len()) |
975 | | /// }); |
976 | | /// ``` |
977 | | #[inline] |
978 | | pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> TryReadError<NewSrc, Dst> { |
979 | | match self { |
980 | | Self::Alignment(i) => match i {}, |
981 | | Self::Size(e) => TryReadError::Size(e.map_src(f)), |
982 | | Self::Validity(e) => TryReadError::Validity(e.map_src(f)), |
983 | | } |
984 | | } |
985 | | } |
986 | | |
987 | | /// The error type of well-aligned, fallible casts. |
988 | | /// |
989 | | /// This is like [`TryCastError`], but for casts that are always well-aligned. |
990 | | /// It is identical to `TryCastError`, except that its alignment error is |
991 | | /// [`Infallible`]. |
992 | | /// |
993 | | /// As of this writing, none of zerocopy's API produces this error directly. |
994 | | /// However, it is useful since it permits users to infallibly discard alignment |
995 | | /// errors when they can prove statically that alignment errors are impossible. |
996 | | /// |
997 | | /// # Examples |
998 | | /// |
999 | | /// ``` |
1000 | | /// use core::convert::Infallible; |
1001 | | /// use zerocopy::*; |
1002 | | /// # use zerocopy_derive::*; |
1003 | | /// |
1004 | | /// #[derive(TryFromBytes, KnownLayout, Unaligned, Immutable)] |
1005 | | /// #[repr(C, packed)] |
1006 | | /// struct Bools { |
1007 | | /// one: bool, |
1008 | | /// two: bool, |
1009 | | /// many: [bool], |
1010 | | /// } |
1011 | | /// |
1012 | | /// impl Bools { |
1013 | | /// fn parse(bytes: &[u8]) -> Result<&Bools, AlignedTryCastError<&[u8], Bools>> { |
1014 | | /// // Since `Bools: Unaligned`, we can infallibly discard |
1015 | | /// // the alignment error. |
1016 | | /// Bools::try_ref_from_bytes(bytes).map_err(Into::into) |
1017 | | /// } |
1018 | | /// } |
1019 | | /// ``` |
1020 | | #[allow(type_alias_bounds)] |
1021 | | pub type AlignedTryCastError<Src, Dst: ?Sized + TryFromBytes> = |
1022 | | ConvertError<Infallible, SizeError<Src, Dst>, ValidityError<Src, Dst>>; |
1023 | | |
1024 | | /// The error type of a failed allocation. |
1025 | | /// |
1026 | | /// This type is intended to be deprecated in favor of the standard library's |
1027 | | /// [`AllocError`] type once it is stabilized. When that happens, this type will |
1028 | | /// be replaced by a type alias to the standard library type. We do not intend |
1029 | | /// to treat this as a breaking change; users who wish to avoid breakage should |
1030 | | /// avoid writing code which assumes that this is *not* such an alias. For |
1031 | | /// example, implementing the same trait for both types will result in an impl |
1032 | | /// conflict once this type is an alias. |
1033 | | /// |
1034 | | /// [`AllocError`]: https://doc.rust-lang.org/alloc/alloc/struct.AllocError.html |
1035 | | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
1036 | | pub struct AllocError; |
1037 | | |
1038 | | #[cfg(test)] |
1039 | | mod tests { |
1040 | | use core::convert::Infallible; |
1041 | | |
1042 | | use super::*; |
1043 | | |
1044 | | #[test] |
1045 | | fn test_send_sync() { |
1046 | | // Test that all error types are `Send + Sync` even if `Dst: !Send + |
1047 | | // !Sync`. |
1048 | | |
1049 | | #[allow(dead_code)] |
1050 | | fn is_send_sync<T: Send + Sync>(_t: T) {} |
1051 | | |
1052 | | #[allow(dead_code)] |
1053 | | fn alignment_err_is_send_sync<Src: Send + Sync, Dst>(err: AlignmentError<Src, Dst>) { |
1054 | | is_send_sync(err) |
1055 | | } |
1056 | | |
1057 | | #[allow(dead_code)] |
1058 | | fn size_err_is_send_sync<Src: Send + Sync, Dst>(err: SizeError<Src, Dst>) { |
1059 | | is_send_sync(err) |
1060 | | } |
1061 | | |
1062 | | #[allow(dead_code)] |
1063 | | fn validity_err_is_send_sync<Src: Send + Sync, Dst: TryFromBytes>( |
1064 | | err: ValidityError<Src, Dst>, |
1065 | | ) { |
1066 | | is_send_sync(err) |
1067 | | } |
1068 | | |
1069 | | #[allow(dead_code)] |
1070 | | fn convert_error_is_send_sync<Src: Send + Sync, Dst: TryFromBytes>( |
1071 | | err: ConvertError< |
1072 | | AlignmentError<Src, Dst>, |
1073 | | SizeError<Src, Dst>, |
1074 | | ValidityError<Src, Dst>, |
1075 | | >, |
1076 | | ) { |
1077 | | is_send_sync(err) |
1078 | | } |
1079 | | } |
1080 | | |
1081 | | #[test] |
1082 | | fn test_eq_partial_eq_clone() { |
1083 | | // Test that all error types implement `Eq`, `PartialEq` |
1084 | | // and `Clone` if src does |
1085 | | // even if `Dst: !Eq`, `!PartialEq`, `!Clone`. |
1086 | | |
1087 | | #[allow(dead_code)] |
1088 | | fn is_eq_partial_eq_clone<T: Eq + PartialEq + Clone>(_t: T) {} |
1089 | | |
1090 | | #[allow(dead_code)] |
1091 | | fn alignment_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst>( |
1092 | | err: AlignmentError<Src, Dst>, |
1093 | | ) { |
1094 | | is_eq_partial_eq_clone(err) |
1095 | | } |
1096 | | |
1097 | | #[allow(dead_code)] |
1098 | | fn size_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst>( |
1099 | | err: SizeError<Src, Dst>, |
1100 | | ) { |
1101 | | is_eq_partial_eq_clone(err) |
1102 | | } |
1103 | | |
1104 | | #[allow(dead_code)] |
1105 | | fn validity_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst: TryFromBytes>( |
1106 | | err: ValidityError<Src, Dst>, |
1107 | | ) { |
1108 | | is_eq_partial_eq_clone(err) |
1109 | | } |
1110 | | |
1111 | | #[allow(dead_code)] |
1112 | | fn convert_error_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst: TryFromBytes>( |
1113 | | err: ConvertError< |
1114 | | AlignmentError<Src, Dst>, |
1115 | | SizeError<Src, Dst>, |
1116 | | ValidityError<Src, Dst>, |
1117 | | >, |
1118 | | ) { |
1119 | | is_eq_partial_eq_clone(err) |
1120 | | } |
1121 | | } |
1122 | | |
1123 | | #[test] |
1124 | | fn alignment_display() { |
1125 | | #[repr(C, align(128))] |
1126 | | struct Aligned { |
1127 | | bytes: [u8; 128], |
1128 | | } |
1129 | | |
1130 | | impl_known_layout!(elain::Align::<8>); |
1131 | | |
1132 | | let aligned = Aligned { bytes: [0; 128] }; |
1133 | | |
1134 | | let bytes = &aligned.bytes[1..]; |
1135 | | let addr = crate::util::AsAddress::addr(bytes); |
1136 | | assert_eq!( |
1137 | | AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), |
1138 | | format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ |
1139 | | \nSource type: &[u8]\ |
1140 | | \nSource address: 0x{:x} (a multiple of 1)\ |
1141 | | \nDestination type: elain::Align<8>\ |
1142 | | \nDestination alignment: 8", addr) |
1143 | | ); |
1144 | | |
1145 | | let bytes = &aligned.bytes[2..]; |
1146 | | let addr = crate::util::AsAddress::addr(bytes); |
1147 | | assert_eq!( |
1148 | | AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), |
1149 | | format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ |
1150 | | \nSource type: &[u8]\ |
1151 | | \nSource address: 0x{:x} (a multiple of 2)\ |
1152 | | \nDestination type: elain::Align<8>\ |
1153 | | \nDestination alignment: 8", addr) |
1154 | | ); |
1155 | | |
1156 | | let bytes = &aligned.bytes[3..]; |
1157 | | let addr = crate::util::AsAddress::addr(bytes); |
1158 | | assert_eq!( |
1159 | | AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), |
1160 | | format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ |
1161 | | \nSource type: &[u8]\ |
1162 | | \nSource address: 0x{:x} (a multiple of 1)\ |
1163 | | \nDestination type: elain::Align<8>\ |
1164 | | \nDestination alignment: 8", addr) |
1165 | | ); |
1166 | | |
1167 | | let bytes = &aligned.bytes[4..]; |
1168 | | let addr = crate::util::AsAddress::addr(bytes); |
1169 | | assert_eq!( |
1170 | | AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(), |
1171 | | format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\ |
1172 | | \nSource type: &[u8]\ |
1173 | | \nSource address: 0x{:x} (a multiple of 4)\ |
1174 | | \nDestination type: elain::Align<8>\ |
1175 | | \nDestination alignment: 8", addr) |
1176 | | ); |
1177 | | } |
1178 | | |
1179 | | #[test] |
1180 | | fn size_display() { |
1181 | | assert_eq!( |
1182 | | SizeError::<_, [u8]>::new(&[0u8; 2][..]).to_string(), |
1183 | | "The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.\n\ |
1184 | | \nSource type: &[u8]\ |
1185 | | \nSource size: 2 bytes\ |
1186 | | \nDestination type: [u8]" |
1187 | | ); |
1188 | | |
1189 | | assert_eq!( |
1190 | | SizeError::<_, [u8; 2]>::new(&[0u8; 1][..]).to_string(), |
1191 | | "The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.\n\ |
1192 | | \nSource type: &[u8]\ |
1193 | | \nSource size: 1 byte\ |
1194 | | \nDestination size: 2 bytes\ |
1195 | | \nDestination type: [u8; 2]" |
1196 | | ); |
1197 | | } |
1198 | | |
1199 | | #[test] |
1200 | | fn validity_display() { |
1201 | | assert_eq!( |
1202 | | ValidityError::<_, bool>::new(&[2u8; 1][..]).to_string(), |
1203 | | "The conversion failed because the source bytes are not a valid value of the destination type.\n\ |
1204 | | \n\ |
1205 | | Destination type: bool" |
1206 | | ); |
1207 | | } |
1208 | | |
1209 | | #[test] |
1210 | | fn test_convert_error_debug() { |
1211 | | let err: ConvertError< |
1212 | | AlignmentError<&[u8], u16>, |
1213 | | SizeError<&[u8], u16>, |
1214 | | ValidityError<&[u8], bool>, |
1215 | | > = ConvertError::Alignment(AlignmentError::new_checked(&[0u8])); |
1216 | | assert_eq!(format!("{:?}", err), "Alignment(AlignmentError)"); |
1217 | | |
1218 | | let err: ConvertError< |
1219 | | AlignmentError<&[u8], u16>, |
1220 | | SizeError<&[u8], u16>, |
1221 | | ValidityError<&[u8], bool>, |
1222 | | > = ConvertError::Size(SizeError::new(&[0u8])); |
1223 | | assert_eq!(format!("{:?}", err), "Size(SizeError)"); |
1224 | | |
1225 | | let err: ConvertError< |
1226 | | AlignmentError<&[u8], u16>, |
1227 | | SizeError<&[u8], u16>, |
1228 | | ValidityError<&[u8], bool>, |
1229 | | > = ConvertError::Validity(ValidityError::new(&[0u8])); |
1230 | | assert_eq!(format!("{:?}", err), "Validity(ValidityError)"); |
1231 | | } |
1232 | | |
1233 | | #[test] |
1234 | | fn test_convert_error_from_unaligned() { |
1235 | | // u8 is Unaligned |
1236 | | let err: ConvertError< |
1237 | | AlignmentError<&[u8], u8>, |
1238 | | SizeError<&[u8], u8>, |
1239 | | ValidityError<&[u8], bool>, |
1240 | | > = ConvertError::Size(SizeError::new(&[0u8])); |
1241 | | let converted: ConvertError<Infallible, SizeError<&[u8], u8>, ValidityError<&[u8], bool>> = |
1242 | | ConvertError::from(err); |
1243 | | match converted { |
1244 | | ConvertError::Size(_) => {} |
1245 | | _ => panic!("Expected Size error"), |
1246 | | } |
1247 | | } |
1248 | | |
1249 | | #[test] |
1250 | | fn test_alignment_error_display_debug() { |
1251 | | let err: AlignmentError<&[u8], u16> = AlignmentError::new_checked(&[0u8]); |
1252 | | assert!(format!("{:?}", err).contains("AlignmentError")); |
1253 | | assert!(format!("{}", err).contains("address of the source is not a multiple")); |
1254 | | } |
1255 | | |
1256 | | #[test] |
1257 | | fn test_size_error_display_debug() { |
1258 | | let err: SizeError<&[u8], u16> = SizeError::new(&[0u8]); |
1259 | | assert!(format!("{:?}", err).contains("SizeError")); |
1260 | | assert!(format!("{}", err).contains("source was incorrectly sized")); |
1261 | | } |
1262 | | |
1263 | | #[test] |
1264 | | fn test_validity_error_display_debug() { |
1265 | | let err: ValidityError<&[u8], bool> = ValidityError::new(&[0u8]); |
1266 | | assert!(format!("{:?}", err).contains("ValidityError")); |
1267 | | assert!(format!("{}", err).contains("source bytes are not a valid value")); |
1268 | | } |
1269 | | |
1270 | | #[test] |
1271 | | fn test_convert_error_display_debug_more() { |
1272 | | let err: ConvertError< |
1273 | | AlignmentError<&[u8], u16>, |
1274 | | SizeError<&[u8], u16>, |
1275 | | ValidityError<&[u8], bool>, |
1276 | | > = ConvertError::Alignment(AlignmentError::new_checked(&[0u8])); |
1277 | | assert!(format!("{}", err).contains("address of the source is not a multiple")); |
1278 | | |
1279 | | let err: ConvertError< |
1280 | | AlignmentError<&[u8], u16>, |
1281 | | SizeError<&[u8], u16>, |
1282 | | ValidityError<&[u8], bool>, |
1283 | | > = ConvertError::Size(SizeError::new(&[0u8])); |
1284 | | assert!(format!("{}", err).contains("source was incorrectly sized")); |
1285 | | |
1286 | | let err: ConvertError< |
1287 | | AlignmentError<&[u8], u16>, |
1288 | | SizeError<&[u8], u16>, |
1289 | | ValidityError<&[u8], bool>, |
1290 | | > = ConvertError::Validity(ValidityError::new(&[0u8])); |
1291 | | assert!(format!("{}", err).contains("source bytes are not a valid value")); |
1292 | | } |
1293 | | |
1294 | | #[test] |
1295 | | fn test_alignment_error_methods() { |
1296 | | let err: AlignmentError<&[u8], u16> = AlignmentError::new_checked(&[0u8]); |
1297 | | |
1298 | | // into_src |
1299 | | let src = err.clone().into_src(); |
1300 | | assert_eq!(src, &[0u8]); |
1301 | | |
1302 | | // into |
1303 | | let converted: ConvertError< |
1304 | | AlignmentError<&[u8], u16>, |
1305 | | SizeError<&[u8], u16>, |
1306 | | ValidityError<&[u8], bool>, |
1307 | | > = err.clone().into(); |
1308 | | match converted { |
1309 | | ConvertError::Alignment(_) => {} |
1310 | | _ => panic!("Expected Alignment error"), |
1311 | | } |
1312 | | |
1313 | | // clone |
1314 | | let cloned = err.clone(); |
1315 | | assert_eq!(err, cloned); |
1316 | | |
1317 | | // eq |
1318 | | assert_eq!(err, cloned); |
1319 | | let err2: AlignmentError<&[u8], u16> = AlignmentError::new_checked(&[1u8]); |
1320 | | assert_ne!(err, err2); |
1321 | | } |
1322 | | |
1323 | | #[test] |
1324 | | fn test_convert_error_from_unaligned_variants() { |
1325 | | // u8 is Unaligned |
1326 | | let err: ConvertError< |
1327 | | AlignmentError<&[u8], u8>, |
1328 | | SizeError<&[u8], u8>, |
1329 | | ValidityError<&[u8], bool>, |
1330 | | > = ConvertError::Validity(ValidityError::new(&[0u8])); |
1331 | | let converted: ConvertError<Infallible, SizeError<&[u8], u8>, ValidityError<&[u8], bool>> = |
1332 | | ConvertError::from(err); |
1333 | | match converted { |
1334 | | ConvertError::Validity(_) => {} |
1335 | | _ => panic!("Expected Validity error"), |
1336 | | } |
1337 | | |
1338 | | let err: ConvertError< |
1339 | | AlignmentError<&[u8], u8>, |
1340 | | SizeError<&[u8], u8>, |
1341 | | ValidityError<&[u8], bool>, |
1342 | | > = ConvertError::Size(SizeError::new(&[0u8])); |
1343 | | let converted: ConvertError<Infallible, SizeError<&[u8], u8>, ValidityError<&[u8], bool>> = |
1344 | | ConvertError::from(err); |
1345 | | match converted { |
1346 | | ConvertError::Size(_) => {} |
1347 | | _ => panic!("Expected Size error"), |
1348 | | } |
1349 | | } |
1350 | | } |