WIP: serialization/deserialization of datum in VM
All checks were successful
per-push tests / build (push) Successful in 1m52s
per-push tests / test-utility (push) Successful in 58s
per-push tests / test-frontend (push) Successful in 1m52s
per-push tests / test-backend (push) Successful in 1m0s
per-push tests / timed-decomposer-parse (push) Successful in 1m2s

Additionally: make release target binaries smaller and faster

Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
Ava Apples Affine 2025-08-26 17:11:37 +00:00
parent 0f85292e6f
commit fea950ea17
4 changed files with 236 additions and 3 deletions

View file

@ -21,6 +21,8 @@ extern crate alloc;
use alloc::string::String;
use alloc::format;
use alloc::fmt::Debug;
use alloc::vec;
use alloc::vec::Vec;
use core::{cmp::Ordering, f64, ops::{Add, Div, Mul, Sub}, str::FromStr};
use num::{integer::{gcd}, pow::Pow};
@ -250,6 +252,96 @@ impl FromStr for Number {
}
}
// this looks rushed and it is
// would rather work on organelles replacement than improve this
impl Into<Vec<u8>> for Number {
fn into(self) -> Vec<u8> {
let mut out = vec![];
match self {
Number::Sci(num) => {
out.push(0x00);
for ele in num.0.to_be_bytes().iter() {
out.push(*ele);
}
for ele in num.1.to_be_bytes().iter() {
out.push(*ele);
}
out
},
Number::Flt(num) => {
out.push(0x01 as u8);
for ele in num.0.to_be_bytes().iter() {
out.push(*ele);
}
out
},
Number::Fra(num) => {
out.push(0x02);
for ele in num.0.to_be_bytes().iter() {
out.push(*ele);
}
for ele in num.1.to_be_bytes().iter() {
out.push(*ele);
}
out
},
Number::Sym(num) => {
match num {
SymbolicNumber::Inf => out.push(0x03),
SymbolicNumber::NaN => out.push(0x04),
SymbolicNumber::NegInf => out.push(0x05),
SymbolicNumber::NegNan => out.push(0x06),
}
out
}
}
}
}
// same as the Into impl
impl TryFrom<&[u8]> for Number {
type Error = &'static str;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
match value[0] {
0x03 => Ok(Number::Sym(SymbolicNumber::Inf)),
0x04 => Ok(Number::Sym(SymbolicNumber::NaN)),
0x05 => Ok(Number::Sym(SymbolicNumber::NegInf)),
0x06 => Ok(Number::Sym(SymbolicNumber::NegNan)),
0x00 if value.len() >= (1 + 4 + (isize::BITS / 8)) as usize => {
let mut i: [u8; 4] = [0, 0, 0, 0];
value[1..5].iter().zip(i.iter_mut())
.for_each(|(a, b)| { *b = *a });
let i = f32::from_be_bytes(i);
let mut j: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
value[5..13].iter().zip(j.iter_mut())
.for_each(|(a, b)| { *b = *a });
let j = isize::from_be_bytes(j);
Ok(Number::Sci(ScientificNotation(i, j)))
},
0x01 if value.len() >= 9 as usize => {
let mut i: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
value[1..9].iter().zip(i.iter_mut())
.for_each(|(a, b)| { *b = *a });
let i = f64::from_be_bytes(i);
Ok(Number::Flt(Float(i)))
},
0x02 if value.len() >= 1 + ((isize::BITS / 8) * 2) as usize => {
let mut i: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
value[1..9].iter().zip(i.iter_mut())
.for_each(|(a, b)| { *b = *a });
let i = isize::from_be_bytes(i);
let mut j: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
value[9..17].iter().zip(j.iter_mut())
.for_each(|(a, b)| { *b = *a });
let j = isize::from_be_bytes(j);
Ok(Number::Fra(Fraction(i, j)))
},
_ => Err("attempted to deserialize invalid number format")
}
}
}
impl Add for Number {
type Output = Number;
fn add(self, rhs: Self) -> Self::Output {
@ -596,6 +688,22 @@ impl Numeric for ScientificNotation {
mod tests {
use super::*;
#[test]
fn serialize_deserialize_tests() {
let cases = vec![
"2/3".parse::<Number>().unwrap(),
"-4/5".parse::<Number>().unwrap(),
"2e45".parse::<Number>().unwrap(),
"1.2432566".parse::<Number>().unwrap(),
"+inf.0".parse::<Number>().unwrap(),
];
for i in cases.iter() {
let j = Into::<Vec<u8>>::into(*i);
assert_eq!(*i, Number::try_from(j.as_slice()).unwrap());
}
}
#[test]
fn parse_fraction_tests() {
assert_eq!("2/3".parse::<Fraction>(),