Initialize repository.

This commit is contained in:
yukirij 2024-11-03 18:21:41 -08:00
commit a8468a99eb
26 changed files with 1257 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "szun"
version = "0.1.0"
edition = "2021"
[dependencies]
num = "0.4.3"
pack = { git = "https://git.tsukiyo.org/Utility/pack" }

44
src/bin/test.rs Normal file
View File

@ -0,0 +1,44 @@
use szun::*;
fn main()
{
{
let data = Boolean::new().with(true);
println!("bool {}", data.get());
}
{
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>());
}
}

26
src/implement/any.rs Normal file
View File

@ -0,0 +1,26 @@
use crate::prelude::{*, internal::*};
pub struct Any {
pub(crate) refer:Ref,
}
impl Any {
pub fn null() -> Self
{
Self { refer:Ref::null() }
}
pub fn typeid(&self) -> usize { self.refer.typeid() }
}
impl Szun for Any {
fn typeid() -> usize { 0 }
}
impl internal::SzunInternal for Any {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer } }
}
impl Clone for Any {
fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) }
}
impl Drop for Any {
fn drop(&mut self) { drop(self.to_ref()); }
}

67
src/implement/array.rs Normal file
View File

@ -0,0 +1,67 @@
use std::marker::PhantomData;
use crate::{prelude::{*, internal::*}, Runtime, Any, types};
pub struct Array<T:Szun, const N:usize> {
refer:Ref,
phantom:PhantomData<T>,
}
impl<T:Szun, const N:usize> Array<T,N> {
pub fn new() -> Self {
Self {
refer:Runtime::acquire(Self::typeid()),
phantom:PhantomData,
}
}
pub fn with<R:Szun>(self, data:&[R]) -> Self
{
self.set(data);
self
}
pub fn set<R:Szun>(&self, data:&[R])
{
for i in 0..data.len() {
let _refer = data[i].to_ref();
/*if self.compatible(&data[i]) {
let inner_type = Runtime::type_in(self.refer.typeid());
let inner_size = types::size(inner_type);
let mut bytes = vec![0u8; types::size(inner_type)];
Runtime::load(data[i].to_ref(), bytes.as_ptr() as _, 0, inner_size);
Runtime::store(self.refer, bytes.as_ptr() as _, 0, inner_size);
Runtime::write(self.refer, 0xFF, inner_size);
if !types::primitive(data[i].to_ref().typeid()) {
bytes.fill(0);
Runtime::store(data[i].to_ref(), bytes.as_ptr() as _, 0, inner_size);
}
}*/
}
}
pub fn get(&self) -> std::option::Option<T>
{
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);
if flag != 0 {
let refer = self.refer;
Some(T::from_ref(refer.inner()))
} else {
None
}
}
}
impl<T:Szun, const N:usize> Szun for Array<T,N> {
fn typeid() -> usize { Runtime::type_from(T::typeid(), &[N, types::ARRAY]) }
}
impl<T:Szun, const N:usize> internal::SzunInternal for Array<T,N> {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer, phantom:PhantomData } }
}
crate::impl_szun_generic_sized!(Array<T, N>);

65
src/implement/block.rs Normal file
View File

@ -0,0 +1,65 @@
use crate::{prelude::{*, internal::*}, Runtime, Any, types};
pub struct Block<const N:usize> {
refer:Ref,
}
impl<const N:usize> Block<N> {
pub fn new() -> Self {
Self {
refer:Runtime::acquire(Self::typeid()),
}
}
pub fn with(mut self, data:&[u8]) -> Self
{
self.set(data);
self
}
pub fn set(&mut self, data:&[u8])
{
let size = 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()));
}
pub fn set_byte(&mut self, index:usize, byte:u8)
{
if index < self.len() {
Runtime::store(self.refer, &byte as _, index, 1);
}
}
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()));
data
}
pub fn get_byte(&mut self, index:usize) -> u8
{
if index < self.len() {
let mut byte = 0u8;
Runtime::load(self.refer, &mut byte as _, index, 1);
byte
} else {
0
}
}
pub fn len(&self) -> usize
{
Runtime::type_of(Runtime::type_in(self.refer.typeid()))
}
}
impl<const N:usize> Szun for Block<N> {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[N, types::BLOCK]) }
}
impl<const N:usize> SzunInternal for Block<N> {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer } }
}
crate::impl_szun_sized!(Block<N>);

