vm_value 0.4.3

Core value trait used by fn_vm, this crate is meant to provide the building blocks to creating pass by value VMs in rust.
Documentation
use std::fmt::{Display, Formatter};
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub};
use std::str::Chars;
use crate::{Logical, str_to_vm_bytes, VM, VMValue};


#[derive(Clone, Debug, PartialOrd, PartialEq)]
pub struct VmStr {
    pub value: String
}

impl From<String> for VmStr {
    fn from(value: String) -> Self {
        VmStr {
            value,
        }
    }
}

impl From<&str> for VmStr {
    fn from(value: &str) -> Self {
        VmStr {
            value: value.to_string(),
        }
    }
}

impl VmStr {

    pub fn is_empty(&self) -> bool {
        self.value.is_empty()
    }

    pub fn len(&self) -> usize {
        self.value.len()
    }
    pub fn chars(&self) -> Chars {
        self.value.chars()
    }

    pub fn as_bytes(&self) -> &[u8] {
        self.value.as_bytes()
    }
}

impl Display for VmStr {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.value)
    }
}

impl Logical for VmStr {
    fn bool_and(&self, b: &VmStr) -> bool {
        !self.value.is_empty() && !b.value.is_empty()
    }

    fn bool_or(&self, b: &VmStr) -> bool {
        !self.value.is_empty() || !b.value.is_empty()
    }

    fn bool_xor(&self, b: &VmStr) -> bool {
        !self.value.is_empty() ^ !b.value.is_empty()
    }

    fn bool_not(&self) -> bool {
        !self.value.is_empty()
    }

    fn bitwise_reverse(&self) -> VmStr {
        let str: String = self.chars().rev().collect();
        str.into()
    }
}

impl <Op, Val> VMValue<Op, Val, VmStr> for VmStr {
    fn create_from_vm_bytes<V: VM<Op, Val, VmStr>>(vm: &mut V) -> VmStr {
        VmStr {
            value: vm.next_str()
        }
    }

    fn to_vm_bytes(&self) -> Vec<u8> {
        str_to_vm_bytes(self.value.as_str())
    }
}

impl Add for VmStr {
    type Output = VmStr;

    fn add(self, rhs: Self) -> Self::Output {
        (self.value + rhs.value.as_str()).into()
    }
}

impl Mul for VmStr {
    type Output = VmStr;

    fn mul(self, rhs: Self) -> Self::Output {
        let mut result = Vec::with_capacity(self.len() * rhs.len());
        for char in self.chars() {
            for oc in rhs.chars() {
                result.push(char);
                result.push(oc);
            }
        }
        let str: String = result.iter().collect();
        str.into()
    }
}

impl Rem for VmStr {
    type Output = VmStr;

    fn rem(self, rhs: Self) -> Self::Output {
        let mut split = self.value.split(rhs.value.as_str());
        VmStr {
            value: split.nth(0).unwrap().to_string()
        }
    }
}

impl Sub for VmStr {
    type Output = VmStr;

    fn sub(self, rhs: Self) -> Self::Output {
        VmStr {
            value: self.value.replacen(rhs.value.as_str(), "", 1)
        }
    }
}

impl Div for VmStr {
    type Output = VmStr;

    fn div(self, rhs: Self) -> Self::Output {
        VmStr { value: self.value.replace(rhs.value.as_str(), "") }
    }
}

impl Not for VmStr {
    type Output = VmStr;

    fn not(self) -> Self::Output {
        VmStr {
            value: self.chars()
                .flat_map(|c| {
                    let mut buffer = [0; 4];
                    let encoded = c.encode_utf8(&mut buffer);
                    encoded.bytes().map(|b| (!b) as char).collect::<Vec<_>>()
                })
                .collect(),
        }
    }
}

impl Neg for VmStr {
    type Output = VmStr;

    fn neg(self) -> Self::Output {
        let str: String = self.chars().filter(|c| !c.is_whitespace()).collect();
        str.into()
    }
}

impl BitXor for VmStr {
    type Output = VmStr;

    fn bitxor(self, rhs: Self) -> Self::Output {
        let lhs_bytes = self.as_bytes();
        let rhs_bytes = rhs.as_bytes();
        let len = std::cmp::min(lhs_bytes.len(), rhs_bytes.len());
        let mut result = Vec::with_capacity(len);

        for i in 0..len {
            result.push(lhs_bytes[i] ^ rhs_bytes[i]);
        }

        String::from_utf8(result).unwrap_or_default().into()
    }
}

impl BitAnd for VmStr {
    type Output = VmStr;

    fn bitand(self, rhs: Self) -> Self::Output {
        let lhs_bytes = self.as_bytes();
        let rhs_bytes = rhs.as_bytes();
        let len = std::cmp::min(lhs_bytes.len(), rhs_bytes.len());
        let mut result = Vec::with_capacity(len);

        for i in 0..len {
            result.push(lhs_bytes[i] & rhs_bytes[i]);
        }

        String::from_utf8(result).unwrap_or_default().into()
    }
}

impl BitOr for VmStr {
    type Output = VmStr;

    fn bitor(self, rhs: Self) -> Self::Output {
        let lhs_bytes = self.as_bytes();
        let rhs_bytes = rhs.as_bytes();
        let len = std::cmp::min(lhs_bytes.len(), rhs_bytes.len());
        let mut result = Vec::with_capacity(len);

        for i in 0..len {
            result.push(lhs_bytes[i] | rhs_bytes[i]);
        }

        String::from_utf8(result).unwrap_or_default().into()
    }
}

impl Shr for VmStr {
    type Output = VmStr;

    fn shr(self, rhs: Self) -> Self::Output {
        let mut v = rhs.value.clone();
        v.insert_str(0, self.value.as_str());
        v.into()
    }
}

impl Shl for VmStr {
    type Output = VmStr;

    fn shl(self, rhs: Self) -> Self::Output {
        let mut v = self.value.clone();
        v.extend(rhs.chars());
        v.into()
    }
}