#![allow(clippy::ptr_as_ptr, clippy::borrow_as_ptr, clippy::missing_errors_doc)]
use core::iter;
#[cfg(feature = "alloc")]
#[allow(unused_imports)]
use alloc::{
    borrow::{Cow, ToOwned},
    boxed::Box,
    rc::Rc,
    string::String,
    sync::Arc,
    vec::Vec,
};
#[cfg_attr(feature = "alloc", doc = "\n[`encode`]: crate::encode")]
#[cfg_attr(not(feature = "alloc"), doc = "\n[`encode`]: crate::encode_to_slice")]
#[deprecated(note = "use `ToHexExt` instead")]
pub trait ToHex {
    fn encode_hex<T: iter::FromIterator<char>>(&self) -> T;
    fn encode_hex_upper<T: iter::FromIterator<char>>(&self) -> T;
}
#[cfg(feature = "alloc")]
pub trait ToHexExt {
    fn encode_hex(&self) -> String;
    fn encode_hex_upper(&self) -> String;
    fn encode_hex_with_prefix(&self) -> String;
    fn encode_hex_upper_with_prefix(&self) -> String;
}
struct BytesToHexChars<'a, const UPPER: bool> {
    inner: core::slice::Iter<'a, u8>,
    next: Option<char>,
}
impl<'a, const UPPER: bool> BytesToHexChars<'a, UPPER> {
    fn new(inner: &'a [u8]) -> Self {
        BytesToHexChars {
            inner: inner.iter(),
            next: None,
        }
    }
}
impl<const UPPER: bool> Iterator for BytesToHexChars<'_, UPPER> {
    type Item = char;
    fn next(&mut self) -> Option<Self::Item> {
        match self.next.take() {
            Some(current) => Some(current),
            None => self.inner.next().map(|byte| {
                let (high, low) = crate::byte2hex::<UPPER>(*byte);
                self.next = Some(low as char);
                high as char
            }),
        }
    }
}
#[inline]
fn encode_to_iter<T: iter::FromIterator<char>, const UPPER: bool>(source: &[u8]) -> T {
    BytesToHexChars::<UPPER>::new(source).collect()
}
#[allow(deprecated)]
impl<T: AsRef<[u8]>> ToHex for T {
    #[inline]
    fn encode_hex<U: iter::FromIterator<char>>(&self) -> U {
        encode_to_iter::<_, false>(self.as_ref())
    }
    #[inline]
    fn encode_hex_upper<U: iter::FromIterator<char>>(&self) -> U {
        encode_to_iter::<_, true>(self.as_ref())
    }
}
#[cfg(feature = "alloc")]
impl<T: AsRef<[u8]>> ToHexExt for T {
    #[inline]
    fn encode_hex(&self) -> String {
        crate::encode(self)
    }
    #[inline]
    fn encode_hex_upper(&self) -> String {
        crate::encode_upper(self)
    }
    #[inline]
    fn encode_hex_with_prefix(&self) -> String {
        crate::encode_prefixed(self)
    }
    #[inline]
    fn encode_hex_upper_with_prefix(&self) -> String {
        crate::encode_upper_prefixed(self)
    }
}
pub trait FromHex: Sized {
    type Error;
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error>;
}
#[cfg(feature = "alloc")]
impl<T: FromHex> FromHex for Box<T> {
    type Error = T::Error;
    #[inline]
    fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
        FromHex::from_hex(hex.as_ref()).map(Box::new)
    }
}
#[cfg(feature = "alloc")]
impl<T> FromHex for Cow<'_, T>
where
    T: ToOwned + ?Sized,
    T::Owned: FromHex,
{
    type Error = <T::Owned as FromHex>::Error;
    #[inline]
    fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
        FromHex::from_hex(hex.as_ref()).map(Cow::Owned)
    }
}
#[cfg(feature = "alloc")]
impl<T: FromHex> FromHex for Rc<T> {
    type Error = T::Error;
    #[inline]
    fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
        FromHex::from_hex(hex.as_ref()).map(Rc::new)
    }
}
#[cfg(feature = "alloc")]
impl<T: FromHex> FromHex for Arc<T> {
    type Error = T::Error;
    #[inline]
    fn from_hex<U: AsRef<[u8]>>(hex: U) -> Result<Self, Self::Error> {
        FromHex::from_hex(hex.as_ref()).map(Arc::new)
    }
}
#[cfg(feature = "alloc")]
impl FromHex for Vec<u8> {
    type Error = crate::FromHexError;
    #[inline]
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
        crate::decode(hex.as_ref())
    }
}
#[cfg(feature = "alloc")]
impl FromHex for Vec<i8> {
    type Error = crate::FromHexError;
    #[inline]
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
        crate::decode(hex.as_ref())
            .map(|vec| unsafe { core::mem::transmute::<Vec<u8>, Vec<i8>>(vec) })
    }
}
#[cfg(feature = "alloc")]
impl FromHex for Box<[u8]> {
    type Error = crate::FromHexError;
    #[inline]
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
        <Vec<u8>>::from_hex(hex).map(Vec::into_boxed_slice)
    }
}
#[cfg(feature = "alloc")]
impl FromHex for Box<[i8]> {
    type Error = crate::FromHexError;
    #[inline]
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
        <Vec<i8>>::from_hex(hex).map(Vec::into_boxed_slice)
    }
}
impl<const N: usize> FromHex for [u8; N] {
    type Error = crate::FromHexError;
    #[inline]
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
        crate::decode_to_array(hex.as_ref())
    }
}
impl<const N: usize> FromHex for [i8; N] {
    type Error = crate::FromHexError;
    #[inline]
    fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
        crate::decode_to_array(hex.as_ref())
            .map(|buf| unsafe { *(&buf as *const [u8; N] as *const [i8; N]) })
    }
}