42
src/implement/boolean.rs Normal file
View File

@ -0,0 +1,42 @@
use crate::{prelude::{*, internal::*}, Runtime, Any, types};
pub struct Boolean {
refer:Ref,
}
impl Boolean {
pub fn new() -> Self {
Self {
refer:Runtime::acquire(Self::typeid()),
}
}
pub fn with(self, data:bool) -> Self
{
self.set(data);
self
}
pub fn set(&self, data:bool)
{
if let Some(memory) = unsafe {(self.refer.address_mut() as *mut bool).as_mut()} {
*memory = data;
}
}
pub fn get(&self) -> bool
{
if let Some(memory) = unsafe {(self.refer.address() as *const bool).as_ref()} {
*memory
} else {
false
}
}
}
impl Szun for Boolean {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::BOOLEAN]) }
}
impl SzunInternal for Boolean {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer } }
}
crate::impl_szun!(Boolean);

43
src/implement/integer.rs Normal file
View File

@ -0,0 +1,43 @@
use crate::{prelude::{*, internal::*}, Runtime, Any, types};
pub struct Integer {
refer:Ref,
}
impl Integer {
pub fn new() -> Self {
Self {
refer:Runtime::acquire(Self::typeid()),
}
}
pub fn with<T:num::ToPrimitive>(mut self, data:T) -> Self
{
self.set(data);
self
}
pub fn set<T:num::ToPrimitive>(&mut self, data:T)
{
let data = data.to_i64().unwrap_or_default();
if let Some(memory) = unsafe {(self.refer.address_mut() as *mut i64).as_mut()} {
*memory = data;
}
}
pub fn get<T:num::FromPrimitive + Default>(&self) -> T
{
T::from_i64(if let Some(memory) = unsafe {(self.refer.address() as *const i64).as_ref()} {
*memory
} else {
0
}).unwrap_or_default()
}
}
impl Szun for Integer {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::INTEGER]) }
}
impl SzunInternal for Integer {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer } }
}
crate::impl_szun!(Integer);

9
src/implement/mod.rs Normal file
View File

@ -0,0 +1,9 @@
pub mod any; pub use any::Any;
pub mod null; pub use null::Null;
pub mod boolean; pub use boolean::Boolean;
pub mod natural; pub use natural::Natural;
pub mod integer; pub use integer::Integer;
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;

43
src/implement/natural.rs Normal file
View File

@ -0,0 +1,43 @@
use crate::{prelude::{*, internal::*}, Runtime, Any, types};
pub struct Natural {
refer:Ref,
}
impl Natural {
pub fn new() -> Self {
Self {
refer:Runtime::acquire(Self::typeid()),
}
}
pub fn with<T:num::ToPrimitive>(mut self, data:T) -> Self
{
self.set(data);
self
}
pub fn set<T:num::ToPrimitive>(&mut self, data:T)
{
let data = data.to_u64().unwrap_or_default();
if let Some(memory) = unsafe {(self.refer.address_mut() as *mut u64).as_mut()} {
*memory = data;
}
}
pub fn get<T:num::FromPrimitive + Default>(&self) -> T
{
T::from_u64(if let Some(memory) = unsafe {(self.refer.address() as *const u64).as_ref()} {
*memory
} else {
0
}).unwrap_or_default()
}
}
impl Szun for Natural {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::NATURAL]) }
}
impl SzunInternal for Natural {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer } }
}
crate::impl_szun!(Natural);

16
src/implement/null.rs Normal file
View File

@ -0,0 +1,16 @@
use crate::{prelude::{*, internal::*}, Runtime, Any, types};
pub struct Null { }
impl Null {
pub fn new() -> Self {
Self { }
}
}
impl Szun for Null {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::BOOLEAN]) }
}
impl SzunInternal for Null {
fn to_ref(&self) -> Ref { Ref::null() }
fn from_ref(_:Ref) -> Self { Self { } }
}
crate::impl_szun!(Null);

