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()
}
}