use std::{alloc::{self, Layout}, ops::Add}; #[derive(Debug, Clone, Copy)] pub struct ObjString { pub ptr: *mut char, pub length: usize, } impl From for ObjString { fn from(value: String) -> Self { unsafe { let layout = Layout::array::(value.len()).unwrap(); let ptr = alloc::alloc(layout) as *mut char; Self { ptr, length: value.len(), } } } } impl From for String { fn from(value: ObjString) -> Self { unsafe { String::from_raw_parts(value.ptr as *mut u8, value.length, value.length) } } } impl ToString for ObjString { fn to_string(&self) -> String { String::from(*self) } } impl Add for ObjString { type Output = Self; fn add(self, other: Self) -> Self { let layout = Layout::array::(self.length + other.length).unwrap(); unsafe { let ptr = alloc::alloc(layout) as *mut char; self.ptr.copy_to(ptr, self.length); other.ptr.copy_to(ptr.offset(self.length as isize), other.length); self.free(); other.free(); Self { ptr, length: self.length + other.length, } } } } impl ObjString { pub fn free(self) { if self.length != 0 { let layout = Layout::array::(self.length).unwrap(); unsafe { alloc::dealloc(self.ptr as *mut u8, layout) } } } }