mod archive;
mod shared;
mod util;
use crate::{
    validation::{
        check_archived_root_with_context, check_archived_value_with_context, ArchiveContext,
        CheckTypeError, SharedContext,
    },
    Archive, Fallible,
};
pub use archive::*;
use bytecheck::CheckBytes;
use core::{
    alloc::{Layout, LayoutError},
    any::TypeId,
    fmt,
};
pub use shared::*;
pub use util::*;
#[derive(Debug)]
pub enum DefaultValidatorError {
    ArchiveError(ArchiveError),
    SharedError(SharedError),
}
impl fmt::Display for DefaultValidatorError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::ArchiveError(e) => write!(f, "{}", e),
            Self::SharedError(e) => write!(f, "{}", e),
        }
    }
}
#[cfg(feature = "std")]
const _: () = {
    use std::error::Error;
    impl Error for DefaultValidatorError {
        fn source(&self) -> Option<&(dyn Error + 'static)> {
            match self {
                Self::ArchiveError(e) => Some(e as &dyn Error),
                Self::SharedError(e) => Some(e as &dyn Error),
            }
        }
    }
};
#[derive(Debug)]
pub struct DefaultValidator<'a> {
    archive: ArchiveValidator<'a>,
    shared: SharedValidator,
}
impl<'a> DefaultValidator<'a> {
    #[inline]
    pub fn new(bytes: &'a [u8]) -> Self {
        Self {
            archive: ArchiveValidator::new(bytes),
            shared: SharedValidator::new(),
        }
    }
}
impl<'a> Fallible for DefaultValidator<'a> {
    type Error = DefaultValidatorError;
}
impl<'a> ArchiveContext for DefaultValidator<'a> {
    type PrefixRange = <ArchiveValidator<'a> as ArchiveContext>::PrefixRange;
    type SuffixRange = <ArchiveValidator<'a> as ArchiveContext>::SuffixRange;
    #[inline]
    unsafe fn bounds_check_ptr(
        &mut self,
        base: *const u8,
        offset: isize,
    ) -> Result<*const u8, Self::Error> {
        self.archive
            .bounds_check_ptr(base, offset)
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    unsafe fn bounds_check_layout(
        &mut self,
        data_address: *const u8,
        layout: &Layout,
    ) -> Result<(), Self::Error> {
        self.archive
            .bounds_check_layout(data_address, layout)
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    unsafe fn bounds_check_subtree_ptr_layout(
        &mut self,
        data_address: *const u8,
        layout: &Layout,
    ) -> Result<(), Self::Error> {
        self.archive
            .bounds_check_subtree_ptr_layout(data_address, layout)
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    unsafe fn push_prefix_subtree_range(
        &mut self,
        root: *const u8,
        end: *const u8,
    ) -> Result<PrefixRange, Self::Error> {
        self.archive
            .push_prefix_subtree_range(root, end)
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    fn pop_prefix_range(&mut self, range: PrefixRange) -> Result<(), Self::Error> {
        self.archive
            .pop_prefix_range(range)
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    unsafe fn push_suffix_subtree_range(
        &mut self,
        start: *const u8,
        root: *const u8,
    ) -> Result<SuffixRange, Self::Error> {
        self.archive
            .push_suffix_subtree_range(start, root)
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    fn pop_suffix_range(&mut self, range: SuffixRange) -> Result<(), Self::Error> {
        self.archive
            .pop_suffix_range(range)
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    fn finish(&mut self) -> Result<(), Self::Error> {
        self.archive
            .finish()
            .map_err(DefaultValidatorError::ArchiveError)
    }
    #[inline]
    fn wrap_layout_error(error: LayoutError) -> Self::Error {
        DefaultValidatorError::ArchiveError(ArchiveValidator::wrap_layout_error(error))
    }
}
impl<'a> SharedContext for DefaultValidator<'a> {
    #[inline]
    fn register_shared_ptr(
        &mut self,
        ptr: *const u8,
        type_id: TypeId,
    ) -> Result<bool, Self::Error> {
        self.shared
            .register_shared_ptr(ptr, type_id)
            .map_err(DefaultValidatorError::SharedError)
    }
}
#[inline]
pub fn check_archived_value<'a, T: Archive>(
    bytes: &'a [u8],
    pos: usize,
) -> Result<&T::Archived, CheckTypeError<T::Archived, DefaultValidator<'a>>>
where
    T::Archived: CheckBytes<DefaultValidator<'a>>,
{
    let mut validator = DefaultValidator::new(bytes);
    check_archived_value_with_context::<T, DefaultValidator>(bytes, pos, &mut validator)
}
#[inline]
pub fn check_archived_root<'a, T: Archive>(
    bytes: &'a [u8],
) -> Result<&'a T::Archived, CheckTypeError<T::Archived, DefaultValidator<'a>>>
where
    T::Archived: CheckBytes<DefaultValidator<'a>>,
{
    let mut validator = DefaultValidator::new(bytes);
    check_archived_root_with_context::<T, DefaultValidator>(bytes, &mut validator)
}