use super::AsStr;
use crate::error::Error;
pub fn apply<T: ByteLength>(v: &T, (min, max): (usize, usize)) -> Result<(), Error> {
if let Err(e) = v.validate_byte_length(min, max) {
match e {
InvalidLength::Min => {
return Err(Error::new(format!("byte length is lower than {min}")))
}
InvalidLength::Max => {
return Err(Error::new(format!("byte length is greater than {max}")))
}
}
}
Ok(())
}
pub trait ByteLength {
fn validate_byte_length(&self, min: usize, max: usize) -> Result<(), InvalidLength>;
}
pub enum InvalidLength {
Min,
Max,
}
#[allow(clippy::len_without_is_empty)]
pub trait HasByteLength {
fn byte_length(&self) -> usize;
}
impl<T: HasByteLength> ByteLength for T {
fn validate_byte_length(&self, min: usize, max: usize) -> Result<(), InvalidLength> {
let len = HasByteLength::byte_length(self);
if len < min {
Err(InvalidLength::Min)
} else if len > max {
Err(InvalidLength::Max)
} else {
Ok(())
}
}
}
impl<T: ByteLength> ByteLength for Option<T> {
fn validate_byte_length(&self, min: usize, max: usize) -> Result<(), InvalidLength> {
match self {
Some(value) => value.validate_byte_length(min, max),
None => Ok(()),
}
}
}
impl<T: AsByteSlice> HasByteLength for T {
fn byte_length(&self) -> usize {
self.as_byte_slice().len()
}
}
pub trait AsByteSlice {
fn as_byte_slice(&self) -> &[u8];
}
impl<'a> AsByteSlice for &'a [u8] {
fn as_byte_slice(&self) -> &[u8] {
self
}
}
impl AsByteSlice for Vec<u8> {
fn as_byte_slice(&self) -> &[u8] {
self.as_slice()
}
}
impl<const N: usize> AsByteSlice for [u8; N] {
fn as_byte_slice(&self) -> &[u8] {
self
}
}
impl<T: AsStr> AsByteSlice for T {
fn as_byte_slice(&self) -> &[u8] {
self.as_str().as_bytes()
}
}