wolfpack 0.3.1

A package manager and a build tool that supports major package formats (deb, RPM, ipk, pkg, MSIX).
Documentation
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hash;
use std::hash::Hasher;
use std::ops::Deref;
use std::str::FromStr;

use base16ct::lower::encode_string;
use base16ct::mixed::decode;
use base64ct::Base64;
use base64ct::Encoding;
use constant_time_eq::constant_time_eq_n;

#[derive(PartialOrd, Ord, Clone)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
pub struct HashArray<const N: usize>([u8; N]);

impl<const N: usize> HashArray<N> {
    pub const fn new(array: [u8; N]) -> Self {
        Self(array)
    }

    pub const fn len(&self) -> usize {
        N
    }

    pub const fn is_empty(&self) -> bool {
        N == 0
    }

    pub fn to_base64(&self) -> String {
        Base64::encode_string(&self[..])
    }

    pub const LEN: usize = N;
    pub const HEX_LEN: usize = 2 * N;
}

impl<const N: usize> PartialEq for HashArray<N> {
    fn eq(&self, other: &Self) -> bool {
        constant_time_eq_n(&self.0, &other.0)
    }
}

impl<const N: usize> Eq for HashArray<N> {}

impl<const N: usize> Hash for HashArray<N> {
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        self.0.hash(state);
    }
}

impl<const N: usize> AsRef<[u8]> for HashArray<N> {
    fn as_ref(&self) -> &[u8] {
        &self.0[..]
    }
}

impl<const N: usize> AsRef<[u8; N]> for HashArray<N> {
    fn as_ref(&self) -> &[u8; N] {
        &self.0
    }
}

impl<const N: usize> From<[u8; N]> for HashArray<N> {
    fn from(data: [u8; N]) -> Self {
        Self(data)
    }
}

impl<const N: usize> TryFrom<&[u8]> for HashArray<N> {
    type Error = HashTryFromError;
    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
        Ok(Self(data.try_into().map_err(|_| HashTryFromError)?))
    }
}

impl<const N: usize> From<HashArray<N>> for [u8; N] {
    fn from(hash: HashArray<N>) -> Self {
        hash.0
    }
}

impl<const N: usize> Deref for HashArray<N> {
    type Target = [u8; N];

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<const N: usize> Display for HashArray<N> {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        let s = encode_string(&self[..]);
        f.write_str(&s)
    }
}

impl<const N: usize> Debug for HashArray<N> {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        Display::fmt(self, f)
    }
}

impl<const N: usize> FromStr for HashArray<N> {
    type Err = HashParseError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut array = [0_u8; N];
        decode(s.as_bytes(), &mut array[..]).map_err(|_| HashParseError)?;
        Ok(Self(array))
    }
}

#[derive(Debug)]
pub struct HashParseError;

impl Display for HashParseError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "Invalid hash string")
    }
}

#[derive(Debug)]
pub struct HashTryFromError;