forked from AbleOS/ableos_userland
296 lines
7.3 KiB
Rust
296 lines
7.3 KiB
Rust
#![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<Attribute>,
|
|
pub children: Vec<XMLElement>,
|
|
}
|
|
|
|
impl XMLElement {
|
|
// pub fn to_bin(&self) -> Result<Vec<u8>, XMLError> {
|
|
// // match bincode::serialize(&self) {
|
|
// // Ok(bin) => return Ok(bin),
|
|
// // Err(err) => return Err(XMLError::EncodingError(err)),
|
|
// // }
|
|
// }
|
|
pub fn from_bin(bin: Vec<u8>) -> Self {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl XMLElement {
|
|
pub fn new<T: Display + Debug>(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<T1: Display + Debug, T2: Display + Debug>(&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<String> 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##"<mouse "x"="1"><last_update></last_update></mouse>"##;
|
|
|
|
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<u64> 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<T: Debug + Display>(string: T) -> Result<Types, XMLError> {
|
|
// 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::<u8>() {
|
|
Ok(num) => return Ok(UnsignedInteger(U8(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<u16>() {
|
|
Ok(num) => return Ok(UnsignedInteger(U16(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<u32>() {
|
|
Ok(num) => return Ok(UnsignedInteger(U32(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<u64>() {
|
|
Ok(num) => return Ok(UnsignedInteger(U64(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<u128>() {
|
|
Ok(num) => return Ok(UnsignedInteger(U128(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<i8>() {
|
|
Ok(num) => return Ok(Integer(I8(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<i16>() {
|
|
Ok(num) => return Ok(Integer(I16(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<i32>() {
|
|
Ok(num) => return Ok(Integer(I32(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<i64>() {
|
|
Ok(num) => return Ok(Integer(I64(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<i128>() {
|
|
Ok(num) => return Ok(Integer(I128(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<f32>() {
|
|
Ok(num) => return Ok(Float(Float32(num))),
|
|
Err(_) => {}
|
|
}
|
|
match string.parse::<f64>() {
|
|
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<char> = 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::<String>();
|
|
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),
|
|
}
|