120
src/implement/optional.rs Normal file
View File

@ -0,0 +1,120 @@
use std::marker::PhantomData;
use internal::SzunInternal;
use crate::{prelude::*, Runtime, Any, types};
pub struct Optional<T> where T:Szun {
refer:Ref,
phantom:PhantomData<T>,
}
impl<T:Szun> Optional<T> {
pub fn new() -> Self {
Self {
refer:Runtime::acquire(Self::typeid()),
phantom:PhantomData,
}
}
pub fn with(self, data:&T) -> Self
{
self.set(data);
self
}
pub fn with_default(self) -> (Self, T)
{
self.set_default();
let refer = self.refer;
(self, T::from_ref(refer.inner()))
}
pub fn set(&self, data:&T)
{
let inner_type = Runtime::type_in(self.refer.typeid());
let inner_size = types::size(inner_type);
let mut bytes = vec![0u8; types::size(inner_type)];
Runtime::load(data.to_ref(), bytes.as_ptr() as _, 0, inner_size);
Runtime::store(self.refer, bytes.as_ptr() as _, 0, inner_size);
Runtime::write(self.refer, 0xFF, inner_size);
if !types::primitive(data.to_ref().typeid()) {
bytes.fill(0);
Runtime::store(data.to_ref(), bytes.as_ptr() as _, 0, inner_size);
}
}
pub fn set_default(&self) -> T
{
let inner_type = Runtime::type_in(self.refer.typeid());
Runtime::write(self.refer, 0xFF, types::size(inner_type));
T::from_ref(self.refer.temporary())
}
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)];
Runtime::store(self.refer, bytes.as_ptr() as _, 0, inner_size);
Runtime::write(self.refer, 0x00, inner_size);
}
pub fn get(&self) -> std::option::Option<T>
{
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);
if flag != 0 {
let refer = self.refer;
Some(T::from_ref(refer.inner()))
} else {
None
}
}
pub fn is_some(&self) -> bool
{
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);
flag != 0
}
pub fn is_none(&self) -> bool
{
!self.is_some()
}
}
impl<T:Szun> Szun for Optional<T> {
fn typeid() -> usize { Runtime::type_from(T::typeid(), &[types::OPTIONAL]) }
}
impl<T:Szun> SzunInternal for Optional<T> {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer, phantom:PhantomData } }
fn mem_clone(refer:Ref, memory:std::prelude::v1::Option<Ref>) -> Ref {
// Allocate new memory if not provided
let memory = if let Some(memory) = memory {
memory
} else {
Runtime::acquire(refer.typeid())
};
// Copy memory
clone(refer.inner(), Some(memory.inner()));
memory
}
fn mem_drop(refer:Ref) {
drop(refer.inner())
}
}
crate::impl_szun_generic!(Optional<T>);

109
src/implement/sequence.rs Normal file
View File

@ -0,0 +1,109 @@
use internal::SzunInternal;
use crate::{prelude::*, Runtime, Any, types};
pub(crate) struct Data {
pub capacity:usize,
pub length:usize,
pub data:*const u8,
}
pub struct Sequence {
refer:Ref,
}
impl Sequence {
pub fn new() -> Self {
Self {
refer:Runtime::acquire(Self::typeid()),
}
}
pub fn with(mut self, data:&[u8]) -> Self
{
self.set(data);
self
}
pub fn with_str(mut self, data:&str) -> Self
{
self.set(data.as_bytes());
self
}
pub fn set(&mut self, data:&[u8])
{
if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} {
// Reallocate memory if capacity is insufficient
if header.capacity < data.len() {
// Free existing memory
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); }
}
}
// Allocate sufficient memory
header.capacity = data.len();
if let Ok(layout) = std::alloc::Layout::from_size_align(header.capacity, 1) {
header.data = unsafe {std::alloc::alloc(layout)};
} else {
header.data = std::ptr::null();
header.capacity = 0;
}
}
// Copy data to memory
if !header.data.is_null() {
header.length = data.len();
unsafe { std::ptr::copy_nonoverlapping(data.as_ptr() as _, header.data as _, data.len()); }
}
}
}
pub fn set_str(&mut self, data:&str)
{
self.set(data.as_bytes())
}
pub fn get(&self) -> Vec<u8>
{
if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} {
// Load data
let mut data = vec![0u8; header.length];
unsafe { std::ptr::copy_nonoverlapping(header.data as _, data.as_mut_ptr() as _, header.length); }
data
} else {
Vec::new()
}
}
pub fn get_str(&self) -> String
{
String::from_utf8(self.get()).unwrap_or_default()
}
pub fn len(&self) -> usize
{
if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} {
header.length
} else {
0
}
}
pub fn capacity(&self) -> usize
{
if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} {
header.capacity
} else {
0
}
}
}
impl Szun for Sequence {
fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::SEQUENCE]) }
}
impl internal::SzunInternal for Sequence {
fn to_ref(&self) -> Ref { self.refer }
fn from_ref(refer:Ref) -> Self { Self { refer } }
}
crate::impl_szun!(Sequence);

