rs-alloc 0.0.1

no-std alloc trait
Documentation
use crate::vec::*;
use ::core::*;
use ::core::cmp::*;
use crate::hash::*;
use core::fmt::{Arguments, Write};

#[repr(C)]
pub struct String {
    data    : Vec<u8>
}

impl String {
    pub fn with_capacity(c: usize) -> Self {
        Self { data: Vec::with_capacity(c) }
    }

    pub fn new() -> Self { Self { data: Vec::new() } }
    pub fn from(s: &str) -> Self {
        let mut st = Self::new();
        for c in s.bytes() {
            st.data.push(c);
        }
        st
    }

    pub fn as_str(&self) -> &str {
        ::core::str::from_utf8(self.data.as_slice()).expect("Error getting string out")
    }

    pub fn push(&mut self, u: u8) {
        self.data.push(u);
    }

    pub fn into_bytes(self) -> Vec<u8> { self.data }
    pub fn as_bytes(&self) -> &[u8] { self.data.as_slice() }
    pub fn as_bytes_mut(&mut self) -> &mut [u8] { self.data.as_mut_slice() }
    pub fn as_mut_vec(&mut self) -> &mut Vec<u8> { &mut self.data }

    pub fn push_str(&mut self, s: &str) {
        for c in s.bytes() {
            self.data.push(c);
        }
    }

    pub fn len(&self) -> usize { self.data.len() }

    pub fn split(&self, pattern: &str) -> Split {
        let mut v = Vec::<String>::new();
        let mut i = 0;
        let ss = self.as_str();
        let ss_len = ss.len();
        let mut chars = ss.chars();
        loop {
            let mut st = String::new();
            loop {
                match chars.next() {
                    Some(c) if pattern.contains(c) => {
                        if st.as_str().len() > 0 {
                            v.push(st);
                        }
                        i += 1;
                        break
                    },
                    Some(c) => {
                        st.push(c as u8);
                        i += 1;
                    },
                    None => {
                        if st.as_str().len() > 0 {
                            v.push(st);
                        }
                        break
                    }
                }
            }
            if i >= ss_len {
                break
            }
        }
        Split { v: v, idx: 0 }
    }

    pub fn lines(&self) -> Lines {
        Lines(self.split("\n"))
    }

    pub fn from_raw_parts(ptr: *mut u8, len: usize, cap: usize) -> Self {
        Self { data : Vec::from_raw_parts(ptr, len, cap) }
    }
}

pub struct Split {
    v: Vec<String>,
    idx: usize,
}

impl Iterator for Split  {
    type Item = String;
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx < self.v.len() {
            self.idx += 1;
            return Some(self.v[self.idx - 1].clone());
        }
        None
    }
}

pub struct Lines(Split);
impl Iterator for Lines {
    type Item = String;
    fn next(&mut self) -> Option<Self::Item> { self.0.next() }
}

pub trait Append<T> {
    fn append(&mut self, other: T);
}


impl Append<&String> for String {
    fn append(&mut self, s: &String) {
        for c in s.as_str().bytes() {
            self.data.push(c);
        }
    }
}

impl PartialEq<String> for String {
    fn eq(&self, other: &Self) -> bool {
        let ls = self.data.len();
        let lo = other.data.len();
        if ls != lo { return false }
        for i in 0..self.data.len() {
            if self.data[i] != other.data[i] { return false }
        }
        true
    }
}

impl Eq for String {}

impl PartialEq<&str> for String {
    fn eq(&self, other: &&str) -> bool {
        let ob = (*other).as_bytes();
        let ls = self.data.len();
        let lo = ob.len();
        if ls != lo { return false }
        for i in 0..self.data.len() {
            if self.data[i] != ob[i] { return false }
        }
        true
    }
}

impl Clone for String {
    fn clone(&self) -> Self {
        String::from(self.as_str())
    }
}

impl fmt::Write for String {
    #[inline]
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.push_str(s);
        Ok(())
    }

    #[inline]
    fn write_char(&mut self, c: char) -> fmt::Result {
        self.push(c as u8);
        Ok(())
    }
}

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

impl Hash for String {
    fn hash(&self) -> usize {
        self.as_bytes().hash()
    }
}

pub fn format(args: Arguments<'_>) -> String {
    let mut output = String::new();
    output.write_fmt(args).expect("a formatting trait implementation returned an error");
    output
}

#[macro_export]
macro_rules! format {
    ($fmt:expr, $($args:expr),+) => {
        $crate::string::format(format_args!($fmt, $($args),+))
    };
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_conversion() {
        {
            let u : u32 = 12345;
            if String::from("12345") != format!("{}", u) {
                panic!("fail {}", u);
            }
        }

        {
            let i : i32 = -12345;
            if String::from("-12345") != format!("{}", i) {
                panic!("fail {}", i);
            }
        }
    }

    #[test]
    fn test_split() {
        let s = String::from("v 0/1/2 4/5/6");
        let ss1 : Vec<String> = s.split(" ").collect();

        assert_eq!(ss1[0].as_str(), "v");
        assert_eq!(ss1[1].as_str(), "0/1/2");
        assert_eq!(ss1[2].as_str(), "4/5/6");

        let v = [ ["0", "1", "2"], ["4", "5", "6"] ];
        for i in 1..3 {
            let ss2 : Vec<String> = ss1[i].split("/").collect();
            for j in 0..3 {
                assert_eq!(ss2[j].as_str(), v[i - 1][j]);
            }
        }
    }

    #[test]
    fn test_lines() {
        let s = String::from("hello world\nsomething is different\n\n");
        let ss1 : Vec<String> = s.lines().collect();
        assert_eq!(ss1.len(), 2);
        assert_eq!(ss1[0].as_str(), "hello world");
        assert_eq!(ss1[1].as_str(), "something is different");
    }

}