size-limit 0.1.0

range limit checker
Documentation
use std::{
    fmt::{Debug, Display},
    ops::Deref,
};

use crate::{error, measurable::Measurable};

use super::{RangeBound, SizeStatus};

pub struct RangeBoundLimit<T, Rb>(pub(crate) T, pub(crate) Rb);

impl<T, Rb: Default> RangeBoundLimit<T, Rb> {
    fn handle_arms(status: SizeStatus, size: usize, value: T) -> Result<Self, error::Error> {
        match status {
            SizeStatus::Ok => Ok(Self(value, Rb::default())),
            SizeStatus::TooLarge(require) => Err(error::Error::TooLarge { require, get: size }),
            SizeStatus::TooSmall(require) => Err(error::Error::TooSmall { require, get: size }),
            SizeStatus::FIxSize(s) => Err(error::Error::FixSize {
                require: s,
                get: size,
            }),
            SizeStatus::Custom(err) => Err(error::Error::Custom(err)),
        }
    }
}

impl<T: Debug + Measurable, Rb: Debug> Debug for RangeBoundLimit<T, Rb> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("RangeLimit")
            .field("data", &self.0)
            .field("bound", &self.1)
            .field("exact length", &self.0.size())
            .finish()
    }
}

impl<T: Display, Rb> Display for RangeBoundLimit<T, Rb> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

impl<T, Rb> Deref for RangeBoundLimit<T, Rb> {
    type Target = T;

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

impl<P, T, Rb> RangeBoundLimit<P, Rb>
where
    P: Deref<Target = T>,
    T: Measurable,
    Rb: RangeBound,
{
    pub fn try_from_ptr(value: P) -> Result<Self, error::Error> {
        Self::handle_arms(Rb::match_range(value.size()), value.size(), value)
    }
}

impl<T: Measurable, Rb: RangeBound> RangeBoundLimit<T, Rb> {
    pub fn try_from(value: T) -> Result<Self, error::Error> {
        Self::handle_arms(Rb::match_range(value.size()), value.size(), value)
    }

    pub fn into(self) -> T {
        self.0
    }
}

impl<T: Measurable, Rb> Measurable for RangeBoundLimit<T, Rb> {
    fn size(&self) -> usize {
        self.0.size()
    }
}