Refactor interface usages, add Decimal type.

This commit is contained in:
yukirij 2023-08-30 03:21:22 -07:00
parent cf5834a511
commit e7781c721f
24 changed files with 462 additions and 421 deletions

View File

@ -1,133 +0,0 @@
#![allow(dead_code)]
#[derive(Clone, Copy)]
struct Decimal<const E:u8> {
data:i64,
}
impl<const E:u8> Decimal<E> {
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<const D:u8>(other:&Decimal<D>) -> 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<const E:u8> std::ops::Add for Decimal<E> {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Decimal::<E>::from_raw(self.data + rhs.data)
}
}
impl<const E:u8> std::ops::AddAssign for Decimal<E> {
fn add_assign(&mut self, rhs: Self) {
self.data += rhs.data;
}
}
impl<const E:u8> std::ops::Sub for Decimal<E> {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Decimal::<E>::from_raw(self.data - rhs.data)
}
}
impl<const E:u8> std::ops::SubAssign for Decimal<E> {
fn sub_assign(&mut self, rhs: Self) {
self.data -= rhs.data;
}
}
impl<const E:u8> std::ops::Mul for Decimal<E> {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Decimal::<E>::from_raw(((self.data as i128 * rhs.data as i128) >> E) as i64)
}
}
impl<const E:u8> std::ops::MulAssign for Decimal<E> {
fn mul_assign(&mut self, rhs: Self) {
self.data = ((self.data as i128 * rhs.data as i128) >> E) as i64;
}
}
impl<const E:u8> std::ops::Div for Decimal<E> {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
Decimal::<E>::from_raw(((self.data as i128 * (1i64 << E) as i128) / rhs.data as i128) as i64)
}
}
impl<const E:u8> std::ops::DivAssign for Decimal<E> {
fn div_assign(&mut self, rhs: Self) {
self.data = ((self.data as i128 * (1i64 << E) as i128) / rhs.data as i128) as i64;
}
}
impl<const E:u8> std::ops::Rem for Decimal<E> {
type Output = Self;
fn rem(self, rhs: Self) -> Self::Output {
Decimal::<E>::from_raw(((self.data as i128 * (1i64 << E) as i128) % rhs.data as i128) as i64)
}
}
impl<const E:u8> std::ops::RemAssign for Decimal<E> {
fn rem_assign(&mut self, rhs: Self) {
self.data = ((self.data as i128 * (1i64 << E) as i128) % rhs.data as i128) as i64;
}
}
impl<const E:u8> std::ops::Neg for Decimal<E> {
type Output = Self;
fn neg(self) -> Self::Output {
Decimal::<E>::from_raw(-self.data)
}
}
fn print_bytes(bytes:&Vec<u8>)
{
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());
}

View File

@ -1,63 +1,19 @@
fn main() { fn main() {
use std::fs::File; let a = szun::Decimal::with(32, 18.5);
use std::io::prelude::*; let b = szun::Decimal::with(24, 6.0);
const MAGAZINE :usize = 0x100; println!("A = {} (.{})", a.get(), a.exponent());
const MAGAZINE_ROW :usize = 0x101; println!("B = {} (.{})", b.get(), b.exponent());
print!("\n");
// define schema "Magazine" println!("A + B = {}", (a.copy() + b.copy()).get());
let magazine = szun::Schema::with(vec![ println!("A - B = {}", (a.copy() - b.copy()).get());
("Capacity", szun::natural()), println!("A * B = {}", (a.copy() * b.copy()).get());
("Quantity", szun::natural()), println!("A / B = {}", (a.copy() / b.copy()).get());
("Content", szun::list(szun::record(MAGAZINE_ROW))), println!("A % B = {}", (a.copy() % b.copy()).get());
]); print!("\n");
magazine.bind(MAGAZINE); println!("B + A = {}", (b.copy() + a.copy()).get());
println!("B - A = {}", (b.copy() - a.copy()).get());
// define schema "Magazine Row" println!("B * A = {}", (b.copy() * a.copy()).get());
szun::Schema::with(vec![ println!("B / A = {}", (b.copy() / a.copy()).get());
("Content", szun::natural()), println!("B % A = {}", (b.copy() % a.copy()).get());
("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"); }
}
} }

