ewe_mem 0.0.1

Low-level memory management utilities that implement a poor man allocator wrappers
Documentation
use std::borrow::Cow;
use std::fmt::{self, Debug};
use std::ops::Deref;
use std::{slice, str};

use crate::encoding;

pub trait Align {
    fn align(&mut self, offset: usize);
}

impl<T: Align> Align for Vec<T> {
    #[inline]
    fn align(&mut self, offset: usize) {
        for item in self.iter_mut() {
            item.align(offset);
        }
    }
}

impl<T: Align> Align for Option<T> {
    #[inline]
    fn align(&mut self, offset: usize) {
        if let Some(val) = self {
            val.align(offset);
        }
    }
}

impl Align for usize {
    #[inline]
    fn align(&mut self, offset: usize) {
        if *self >= offset {
            *self -= offset;
        }
    }
}

#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Range {
    pub start: usize,
    pub end: usize,
}

impl Align for Range {
    fn align(&mut self, offset: usize) {
        self.start.align(offset);
        self.end.align(offset);
    }
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Bytes<'b>(Cow<'b, [u8]>);

impl<'b> Bytes<'b> {
    #[inline]
    pub fn from_slice(slice: &'b [u8]) -> Bytes<'b> {
        Bytes(Cow::from(slice))
    }

    #[inline]
    pub fn from_str(text: &'b str, encoder: encoding::SharedEncoding) -> Bytes<'b> {
        Self(encoder.encode(text))
    }

    #[inline]
    pub fn to_string(&self, decoder: encoding::SharedEncoding) -> String {
        decoder.decode(self).to_owned()
    }

    #[inline]
    pub fn to_utf8_string(&self) -> String {
        str::from_utf8(self.0.as_ref())
            .expect("should be utf8 string")
            .to_string()
    }

    #[inline]
    pub fn to_upper(self) -> Bytes<'b> {
        Bytes(Cow::from(self.0.to_ascii_uppercase()))
    }

    #[inline]
    pub fn to_lower(self) -> Bytes<'b> {
        Bytes(Cow::from(self.0.to_ascii_lowercase()))
    }

    #[inline]
    pub fn as_upper(&self, encoder: encoding::SharedEncoding) -> String {
        encoder.decode(self).to_ascii_uppercase()
    }

    #[inline]
    pub fn as_lower(&self, encoder: encoding::SharedEncoding) -> String {
        encoder.decode(self).to_ascii_lowercase()
    }

    #[inline]
    pub fn into_owned(self) -> Bytes<'static> {
        Bytes(Cow::Owned(self.0.into_owned()))
    }

    #[inline]
    pub fn to_slice(&'b self, range: Range) -> Bytes<'b> {
        let byte_slice = self.0[range.start..range.end].into();
        Bytes(Cow::Borrowed(byte_slice))
    }

    #[inline]
    pub fn opt_slice(&self, range: Option<Range>) -> Option<Bytes> {
        range.map(|range| self.to_slice(range))
    }

    #[inline]
    pub fn into_iter(&'b self) -> slice::Iter<'b, u8> {
        self.0.into_iter()
    }
}

impl Deref for Bytes<'_> {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        &self.0
    }
}

impl<'b> From<Cow<'b, [u8]>> for Bytes<'b> {
    #[inline]
    fn from(bytes: Cow<'b, [u8]>) -> Self {
        Bytes(bytes)
    }
}

impl<'b> From<&'b [u8]> for Bytes<'b> {
    #[inline]
    fn from(bytes: &'b [u8]) -> Self {
        Bytes(bytes.into())
    }
}

impl Debug for Bytes<'_> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "`{}`", self.to_utf8_string())
    }
}