From 0b6be97e359d6bffbfaa8e9c9b494287f90a2ba1 Mon Sep 17 00:00:00 2001 From: yukirij Date: Mon, 30 Dec 2024 22:20:47 -0800 Subject: [PATCH] Fix dependencies, implement integer packing. --- Cargo.toml | 2 +- src/bin/test.rs | 51 ++++------- src/implement/any.rs | 2 +- src/implement/array.rs | 11 ++- src/implement/block.rs | 24 ++++-- src/implement/boolean.rs | 2 +- src/implement/integer.rs | 8 ++ src/implement/mod.rs | 1 + src/implement/natural.rs | 7 +- src/implement/null.rs | 2 +- src/implement/optional.rs | 29 +++++-- src/implement/record.rs | 41 +++++++++ src/implement/schema.rs | 114 ++++++++++++++++++++++-- src/implement/sequence.rs | 26 +++++- src/prelude/clone.rs | 2 +- src/prelude/drop.rs | 38 ++++---- src/prelude/internal/mod.rs | 4 +- src/prelude/mod.rs | 2 +- src/prelude/refer.rs | 5 ++ src/runtime/mod.rs | 157 +++++++++++++++++++++++++++++++--- src/types.rs | 102 ++++++++-------------- src/util/container/dynlist.rs | 108 +++++++++++++++-------- src/util/container/mod.rs | 2 +- src/util/mod.rs | 1 + src/util/pack.rs | 139 ++++++++++++++++++++++++++++++ 25 files changed, 678 insertions(+), 202 deletions(-) create mode 100644 src/util/pack.rs diff --git a/Cargo.toml b/Cargo.toml index 7e69103..5d5e4c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" num = "0.4.3" pack = { git = "https://git.tsukiyo.org/Utility/pack" } -dict = { git = "https://git.tsukiyo.org/Utility/dictionary" } +dictionary = { git = "https://git.tsukiyo.org/Utility/dictionary" } pool = { git = "https://git.tsukiyo.org/Utility/pool" } sparse = { git = "https://git.tsukiyo.org/Utility/sparse" } diff --git a/src/bin/test.rs b/src/bin/test.rs index 7ad9a74..1edc9ed 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -1,44 +1,23 @@ use szun::*; +fn print_hex(data:&[u8]) +{ + for i in 0..data.len() { + print!("{:02x} ", data[i]); + } println!(""); +} + fn main() { { - let data = Boolean::new().with(true); - println!("bool {}", data.get()); - } + println!("[TEST NATURAL]"); - { - let data = Natural::new().with(15); - println!("nat {}", data.get::()); - } - - { - let data = Integer::new().with(-55); - println!("int {}", data.get::()); - } - - { - let (data, mut value) = Optional::::new().with_default(); - value.set(-1); - println!("opt {}", data.is_some()); - - if let Some(data) = data.get() { - println!("opt {}", data.get::()); - } - - data.unset(); - println!("opt {}", data.is_some()); - } - - { - let seq = Sequence::new().with_str("Hello, world!"); - println!("{} {} {}", seq.len(), seq.capacity(), seq.get_str()); - } - - { - let a = Integer::new().with(100); - let b = a.clone(); - - println!("100 <> {}, {}", a.get::(), b.get::()); + let data = 26; + println!(" = {}", data); + let mut v = Natural::new().with(data); + let b = v.encode(); + print_hex(&b); + v.decode(&b, &mut 0).ok(); + println!(" = {}", v.get::()); } } diff --git a/src/implement/any.rs b/src/implement/any.rs index 2bc01d0..183df80 100644 --- a/src/implement/any.rs +++ b/src/implement/any.rs @@ -15,7 +15,7 @@ impl Szun for Any { fn typeid() -> usize { 0 } fn encode(&self) -> Vec { Vec::new() } - fn decode(&mut self, _:&Vec, _:&mut usize) -> Result<(),()> { Err(()) } + fn decode(&mut self, _:&[u8], _:&mut usize) -> Result<(),()> { Err(()) } } impl internal::SzunInternal for Any { fn to_ref(&self) -> Ref { self.refer } diff --git a/src/implement/array.rs b/src/implement/array.rs index 2d65b52..36e1f99 100644 --- a/src/implement/array.rs +++ b/src/implement/array.rs @@ -48,7 +48,8 @@ impl Array { let inner_type = Runtime::type_in(self.refer.typeid()); let mut flag :u8 = 0; - Runtime::load(self.refer, &mut flag as _, types::size(inner_type), 1); + let (size, _) = types::size_align(inner_type); + Runtime::load(self.refer, &mut flag as _, size, 1); if flag != 0 { let refer = self.refer; Some(T::from_ref(refer.inner())) @@ -59,6 +60,14 @@ impl Array { } impl Szun for Array { fn typeid() -> usize { Runtime::type_from(T::typeid(), &[N, types::ARRAY]) } + + fn encode(&self) -> Vec { + Vec::new() + } + + fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> { + Err(()) + } } impl internal::SzunInternal for Array { fn to_ref(&self) -> Ref { self.refer } diff --git a/src/implement/block.rs b/src/implement/block.rs index 0de0332..f523f44 100644 --- a/src/implement/block.rs +++ b/src/implement/block.rs @@ -18,10 +18,12 @@ impl Block { pub fn set(&mut self, data:&[u8]) { - let size = Runtime::type_of(Runtime::type_in(self.refer.typeid())); + let length = Runtime::type_of(Runtime::type_in(self.refer.typeid())); let mut write = data.to_vec(); - write.resize(size, 0); - Runtime::store(self.refer, write.as_ptr() as _, 0, types::size(self.refer.typeid())); + write.resize(length, 0); + + let (size, _) = types::size_align(self.refer.typeid()); + Runtime::store(self.refer, write.as_ptr() as _, 0, size); } pub fn set_byte(&mut self, index:usize, byte:u8) @@ -33,9 +35,11 @@ impl Block { pub fn get(&self) -> Vec { - let size = Runtime::type_of(Runtime::type_in(self.refer.typeid())); - let mut data = vec![0u8; size]; - Runtime::load(self.refer, data.as_mut_ptr() as _, 0, types::size(self.refer.typeid())); + let length = Runtime::type_of(Runtime::type_in(self.refer.typeid())); + let mut data = vec![0u8; length]; + + let (size, _) = types::size_align(self.refer.typeid()); + Runtime::load(self.refer, data.as_mut_ptr() as _, 0, size); data } @@ -57,6 +61,14 @@ impl Block { } impl Szun for Block { fn typeid() -> usize { Runtime::type_from(types::ANY, &[N, types::BLOCK]) } + + fn encode(&self) -> Vec { + Vec::new() + } + + fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> { + Err(()) + } } impl SzunInternal for Block { fn to_ref(&self) -> Ref { self.refer } diff --git a/src/implement/boolean.rs b/src/implement/boolean.rs index 35a1045..6007ff3 100644 --- a/src/implement/boolean.rs +++ b/src/implement/boolean.rs @@ -39,7 +39,7 @@ impl Szun for Boolean { vec![self.get() as u8] } - fn decode(&mut self, bytes:&Vec, index:&mut usize) -> Result<(),()> { + fn decode(&mut self, bytes:&[u8], index:&mut usize) -> Result<(),()> { if bytes.len() - *index >= 1 { self.set(bytes[*index] != 0); *index += 1; diff --git a/src/implement/integer.rs b/src/implement/integer.rs index d43a1b4..719569d 100644 --- a/src/implement/integer.rs +++ b/src/implement/integer.rs @@ -35,6 +35,14 @@ impl Integer { } impl Szun for Integer { fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::INTEGER]) } + + fn encode(&self) -> Vec { + Vec::new() + } + + fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> { + Err(()) + } } impl SzunInternal for Integer { fn to_ref(&self) -> Ref { self.refer } diff --git a/src/implement/mod.rs b/src/implement/mod.rs index fcbe665..5079477 100644 --- a/src/implement/mod.rs +++ b/src/implement/mod.rs @@ -7,4 +7,5 @@ pub mod block; pub use block::Block; pub mod sequence; pub use sequence::Sequence; pub mod optional; pub use optional::Optional; pub mod array; pub use array::Array; +pub mod record; pub use record::Record; pub mod schema; pub use schema::Schema; diff --git a/src/implement/natural.rs b/src/implement/natural.rs index 6e0fe03..10fc6c4 100644 --- a/src/implement/natural.rs +++ b/src/implement/natural.rs @@ -37,11 +37,12 @@ impl Szun for Natural { fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::NATURAL]) } fn encode(&self) -> Vec { - Vec::new() + crate::util::pack::pack_natural(self.get()) } - fn decode(&mut self, bytes:&Vec, index:&mut usize) -> Result<(),()> { - Err(()) + fn decode(&mut self, bytes:&[u8], index:&mut usize) -> Result<(),()> { + self.set(crate::util::pack::unpack_natural(bytes, index)); + Ok(()) } } impl SzunInternal for Natural { diff --git a/src/implement/null.rs b/src/implement/null.rs index 4914df4..3bc4ffb 100644 --- a/src/implement/null.rs +++ b/src/implement/null.rs @@ -10,7 +10,7 @@ impl Szun for Null { fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::BOOLEAN]) } fn encode(&self) -> Vec { Vec::new() } - fn decode(&mut self, _:&Vec, _:&mut usize) -> Result<(),()> { Err(()) } + fn decode(&mut self, _:&[u8], _:&mut usize) -> Result<(),()> { Err(()) } } impl SzunInternal for Null { fn to_ref(&self) -> Ref { Ref::null() } diff --git a/src/implement/optional.rs b/src/implement/optional.rs index 482a6c7..e05cf83 100644 --- a/src/implement/optional.rs +++ b/src/implement/optional.rs @@ -31,9 +31,9 @@ impl Optional { pub fn set(&self, data:&T) { let inner_type = Runtime::type_in(self.refer.typeid()); - let inner_size = types::size(inner_type); + let (inner_size, _) = types::size_align(inner_type); - let mut bytes = vec![0u8; types::size(inner_type)]; + let mut bytes = vec![0u8; inner_size]; Runtime::load(data.to_ref(), bytes.as_ptr() as _, 0, inner_size); @@ -49,7 +49,8 @@ impl Optional { pub fn set_default(&self) -> T { let inner_type = Runtime::type_in(self.refer.typeid()); - Runtime::write(self.refer, 0xFF, types::size(inner_type)); + let (inner_size, _) = types::size_align(inner_type); + Runtime::write(self.refer, 0xFF, inner_size); T::from_ref(self.refer.temporary()) } @@ -57,8 +58,8 @@ impl Optional { pub fn unset(&self) { let inner_type = Runtime::type_in(self.refer.typeid()); - let inner_size = types::size(inner_type); - let bytes = vec![0u8; types::size(inner_type)]; + let (inner_size, _) = types::size_align(inner_type); + let bytes = vec![0u8; inner_size]; Runtime::store(self.refer, bytes.as_ptr() as _, 0, inner_size); Runtime::write(self.refer, 0x00, inner_size); @@ -67,9 +68,10 @@ impl Optional { pub fn get(&self) -> std::option::Option { let inner_type = Runtime::type_in(self.refer.typeid()); + let (inner_size, _) = types::size_align(inner_type); let mut flag :u8 = 0; - Runtime::load(self.refer, &mut flag as _, types::size(inner_type), 1); + Runtime::load(self.refer, &mut flag as _, inner_size, 1); if flag != 0 { let refer = self.refer; Some(T::from_ref(refer.inner())) @@ -81,9 +83,10 @@ impl Optional { pub fn is_some(&self) -> bool { let inner_type = Runtime::type_in(self.refer.typeid()); + let (inner_size, _) = types::size_align(inner_type); let mut flag :u8 = 0; - Runtime::load(self.refer, &mut flag as _, types::size(inner_type), 1); + Runtime::load(self.refer, &mut flag as _, inner_size, 1); flag != 0 } @@ -106,7 +109,7 @@ impl Szun for Optional { } } - fn decode(&mut self, bytes:&Vec, index:&mut usize) -> Result<(),()> { + fn decode(&mut self, bytes:&[u8], index:&mut usize) -> Result<(),()> { if bytes.len() - *index >= 1 { let some = bytes[*index]; *index += 1; @@ -141,7 +144,15 @@ impl SzunInternal for Optional { } fn mem_drop(refer:Ref) { - drop(refer.inner()) + let inner_type = Runtime::type_in(refer.typeid()); + let (size, _) = types::size_align(inner_type); + + let mut flag :u8 = 0; + Runtime::load(refer, &mut flag as _, size, 1); + + if flag != 0 { + drop_memory(refer.inner()) + } } } crate::impl_szun_generic!(Optional); diff --git a/src/implement/record.rs b/src/implement/record.rs index e69de29..90318ae 100644 --- a/src/implement/record.rs +++ b/src/implement/record.rs @@ -0,0 +1,41 @@ +use crate::{prelude::{*, internal::*}, Runtime, Any, types}; + +pub struct Record { + refer:Ref, +} +impl Record { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + } + } + + pub fn get(&mut self, index:usize) -> T + { + if let Ok(member) = Runtime::member(Runtime::type_of(Runtime::type_in(self.refer.typeid())), index) { + if let Ok(data) = Any::from_ref(Ref::new(member.typeid, unsafe {self.refer.address().byte_add(member.offset)})).try_into() { + data + } else { + panic!("mismatched data type"); + } + } else { + panic!("invalid member index"); + } + } +} +impl Szun for Record { + fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::RECORD]) } + + fn encode(&self) -> Vec { + Vec::new() + } + + fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> { + Err(()) + } +} +impl SzunInternal for Record { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer } } +} +crate::impl_szun!(Record); diff --git a/src/implement/schema.rs b/src/implement/schema.rs index 1595a68..15a58f7 100644 --- a/src/implement/schema.rs +++ b/src/implement/schema.rs @@ -1,7 +1,14 @@ -use crate::{prelude::{*, internal::*}, Runtime, Any, types}; +use crate::{prelude::{*, internal::*}, Runtime, Any, types, util::{DynList, DynListData}}; -pub(crate) struct SchemaData { - +#[derive(Clone, Copy)] +pub(crate) struct Member { + pub term:usize, + pub typeid:usize, + pub offset:usize, +} + +pub(crate) struct Data { + pub members:DynListData, } pub struct Schema { @@ -14,14 +21,79 @@ impl Schema { } } + pub fn build() -> Builder { + Builder { + data:Self::new(), + } + } + pub fn add(&mut self) -> Result<(),()> { - Err(()) + let data = unsafe {&mut *(self.refer.address_mut() as *mut Data)}; + let mut members = DynList::from_parts( + std::mem::size_of::(), + std::mem::align_of::(), + &mut data.members as _, + ); + + if let Ok(cell) = members.acquire() { + let member = unsafe {&mut *(cell as *mut Member)}; + member.term = usize::MAX; + member.typeid = T::typeid(); + + Ok(()) + } else { + Err(()) + } } pub fn add_named(&mut self, name:&str) -> Result<(),()> { - Err(()) + let data = unsafe {&mut *(self.refer.address_mut() as *mut Data)}; + let mut members = DynList::from_parts( + std::mem::size_of::(), + std::mem::align_of::(), + &mut data.members as _, + ); + + if let Ok(cell) = members.acquire() { + let member = unsafe {&mut *(cell as *mut Member)}; + member.term = Runtime::term(name); + member.typeid = T::typeid(); + + Ok(()) + } else { + Err(()) + } + } + + pub fn get(&self, _index:usize) -> Option { + None + } + + pub fn length(&self) -> usize + { + 0 + } + + pub fn size(&self) -> usize + { + 0 + } + + pub fn align(&self) -> usize + { + 0 + } + + pub fn bind(&self) -> Result + { + Runtime::bind(self, None) + } + + pub fn bind_key(&self, key:usize) -> Result + { + Runtime::bind(self, Some(key)) } } impl Szun for Schema { @@ -31,7 +103,7 @@ impl Szun for Schema { Vec::new() } - fn decode(&mut self, bytes:&Vec, index:&mut usize) -> Result<(),()> { + fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> { Err(()) } } @@ -40,3 +112,33 @@ impl SzunInternal for Schema { fn from_ref(refer:Ref) -> Self { Self { refer } } } crate::impl_szun!(Schema); + + +pub struct Builder { + data:Schema, +} +impl Builder { + pub fn build(self) -> Schema { self.data } + + pub fn add(mut self) -> Self + { + self.data.add::(); + self + } + + pub fn add_named(mut self, name:&str) -> Self + { + self.data.add_named::(name); + self + } + + pub fn bind(self) -> Result + { + self.data.bind() + } + + pub fn bind_key(self, key:usize) -> Result + { + self.data.bind_key(key) + } +} diff --git a/src/implement/sequence.rs b/src/implement/sequence.rs index 950904c..8279e6f 100644 --- a/src/implement/sequence.rs +++ b/src/implement/sequence.rs @@ -106,12 +106,36 @@ impl Szun for Sequence { Vec::new() } - fn decode(&mut self, bytes:&Vec, index:&mut usize) -> Result<(),()> { + fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> { Err(()) } } impl internal::SzunInternal for Sequence { fn to_ref(&self) -> Ref { self.refer } fn from_ref(refer:Ref) -> Self { Self { refer } } + + fn mem_clone(refer:Ref, memory:Option) -> Ref { + let memory = if let Some(memory) = memory { + memory + } else { + Runtime::acquire(Self::typeid()) + }; + + let src = Sequence::from_ref(refer); + let mut dst = Sequence::from_ref(memory); + dst.set(&src.get()); + + memory + } + + fn mem_drop(refer:Ref) { + if let Some(header) = unsafe {(refer.address_mut() as *mut Data).as_mut()} { + if !header.data.is_null() { + if let Ok(layout) = std::alloc::Layout::from_size_align(header.capacity, 1) { + unsafe { std::alloc::dealloc(header.data as _, layout); } + } + } + } + } } crate::impl_szun!(Sequence); diff --git a/src/prelude/clone.rs b/src/prelude/clone.rs index 59a7c59..3f54628 100644 --- a/src/prelude/clone.rs +++ b/src/prelude/clone.rs @@ -1,6 +1,6 @@ use crate::Ref; -pub fn clone(refer:Ref, memory:Option) -> Ref +pub(crate) fn clone(refer:Ref, memory:Option) -> Ref // Deep copy an object and return the copy's reference. // { diff --git a/src/prelude/drop.rs b/src/prelude/drop.rs index dbb890c..48fb275 100644 --- a/src/prelude/drop.rs +++ b/src/prelude/drop.rs @@ -1,6 +1,6 @@ use crate::{prelude::{*, internal::*}, types::*, implement::*}; -pub fn drop(refer:Ref) +pub(crate) fn drop(refer:Ref) { if !refer.is_temporary() { drop_memory(refer); @@ -8,27 +8,23 @@ pub fn drop(refer:Ref) } } -fn drop_memory(refer:Ref) +pub(crate) fn drop_memory(refer:Ref) { - let typeid = refer.typeid(); - match typeid { - OPTIONAL => { - let obj = crate::Optional::::from_ref(refer.temporary()); - if obj.is_some() { - drop_memory(refer.inner()); - } - } - - SEQUENCE => { - if let Some(header) = unsafe {(refer.address_mut() as *mut sequence::Data).as_mut()} { - if !header.data.is_null() { - if let Ok(layout) = std::alloc::Layout::from_size_align(header.capacity, 1) { - unsafe { std::alloc::dealloc(header.data as _, layout); } - } - } - } - } + if !refer.is_null() { + let typeid = refer.typeid(); + match typeid { + ANY => Any::mem_drop(refer), + SEQUENCE => Sequence::mem_drop(refer), + //VAR => Var::mem_drop(refer), + OPTIONAL => Optional::::mem_drop(refer), + ARRAY => Array::::mem_drop(refer), + //LIST => List::::mem_drop(refer), + //RECORD => Record::<0>::mem_drop(refer), + SCHEMA => Schema::mem_drop(refer), - _ => { } + BOOLEAN | NATURAL | INTEGER | BLOCK => { } + + _ => { panic!("drop_memory called for unhandled type"); } + } } } diff --git a/src/prelude/internal/mod.rs b/src/prelude/internal/mod.rs index 8e1b651..43460cd 100644 --- a/src/prelude/internal/mod.rs +++ b/src/prelude/internal/mod.rs @@ -15,8 +15,10 @@ pub(crate) trait SzunInternal { Runtime::acquire(typeid) }; + let (size, _) = types::size_align(typeid); + // Copy data to destination - Runtime::copy(refer.address(), memory.address_mut(), types::size(typeid)); + Runtime::copy(refer.address(), memory.address_mut(), size); memory } diff --git a/src/prelude/mod.rs b/src/prelude/mod.rs index b1def38..f8a4ed4 100644 --- a/src/prelude/mod.rs +++ b/src/prelude/mod.rs @@ -19,7 +19,7 @@ pub trait Szun : internal::SzunInternal + Clone + TryFrom + Into + Dro } fn encode(&self) -> Vec; - fn decode(&mut self, bytes:&Vec, index:&mut usize) -> Result<(),()>; + fn decode(&mut self, bytes:&[u8], index:&mut usize) -> Result<(),()>; fn tag(&self) -> Vec { diff --git a/src/prelude/refer.rs b/src/prelude/refer.rs index 5fa0b85..221ebc1 100644 --- a/src/prelude/refer.rs +++ b/src/prelude/refer.rs @@ -41,6 +41,11 @@ impl Ref { (self.typeid & (1 << (usize::BITS - 1))) != 0 } + pub fn is_null(&self) -> bool + { + self.address.is_null() + } + pub fn typeid(&self) -> usize { self.typeid & !(1 << (usize::BITS - 1)) diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 744eae6..0938afc 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -1,26 +1,28 @@ -use crate::{prelude::*, types}; +use crate::{prelude::{*, internal::SzunInternal}, types, util::DynList, Schema}; +use dictionary::Dictionary; use sparse::Sparse; use pool::Pool; mod typetree; use typetree::TypeTree; +#[derive(Clone, Copy)] enum Binding { + Temporary, Schema { + bind:usize, length:usize, size:usize, align:usize, next:usize, }, Member { - term:usize, - typeid:usize, - offset:usize, + data:crate::schema::Member, next:usize, }, } struct RuntimeData { - terms:dict::Dictionary, + terms:Dictionary, types:TypeTree, bindings:Pool, bindings_ext:Sparse, @@ -29,7 +31,7 @@ impl RuntimeData { const fn init() -> Self { Self { - terms:Vec::new(), + terms:Dictionary::new(), types:TypeTree::new(), bindings:Pool::new(), bindings_ext:Sparse::new(), @@ -40,9 +42,9 @@ impl RuntimeData { { use std::alloc::{alloc_zeroed, Layout}; - let size = types::size(typeid); + let (size, align) = types::size_align(typeid); if size > 0 { - if let Ok(layout) = Layout::from_size_align(size, types::align(typeid)) { + if let Ok(layout) = Layout::from_size_align(size, align) { let address :*const u8; unsafe { address = alloc_zeroed(layout) as _; @@ -61,9 +63,9 @@ impl RuntimeData { use std::alloc::{dealloc, Layout}; let typeid = refer.typeid(); - let size = types::size(typeid); + let (size, align) = types::size_align(typeid); if size > 0 { - if let Ok(layout) = Layout::from_size_align(size, types::align(typeid)) { + if let Ok(layout) = Layout::from_size_align(size, align) { unsafe { dealloc(refer.address_mut(), layout); } @@ -99,7 +101,7 @@ impl RuntimeData { fn zero(&mut self, refer:Ref) { - let size = types::size(refer.typeid()); + let (size, _) = types::size_align(refer.typeid()); for i in 0..size { unsafe { *refer.address_mut().byte_add(i) = 0; } } @@ -119,6 +121,134 @@ impl RuntimeData { { self.types.value(typeid) } + + fn term(&mut self, text:&str) -> usize + { + self.terms.set(text.as_bytes()) + } + + fn bind(&mut self, schema:&Schema, key:Option) -> Result + { + + if let Some(schema_data) = unsafe {(schema.to_ref().address_mut() as *mut crate::schema::Data).as_mut()} { + + let members = DynList::from_parts( + std::mem::size_of::(), + std::mem::align_of::(), + &mut schema_data.members as _, + ); + + // Prepare bindings for schema and members. + let mut bindings = Vec::new(); + bindings.push(Binding::Schema { + bind:if let Some(key) = key { key } else { usize::MAX }, + length:members.size(), + size:0, + align:0, + next:0, + }); + + for i in 0..members.size() { + if let Ok(member) = members.cell_as::(i) { + bindings.push(Binding::Member { + data:member.clone(), + next:0, + }); + } + } + + // Acquire binding allocations. + let mut slots = Vec::new(); + for _ in 0..bindings.len() { + slots.push(self.bindings.add(Binding::Temporary)); + } + + // Fill next pointers with allocations. + for i in 0..bindings.len() - 1 { + match &mut bindings[i] { + Binding::Schema { + bind:_, + length:_, + size:_, + align:_, + next + } => { + *next = slots[i + 1]; + } + + Binding::Member { + data:_, + next + } => { + *next = slots[i + 1]; + } + + _ => { } + } + } + + // Write bindings to pool. + for i in 0..bindings.len() { + if let Some(cell) = self.bindings.get_mut(slots[i]) { + *cell = bindings[i]; + } + } + + // Map key to binding. + if let Some(key) = key { + self.bindings_ext.set(key as isize, slots[0]); + } + + Ok(slots[0]) + } else { + Err(()) + } + } + + fn member(&mut self, schema:usize, index:usize) -> Result + { + let mut bind_index = 0; + let bind_id = schema; + + while bind_index < index { + if let Some(bind) = self.bindings.get(bind_id) { + match bind { + Binding::Schema { + bind:_, + length:_, + size:_, + align:_, + next:_, + } => { + + } + + Binding::Member { + data:_, + next:_, + } => { + if index == bind_index { + + } else { + + bind_index += 1; + } + } + + _ => return Err(()), + } + } else { + + } + } + + Err(()) + } + + fn member_name(&mut self, _schema:usize, _name:&str) -> Result + { + Err(()) + } } static mut RUNTIME :RuntimeData = RuntimeData::init(); @@ -136,4 +266,9 @@ impl Runtime { pub fn type_in(typeid:usize) -> usize {unsafe{ RUNTIME.type_in(typeid).unwrap_or_default() }} pub fn type_in_opt(typeid:usize) -> Option {unsafe{ RUNTIME.type_in(typeid) }} pub fn type_from(typeid:usize, types:&[usize]) -> usize {unsafe{ RUNTIME.type_from(typeid, types) }} + + pub fn term(text:&str) -> usize { unsafe { RUNTIME.term(text) } } + + pub fn bind(schema:&Schema, key:Option) -> Result {unsafe{ RUNTIME.bind(schema, key) }} + pub fn member(schema:usize, index:usize) -> Result {unsafe { RUNTIME.member(schema, index) }} } diff --git a/src/types.rs b/src/types.rs index b284046..887dc46 100644 --- a/src/types.rs +++ b/src/types.rs @@ -27,79 +27,51 @@ pub const ENUM :usize = 0x7D; pub const RECORD :usize = 0x7E; pub const SCHEMA :usize = 0x7F; -pub fn size(typeid:usize) -> usize +pub fn size_align(typeid:usize) -> (usize, usize) // Byte size of static data in memory. // { - use std::mem::size_of; + use std::mem::{size_of, align_of}; match Runtime::type_of(typeid) { - ANY => 0, - BOOLEAN => size_of::(), - BYTE => size_of::(), - CHAR => size_of::(), - NATURAL => size_of::(), - INTEGER => size_of::(), - DECIMAL => size_of::(), - SIGNIFICANT => size_of::(), - BLOCK => Runtime::type_of(Runtime::type_in(typeid)), - SEQUENCE => size_of::(), - VAR => 16, - OPTIONAL => size(Runtime::type_in(typeid)) + 1, + ANY => (0, 0), + BOOLEAN => (size_of::(), align_of::()), + BYTE => (size_of::(), align_of::()), + CHAR => (size_of::(), align_of::()), + NATURAL => (size_of::(), align_of::()), + INTEGER => (size_of::(), align_of::()), + DECIMAL => (size_of::(), align_of::()), + SIGNIFICANT => (size_of::(), align_of::()), + BLOCK => (Runtime::type_of(Runtime::type_in(typeid)), 1), + SEQUENCE => (size_of::(), align_of::()), + VAR => (0, 0), + OPTIONAL => { + let (size, align) = size_align(Runtime::type_of(Runtime::type_in(typeid))); + ( + size + 1, + align, + ) + }, ARRAY => { let inner_size = Runtime::type_in(typeid); let inner_type = Runtime::type_in(inner_size); - Runtime::type_of(inner_size) * size(Runtime::type_of(inner_type)) + let (size, align) = size_align(Runtime::type_of(inner_type)); + ( + Runtime::type_of(inner_size) * size, + align, + ) }, - LIST => 16, - GRAPH => 0, - TRIE => 0, - MAP => 0, - SPARSE => 0, - POOL => 0, - TABLE => 0, - ENUM => 0, - RECORD => 0, - SCHEMA => 0, - _ => 0, - } -} - -pub fn align(typeid:usize) -> usize -// Byte alignment of type. -// -{ - use std::mem::align_of; - - match Runtime::type_of(typeid) { - ANY => 0, - BOOLEAN => align_of::(), - BYTE => align_of::(), - CHAR => align_of::(), - NATURAL => align_of::(), - INTEGER => align_of::(), - DECIMAL => align_of::(), - SIGNIFICANT => align_of::(), - BLOCK => align_of::(), - SEQUENCE => align_of::(), - VAR => 8, - OPTIONAL => align(Runtime::type_in(typeid)), - ARRAY => { - let inner_size = Runtime::type_in(typeid); - let inner_type = Runtime::type_in(inner_size); - align(Runtime::type_of(inner_type)) - }, - LIST => 8, - GRAPH => 0, - TRIE => 0, - MAP => 0, - SPARSE => 0, - POOL => 0, - TABLE => 0, - ENUM => 0, - RECORD => 0, - SCHEMA => 0, - _ => 0, + LIST => (size_of::(), align_of::()), + GRAPH => (0, 0), + TRIE => (0, 0), + MAP => (0, 0), + SPARSE => (0, 0), + POOL => (0, 0), + TABLE => (0, 0), + ENUM => (0, 0), + RECORD => (0, 0), + SCHEMA => (size_of::(), align_of::()), + _ => (0, 0), } } @@ -108,7 +80,7 @@ pub fn primitive(typeid:usize) -> bool // { match Runtime::type_of(typeid) { - ANY | BOOLEAN + BOOLEAN | BYTE | CHAR | NATURAL | INTEGER | DECIMAL | SIGNIFICANT | BLOCK diff --git a/src/util/container/dynlist.rs b/src/util/container/dynlist.rs index 964a163..1ae3e47 100644 --- a/src/util/container/dynlist.rs +++ b/src/util/container/dynlist.rs @@ -1,5 +1,5 @@ #[derive(Clone, Copy)] -pub(crate) struct DynListData { +pub struct DynListData { capacity:usize, length:usize, data:*mut u8, @@ -9,56 +9,94 @@ pub(crate) struct DynListData { pub struct DynList { size:usize, align:usize, - data:DynListData, + data:*mut DynListData, } -impl DynList { - pub fn from_parts(ptr:*const DynListData, size:usize, align:usize) -> Self { +impl DynList { + pub fn from_parts(size:usize, align:usize, ptr:*mut DynListData) -> Self { Self { size, align, - data:unsafe {*ptr}, + data:ptr, } } - pub fn reserve(&mut self) -> Result<*mut u8,()> + pub fn acquire(&mut self) -> Result<*mut u8,()> { - if self.length == self.capacity { - self.resize(self.capacity * 2)?; - } - self.length += 1; - cell(self.length - 1) - } - - pub fn cell(&self, index:usize) -> Result<*mut u8,()> - { - if index < self.length { - Ok(unsafe {self.data.byte_add(index * self.size)}) + if let Some(data) = unsafe {self.data.as_mut()} { + if data.length == data.capacity { + self.resize(data.capacity * 2)?; + } + data.length += 1; + self.cell(data.length - 1) } else { Err(()) } } - pub fn resize(&mut self, capacity:usize) -> Result<(),()> + pub fn cell(&self, index:usize) -> Result<*mut u8,()> { - use std::alloc::{alloc_zeroed, Layout}; - - let ptr = self.data; - - if capacity > 0 { - if let Ok(layout) = Layout::from_size_align(size, types::align(typeid)) { - let address :*const u8; - unsafe { - address = alloc_zeroed(layout) as _; - } - Ref::new(typeid, address) - } else { - Ref::null() + if let Some(data) = unsafe {self.data.as_mut()} { + if index < data.length { + return Ok(unsafe {self.data.byte_add(index * self.size)} as _); } - } else { - Ref::null() } + Err(()) + } - self.capacity = capacity; - Ok(()) + pub fn cell_as(&self, index:usize) -> Result<&mut T,()> + { + if let Some(data) = unsafe {self.data.as_mut()} { + if index < data.length { + if let Some(result) = unsafe {(self.data.byte_add(index * self.size) as *mut T).as_mut()} { + return Ok(result); + } + } + } + Err(()) + } + + pub fn resize(&mut self, _capacity:usize) -> Result<(),()> + { + /*use std::alloc::{alloc_zeroed, Layout}; + if let Some(data) = unsafe {self.data.as_mut()} { + let ptr = self.data; + + if capacity > 0 { + if let Ok(layout) = Layout::from_size_align(capacity * self.size, self.align) { + //Ref::new(typeid, unsafe {alloc_zeroed(layout) as *const u8}) + } else { + //Ref::null() + } + } else { + //Ref::null() + } + + data.capacity = capacity; + Ok(()) + } else { + Err(()) + }*/ + Err(()) + } + + pub fn capacity(&self) -> usize + { + unsafe {(*self.data).capacity} + } + + pub fn size(&self) -> usize + { + unsafe {(*self.data).length} + } + + pub fn drop(&mut self) + { + use std::alloc::{dealloc, Layout}; + if let Some(data) = unsafe {self.data.as_mut()} { + if let Ok(layout) = Layout::from_size_align(self.size * data.capacity, self.align) { + unsafe { dealloc(data.data, layout); } + data.data = std::ptr::null_mut(); + } + } } } diff --git a/src/util/container/mod.rs b/src/util/container/mod.rs index 0a52305..d476225 100644 --- a/src/util/container/mod.rs +++ b/src/util/container/mod.rs @@ -1 +1 @@ -mod dynlist; pub use dynlist::RawList; +mod dynlist; pub use dynlist::*; diff --git a/src/util/mod.rs b/src/util/mod.rs index 4f2f16c..d852306 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,2 +1,3 @@ pub mod macros; mod container; pub use container::*; +pub mod pack; diff --git a/src/util/pack.rs b/src/util/pack.rs new file mode 100644 index 0000000..d1f65d7 --- /dev/null +++ b/src/util/pack.rs @@ -0,0 +1,139 @@ +fn pack_size(data:u64, signed:bool) -> usize +{ + let sign_bit = signed as u32; + 1 + (data >= 1 << (7 - sign_bit)) as usize + + (data >= 1 << (14 - sign_bit)) as usize + + (data >= 1 << (21 - sign_bit)) as usize + + (data >= 1 << (28 - sign_bit)) as usize + + (data >= 1 << (35 - sign_bit)) as usize + + (data >= 1 << (42 - sign_bit)) as usize + + (data >= 1 << (49 - sign_bit)) as usize + + (data >= 1 << (56 - sign_bit)) as usize + + (signed && data >= 1 << 63) as usize +} + +pub fn pack_natural(data:u64) -> Vec +{ + let mut result = [0u8; 9]; + let size = pack_size(data, false); + let tag = (0xFF00u32 >> (size - 1)) as u8; + + match size { + 1 => { + result[0] = data as u8; + } + 2 => { + result[0] = (data >> 8) as u8; + result[1] = data as u8; + } + 3 => { + result[0] = (data >> 16) as u8; + result[1] = (data >> 8) as u8; + result[2] = data as u8; + } + 4 => { + result[0] = (data >> 24) as u8; + result[1] = (data >> 16) as u8; + result[2] = (data >> 8) as u8; + result[3] = data as u8; + } + 5 => { + result[0] = (data >> 24) as u8; + result[0] = (data >> 24) as u8; + result[1] = (data >> 16) as u8; + result[2] = (data >> 8) as u8; + result[3] = data as u8; + } + 6 => { + result[0] = (data >> 24) as u8; + result[0] = (data >> 24) as u8; + result[0] = (data >> 24) as u8; + result[1] = (data >> 16) as u8; + result[2] = (data >> 8) as u8; + result[3] = data as u8; + } + 7 => { + result[0] = (data >> 24) as u8; + result[0] = (data >> 24) as u8; + result[0] = (data >> 24) as u8; + result[0] = (data >> 24) as u8; + result[1] = (data >> 16) as u8; + result[2] = (data >> 8) as u8; + result[3] = data as u8; + } + 8 => { + result[0] = (data >> 56) as u8; + result[1] = (data >> 48) as u8; + result[2] = (data >> 40) as u8; + result[3] = (data >> 32) as u8; + result[4] = (data >> 24) as u8; + result[5] = (data >> 16) as u8; + result[6] = (data >> 8) as u8; + result[7] = data as u8; + } + 9 => { + result[1] = (data >> 56) as u8; + result[2] = (data >> 48) as u8; + result[3] = (data >> 40) as u8; + result[4] = (data >> 32) as u8; + result[5] = (data >> 24) as u8; + result[6] = (data >> 16) as u8; + result[7] = (data >> 8) as u8; + result[8] = data as u8; + } + _ => { } + } + + result[0] |= tag; + result[0..size].to_vec() +} + +pub fn pack_integer(data:i64) -> Vec +{ + let negative = data < 0; + let data = ((negative as u64) * (!data as u64)) + ((!negative as u64) * data as u64); + let size = pack_size(data, true); + + let sign = [ + (((negative as u32) << 6) >> (size - 1)) as u8, + (((negative as u32) << 14) >> (size - 1)) as u8, + ]; + let sign_index = (size >= 6) as usize; + + let mut result = pack_natural(data); + + result[sign_index] |= sign[sign_index]; + result +} + +pub fn unpack_natural(data:&[u8], index:&mut usize) -> u64 +{ + let size = data[*index].leading_ones(); + let mut result = (data[*index] & (0x7F >> size)) as u64; + *index += 1; + + for _ in 0..size { + result << 8; + result += data[*index] as u64; + *index += 1; + } + + result +} + +pub fn unpack_integer(data:&[u8], index:&mut usize) -> u64 +{ + let size = data[*index].leading_ones(); + let sign = (data[*index + (size == 8) as usize] & (0x40 >> size)) != 0; + let mut result = (data[*index] & (0x3F >> size)) as u64; + *index += 1; + + for _ in 0..size { + result << 8; + result += data[*index] as u64; + *index += 1; + } + + ((sign) as u64 * (!result)) + ((!sign) as u64 * result) +} +