7
src/lib.rs Normal file
View File

@ -0,0 +1,7 @@
#![allow(dead_code)]
mod util;
pub mod prelude; pub use prelude::*;
mod types;
mod runtime; use runtime::Runtime;
mod implement; pub use implement::*;

15
src/prelude/clone.rs Normal file
View File

@ -0,0 +1,15 @@
use crate::Ref;
pub fn clone(refer:Ref, memory:Option<Ref>) -> Ref
// Deep copy an object and return the copy's reference.
//
{
use crate::{*, prelude::internal::*};
match Runtime::type_of(refer.typeid()) {
types::SEQUENCE => Sequence::mem_clone(refer, memory),
types::OPTIONAL => Optional::<Any>::mem_clone(refer, memory),
types::ARRAY => Array::<Any,0>::mem_clone(refer, memory),
_ => Any::mem_clone(refer, memory),
}
}

34
src/prelude/drop.rs Normal file
View File

@ -0,0 +1,34 @@
use crate::{prelude::{*, internal::*}, types::*, implement::*};
pub fn drop(refer:Ref)
{
if !refer.is_temporary() {
drop_memory(refer);
Runtime::release(refer);
}
}
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); }
}
}
}
}
_ => { }
}
}

70
src/prelude/encode.rs Normal file
View File

@ -0,0 +1,70 @@
use crate::{*, prelude::{*, internal::*}, types::*};
pub fn encode(refer:Ref) -> Vec<u8>
{
let refer = refer.temporary();
let mut result = Vec::new();
let typeid = Runtime::type_of(refer.typeid());
match typeid {
BOOLEAN => {
// <Data:1>
//
let data = Boolean::from_ref(refer);
result.push(data.get() as u8);
}
NATURAL => {
// <Data:Uint>
//
let data = Natural::from_ref(refer);
result.append(&mut data.get::<u64>().pack());
}
INTEGER => {
// <Data:Int>
//
let _data = Integer::from_ref(refer);
//result.append(&mut data.get::<i64>().pack());
}
BLOCK => {
// <Data:N>
//
let data = Block::<0>::from_ref(refer);
result.append(&mut data.get());
}
SEQUENCE => {
// <Length:Uint> <Data:Length>
//
let data = Sequence::from_ref(refer);
result.append(&mut (data.len() as u64).pack());
result.append(&mut data.get());
}
OPTIONAL => {
// <IsSome:1> <Data:N>?
//
let data = Optional::<Any>::from_ref(refer);
let is_some = data.is_some();
result.push(is_some as u8);
if let Some(value) = data.get() {
result.append(&mut encode(value.to_ref()));
}
}
_ => { }
}
result
}
pub fn decode(refer:Ref, _data:&[u8], _index:&mut usize) -> Result<(),()>
{
let typeid = Runtime::type_of(refer.typeid());
match typeid {
_ => { }
}
Err(())
}

13
src/prelude/implement.rs Normal file
View File

@ -0,0 +1,13 @@
use crate::prelude::{*, internal::*};
pub(crate) fn to_any<T:Szun>(data:T) -> Any
{
Any::from_ref(data.to_ref())
}
pub(crate) fn from_any<T:Szun>(any:Any) -> Result<T,()>
{
if any.typeid() == T::typeid()
|| (Runtime::type_of(any.typeid()) == Runtime::type_of(T::typeid()) && Runtime::type_in(T::typeid()) == 0)
{ Ok(T::from_ref(any.refer)) } else { Err(()) }
}

