diff --git a/src/bin/decimal.rs b/src/bin/decimal.rs deleted file mode 100644 index 5c0bf79..0000000 --- a/src/bin/decimal.rs +++ /dev/null @@ -1,133 +0,0 @@ -#![allow(dead_code)] - -#[derive(Clone, Copy)] -struct Decimal { - data:i64, -} -impl Decimal { - pub fn new() -> Self - { - Self { data:0 } - } - - pub fn with(value:f64) -> Self - { - let whole = value as i64; - let decimal = ((value - value.trunc()).abs() * (1i64 << E) as f64).floor() as i64; - Self { - data:(whole << E) + (decimal as i64), - } - } - - pub fn from(other:&Decimal) -> Self - { - let data :i64; - if E > D { data = other.data << (E - D); } - else if D > E { data = other.data >> (D - E); } - else { data = other.data; } - - Self { data:data } - } - - pub fn from_raw(data:i64) -> Self - { - Self { data:data } - } - - pub fn raw(&self) -> i64 - { - self.data - } - - pub fn f32(&self) -> f32 - { - (self.data >> E) as f32 + ((self.data & ((1i64 << E) - 1)) as f32 / (1i64 << E) as f32) - } - - pub fn f64(&self) -> f64 - { - (self.data >> E) as f64 + ((self.data & ((1i64 << E) - 1)) as f64 / (1i64 << E) as f64) - } -} -impl std::ops::Add for Decimal { - type Output = Self; - fn add(self, rhs: Self) -> Self::Output { - Decimal::::from_raw(self.data + rhs.data) - } -} -impl std::ops::AddAssign for Decimal { - fn add_assign(&mut self, rhs: Self) { - self.data += rhs.data; - } -} -impl std::ops::Sub for Decimal { - type Output = Self; - fn sub(self, rhs: Self) -> Self::Output { - Decimal::::from_raw(self.data - rhs.data) - } -} -impl std::ops::SubAssign for Decimal { - fn sub_assign(&mut self, rhs: Self) { - self.data -= rhs.data; - } -} -impl std::ops::Mul for Decimal { - type Output = Self; - fn mul(self, rhs: Self) -> Self::Output { - Decimal::::from_raw(((self.data as i128 * rhs.data as i128) >> E) as i64) - } -} -impl std::ops::MulAssign for Decimal { - fn mul_assign(&mut self, rhs: Self) { - self.data = ((self.data as i128 * rhs.data as i128) >> E) as i64; - } -} -impl std::ops::Div for Decimal { - type Output = Self; - fn div(self, rhs: Self) -> Self::Output { - Decimal::::from_raw(((self.data as i128 * (1i64 << E) as i128) / rhs.data as i128) as i64) - } -} -impl std::ops::DivAssign for Decimal { - fn div_assign(&mut self, rhs: Self) { - self.data = ((self.data as i128 * (1i64 << E) as i128) / rhs.data as i128) as i64; - } -} -impl std::ops::Rem for Decimal { - type Output = Self; - fn rem(self, rhs: Self) -> Self::Output { - Decimal::::from_raw(((self.data as i128 * (1i64 << E) as i128) % rhs.data as i128) as i64) - } -} -impl std::ops::RemAssign for Decimal { - fn rem_assign(&mut self, rhs: Self) { - self.data = ((self.data as i128 * (1i64 << E) as i128) % rhs.data as i128) as i64; - } -} -impl std::ops::Neg for Decimal { - type Output = Self; - fn neg(self) -> Self::Output { - Decimal::::from_raw(-self.data) - } -} - -fn print_bytes(bytes:&Vec) -{ - for b in bytes { - print!("{:02x} ", b); - } print!("\n"); -} - -fn main() -{ - let a = Decimal::<16>::with(5.0); - let b = Decimal::<16>::with(3.0); - println!("a = {}", a.f64()); - println!("b = {}", b.f64()); - println!("add = {}", (a + b).f64()); - println!("sub = {}", (a - b).f64()); - println!("mul = {}", (a * b).f64()); - println!("div = {}", (a / b).f64()); - println!("rem = {}", (a % b).f64()); - println!("neg = {}", (-a).f64()); -} diff --git a/src/bin/main.rs b/src/bin/main.rs index 52a9164..9b926c8 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,63 +1,19 @@ fn main() { - use std::fs::File; - use std::io::prelude::*; + let a = szun::Decimal::with(32, 18.5); + let b = szun::Decimal::with(24, 6.0); - const MAGAZINE :usize = 0x100; - const MAGAZINE_ROW :usize = 0x101; - - // define schema "Magazine" - let magazine = szun::Schema::with(vec![ - ("Capacity", szun::natural()), - ("Quantity", szun::natural()), - ("Content", szun::list(szun::record(MAGAZINE_ROW))), - ]); - magazine.bind(MAGAZINE); - - // define schema "Magazine Row" - szun::Schema::with(vec![ - ("Content", szun::natural()), - ("Quantity", szun::natural()), - ]).bind(MAGAZINE_ROW); - - // create record "Magazine" - let _data = szun::Record::with(MAGAZINE, vec![ - ("Capacity", *szun::Natural::with(30)), - ("Quantity", *szun::Natural::with(25)), - ("Content", *szun::List::with(szun::record(MAGAZINE_ROW), vec![ - *szun::Record::with(MAGAZINE_ROW, vec![ - ("Content", *szun::Natural::with(15)), - ("Quantity", *szun::Natural::with(5)), - ]).unwrap(), - *szun::Record::with(MAGAZINE_ROW, vec![ - ("Content", *szun::Natural::with(16)), - ("Quantity", *szun::Natural::with(20)), - ]).unwrap(), - ])), - ]).unwrap(); - - // encode record - let out = szun::encode(*magazine); - - // write encoding to file - let mut file = File::create("target/dat.szn").unwrap(); - file.write_all(&out).ok(); - - // print hex series of encoding - print!("[{}]: ", out.len()); - for byte in &out { - print!("{:02x} ", *byte); - } println!(""); - - match szun::decode(&out, &mut 0) { - Ok(t) => match t { - szun::Type::Schema(data) => { - println!("len: {}", data.length()); - for i in 0..data.length() { - println!("'{}': {} ({:02x})", data.keyof(i).unwrap(), data.get(i).unwrap(), szun::kind(data.get(i).unwrap())); - } - } - _ => { println!("not expected"); } - } - Err(_) => { println!("failed"); } - } + println!("A = {} (.{})", a.get(), a.exponent()); + println!("B = {} (.{})", b.get(), b.exponent()); + print!("\n"); + println!("A + B = {}", (a.copy() + b.copy()).get()); + println!("A - B = {}", (a.copy() - b.copy()).get()); + println!("A * B = {}", (a.copy() * b.copy()).get()); + println!("A / B = {}", (a.copy() / b.copy()).get()); + println!("A % B = {}", (a.copy() % b.copy()).get()); + print!("\n"); + println!("B + A = {}", (b.copy() + a.copy()).get()); + println!("B - A = {}", (b.copy() - a.copy()).get()); + println!("B * A = {}", (b.copy() * a.copy()).get()); + println!("B / A = {}", (b.copy() / a.copy()).get()); + println!("B % A = {}", (b.copy() % a.copy()).get()); } diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs index 45acda5..3367667 100644 --- a/src/encoding/mod.rs +++ b/src/encoding/mod.rs @@ -44,31 +44,31 @@ pub fn encode_data(addr:Reference) -> Vec let mut result = Vec::::new(); match unsafe {type_key(addr.class)} { tag::VARYING => { - let data = Varying::from(addr).unwrap(); + let data = Varying::try_from(addr).unwrap(); result.append(&mut encode(data.get())); } tag::BOOLEAN => { - result.append(&mut util::pack_natural(Boolean::from(addr).unwrap().get() as u64)); + result.append(&mut util::pack_natural(Boolean::try_from(addr).unwrap().get() as u64)); } tag::NATURAL => { - result.append(&mut util::pack_natural(Natural::from(addr).unwrap().get() as u64)); + result.append(&mut util::pack_natural(Natural::try_from(addr).unwrap().get() as u64)); } tag::INTEGER => { - result.append(&mut &mut util::pack_integer(Integer::from(addr).unwrap().get() as i64)); + result.append(&mut &mut util::pack_integer(Integer::try_from(addr).unwrap().get() as i64)); } tag::SIGNIFICANT => { result.append(&mut vec![0]); } tag::BLOCK => { - result.append(&mut Block::from(addr).unwrap().get()); + result.append(&mut Block::try_from(addr).unwrap().get()); } tag::SEQUENCE => { - let data = Sequence::from(addr).unwrap(); + let data = Sequence::try_from(addr).unwrap(); result.append(&mut util::pack_natural(data.size() as u64)); result.append(&mut data.get_raw()); } tag::ARRAY => { - let data = Array::from(addr).unwrap(); + let data = Array::try_from(addr).unwrap(); for i in 0..data.length() { if unsafe {type_innerkey(addr.class)} == tag::VARYING { result.append(&mut encode(data.at(i))); @@ -79,7 +79,7 @@ pub fn encode_data(addr:Reference) -> Vec } } tag::LIST => { - let data = List::from(addr).unwrap(); + let data = List::try_from(addr).unwrap(); result.append(&mut util::pack_natural(data.length() as u64)); for i in 0..data.length() { if unsafe {type_innerkey(addr.class)} == tag::VARYING { @@ -91,7 +91,7 @@ pub fn encode_data(addr:Reference) -> Vec } } tag::SPARSE => { - let data = crate::Sparse::from(addr).unwrap(); + let data = crate::Sparse::try_from(addr).unwrap(); let header_length = unsafe {runtime::sparse_header_length(addr)}; @@ -114,7 +114,7 @@ pub fn encode_data(addr:Reference) -> Vec } } tag::RECORD => { - let data = Record::from(addr).unwrap(); + let data = Record::try_from(addr).unwrap(); for i in 0..data.length() { if kind(data.kindof(i)) == tag::VARYING { result.append(&mut encode(data.at(i))); @@ -125,7 +125,7 @@ pub fn encode_data(addr:Reference) -> Vec } } tag::SCHEMA => { - let data = Schema::from(addr).unwrap(); + let data = Schema::try_from(addr).unwrap(); result.append(&mut util::pack_natural(data.length() as u64)); diff --git a/src/interface/array.rs b/src/interface/array.rs index a2899f7..01db1a6 100644 --- a/src/interface/array.rs +++ b/src/interface/array.rs @@ -34,16 +34,6 @@ impl Array { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::ARRAY) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(length:usize, class:usize, data:Vec) -> Self { let mut obj = Self::new(length, class); @@ -73,6 +63,17 @@ impl Array { unsafe {type_inner(self.addr.class)} } } +impl TryFrom for Array { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::ARRAY) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Array { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/block.rs b/src/interface/block.rs index 2053ba6..19d461e 100644 --- a/src/interface/block.rs +++ b/src/interface/block.rs @@ -21,16 +21,6 @@ impl Block { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::BLOCK) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(size:usize, data:Vec) -> Self { let mut obj = Self::new(size); @@ -64,6 +54,17 @@ impl Block { return result; } } +impl TryFrom for Block { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::BLOCK) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Block { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/boolean.rs b/src/interface/boolean.rs index c9b29e2..e4debfd 100644 --- a/src/interface/boolean.rs +++ b/src/interface/boolean.rs @@ -20,21 +20,11 @@ impl Boolean { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::BOOLEAN) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(value:bool) -> Self { - let mut obj = Self::new(); - obj.set(value); - return obj; + let mut result = Self::new(); + result.set(value); + return result; } pub fn set(&mut self, value:bool) @@ -47,6 +37,17 @@ impl Boolean { unsafe { bool_get(self.addr) } } } +impl TryFrom for Boolean { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::BOOLEAN) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Boolean { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } @@ -54,3 +55,8 @@ impl std::ops::Deref for Boolean { impl Drop for Boolean { fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } } +impl Into for Boolean { + fn into(self) -> bool { + self.get() + } +} diff --git a/src/interface/builder.rs b/src/interface/builder.rs index 4c868e1..1597830 100644 --- a/src/interface/builder.rs +++ b/src/interface/builder.rs @@ -11,6 +11,13 @@ pub fn natural() -> usize { unsafe { runtime::type_outer(0, tag::NATURAL) } } pub fn integer() -> usize { unsafe { runtime::type_outer(0, tag::INTEGER) } } pub fn significant() -> usize { unsafe { runtime::type_outer(0, tag::SIGNIFICANT) } } +pub fn decimal(exponent:usize) -> usize { + unsafe { + let inner_node = runtime::type_outer(0, exponent); + runtime::type_outer(inner_node, tag::DECIMAL) + } +} + pub fn block(size:usize) -> usize { unsafe { let inner_node = runtime::type_outer(0, size); diff --git a/src/interface/decimal.rs b/src/interface/decimal.rs new file mode 100644 index 0000000..fcd42e6 --- /dev/null +++ b/src/interface/decimal.rs @@ -0,0 +1,229 @@ +use crate::runtime::{ + Reference, + acquire, release, + type_key, + decimal_get, decimal_set, type_innerkey, +}; +use crate::tag; +use super::decimal; + +pub struct Decimal { + managed:bool, + addr:Reference, +} +impl Decimal { + pub fn new(exponent:usize) -> Self + { + Self { + managed:true, + addr:unsafe {acquire(decimal(exponent))}, + } + } + + fn with_raw(exponent:usize, data:i64) -> Self + { + let mut obj = Self::new(exponent); + obj.set_raw(data); + return obj; + } + + pub fn with(exponent:usize, value:f64) -> Self + { + let mut obj = Self::new(exponent); + obj.set(value); + return obj; + } + + pub fn copy(&self) -> Self + { + Decimal::try_from(self.addr).unwrap() + } + + fn set_raw(&mut self, data:i64) + { + unsafe { decimal_set(self.addr, data) }; + } + + pub fn set(&mut self, value:f64) + { + let exponent = unsafe {type_innerkey(self.addr.class)}; + let whole = value as i64; + let decimal = ((value - value.trunc()).abs() * (1i64 << exponent) as f64).floor() as i64; + let data = (whole << exponent) + (decimal as i64); + self.set_raw(data); + } + + fn get_raw(&self) -> i64 + { + unsafe {decimal_get(self.addr)} + } + + pub fn get(&self) -> f64 + { + let exponent = unsafe {type_innerkey(self.addr.class)}; + let data = self.get_raw(); + (data >> exponent) as f64 + ((data & ((1i64 << exponent) - 1)) as f64 / (1i64 << exponent) as f64) + } + + fn rebase(to:usize, from:usize, data:i64) -> i64 + { + return if to > from { + data << (to - from) as i64 + } else if to < from { + data >> (from - to) as i64 + } else { data } + } + + pub fn to_base(&self, exponent:usize) -> Self + { + let from_exp = self.exponent(); + let mut result = Decimal::new(exponent); + result.set_raw(Self::rebase(from_exp, exponent, self.get_raw())); + return result; + } + + pub fn exponent(&self) -> usize + { + unsafe {type_innerkey(self.addr.class)} + } +} +impl Clone for Decimal { + fn clone(&self) -> Self { + Decimal::with_raw(self.exponent(), self.get_raw()) + } +} +impl std::ops::Add for Decimal { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + Decimal::with_raw(lhe, lhd + rhd) + } +} +impl std::ops::AddAssign for Decimal { + fn add_assign(&mut self, rhs: Self) { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + self.set_raw(lhd + rhd); + } +} +impl std::ops::Sub for Decimal { + type Output = Self; + fn sub(self, rhs: Self) -> Self::Output { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + Decimal::with_raw(lhe, lhd - rhd) + } +} +impl std::ops::SubAssign for Decimal { + fn sub_assign(&mut self, rhs: Self) { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + self.set_raw(lhd - rhd); + } +} +impl std::ops::Mul for Decimal { + type Output = Self; + fn mul(self, rhs: Self) -> Self::Output { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + Decimal::with_raw(lhe, ((lhd as i128 * rhd as i128) >> lhe) as i64) + } +} +impl std::ops::MulAssign for Decimal { + fn mul_assign(&mut self, rhs: Self) { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + self.set_raw(((lhd as i128 * rhd as i128) >> lhe) as i64); + } +} +impl std::ops::Div for Decimal { + type Output = Self; + fn div(self, rhs: Self) -> Self::Output { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + Decimal::with_raw(lhe, ((lhd as i128 * (1i64 << lhe) as i128) / rhd as i128) as i64) + } +} +impl std::ops::DivAssign for Decimal { + fn div_assign(&mut self, rhs: Self) { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + self.set_raw(((lhd as i128 * (1i64 << lhe) as i128) / rhd as i128) as i64); + } +} +impl std::ops::Rem for Decimal { + type Output = Self; + fn rem(self, rhs: Self) -> Self::Output { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + Decimal::with_raw(lhe, (lhd as i128 % rhd as i128) as i64) + } +} +impl std::ops::RemAssign for Decimal { + fn rem_assign(&mut self, rhs: Self) { + let lhe = unsafe {type_innerkey(self.addr.class)}; + let rhe = unsafe {type_innerkey(rhs.addr.class)}; + let lhd = self.get_raw(); + let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); + + self.set_raw(((lhd as i128 * (1i64 << lhe) as i128) % rhd as i128) as i64); + } +} +impl std::ops::Neg for Decimal { + type Output = Self; + fn neg(self) -> Self::Output { + let exponent = unsafe {type_innerkey(self.addr.class)}; + Decimal::with_raw(exponent, -self.get_raw()) + } +} +impl std::ops::Deref for Decimal { + type Target = Reference; + fn deref(&self) -> &Self::Target { return &self.addr; } +} +impl Drop for Decimal { + fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } +} +impl TryFrom for Decimal { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::DECIMAL) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} +impl Into for Decimal { + fn into(self) -> f64 { + self.get() + } +} diff --git a/src/interface/integer.rs b/src/interface/integer.rs index f5605bb..c6cd588 100644 --- a/src/interface/integer.rs +++ b/src/interface/integer.rs @@ -20,16 +20,6 @@ impl Integer { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::INTEGER) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(value:i64) -> Self { let mut obj = Self::new(); @@ -47,6 +37,17 @@ impl Integer { unsafe { integer_get(self.addr) } } } +impl TryFrom for Integer { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::INTEGER) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Integer { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } @@ -54,3 +55,4 @@ impl std::ops::Deref for Integer { impl Drop for Integer { fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } } + diff --git a/src/interface/list.rs b/src/interface/list.rs index 4fbdbf1..148ff6f 100644 --- a/src/interface/list.rs +++ b/src/interface/list.rs @@ -25,16 +25,6 @@ impl List { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::LIST) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(type_id:usize, data:Vec) -> Self { let mut obj = Self::new(type_id); @@ -108,6 +98,17 @@ impl List { unsafe {type_inner(self.addr.class)} } } +impl TryFrom for List { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::LIST) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for List { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 6da38fe..aebd74d 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -8,6 +8,7 @@ mod varying; pub use varying::Varying; mod boolean; pub use boolean::Boolean; mod natural; pub use natural::Natural; mod integer; pub use integer::Integer; +mod decimal; pub use decimal::Decimal; mod signficant; pub use signficant::Significant; mod block; pub use block::Block; mod sequence; pub use sequence::Sequence; @@ -23,6 +24,8 @@ pub enum Type { Boolean(Boolean), Natural(Natural), Integer(Integer), + Decimal(Decimal), + Significant(Significant), Block(Block), Sequence(Sequence), Array(Array), @@ -36,16 +39,18 @@ impl Type { { match unsafe {type_key(addr.class)} { tag::NULL => Type::Null, - tag::VARYING => Type::Varying(Varying::from(addr).unwrap()), - tag::BOOLEAN => Type::Boolean(Boolean::from(addr).unwrap()), - tag::NATURAL => Type::Natural(Natural::from(addr).unwrap()), - tag::INTEGER => Type::Integer(Integer::from(addr).unwrap()), - tag::BLOCK => Type::Block(Block::from(addr).unwrap()), - tag::SEQUENCE => Type::Sequence(Sequence::from(addr).unwrap()), - tag::ARRAY => Type::Array(Array::from(addr).unwrap()), - tag::LIST => Type::List(List::from(addr).unwrap()), - tag::SPARSE => Type::Sparse(Sparse::from(addr).unwrap()), - tag::RECORD => Type::Record(Record::from(addr).unwrap()), + tag::VARYING => Type::Varying(Varying::try_from(addr).unwrap()), + tag::BOOLEAN => Type::Boolean(Boolean::try_from(addr).unwrap()), + tag::NATURAL => Type::Natural(Natural::try_from(addr).unwrap()), + tag::INTEGER => Type::Integer(Integer::try_from(addr).unwrap()), + tag::DECIMAL => Type::Decimal(Decimal::try_from(addr).unwrap()), + tag::SIGNIFICANT => Type::Significant(Significant::try_from(addr).unwrap()), + tag::BLOCK => Type::Block(Block::try_from(addr).unwrap()), + tag::SEQUENCE => Type::Sequence(Sequence::try_from(addr).unwrap()), + tag::ARRAY => Type::Array(Array::try_from(addr).unwrap()), + tag::LIST => Type::List(List::try_from(addr).unwrap()), + tag::SPARSE => Type::Sparse(Sparse::try_from(addr).unwrap()), + tag::RECORD => Type::Record(Record::try_from(addr).unwrap()), _ => Type::Null, } } @@ -57,6 +62,8 @@ impl Type { Type::Boolean(obj) => **obj, Type::Natural(obj) => **obj, Type::Integer(obj) => **obj, + Type::Decimal(obj) => **obj, + Type::Significant(obj) => **obj, Type::Block(obj) => **obj, Type::Sequence(obj) => **obj, Type::Array(obj) => **obj, diff --git a/src/interface/natural.rs b/src/interface/natural.rs index 007cb51..2aefe7d 100644 --- a/src/interface/natural.rs +++ b/src/interface/natural.rs @@ -20,16 +20,6 @@ impl Natural { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::NATURAL) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(value:u64) -> Self { let mut obj = Self::new(); @@ -47,6 +37,17 @@ impl Natural { unsafe { natural_get(self.addr) } } } +impl TryFrom for Natural { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::NATURAL) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Natural { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/record.rs b/src/interface/record.rs index 96ed0e0..0d23822 100644 --- a/src/interface/record.rs +++ b/src/interface/record.rs @@ -28,15 +28,6 @@ impl Record { Err(()) } } - - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::RECORD) { - Ok(Self { managed:false, addr:addr }) - } else { - Err(()) - } - } pub fn with(schema:usize, data:Vec<(&str, Reference)>) -> Result { @@ -126,6 +117,17 @@ impl Record { unsafe {record_type(self.addr, index)} } } +impl TryFrom for Record { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::RECORD) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Record { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/schema.rs b/src/interface/schema.rs index a9651fb..880b94d 100644 --- a/src/interface/schema.rs +++ b/src/interface/schema.rs @@ -25,16 +25,6 @@ impl Schema { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::SCHEMA) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(members:Vec<(&str, usize)>) -> Self { let mut obj = Self::new(); @@ -135,6 +125,17 @@ impl Schema { unsafe {schema_bind(self.addr, id)} } } +impl TryFrom for Schema { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::SCHEMA) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Schema { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/sequence.rs b/src/interface/sequence.rs index 1a9e02f..3973226 100644 --- a/src/interface/sequence.rs +++ b/src/interface/sequence.rs @@ -23,16 +23,6 @@ impl Sequence { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::SEQUENCE) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with_raw(data:Vec) -> Self { let mut obj = Self::new(); @@ -105,6 +95,17 @@ impl Sequence { } } } +impl TryFrom for Sequence { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::SEQUENCE) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Sequence { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/signficant.rs b/src/interface/signficant.rs index 53068d1..69e1d4e 100644 --- a/src/interface/signficant.rs +++ b/src/interface/signficant.rs @@ -20,16 +20,6 @@ impl Significant { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::SIGNIFICANT) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(value:f64) -> Self { let mut obj = Self::new(); @@ -47,6 +37,17 @@ impl Significant { unsafe { significant_get(self.addr) } } } +impl TryFrom for Significant { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::SIGNIFICANT) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Significant { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/sparse.rs b/src/interface/sparse.rs index eabb4de..cf1d18e 100644 --- a/src/interface/sparse.rs +++ b/src/interface/sparse.rs @@ -24,16 +24,6 @@ impl Sparse { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::SPARSE) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(class:usize, data:Vec<(usize, Reference)>) -> Self { let mut obj = Self::new(class); @@ -88,6 +78,17 @@ impl Sparse { unsafe {type_inner(self.addr.class)} } } +impl TryFrom for Sparse { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::SPARSE) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Sparse { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/interface/varying.rs b/src/interface/varying.rs index 2be34bf..d7d0607 100644 --- a/src/interface/varying.rs +++ b/src/interface/varying.rs @@ -21,16 +21,6 @@ impl Varying { } } - pub fn from(addr:Reference) -> Result - { - return if(unsafe {type_key(addr.class)} == tag::VARYING) { - Ok(Self { managed:false, addr:addr }) - } - else { - Err(()) - } - } - pub fn with(addr:Reference) -> Self { let mut obj = Varying::new(); @@ -63,6 +53,17 @@ impl Varying { unsafe {varying_get(self.addr).class} } } +impl TryFrom for Varying { + type Error = (); + fn try_from(addr:Reference) -> Result { + return if(unsafe {type_key(addr.class)} == tag::VARYING) { + Ok(Self { managed:false, addr:addr }) + } + else { + Err(()) + } + } +} impl std::ops::Deref for Varying { type Target = Reference; fn deref(&self) -> &Self::Target { return &self.addr; } diff --git a/src/lib.rs b/src/lib.rs index 82f2726..3f7e52b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,69 +6,5 @@ mod runtime; mod interface; pub use interface::*; mod encoding; pub use encoding::*; -/* pub fn test() { - use std::fs::File; - use std::io::prelude::*; - - const MAGAZINE :usize = 0x100; - const MAGAZINE_ROW :usize = 0x101; - - // define schema "Magazine Row" - Schema::with(vec![ - ("Content", natural()), - ("Quantity", natural()), - ]).bind(MAGAZINE_ROW); - - // define schema "Magazine" - let magazine = Schema::with(vec![ - ("Capacity", natural()), - ("Quantity", natural()), - ("Content", list(record(MAGAZINE_ROW))), - ]); - magazine.bind(MAGAZINE); - - // create record "Magazine" - let _data = Record::with(MAGAZINE, vec![ - ("Capacity", *Natural::with(30)), - ("Quantity", *Natural::with(25)), - ("Content", *List::with(record(MAGAZINE_ROW), vec![ - *Record::with(MAGAZINE_ROW, vec![ - ("Content", *Natural::with(15)), - ("Quantity", *Natural::with(5)), - ]).unwrap(), - *Record::with(MAGAZINE_ROW, vec![ - ("Content", *Natural::with(16)), - ("Quantity", *Natural::with(20)), - ]).unwrap(), - ])), - ]).unwrap(); - - // encode record - let out = encode(*magazine); - - // write encoding to file - let mut file = File::create("target/dat.szn").unwrap(); - file.write_all(&out).ok(); - - // print hex series of encoding - print!("[{}]: ", out.len()); - for byte in &out { - print!("{:02x} ", *byte); - } println!(""); - - match decode(&out, &mut 0) { - Ok(t) => match t { - Type::Schema(data) => { - println!("len: {}", data.length()); - for i in 0..data.length() { - println!("'{}': {} ({:02x})", data.keyof(i).unwrap(), data.get(i).unwrap(), kind(data.get(i).unwrap())); - } - } - _ => { println!("not expected"); } - } - Err(_) => { println!("failed"); } - } -} */ - #[cfg(test)] mod tests; diff --git a/src/runtime/lib.cc b/src/runtime/lib.cc index 02a12ad..21cb391 100644 --- a/src/runtime/lib.cc +++ b/src/runtime/lib.cc @@ -34,14 +34,15 @@ extern "C" size_t type_size(size_t type_id) size_t type = DB_TYPE.key(type_id); switch(type) { - case Type::Tag::Null: return 0; - case Type::Tag::Varying: return sizeof(Reference); - case Type::Tag::Boolean: return sizeof(Type::Boolean); - case Type::Tag::Natural: return sizeof(Type::Natural); - case Type::Tag::Integer: return sizeof(Type::Integer); - case Type::Tag::Significant: return sizeof(Type::Integer); - case Type::Tag::Block: return type_innerkey(type_id); - case Type::Tag::Sequence: return sizeof(Type::Sequence); + case Type::Tag::Null: return 0; + case Type::Tag::Varying: return sizeof(Reference); + case Type::Tag::Boolean: return sizeof(Type::Boolean); + case Type::Tag::Natural: return sizeof(Type::Natural); + case Type::Tag::Integer: return sizeof(Type::Integer); + case Type::Tag::Significant: return sizeof(Type::Significant); + case Type::Tag::Decimal: return sizeof(Type::Decimal); + case Type::Tag::Block: return type_innerkey(type_id); + case Type::Tag::Sequence: return sizeof(Type::Sequence); case Type::Tag::Array: { size_t length = DB_TYPE.inner(type_id); @@ -95,6 +96,7 @@ size_t type_alignment(size_t type_id) case Type::Tag::Natural: return sizeof(Type::Natural); case Type::Tag::Integer: return sizeof(Type::Integer); case Type::Tag::Significant: return sizeof(Type::Significant); + case Type::Tag::Decimal: return sizeof(Type::Decimal); case Type::Tag::Block: return sizeof(uint8_t); case Type::Tag::Array: return type_alignment(type_inner(type_id)); @@ -119,6 +121,7 @@ extern "C" size_t kind_hasinner(size_t kind) switch(kind) { case Type::Tag::Array: return 2; + case Type::Tag::Decimal: case Type::Tag::Block: case Type::Tag::List: case Type::Tag::Sparse: @@ -517,6 +520,19 @@ extern "C" Type::Significant significant_get(Reference addr) } +// Decimal // + +extern "C" void decimal_set(Reference addr, Type::Decimal value) +{ + *(reinterpret_cast(addr.address)) = value; +} + +extern "C" Type::Decimal decimal_get(Reference addr) +{ + return *(reinterpret_cast(addr.address)); +} + + // Block // extern "C" size_t block_length(Reference addr) diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 5548ede..4b2264d 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -76,6 +76,9 @@ extern "C" { pub fn integer_set(addr:Reference, data:i64); pub fn integer_get(addr:Reference) -> i64; + pub fn decimal_set(addr:Reference, data:i64); + pub fn decimal_get(addr:Reference) -> i64; + pub fn significant_set(addr:Reference, data:f64); pub fn significant_get(addr:Reference) -> f64; diff --git a/src/runtime/type.h b/src/runtime/type.h index 0e49183..0ab7090 100644 --- a/src/runtime/type.h +++ b/src/runtime/type.h @@ -17,7 +17,7 @@ namespace Tag { Boolean = 0x02, Natural = 0x10, Integer = 0x11, - //Decimal = 0x12, + Decimal = 0x12, Significant = 0x13, Block = 0x1e, Sequence = 0x1f, @@ -32,6 +32,7 @@ namespace Tag { typedef bool Boolean; typedef uint64_t Natural; typedef int64_t Integer; +typedef int64_t Decimal; typedef double Significant; struct Sequence { diff --git a/src/tag.rs b/src/tag.rs index 4b42ad4..3e7c7cb 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -5,7 +5,7 @@ pub const VARYING :usize = 0x01; pub const BOOLEAN :usize = 0x02; pub const NATURAL :usize = 0x10; pub const INTEGER :usize = 0x11; -//pub const DECIMAL :usize = 0x12; +pub const DECIMAL :usize = 0x12; pub const SIGNIFICANT :usize = 0x13; //pub const COMPLEX :usize = 0x14; //pub const RANGE :usize = 0x1c; diff --git a/src/tests/list.rs b/src/tests/list.rs index ac8f315..db26efa 100644 --- a/src/tests/list.rs +++ b/src/tests/list.rs @@ -12,11 +12,11 @@ fn list_initialize() fn list_from() { let list = List::new(natural()); - let mut list_ref = List::from(*list).unwrap(); + let mut list_ref = List::try_from(*list).unwrap(); list_ref.append(*Natural::with(10)); assert_eq!(1, list.length(), "List has length 1 after append to reference."); - assert_eq!(10, Natural::from(list.at(0)).unwrap().get()); + assert_eq!(10, Natural::try_from(list.at(0)).unwrap().get()); } #[test] @@ -29,7 +29,7 @@ fn list_with() *Natural::with(20), ]); assert_eq!(4, list.length()); - assert_eq!(15, Natural::from(list.at(2)).unwrap().get()); + assert_eq!(15, Natural::try_from(list.at(2)).unwrap().get()); } #[test] @@ -71,8 +71,8 @@ fn list_prepend() assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3."); list.prepend(*Natural::with(0)); assert_eq!(4, list.length(), "List of 3 elements has length of 4 after prepend."); - assert_eq!(0, Natural::from(list.at(0)).unwrap().get(), "First element in list has value 0."); - assert_eq!(1000, Natural::from(list.at(1)).unwrap().get(), "Second element in list has value 1000."); + assert_eq!(0, Natural::try_from(list.at(0)).unwrap().get(), "First element in list has value 0."); + assert_eq!(1000, Natural::try_from(list.at(1)).unwrap().get(), "Second element in list has value 1000."); } #[test] @@ -86,8 +86,8 @@ fn list_append() assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3."); list.append(*Natural::with(4000)); assert_eq!(4, list.length(), "List of 3 elements has length of 4 after prepend."); - assert_eq!(3000, Natural::from(list.at(2)).unwrap().get(), "Third element in list has value 3000."); - assert_eq!(4000, Natural::from(list.at(3)).unwrap().get(), "Last element in list has value 4000.");} + assert_eq!(3000, Natural::try_from(list.at(2)).unwrap().get(), "Third element in list has value 3000."); + assert_eq!(4000, Natural::try_from(list.at(3)).unwrap().get(), "Last element in list has value 4000.");} #[test] fn list_set() @@ -99,7 +99,7 @@ fn list_set() ]); assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3."); list.set(1, *Natural::with(2)); - assert_eq!(2, Natural::from(list.at(1)).unwrap().get(), "Second element in list has value 2."); + assert_eq!(2, Natural::try_from(list.at(1)).unwrap().get(), "Second element in list has value 2."); } #[test] @@ -118,9 +118,9 @@ fn list_remove() list.remove(0); list.remove(2); assert_eq!(3, list.length(), "List with 3/6 elements removed has length of 3."); - assert_eq!(1, Natural::from(list.at(0)).unwrap().get(), "First element in list is 1."); - assert_eq!(2, Natural::from(list.at(1)).unwrap().get(), "Second element in list is 2."); - assert_eq!(4, Natural::from(list.at(2)).unwrap().get(), "Last element in list is 4."); + assert_eq!(1, Natural::try_from(list.at(0)).unwrap().get(), "First element in list is 1."); + assert_eq!(2, Natural::try_from(list.at(1)).unwrap().get(), "Second element in list is 2."); + assert_eq!(4, Natural::try_from(list.at(2)).unwrap().get(), "Last element in list is 4."); } #[test]