initial work on the EXI format

This commit is contained in:
Able 2023-03-30 22:19:57 -05:00
parent 32928f7913
commit f8575ec041
9 changed files with 181 additions and 133 deletions

4
Cargo.lock generated
View file

@ -107,6 +107,10 @@ dependencies = [
name = "derelict_microarchitecture"
version = "0.1.0"
[[package]]
name = "exi"
version = "0.1.0"
[[package]]
name = "fnv"
version = "1.0.7"

View file

@ -18,6 +18,7 @@ members = [
"libraries/audio_interface",
"libraries/clparse",
"libraries/cryptography",
"libraries/exi",
"libraries/locale-maxima",
"libraries/messaging",
"libraries/process",

View file

@ -1,7 +1,10 @@
#![no_std]
#![no_main]
extern crate alloc;
#[no_mangle]
fn start() {
// Simple driver
let mut audio_ring: [u8; 2048] = [0; 2048];
}

8
libraries/exi/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "exi"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

58
libraries/exi/src/lib.rs Normal file
View file

@ -0,0 +1,58 @@
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 {}

107
libraries/exi/src/types.rs Normal file
View file

@ -0,0 +1,107 @@
pub struct List {
pub length: usize,
pub values: Vec<EXITypes>,
}
// https://www.w3.org/TR/exi/#encodingUnsignedInteger
pub struct NBitUnsignedInteger {
pub length: Option<Integer>,
pub bits: Vec<bool>,
}
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<u8>,
}
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<u8>,
}
impl Integer {
pub fn new() -> Self {
Self {
negative: false,
bits: vec![0],
}
}
}
impl From<i8> 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<u8>,
}
impl UnsignedInteger {
pub fn new() -> Self {
Self { bits: vec![0] }
}
}
impl From<i8> for UnsignedInteger {
fn from(value: i8) -> Self {
Self {
bits: value.abs().to_le_bytes().to_vec(),
}
}
}

View file

@ -8,7 +8,6 @@ mod entry;
pub mod env;
pub mod exit;
pub mod io;
pub mod object;
#[cfg(not(test))]
pub mod panic;

View file

@ -1,84 +0,0 @@
pub mod types;
use types::*;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use hashbrown::HashMap;
#[derive(Debug)]
pub enum ObjectErrors {
PropertyNotFound,
NoProperties,
FailureToInsert,
}
pub struct Object {
properties: HashMap<Types, Types>,
children: Option<Vec<Object>>,
}
impl Object {
pub fn new(name: Types) -> Self {
let mut obj = Self {
properties: HashMap::new(),
children: None,
};
let _ = obj.set_value("name".into(), name);
obj
}
pub fn get_value(&mut self, key: Types) -> Result<Types, ObjectErrors> {
use ObjectErrors::*;
if self.properties.is_empty() {
return Err(NoProperties);
}
let ret = self.properties.get(&key).unwrap();
Ok(ret.clone())
}
pub fn set_value(&mut self, key: Types, value: Types) -> Result<(), ObjectErrors> {
let ret = self.properties.insert(key, value);
match ret {
Some(_) => {}
None => return Err(ObjectErrors::FailureToInsert),
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{types::Types, Object};
#[test]
fn object_creation() {
let obj = Object::new(Types::new("hi"));
}
#[test]
fn property_set() {
let key = Types::Byte(8);
let value = Types::Byte(9);
let mut obj = Object::new("hi".into());
obj.set_value(key, value);
}
#[test]
fn property_read() {
let key = Types::new("name");
let mut obj = Object::new("hi".into());
obj.set_value("name".into(), "hi".into()).unwrap();
let ret = obj.get_value(key);
match ret {
Ok(val) => assert_eq!(val, Types::new("hi")),
Err(_err) => todo!(),
}
}
}
#[inline]
fn type_of<T>(_: &T) -> &str {
core::any::type_name::<T>()
}

View file

@ -1,48 +0,0 @@
use core::fmt::Debug;
use core::fmt::Display;
use alloc::string::{String, ToString};
use super::type_of;
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub enum Types {
Null,
Byte(u8),
String(String),
}
impl Types {
pub fn new<T: Debug + Display>(value: T) -> Self {
let type_of = type_of(&value);
match type_of {
"&str" => return Self::String(value.to_string()),
"alloc::string::String" => return Self::String(value.to_string()),
type_name => {
panic!(
"
Invalid type: {}
{}",
value, type_name
);
}
}
}
}
impl From<u8> for Types {
fn from(value: u8) -> Self {
Self::Byte(value)
}
}
impl From<String> for Types {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<&str> for Types {
fn from(value: &str) -> Self {
Self::String(value.to_string())
}
}