View File

@ -0,0 +1,25 @@
use crate::{Ref, Runtime, types};
#[allow(drop_bounds)]
pub(crate) trait SzunInternal {
fn to_ref(&self) -> Ref;
fn from_ref(refer:Ref) -> Self;
fn mem_clone(refer:Ref, memory:Option<Ref>) -> Ref {
let typeid = refer.typeid();
// Acquire memory if not provided
let memory = if let Some(memory) = memory {
memory
} else {
Runtime::acquire(typeid)
};
// Copy data to destination
Runtime::copy(refer.address(), memory.address_mut(), types::size(typeid));
memory
}
fn mem_drop(_refer:Ref) { /* Do nothing */ }
}

38
src/prelude/mod.rs Normal file
View File

@ -0,0 +1,38 @@
use crate::{Runtime, Any};
use pack::prelude::*;
pub mod internal;
mod refer; pub(crate) use refer::Ref;
mod encode; pub(crate) use encode::*;
#[allow(drop_bounds, private_bounds)]
pub trait Szun : internal::SzunInternal + Clone + TryFrom<Any> + Into<Any> + Drop {
fn typeid() -> usize;
fn compatible<T:Szun>(&self, data:&T) -> bool
{
let data_type = data.to_ref().typeid();
let self_type = self.to_ref().typeid();
data_type == Runtime::type_in(self_type)
|| Runtime::type_in(self_type) == 0
}
fn encode(&self) -> Vec<u8> { encode(self.to_ref()) }
fn decode(&mut self, bytes:&Vec<u8>, index:&mut usize) -> Result<(),()> { decode(self.to_ref(), bytes, index) }
fn tag(&self) -> Vec<u8>
{
let mut result = Vec::new();
let mut next = Some(Self::typeid());
while let Some(next_id) = next {
result.append(&mut 0u32.pack());
next = Runtime::type_in_opt(next_id);
}
result
}
}
mod implement; pub(crate) use implement::*;
mod clone; pub(crate) use clone::*;
mod drop; pub(crate) use drop::*;

58
src/prelude/refer.rs Normal file
View File

@ -0,0 +1,58 @@
use crate::Runtime;
#[derive(Clone, Copy)]
pub struct Ref {
typeid:usize,
address:*const u8,
}
impl Ref {
pub(crate) fn new(typeid:usize, address:*const u8) -> Self
{
Self {
typeid,
address,
}
}
pub fn null() -> Self
{
Self {
typeid:0,
address:std::ptr::null(),
}
}
pub fn inner(&self) -> Self
{
let mut refer = *self;
refer.typeid = Runtime::type_in(self.typeid);
self.temporary()
}
pub fn temporary(&self) -> Self
{
let mut refer = *self;
refer.typeid |= 1 << (usize::BITS - 1);
refer
}
pub fn is_temporary(&self) -> bool
{
(self.typeid & (1 << (usize::BITS - 1))) != 0
}
pub fn typeid(&self) -> usize
{
self.typeid & !(1 << (usize::BITS - 1))
}
pub fn address(&self) -> *const u8
{
self.address
}
pub fn address_mut(&self) -> *mut u8
{
self.address as _
}
}

118
src/runtime/mod.rs Normal file
View File

