#![no_std] use core::fmt::{self, Debug, Display}; #[macro_use] extern crate alloc; use alloc::string::{String, ToString}; use alloc::vec::Vec; use serde::{Deserialize, Serialize}; #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub struct Attribute { name: String, value: String, } impl fmt::Display for Attribute { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} = {}", self.name, self.value)?; Ok(()) } } impl Attribute { pub fn to_string(&self) -> String { format!("{} = {}", self.name, self.value) } } #[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] // TODO Add an autotype attribute that defaults to true pub struct XMLElement { pub name: String, pub text: String, pub attributes: Vec, pub children: Vec, } impl XMLElement { // pub fn to_bin(&self) -> Result, XMLError> { // // match bincode::serialize(&self) { // // Ok(bin) => return Ok(bin), // // Err(err) => return Err(XMLError::EncodingError(err)), // // } // } pub fn from_bin(bin: Vec) -> Self { todo!() } } impl XMLElement { pub fn new(name: T) -> Self { Self { name: name.to_string(), text: String::new(), attributes: vec![], children: vec![], } } pub fn to_string(self) -> String { self.into() } pub fn set_child(&mut self, child: XMLElement) { // TODO: handle replacing preexisting children if child.name == "".to_string() { panic!("empty element name") } self.children.push(child); } pub fn set_attribute(&mut self, name: T1, value: T2) { let new_attr = Attribute { name: name.to_string(), value: value.to_string(), }; let mut duplicate_attribute = (false, 0); for (index, attr) in self.attributes.clone().into_iter().enumerate() { if attr.name == name.to_string() { duplicate_attribute = (true, index); break; } } match duplicate_attribute { (false, _) => { self.attributes.push(new_attr.clone()); } (true, index) => { self.attributes[index] = new_attr.clone(); } } } } impl Into for XMLElement { fn into(self) -> String { let mut string = "".to_string(); let element_open: String = format!("<{}", self.name); string.push_str(&element_open); if self.attributes.len() > 0 { string.push(' '); } let mut attr_count = 0; for attr in &self.attributes { string.push_str(&attr.to_string()); attr_count += 1; if &attr_count != &self.attributes.len() { string.push(' '); } } string.push('>'); string.push_str(&self.text); for children in &self.children.clone() { let chl: String = (*children).clone().into(); string.push_str(&chl); } let element_close: String = format!("", self.name); string.push_str(&element_close); string } } #[test] fn element_to_string_test() { let mut xml_ele = XMLElement::new("mouse"); xml_ele.set_attribute("x", 0); xml_ele.set_attribute("x", 1); xml_ele.set_child(XMLElement::new("last_update")); let xml_str: String = xml_ele.into(); let rhs = r##""##; assert_eq!(xml_str, rhs.to_string()); } #[repr(C)] #[derive(Debug)] pub enum Types { // Used to represent an empty attribute None, Integer(Int), UnsignedInteger(UInt), Fixed(FixedPoint), Float(FloatingPoint), String(String), } #[derive(Debug)] pub enum FixedPoint { Fixed16(bool, u8, u8), Fixed32(bool, u16, u16), Fixed64(bool, u32, u32), Fixed128(bool, u64, u64), Fixed256(bool, u128, u128), } #[derive(Debug)] pub enum FloatingPoint { Float32(f32), Float64(f64), } #[derive(Debug)] pub enum Int { I8(i8), I16(i16), I32(i32), I64(i64), I128(i128), } #[derive(Debug)] pub enum UInt { U8(u8), U16(u16), U32(u32), U64(u64), U128(u128), } impl From for UInt { fn from(value: u64) -> Self { Self::U64(value) } } // #[test] // pub fn test_string_to_num() { // string_to_num("-256.0") // } pub fn string_to_num(string: T) -> Result { // let string = "-27".to_string(); // `parse()` works with `&str` and `String`! let string: String = string.to_string(); use FloatingPoint::*; use Int::*; use Types::{Fixed, Float, Integer, UnsignedInteger}; use UInt::*; match string.parse::() { Ok(num) => return Ok(UnsignedInteger(U8(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(UnsignedInteger(U16(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(UnsignedInteger(U32(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(UnsignedInteger(U64(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(UnsignedInteger(U128(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(Integer(I8(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(Integer(I16(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(Integer(I32(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(Integer(I64(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(Integer(I128(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(Float(Float32(num))), Err(_) => {} } match string.parse::() { Ok(num) => return Ok(Float(Float64(num))), Err(_) => {} } // TODO: Decimal handler { let mut split_string = string.split("."); let positive; let mut lhs = split_string.next().unwrap(); // println!("{:?}", lhs.chars().next()); let mut lhs_median: Vec = lhs.chars().collect(); if lhs.chars().next() == Some('-') { // lhs positive = false; lhs_median.remove(0); // println!("A {:?}", lhs_median); } else { positive = true; } // println!("{:?}", lhs); let lhs_median_2 = lhs_median.iter().cloned().collect::(); let mut lhs_final: Types = Types::None; let abc = string_to_num(lhs_median_2); // println!("{:?}", lhs_final); let rhs = split_string.next().unwrap(); // println!("{:?}", rhs); let xyz = string_to_num(rhs); // println!("{:?}", abc); // println!("{:?}", xyz); // return Types::Fixed(); } Err(XMLError::TypeNotANumber) } #[derive(Debug)] pub enum XMLError { TypeNotANumber, // EncodingError(bincode::Error), // DecodingError(bincode::Error), }