// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
// Copyright 2024 The Fuchsia Authors
//
// Licensed under the 2-Clause BSD License <LICENSE-BSD or
// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
//! Types related to error reporting.
//!
//! ## Single failure mode errors
//!
//! Generally speaking, zerocopy's conversions may fail for one of up to three
//! reasons:
//! - [`AlignmentError`]: the conversion source was improperly aligned
//! - [`SizeError`]: the conversion source was of incorrect size
//! - [`ValidityError`]: the conversion source contained invalid data
//!
//! Methods that only have one failure mode, like
//! [`FromBytes::read_from_bytes`], return that mode's corresponding error type
//! directly.
//!
//! ## Compound errors
//!
//! Conversion methods that have either two or three possible failure modes
//! return one of these error types:
//! - [`CastError`]: the error type of reference conversions
//! - [`TryCastError`]: the error type of fallible reference conversions
//! - [`TryReadError`]: the error type of fallible read conversions
//!
//! ## [`Unaligned`] destination types
//!
//! For [`Unaligned`] destination types, alignment errors are impossible. All
//! compound error types support infallibly discarding the alignment error via
//! [`From`] so long as `Dst: Unaligned`. For example, see [`<SizeError as
//! From<ConvertError>>::from`][size-error-from].
//!
//! [size-error-from]: struct.SizeError.html#method.from-1
//!
//! ## Accessing the conversion source
//!
//! All error types provide an `into_src` method that converts the error into
//! the source value underlying the failed conversion.
//!
//! ## Display formatting
//!
//! All error types provide a `Display` implementation that produces a
//! human-readable error message. When `debug_assertions` are enabled, these
//! error messages are verbose and may include potentially sensitive
//! information, including:
//!
//! - the names of the involved types
//! - the sizes of the involved types
//! - the addresses of the involved types
//! - the contents of the involved types
//!
//! When `debug_assertions` are disabled (as is default for `release` builds),
//! such potentially sensitive information is excluded.
//!
//! In the future, we may support manually configuring this behavior. If you are
//! interested in this feature, [let us know on GitHub][issue-1457] so we know
//! to prioritize it.
//!
//! [issue-1457]: https://github.com/google/zerocopy/issues/1457
//!
//! ## Validation order
//!
//! Our conversion methods typically check alignment, then size, then bit
//! validity. However, we do not guarantee that this is always the case, and
//! this behavior may change between releases.
//!
//! ## `Send`, `Sync`, and `'static`
//!
//! Our error types are `Send`, `Sync`, and `'static` when their `Src` parameter
//! is `Send`, `Sync`, or `'static`, respectively. This can cause issues when an
//! error is sent or synchronized across threads; e.g.:
//!
//! ```compile_fail,E0515
//! use zerocopy::*;
//!
//! let result: SizeError<&[u8], u32> = std::thread::spawn(|| {
//! let source = &mut [0u8, 1, 2][..];
//! // Try (and fail) to read a `u32` from `source`.
//! u32::read_from_bytes(source).unwrap_err()
//! }).join().unwrap();
//! ```
//!
//! To work around this, use [`map_src`][CastError::map_src] to convert the
//! source parameter to an unproblematic type; e.g.:
//!
//! ```
//! use zerocopy::*;
//!
//! let result: SizeError<(), u32> = std::thread::spawn(|| {
//! let source = &mut [0u8, 1, 2][..];
//! // Try (and fail) to read a `u32` from `source`.
//! u32::read_from_bytes(source).unwrap_err()
//! // Erase the error source.
//! .map_src(drop)
//! }).join().unwrap();
//! ```
//!
//! Alternatively, use `.to_string()` to eagerly convert the error into a
//! human-readable message; e.g.:
//!
//! ```
//! use zerocopy::*;
//!
//! let result: Result<u32, String> = std::thread::spawn(|| {
//! let source = &mut [0u8, 1, 2][..];
//! // Try (and fail) to read a `u32` from `source`.
//! u32::read_from_bytes(source)
//! // Eagerly render the error message.
//! .map_err(|err| err.to_string())
//! }).join().unwrap();
//! ```
#[cfg(not(no_zerocopy_core_error_1_81_0))]
use core::error::Error;
use core::{
convert::Infallible,
fmt::{self, Debug, Write},
ops::Deref,
};
#[cfg(all(no_zerocopy_core_error_1_81_0, any(feature = "std", test)))]
use std::error::Error;
use crate::{util::SendSyncPhantomData, KnownLayout, TryFromBytes, Unaligned};
#[cfg(doc)]
use crate::{FromBytes