@ -0,0 +1,118 @@
use crate::{prelude::*, types};
mod typetree; use typetree::TypeTree;
struct RuntimeData {
terms:Vec<u8>,
types:TypeTree,
}
impl RuntimeData {
const fn init() -> Self
{
Self {
terms:Vec::new(),
types:TypeTree::new(),
}
}
fn acquire(&mut self, typeid:usize) -> Ref
{
use std::alloc::{alloc_zeroed, Layout};
let size = types::size(typeid);
if size > 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()
}
} else {
Ref::null()
}
}
fn release(&mut self, refer:Ref)
{
use std::alloc::{dealloc, Layout};
let typeid = refer.typeid();
let size = types::size(typeid);
if size > 0 {
if let Ok(layout) = Layout::from_size_align(size, types::align(typeid)) {
unsafe {
dealloc(refer.address_mut(), layout);
}
}
}
}
fn store(&mut self, refer:Ref, data:*const u8, index:usize, len:usize)
{
unsafe {
std::ptr::copy_nonoverlapping(data, refer.address_mut().add(index), len);
}
}
fn load(&mut self, refer:Ref, data:*mut u8, index:usize, len:usize)
{
unsafe {
std::ptr::copy_nonoverlapping(refer.address().add(index), data, len);
}
}
fn copy(&mut self, src:*const u8, dst:*mut u8, len:usize)
{
unsafe {
std::ptr::copy_nonoverlapping(src, dst, len);
}
}
fn write(&mut self, refer:Ref, data:u8, index:usize)
{
unsafe { *refer.address_mut().byte_add(index) = data; }
}
fn zero(&mut self, refer:Ref)
{
let size = types::size(refer.typeid());
for i in 0..size {
unsafe { *refer.address_mut().byte_add(i) = 0; }
}
}
fn type_from(&mut self, parent:usize, types:&[usize]) -> usize
{
self.types.outer(parent, types)
}
fn type_in(&mut self, typeid:usize) -> Option<usize>
{
self.types.inner(typeid)
}
fn type_of(&mut self, typeid:usize) -> usize
{
self.types.value(typeid)
}
}
static mut RUNTIME :RuntimeData = RuntimeData::init();
pub struct Runtime { }
impl Runtime {
pub fn acquire(typeid:usize) -> Ref {unsafe{ RUNTIME.acquire(typeid) }}
pub fn release(refer:Ref) {unsafe{ RUNTIME.release(refer) }}
pub fn store(refer:Ref, data:*const u8, index:usize, len:usize) {unsafe{ RUNTIME.store(refer, data, index, len) }}
pub fn load(refer:Ref, data:*mut u8, index:usize, len:usize) {unsafe{ RUNTIME.load(refer, data, index, len) }}
pub fn copy(src:*const u8, dst:*mut u8, len:usize) {unsafe{ RUNTIME.copy(src, dst, len) }}
pub fn write(refer:Ref, data:u8, index:usize) {unsafe { RUNTIME.write(refer, data, index) }}
pub fn zero(refer:Ref) {unsafe { RUNTIME.zero(refer) }}
pub fn type_of(typeid:usize) -> usize {unsafe{ RUNTIME.type_of(typeid) }}
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) }}
}

104
src/runtime/typetree.rs Normal file
View File

@ -0,0 +1,104 @@
struct Node {
typeid:usize,
parent:Option<usize>,
child:Option<usize>,
next:Option<usize>,
}
pub struct TypeTree {
data:Vec<Node>,
}
impl TypeTree {
pub const fn new() -> Self
{
Self {
data:Vec::new(),
}
}
pub fn value(&self, id:usize) -> usize
{
if id < self.data.len() {
self.data[id].typeid
} else {
0
}
}
pub fn inner(&self, id:usize) -> Option<usize>
{
if id < self.data.len() {
self.data[id].parent
} else {
None
}
}
pub fn outer(&mut self, typeid:usize, types:&[usize]) -> usize
{
let mut itr = typeid;
let mut type_index = 0;
if self.data.len() == 0 {
self.data.push(Node {
typeid:0,
parent:None,
child:None,
next:None,
});
}
if typeid != 0 {
if let Some(child) = self.data[itr].child {
itr = child;
} else {
let node = Node {
typeid:types[type_index],
parent:Some(itr),
child:None,
next:None,
};
itr = self.data.len();
self.data.push(node);
}
}
while type_index < types.len() {
if self.data[itr].typeid == types[type_index] {
if type_index + 1 < types.len() {
if let Some(child) = self.data[itr].child {
itr = child;
} else {
let node = Node {
typeid:types[type_index],
parent:Some(itr),
child:None,
next:None,
};
itr = self.data.len();
self.data.push(node);
}
type_index += 1;
} else {
break;
}
} else {
if let Some(next) = self.data[itr].next {
itr = next;
} else {
let node = Node {
typeid:types[type_index],
parent:self.data[itr].parent,
child:None,
next:None,
};
self.data[itr].next = Some(self.data.len());
itr = self.data.len();
self.data.push(node);
}
}
}
itr
}
}