View File

@ -44,31 +44,31 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
let mut result = Vec::<u8>::new(); let mut result = Vec::<u8>::new();
match unsafe {type_key(addr.class)} { match unsafe {type_key(addr.class)} {
tag::VARYING => { tag::VARYING => {
let data = Varying::from(addr).unwrap(); let data = Varying::try_from(addr).unwrap();
result.append(&mut encode(data.get())); result.append(&mut encode(data.get()));
} }
tag::BOOLEAN => { 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 => { 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 => { 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 => { tag::SIGNIFICANT => {
result.append(&mut vec![0]); result.append(&mut vec![0]);
} }
tag::BLOCK => { tag::BLOCK => {
result.append(&mut Block::from(addr).unwrap().get()); result.append(&mut Block::try_from(addr).unwrap().get());
} }
tag::SEQUENCE => { 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 util::pack_natural(data.size() as u64));
result.append(&mut data.get_raw()); result.append(&mut data.get_raw());
} }
tag::ARRAY => { tag::ARRAY => {
let data = Array::from(addr).unwrap(); let data = Array::try_from(addr).unwrap();
for i in 0..data.length() { for i in 0..data.length() {
if unsafe {type_innerkey(addr.class)} == tag::VARYING { if unsafe {type_innerkey(addr.class)} == tag::VARYING {
result.append(&mut encode(data.at(i))); result.append(&mut encode(data.at(i)));
@ -79,7 +79,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
tag::LIST => { 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)); result.append(&mut util::pack_natural(data.length() as u64));
for i in 0..data.length() { for i in 0..data.length() {
if unsafe {type_innerkey(addr.class)} == tag::VARYING { if unsafe {type_innerkey(addr.class)} == tag::VARYING {
@ -91,7 +91,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
tag::SPARSE => { 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)}; let header_length = unsafe {runtime::sparse_header_length(addr)};
@ -114,7 +114,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
tag::RECORD => { tag::RECORD => {
let data = Record::from(addr).unwrap(); let data = Record::try_from(addr).unwrap();
for i in 0..data.length() { for i in 0..data.length() {
if kind(data.kindof(i)) == tag::VARYING { if kind(data.kindof(i)) == tag::VARYING {
result.append(&mut encode(data.at(i))); result.append(&mut encode(data.at(i)));
@ -125,7 +125,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
tag::SCHEMA => { 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)); result.append(&mut util::pack_natural(data.length() as u64));

View File

@ -34,16 +34,6 @@ impl Array {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
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<Reference>) -> Self pub fn with(length:usize, class:usize, data:Vec<Reference>) -> Self
{ {
let mut obj = Self::new(length, class); let mut obj = Self::new(length, class);
@ -73,6 +63,17 @@ impl Array {
unsafe {type_inner(self.addr.class)} unsafe {type_inner(self.addr.class)}
} }
} }
impl TryFrom<Reference> for Array {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::ARRAY) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Array { impl std::ops::Deref for Array {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -21,16 +21,6 @@ impl Block {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::BLOCK) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(size:usize, data:Vec<u8>) -> Self pub fn with(size:usize, data:Vec<u8>) -> Self
{ {
let mut obj = Self::new(size); let mut obj = Self::new(size);
@ -64,6 +54,17 @@ impl Block {
return result; return result;
} }
} }
impl TryFrom<Reference> for Block {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::BLOCK) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Block { impl std::ops::Deref for Block {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -20,21 +20,11 @@ impl Boolean {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::BOOLEAN) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(value:bool) -> Self pub fn with(value:bool) -> Self
{ {
let mut obj = Self::new(); let mut result = Self::new();
obj.set(value); result.set(value);
return obj; return result;
} }
pub fn set(&mut self, value:bool) pub fn set(&mut self, value:bool)
@ -47,6 +37,17 @@ impl Boolean {
unsafe { bool_get(self.addr) } unsafe { bool_get(self.addr) }
} }
} }
impl TryFrom<Reference> for Boolean {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::BOOLEAN) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Boolean { impl std::ops::Deref for Boolean {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }
@ -54,3 +55,8 @@ impl std::ops::Deref for Boolean {
impl Drop for Boolean { impl Drop for Boolean {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }
impl Into<bool> for Boolean {
fn into(self) -> bool {
self.get()
}
}

View File

@ -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 integer() -> usize { unsafe { runtime::type_outer(0, tag::INTEGER) } }
pub fn significant() -> usize { unsafe { runtime::type_outer(0, tag::SIGNIFICANT) } } 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 { pub fn block(size:usize) -> usize {
unsafe { unsafe {
let inner_node = runtime::type_outer(0, size); let inner_node = runtime::type_outer(0, size);

229
src/interface/decimal.rs Normal file
View File

@ -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<Reference> for Decimal {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::DECIMAL) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl Into<f64> for Decimal {
fn into(self) -> f64 {
self.get()
}
}

View File

@ -20,16 +20,6 @@ impl Integer {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::INTEGER) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(value:i64) -> Self pub fn with(value:i64) -> Self
{ {
let mut obj = Self::new(); let mut obj = Self::new();
@ -47,6 +37,17 @@ impl Integer {
unsafe { integer_get(self.addr) } unsafe { integer_get(self.addr) }
} }
} }
impl TryFrom<Reference> for Integer {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::INTEGER) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Integer { impl std::ops::Deref for Integer {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }
@ -54,3 +55,4 @@ impl std::ops::Deref for Integer {
impl Drop for Integer { impl Drop for Integer {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }

View File

@ -25,16 +25,6 @@ impl List {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
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<Reference>) -> Self pub fn with(type_id:usize, data:Vec<Reference>) -> Self
{ {
let mut obj = Self::new(type_id); let mut obj = Self::new(type_id);
@ -108,6 +98,17 @@ impl List {
unsafe {type_inner(self.addr.class)} unsafe {type_inner(self.addr.class)}
} }
} }
impl TryFrom<Reference> for List {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::LIST) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for List { impl std::ops::Deref for List {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -8,6 +8,7 @@ mod varying; pub use varying::Varying;
mod boolean; pub use boolean::Boolean; mod boolean; pub use boolean::Boolean;
mod natural; pub use natural::Natural; mod natural; pub use natural::Natural;
mod integer; pub use integer::Integer; mod integer; pub use integer::Integer;
mod decimal; pub use decimal::Decimal;
mod signficant; pub use signficant::Significant; mod signficant; pub use signficant::Significant;
mod block; pub use block::Block; mod block; pub use block::Block;
mod sequence; pub use sequence::Sequence; mod sequence; pub use sequence::Sequence;
@ -23,6 +24,8 @@ pub enum Type {
Boolean(Boolean), Boolean(Boolean),
Natural(Natural), Natural(Natural),
Integer(Integer), Integer(Integer),
Decimal(Decimal),
Significant(Significant),
Block(Block), Block(Block),
Sequence(Sequence), Sequence(Sequence),
Array(Array), Array(Array),
@ -36,16 +39,18 @@ impl Type {
{ {
match unsafe {type_key(addr.class)} { match unsafe {type_key(addr.class)} {
tag::NULL => Type::Null, tag::NULL => Type::Null,
tag::VARYING => Type::Varying(Varying::from(addr).unwrap()), tag::VARYING => Type::Varying(Varying::try_from(addr).unwrap()),
tag::BOOLEAN => Type::Boolean(Boolean::from(addr).unwrap()), tag::BOOLEAN => Type::Boolean(Boolean::try_from(addr).unwrap()),
tag::NATURAL => Type::Natural(Natural::from(addr).unwrap()), tag::NATURAL => Type::Natural(Natural::try_from(addr).unwrap()),
tag::INTEGER => Type::Integer(Integer::from(addr).unwrap()), tag::INTEGER => Type::Integer(Integer::try_from(addr).unwrap()),
tag::BLOCK => Type::Block(Block::from(addr).unwrap()), tag::DECIMAL => Type::Decimal(Decimal::try_from(addr).unwrap()),
tag::SEQUENCE => Type::Sequence(Sequence::from(addr).unwrap()), tag::SIGNIFICANT => Type::Significant(Significant::try_from(addr).unwrap()),
tag::ARRAY => Type::Array(Array::from(addr).unwrap()), tag::BLOCK => Type::Block(Block::try_from(addr).unwrap()),
tag::LIST => Type::List(List::from(addr).unwrap()), tag::SEQUENCE => Type::Sequence(Sequence::try_from(addr).unwrap()),
tag::SPARSE => Type::Sparse(Sparse::from(addr).unwrap()), tag::ARRAY => Type::Array(Array::try_from(addr).unwrap()),
tag::RECORD => Type::Record(Record::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, _ => Type::Null,
} }
} }
@ -57,6 +62,8 @@ impl Type {
Type::Boolean(obj) => **obj, Type::Boolean(obj) => **obj,
Type::Natural(obj) => **obj, Type::Natural(obj) => **obj,
Type::Integer(obj) => **obj, Type::Integer(obj) => **obj,
Type::Decimal(obj) => **obj,
Type::Significant(obj) => **obj,
Type::Block(obj) => **obj, Type::Block(obj) => **obj,
Type::Sequence(obj) => **obj, Type::Sequence(obj) => **obj,
Type::Array(obj) => **obj, Type::Array(obj) => **obj,

View File

@ -20,16 +20,6 @@ impl Natural {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::NATURAL) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(value:u64) -> Self pub fn with(value:u64) -> Self
{ {
let mut obj = Self::new(); let mut obj = Self::new();
@ -47,6 +37,17 @@ impl Natural {
unsafe { natural_get(self.addr) } unsafe { natural_get(self.addr) }
} }
} }
impl TryFrom<Reference> for Natural {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::NATURAL) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Natural { impl std::ops::Deref for Natural {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -28,15 +28,6 @@ impl Record {
Err(()) Err(())
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
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<Self,()> pub fn with(schema:usize, data:Vec<(&str, Reference)>) -> Result<Self,()>
{ {
@ -126,6 +117,17 @@ impl Record {
unsafe {record_type(self.addr, index)} unsafe {record_type(self.addr, index)}
} }
} }
impl TryFrom<Reference> for Record {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::RECORD) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Record { impl std::ops::Deref for Record {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -25,16 +25,6 @@ impl Schema {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
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 pub fn with(members:Vec<(&str, usize)>) -> Self
{ {
let mut obj = Self::new(); let mut obj = Self::new();
@ -135,6 +125,17 @@ impl Schema {
unsafe {schema_bind(self.addr, id)} unsafe {schema_bind(self.addr, id)}
} }
} }
impl TryFrom<Reference> for Schema {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SCHEMA) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Schema { impl std::ops::Deref for Schema {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -23,16 +23,6 @@ impl Sequence {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::SEQUENCE) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with_raw(data:Vec<u8>) -> Self pub fn with_raw(data:Vec<u8>) -> Self
{ {
let mut obj = Self::new(); let mut obj = Self::new();
@ -105,6 +95,17 @@ impl Sequence {
} }
} }
} }
impl TryFrom<Reference> for Sequence {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SEQUENCE) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Sequence { impl std::ops::Deref for Sequence {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -20,16 +20,6 @@ impl Significant {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::SIGNIFICANT) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(value:f64) -> Self pub fn with(value:f64) -> Self
{ {
let mut obj = Self::new(); let mut obj = Self::new();
@ -47,6 +37,17 @@ impl Significant {
unsafe { significant_get(self.addr) } unsafe { significant_get(self.addr) }
} }
} }
impl TryFrom<Reference> for Significant {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SIGNIFICANT) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Significant { impl std::ops::Deref for Significant {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -24,16 +24,6 @@ impl Sparse {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
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 pub fn with(class:usize, data:Vec<(usize, Reference)>) -> Self
{ {
let mut obj = Self::new(class); let mut obj = Self::new(class);
@ -88,6 +78,17 @@ impl Sparse {
unsafe {type_inner(self.addr.class)} unsafe {type_inner(self.addr.class)}
} }
} }
impl TryFrom<Reference> for Sparse {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SPARSE) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Sparse { impl std::ops::Deref for Sparse {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -21,16 +21,6 @@ impl Varying {
} }
} }
pub fn from(addr:Reference) -> Result<Self,()>
{
return if(unsafe {type_key(addr.class)} == tag::VARYING) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
pub fn with(addr:Reference) -> Self pub fn with(addr:Reference) -> Self
{ {
let mut obj = Varying::new(); let mut obj = Varying::new();
@ -63,6 +53,17 @@ impl Varying {
unsafe {varying_get(self.addr).class} unsafe {varying_get(self.addr).class}
} }
} }
impl TryFrom<Reference> for Varying {
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::VARYING) {
Ok(Self { managed:false, addr:addr })
}
else {
Err(())
}
}
}
impl std::ops::Deref for Varying { impl std::ops::Deref for Varying {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }

View File

@ -6,69 +6,5 @@ mod runtime;
mod interface; pub use interface::*; mod interface; pub use interface::*;
mod encoding; pub use encoding::*; 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)] #[cfg(test)]
mod tests; mod tests;

View File

@ -34,14 +34,15 @@ extern "C" size_t type_size(size_t type_id)
size_t type = DB_TYPE.key(type_id); size_t type = DB_TYPE.key(type_id);
switch(type) { switch(type) {
case Type::Tag::Null: return 0; case Type::Tag::Null: return 0;
case Type::Tag::Varying: return sizeof(Reference); case Type::Tag::Varying: return sizeof(Reference);
case Type::Tag::Boolean: return sizeof(Type::Boolean); case Type::Tag::Boolean: return sizeof(Type::Boolean);
case Type::Tag::Natural: return sizeof(Type::Natural); case Type::Tag::Natural: return sizeof(Type::Natural);
case Type::Tag::Integer: return sizeof(Type::Integer); case Type::Tag::Integer: return sizeof(Type::Integer);
case Type::Tag::Significant: return sizeof(Type::Integer); case Type::Tag::Significant: return sizeof(Type::Significant);
case Type::Tag::Block: return type_innerkey(type_id); case Type::Tag::Decimal: return sizeof(Type::Decimal);
case Type::Tag::Sequence: return sizeof(Type::Sequence); case Type::Tag::Block: return type_innerkey(type_id);
case Type::Tag::Sequence: return sizeof(Type::Sequence);
case Type::Tag::Array: { case Type::Tag::Array: {
size_t length = DB_TYPE.inner(type_id); 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::Natural: return sizeof(Type::Natural);
case Type::Tag::Integer: return sizeof(Type::Integer); case Type::Tag::Integer: return sizeof(Type::Integer);
case Type::Tag::Significant: return sizeof(Type::Significant); 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::Block: return sizeof(uint8_t);
case Type::Tag::Array: return type_alignment(type_inner(type_id)); 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) { switch(kind) {
case Type::Tag::Array: case Type::Tag::Array:
return 2; return 2;
case Type::Tag::Decimal:
case Type::Tag::Block: case Type::Tag::Block:
case Type::Tag::List: case Type::Tag::List:
case Type::Tag::Sparse: 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<Type::Decimal*>(addr.address)) = value;
}
extern "C" Type::Decimal decimal_get(Reference addr)
{
return *(reinterpret_cast<Type::Decimal*>(addr.address));
}
// Block // // Block //
extern "C" size_t block_length(Reference addr) extern "C" size_t block_length(Reference addr)

View File

@ -76,6 +76,9 @@ extern "C" {
pub fn integer_set(addr:Reference, data:i64); pub fn integer_set(addr:Reference, data:i64);
pub fn integer_get(addr:Reference) -> 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_set(addr:Reference, data:f64);
pub fn significant_get(addr:Reference) -> f64; pub fn significant_get(addr:Reference) -> f64;

View File

@ -17,7 +17,7 @@ namespace Tag {
Boolean = 0x02, Boolean = 0x02,
Natural = 0x10, Natural = 0x10,
Integer = 0x11, Integer = 0x11,
//Decimal = 0x12, Decimal = 0x12,
Significant = 0x13, Significant = 0x13,
Block = 0x1e, Block = 0x1e,
Sequence = 0x1f, Sequence = 0x1f,
@ -32,6 +32,7 @@ namespace Tag {
typedef bool Boolean; typedef bool Boolean;
typedef uint64_t Natural; typedef uint64_t Natural;
typedef int64_t Integer; typedef int64_t Integer;
typedef int64_t Decimal;
typedef double Significant; typedef double Significant;
struct Sequence { struct Sequence {

View File

@ -5,7 +5,7 @@ pub const VARYING :usize = 0x01;
pub const BOOLEAN :usize = 0x02; pub const BOOLEAN :usize = 0x02;
pub const NATURAL :usize = 0x10; pub const NATURAL :usize = 0x10;
pub const INTEGER :usize = 0x11; pub const INTEGER :usize = 0x11;
//pub const DECIMAL :usize = 0x12; pub const DECIMAL :usize = 0x12;
pub const SIGNIFICANT :usize = 0x13; pub const SIGNIFICANT :usize = 0x13;
//pub const COMPLEX :usize = 0x14; //pub const COMPLEX :usize = 0x14;
//pub const RANGE :usize = 0x1c; //pub const RANGE :usize = 0x1c;

View File

@ -12,11 +12,11 @@ fn list_initialize()
fn list_from() fn list_from()
{ {
let list = List::new(natural()); 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)); list_ref.append(*Natural::with(10));
assert_eq!(1, list.length(), "List has length 1 after append to reference."); 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] #[test]
@ -29,7 +29,7 @@ fn list_with()
*Natural::with(20), *Natural::with(20),
]); ]);
assert_eq!(4, list.length()); 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] #[test]
@ -71,8 +71,8 @@ fn list_prepend()
assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3."); assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3.");
list.prepend(*Natural::with(0)); list.prepend(*Natural::with(0));
assert_eq!(4, list.length(), "List of 3 elements has length of 4 after prepend."); 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!(0, Natural::try_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!(1000, Natural::try_from(list.at(1)).unwrap().get(), "Second element in list has value 1000.");
} }
#[test] #[test]
@ -86,8 +86,8 @@ fn list_append()
assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3."); assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3.");
list.append(*Natural::with(4000)); list.append(*Natural::with(4000));
assert_eq!(4, list.length(), "List of 3 elements has length of 4 after prepend."); 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!(3000, Natural::try_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!(4000, Natural::try_from(list.at(3)).unwrap().get(), "Last element in list has value 4000.");}
#[test] #[test]
fn list_set() fn list_set()
@ -99,7 +99,7 @@ fn list_set()
]); ]);
assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3."); assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3.");
list.set(1, *Natural::with(2)); 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] #[test]
@ -118,9 +118,9 @@ fn list_remove()
list.remove(0); list.remove(0);
list.remove(2); list.remove(2);
assert_eq!(3, list.length(), "List with 3/6 elements removed has length of 3."); 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!(1, Natural::try_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!(2, Natural::try_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!(4, Natural::try_from(list.at(2)).unwrap().get(), "Last element in list is 4.");
} }
#[test] #[test]