Fix dependencies, implement integer packing.

This commit is contained in:
yukirij 2024-12-30 22:20:47 -08:00
parent d53c560f5d
commit 0b6be97e35
25 changed files with 678 additions and 202 deletions

View File

@ -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" }

View File

@ -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::<u32>());
}
{
let data = Integer::new().with(-55);
println!("int {}", data.get::<i32>());
}
{
let (data, mut value) = Optional::<Integer>::new().with_default();
value.set(-1);
println!("opt {}", data.is_some());
if let Some(data) = data.get() {
println!("opt {}", data.get::<i32>());
}
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::<i32>(), b.get::<i32>());
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::<u64>());
}
}

View File

@ -15,7 +15,7 @@ impl Szun for Any {
fn typeid() -> usize { 0 }
fn encode(&self) -> Vec<u8> { Vec::new() }
fn decode(&mut self, _:&Vec<u8>, _:&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 }

View File

@ -48,7 +48,8 @@ impl<T:Szun, const N:usize> Array<T,N> {
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<T:Szun, const N:usize> Array<T,N> {
}
impl<T:Szun, const N:usize> Szun for Array<T,N> {
fn typeid() -> usize { Runtime::type_from(T::typeid(), &[N, types::ARRAY]) }
fn encode(&self) -> Vec<u8> {
Vec::new()
}
fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> {
Err(())
}
}
impl<T:Szun, const N:usize> internal::SzunInternal for Array<T,N> {
fn to_ref(&self) -> Ref { self.refer }

View File

@ -18,10 +18,12 @@ impl<const N:usize> Block<N> {
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<const N:usize> Block<N> {
pub fn get(&self) -> Vec<u8>
{
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<const N:usize> Block<N> {
}
impl<const N:usize> Szun for Block<N> {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[N, types::BLOCK]) }
fn encode(&self) -> Vec<u8> {
Vec::new()
}
fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> {
Err(())
}
}
impl<const N:usize> SzunInternal for Block<N> {
fn to_ref(&self) -> Ref { self.refer }

View File

@ -39,7 +39,7 @@ impl Szun for Boolean {
vec![self.get() as u8]
}
fn decode(&mut self, bytes:&Vec<u8>, 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;

View File

@ -35,6 +35,14 @@ impl Integer {
}
impl Szun for Integer {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::INTEGER]) }
fn encode(&self) -> Vec<u8> {
Vec::new()
}
fn decode(&mut self, _bytes:&[u8], _index:&mut usize) -> Result<(),()> {
Err(())
}
}
impl SzunInternal for Integer {
fn to_ref(&self) -> Ref { self.refer }

View File

@ -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;

View File

@ -37,11 +37,12 @@ impl Szun for Natural {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::NATURAL]) }
fn encode(&self) -> Vec<u8> {
Vec::new()
crate::util::pack::pack_natural(self.get())
}
fn decode(&mut self, bytes:&Vec<u8>, 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 {

View File

@ -10,7 +10,7 @@ impl Szun for Null {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::BOOLEAN]) }
fn encode(&self) -> Vec<u8> { Vec::new() }
fn decode(&mut self, _:&Vec<u8>, _:&mut usize) -> Result<(),()> { Err(()) }
fn decode(&mut self, _:&[u8], _:&mut usize) -> Result<(),()> { Err(()) }
}
impl SzunInternal for Null {
fn to_ref(&self) -> Ref { Ref::null() }

View File

@ -31,9 +31,9 @@ impl<T:Szun> Optional<T> {
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<T:Szun> Optional<T> {
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<T:Szun> Optional<T> {
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<T:Szun> Optional<T> {
pub fn get(&self) -> std::option::Option<T>
{
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<T:Szun> Optional<T> {
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<T:Szun> Szun for Optional<T> {
}
}
fn decode(&mut self, bytes:&Vec<u8>, 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<T:Szun> SzunInternal for Optional<T> {
}
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<T>);

View File

@ -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<T:Szun>(&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<u8> {
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);

View File

@ -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<T:Szun>(&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::<Member>(),
std::mem::align_of::<Member>(),
&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<T:Szun>(&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::<Member>(),
std::mem::align_of::<Member>(),
&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<Member> {
None
}
pub fn length(&self) -> usize
{
0
}
pub fn size(&self) -> usize
{
0
}
pub fn align(&self) -> usize
{
0
}
pub fn bind(&self) -> Result<usize,()>
{
Runtime::bind(self, None)
}
pub fn bind_key(&self, key:usize) -> Result<usize,()>
{
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<u8>, 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<T:Szun>(mut self) -> Self
{
self.data.add::<T>();
self
}
pub fn add_named<T:Szun>(mut self, name:&str) -> Self
{
self.data.add_named::<T>(name);
self
}
pub fn bind(self) -> Result<usize,()>
{
self.data.bind()
}
pub fn bind_key(self, key:usize) -> Result<usize,()>
{
self.data.bind_key(key)
}
}

View File

@ -106,12 +106,36 @@ impl Szun for Sequence {
Vec::new()
}
fn decode(&mut self, bytes:&Vec<u8>, 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>) -> 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);

View File

@ -1,6 +1,6 @@
use crate::Ref;
pub fn clone(refer:Ref, memory:Option<Ref>) -> Ref
pub(crate) fn clone(refer:Ref, memory:Option<Ref>) -> Ref
// Deep copy an object and return the copy's reference.
//
{

View File

@ -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::<Any>::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::<Any>::mem_drop(refer),
ARRAY => Array::<Any, 0>::mem_drop(refer),
//LIST => List::<Any>::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"); }
}
}
}

View File

@ -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
}

View File

@ -19,7 +19,7 @@ pub trait Szun : internal::SzunInternal + Clone + TryFrom<Any> + Into<Any> + Dro
}
fn encode(&self) -> Vec<u8>;
fn decode(&mut self, bytes:&Vec<u8>, index:&mut usize) -> Result<(),()>;
fn decode(&mut self, bytes:&[u8], index:&mut usize) -> Result<(),()>;
fn tag(&self) -> Vec<u8>
{

View File

@ -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))

View File

@ -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<Binding>,
bindings_ext:Sparse<usize>,
@ -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<usize>) -> Result<usize,()>
{
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::<crate::schema::Member>(),
std::mem::align_of::<crate::schema::Member>(),
&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::<crate::schema::Member>(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<crate::schema::Member,()>
{
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<crate::schema::Member,()>
{
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<usize> {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<usize>) -> Result<usize,()> {unsafe{ RUNTIME.bind(schema, key) }}
pub fn member(schema:usize, index:usize) -> Result<crate::schema::Member,()> {unsafe { RUNTIME.member(schema, index) }}
}

View File

@ -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::<bool>(),
BYTE => size_of::<u8>(),
CHAR => size_of::<char>(),
NATURAL => size_of::<u64>(),
INTEGER => size_of::<i64>(),
DECIMAL => size_of::<i64>(),
SIGNIFICANT => size_of::<f64>(),
BLOCK => Runtime::type_of(Runtime::type_in(typeid)),
SEQUENCE => size_of::<crate::implement::sequence::Data>(),
VAR => 16,
OPTIONAL => size(Runtime::type_in(typeid)) + 1,
ANY => (0, 0),
BOOLEAN => (size_of::<bool>(), align_of::<bool>()),
BYTE => (size_of::<u8>(), align_of::<u8>()),
CHAR => (size_of::<char>(), align_of::<char>()),
NATURAL => (size_of::<u64>(), align_of::<u64>()),
INTEGER => (size_of::<i64>(), align_of::<i64>()),
DECIMAL => (size_of::<i64>(), align_of::<i64>()),
SIGNIFICANT => (size_of::<f64>(), align_of::<f64>()),
BLOCK => (Runtime::type_of(Runtime::type_in(typeid)), 1),
SEQUENCE => (size_of::<crate::implement::sequence::Data>(), align_of::<crate::implement::sequence::Data>()),
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::<bool>(),
BYTE => align_of::<u8>(),
CHAR => align_of::<char>(),
NATURAL => align_of::<u64>(),
INTEGER => align_of::<i64>(),
DECIMAL => align_of::<i64>(),
SIGNIFICANT => align_of::<f64>(),
BLOCK => align_of::<u8>(),
SEQUENCE => align_of::<crate::implement::sequence::Data>(),
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::<crate::util::DynListData>(), align_of::<crate::util::DynListData>()),
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::<crate::implement::schema::Data>(), align_of::<crate::implement::schema::Data>()),
_ => (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

View File

@ -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<Z> {
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<T>(&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();
}
}
}
}

View File

@ -1 +1 @@
mod dynlist; pub use dynlist::RawList;
mod dynlist; pub use dynlist::*;

View File

@ -1,2 +1,3 @@
pub mod macros;
mod container; pub use container::*;
pub mod pack;

139
src/util/pack.rs Normal file
View File

@ -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<u8>
{
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<u8>
{
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)
}