140
src/types.rs Normal file
View File

@ -0,0 +1,140 @@
use crate::Runtime;
/*
** Type Codes
*/
pub const ANY :usize = 0x00;
pub const BOOLEAN :usize = 0x01;
pub const BYTE :usize = 0x02;
pub const CHAR :usize = 0x03;
pub const NATURAL :usize = 0x10;
pub const INTEGER :usize = 0x11;
pub const DECIMAL :usize = 0x12;
pub const SIGNIFICANT :usize = 0x13;
pub const BLOCK :usize = 0x20;
pub const SEQUENCE :usize = 0x21;
pub const VAR :usize = 0x30;
pub const OPTIONAL :usize = 0x31;
pub const ARRAY :usize = 0x32;
pub const LIST :usize = 0x33;
pub const GRAPH :usize = 0x34;
pub const TRIE :usize = 0x35;
pub const MAP :usize = 0x40;
pub const SPARSE :usize = 0x41;
pub const POOL :usize = 0x42;
pub const TABLE :usize = 0x43;
pub const ENUM :usize = 0x7D;
pub const RECORD :usize = 0x7E;
pub const SCHEMA :usize = 0x7F;
pub fn size(typeid:usize) -> usize
// Byte size of static data in memory.
//
{
use std::mem::size_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,
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))
},
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,
}
}
pub fn primitive(typeid:usize) -> bool
// Whether type may be shallow copied.
//
{
match Runtime::type_of(typeid) {
ANY | BOOLEAN
| BYTE | CHAR
| NATURAL | INTEGER | DECIMAL | SIGNIFICANT
| BLOCK
=> true,
_ => false,
}
}
pub fn tag_stack(typeid:usize) -> usize
// Number of dependent tags following root.
//
{
match Runtime::type_of(typeid) {
ANY => 1,
BLOCK => 1,
OPTIONAL => 1,
ARRAY => 2,
LIST => 1,
GRAPH => 1,
TRIE => 1,
MAP => 1,
SPARSE => 1,
POOL => 1,
TABLE => 2,
RECORD => 1,
_ => 0,
}
}

39
src/util/macros.rs Normal file
View File

@ -0,0 +1,39 @@
#[macro_export]
macro_rules! impl_szun {
($type_name:ty) => {
impl Into<Any> for $type_name { fn into(self) -> Any { to_any(self) } }
impl TryFrom<Any> for $type_name { type Error = (); fn try_from(any: Any) -> Result<Self, Self::Error> { from_any(any) } }
impl Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } }
impl Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } }
}
}
#[macro_export]
macro_rules! impl_szun_generic {
($type_name:ty) => {
impl<T:Szun> Into<Any> for $type_name { fn into(self) -> Any { to_any(self) } }
impl<T:Szun> TryFrom<Any> for $type_name { type Error = (); fn try_from(any: Any) -> Result<Self, Self::Error> { from_any(any) } }
impl<T:Szun> Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } }
impl<T:Szun> Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } }
}
}
#[macro_export]
macro_rules! impl_szun_sized {
($type_name:ty) => {
impl<const N:usize> Into<Any> for $type_name { fn into(self) -> Any { to_any(self) } }
impl<const N:usize> TryFrom<Any> for $type_name { type Error = (); fn try_from(any: Any) -> Result<Self, Self::Error> { from_any(any) } }
impl<const N:usize> Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } }
impl<const N:usize> Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } }
}
}
#[macro_export]
macro_rules! impl_szun_generic_sized {
($type_name:ty) => {
impl<T:Szun, const N:usize> Into<Any> for $type_name { fn into(self) -> Any { to_any(self) } }
impl<T:Szun, const N:usize> TryFrom<Any> for $type_name { type Error = (); fn try_from(any: Any) -> Result<Self, Self::Error> { from_any(any) } }
impl<T:Szun, const N:usize> Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } }
impl<T:Szun, const N:usize> Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } }
}
}

1
src/util/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod macros;