Refactor interface usages, add Decimal type.
This commit is contained in:
parent
cf5834a511
commit
e7781c721f
@ -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());
|
|
||||||
}
|
|
@ -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"); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
229
src/interface/decimal.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
@ -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)}; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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; }
|
||||||
|
@ -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,
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
|
64
src/lib.rs
64
src/lib.rs
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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]
|
||||||
|
Reference in New Issue
Block a user