diff --git a/Cargo.lock b/Cargo.lock index fd51f0b..b76e9ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,10 +107,6 @@ dependencies = [ name = "derelict_microarchitecture" version = "0.1.0" -[[package]] -name = "exi" -version = "0.1.0" - [[package]] name = "fnv" version = "1.0.7" @@ -330,12 +326,6 @@ dependencies = [ "versioning", ] -[[package]] -name = "simple_xml_serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f8896c3696f051907ae5e59f0c2d9fb9f7521c29d636e4a1ea4ff0e4e5aac15" - [[package]] name = "std" version = "0.1.0" @@ -486,15 +476,12 @@ dependencies = [ ] [[package]] -name = "xml-builder" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc4f1a86af7800dfc4056c7833648ea4515ae21502060b5c98114d828f5333b" +name = "xml" +version = "0.1.0" [[package]] name = "xml_tests" version = "0.1.0" dependencies = [ - "simple_xml_serialize", - "xml-builder", + "xml", ] diff --git a/Cargo.toml b/Cargo.toml index be75e02..7ef3f7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ members = [ "libraries/audio_interface", "libraries/clparse", "libraries/cryptography", - "libraries/exi", + "libraries/xml", "libraries/locale-maxima", "libraries/messaging", "libraries/process", diff --git a/libraries/exi/src/lib.rs b/libraries/exi/src/lib.rs deleted file mode 100644 index 6321314..0000000 --- a/libraries/exi/src/lib.rs +++ /dev/null @@ -1,87 +0,0 @@ -use types::NBitUnsignedInteger; - -pub mod types; - -pub const EXI_HEADER_START: &str = "$EXI"; - -pub struct ExiOptions { - // NOTE: Go back to the EXI spec and fix this - pub alignment: u8, - - pub compression: bool, - - pub strict: bool, - - pub fragment: bool, - - // https://www.w3.org/TR/exi/#key-preserveOption - pub preserve: bool, - - // https://www.w3.org/TR/exi/#key-selfContained - pub self_contained: bool, - - // https://www.w3.org/TR/exi/#key-schemaIdOption - pub schema_id: String, - - // https://www.w3.org/TR/exi/#key-datatypeRepresentationOption - // NOTE: What possible usecase could you have for changing the representation of data types. - // Touching this will be UB. Cry about it. - pub datatype_representation_map: bool, - - // https://www.w3.org/TR/exi/#key-blockSizeOption - pub block_size: NBitUnsignedInteger, - - // https://www.w3.org/TR/exi/#key-valueMaxLengthOption - pub value_max_length: NBitUnsignedInteger, - - // https://www.w3.org/TR/exi/#key-valuePartitionCapacityOption - pub value_partition_capacity: NBitUnsignedInteger, - - // https://www.w3.org/TR/exi/#key-userMetaData - pub user_defined_meta_data: String, -} - -pub enum ExiFormatVersion { - PreviewVersion1 = 1_0000, - // The ableOS standard - FinalVersion1 = 0_0000, - FinalVersion15 = 0_1110, - FinalVersion16 = 0_1111_0000, - FinalVersion17 = 0_1111_0001, -} - -pub struct ExiHeader { - exi_format: ExiFormatVersion, - exi_options: ExiOptions, -} - -pub struct ExiDocument {} -impl ExiDocument { - pub fn new_from_xml(xml_string: String) -> Self { - println!("{}", xml_string); - Self {} - } -} - -#[cfg(unix)] -mod unix { - use std::{ - fs::{self, File}, - io::Read, - path::Path, - }; - - use crate::ExiDocument; - fn parse_exi_from_file(path: &Path) -> ExiDocument { - let file_contents = fs::read_to_string(path).unwrap(); - - ExiDocument::new_from_xml(file_contents) - // ExiDocument {} - } - #[test] - fn test_xml_to_exi() { - parse_exi_from_file(Path::new( - "/home/able/Projects/ableos_userland/libraries/exi/assets/sample.xml", - )); - } -} diff --git a/libraries/exi/src/types.rs b/libraries/exi/src/types.rs deleted file mode 100644 index d871755..0000000 --- a/libraries/exi/src/types.rs +++ /dev/null @@ -1,107 +0,0 @@ -pub struct List { - pub length: usize, - pub values: Vec, -} -// https://www.w3.org/TR/exi/#encodingUnsignedInteger -pub struct NBitUnsignedInteger { - pub length: Option, - pub bits: Vec, -} -impl NBitUnsignedInteger { - pub fn new(length: Integer) -> Self { - let c = if length.bits == vec![0] { - None - } else { - Some(length) - }; - Self { - length: c, - bits: Vec::new(), - } - } -} - -pub struct BinaryBlob { - pub length: Integer, - pub bytes: Vec, -} - -pub struct Decimal { - pub lhs: UnsignedInteger, - pub rhs: UnsignedInteger, -} - -pub enum EXITypes { - Binary(BinaryBlob), - Boolean(bool), - Decimal(Decimal), - Float(f64), - Integer(Integer), - UnsignedInteger(UnsignedInteger), - QName(String), - DateTime(DateTime), - NBitUnsignedInteger(NBitUnsignedInteger), - String(String), - List(List), -} - -pub struct DateTime { - pub year: Integer, - pub month_day: NBitUnsignedInteger, - pub time: NBitUnsignedInteger, - pub fractional_secs: NBitUnsignedInteger, - pub timezone: NBitUnsignedInteger, - pub presence: bool, -} - -impl DateTime { - pub fn new() -> Self { - Self { - year: Integer::new(), - month_day: NBitUnsignedInteger::new(9.into()), - time: NBitUnsignedInteger::new(17.into()), - fractional_secs: NBitUnsignedInteger::new(9.into()), - timezone: NBitUnsignedInteger::new(11.into()), - presence: false, - } - } -} - -pub struct Integer { - pub negative: bool, - pub bits: Vec, -} -impl Integer { - pub fn new() -> Self { - Self { - negative: false, - bits: vec![0], - } - } -} - -impl From for Integer { - fn from(value: i8) -> Self { - Self { - negative: value.is_negative(), - bits: value.abs().to_le_bytes().to_vec(), - } - } -} - -pub struct UnsignedInteger { - pub bits: Vec, -} -impl UnsignedInteger { - pub fn new() -> Self { - Self { bits: vec![0] } - } -} - -impl From for UnsignedInteger { - fn from(value: i8) -> Self { - Self { - bits: value.abs().to_le_bytes().to_vec(), - } - } -} diff --git a/libraries/exi/Cargo.toml b/libraries/xml/Cargo.toml similarity index 92% rename from libraries/exi/Cargo.toml rename to libraries/xml/Cargo.toml index f997c39..71a2006 100644 --- a/libraries/exi/Cargo.toml +++ b/libraries/xml/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "exi" +name = "xml" version = "0.1.0" edition = "2021" diff --git a/libraries/exi/assets/sample.xml b/libraries/xml/assets/sample.xml similarity index 100% rename from libraries/exi/assets/sample.xml rename to libraries/xml/assets/sample.xml diff --git a/libraries/xml/src/lib.rs b/libraries/xml/src/lib.rs new file mode 100644 index 0000000..24defea --- /dev/null +++ b/libraries/xml/src/lib.rs @@ -0,0 +1,232 @@ +use core::fmt::{Debug, Display}; + +#[derive(PartialEq, Clone)] +pub struct Attribute { + name: String, + value: String, +} + +impl Attribute { + fn to_string(&self) -> String { + format!("{:?}={:?}", self.name, self.value) + } +} +#[derive(Clone)] +// 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 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() { + println!("{:?}", string_to_num(256)); +} + +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 + {} + + Err(XMLError::TypeNotANumber) +} +#[derive(Debug)] +pub enum XMLError { + TypeNotANumber, +} diff --git a/programs/xml_tests/Cargo.toml b/programs/xml_tests/Cargo.toml index fe19e03..66f3eed 100644 --- a/programs/xml_tests/Cargo.toml +++ b/programs/xml_tests/Cargo.toml @@ -6,5 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -simple_xml_serialize = "*" -xml-builder = "0.5.2" +xml = { path = "../../libraries/xml" } diff --git a/programs/xml_tests/src/main.rs b/programs/xml_tests/src/main.rs index fabbe05..ea39a23 100644 --- a/programs/xml_tests/src/main.rs +++ b/programs/xml_tests/src/main.rs @@ -1,28 +1,7 @@ -// use simple_xml_serialize::XMLElement; - -// fn main() { -// let mut ele = XMLElement::new("mouse"); - -// println!("{}", ele); -// } - -use xml_builder::{XMLBuilder, XMLElement, XMLVersion}; +use xml; fn main() { - let mut xml = XMLBuilder::new() - .version(XMLVersion::XML1_1) - .encoding("UTF-8".into()) - .build(); + let root = xml::XMLElement::new("name"); - let mut mouse = XMLElement::new("mouse"); - mouse.add_attribute("x", "8"); - mouse.add_attribute("y", "0"); - mouse.add_attribute("y_change", "-1"); - mouse.add_attribute("x_change", "1"); - - xml.set_root_element(mouse); - - let mut writer: Vec = Vec::new(); - xml.generate(&mut writer).unwrap(); - println!("{}", String::from_utf8_lossy(&writer)); + println!("{}", root.to_string()) }