Refactor object interfaces.

This commit is contained in:
yukirij 2024-06-21 00:57:33 -07:00
parent 41331e8e2b
commit 8116af305f
84 changed files with 5122 additions and 4905 deletions

View File

@ -11,6 +11,7 @@ publish = false
cc = "1.0" cc = "1.0"
[dependencies] [dependencies]
num = "0.4.3"
[profile.dev] [profile.dev]
opt-level = 0 opt-level = 0

915
README.md
View File

@ -14,189 +14,41 @@ The notation may be parsed and loaded at runtime or compiled directly into encod
# Runtime Documentation # Runtime Documentation
## Conventions
### Namespacing
Examples in this documentation will assume inclusion of the szun namespace.
Practical examples should use `szun::` or `use szun::{...};` in limited scopes.
### Interface Usage
While the runtime provides methods for directly acquring and releasing memory, it is recommended that developers use typed interfaces to ensure memory is freed upon leaving scope.
## Data Types ## Data Types
|Type|Code|Parameters|Description| |Status|Type|Code|Parameters|Description|
|---|---|---|---| |---|---|---|---|---|
|Undefined|x00|--|Data is not defined| |x|None|x00|--|No data|
|Varying|x01|--|Stores any data type| |x|Boolean|x01|--|True or false|
|Boolean|x02|--|True or false| |x|Byte|x04|--|0-255|
|Natural|x10|--|Non-negative integers| |x|Char|x05|--|Unicode codepoint|
|Integer|x11|--|Positive and negative whole numbers| |x|Natural|x08|--|Non-negative integers|
|Decimal|x12|mantissa|Fixed-maginutide rational numbers| |x|Integer|x09|--|Positive and negative whole numbers|
|Significant|x13|--|Variable-magnitude rational numbers| |x|Decimal|x0A|mantissa|Fixed-maginutide rational numbers|
|Block|x1e|size|Constant-sized series of bytes| |x|Significant|x0B|--|Variable-magnitude rational numbers|
|Sequence|x1f|--|Variable-sized series of bytes| |x|Complex|x0C|--|Complex number|
|Array|x22|size, type|Constant-sized, indexed collection| |x|Range|x0F|min, max|...|
|List|x23|type|Variable-sized, indexed collection| |x|Block|x10|size|Constant-sized series of bytes|
|Sparse|x24|type|Variable-sized, discontinuously indexed collection| |x|Sequence|x11|--|Variable-sized series of bytes|
|Record|x7e|schema|Instance of a schema| |x|Varying|x20|--|Any data|
|Schema|x7f|--|Definition of abstract structure| |x|Optional|x21|--|Data or None|
|x|Array|x21|size, type|Constant-sized, indexed collection|
|x|List|x23|type|Variable-sized, indexed collection|
|x|Bag|x24|type|Variable-sized, indexed collection with repetition count|
|x|Sparse|x25|type|Variable-sized, discontinuously indexed collection|
|x|Trie|x26|type|Mapping of sequences onto data|
|x|Map|x26|key_type, data_type|Mapping of data onto data|
|x|Tree|x26|type|Collection of directed nodes|
|x|Graph|x26|data_type, edge_type|Collection of nodes and edges|
|x|Enum|x7d|schema|Indexed enuemration of values|
|x|Record|x7e|schema|Instance of a schema|
|x|Schema|x7f|--|Definition of abstract structure|
### Type Building ### Type Building
Type building functions are used to generate identifiers used in the construction of complex data types.
* `varying()`
* `boolean()`
* `natural()`
* `integer()`
* `decimal(mantissa)`
* `significant()`
* `block(size)`
* `sequence()`
* `array(size, type)`
* `list(type)`
* `sparse(type)`
* `record(schema)`
* `schema()`
#### Example
This example produces an identifier representing a block of 4 bytes, which can be used to construct a list containing that type.
```
let type_id = block(4);
let list = List::new(type_id);
```
## Code Examples
### Example 1
```
const VEC3F :usize = 0x200;
const VEC3U :usize = 0x201;
const MESH :usize = 0x202;
fn vec3f(x:f64, y:f64, z:f64) -> szun::Record
{
use szun::*;
Record::with_values(VEC3F, vec![
*Significant::with(x),
*Significant::with(y),
*Significant::with(z),
]).unwrap()
}
fn vec3u(x:u64, y:u64, z:u64) -> szun::Record
{
use szun::*;
Record::with_values(VEC3U, vec![
*Natural::with(x),
*Natural::with(y),
*Natural::with(z),
]).unwrap()
}
fn main()
{
use szun::*;
// Vec3f
Schema::with(vec![
("x", significant()),
("y", significant()),
("z", significant()),
]).bind(VEC3F);
// Vec3u
Schema::with(vec![
("x", natural()),
("y", natural()),
("z", natural()),
]).bind(VEC3U);
// Mesh
Schema::with(vec![
("vertices", list(record(VEC3F))),
("faces", list(record(VEC3U))),
]).bind(MESH);
let pyramid = Record::with(MESH, vec![
("vertices", *List::with(record(VEC3F), vec![
*vec3f(0.0, 2.0, 0.0),
*vec3f(1.0, 0.0, 1.0),
*vec3f(1.0, 0.0, -1.0),
*vec3f(-1.0, 0.0, -1.0),
*vec3f(-1.0, 0.0, 1.0),
])),
("faces", *List::with(record(VEC3U), vec![
*vec3u(0, 1, 2),
*vec3u(0, 2, 3),
*vec3u(0, 3, 4),
*vec3u(0, 4, 1),
*vec3u(1, 2, 3),
*vec3u(1, 3, 4),
])),
]).unwrap();
}
```
## Global Functions ## Global Functions
`acquire(type) -> Reference` ## Binary Encoding
Allocate a new instance of the provided type.
> This method of allocation does not provide automatic memory management.
```
let refer = acquire(list(integer()));
```
---
`release(refer:Reference)`
Destruct and deallocate an object.
```
release(refer);
```
---
`transfer(dst:Reference, src:Reference) -> Result<(),()>`
Move an object from one location to another, clearing the original.
```
let original = Sequence::with("Hello, world!");
let target = Sequence::new();
println!("{}", original.get()); // prints "Hello, world!"
println!("{}", target.get()); // prints ""
transfer(target, original).ok();
println!("{}", original.get()); // prints ""
println!("{}", target.get()); // prints "Hello, world!"
```
---
`copy(dst:Reference, src:Reference) -> Result<(),()>`
Copy the contents of an object to another location, keeping the original.
```
let original = Sequence::with("Hello, world!");
let target = Sequence::new();
println!("{}", original.get()); // prints "Hello, world!"
println!("{}", target.get()); // prints ""
copy(target, original).ok();
println!("{}", original.get()); // prints "Hello, world!"
println!("{}", target.get()); // prints "Hello, world!"
```
---
## Encoding
Encoding converts data between runtime memory and binary serialization. Encoding converts data between runtime memory and binary serialization.
`encode(refer:Reference) -> Vec<u8>` `encode(refer:Reference) -> Vec<u8>`
@ -218,714 +70,3 @@ The raw variant does not decode a tag prefix on the root object.
The tag variant only decodes a tag prefix. The tag variant only decodes a tag prefix.
--- ---
## Language Compiler
> Not implemented
## Common Methods
`new() -> Self`
```
let value = Integer::new();
```
---
`try_from(refer:Reference) -> Result<Self,()>`
```
match Integer::from(list.at(0)) {
Ok(int) => { println!("Integer: {}", int.get()); }
Err(_) => { println!("Not Integer"); }
}
```
---
`*Dereference -> Reference`
```
let refer = *Integer::new();
```
---
## Reference
Identifier for an object in memory.
`is_null() -> bool`
Indicates whether the identifier represents a valid object.
---
`kind() -> usize`
Returns the type identifier of the referenced object.
---
## Varying
Stores a value of any other type.
`is_null() -> bool`
Indicates whether or not the variable contains a object.
---
`get() -> Reference`
Returns a reference to the contained object.
```
let var = Varying::with(*Boolean::with(true));
let value = Boolean::from(var.get()).unwrap();
```
---
`set(refer:Reference)`
Replaces the contained object.
```
let var = Varying::new();
var.set(*Sequence::with("Hello!"));
```
---
`clear()`
Removes the contained object.
---
`kindof() -> usize`
Returns the type identifier of the contained object.
---
## Boolean
Stores the value true or false.
`get() -> bool`
Returns the contained value.
```
let value = Boolean::with(true);
if value.get() {
println!("True");
}
```
---
`set(value:bool)`
Replaces the contained value.
```
let mut value = Boolean::new();
value.set(true);
```
---
## Natural
Stores a non-negative integer value.
`get() -> u64`
Returns the contained value.
```
let value = Integer::with(-1);
println!("{}", value.get());
```
---
`set(value:u64)`
Replaces the contained value.
```
let mut value = Integer::new();
value.set(-273);
```
---
## Integer
Stores a signed integer value.
`get() -> i64`
Returns the contained value.
```
let value = Integer::with(-1);
println!("{}", value.get());
```
---
`set(value:i64)`
Replaces the contained value.
```
let mut value = Integer::new();
value.set(-273);
```
---
## Decimal
Stores a constant-magnitude rational number of specified mantissa size.
`new(mantissa:u8) -> Self`
---
`with(mantissa:u8, value:f64) -> Self`
---
`with_raw(mantissa:u8, value:i64) -> Self`
---
`get() -> f64`
Returns the contained value.
---
`get_raw() -> i64`
Returns the raw contained value.
---
`set(value:f64)`
Replaces the contained value.
---
`set_raw(value:i64)`
Replaces the raw contained value.
---
`-Neg() -> Self`
`Add+(rhs:Self) -> Self`
`AddAssign+=(rhs:Self)`
`Sub-(rhs:Self) -> Self`
`SubAssign-=(rhs:Self)`
`Mul*(rhs:Self) -> Self`
`MulAssign*=(rhs:Self)`
`Div/(rhs:Self) -> Self`
`DivAssign/=(rhs:Self)`
`Rem%(rhs:Self) -> Self`
`RemAssign%=(rhs:Self)`
---
## Significant
Stores a variable-magnitude rational number.
> Encode/decode not implemented.
`get() -> f64`
Returns the contained value.
---
`set(value:f64)`
Replaces the contained value.
---
## Block
Constant-sized series of bytes.
`new(size:usize) -> Block`
Produces a new block of the specified size.
---
`size() -> usize`
Returns the size of the allocated block.
---
`get() -> Vec<u8>`
Returns the contents of the block.
---
`at(index:usize) -> u8`
Returns the byte at the specified index or zero if out of bounds.
---
`set(data:Vec<u8>)`
Replaces the contents of the block up to the length of the parameter.
---
`set_at(index:usize, data:u8)`
Replaces the byte at the given index.
---
## Sequence
Variable-sized series of bytes.
`capacity() -> usize`
Returns the memory capacity of the sequeunce.
---
`size() -> usize`
Returns the length of the series.
---
`get() -> String`
Returns a UTF-8 string representation of the series.
---
`get_raw() -> Vec<u8>`
Returns the contents of the series.
---
`at(index:usize) -> u8`
Returns the byte at the specified index or zero if out of bounds.
---
`set(data:&str)`
Replaces the contents with the byte representation of a string.
```
let text = Sequence::new();
text.set("こんにちは");
```
---
`set_raw(data:Vec<u8>)`
Replaces the contents with a series of bytes.
```
let bytes = Sequence::new();
bytes.set_raw(vec![1, 2, 3, 4, 5, 6]);
```
---
`set_at(index:usize, data:u8)`
Replaces a byte at the given index.
---
`reserve(capacity:usize)`
Reallocates the sequeunce to have capacity not less than the specified size.
---
## Array
Constant-sized, indexed collection of items.
`new(length:usize, type_id:usize) -> Array`
Produces a new array of given type and length.
---
`length() -> usize`
Returns the length of the array.
---
`at(index:usize) -> Reference`
Returns a reference to the element at the given index or a null reference if out of bounds.
---
`set(index:usize, source:Reference)`
Replaces the element at the given index with a copy of the source.
---
`kind() -> usize`
Returns the type identifier of the contents.
---
## List
Variable-sized, indexed collection of items.
`new(type_id:usize) -> List`
Produces a new list of the given type.
---
`with(type_id:usize, data:Vec<Reference>) -> List`
Produces a new list with the provided contents.
```
let list = List::with(natural(), vec![
*Natural::with(1),
*Natural::with(2),
*Natural::with(3),
]);
```
---
`capacity() -> usize`
Returns the allocated capacity of the list.
---
`length() -> usize`
Returns the length of the list.
---
`at(index:usize) -> Reference`
Returns the object at the given index or a null reference if out of bounds.
---
`get() -> Vec<Reference>`
Returns a vector containing references to the contents of the list.
---
`set(index:usize, source:Reference)`
Replaces the object at the given index with a copy of the source.
---
`insert(index:usize, source:Reference)`
Inserts a copy of the source at a given index.
---
`prepend(source:Reference)`
Adds an element to the start of the list.
---
`append(source:Reference)`
Adds an element to the end of the list.
---
`remove(index:usize)`
Removes the object at the given index from the list.
---
`clear()`
Removes all elements from the list.
---
`reserve(capacity:usize)`
Reallocates the list to have capacity not less than the specified size.
---
`kind() -> usize`
Returns the type identifier of the contents.
---
## Sparse
List of discontinuous indicies.
`new(type_id:usize) -> Sparse`
Produces a new sparse array of the specified type.
---
`with(type_id:usize, data:Vec<(usize, Reference)>) -> Sparse`
Produces a new sparse array with the specified contents.
```
let list = Sparse::with(natural(), vec![
(1, *Natural::with(10)),
(5, *Natural::with(50)),
(6, *Natural::with(60)),
(10, *Natural::with(100)),
]);
```
---
`length() -> usize`
Returns the number of elements in the collection.
---
`at(index:usize) -> Reference`
Returns a reference to the item at the specified index.
---
`has(key:usize) -> bool`
Returns whether the specified key is assigned.
---
`get(key:usize) -> Reference`
Returns a reference to the item at the specified key.
---
`set(key:usize, source:Reference)`
Adds or updates an element at the specified key.
---
`unset(key:usize)`
Removes an element from the collection.
---
`clear()`
Removes all elements from the collection.
---
`indexof(index:usize) -> usize`
Returns the key of the element at the specified index.
---
`kind() -> usize`
Returns the type identifier of the contents.
---
## Schema
Definition of an abstract structure composed of named items.
`with(members:Vec<(&str, usize)>) -> Schema`
Produces a schema with the provided member assignments.
```
let schema_rgba = Schema::with(vec![
("r", significant()),
("g", significant()),
("b", significant()),
("a", significant()),
]);
```
---
`length() -> usize`
Returns the number of members in the schema.
---
`get(index:usize) -> usize`
Returns the type identifier of the given index or zero if out of bounds.
---
`add(type_id:usize) -> usize`
Appends a member of the specified type to the schema.
---
`assign(key:&str, type_id:usize) -> usize`
Appends a member of the specified type to the schema and maps the provided string to that index.
---
`set(index:usize, type_id:usize)`
Replaces the type identifier of the member at the specified index.
---
`remove(index:usize)`
Removes the member at the given index from the schema.
---
`map(key:&str, index:usize)`
Maps a string to the specified index.
---
`unmap(key:&str)`
Removes a mapping of the specified string from the schema.
---
`clear()`
Removes all members and mappings from the schema.
---
`bind(id:usize)`
Submits the template to the schema database under the provided identifier.
> Note: zero is used as a wildcard identifier and is not a valid parameter.
```
let vec3i :usize = Schema::with(vec![
("x", integer()),
("y", integer()),
("z", integer()),
]).bind(0x100);
```
---
## Record
Instance of a schema.
`new(schema_id:usize) -> Result<Record,()>`
Produces a new record of the provided schema.
---
`with(schema_id:usize, data:Vec<(&str, Reference)>) -> Result<Record,()>`
Produces a record of the provided schema and keyed assignments.
---
`with_values(schema_id:usize, data:Vec<Reference>) -> Result<Record,()>`
Produces a record of the provided schema and indexed assignments.
---
`length() -> usisze`
Returns the number of elements in the record.
---
`at(index:usize) -> Reference`
Returns a reference to the member at the specified index.
---
`get(key:&str) -> Reference`
Returns a reference to the member with the specified key.
---
`set_at(index:usize, source:Reference)`
Replaces the member at the specified index with a copy of the source.
---
`set(key:&str, source:Reference)`
Replaces the member at the specified key with a copy of the source.
---
`keyof(index:usize) -> String`
Returns the string mapped to the specified index or an empty string if no mapping exists.
---
`indexof(key:&str) -> usize`
Returns the index of a mapped string or the number of elements in the record if no mapping exists.
---
`kindof(index:usize) -> usize`
Returns the type identifier of the given index.
---

View File

@ -1 +0,0 @@
fn main() { }

34
src/bin/sandbox.rs Normal file
View File

@ -0,0 +1,34 @@
use szun::*;
fn main() {
let mut int = Integer::new().with(512);
let boo = Boolean::new().with(false);
let mut var = Var::new();
var.set(&int);
let int2 :Integer = var.get();
println!("{}", int2.get::<i32>());
int.set(1024);
let mut lst = List::<Var>::new();
lst.push(&int);
lst.push(&boo);
int.set(20); lst.push(&int);
for i in 0..lst.len() {
if let Ok(int) = lst.get(i).try_get::<Integer>() {
println!("{}", int.get::<i32>());
}
}
let mut arr = Array::<2, Var>::new();
int.set(30); arr.set(0, &int);
arr.set(1, &boo);
for i in 0..arr.len() {
if let Ok(int) = arr.get(i).try_get::<Integer>() {
println!("{}", int.get::<i32>());
}
}
}

View File

@ -5,7 +5,7 @@ use crate::{
kind_hasinner, type_hasinner, type_inner, type_outer, kind_hasinner, type_hasinner, type_inner, type_outer,
type_key, type_innerkey, SparseHeader, type_key, type_innerkey, SparseHeader,
}, },
tag, types,
Object, Object,
util::*, util::*,
}; };
@ -43,20 +43,20 @@ 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 => { types::VARYING => {
let data = Varying::try_from(addr).unwrap(); let data = Varying::try_from(addr).unwrap();
result.append(&mut encode(data.get())); result.append(&mut encode(data.get()));
} }
tag::BOOLEAN => { types::BOOLEAN => {
result.append(&mut util::pack_natural(Boolean::try_from(addr).unwrap().get() as u64)); result.append(&mut util::pack_natural(Boolean::try_from(addr).unwrap().get() as u64));
} }
tag::NATURAL => { types::NATURAL => {
result.append(&mut util::pack_natural(Natural::try_from(addr).unwrap().get() as u64)); result.append(&mut util::pack_natural(Natural::try_from(addr).unwrap().get() as u64));
} }
tag::INTEGER => { types::INTEGER => {
result.append(&mut &mut util::pack_integer(Integer::try_from(addr).unwrap().get() as i64)); result.append(&mut &mut util::pack_integer(Integer::try_from(addr).unwrap().get() as i64));
} }
tag::DECIMAL => { types::DECIMAL => {
let mantissa = unsafe {type_innerkey(addr.class)}; let mantissa = unsafe {type_innerkey(addr.class)};
let raw = Decimal::try_from(addr).unwrap().get_raw(); let raw = Decimal::try_from(addr).unwrap().get_raw();
let whole = raw >> mantissa; let whole = raw >> mantissa;
@ -64,21 +64,21 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
result.append(&mut &mut util::pack_integer(whole)); result.append(&mut &mut util::pack_integer(whole));
result.append(&mut &mut util::pack_natural(fract)); result.append(&mut &mut util::pack_natural(fract));
} }
tag::SIGNIFICANT => { types::SIGNIFICANT => {
result.append(&mut vec![0]); result.append(&mut vec![0]);
} }
tag::BLOCK => { types::BLOCK => {
result.append(&mut Block::try_from(addr).unwrap().get()); result.append(&mut Block::try_from(addr).unwrap().get());
} }
tag::SEQUENCE => { types::SEQUENCE => {
let data = Sequence::try_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 => { types::ARRAY => {
let data = Array::try_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)} == types::VARYING {
result.append(&mut encode(data.at(i))); result.append(&mut encode(data.at(i)));
} }
else { else {
@ -86,11 +86,11 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
} }
tag::LIST => { types::LIST => {
let data = List::try_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)} == types::VARYING {
result.append(&mut encode(data.at(i))); result.append(&mut encode(data.at(i)));
} }
else { else {
@ -98,7 +98,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
} }
tag::SPARSE => { types::SPARSE => {
let data = crate::Sparse::try_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)};
@ -113,7 +113,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
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)} == types::VARYING {
result.append(&mut encode(data.at(i))); result.append(&mut encode(data.at(i)));
} }
else { else {
@ -121,10 +121,10 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
} }
tag::RECORD => { types::RECORD => {
let data = Record::try_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)) == types::VARYING {
result.append(&mut encode(data.at(i))); result.append(&mut encode(data.at(i)));
} }
else { else {
@ -132,7 +132,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
} }
tag::SCHEMA => { types::SCHEMA => {
let data = Schema::try_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));
@ -182,7 +182,7 @@ pub fn decode_tag(data:&Vec<u8>, index:&mut usize) -> Result<usize,()>
pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Object,()> pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Object,()>
{ {
match unsafe {type_key(type_id)} { match unsafe {type_key(type_id)} {
tag::VARYING => { types::VARYING => {
return match decode(data, index) { return match decode(data, index) {
Ok(value) => { Ok(value) => {
Ok(Object::Varying(Varying::with(value.get()))) Ok(Object::Varying(Varying::with(value.get())))
@ -190,16 +190,16 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
Err(_) => Err(()), Err(_) => Err(()),
} }
} }
tag::BOOLEAN => { types::BOOLEAN => {
return Ok(Object::Boolean(Boolean::with(unpack_natural(data, index) == 1))); return Ok(Object::Boolean(Boolean::with(unpack_natural(data, index) == 1)));
} }
tag::NATURAL => { types::NATURAL => {
return Ok(Object::Natural(Natural::with(unpack_natural(data, index)))); return Ok(Object::Natural(Natural::with(unpack_natural(data, index))));
} }
tag::INTEGER => { types::INTEGER => {
return Ok(Object::Integer(Integer::with(unpack_integer(data, index)))); return Ok(Object::Integer(Integer::with(unpack_integer(data, index))));
} }
tag::DECIMAL => { types::DECIMAL => {
let mantissa = unsafe {type_innerkey(type_id)}; let mantissa = unsafe {type_innerkey(type_id)};
let whole = unpack_integer(data, index); let whole = unpack_integer(data, index);
let fract = unpack_natural(data, index).reverse_bits() >> (u64::BITS as usize - mantissa); let fract = unpack_natural(data, index).reverse_bits() >> (u64::BITS as usize - mantissa);
@ -207,10 +207,10 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
return Ok(Object::Decimal(Decimal::with_raw(unsafe {type_innerkey(type_id)}, raw))); return Ok(Object::Decimal(Decimal::with_raw(unsafe {type_innerkey(type_id)}, raw)));
} }
tag::SIGNIFICANT => { types::SIGNIFICANT => {
return Err(()) return Err(())
} }
tag::BLOCK => { types::BLOCK => {
let size = unsafe {type_innerkey(type_id)}; let size = unsafe {type_innerkey(type_id)};
let mut bytes = Vec::<u8>::with_capacity(size); let mut bytes = Vec::<u8>::with_capacity(size);
if *index + size <= data.len() { if *index + size <= data.len() {
@ -221,7 +221,7 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
} }
return Ok(Object::Block(Block::with(size, bytes))); return Ok(Object::Block(Block::with(size, bytes)));
} }
tag::SEQUENCE => { types::SEQUENCE => {
let size = unpack_natural(data, index) as usize; let size = unpack_natural(data, index) as usize;
let mut bytes = Vec::<u8>::with_capacity(size); let mut bytes = Vec::<u8>::with_capacity(size);
if *index + size <= data.len() { if *index + size <= data.len() {
@ -232,13 +232,13 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
} }
return Ok(Object::Sequence(Sequence::with_raw(bytes))); return Ok(Object::Sequence(Sequence::with_raw(bytes)));
} }
tag::ARRAY => { types::ARRAY => {
let length = unsafe {type_innerkey(type_id)}; let length = unsafe {type_innerkey(type_id)};
let inner = unsafe {type_inner(type_inner(type_id))}; let inner = unsafe {type_inner(type_inner(type_id))};
let mut result = Array::new(length, inner); let mut result = Array::new(length, inner);
for i in 0..length { for i in 0..length {
match if unsafe {type_key(inner)} == tag::VARYING { match if unsafe {type_key(inner)} == types::VARYING {
decode(data, index) decode(data, index)
} else { } else {
decode_data(data, inner, index) decode_data(data, inner, index)
@ -250,7 +250,7 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
return Ok(Object::Array(result)); return Ok(Object::Array(result));
} }
tag::LIST => { types::LIST => {
let inner = unsafe {type_inner(type_id)}; let inner = unsafe {type_inner(type_id)};
let length = util::unpack_natural(data, index) as usize; let length = util::unpack_natural(data, index) as usize;
@ -258,7 +258,7 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
result.reserve(length); result.reserve(length);
for _ in 0..length { for _ in 0..length {
match if unsafe {type_key(inner)} == tag::VARYING { match if unsafe {type_key(inner)} == types::VARYING {
decode(data, index) decode(data, index)
} else { } else {
decode_data(data, inner, index) decode_data(data, inner, index)
@ -270,7 +270,7 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
return Ok(Object::List(result)); return Ok(Object::List(result));
} }
tag::SPARSE => { types::SPARSE => {
let inner = unsafe {type_inner(type_id)}; let inner = unsafe {type_inner(type_id)};
let mut result = crate::Sparse::new(inner); let mut result = crate::Sparse::new(inner);
@ -287,7 +287,7 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
for header in headers { for header in headers {
for i in 0..header.length { for i in 0..header.length {
match if unsafe {type_key(inner)} == tag::VARYING { match if unsafe {type_key(inner)} == types::VARYING {
decode(data, index) decode(data, index)
} else { } else {
decode_data(data, inner, index) decode_data(data, inner, index)
@ -302,7 +302,7 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
return Ok(Object::Sparse(result)); return Ok(Object::Sparse(result));
} }
tag::RECORD => { types::RECORD => {
return match Record::new(unsafe {type_innerkey(type_id)}) { return match Record::new(unsafe {type_innerkey(type_id)}) {
Ok(mut value) => { Ok(mut value) => {
for i in 0..value.length() { for i in 0..value.length() {
@ -318,7 +318,7 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Obj
Err(_) => Err(()), Err(_) => Err(()),
} }
} }
tag::SCHEMA => { types::SCHEMA => {
let mut result = Schema::new(); let mut result = Schema::new();
let length = util::unpack_natural(data, index) as usize; let length = util::unpack_natural(data, index) as usize;

View File

@ -0,0 +1,83 @@
use crate::runtime::{
Reference,
type_inner, type_key,
acquire, release,
array_length, array_at, array_update
};
use crate::tag;
use super::array;
/// Constant-sized, indexed, ordered collection.
pub struct Array {
managed:bool,
addr:Reference,
}
impl Array {
/// Allocates a new array of a given size and type.
///
/// # Arguments
///
/// * `length` - number of elements in the array
/// * `class` - type identifier of the array contents
///
/// # Examples
///
/// ```
/// // Produces an array of 8 integers.
/// let int_array = szun::Array::new(8, szun::integer());
/// ```
pub fn new(length:usize, class:usize) -> Self
{
Self {
managed:true,
addr:unsafe {acquire(array(length, class))},
}
}
pub fn with(length:usize, class:usize, data:Vec<Reference>) -> Self
{
let mut obj = Self::new(length, class);
for i in 0..usize::min(length, data.len()) {
obj.set(i, data[i]);
}
return obj;
}
pub fn length(&self) -> usize
{
unsafe {array_length(self.addr)}
}
pub fn set(&mut self, index:usize, source:Reference)
{
unsafe { array_update(self.addr, index, source); }
}
pub fn at(&self, index:usize) -> Reference
{
unsafe {array_at(self.addr, index)}
}
pub fn kind(&self) -> usize
{
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 {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Array {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

107
src/interface-old/block.rs Normal file
View File

@ -0,0 +1,107 @@
use crate::runtime::{
Reference,
acquire, release,
type_inner, type_key,
block_length,
block_set, block_get,
block_set_natural, block_get_natural,
block_set_integer, block_get_integer,
block_set_field, block_get_field,
};
use crate::tag;
use super::block;
pub struct Block {
managed:bool,
addr:Reference,
}
impl Block {
pub fn new(size:usize) -> Self
{
Self {
managed:true,
addr:unsafe {acquire(block(size))},
}
}
pub fn with(size:usize, data:Vec<u8>) -> Self
{
let mut obj = Self::new(size);
obj.set(data);
return obj;
}
pub fn size(&self) -> usize
{
unsafe {block_length(self.addr)}
}
pub fn set(&mut self, data:Vec<u8>)
{
let length = unsafe {type_key(type_inner(self.addr.class))};
for index in 0..usize::min(data.len(), length) {
unsafe {block_set(self.addr, index, data[index])};
}
}
pub fn set_u64(&self, data:u64)
{
unsafe {block_set_natural(self.addr, data)}
}
pub fn set_i64(&self, data:i64)
{
unsafe {block_set_integer(self.addr, data)}
}
pub fn set_field(&mut self, index:usize, length:usize, data:u64)
{
unsafe { block_set_field(self.addr, index, length, data); }
}
pub fn get(&self) -> Vec<u8>
{
let mut result = Vec::<u8>::new();
let length = unsafe {type_key(type_inner(self.addr.class))};
if length > 0 {
result.resize(length, 0);
for index in 0..length {
result[index] = unsafe {block_get(self.addr, index)};
}
}
return result;
}
pub fn get_u64(&self) -> u64
{
unsafe {block_get_natural(self.addr)}
}
pub fn get_i64(&self) -> i64
{
unsafe {block_get_integer(self.addr)}
}
pub fn get_field(&self, index:usize, length:usize) -> u64
{
unsafe {block_get_field(self.addr, index, length)}
}
}
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 {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Block {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

View File

@ -0,0 +1,62 @@
use crate::runtime::{
Reference,
acquire, release,
type_key,
bool_get, bool_set
};
use crate::tag;
use super::boolean;
pub struct Boolean {
managed:bool,
addr:Reference,
}
impl Boolean {
pub fn new() -> Self
{
Self {
managed:true,
addr:unsafe {acquire(boolean())},
}
}
pub fn with(value:bool) -> Self
{
let mut result = Self::new();
result.set(value);
return result;
}
pub fn set(&mut self, value:bool)
{
unsafe { bool_set(self.addr, value) };
}
pub fn get(&self) -> bool
{
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 {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Boolean {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}
impl Into<bool> for Boolean {
fn into(self) -> bool {
self.get()
}
}

View File

@ -1,47 +1,47 @@
use crate::tag; use crate::tag;
use crate::runtime; use crate::runtime;
pub fn inner(type_id:usize) -> usize { unsafe {runtime::type_inner(type_id)} } pub fn inner(type_id:usize) -> usize { unsafe {runtime::type_inner(type_id)} }
pub fn kind(type_id:usize) -> usize { unsafe {runtime::type_key(type_id)} } pub fn kind(type_id:usize) -> usize { unsafe {runtime::type_key(type_id)} }
pub fn null() -> usize { 0 } pub fn null() -> usize { 0 }
pub fn varying() -> usize { unsafe { runtime::type_outer(0, tag::VARYING) } } pub fn varying() -> usize { unsafe { runtime::type_outer(0, tag::VARYING) } }
pub fn boolean() -> usize { unsafe { runtime::type_outer(0, tag::BOOLEAN) } } pub fn boolean() -> usize { unsafe { runtime::type_outer(0, tag::BOOLEAN) } }
pub fn natural() -> usize { unsafe { runtime::type_outer(0, tag::NATURAL) } } 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(mantissa:usize) -> usize { pub fn decimal(mantissa:usize) -> usize {
unsafe { unsafe {
let inner_node = runtime::type_outer(0, mantissa); let inner_node = runtime::type_outer(0, mantissa);
runtime::type_outer(inner_node, tag::DECIMAL) 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);
runtime::type_outer(inner_node, tag::BLOCK) runtime::type_outer(inner_node, tag::BLOCK)
} }
} }
pub fn sequence() -> usize { unsafe { runtime::type_outer(0, tag::SEQUENCE) } } pub fn sequence() -> usize { unsafe { runtime::type_outer(0, tag::SEQUENCE) } }
pub fn array(size:usize, type_id:usize) -> usize { pub fn array(size:usize, type_id:usize) -> usize {
unsafe { unsafe {
let inner_node = runtime::type_outer(type_id, size); let inner_node = runtime::type_outer(type_id, size);
runtime::type_outer(inner_node, tag::ARRAY) runtime::type_outer(inner_node, tag::ARRAY)
} }
} }
pub fn list(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::LIST) } } pub fn list(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::LIST) } }
pub fn sparse(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::SPARSE) } } pub fn sparse(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::SPARSE) } }
pub fn record(schema_id:usize) -> usize { pub fn record(schema_id:usize) -> usize {
unsafe { unsafe {
let inner_node = runtime::type_outer(0, schema_id); let inner_node = runtime::type_outer(0, schema_id);
runtime::type_outer(inner_node, tag::RECORD) runtime::type_outer(inner_node, tag::RECORD)
} }
} }
pub fn schema() -> usize { unsafe { runtime::type_outer(0, tag::SCHEMA) } } pub fn schema() -> usize { unsafe { runtime::type_outer(0, tag::SCHEMA) } }

View File

@ -1,228 +1,228 @@
use crate::runtime::{ use crate::runtime::{
Reference, Reference,
acquire, release, acquire, release,
type_key, type_key,
decimal_get, decimal_set, type_innerkey, decimal_get, decimal_set, type_innerkey,
}; };
use crate::tag; use crate::tag;
use super::decimal; use super::decimal;
pub struct Decimal { pub struct Decimal {
managed:bool, managed:bool,
addr:Reference, addr:Reference,
} }
impl Decimal { impl Decimal {
pub fn new(mantissa:usize) -> Self pub fn new(mantissa:usize) -> Self
{ {
Self { Self {
managed:true, managed:true,
addr:unsafe {acquire(decimal(mantissa))}, addr:unsafe {acquire(decimal(mantissa))},
} }
} }
pub fn with_raw(mantissa:usize, data:i64) -> Self pub fn with_raw(mantissa:usize, data:i64) -> Self
{ {
let mut obj = Self::new(mantissa); let mut obj = Self::new(mantissa);
obj.set_raw(data); obj.set_raw(data);
return obj; return obj;
} }
pub fn with(mantissa:usize, value:f64) -> Self pub fn with(mantissa:usize, value:f64) -> Self
{ {
let mut obj = Self::new(mantissa); let mut obj = Self::new(mantissa);
obj.set(value); obj.set(value);
return obj; return obj;
} }
pub fn copy(&self) -> Self pub fn copy(&self) -> Self
{ {
Decimal::try_from(self.addr).unwrap() Decimal::try_from(self.addr).unwrap()
} }
pub fn set_raw(&mut self, data:i64) pub fn set_raw(&mut self, data:i64)
{ {
unsafe { decimal_set(self.addr, data) }; unsafe { decimal_set(self.addr, data) };
} }
pub fn set(&mut self, value:f64) pub fn set(&mut self, value:f64)
{ {
let mantissa = unsafe {type_innerkey(self.addr.class)}; let mantissa = unsafe {type_innerkey(self.addr.class)};
let whole = value as i64; let whole = value as i64;
let decimal = ((value - value.trunc()).abs() * (1i64 << mantissa) as f64).floor() as i64; let decimal = ((value - value.trunc()).abs() * (1i64 << mantissa) as f64).floor() as i64;
let data = (whole << mantissa) + (decimal as i64); let data = (whole << mantissa) + (decimal as i64);
self.set_raw(data); self.set_raw(data);
} }
pub fn get_raw(&self) -> i64 pub fn get_raw(&self) -> i64
{ {
unsafe {decimal_get(self.addr)} unsafe {decimal_get(self.addr)}
} }
pub fn get(&self) -> f64 pub fn get(&self) -> f64
{ {
let mantissa = unsafe {type_innerkey(self.addr.class)}; let mantissa = unsafe {type_innerkey(self.addr.class)};
let data = self.get_raw(); let data = self.get_raw();
(data >> mantissa) as f64 + ((data & ((1i64 << mantissa) - 1)) as f64 / (1i64 << mantissa) as f64) (data >> mantissa) as f64 + ((data & ((1i64 << mantissa) - 1)) as f64 / (1i64 << mantissa) as f64)
} }
fn rebase(to:usize, from:usize, data:i64) -> i64 fn rebase(to:usize, from:usize, data:i64) -> i64
{ {
return if to > from { return if to > from {
data << (to - from) as i64 data << (to - from) as i64
} else if to < from { } else if to < from {
data >> (from - to) as i64 data >> (from - to) as i64
} else { data } } else { data }
} }
pub fn to_base(&self, mantissa:usize) -> Self pub fn to_base(&self, mantissa:usize) -> Self
{ {
let mut result = Decimal::new(mantissa); let mut result = Decimal::new(mantissa);
result.set_raw(Self::rebase(mantissa, self.mantissa(), self.get_raw())); result.set_raw(Self::rebase(mantissa, self.mantissa(), self.get_raw()));
return result; return result;
} }
pub fn mantissa(&self) -> usize pub fn mantissa(&self) -> usize
{ {
unsafe {type_innerkey(self.addr.class)} unsafe {type_innerkey(self.addr.class)}
} }
} }
impl Clone for Decimal { impl Clone for Decimal {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Decimal::with_raw(self.mantissa(), self.get_raw()) Decimal::with_raw(self.mantissa(), self.get_raw())
} }
} }
impl std::ops::Add for Decimal { impl std::ops::Add for Decimal {
type Output = Self; type Output = Self;
fn add(self, rhs: Self) -> Self::Output { fn add(self, rhs: Self) -> Self::Output {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); let rhd = Self::rebase(lhe, rhe, rhs.get_raw());
Decimal::with_raw(lhe, lhd + rhd) Decimal::with_raw(lhe, lhd + rhd)
} }
} }
impl std::ops::AddAssign for Decimal { impl std::ops::AddAssign for Decimal {
fn add_assign(&mut self, rhs: Self) { fn add_assign(&mut self, rhs: Self) {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); let rhd = Self::rebase(lhe, rhe, rhs.get_raw());
self.set_raw(lhd + rhd); self.set_raw(lhd + rhd);
} }
} }
impl std::ops::Sub for Decimal { impl std::ops::Sub for Decimal {
type Output = Self; type Output = Self;
fn sub(self, rhs: Self) -> Self::Output { fn sub(self, rhs: Self) -> Self::Output {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); let rhd = Self::rebase(lhe, rhe, rhs.get_raw());
Decimal::with_raw(lhe, lhd - rhd) Decimal::with_raw(lhe, lhd - rhd)
} }
} }
impl std::ops::SubAssign for Decimal { impl std::ops::SubAssign for Decimal {
fn sub_assign(&mut self, rhs: Self) { fn sub_assign(&mut self, rhs: Self) {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); let rhd = Self::rebase(lhe, rhe, rhs.get_raw());
self.set_raw(lhd - rhd); self.set_raw(lhd - rhd);
} }
} }
impl std::ops::Mul for Decimal { impl std::ops::Mul for Decimal {
type Output = Self; type Output = Self;
fn mul(self, rhs: Self) -> Self::Output { fn mul(self, rhs: Self) -> Self::Output {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); let rhd = Self::rebase(lhe, rhe, rhs.get_raw());
Decimal::with_raw(lhe, ((lhd as i128 * rhd as i128) >> lhe) as i64) Decimal::with_raw(lhe, ((lhd as i128 * rhd as i128) >> lhe) as i64)
} }
} }
impl std::ops::MulAssign for Decimal { impl std::ops::MulAssign for Decimal {
fn mul_assign(&mut self, rhs: Self) { fn mul_assign(&mut self, rhs: Self) {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); let rhd = Self::rebase(lhe, rhe, rhs.get_raw());
self.set_raw(((lhd as i128 * rhd as i128) >> lhe) as i64); self.set_raw(((lhd as i128 * rhd as i128) >> lhe) as i64);
} }
} }
impl std::ops::Div for Decimal { impl std::ops::Div for Decimal {
type Output = Self; type Output = Self;
fn div(self, rhs: Self) -> Self::Output { fn div(self, rhs: Self) -> Self::Output {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.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) Decimal::with_raw(lhe, ((lhd as i128 * (1i64 << lhe) as i128) / rhd as i128) as i64)
} }
} }
impl std::ops::DivAssign for Decimal { impl std::ops::DivAssign for Decimal {
fn div_assign(&mut self, rhs: Self) { fn div_assign(&mut self, rhs: Self) {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.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); self.set_raw(((lhd as i128 * (1i64 << lhe) as i128) / rhd as i128) as i64);
} }
} }
impl std::ops::Rem for Decimal { impl std::ops::Rem for Decimal {
type Output = Self; type Output = Self;
fn rem(self, rhs: Self) -> Self::Output { fn rem(self, rhs: Self) -> Self::Output {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.get_raw()); let rhd = Self::rebase(lhe, rhe, rhs.get_raw());
Decimal::with_raw(lhe, (lhd as i128 % rhd as i128) as i64) Decimal::with_raw(lhe, (lhd as i128 % rhd as i128) as i64)
} }
} }
impl std::ops::RemAssign for Decimal { impl std::ops::RemAssign for Decimal {
fn rem_assign(&mut self, rhs: Self) { fn rem_assign(&mut self, rhs: Self) {
let lhe = unsafe {type_innerkey(self.addr.class)}; let lhe = unsafe {type_innerkey(self.addr.class)};
let rhe = unsafe {type_innerkey(rhs.addr.class)}; let rhe = unsafe {type_innerkey(rhs.addr.class)};
let lhd = self.get_raw(); let lhd = self.get_raw();
let rhd = Self::rebase(lhe, rhe, rhs.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); self.set_raw(((lhd as i128 * (1i64 << lhe) as i128) % rhd as i128) as i64);
} }
} }
impl std::ops::Neg for Decimal { impl std::ops::Neg for Decimal {
type Output = Self; type Output = Self;
fn neg(self) -> Self::Output { fn neg(self) -> Self::Output {
let mantissa = unsafe {type_innerkey(self.addr.class)}; let mantissa = unsafe {type_innerkey(self.addr.class)};
Decimal::with_raw(mantissa, -self.get_raw()) Decimal::with_raw(mantissa, -self.get_raw())
} }
} }
impl std::ops::Deref for Decimal { impl std::ops::Deref for Decimal {
type Target = Reference; type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn deref(&self) -> &Self::Target { return &self.addr; }
} }
impl Drop for Decimal { impl Drop for Decimal {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }
impl TryFrom<Reference> for Decimal { impl TryFrom<Reference> for Decimal {
type Error = (); type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::DECIMAL) { return if(unsafe {type_key(addr.class)} == tag::DECIMAL) {
Ok(Self { managed:false, addr:addr }) Ok(Self { managed:false, addr:addr })
} }
else { else {
Err(()) Err(())
} }
} }
} }
impl Into<f64> for Decimal { impl Into<f64> for Decimal {
fn into(self) -> f64 { fn into(self) -> f64 {
self.get() self.get()
} }
} }

View File

@ -0,0 +1,58 @@
use crate::runtime::{
Reference,
acquire, release,
type_key,
integer_get, integer_set
};
use crate::tag;
use super::integer;
pub struct Integer {
managed:bool,
addr:Reference,
}
impl Integer {
pub fn new() -> Self
{
Self {
managed:true,
addr:unsafe {acquire(integer())},
}
}
pub fn with(value:i64) -> Self
{
let mut obj = Self::new();
obj.set(value);
return obj;
}
pub fn set(&mut self, value:i64)
{
unsafe { integer_set(self.addr, value) };
}
pub fn get(&self) -> i64
{
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 {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Integer {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

118
src/interface-old/list.rs Normal file
View File

@ -0,0 +1,118 @@
use crate::runtime::{
Reference,
acquire, release,
type_inner, type_key,
list_capacity, list_length,
list_at,
list_clear,
list_insert, list_prepend, list_append, list_update,
list_remove,
list_reserve,
};
use crate::tag;
use super::list;
pub struct List {
managed:bool,
addr:Reference,
}
impl List {
pub fn new(type_id:usize) -> Self
{
Self {
managed:true,
addr:unsafe {acquire(list(type_id))},
}
}
pub fn with(type_id:usize, data:Vec<Reference>) -> Self
{
let mut obj = Self::new(type_id);
for item in data {
obj.insert(obj.length(), item);
}
return obj;
}
pub fn capacity(&self) -> usize
{
unsafe {list_capacity(self.addr)}
}
pub fn length(&self) -> usize
{
unsafe {list_length(self.addr)}
}
pub fn at(&self, index:usize) -> Reference
{
unsafe {list_at(self.addr, index)}
}
pub fn get(&self) -> Vec<Reference>
{
let mut result = Vec::<Reference>::with_capacity(self.length());
for i in 0..self.length() {
result.push(self.at(i));
}
return result;
}
pub fn clear(&mut self)
{
unsafe{list_clear(self.addr)};
}
pub fn insert(&mut self, index:usize, source:Reference)
{
unsafe{list_insert(self.addr, index, source)};
}
pub fn prepend(&mut self, source:Reference)
{
unsafe{list_prepend(self.addr, source)};
}
pub fn append(&mut self, source:Reference)
{
unsafe{list_append(self.addr, source)};
}
pub fn set(&mut self, index:usize, source:Reference)
{
unsafe{list_update(self.addr, index, source)};
}
pub fn remove(&mut self, index:usize)
{
unsafe{list_remove(self.addr, index)};
}
pub fn reserve(&mut self, length:usize)
{
unsafe{list_reserve(self.addr, length)};
}
pub fn kind(&self) -> usize
{
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 {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for List {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

76
src/interface-old/mod.rs Normal file
View File

@ -0,0 +1,76 @@
use crate::runtime::{Reference, type_key};
use crate::tag;
mod builder; pub use builder::*;
mod util; pub use util::*;
mod varying; pub use varying::Varying;
mod boolean; pub use boolean::Boolean;
mod natural; pub use natural::Natural;
mod integer; pub use integer::Integer;
mod decimal; pub use decimal::Decimal;
mod signficant; pub use signficant::Significant;
mod block; pub use block::Block;
mod sequence; pub use sequence::Sequence;
mod array; pub use array::Array;
mod list; pub use list::List;
mod sparse; pub use sparse::Sparse;
mod schema; pub use schema::Schema;
mod record; pub use record::Record;
pub enum Object {
Null,
Varying(Varying),
Boolean(Boolean),
Natural(Natural),
Integer(Integer),
Decimal(Decimal),
Significant(Significant),
Block(Block),
Sequence(Sequence),
Array(Array),
List(List),
Sparse(Sparse),
Record(Record),
Schema(Schema),
}
impl Object {
pub fn from(addr:Reference) -> Self
{
match unsafe {type_key(addr.class)} {
tag::NULL => Object::Null,
tag::VARYING => Object::Varying(Varying::try_from(addr).unwrap()),
tag::BOOLEAN => Object::Boolean(Boolean::try_from(addr).unwrap()),
tag::NATURAL => Object::Natural(Natural::try_from(addr).unwrap()),
tag::INTEGER => Object::Integer(Integer::try_from(addr).unwrap()),
tag::DECIMAL => Object::Decimal(Decimal::try_from(addr).unwrap()),
tag::SIGNIFICANT => Object::Significant(Significant::try_from(addr).unwrap()),
tag::BLOCK => Object::Block(Block::try_from(addr).unwrap()),
tag::SEQUENCE => Object::Sequence(Sequence::try_from(addr).unwrap()),
tag::ARRAY => Object::Array(Array::try_from(addr).unwrap()),
tag::LIST => Object::List(List::try_from(addr).unwrap()),
tag::SPARSE => Object::Sparse(Sparse::try_from(addr).unwrap()),
tag::RECORD => Object::Record(Record::try_from(addr).unwrap()),
_ => Object::Null,
}
}
pub fn get(&self) -> Reference
{
match &self {
Object::Varying(obj) => **obj,
Object::Boolean(obj) => **obj,
Object::Natural(obj) => **obj,
Object::Integer(obj) => **obj,
Object::Decimal(obj) => **obj,
Object::Significant(obj) => **obj,
Object::Block(obj) => **obj,
Object::Sequence(obj) => **obj,
Object::Array(obj) => **obj,
Object::List(obj) => **obj,
Object::Sparse(obj) => **obj,
Object::Record(obj) => **obj,
_ => Reference::null(),
}
}
}

View File

@ -0,0 +1,57 @@
use crate::runtime::{
Reference,
acquire, release,
type_key,
natural_get, natural_set
};
use crate::tag;
use super::natural;
pub struct Natural {
managed:bool,
addr:Reference,
}
impl Natural {
pub fn new() -> Self
{
Self {
managed:true,
addr:unsafe {acquire(natural())},
}
}
pub fn with(value:u64) -> Self
{
let mut obj = Self::new();
obj.set(value);
return obj;
}
pub fn set(&mut self, value:u64)
{
unsafe { natural_set(self.addr, value) };
}
pub fn get(&self) -> u64
{
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 {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Natural {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

View File

@ -1,137 +1,137 @@
use crate::runtime::{ use crate::runtime::{
util::{name_indexof, name_keyof}, util::{name_indexof, name_keyof},
Reference, Reference,
acquire, release, acquire, release,
schema_has, schema_has,
type_key, type_key,
record_length, record_length,
record_at, record_update, record_at, record_update,
record_indexof, record_keyof, record_indexof, record_keyof,
record_type, record_type,
}; };
use crate::tag; use crate::tag;
use super::record; use super::record;
pub struct Record { pub struct Record {
managed:bool, managed:bool,
addr:Reference, addr:Reference,
} }
impl Record { impl Record {
pub fn new(schema:usize) -> Result<Self,()> pub fn new(schema:usize) -> Result<Self,()>
{ {
if unsafe {schema_has(schema)} { if unsafe {schema_has(schema)} {
Ok(Self { Ok(Self {
managed:true, managed:true,
addr:unsafe {acquire(record(schema))}, addr:unsafe {acquire(record(schema))},
}) })
} else { } else {
Err(()) Err(())
} }
} }
pub fn with(schema:usize, data:Vec<(&str, Reference)>) -> Result<Self,()> pub fn with(schema:usize, data:Vec<(&str, Reference)>) -> Result<Self,()>
{ {
match Self::new(schema) { match Self::new(schema) {
Ok(mut obj) => { Ok(mut obj) => {
for (key, value) in data { for (key, value) in data {
obj.set(key, value); obj.set(key, value);
} }
Ok(obj) Ok(obj)
} }
Err(_) => Err(()) Err(_) => Err(())
} }
} }
pub fn with_values(schema:usize, data:Vec<Reference>) -> Result<Self,()> pub fn with_values(schema:usize, data:Vec<Reference>) -> Result<Self,()>
{ {
match Self::new(schema) { match Self::new(schema) {
Ok(mut obj) => { Ok(mut obj) => {
for index in 0..data.len() { for index in 0..data.len() {
obj.set_at(index, data[index]); obj.set_at(index, data[index]);
} }
Ok(obj) Ok(obj)
} }
Err(_) => Err(()) Err(_) => Err(())
} }
} }
pub fn length(&self) -> usize pub fn length(&self) -> usize
{ {
unsafe {record_length(self.addr)} unsafe {record_length(self.addr)}
} }
pub fn set_at(&mut self, index:usize, source:Reference) pub fn set_at(&mut self, index:usize, source:Reference)
{ {
unsafe { record_update(self.addr, index, source); } unsafe { record_update(self.addr, index, source); }
} }
pub fn set(&mut self, key:&str, source:Reference) pub fn set(&mut self, key:&str, source:Reference)
{ {
match self.indexof(key) { match self.indexof(key) {
Some(index) => { Some(index) => {
unsafe { record_update(self.addr, index, source); } unsafe { record_update(self.addr, index, source); }
} }
None => { } None => { }
} }
} }
pub fn at(&self, index:usize) -> Reference pub fn at(&self, index:usize) -> Reference
{ {
unsafe {record_at(self.addr, index)} unsafe {record_at(self.addr, index)}
} }
pub fn get(&self, key:&str) -> Reference pub fn get(&self, key:&str) -> Reference
{ {
match self.indexof(key) { match self.indexof(key) {
Some(index) => { Some(index) => {
unsafe {record_at(self.addr, index)} unsafe {record_at(self.addr, index)}
} }
None => Reference::null() None => Reference::null()
} }
} }
pub fn indexof(&self, key:&str) -> Option<usize> pub fn indexof(&self, key:&str) -> Option<usize>
{ {
let key_index = name_indexof(key); let key_index = name_indexof(key);
let result = unsafe {record_indexof(self.addr, key_index)}; let result = unsafe {record_indexof(self.addr, key_index)};
if result != self.length() { if result != self.length() {
Some(result) Some(result)
} else { } else {
None None
} }
} }
pub fn keyof(&self, index:usize) -> Option<String> pub fn keyof(&self, index:usize) -> Option<String>
{ {
let result = unsafe {record_keyof(self.addr, index)}; let result = unsafe {record_keyof(self.addr, index)};
if result != 0 { if result != 0 {
Some(name_keyof(result)) Some(name_keyof(result))
} }
else { else {
None None
} }
} }
pub fn kindof(&self, index:usize) -> usize pub fn kindof(&self, index:usize) -> usize
{ {
unsafe {record_type(self.addr, index)} unsafe {record_type(self.addr, index)}
} }
} }
impl TryFrom<Reference> for Record { impl TryFrom<Reference> for Record {
type Error = (); type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::RECORD) { return if(unsafe {type_key(addr.class)} == tag::RECORD) {
Ok(Self { managed:false, addr:addr }) Ok(Self { managed:false, addr:addr })
} }
else { else {
Err(()) 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; }
} }
impl Drop for Record { impl Drop for Record {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }

View File

@ -1,145 +1,145 @@
use crate::runtime::{ use crate::runtime::{
util::{name_indexof, name_keyof}, util::{name_indexof, name_keyof},
Reference, Reference,
acquire, release, acquire, release,
type_key, type_key,
schema_length, schema_length,
schema_insert, schema_update, schema_get, schema_insert, schema_update, schema_get,
schema_remove, schema_clear, schema_remove, schema_clear,
schema_map, schema_unmap, schema_indexof, schema_keyof, schema_map, schema_unmap, schema_indexof, schema_keyof,
schema_bind, schema_bind,
}; };
use crate::tag; use crate::tag;
use super::schema; use super::schema;
pub struct Schema { pub struct Schema {
managed:bool, managed:bool,
addr:Reference, addr:Reference,
} }
impl Schema { impl Schema {
pub fn new() -> Self pub fn new() -> Self
{ {
Self { Self {
managed:true, managed:true,
addr:unsafe {acquire(schema())}, addr:unsafe {acquire(schema())},
} }
} }
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();
for binding in members { for binding in members {
let (key, type_id) = binding; let (key, type_id) = binding;
obj.assign(key, type_id); obj.assign(key, type_id);
} }
return obj; return obj;
} }
pub fn length(&self) -> usize pub fn length(&self) -> usize
{ {
unsafe {schema_length(self.addr)} unsafe {schema_length(self.addr)}
} }
pub fn clear(&mut self) pub fn clear(&mut self)
{ {
unsafe { schema_clear(self.addr); } unsafe { schema_clear(self.addr); }
} }
pub fn add(&mut self, type_id:usize) -> usize pub fn add(&mut self, type_id:usize) -> usize
{ {
unsafe {schema_insert(self.addr, usize::MAX, type_id)} unsafe {schema_insert(self.addr, usize::MAX, type_id)}
} }
pub fn assign(&mut self, key:&str, type_id:usize) pub fn assign(&mut self, key:&str, type_id:usize)
{ {
if key.len() > 0 { if key.len() > 0 {
let key_index = name_indexof(key); let key_index = name_indexof(key);
unsafe { unsafe {
schema_map( schema_map(
self.addr, self.addr,
key_index, key_index,
schema_insert(self.addr, usize::MAX, type_id) schema_insert(self.addr, usize::MAX, type_id)
); );
} }
} }
else { else {
self.add(type_id); self.add(type_id);
} }
} }
pub fn set(&mut self, index:usize, type_id:usize) pub fn set(&mut self, index:usize, type_id:usize)
{ {
unsafe { schema_update(self.addr, index, type_id); } unsafe { schema_update(self.addr, index, type_id); }
} }
pub fn get(&self, index:usize) -> Option<usize> pub fn get(&self, index:usize) -> Option<usize>
{ {
match unsafe {schema_get(self.addr, index)} { match unsafe {schema_get(self.addr, index)} {
0 => None, 0 => None,
value => Some(value), value => Some(value),
} }
} }
pub fn remove(&mut self, index:usize) pub fn remove(&mut self, index:usize)
{ {
unsafe { schema_remove(self.addr, index); } unsafe { schema_remove(self.addr, index); }
} }
pub fn map(&mut self, key:&str, index:usize) pub fn map(&mut self, key:&str, index:usize)
{ {
let key_index = name_indexof(key); let key_index = name_indexof(key);
unsafe { schema_map(self.addr, key_index, index); } unsafe { schema_map(self.addr, key_index, index); }
} }
pub fn unmap(&mut self, key:&str) pub fn unmap(&mut self, key:&str)
{ {
let key_index = name_indexof(key); let key_index = name_indexof(key);
unsafe { schema_unmap(self.addr, key_index); } unsafe { schema_unmap(self.addr, key_index); }
} }
pub fn indexof(&self, key:&str) -> Option<usize> pub fn indexof(&self, key:&str) -> Option<usize>
{ {
let key_index = name_indexof(key); let key_index = name_indexof(key);
let result = unsafe {schema_indexof(self.addr, key_index)}; let result = unsafe {schema_indexof(self.addr, key_index)};
if result != self.length() { if result != self.length() {
Some(result) Some(result)
} }
else { else {
None None
} }
} }
pub fn keyof(&self, index:usize) -> Option<String> pub fn keyof(&self, index:usize) -> Option<String>
{ {
let result = unsafe {schema_keyof(self.addr, index)}; let result = unsafe {schema_keyof(self.addr, index)};
if result != 0 { if result != 0 {
Some(name_keyof(result)) Some(name_keyof(result))
} }
else { else {
None None
} }
} }
pub fn bind(&self, id:usize) -> usize pub fn bind(&self, id:usize) -> usize
{ {
unsafe {schema_bind(self.addr, id)} unsafe {schema_bind(self.addr, id)}
} }
} }
impl TryFrom<Reference> for Schema { impl TryFrom<Reference> for Schema {
type Error = (); type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SCHEMA) { return if(unsafe {type_key(addr.class)} == tag::SCHEMA) {
Ok(Self { managed:false, addr:addr }) Ok(Self { managed:false, addr:addr })
} }
else { else {
Err(()) 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; }
} }
impl Drop for Schema { impl Drop for Schema {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }

View File

@ -0,0 +1,115 @@
use crate::runtime::{
Reference,
acquire, release,
type_key,
sequence_capacity, sequence_length,
sequence_clear, sequence_reserve,
sequence_get,
sequence_insert, sequence_set,
};
use crate::tag;
use super::sequence;
pub struct Sequence {
managed:bool,
addr:Reference,
}
impl Sequence {
pub fn new() -> Self
{
Self {
managed:true,
addr:unsafe {acquire(sequence())},
}
}
pub fn with_raw(data:Vec<u8>) -> Self
{
let mut obj = Self::new();
obj.set_raw(data);
return obj;
}
pub fn with(data:&str) -> Self
{
let mut obj = Self::new();
obj.set(data);
return obj;
}
pub fn capacity(&self) -> usize
{
unsafe {sequence_capacity(self.addr)}
}
pub fn size(&self) -> usize
{
unsafe {sequence_length(self.addr)}
}
pub fn set_at(&mut self, index:usize, value:u8)
{
unsafe { sequence_set(self.addr, index, value); }
}
pub fn set_raw(&mut self, data:Vec<u8>)
{
unsafe { sequence_clear(self.addr); }
if data.len() > 0 {
unsafe { sequence_reserve(self.addr, data.len()); }
for i in 0..data.len() {
unsafe { sequence_insert(self.addr, i, data[i]); }
}
}
}
pub fn set(&mut self, data:&str)
{
self.set_raw(Vec::from(data.as_bytes()));
}
pub fn get_at(&self, index:usize) -> u8
{
unsafe {sequence_get(self.addr, index)}
}
pub fn get_raw(&self) -> Vec<u8>
{
let length = unsafe {sequence_length(self.addr)};
let mut result = Vec::<u8>::new();
if length > 0 {
result.reserve_exact(length);
for i in 0..length {
result.push(unsafe {sequence_get(self.addr, i)});
}
}
return result;
}
pub fn get(&self) -> String
{
match String::from_utf8(self.get_raw()) {
Ok(s) => s,
Err(_) => String::new(),
}
}
}
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 {
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Sequence {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

View File

@ -1,57 +1,57 @@
use crate::runtime::{ use crate::runtime::{
Reference, Reference,
acquire, release, acquire, release,
type_key, type_key,
significant_get, significant_set significant_get, significant_set
}; };
use crate::tag; use crate::tag;
use super::significant; use super::significant;
pub struct Significant { pub struct Significant {
managed:bool, managed:bool,
addr:Reference, addr:Reference,
} }
impl Significant { impl Significant {
pub fn new() -> Self pub fn new() -> Self
{ {
Self { Self {
managed:true, managed:true,
addr:unsafe {acquire(significant())}, addr:unsafe {acquire(significant())},
} }
} }
pub fn with(value:f64) -> Self pub fn with(value:f64) -> Self
{ {
let mut obj = Self::new(); let mut obj = Self::new();
obj.set(value); obj.set(value);
return obj; return obj;
} }
pub fn set(&mut self, value:f64) pub fn set(&mut self, value:f64)
{ {
unsafe { significant_set(self.addr, value) }; unsafe { significant_set(self.addr, value) };
} }
pub fn get(&self) -> f64 pub fn get(&self) -> f64
{ {
unsafe { significant_get(self.addr) } unsafe { significant_get(self.addr) }
} }
} }
impl TryFrom<Reference> for Significant { impl TryFrom<Reference> for Significant {
type Error = (); type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SIGNIFICANT) { return if(unsafe {type_key(addr.class)} == tag::SIGNIFICANT) {
Ok(Self { managed:false, addr:addr }) Ok(Self { managed:false, addr:addr })
} }
else { else {
Err(()) 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; }
} }
impl Drop for Significant { impl Drop for Significant {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }

View File

@ -1,114 +1,114 @@
use crate::runtime::{ use crate::runtime::{
Reference, Reference,
acquire, release, acquire, release,
type_inner, type_key, type_inner, type_key,
sparse_length, sparse_length,
sparse_first, sparse_next, sparse_last, sparse_first, sparse_next, sparse_last,
sparse_at, sparse_get, sparse_at, sparse_get,
sparse_clear, sparse_clear,
sparse_set, sparse_unset, sparse_set, sparse_unset,
sparse_indexof, sparse_indexof,
}; };
use crate::tag; use crate::tag;
use super::sparse; use super::sparse;
pub struct Sparse { pub struct Sparse {
managed:bool, managed:bool,
addr:Reference, addr:Reference,
} }
impl Sparse { impl Sparse {
pub fn new(class:usize) -> Self pub fn new(class:usize) -> Self
{ {
Self { Self {
managed:true, managed:true,
addr:unsafe {acquire(sparse(class))}, addr:unsafe {acquire(sparse(class))},
} }
} }
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);
for (key, item) in data { for (key, item) in data {
obj.set(key, item); obj.set(key, item);
} }
return obj; return obj;
} }
pub fn length(&self) -> usize pub fn length(&self) -> usize
{ {
unsafe {sparse_length(self.addr)} unsafe {sparse_length(self.addr)}
} }
pub fn first(&self) -> usize pub fn first(&self) -> usize
{ {
unsafe {sparse_first(self.addr)} unsafe {sparse_first(self.addr)}
} }
pub fn next(&self) -> usize pub fn next(&self) -> usize
{ {
unsafe {sparse_next(self.addr)} unsafe {sparse_next(self.addr)}
} }
pub fn last(&self) -> usize pub fn last(&self) -> usize
{ {
unsafe {sparse_last(self.addr)} unsafe {sparse_last(self.addr)}
} }
pub fn at(&self, index:usize) -> Reference pub fn at(&self, index:usize) -> Reference
{ {
unsafe {sparse_at(self.addr, index)} unsafe {sparse_at(self.addr, index)}
} }
pub fn has(&self, key:usize) -> bool pub fn has(&self, key:usize) -> bool
{ {
unsafe {sparse_get(self.addr, key)}.address != 0 unsafe {sparse_get(self.addr, key)}.address != 0
} }
pub fn get(&self, key:usize) -> Reference pub fn get(&self, key:usize) -> Reference
{ {
unsafe {sparse_get(self.addr, key)} unsafe {sparse_get(self.addr, key)}
} }
pub fn clear(&mut self) pub fn clear(&mut self)
{ {
unsafe{sparse_clear(self.addr)}; unsafe{sparse_clear(self.addr)};
} }
pub fn set(&mut self, key:usize, source:Reference) pub fn set(&mut self, key:usize, source:Reference)
{ {
unsafe{sparse_set(self.addr, key, source)}; unsafe{sparse_set(self.addr, key, source)};
} }
pub fn unset(&mut self, key:usize) pub fn unset(&mut self, key:usize)
{ {
unsafe{sparse_unset(self.addr, key)}; unsafe{sparse_unset(self.addr, key)};
} }
pub fn indexof(&self, index:usize) -> usize pub fn indexof(&self, index:usize) -> usize
{ {
unsafe{sparse_indexof(self.addr, index)} unsafe{sparse_indexof(self.addr, index)}
} }
pub fn kind(&self) -> usize pub fn kind(&self) -> usize
{ {
unsafe {type_inner(self.addr.class)} unsafe {type_inner(self.addr.class)}
} }
} }
impl TryFrom<Reference> for Sparse { impl TryFrom<Reference> for Sparse {
type Error = (); type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SPARSE) { return if(unsafe {type_key(addr.class)} == tag::SPARSE) {
Ok(Self { managed:false, addr:addr }) Ok(Self { managed:false, addr:addr })
} }
else { else {
Err(()) 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; }
} }
impl Drop for Sparse { impl Drop for Sparse {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }

View File

@ -1,23 +1,23 @@
use crate::runtime; use crate::runtime;
pub fn acquire(type_id:usize) -> runtime::Reference pub fn acquire(type_id:usize) -> runtime::Reference
{ {
unsafe {runtime::acquire(type_id)} unsafe {runtime::acquire(type_id)}
} }
pub fn release(addr:runtime::Reference) pub fn release(addr:runtime::Reference)
{ {
unsafe {runtime::release(addr)} unsafe {runtime::release(addr)}
} }
pub fn copy(dst:runtime::Reference, src:runtime::Reference) -> Result<(),()> pub fn copy(dst:runtime::Reference, src:runtime::Reference) -> Result<(),()>
{ {
if unsafe {runtime::copy(dst, src)} { Ok(()) } if unsafe {runtime::copy(dst, src)} { Ok(()) }
else { Err(()) } else { Err(()) }
} }
pub fn transfer(dst:runtime::Reference, src:runtime::Reference) -> Result<(),()> pub fn transfer(dst:runtime::Reference, src:runtime::Reference) -> Result<(),()>
{ {
if unsafe {runtime::transfer(dst, src)} { Ok(()) } if unsafe {runtime::transfer(dst, src)} { Ok(()) }
else { Err(()) } else { Err(()) }
} }

View File

@ -1,73 +1,73 @@
use crate::runtime::{ use crate::runtime::{
Reference, Reference,
acquire, release, acquire, release,
type_key, type_key,
varying_get, varying_set, varying_get, varying_set,
varying_clear, varying_clear,
}; };
use crate::tag; use crate::tag;
use super::varying; use super::varying;
pub struct Varying { pub struct Varying {
managed:bool, managed:bool,
addr:Reference, addr:Reference,
} }
impl Varying { impl Varying {
pub fn new() -> Self pub fn new() -> Self
{ {
Self { Self {
managed:true, managed:true,
addr:unsafe {acquire(varying())}, addr:unsafe {acquire(varying())},
} }
} }
pub fn with(addr:Reference) -> Self pub fn with(addr:Reference) -> Self
{ {
let mut obj = Varying::new(); let mut obj = Varying::new();
obj.set(addr); obj.set(addr);
return obj; return obj;
} }
pub fn is_null(&self) -> bool pub fn is_null(&self) -> bool
{ {
(unsafe {varying_get(self.addr)}).address == 0 (unsafe {varying_get(self.addr)}).address == 0
} }
pub fn set(&mut self, source:Reference) pub fn set(&mut self, source:Reference)
{ {
unsafe { varying_set(self.addr, source); } unsafe { varying_set(self.addr, source); }
} }
pub fn clear(&mut self) pub fn clear(&mut self)
{ {
unsafe { varying_clear(self.addr); } unsafe { varying_clear(self.addr); }
} }
pub fn get(&self) -> Reference pub fn get(&self) -> Reference
{ {
unsafe { varying_get(self.addr) } unsafe { varying_get(self.addr) }
} }
pub fn kindof(&self) -> usize pub fn kindof(&self) -> usize
{ {
unsafe {varying_get(self.addr).class} unsafe {varying_get(self.addr).class}
} }
} }
impl TryFrom<Reference> for Varying { impl TryFrom<Reference> for Varying {
type Error = (); type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::VARYING) { return if(unsafe {type_key(addr.class)} == tag::VARYING) {
Ok(Self { managed:false, addr:addr }) Ok(Self { managed:false, addr:addr })
} }
else { else {
Err(()) 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; }
} }
impl Drop for Varying { impl Drop for Varying {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} }

View File

@ -1,83 +1,78 @@
use crate::runtime::{ use std::marker::PhantomData;
Reference, use crate::{
type_inner, type_key, prelude::*, types,
acquire, release, runtime::{
array_length, array_at, array_update acquire, release,
}; type_outer, type_key,
use crate::tag; clone,
use super::array; array_set, array_at,
},
/// Constant-sized, indexed, ordered collection. };
pub struct Array {
managed:bool, pub struct Array<const N :usize, T: SzunType> {
addr:Reference, address:Ref,
} _data:PhantomData<T>,
impl Array { }
/// Allocates a new array of a given size and type. impl<const N :usize, T: SzunType> Array<N,T> {
/// pub fn new() -> Self
/// # Arguments {
/// Self { address:unsafe {acquire(Self::type_id())}, _data:PhantomData }
/// * `length` - number of elements in the array }
/// * `class` - type identifier of the array contents
/// pub fn set<D: SzunType>(&mut self, index:usize, data:&D)
/// # Examples {
/// if self.compatible(data) {
/// ``` unsafe {array_set(self.address.clone(), index, data.__to_ref())};
/// // Produces an array of 8 integers. }
/// let int_array = szun::Array::new(8, szun::integer()); }
/// ```
pub fn new(length:usize, class:usize) -> Self pub fn get(&self, index:usize) -> T
{ {
Self { let refr = unsafe {array_at(self.address.clone(), index)};
managed:true, if refr.is_some() {
addr:unsafe {acquire(array(length, class))}, T::__from_ref(refr)
} } else { panic!("array index out of bounds"); }
} }
pub fn with(length:usize, class:usize, data:Vec<Reference>) -> Self pub fn len(&self) -> usize
{ {
let mut obj = Self::new(length, class); N
for i in 0..usize::min(length, data.len()) { }
obj.set(i, data[i]); }
} impl<const N :usize, T: SzunType> SzunType for Array<N,T> {
return obj; fn type_id() -> usize {
} let inner = unsafe {type_outer(T::type_id(), N)};
unsafe {type_outer(inner, types::TYPE_ARRAY)}
pub fn length(&self) -> usize }
{ fn to_ref(self) -> Ref { self.address.clone() }
unsafe {array_length(self.addr)}
} fn compatible<R: SzunType>(&self, _:&R) -> bool {
R::type_id() == T::type_id() || unsafe {type_key(T::type_id())} == types::TYPE_VARYING
pub fn set(&mut self, index:usize, source:Reference) }
{
unsafe { array_update(self.addr, index, source); } fn __to_ref(&self) -> Ref { self.address.clone() }
} fn __from_ref(refr:Ref) -> Self { Self { address:refr, _data:PhantomData } }
}
pub fn at(&self, index:usize) -> Reference
{ impl<const N :usize, T: SzunType> Clone for Array<N,T> {
unsafe {array_at(self.addr, index)} fn clone(&self) -> Self {
} Self { address:unsafe {clone(self.address.clone())}, _data:PhantomData }
}
pub fn kind(&self) -> usize }
{
unsafe {type_inner(self.addr.class)} impl<const N :usize, T: SzunType> TryFrom<Ref> for Array<N,T> {
} type Error = SzunError;
}
impl TryFrom<Reference> for Array { fn try_from(addr: Ref) -> Result<Self, Self::Error> {
type Error = (); if addr.class == Self::type_id() {
fn try_from(addr:Reference) -> Result<Self, Self::Error> { Ok(Self { address:addr, _data:PhantomData })
return if(unsafe {type_key(addr.class)} == tag::ARRAY) { } else { Err(SzunError::MismatchedType) }
Ok(Self { managed:false, addr:addr }) }
} }
else { impl<const N :usize, T: SzunType> Into<Ref> for Array<N,T> { fn into(self) -> Ref { self.address.clone() } }
Err(())
} impl<const N :usize, T: SzunType> Drop for Array<N,T> {
} fn drop(&mut self) {
} unsafe {release(self.address.clone())};
impl std::ops::Deref for Array { }
type Target = Reference; }
fn deref(&self) -> &Self::Target { return &self.addr; }
}
impl Drop for Array {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
}

View File

@ -1,107 +1,116 @@
use crate::runtime::{ use crate::{
Reference, prelude::*, types,
acquire, release, runtime::{
type_inner, type_key, acquire, release,
block_length, type_outer,
block_set, block_get, clone,
block_set_natural, block_get_natural, block_set, block_get,
block_set_integer, block_get_integer, },
block_set_field, block_get_field,
}; };
use crate::tag;
use super::block;
pub struct Block { pub struct Block<const N :usize> {
managed:bool, address:Ref,
addr:Reference,
} }
impl Block { impl<const N :usize> Block<N> {
pub fn new(size:usize) -> Self pub fn new() -> Self
{ {
Self { Self { address:unsafe {acquire(Self::type_id())} }
managed:true, }
addr:unsafe {acquire(block(size))},
pub fn with(mut self, data:&[u8; N]) -> Self
{
self.set(data);
self
}
pub fn set(&mut self, data:&[u8; N])
{
for i in 0..data.len() {
unsafe {block_set(self.address.clone(), i, data[i])};
} }
} }
pub fn with(size:usize, data:Vec<u8>) -> Self pub fn get(&self) -> [u8; N]
{ {
let mut obj = Self::new(size); let mut data = [0; N];
obj.set(data); for i in 0..data.len() {
return obj; data[i] = unsafe {block_get(self.address.clone(), i)};
}
data
} }
pub fn size(&self) -> usize pub fn set_at(&mut self, index:usize, data:u8)
{ {
unsafe {block_length(self.addr)} unsafe {block_set(self.address.clone(), index, data)}
} }
pub fn set(&mut self, data:Vec<u8>) pub fn get_at(&self, index:usize) -> u8
{ {
let length = unsafe {type_key(type_inner(self.addr.class))}; unsafe {block_get(self.address.clone(), index)}
for index in 0..usize::min(data.len(), length) { }
unsafe {block_set(self.addr, index, data[index])};
pub fn set_unsigned<T: num::Num + num::NumCast>(&mut self, data:T)
{
let mut value :u128 = num::NumCast::from(data).unwrap();
let n = N - 1;
for i in 0..N {
unsafe {block_set(self.address.clone(), n - i, (value & 0xFF) as u8)};
value >>= 8;
} }
} }
pub fn set_u64(&self, data:u64) pub fn get_unsigned<T: num::Num + num::NumCast>(&mut self) -> T
{ {
unsafe {block_set_natural(self.addr, data)} let mut value :u128 = 0;
} for i in 0..N {
value <<= 8;
pub fn set_i64(&self, data:i64) value |= unsafe {block_get(self.address.clone(), i)} as u128;
{
unsafe {block_set_integer(self.addr, data)}
}
pub fn set_field(&mut self, index:usize, length:usize, data:u64)
{
unsafe { block_set_field(self.addr, index, length, data); }
}
pub fn get(&self) -> Vec<u8>
{
let mut result = Vec::<u8>::new();
let length = unsafe {type_key(type_inner(self.addr.class))};
if length > 0 {
result.resize(length, 0);
for index in 0..length {
result[index] = unsafe {block_get(self.addr, index)};
}
} }
return result; num::NumCast::from(value).unwrap()
} }
pub fn get_u64(&self) -> u64 pub fn len(&self) -> usize
{ {
unsafe {block_get_natural(self.addr)} N
} }
}
pub fn get_i64(&self) -> i64 impl<const N :usize> SzunType for Block<N> {
{ fn type_id() -> usize {
unsafe {block_get_integer(self.addr)} let inner = unsafe {type_outer(0, N)};
unsafe {type_outer(inner, types::TYPE_BLOCK)}
} }
fn to_ref(self) -> Ref { self.address.clone() }
pub fn get_field(&self, index:usize, length:usize) -> u64 fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
{
unsafe {block_get_field(self.addr, index, length)} fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
}
pub fn block<const N :usize>(data:&[u8; N]) -> Block<N>
{
Block::new().with(data)
}
impl<const N :usize> Clone for Block<N> {
fn clone(&self) -> Self {
Self { address:unsafe {clone(self.address.clone())} }
} }
} }
impl TryFrom<Reference> for Block {
type Error = (); impl<const N :usize> TryFrom<Ref> for Block<N> {
fn try_from(addr:Reference) -> Result<Self, Self::Error> { type Error = SzunError;
return if(unsafe {type_key(addr.class)} == tag::BLOCK) {
Ok(Self { managed:false, addr:addr }) fn try_from(addr: Ref) -> Result<Self, Self::Error> {
} if addr.class == Self::type_id() {
else { Ok(Self { address:addr })
Err(()) } else { Err(SzunError::MismatchedType) }
}
} }
} }
impl std::ops::Deref for Block { impl<const N :usize> Into<Ref> for Block<N> { fn into(self) -> Ref { self.address.clone() } }
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } impl<const N :usize> Drop for Block<N> {
} fn drop(&mut self) {
impl Drop for Block { unsafe {release(self.address.clone())};
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } }
} }

View File

@ -1,62 +1,82 @@
use crate::runtime::{ use crate::{
Reference, prelude::*, types,
acquire, release, runtime::{
type_key, acquire, release,
bool_get, bool_set type_outer,
}; clone,
use crate::tag; bool_set, bool_get,
use super::boolean; },
};
pub struct Boolean {
managed:bool, pub struct Boolean {
addr:Reference, address:Ref,
} }
impl Boolean { impl Boolean {
pub fn new() -> Self pub fn new() -> Self
{ {
Self { Self { address:unsafe {acquire(Self::type_id())} }
managed:true, }
addr:unsafe {acquire(boolean())},
} pub fn with(mut self, data:bool) -> Self
} {
self.set(data);
pub fn with(value:bool) -> Self self
{ }
let mut result = Self::new();
result.set(value); pub fn set(&mut self, data:bool)
return result; {
} unsafe {bool_set(self.address.clone(), data)}
}
pub fn set(&mut self, value:bool)
{ pub fn get(&self) -> bool
unsafe { bool_set(self.addr, value) }; {
} unsafe {bool_get(self.address.clone())}
}
pub fn get(&self) -> bool }
{ impl SzunType for Boolean {
unsafe { bool_get(self.addr) } fn type_id() -> usize { unsafe {type_outer(0, types::TYPE_BOOLEAN)} }
} fn to_ref(self) -> Ref { self.address.clone() }
}
impl TryFrom<Reference> for Boolean { fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn __to_ref(&self) -> Ref { self.address.clone() }
return if(unsafe {type_key(addr.class)} == tag::BOOLEAN) { fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
Ok(Self { managed:false, addr:addr }) }
}
else { pub fn boolean(data:bool) -> Boolean
Err(()) {
} Boolean::from(data)
} }
}
impl std::ops::Deref for Boolean { impl Clone for Boolean {
type Target = Reference; fn clone(&self) -> Self {
fn deref(&self) -> &Self::Target { return &self.addr; } Self { address:unsafe {clone(self.address.clone())} }
} }
impl Drop for Boolean { }
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} impl std::ops::Not for Boolean {
impl Into<bool> for Boolean { type Output = Self;
fn into(self) -> bool { fn not(self) -> Self::Output {
self.get() Self::from(!self.get())
} }
} }
impl TryFrom<Ref> for Boolean {
type Error = SzunError;
fn try_from(addr: Ref) -> Result<Self, Self::Error> {
if addr.class == Self::type_id() {
Ok(Self { address:addr })
} else { Err(SzunError::MismatchedType) }
}
}
impl Into<Ref> for Boolean { fn into(self) -> Ref { self.address.clone() } }
impl From<bool> for Boolean { fn from(value: bool) -> Self { Self::new().with(value) } }
impl Into<bool> for Boolean { fn into(self) -> bool { self.get() } }
impl Drop for Boolean {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

View File

@ -1,58 +1,80 @@
use crate::runtime::{ use crate::{
Reference, prelude::*, types,
acquire, release, runtime::{
type_key, acquire, release,
integer_get, integer_set type_outer,
}; clone,
use crate::tag; integer_set, integer_get,
use super::integer; },
};
pub struct Integer {
managed:bool, pub struct Integer {
addr:Reference, address:Ref,
} }
impl Integer { impl Integer {
pub fn new() -> Self pub fn new() -> Self {
{ Self { address:unsafe {acquire(Self::type_id())} }
Self { }
managed:true,
addr:unsafe {acquire(integer())}, pub fn with<T: num::Num + num::NumCast>(mut self, data:T) -> Self
} {
} self.set(data);
self
pub fn with(value:i64) -> Self }
{
let mut obj = Self::new(); pub fn set<T: num::Num + num::NumCast>(&mut self, data:T) {
obj.set(value); match num::NumCast::from(data) {
return obj; Some(data) => unsafe {integer_set(self.address.clone(), data)}
} None => { }
}
pub fn set(&mut self, value:i64) }
{
unsafe { integer_set(self.addr, value) }; pub fn get<T: num::Num + num::NumCast>(&self) -> T {
} num::NumCast::from(unsafe {integer_get(self.address.clone())}).unwrap()
}
pub fn get(&self) -> i64 }
{ impl SzunType for Integer {
unsafe { integer_get(self.addr) } fn type_id() -> usize { unsafe {type_outer(0, types::TYPE_INTEGER)} }
} fn to_ref(self) -> Ref { self.address.clone() }
}
impl TryFrom<Reference> for Integer { fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
type Error = ();
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn __to_ref(&self) -> Ref { self.address.clone() }
return if(unsafe {type_key(addr.class)} == tag::INTEGER) { fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
Ok(Self { managed:false, addr:addr }) }
}
else { pub fn integer<T: num::Num + num::NumCast>(data:T) -> Integer
Err(()) {
} Integer::new().with(data)
} }
}
impl std::ops::Deref for Integer { impl Clone for Integer {
type Target = Reference; fn clone(&self) -> Self {
fn deref(&self) -> &Self::Target { return &self.addr; } Self { address:unsafe {clone(self.address.clone())} }
} }
impl Drop for Integer { }
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} impl std::ops::Neg for Integer {
type Output = Self;
fn neg(self) -> Self::Output {
Self::new().with(-self.get::<i64>())
}
}
crate::util::macros::impl_ops_numeric_all!(Integer, i64);
impl TryFrom<Ref> for Integer {
type Error = SzunError;
fn try_from(addr: Ref) -> Result<Self, Self::Error> {
if addr.class == Self::type_id() {
Ok(Self { address:addr })
} else { Err(SzunError::MismatchedType) }
}
}
impl Into<Ref> for Integer { fn into(self) -> Ref { self.address.clone() } }
impl Drop for Integer {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

View File

@ -1,118 +1,128 @@
use crate::runtime::{ use std::marker::PhantomData;
Reference, use crate::{
acquire, release, prelude::*, runtime::{
type_inner, type_key, acquire, release, clone,
list_capacity, list_length, type_outer, type_key,
list_at, list_reserve, list_clear,
list_clear, list_insert, list_push, list_pop,
list_insert, list_prepend, list_append, list_update, list_at, list_back, list_set,
list_remove, list_length, list_capacity,
list_reserve, }, types
}; };
use crate::tag;
use super::list; pub struct List<T: SzunType> {
address:Ref,
pub struct List { _data:PhantomData<T>,
managed:bool, }
addr:Reference, impl<T: SzunType> List<T> {
} pub fn new() -> Self {
impl List { Self {
pub fn new(type_id:usize) -> Self address:unsafe {acquire(Self::type_id())},
{ _data:PhantomData
Self { }
managed:true, }
addr:unsafe {acquire(list(type_id))},
} pub fn insert<D: SzunType>(&mut self, index:usize, data:&D)
} {
if index <= self.len() && self.compatible(data) {
pub fn with(type_id:usize, data:Vec<Reference>) -> Self unsafe {list_insert(self.address.clone(), index, data.__to_ref())};
{ }
let mut obj = Self::new(type_id); }
for item in data {
obj.insert(obj.length(), item); pub fn push<D: SzunType>(&mut self, data:&D)
} {
return obj; if self.compatible(data) {
} unsafe {list_push(self.address.clone(), data.__to_ref())};
}
pub fn capacity(&self) -> usize }
{
unsafe {list_capacity(self.addr)} pub fn pop(&mut self) -> Option<T>
} {
let refr = unsafe {list_back(self.address.clone())};
pub fn length(&self) -> usize if refr.is_some() {
{ let result = Some(T::__from_ref(unsafe {clone(refr)}));
unsafe {list_length(self.addr)} unsafe {list_pop(self.address.clone())};
} result
} else { None }
pub fn at(&self, index:usize) -> Reference }
{
unsafe {list_at(self.addr, index)} pub fn set<D: SzunType>(&mut self, index:usize, data:&D)
} {
if self.compatible(data) {
pub fn get(&self) -> Vec<Reference> unsafe {list_set(self.address.clone(), index, data.__to_ref())};
{ }
let mut result = Vec::<Reference>::with_capacity(self.length()); }
for i in 0..self.length() {
result.push(self.at(i)); pub fn clear(&mut self)
} {
return result; unsafe {list_clear(self.address.clone())};
} }
pub fn clear(&mut self) pub fn reserve(&mut self, length:usize)
{ {
unsafe{list_clear(self.addr)}; unsafe {list_reserve(self.address.clone(), length)};
} }
pub fn insert(&mut self, index:usize, source:Reference) pub fn get(&mut self, index:usize) -> T
{ {
unsafe{list_insert(self.addr, index, source)}; let refr = unsafe {list_at(self.address.clone(), index)};
} if refr.is_some() {
T::__from_ref(refr)
pub fn prepend(&mut self, source:Reference) } else { panic!("index out of bounds: {} / {}", index, self.len()) }
{ }
unsafe{list_prepend(self.addr, source)};
} pub fn try_get(&mut self, index:usize) -> Option<T>
{
pub fn append(&mut self, source:Reference) let refr = unsafe {list_at(self.address.clone(), index)};
{ if refr.is_some() {
unsafe{list_append(self.addr, source)}; Some(T::__from_ref(refr))
} } else { None }
}
pub fn set(&mut self, index:usize, source:Reference)
{ pub fn len(&self) -> usize
unsafe{list_update(self.addr, index, source)}; {
} unsafe {list_length(self.address.clone())}
}
pub fn remove(&mut self, index:usize)
{ pub fn capacity(&self) -> usize
unsafe{list_remove(self.addr, index)}; {
} unsafe {list_capacity(self.address.clone())}
}
pub fn reserve(&mut self, length:usize) }
{ impl<T: SzunType> SzunType for List<T> {
unsafe{list_reserve(self.addr, length)}; fn type_id() -> usize {
} unsafe {type_outer(T::type_id(), types::TYPE_LIST)}
}
pub fn kind(&self) -> usize fn to_ref(self) -> Ref { self.address.clone() }
{
unsafe {type_inner(self.addr.class)} fn compatible<R: SzunType>(&self, _:&R) -> bool {
} R::type_id() == T::type_id() || unsafe {type_key(T::type_id())} == types::TYPE_VARYING
} }
impl TryFrom<Reference> for List {
type Error = (); fn __to_ref(&self) -> Ref { self.address.clone() }
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn __from_ref(address:Ref) -> Self { Self { address:address, _data:PhantomData } }
return if(unsafe {type_key(addr.class)} == tag::LIST) { }
Ok(Self { managed:false, addr:addr }) impl<T: SzunType> Clone for List<T> {
} fn clone(&self) -> Self {
else { Self::new()
Err(()) }
} }
}
} impl<T: SzunType> TryFrom<Ref> for List<T> {
impl std::ops::Deref for List { type Error = SzunError;
type Target = Reference;
fn deref(&self) -> &Self::Target { return &self.addr; } fn try_from(addr: Ref) -> Result<Self, Self::Error> {
} if addr.class == Self::type_id() {
impl Drop for List { Ok(Self { address:addr, _data:PhantomData })
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } } else { Err(SzunError::MismatchedType) }
} }
}
impl<T: SzunType> Into<Ref> for List<T> {
fn into(self) -> Ref { self.address.clone() }
}
impl<T: SzunType> Drop for List<T> {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

View File

@ -1,76 +1,12 @@
use crate::runtime::{Reference, type_key}; mod null; pub use null::*;
use crate::tag; mod boolean; pub use boolean::*;
mod builder; pub use builder::*; mod natural; pub use natural::*;
mod util; pub use util::*; mod integer; pub use integer::*;
mod varying; pub use varying::Varying; mod block; pub use block::*;
mod boolean; pub use boolean::Boolean; mod sequence; pub use sequence::*;
mod natural; pub use natural::Natural;
mod integer; pub use integer::Integer; mod var; pub use var::*;
mod decimal; pub use decimal::Decimal; mod array; pub use array::*;
mod signficant; pub use signficant::Significant; mod list; pub use list::*;
mod block; pub use block::Block;
mod sequence; pub use sequence::Sequence;
mod array; pub use array::Array;
mod list; pub use list::List;
mod sparse; pub use sparse::Sparse;
mod schema; pub use schema::Schema;
mod record; pub use record::Record;
pub enum Object {
Null,
Varying(Varying),
Boolean(Boolean),
Natural(Natural),
Integer(Integer),
Decimal(Decimal),
Significant(Significant),
Block(Block),
Sequence(Sequence),
Array(Array),
List(List),
Sparse(Sparse),
Record(Record),
Schema(Schema),
}
impl Object {
pub fn from(addr:Reference) -> Self
{
match unsafe {type_key(addr.class)} {
tag::NULL => Object::Null,
tag::VARYING => Object::Varying(Varying::try_from(addr).unwrap()),
tag::BOOLEAN => Object::Boolean(Boolean::try_from(addr).unwrap()),
tag::NATURAL => Object::Natural(Natural::try_from(addr).unwrap()),
tag::INTEGER => Object::Integer(Integer::try_from(addr).unwrap()),
tag::DECIMAL => Object::Decimal(Decimal::try_from(addr).unwrap()),
tag::SIGNIFICANT => Object::Significant(Significant::try_from(addr).unwrap()),
tag::BLOCK => Object::Block(Block::try_from(addr).unwrap()),
tag::SEQUENCE => Object::Sequence(Sequence::try_from(addr).unwrap()),
tag::ARRAY => Object::Array(Array::try_from(addr).unwrap()),
tag::LIST => Object::List(List::try_from(addr).unwrap()),
tag::SPARSE => Object::Sparse(Sparse::try_from(addr).unwrap()),
tag::RECORD => Object::Record(Record::try_from(addr).unwrap()),
_ => Object::Null,
}
}
pub fn get(&self) -> Reference
{
match &self {
Object::Varying(obj) => **obj,
Object::Boolean(obj) => **obj,
Object::Natural(obj) => **obj,
Object::Integer(obj) => **obj,
Object::Decimal(obj) => **obj,
Object::Significant(obj) => **obj,
Object::Block(obj) => **obj,
Object::Sequence(obj) => **obj,
Object::Array(obj) => **obj,
Object::List(obj) => **obj,
Object::Sparse(obj) => **obj,
Object::Record(obj) => **obj,
_ => Reference::null(),
}
}
}

View File

@ -1,57 +1,71 @@
use crate::runtime::{ use crate::{
Reference, prelude::*, types,
acquire, release, runtime::{
type_key, acquire, release,
natural_get, natural_set type_outer,
}; clone,
use crate::tag; natural_set, natural_get,
use super::natural; },
};
pub struct Natural {
managed:bool, pub struct Natural {
addr:Reference, address:Ref,
} }
impl Natural { impl Natural {
pub fn new() -> Self pub fn new() -> Self {
{ Self { address:unsafe {acquire(Self::type_id())} }
Self { }
managed:true,
addr:unsafe {acquire(natural())}, pub fn with<T: num::Num + num::NumCast>(mut self, data:T) -> Self {
} self.set(data);
} self
}
pub fn with(value:u64) -> Self
{ pub fn set<T: num::Num + num::NumCast>(&mut self, data:T) {
let mut obj = Self::new(); match num::NumCast::from(data) {
obj.set(value); Some(data) => unsafe {natural_set(self.address.clone(), data)}
return obj; None => { }
} }
}
pub fn set(&mut self, value:u64)
{ pub fn get<T: num::Num + num::NumCast>(&self) -> T {
unsafe { natural_set(self.addr, value) }; num::NumCast::from(unsafe {natural_get(self.address.clone())}).unwrap()
} }
}
pub fn get(&self) -> u64 impl SzunType for Natural {
{ fn type_id() -> usize { unsafe {type_outer(0, types::TYPE_NATURAL)} }
unsafe { natural_get(self.addr) } fn to_ref(self) -> Ref { self.address.clone() }
}
} fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
impl TryFrom<Reference> for Natural {
type Error = (); fn __to_ref(&self) -> Ref { self.address.clone() }
fn try_from(addr:Reference) -> Result<Self, Self::Error> { fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
return if(unsafe {type_key(addr.class)} == tag::NATURAL) { }
Ok(Self { managed:false, addr:addr })
} pub fn natural<T: num::Num + num::NumCast>(data:T) -> Natural
else { {
Err(()) Natural::new().with(data)
} }
}
} impl Clone for Natural {
impl std::ops::Deref for Natural { fn clone(&self) -> Self {
type Target = Reference; Self { address:unsafe {clone(self.address.clone())} }
fn deref(&self) -> &Self::Target { return &self.addr; } }
} }
impl Drop for Natural {
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } } crate::util::macros::impl_ops_numeric_all!(Natural, u64);
}
impl From<Ref> for Natural {
fn from(refr: Ref) -> Self {
if refr.class == Self::type_id() {
Self { address:refr }
} else { panic!("mismatched szun types"); }
}
}
impl Into<Ref> for Natural { fn into(self) -> Ref { self.address.clone() } }
impl Drop for Natural {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

22
src/interface/null.rs Normal file
View File

@ -0,0 +1,22 @@
use crate::{
prelude::*, types,
};
pub struct Null { }
impl Null {
pub fn new() -> Self { Self { } }
}
pub fn null() -> Null { Null::new() }
impl SzunType for Null {
fn type_id() -> usize { types::TYPE_NULL }
fn to_ref(self) -> Ref { Ref { class:0, address:0 } }
fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
fn __to_ref(&self) -> Ref { Ref { class:0, address:0 } }
fn __from_ref(_:Ref) -> Self { Self { } }
}
impl Clone for Null {
fn clone(&self) -> Self { Null::new() }
}

View File

@ -1,115 +1,127 @@
use crate::runtime::{ use crate::{
Reference, prelude::*, types,
acquire, release, runtime::{
type_key, acquire, release,
sequence_capacity, sequence_length, type_outer,
sequence_clear, sequence_reserve, clone,
sequence_get, sequence_resize,
sequence_insert, sequence_set, sequence_set, sequence_get,
}; sequence_length,
use crate::tag; },
use super::sequence; };
pub struct Sequence { pub struct Sequence {
managed:bool, pub(crate) address:Ref,
addr:Reference, }
} impl Sequence {
impl Sequence { pub fn new() -> Self
pub fn new() -> Self {
{ Self { address:unsafe {acquire(Self::type_id())} }
Self { }
managed:true,
addr:unsafe {acquire(sequence())}, pub fn with(mut self, data:Vec<u8>) -> Self
} {
} self.set(data);
self
pub fn with_raw(data:Vec<u8>) -> Self }
{
let mut obj = Self::new(); pub fn with_str(mut self, data:&str) -> Self
obj.set_raw(data); {
return obj; self.set_str(data);
} self
}
pub fn with(data:&str) -> Self
{ pub fn set(&mut self, data:Vec<u8>)
let mut obj = Self::new(); {
obj.set(data); unsafe {sequence_resize(self.address.clone(), data.len())};
return obj; for i in 0..data.len() {
} unsafe {sequence_set(self.address.clone(), i, data[i])};
}
pub fn capacity(&self) -> usize }
{
unsafe {sequence_capacity(self.addr)} pub fn set_str(&mut self, data:&str)
} {
let data = data.as_bytes();
pub fn size(&self) -> usize unsafe {sequence_resize(self.address.clone(), data.len())};
{ for i in 0..data.len() {
unsafe {sequence_length(self.addr)} unsafe {sequence_set(self.address.clone(), i, data[i])};
} }
}
pub fn set_at(&mut self, index:usize, value:u8)
{ pub fn get(&self) -> Vec<u8>
unsafe { sequence_set(self.addr, index, value); } {
} let mut data = Vec::new();
for i in 0..data.len() {
pub fn set_raw(&mut self, data:Vec<u8>) data.push(unsafe {sequence_get(self.address.clone(), i)});
{ }
unsafe { sequence_clear(self.addr); } data
if data.len() > 0 { }
unsafe { sequence_reserve(self.addr, data.len()); }
for i in 0..data.len() { pub fn get_str(&self) -> String
unsafe { sequence_insert(self.addr, i, data[i]); } {
} let mut data = Vec::new();
} for i in 0..self.len() {
} data.push(unsafe {sequence_get(self.address.clone(), i)});
}
pub fn set(&mut self, data:&str) String::from_utf8(data).unwrap()
{ }
self.set_raw(Vec::from(data.as_bytes()));
} pub fn set_at(&mut self, index:usize, data:u8)
{
pub fn get_at(&self, index:usize) -> u8 unsafe {sequence_set(self.address.clone(), index, data)}
{ }
unsafe {sequence_get(self.addr, index)}
} pub fn get_at(&self, index:usize) -> u8
{
pub fn get_raw(&self) -> Vec<u8> unsafe {sequence_get(self.address.clone(), index)}
{ }
let length = unsafe {sequence_length(self.addr)};
let mut result = Vec::<u8>::new(); pub fn len(&self) -> usize
{
if length > 0 { unsafe {sequence_length(self.address.clone())}
result.reserve_exact(length); }
for i in 0..length { }
result.push(unsafe {sequence_get(self.addr, i)}); impl SzunType for Sequence {
} fn type_id() -> usize {
} unsafe {type_outer(0, types::TYPE_SEQUENCE)}
return result; }
} fn to_ref(self) -> Ref { self.address.clone() }
pub fn get(&self) -> String fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
{
match String::from_utf8(self.get_raw()) { fn __to_ref(&self) -> Ref { self.address.clone() }
Ok(s) => s, fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
Err(_) => String::new(), }
}
} pub fn sequence(data:Vec<u8>) -> Sequence
} {
impl TryFrom<Reference> for Sequence { Sequence::new().with(data)
type Error = (); }
fn try_from(addr:Reference) -> Result<Self, Self::Error> {
return if(unsafe {type_key(addr.class)} == tag::SEQUENCE) { pub fn string(data:&str) -> Sequence
Ok(Self { managed:false, addr:addr }) {
} Sequence::new().with_str(data)
else { }
Err(())
} impl Clone for Sequence {
} fn clone(&self) -> Self {
} Self { address:unsafe {clone(self.address.clone())} }
impl std::ops::Deref for Sequence { }
type Target = Reference; }
fn deref(&self) -> &Self::Target { return &self.addr; }
} impl TryFrom<Ref> for Sequence {
impl Drop for Sequence { type Error = SzunError;
fn drop(&mut self) { if self.managed { unsafe {release(self.addr)}; } }
} fn try_from(addr: Ref) -> Result<Self, Self::Error> {
if addr.class == Self::type_id() {
Ok(Self { address:addr })
} else { Err(SzunError::MismatchedType) }
}
}
impl Into<Ref> for Sequence { fn into(self) -> Ref { self.address.clone() } }
impl Drop for Sequence {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

86
src/interface/var.rs Normal file
View File

@ -0,0 +1,86 @@
use crate::{
prelude::*, types,
runtime::{
acquire, release,
type_outer, type_sanitize,
clone,
var_set, var_get,
},
};
pub struct Var {
address:Ref,
}
impl Var {
pub fn new() -> Self {
Self { address:unsafe {acquire(Self::type_id())} }
}
pub fn with<T: SzunType>(mut self, data:&T) -> Self {
self.set(data);
self
}
pub fn set<T: SzunType>(&mut self, data:&T) {
unsafe {var_set(self.address.clone(), data.__to_ref())}
}
pub fn get<T: SzunType>(&self) -> T {
let refr = unsafe {var_get(self.address.clone())};
if unsafe {type_sanitize(refr.class)} == T::type_id() {
T::__from_ref(refr)
} else { panic!("mismatched szun types"); }
}
pub fn try_get<T: SzunType>(&self) -> Result<T,SzunError> {
let refr = unsafe {var_get(self.address.clone())};
if unsafe {type_sanitize(refr.class)} == T::type_id() {
Ok(T::__from_ref(refr))
} else { Err(SzunError::MismatchedType) }
}
pub fn has<T: SzunType>(&self) -> bool {
let refr = unsafe {var_get(self.address.clone())};
unsafe {type_sanitize(refr.class) == T::type_id()}
}
pub fn clear(&mut self)
{
unsafe {var_set(self.address.clone(), Ref::null())}
}
}
impl SzunType for Var {
fn type_id() -> usize { unsafe {type_outer(0, types::TYPE_VARYING)} }
fn to_ref(self) -> Ref { self.address.clone() }
fn compatible<T: SzunType>(&self, _:&T) -> bool { true }
fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
}
pub fn var<T: SzunType>(data:&T) -> Var
{
Var::new().with(data)
}
impl Clone for Var {
fn clone(&self) -> Self {
Self { address:unsafe {clone(self.address.clone())} }
}
}
impl From<Ref> for Var {
fn from(refr: Ref) -> Self {
if refr.class == Self::type_id() {
Self { address:refr }
} else { panic!("mismatched szun types"); }
}
}
impl Into<Ref> for Var { fn into(self) -> Ref { self.address.clone() } }
impl Drop for Var {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

View File

@ -1,8 +0,0 @@
struct Parser {
}
pub fn compile() -> Result<(),()>
{
Err(())
}

View File

@ -1,10 +1,11 @@
#![allow(dead_code)] #![allow(dead_code, private_bounds)]
mod tag; pub mod prelude; pub use prelude::*;
mod types;
mod util; mod util;
mod runtime; mod runtime;
mod interface; pub use interface::*; mod interface; pub use interface::*;
mod encoding; pub use encoding::*; //mod encoding; pub use encoding::*;
#[cfg(test)] //#[cfg(test)] mod tests;
mod tests;

3
src/prelude/error.rs Normal file
View File

@ -0,0 +1,3 @@
pub enum SzunError {
MismatchedType,
}

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

@ -0,0 +1,12 @@
mod reference; pub use reference::Ref;
mod error; pub use error::SzunError;
pub trait SzunType : Clone {
fn type_id() -> usize;
fn to_ref(self) -> Ref;
fn compatible<T: SzunType>(&self, refr:&T) -> bool;
fn __to_ref(&self) -> Ref;
fn __from_ref(refr:Ref) -> Self;
}

33
src/prelude/reference.rs Normal file
View File

@ -0,0 +1,33 @@
use crate::{
prelude::*,
runtime::type_key,
};
#[repr(C)]
pub struct Ref {
pub(crate) class:usize,
pub(crate) address:usize,
}
impl Ref {
pub fn null() -> Self { Self { class:0, address:0 } }
pub fn is_some(&self) -> bool { self.address != 0 }
pub fn is_none(&self) -> bool { self.address == 0 }
pub fn is<T: SzunType>(&self) -> bool { unsafe {type_key(T::type_id()) == type_key(self.class)} }
pub(crate) fn clone(&self) -> Self
{
Ref { class:self.class, address:self.address }
}
pub fn try_into<T: SzunType>(self) -> Result<T, SzunError>
{
if self.class == T::type_id() {
Ok(T::__from_ref(self))
} else {
Err(SzunError::MismatchedType)
}
}
}

View File

@ -0,0 +1,5 @@
size_t array_length(Reference addr);
Reference array_cell(Reference addr, size_t index);
extern "C" Reference array_at(Reference addr, size_t index);
extern "C" void array_set(Reference addr, size_t index, Reference source);

View File

@ -0,0 +1,11 @@
size_t block_length(Reference addr);
extern "C" uint8_t block_get(Reference addr, size_t index);
extern "C" void block_set(Reference addr, size_t index, uint8_t value);
//extern "C" uint64_t block_get_natural(Reference addr);
//extern "C" int64_t block_get_integer(Reference addr);
//extern "C" uint64_t block_get_field(Reference addr, size_t index, size_t length);
//extern "C" void block_set_natural(Reference addr, uint64_t data);
//extern "C" void block_set_integer(Reference addr, int64_t data);
//extern "C" void block_set_field(Reference addr, size_t index, size_t length, uint64_t value);

View File

@ -0,0 +1,2 @@
extern "C" void bool_set(Reference addr, Type::Boolean value);
extern "C" Type::Boolean bool_get(Reference addr);

View File

@ -0,0 +1,2 @@
extern "C" void integer_set(Reference addr, Type::Integer value);
extern "C" Type::Integer integer_get(Reference addr);

View File

@ -0,0 +1,21 @@
Reference list_cell(Reference addr, size_t index);
extern "C" size_t list_capacity(Reference addr);
extern "C" size_t list_length(Reference addr);
extern "C" Reference list_at(Reference addr, size_t index);
extern "C" Reference list_front(Reference addr);
extern "C" Reference list_back(Reference addr);
extern "C" void list_clear(Reference addr);
extern "C" void list_insert(Reference addr, size_t index, Reference source);
extern "C" void list_push(Reference addr, Reference source);
extern "C" void list_pop(Reference addr);
extern "C" void list_set(Reference addr, size_t index, Reference source);
extern "C" void list_remove(Reference addr, size_t index);
extern "C" void list_reserve(Reference addr, size_t capacity);
//pub fn list_resize(addr:Ref, length:usize);
//pub fn list_cut(addr:Ref, index:usize, length:usize) -> Ref;
//pub fn list_find(addr:Ref, target:Ref, start:usize) -> usize;
//pub fn list_count(addr:Ref, target:Ref, start:usize) -> usize;
//pub fn list_truncate(addr:Ref, maximum:usize);
//pub fn list_shift(addr:Ref, maximum:usize);

View File

@ -0,0 +1,2 @@
extern "C" void natural_set(Reference addr, Type::Natural value);
extern "C" Type::Natural natural_get(Reference addr);

View File

@ -0,0 +1,7 @@
extern "C" size_t record_length(Reference addr);
extern "C" size_t record_type(Reference addr, size_t index);
Reference record_cell(Reference addr, size_t index);
extern "C" Reference record_at(Reference addr, size_t index);
extern "C" void record_update(Reference addr, size_t index, Reference source);
extern "C" size_t record_keyof(Reference addr, size_t index);
extern "C" size_t record_indexof(Reference addr, size_t key);

View File

@ -0,0 +1,14 @@
extern "C" size_t schema_length(Reference addr);
extern "C" size_t schema_insert(Reference addr, size_t index, size_t type_id);
extern "C" void schema_update(Reference addr, size_t index, size_t type_id);
extern "C" size_t schema_get(Reference addr, size_t index);
extern "C" void schema_remove(Reference addr, size_t index);
extern "C" void schema_clear(Reference addr);
//extern "C" void schema_reorder(Reference addr, size_t index_from, size_t index_to);
extern "C" void schema_map(Reference addr, size_t key, size_t index);
extern "C" void schema_unmap(Reference addr, size_t key);
extern "C" size_t schema_indexof(Reference addr, size_t key);
extern "C" size_t schema_keyof(Reference addr, size_t index);
extern "C" size_t schema_bind(Reference addr, size_t key);
extern "C" size_t schema_binding(size_t key);
extern "C" bool schema_has(size_t id);

View File

@ -0,0 +1,5 @@
extern "C" size_t sequence_length(Reference addr);
extern "C" uint8_t sequence_get(Reference addr, size_t index);
extern "C" void sequence_clear(Reference addr);
extern "C" void sequence_set(Reference addr, size_t index, uint8_t value);
extern "C" void sequence_resize(Reference addr, size_t capacity);

View File

@ -0,0 +1,2 @@
extern "C" void significant_set(Reference addr, Type::Significant value);
extern "C" Type::Significant significant_get(Reference addr);

View File

@ -0,0 +1,12 @@
extern "C" size_t sparse_header_length(Reference addr);
extern "C" Type::SparseHeader sparse_header_data(Reference addr, size_t index);
extern "C" size_t sparse_length(Reference addr);
extern "C" void sparse_clear(Reference addr);
extern "C" size_t sparse_first(Reference addr);
extern "C" size_t sparse_next(Reference addr);
extern "C" size_t sparse_last(Reference addr);
extern "C" Reference sparse_at(Reference addr, size_t index);
extern "C" Reference sparse_get(Reference addr, size_t index);
extern "C" void sparse_set(Reference addr, size_t index, Reference source);
extern "C" void sparse_unset(Reference addr, size_t index);
extern "C" size_t sparse_indexof(Reference addr, size_t index);

View File

@ -0,0 +1,2 @@
extern "C" Reference var_get(Reference addr);
extern "C" void var_set(Reference addr, Reference source);

View File

@ -0,0 +1,6 @@
uint8_t* allocate(size_t type_id, size_t count);
extern "C" Reference acquire(size_t type_id);
extern "C" void release(Reference id);
extern "C" Reference clone(Reference src);
extern "C" bool copy(Reference dst, Reference src);
extern "C" bool transfer(Reference dst, Reference src);

View File

@ -0,0 +1,3 @@
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length);
std::string name_keyof_internal(size_t index);
extern "C" Str name_keyof(size_t index);

View File

@ -0,0 +1,6 @@
extern const size_t MASK_TEMPORARY;
Reference refr_resolve(Reference refr);
Reference refr_make_temporary(Reference refr);
bool refr_is_temporary(Reference refr);
Reference refr_restore(Reference refr);

View File

@ -0,0 +1,9 @@
extern "C" size_t type_outer(size_t id, size_t key);
extern "C" size_t type_inner(size_t id);
extern "C" size_t type_key(size_t id);
extern "C" size_t type_innerkey(size_t id);
extern "C" size_t type_size(size_t type_id);
size_t type_alignment(size_t type_id);
extern "C" size_t kind_hasinner(size_t kind);
extern "C" size_t type_hasinner(size_t type_id);
extern "C" size_t type_sanitize(size_t type_id);

View File

@ -0,0 +1,49 @@
size_t array_length(Reference addr)
{
return type_innerkey(addr.type);
}
Reference array_cell(Reference addr, size_t index)
{
Reference result {0};
size_t lnode = type_inner(addr.type);
size_t length = type_key(lnode);
size_t type = type_inner(lnode);
size_t offset = type_size(type);
// validate for overflow
if(addr.address != nullptr && offset > 0 && index < length) {
result.type = type;
result.address = addr.address + (offset * index);
}
return result;
}
extern "C" Reference array_at(Reference addr, size_t index)
{
Reference result {0};
Reference cell = array_cell(addr, index);
if(cell.address != nullptr) {
//if(type_key(cell.type) == Type::TYPE_VARYING) {
// result = var_get(cell);
//}
//else {
result = cell;
//}
}
return refr_make_temporary(result);
}
extern "C" void array_set(Reference addr, size_t index, Reference source)
{
Reference cell = array_cell(addr, index);
if(cell.address != nullptr) {
if(type_key(cell.type) == Type::TYPE_VARYING) {
var_set(cell, source);
}
else {
copy(cell, source);
}
}
}

View File

@ -0,0 +1,134 @@
size_t block_length(Reference addr)
// Returns the data length of the block.
//
{
return type_innerkey(addr.type);
}
extern "C" uint8_t block_get(Reference addr, size_t index)
// Returns one byte of data from the specified index.
//
{
if(index < block_length(addr)) {
return reinterpret_cast<uint8_t*>(addr.address)[index];
}
return 0;
}
extern "C" void block_set(Reference addr, size_t index, uint8_t value)
// Sets one byte of data at the specified index.
//
{
if(index < block_length(addr)) {
reinterpret_cast<uint8_t*>(addr.address)[index] = value;
}
}
/*extern "C" uint64_t block_get_natural(Reference addr)
{
size_t length = type_innerkey(addr.type);
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
uint64_t result = 0;
for(size_t i = 0; i < length; ++i) {
result |= data[i] << (8 * i);
}
return result;
}*/
/*extern "C" int64_t block_get_integer(Reference addr)
{
size_t length = type_innerkey(addr.type);
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
int64_t result = 0;
for(size_t i = 0; i < length; ++i) {
result |= data[i] << (8 * i);
}
return result;
}*/
/*extern "C" uint64_t block_get_field(Reference addr, size_t index, size_t length)
{
size_t data_length = type_innerkey(addr.type);
size_t byte_start = index >> 3;
size_t bit_offset = index & 0x07;
size_t byte_length = 1 + ((bit_offset + length) >> 3);
size_t byte_end = byte_start + byte_length;
size_t mask_offset = ((8 * byte_length) - (length + bit_offset));
uint64_t mask = ((1 << length) - 1) << mask_offset;
uint64_t bits = 0;
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
size_t i = byte_start;
for(; i < data_length && i < byte_end; ++i) {
bits <<= 8;
bits |= data[i];
}
for(; i < byte_end; ++i) {
bits <<= 8;
}
return (bits & mask) >> mask_offset;
}*/
/*extern "C" void block_set_natural(Reference addr, uint64_t data)
{
size_t length = type_innerkey(addr.type);
uint8_t* dest = reinterpret_cast<uint8_t*>(addr.address);
for(size_t i = 0; i < length; ++i) {
dest[i] = (data >> (i * 8)) & 0xFF;
}
}*/
/*extern "C" void block_set_integer(Reference addr, int64_t data)
{
size_t length = type_innerkey(addr.type);
uint8_t* dest = reinterpret_cast<uint8_t*>(addr.address);
for(size_t i = length; i > 0; --i) {
dest[i] = (data >> (i * 8)) & 0xFF;
}
}*/
/*extern "C" void block_set_field(Reference addr, size_t index, size_t length, uint64_t value)
{
size_t data_length = type_innerkey(addr.type);
size_t byte_start = index >> 3;
size_t bit_offset = index & 0x07;
size_t byte_length = 1 + ((bit_offset + length) >> 3);
size_t byte_end = byte_start + byte_length;
size_t mask_offset = ((8 * byte_length) - (length + bit_offset));
uint64_t mask = ((1 << length) - 1) << mask_offset;
uint64_t bits = 0;
uint8_t* data = reinterpret_cast<uint8_t*>(addr.address);
size_t byte_index = byte_start;
for(; byte_index < data_length && byte_index < byte_end; ++byte_index) {
bits <<= 8;
bits |= data[byte_index];
}
for(; byte_index < byte_end; ++byte_index) {
bits <<= 8;
}
bits &= ~mask;
bits |= mask & (value << mask_offset);
for(; byte_index > data_length; --byte_index) {
bits >>= 8;
}
for(; byte_index > byte_start; --byte_index) {
data[byte_index - 1] = bits & 0xFF;
bits >>= 8;
}
}*/

View File

@ -0,0 +1,9 @@
extern "C" void bool_set(Reference addr, Type::Boolean value)
{
*(reinterpret_cast<Type::Boolean*>(addr.address)) = value;
}
extern "C" Type::Boolean bool_get(Reference addr)
{
return *(reinterpret_cast<Type::Boolean*>(addr.address));
}

View File

@ -0,0 +1,9 @@
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));
}

View File

@ -0,0 +1,9 @@
extern "C" void integer_set(Reference addr, Type::Integer value)
{
*(reinterpret_cast<Type::Integer*>(addr.address)) = value;
}
extern "C" Type::Integer integer_get(Reference addr)
{
return *(reinterpret_cast<Type::Integer*>(addr.address));
}

View File

@ -0,0 +1,152 @@
Reference list_cell(Reference addr, size_t index)
// Returns a reference to the list cell at the specified index.
//
{
Reference result {0};
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
// validate for overflow
if(list.data.data != nullptr && offset > 0 && index < list.data.capacity) {
result.type = inner;
result.address = rawlist_cell(list.data, offset, index);
}
return result;
}
extern "C" size_t list_capacity(Reference addr)
// Returns the capacity of the list.
//
{
return (*reinterpret_cast<Type::List*>(addr.address)).data.capacity;
}
extern "C" size_t list_length(Reference addr)
// Returns the number of elements in the list.
//
{
return (*reinterpret_cast<Type::List*>(addr.address)).data.length;
}
extern "C" Reference list_at(Reference addr, size_t index)
// Returns a reference to the cell at the specified index.
//
{
Reference result {0};
Reference cell = list_cell(addr, index);
if(cell.address != nullptr) {
//if(type_key(cell.type) == Type::TYPE_VARYING) {
// result = *reinterpret_cast<Reference*>(cell.address);
//} else {
result = cell;
//}
}
return refr_make_temporary(result);
}
extern "C" Reference list_front(Reference addr)
// Returns a reference to the first element in the list.
//
{
return list_at(addr, 0);
}
extern "C" Reference list_back(Reference addr)
// Returns a reference to the last element in the list.
//
{
Reference result {0};
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
if(list.data.length > 0) {
result = list_at(addr, list.data.length - 1);
}
return result;
}
extern "C" void list_clear(Reference addr)
// Drops and removes all elements from the list.
//
{
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
for(size_t i = 0; i < list.data.length; ++i) {
drop(list_cell(addr, i));
}
rawlist_clear(list.data);
}
extern "C" void list_insert(Reference addr, size_t index, Reference source)
// Inserts an element at the specified index, shifting the trailing items.
//
{
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
if(index > list.data.length) { index = list.data.length; }
Reference cell {0};
cell.type = inner;
cell.address = rawlist_insert(list.data, offset, index);
if(type_key(inner) == Type::TYPE_VARYING) {
var_set(cell, source);
}
else {
copy(cell, source);
}
}
extern "C" void list_push(Reference addr, Reference source)
// Adds an element to the end of the list.
//
{
auto& list = *reinterpret_cast<Type::List*>(addr.address);
list_insert(addr, list.data.length, source);
}
extern "C" void list_pop(Reference addr)
// Removes an element from the end of the list.
//
{
auto& list = *reinterpret_cast<Type::List*>(addr.address);
list_remove(addr, list.data.length - 1);
}
extern "C" void list_set(Reference addr, size_t index, Reference source)
{
auto& list = *reinterpret_cast<Type::List*>(addr.address);
if(index < list.data.length) {
size_t inner = type_inner(addr.type);
if(type_key(inner) == Type::TYPE_VARYING) {
var_set(list_cell(addr, index), source);
}
else {
copy(list_cell(addr, index), source);
}
}
}
extern "C" void list_remove(Reference addr, size_t index)
{
auto& list = *reinterpret_cast<Type::List*>(addr.address);
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
if(index < list.data.length) {
drop(list_at(addr, index));
rawlist_remove(list.data, offset, index);
}
}
extern "C" void list_reserve(Reference addr, size_t capacity)
{
auto& list = *reinterpret_cast<Type::List*>(addr.address);
size_t inner = type_inner(addr.type);
size_t offset = type_size(inner);
rawlist_reserve(list.data, offset, capacity);
}

View File

@ -0,0 +1,9 @@
extern "C" void natural_set(Reference addr, Type::Natural value)
{
*(reinterpret_cast<Type::Natural*>(addr.address)) = value;
}
extern "C" Type::Natural natural_get(Reference addr)
{
return *(reinterpret_cast<Type::Natural*>(addr.address));
}

View File

@ -0,0 +1,79 @@
extern "C" size_t record_length(Reference addr)
{
auto binding = DB_SCHEMA.get(type_innerkey(addr.type));
if(binding != nullptr) {
return binding->data.size();
}
return 0;
}
extern "C" size_t record_type(Reference addr, size_t index)
{
auto binding = DB_SCHEMA.get(type_innerkey(addr.type));
if(binding != nullptr && index < binding->data.size()) {
return binding->data[index].type;
}
return 0;
}
Reference record_cell(Reference addr, size_t index)
{
Reference result {0};
auto binding = DB_SCHEMA.get(type_innerkey(addr.type));
if(binding != nullptr) {
if(index < binding->data.size()) {
result.type = binding->data[index].type;
result.address = addr.address + binding->data[index].offset;
}
}
return result;
}
extern "C" Reference record_at(Reference addr, size_t index)
{
Reference result = record_cell(addr, index);
if(type_key(result.type) == Type::TYPE_VARYING) {
result = var_get(result);
}
return result;
}
extern "C" void record_update(Reference addr, size_t index, Reference source)
{
Reference destination {0};
size_t schid = type_innerkey(addr.type);
auto binding = DB_SCHEMA.get(schid);
if(binding != nullptr) {
if(index < binding->data.size()) {
destination.type = binding->data[index].type;
destination.address = addr.address + binding->data[index].offset;
copy(destination, source);
}
}
}
extern "C" size_t record_keyof(Reference addr, size_t index)
{
Reference destination {0};
auto binding = DB_SCHEMA.get(type_innerkey(addr.type));
if(binding != nullptr) {
if(index < binding->data.size()) {
return binding->data[index].key;
}
}
return 0;
}
extern "C" size_t record_indexof(Reference addr, size_t key)
{
Reference destination {0};
auto binding = DB_SCHEMA.get(type_innerkey(addr.type));
if(binding != nullptr) {
auto result = binding->map.get(key);
if(result != nullptr) {
return *result;
}
return binding->data.size();
}
return 0;
}

View File

@ -0,0 +1,216 @@
extern "C" size_t schema_length(Reference addr)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
return object.data.length;
}
extern "C" size_t schema_insert(Reference addr, size_t index, size_t type_id)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index >= object.data.length) {
index = object.data.length;
}
void* cell = rawlist_insert(object.data, sizeof(size_t), index);
*reinterpret_cast<size_t*>(cell) = type_id;
return index;
}
extern "C" void schema_update(Reference addr, size_t index, size_t type_id)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index < object.data.length) {
auto cell = reinterpret_cast<size_t*>(rawlist_cell(object.data, sizeof(size_t), index));
if(cell != nullptr) {
*cell = type_id;
}
}
}
extern "C" size_t schema_get(Reference addr, size_t index)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index < object.data.length) {
auto cell = reinterpret_cast<size_t*>(rawlist_cell(object.data, sizeof(size_t), index));
if(cell != nullptr) {
return *cell;
}
}
return 0;
}
extern "C" void schema_data_set(Reference addr, size_t index)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index < object.data.length) {
auto cell = reinterpret_cast<size_t*>(rawlist_cell(object.map, sizeof(size_t), index));
if(cell != nullptr) {
}
}
}
extern "C" void schema_data_get(Reference addr, size_t index)
{
}
extern "C" void schema_remove(Reference addr, size_t index)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index < object.data.length) {
rawlist_remove(object.data, sizeof(size_t), index);
// remove mapping
for(size_t i = 0; i < object.map.length; i++) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.data, sizeof(Type::Schema::Mapping), i));
if(cell != nullptr) {
if(cell->index == index) {
rawlist_remove(object.map, sizeof(Type::Schema::Mapping), i);
return;
}
}
}
}
}
extern "C" void schema_clear(Reference addr)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
rawlist_clear(object.data);
rawlist_clear(object.map);
}
extern "C" void schema_map(Reference addr, size_t key, size_t index)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
if(index < object.data.length) {
size_t find_index = 0;
for(; find_index < object.map.length; find_index++) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), find_index));
if(cell != nullptr) {
if(cell->key == key) { break; }
}
}
// if key is not found, add new mapping
if(find_index == object.map.length) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_insert(object.map, sizeof(Type::Schema::Mapping), object.map.length));
cell->key = key;
cell->index = index;
}
// otherwise, update existing key
else {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), find_index));
cell->index = index;
}
}
}
extern "C" void schema_unmap(Reference addr, size_t key)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
for(size_t i; i < object.map.length; ++i) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
if(cell != nullptr) {
if(cell->key == key) {
rawlist_remove(object.map, sizeof(Type::Schema::Mapping), i);
return;
}
}
}
}
extern "C" size_t schema_indexof(Reference addr, size_t key)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
for(size_t i = 0; i < object.map.length; i++) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
if(cell != nullptr) {
if(cell->key == key) {
return cell->index;
}
}
}
return object.data.length;
}
extern "C" size_t schema_keyof(Reference addr, size_t index)
{
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
for(size_t i = 0; i < object.map.length; i++) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
if(cell != nullptr) {
if(cell->index == index) {
return cell->key;
}
}
}
return object.data.length;
}
extern "C" size_t schema_bind(Reference addr, size_t id)
{
if(id > 0) {
Type::SchemaBinding binding {0};
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
// prepare binding
binding.binding = id;
for(size_t i = 0; i < object.data.length; ++i) {
Type::SchemaBinding::Row row {0};
size_t type_id = *reinterpret_cast<size_t*>(rawlist_cell(object.data, sizeof(size_t), i));
size_t size = type_size(type_id);
// fail if size is not valid
if(size == 0) { return 0; }
size_t alignment = type_alignment(type_id);
binding.alignment = std::max(alignment, binding.alignment);
size_t position = ((binding.size + (alignment - 1)) & ~(alignment - 1));
binding.size = size + position;
row.type = type_id;
row.offset = position;
binding.data.push_back(row);
}
binding.size = ((binding.size + (binding.alignment - 1)) & ~(binding.alignment - 1));
binding.references = 0;
for(size_t i = 0; i < object.map.length; ++i) {
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
binding.map.set(cell->key, cell->index);
binding.data[cell->index].key = cell->key;
}
/* printf("[Binding]\n");
printf(" Id: %zu\n", binding.binding);
printf(" Size: %zu\n", binding.size);
printf(" Align: %zu\n", binding.alignment);
printf(" Data:\n");
for(size_t i = 0; i < binding.data.size(); ++i) {
printf(" - %zu:%#x +%zu\n",
binding.data[i].type,
type_key(binding.data[i].type),
binding.data[i].offset
);
}
printf(" Map:\n");
for(size_t key : binding.map.indices()) {
printf(" - %zu -> %zu\n",
key,
*binding.map.get(key)
);
} */
// add binding to pool
DB_SCHEMA.set(id, binding);
return id;
}
return 0;
}
extern "C" bool schema_has(size_t id)
{
return DB_SCHEMA.has(id);
}

View File

@ -0,0 +1,44 @@
extern "C" size_t sequence_length(Reference addr)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
return seq.data.length;
}
extern "C" uint8_t sequence_get(Reference addr, size_t index)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
if(index < seq.data.length) {
return *reinterpret_cast<uint8_t*>(rawlist_cell(seq.data, 1, index));
}
return 0;
}
extern "C" void sequence_clear(Reference addr)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
rawlist_clear(seq.data);
}
extern "C" void sequence_set(Reference addr, size_t index, uint8_t value)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
auto cell = reinterpret_cast<uint8_t*>(rawlist_cell(seq.data, 1, index));
if(cell != nullptr) {
*cell = value;
}
}
extern "C" void sequence_insert(Reference addr, size_t index, uint8_t value)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
auto cell = reinterpret_cast<uint8_t*>(rawlist_insert(seq.data, 1, index));
if(cell != nullptr) {
*cell = value;
}
}
extern "C" void sequence_resize(Reference addr, size_t capacity)
{
Type::Sequence& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
rawlist_resize(seq.data, 1, capacity);
}

View File

@ -0,0 +1,9 @@
extern "C" void significant_set(Reference addr, Type::Significant value)
{
*(reinterpret_cast<Type::Significant*>(addr.address)) = value;
}
extern "C" Type::Significant significant_get(Reference addr)
{
return *(reinterpret_cast<Type::Significant*>(addr.address));
}

View File

@ -0,0 +1,288 @@
extern "C" size_t sparse_header_length(Reference addr)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
return list.header.length;
}
extern "C" Type::SparseHeader sparse_header_data(Reference addr, size_t index)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
Type::SparseHeader header {0};
if(index < list.header.length) {
header = *reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), index));
}
return header;
}
extern "C" size_t sparse_length(Reference addr)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
return list.data.length;
}
extern "C" void sparse_clear(Reference addr)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
size_t inner = type_inner(addr.type);
Reference ref {0};
ref.type = inner;
for(size_t i = 0; i < list.data.length; ++i) {
ref.address = rawlist_cell(list.data, type_size(inner), i);
drop(ref);
}
rawlist_clear(list.data);
rawlist_clear(list.header);
}
extern "C" size_t sparse_first(Reference addr)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
if(list.header.length > 0) {
auto cell = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), 0));
if(cell != nullptr) {
return cell->start;
}
}
return 0;
}
extern "C" size_t sparse_next(Reference addr)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
if(list.header.length > 0) {
auto cell = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), 0));
if(cell != nullptr) {
return cell->start + cell->length;
}
}
return 0;
}
extern "C" size_t sparse_last(Reference addr)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
if(list.header.length > 0) {
auto cell = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), list.header.length - 1));
if(cell != nullptr) {
return cell->start + cell->length - 1;
}
}
return 0;
}
extern "C" Reference sparse_at(Reference addr, size_t index)
{
Reference result {0};
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
size_t inner = type_inner(addr.type);
if(index < list.data.length) {
auto cell = rawlist_cell(list.data, type_size(inner), index);
if(cell != nullptr) {
result.type = inner;
result.address = cell;
}
if(type_key(inner) == Type::TYPE_VARYING) {
result = var_get(result);
}
}
return result;
}
extern "C" Reference sparse_get(Reference addr, size_t index)
{
Reference result {0};
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
size_t inner = type_inner(addr.type);
size_t bound_lower = 0;
size_t bound_upper = list.header.length;
size_t header_index = 0;
Type::SparseHeader* header = nullptr;
while(bound_lower != bound_upper) {
header_index = bound_lower + ((bound_upper - bound_lower) / 2);
header = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), header_index));
if(index >= header->start && index < (header->start + header->length)) {
break;
}
else if(index < header->start) {
bound_upper = header_index;
}
else {
bound_lower = header_index + 1;
}
header = nullptr;
}
if(header != nullptr) {
result.type = inner;
size_t data_index = header->index + (index - header->start);
result.address = rawlist_cell(list.data, type_size(inner), data_index);
if(type_key(result.type) == Type::TYPE_VARYING) {
result = var_get(result);
}
}
return result;
}
extern "C" void sparse_set(Reference addr, size_t index, Reference source)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
size_t inner = type_inner(addr.type);
size_t header_index = 0;
Type::SparseHeader* header = nullptr;
for(; header_index < list.header.length; ++header_index) {
header = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), header_index));
if(index <= (header->start + header->length)) {
break;
}
}
Type::SparseHeader header_new;
Reference new_data {0};
new_data.type = inner;
if(header_index == list.header.length) {
// append header to end
header_new.start = index;
header_new.length = 1;
header_new.index = list.data.length;
new_data.address = rawlist_insert(list.data, type_size(inner), list.data.length);
copy(new_data, source);
auto& h_cell = *reinterpret_cast<Type::SparseHeader*>(rawlist_insert(list.header, sizeof(Type::SparseHeader), list.header.length));
h_cell = header_new;
} else {
if(index < header->start) {
// insert header before current
header_new.start = index;
header_new.length = 1;
header_new.index = header->index;
new_data.address = rawlist_insert(list.data, type_size(inner), header->index);
copy(new_data, source);
header = reinterpret_cast<Type::SparseHeader*>(rawlist_insert(list.header, sizeof(Type::SparseHeader), header_index));
*header = header_new;
for(size_t i = header_index + 1; i < list.header.length; ++i) {
auto hcell = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), i));
hcell->index++;
}
} else {
size_t offset = index - header->start;
if(offset < header->length) {
// update existing value
new_data.address = rawlist_cell(list.data, type_size(inner), header->index + offset);
drop(new_data);
copy(new_data, source);
} else {
// append value to current
new_data.address = rawlist_insert(list.data, type_size(inner), header->index + offset);
copy(new_data, source);
header->length++;
for(size_t i = header_index + 1; i < list.header.length; ++i) {
auto hcell = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), i));
hcell->index++;
}
}
}
// join headers if ranges intersect
if(header_index + 1 < list.header.length) {
auto next_header = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), header_index + 1));
if(next_header->start == header->start + header->length) {
header->length += next_header->length;
rawlist_remove(list.header, sizeof(Type::SparseHeader), header_index + 1);
}
}
}
}
extern "C" void sparse_unset(Reference addr, size_t index)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
size_t inner = type_inner(addr.type);
size_t header_index = 0;
Type::SparseHeader* header = nullptr;
for(; header_index < list.header.length; ++header_index) {
header = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), header_index));
if(index <= (header->start + header->length)) {
break;
}
}
Type::SparseHeader header_new;
Reference cell {0};
cell.type = inner;
if(header_index < list.header.length && index >= header->start) {
size_t offset = index - header->start;
size_t data_index = header->index + offset;
if(offset == 0) {
// shift start of range
header->start++;
} else if(offset < header->length - 1) {
// split header at index
header_new.start = index + 1;
header_new.length = header->length - offset - 1;
header_new.index = header->index + offset + 1;
header->length = offset + 1;
auto header_insert = reinterpret_cast<Type::SparseHeader*>(rawlist_insert(list.header, sizeof(Type::SparseHeader), header_index + 1));
*header_insert = header_new;
}
cell.address = rawlist_cell(list.data, type_size(inner), data_index);
drop(cell);
rawlist_remove(list.data, type_size(inner), data_index);
header->length--;
for(size_t i = header_index + 1; i < list.header.length; ++i) {
auto hcell = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), i));
hcell->index--;
}
if(header->length == 0) {
rawlist_remove(list.header, sizeof(Type::SparseHeader), header_index);
}
}
}
extern "C" size_t sparse_indexof(Reference addr, size_t index)
{
auto& list = *reinterpret_cast<Type::Sparse*>(addr.address);
for(size_t i = 0; i < list.header.length; ++i) {
auto hcell = reinterpret_cast<Type::SparseHeader*>(rawlist_cell(list.header, sizeof(Type::SparseHeader), i));
if(index < hcell->length) {
return hcell->start + index;
} else {
index -= hcell->length;
}
}
return 0;
}

View File

@ -0,0 +1,29 @@
extern "C" Reference var_get(Reference addr)
// Returns the inner reference.
//
{
Reference result {0};
result = *reinterpret_cast<Reference*>(addr.address);
return refr_make_temporary(result);
}
extern "C" void var_set(Reference addr, Reference source)
// Sets the inner reference.
//
{
Reference& var = *reinterpret_cast<Reference*>(addr.address);
if(var.address != nullptr) {
drop(var);
}
if(var.type != source.type || var.address == nullptr) {
if(var.address != nullptr) {
free(var.address);
}
var.type = source.type;
var.address = allocate(source.type, 1);
}
copy(var, source);
}

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,12 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include "type.h" #include "util/rawlist/rawlist.h"
#include "typetree.h" #include "util/sparselist.h"
#include "nametree.h" #include "util/pool.h"
#include "sparselist.h" #include "util/type.h"
#include "rawlist.h" #include "util/typetree.h"
#include "pool.h" #include "util/nametree.h"
extern "C" struct Str { extern "C" struct Str {
uint8_t* bytes; uint8_t* bytes;
@ -21,128 +21,24 @@ extern Pool<Reference> DB_REFERENCE;
extern "C" void test(); extern "C" void test();
extern "C" size_t type_outer(size_t id, size_t key); #include "header/refr.h"
extern "C" size_t type_inner(size_t id); #include "header/type.h"
extern "C" size_t type_key(size_t id); #include "header/name.h"
extern "C" size_t type_innerkey(size_t id); #include "header/memory.h"
extern "C" size_t type_size(size_t type_id);
size_t type_alignment(size_t type_id);
extern "C" size_t kind_hasinner(size_t kind);
extern "C" size_t type_hasinner(size_t type_id);
#include "header/implement/boolean.h"
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length); #include "header/implement/natural.h"
std::string name_keyof_internal(size_t index); #include "header/implement/integer.h"
extern "C" Str name_keyof(size_t index); #include "header/implement/significant.h"
uint8_t* allocate(size_t type_id, size_t count); #include "header/implement/block.h"
extern "C" Reference acquire(size_t type_id); #include "header/implement/sequence.h"
extern "C" void release(Reference id);
extern "C" bool copy(Reference dst, Reference src);
extern "C" bool transfer(Reference dst, Reference src);
Reference resolve_addr(Reference addr); #include "header/implement/var.h"
#include "header/implement/array.h"
#include "header/implement/list.h"
#include "header/implement/sparse.h"
// Varying // #include "header/implement/record.h"
extern "C" Reference varying_get(Reference addr); #include "header/implement/schema.h"
extern "C" void varying_set(Reference addr, Reference source);
extern "C" void varying_clear(Reference addr);
// Boolean //
extern "C" void bool_set(Reference addr, Type::Boolean value);
extern "C" Type::Boolean bool_get(Reference addr);
// Natural //p
extern "C" void natural_set(Reference addr, Type::Natural value);
extern "C" Type::Natural natural_get(Reference addr);
// Integer //
extern "C" void integer_set(Reference addr, Type::Integer value);
extern "C" Type::Integer integer_get(Reference addr);
// Significant //
extern "C" void significant_set(Reference addr, Type::Significant value);
extern "C" Type::Significant significant_get(Reference addr);
// Block //
extern "C" size_t block_length(Reference addr);
extern "C" uint8_t block_get(Reference addr, size_t index);
extern "C" uint64_t block_get_natural(Reference addr);
extern "C" int64_t block_get_integer(Reference addr);
extern "C" uint64_t block_get_field(Reference addr, size_t index, size_t length);
extern "C" void block_set(Reference addr, size_t index, uint8_t value);
extern "C" void block_set_natural(Reference addr, uint64_t data);
extern "C" void block_set_integer(Reference addr, int64_t data);
extern "C" void block_set_field(Reference addr, size_t index, size_t length, uint64_t value);
// Sequence //
extern "C" size_t sequence_capacity(Reference addr);
extern "C" size_t sequence_length(Reference addr);
extern "C" uint8_t sequence_get(Reference addr, size_t index);
extern "C" void sequence_clear(Reference addr);
extern "C" void sequence_set(Reference addr, size_t index, uint8_t value);
extern "C" void sequence_insert(Reference addr, size_t index, uint8_t value);
extern "C" void sequence_reserve(Reference addr, size_t capacity);
// Array //
extern "C" size_t array_length(Reference addr);
Reference array_cell(Reference addr, size_t index);
extern "C" Reference array_at(Reference addr, size_t index);
extern "C" void array_update(Reference addr, size_t index, Reference source);
// List //
extern "C" size_t list_capacity(Reference addr);
extern "C" size_t list_length(Reference addr);
Reference list_cell(Reference addr, size_t index);
extern "C" Reference list_at(Reference addr, size_t index);
//extern "C" Reference list_first(Reference addr);
//extern "C" Reference list_last(Reference addr);
extern "C" void list_clear(Reference addr);
extern "C" void list_insert(Reference addr, size_t index, Reference source);
extern "C" void list_prepend(Reference addr, Reference source);
extern "C" void list_append(Reference addr, Reference source);
extern "C" void list_update(Reference addr, size_t index, Reference source);
//extern "C" void list_truncate(Reference addr, size_t maximum);
//extern "C" void list_shift(Reference addr);
extern "C" void list_remove(Reference addr, size_t index);
extern "C" void list_reserve(Reference addr, size_t capacity);
//extern "C" void list_resize(Reference addr, size_t length);
// Sparse //
extern "C" size_t sparse_header_length(Reference addr);
extern "C" Type::SparseHeader sparse_header_data(Reference addr, size_t index);
extern "C" size_t sparse_length(Reference addr);
extern "C" void sparse_clear(Reference addr);
extern "C" size_t sparse_first(Reference addr);
extern "C" size_t sparse_next(Reference addr);
extern "C" size_t sparse_last(Reference addr);
extern "C" Reference sparse_at(Reference addr, size_t index);
extern "C" Reference sparse_get(Reference addr, size_t index);
extern "C" void sparse_set(Reference addr, size_t index, Reference source);
extern "C" void sparse_unset(Reference addr, size_t index);
extern "C" size_t sparse_indexof(Reference addr, size_t index);
// Record //
extern "C" size_t record_length(Reference addr);
extern "C" size_t record_type(Reference addr, size_t index);
Reference record_cell(Reference addr, size_t index);
extern "C" Reference record_at(Reference addr, size_t index);
extern "C" void record_update(Reference addr, size_t index, Reference source);
extern "C" size_t record_keyof(Reference addr, size_t index);
extern "C" size_t record_indexof(Reference addr, size_t key);
// Schema //
extern "C" size_t schema_length(Reference addr);
extern "C" size_t schema_insert(Reference addr, size_t index, size_t type_id);
extern "C" void schema_update(Reference addr, size_t index, size_t type_id);
extern "C" size_t schema_get(Reference addr, size_t index);
extern "C" void schema_remove(Reference addr, size_t index);
extern "C" void schema_clear(Reference addr);
//extern "C" void schema_reorder(Reference addr, size_t index_from, size_t index_to);
extern "C" void schema_map(Reference addr, size_t key, size_t index);
extern "C" void schema_unmap(Reference addr, size_t key);
extern "C" size_t schema_indexof(Reference addr, size_t key);
extern "C" size_t schema_keyof(Reference addr, size_t index);
extern "C" size_t schema_bind(Reference addr, size_t key);
extern "C" size_t schema_binding(size_t key);
extern "C" bool schema_has(size_t id);

View File

@ -1,30 +1,6 @@
pub mod util; pub mod util;
#[repr(C)] use crate::prelude::Ref;
#[derive(Clone, Copy)]
pub struct Reference {
pub(crate) class:usize,
pub(crate) address:usize,
}
impl Reference {
pub fn null() -> Self
{
Self {
class:0,
address:0,
}
}
pub fn is_null(&self) -> bool
{
self.address != 0
}
pub fn kind(&self) -> usize
{
self.class
}
}
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -44,11 +20,12 @@ pub struct SparseHeader {
extern "C" { extern "C" {
pub fn test(); pub fn test();
pub fn acquire(type_id:usize) -> Reference; pub fn acquire(type_id:usize) -> Ref;
pub fn release(addr:Reference); pub fn release(addr:Ref);
pub fn copy(dst:Reference, src:Reference) -> bool; pub fn clone(src:Ref) -> Ref;
pub fn transfer(dst:Reference, src:Reference) -> bool; pub fn copy(dst:Ref, src:Ref) -> bool;
pub fn transfer(dst:Ref, src:Ref) -> bool;
pub fn type_outer(type_id:usize, key:usize) -> usize; pub fn type_outer(type_id:usize, key:usize) -> usize;
pub fn type_inner(type_id:usize) -> usize; pub fn type_inner(type_id:usize) -> usize;
@ -56,104 +33,89 @@ extern "C" {
pub fn type_innerkey(type_id:usize) -> usize; pub fn type_innerkey(type_id:usize) -> usize;
pub fn kind_hasinner(kind:usize) -> usize; pub fn kind_hasinner(kind:usize) -> usize;
pub fn type_hasinner(type_id:usize) -> usize; pub fn type_hasinner(type_id:usize) -> usize;
pub fn type_sanitize(type_id:usize) -> usize;
pub fn type_size(type_id:usize) -> usize; //pub fn type_size(type_id:usize) -> usize;
pub fn name_indexof(data:*const u8, length:usize) -> usize; pub fn name_indexof(data:*const u8, length:usize) -> usize;
pub fn name_keyof(index:usize) -> Str; pub fn name_keyof(index:usize) -> Str;
pub fn name_release(data:Str); pub fn name_release(data:Str);
pub fn varying_get(addr:Reference) -> Reference; pub fn bool_set(addr:Ref, data:bool);
pub fn varying_set(addr:Reference, source:Reference); pub fn bool_get(addr:Ref) -> bool;
pub fn varying_clear(addr:Reference);
pub fn bool_set(addr:Reference, data:bool);
pub fn bool_get(addr:Reference) -> bool;
pub fn natural_set(addr:Reference, data:u64); pub fn natural_set(addr:Ref, data:u64);
pub fn natural_get(addr:Reference) -> u64; pub fn natural_get(addr:Ref) -> u64;
pub fn integer_set(addr:Reference, data:i64); pub fn integer_set(addr:Ref, data:i64);
pub fn integer_get(addr:Reference) -> i64; pub fn integer_get(addr:Ref) -> i64;
pub fn decimal_set(addr:Reference, data:i64); //pub fn decimal_set(addr:Ref, data:i64);
pub fn decimal_get(addr:Reference) -> i64; //pub fn decimal_get(addr:Ref) -> i64;
pub fn significant_set(addr:Reference, data:f64); //pub fn significant_set(addr:Ref, data:f64);
pub fn significant_get(addr:Reference) -> f64; //pub fn significant_get(addr:Ref) -> f64;
pub fn block_length(addr:Reference) -> usize; pub fn block_get(addr:Ref, index:usize) -> u8;
pub fn block_get(addr:Reference, index:usize) -> u8; pub fn block_set(addr:Ref, index:usize, data:u8);
pub fn block_get_natural(addr:Reference) -> u64;
pub fn block_get_integer(addr:Reference) -> i64;
pub fn block_get_field(addr:Reference, index:usize, length:usize) -> u64;
pub fn block_set(addr:Reference, index:usize, data:u8);
pub fn block_set_natural(addr:Reference, data:u64);
pub fn block_set_integer(addr:Reference, data:i64);
pub fn block_set_field(addr:Reference, index:usize, length:usize, data:u64);
pub fn sequence_capacity(addr:Reference) -> usize; pub fn sequence_length(addr:Ref) -> usize;
pub fn sequence_length(addr:Reference) -> usize; pub fn sequence_get(addr:Ref, index:usize) -> u8;
pub fn sequence_get(addr:Reference, index:usize) -> u8; pub fn sequence_clear(addr:Ref);
pub fn sequence_clear(addr:Reference); pub fn sequence_set(addr:Ref, index:usize, value:u8);
pub fn sequence_set(addr:Reference, index:usize, value:u8); pub fn sequence_resize(addr:Ref, capacity:usize);
pub fn sequence_insert(addr:Reference, index:usize, value:u8);
pub fn sequence_reserve(addr:Reference, capacity:usize);
pub fn array_length(addr:Reference) -> usize;
pub fn array_at(addr:Reference, index:usize) -> Reference;
pub fn array_update(addr:Reference, index:usize, source:Reference);
pub fn list_capacity(addr:Reference) -> usize; pub fn var_get(addr:Ref) -> Ref;
pub fn list_length(addr:Reference) -> usize; pub fn var_set(addr:Ref, source:Ref);
//pub fn list_first(addr:Reference) -> Reference; pub fn var_clear(addr:Ref);
//pub fn list_last(addr:Reference) -> Reference;
pub fn list_at(addr:Reference, index:usize) -> Reference;
pub fn list_clear(addr:Reference);
pub fn list_insert(addr:Reference, index:usize, src:Reference);
pub fn list_prepend(addr:Reference, src:Reference);
pub fn list_append(addr:Reference, src:Reference);
pub fn list_update(addr:Reference, index:usize, src:Reference);
//pub fn list_truncate(addr:Reference, maximum:usize);
//pub fn list_shift(addr:Reference, maximum:usize);
pub fn list_remove(addr:Reference, index:usize);
pub fn list_reserve(addr:Reference, capacity:usize);
//pub fn list_resize(addr:Reference, length:usize);
//pub fn list_cut(addr:Reference, index:usize, length:usize) -> Reference;
//pub fn list_find(addr:Reference, target:Reference, start:usize) -> usize;
//pub fn list_count(addr:Reference, target:Reference, start:usize) -> usize;
pub fn sparse_header_length(addr:Reference) -> usize; pub fn array_at(addr:Ref, index:usize) -> Ref;
pub fn sparse_header_data(addr:Reference, index:usize) -> SparseHeader; pub fn array_set(addr:Ref, index:usize, source:Ref);
pub fn sparse_length(addr:Reference) -> usize;
pub fn sparse_clear(addr:Reference);
pub fn sparse_first(addr:Reference) -> usize;
pub fn sparse_next(addr:Reference) -> usize;
pub fn sparse_last(addr:Reference) -> usize;
pub fn sparse_get(addr:Reference, index:usize) -> Reference;
pub fn sparse_at(addr:Reference, index:usize) -> Reference;
pub fn sparse_set(addr:Reference, index:usize, source:Reference);
pub fn sparse_unset(addr:Reference, index:usize);
pub fn sparse_indexof(addr:Reference, index:usize) -> usize;
pub fn record_length(addr:Reference) -> usize; pub fn list_capacity(addr:Ref) -> usize;
pub fn record_type(addr:Reference, index:usize) -> usize; pub fn list_length(addr:Ref) -> usize;
pub fn record_at(addr:Reference, index:usize) -> Reference; pub fn list_front(addr:Ref) -> Ref;
pub fn record_update(addr:Reference, index:usize, source:Reference); pub fn list_back(addr:Ref) -> Ref;
pub fn record_keyof(addr:Reference, index:usize) -> usize; pub fn list_at(addr:Ref, index:usize) -> Ref;
pub fn record_indexof(addr:Reference, key:usize) -> usize; pub fn list_clear(addr:Ref);
pub fn list_insert(addr:Ref, index:usize, src:Ref);
pub fn list_push(addr:Ref, src:Ref);
pub fn list_pop(addr:Ref);
pub fn list_set(addr:Ref, index:usize, src:Ref);
pub fn list_remove(addr:Ref, index:usize);
pub fn list_reserve(addr:Ref, capacity:usize);
pub fn schema_length(addr:Reference) -> usize; //pub fn sparse_header_length(addr:Ref) -> usize;
pub fn schema_insert(addr:Reference, index:usize, type_id:usize) -> usize; //pub fn sparse_header_data(addr:Ref, index:usize) -> SparseHeader;
pub fn schema_update(addr:Reference, index:usize, type_id:usize); //pub fn sparse_length(addr:Ref) -> usize;
pub fn schema_get(addr:Reference, index:usize) -> usize; //pub fn sparse_clear(addr:Ref);
pub fn schema_remove(addr:Reference, index:usize); //pub fn sparse_first(addr:Ref) -> usize;
pub fn schema_clear(addr:Reference); //pub fn sparse_next(addr:Ref) -> usize;
//pub fn schema_reorder(addr:Reference, from:usize, to:usize); //pub fn sparse_last(addr:Ref) -> usize;
pub fn schema_map(addr:Reference, key:usize, index:usize); //pub fn sparse_get(addr:Ref, index:usize) -> Ref;
pub fn schema_unmap(addr:Reference, key:usize); //pub fn sparse_at(addr:Ref, index:usize) -> Ref;
pub fn schema_indexof(addr:Reference, key:usize) -> usize; //pub fn sparse_set(addr:Ref, index:usize, source:Ref);
pub fn schema_keyof(addr:Reference, index:usize) -> usize; //pub fn sparse_unset(addr:Ref, index:usize);
pub fn schema_bind(addr:Reference, id:usize) -> usize; //pub fn sparse_indexof(addr:Ref, index:usize) -> usize;
pub fn schema_has(id:usize) -> bool;
//pub fn record_length(addr:Ref) -> usize;
//pub fn record_type(addr:Ref, index:usize) -> usize;
//pub fn record_at(addr:Ref, index:usize) -> Ref;
//pub fn record_update(addr:Ref, index:usize, source:Ref);
//pub fn record_keyof(addr:Ref, index:usize) -> usize;
//pub fn record_indexof(addr:Ref, key:usize) -> usize;
//pub fn schema_length(addr:Ref) -> usize;
//pub fn schema_insert(addr:Ref, index:usize, type_id:usize) -> usize;
//pub fn schema_update(addr:Ref, index:usize, type_id:usize);
//pub fn schema_get(addr:Ref, index:usize) -> usize;
//pub fn schema_remove(addr:Ref, index:usize);
//pub fn schema_clear(addr:Ref);
//pub fn schema_reorder(addr:Ref, from:usize, to:usize);
//pub fn schema_map(addr:Ref, key:usize, index:usize);
//pub fn schema_unmap(addr:Ref, key:usize);
//pub fn schema_indexof(addr:Ref, key:usize) -> usize;
//pub fn schema_keyof(addr:Ref, index:usize) -> usize;
//pub fn schema_bind(addr:Ref, id:usize) -> usize;
//pub fn schema_has(id:usize) -> bool;
} }

View File

@ -0,0 +1,261 @@
uint8_t* allocate(size_t type_id, size_t count)
// Allocates a new block of memory to store n-many instances of type.
//
{
uint8_t* mem = nullptr;
size_t size = type_size(type_id) * count;
if(size > 0) {
mem = reinterpret_cast<uint8_t*>(malloc(size));
if(mem != nullptr) {
memset(mem, 0, size);
}
return mem;
}
return nullptr;
}
extern "C" Reference acquire(size_t type_id)
// Allocates memory for a type and returns a reference.
//
{
Reference addr {0};
addr.address = allocate(type_id, 1);
if(addr.address != nullptr) {
addr.type = type_id;
}
return addr;
}
void drop(Reference addr)
// Recursively deletes and zeros an instantiated type.
//
{
if(addr.address != nullptr) {
switch(type_key(addr.type)) {
case Type::TYPE_VARYING: {
var_set(addr, Reference());
} break;
case Type::TYPE_SEQUENCE: {
sequence_clear(addr);
} break;
case Type::TYPE_LIST: {
list_clear(addr);
} break;
case Type::TYPE_SPARSE: {
sparse_clear(addr);
} break;
case Type::TYPE_RECORD: {
size_t schema_id = type_innerkey(addr.type);
auto binding = DB_SCHEMA.get(schema_id);
if(binding != nullptr) {
for(size_t i = 0; i < binding->data.size(); ++i) {
auto cell = record_cell(addr, i);
drop(cell);
}
}
} break;
case Type::TYPE_SCHEMA: {
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
rawlist_clear(object.data);
rawlist_clear(object.map);
} break;
}
memset(addr.address, 0, type_size(addr.type));
}
}
extern "C" void release(Reference addr)
// Recursively deletes and frees allocated memory.
//
{
if(!refr_is_temporary(addr) && addr.address != nullptr) {
drop(addr);
free(addr.address);
}
}
extern "C" Reference clone(Reference src)
// Create a new object with contents equivalent to a source.
//
{
Reference dst = acquire(src.type);
copy(dst, src);
return dst;
}
extern "C" bool copy(Reference dst, Reference src)
// Deep-copy data from a source to a destination.
//
{
if(src.address != dst.address) {
Reference source = src;
Reference destination = dst;
// dereference varying data
if(type_key(src.type) == Type::TYPE_VARYING) {
source = *reinterpret_cast<Reference*>(src.address);
}
// prepare destination for varying data
if(type_key(dst.type) == Type::TYPE_VARYING) {
auto& dest_ref = *reinterpret_cast<Reference*>(dst.address);
// determine if memory can be reused, otherwise free and reallocate
if(source.type != dest_ref.type) {
if(dest_ref.address != nullptr) {
free(dest_ref.address);
dest_ref.type = Type::TYPE_NULL;
dest_ref.address = nullptr;
}
dest_ref = acquire(source.type);
}
}
// copy data into destination
if(source.type == destination.type) {
drop(destination);
switch(type_key(destination.type)) {
case Type::TYPE_NULL: { } break;
case Type::TYPE_SEQUENCE: {
auto& src_seq = *reinterpret_cast<Type::Sequence*>(source.address);
auto& dst_seq = *reinterpret_cast<Type::Sequence*>(destination.address);
rawlist_clear(dst_seq.data);
rawlist_reserve(dst_seq.data, sizeof(uint8_t), src_seq.data.length);
memcpy(dst_seq.data.data, src_seq.data.data, sizeof(uint8_t) * src_seq.data.length);
dst_seq.data.length = src_seq.data.length;
} break;
case Type::TYPE_ARRAY: {
for(size_t i = 0; i < array_length(source); ++i) {
copy(array_cell(destination, i), array_cell(source, i));
}
} break;
case Type::TYPE_LIST: {
auto& src_list = *reinterpret_cast<Type::List*>(source.address);
auto& dst_list = *reinterpret_cast<Type::List*>(destination.address);
rawlist_reserve(dst_list.data, type_size(type_inner(source.type)), src_list.data.capacity);
dst_list.data.length = src_list.data.length;
for(size_t i = 0; i < src_list.data.length; ++i) {
copy(list_at(destination, i), list_at(source, i));
}
} break;
case Type::TYPE_SPARSE: {
auto& src_list = *reinterpret_cast<Type::Sparse*>(source.address);
auto& dst_list = *reinterpret_cast<Type::Sparse*>(destination.address);
rawlist_reserve(dst_list.header, sizeof(Type::SparseHeader), src_list.header.capacity);
dst_list.header.length = src_list.header.length;
for(size_t i = 0; i < src_list.header.length; ++i) {
Type::SparseHeader& src_header = *reinterpret_cast<Type::SparseHeader*>(rawlist_cell(src_list.header, sizeof(Type::SparseHeader), i));
Type::SparseHeader& dst_header = *reinterpret_cast<Type::SparseHeader*>(rawlist_cell(dst_list.header, sizeof(Type::SparseHeader), i));
dst_header = src_header;
}
rawlist_reserve(dst_list.data, type_size(type_inner(source.type)), src_list.data.capacity);
dst_list.data.length = src_list.data.length;
for(size_t i = 0; i < src_list.data.length; ++i) {
copy(list_at(destination, i), list_at(source, i));
}
} break;
case Type::TYPE_RECORD: {
size_t schema_id = type_innerkey(source.type);
auto binding = DB_SCHEMA.get(schema_id);
if(binding != nullptr) {
for(size_t i = 0; i < binding->data.size(); ++i) {
auto src_cell = record_cell(source, i);
auto dst_cell = record_cell(destination, i);
copy(dst_cell, src_cell);
}
}
} break;
case Type::TYPE_SCHEMA: {
auto& src_schema = *reinterpret_cast<Type::Schema*>(source.address);
auto& dst_schema = *reinterpret_cast<Type::Schema*>(destination.address);
rawlist_clear(dst_schema.data);
rawlist_clear(dst_schema.map);
rawlist_reserve(dst_schema.data, sizeof(size_t), src_schema.data.length);
rawlist_reserve(dst_schema.map, sizeof(size_t), src_schema.map.length);
for(size_t i = 0; i < src_schema.data.length; ++i) {
auto src_cell = reinterpret_cast<size_t*>(rawlist_cell(src_schema.data, sizeof(size_t), i));
auto dst_cell = reinterpret_cast<size_t*>(rawlist_cell(dst_schema.data, sizeof(size_t), i));
if(src_cell != nullptr && dst_cell != nullptr) {
*dst_cell = *src_cell;
}
}
for(size_t i = 0; i < src_schema.map.length; ++i) {
auto src_cell = reinterpret_cast<size_t*>(rawlist_cell(src_schema.map, sizeof(size_t), i));
auto dst_cell = reinterpret_cast<size_t*>(rawlist_cell(dst_schema.map, sizeof(size_t), i));
if(src_cell != nullptr && dst_cell != nullptr) {
*dst_cell = *src_cell;
}
}
} break;
default: {
memcpy(destination.address, source.address, type_size(source.type));
} break;
}
return true;
}
}
return false;
}
extern "C" bool transfer(Reference dst, Reference src)
// Shallow copy data from a source to a destination and delete the original.
//
{
if(src.address != dst.address && src.type != 0 && dst.type != 0) {
Reference source = src;
Reference destination = dst;
// dereference varying data
if(type_key(src.type) == Type::TYPE_VARYING) {
source = *reinterpret_cast<Reference*>(src.address);
}
// prepare destination for varying data
if(type_key(dst.type) == Type::TYPE_VARYING) {
auto& dest_ref = *reinterpret_cast<Reference*>(dst.address);
// determine if memory can be reused, otherwise free and reallocate
if(source.type != dest_ref.type) {
if(dest_ref.address != nullptr) {
free(dest_ref.address);
dest_ref.type = Type::TYPE_NULL;
dest_ref.address = nullptr;
}
dest_ref = acquire(source.type);
}
}
// copy data into destination
if(source.type == destination.type) {
drop(destination);
memcpy(destination.address, source.address, type_size(source.type));
memset(source.address, 0, type_size(source.type));
return true;
}
}
return false;
}

View File

@ -0,0 +1,34 @@
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length)
{
std::string str(reinterpret_cast<const char*>(bytes), length);
if(str.size() > 0) {
return DB_NAME.indexof(str);
}
return 0;
}
extern "C" Str name_keyof(size_t index)
{
Str result {0};
std::string str = DB_NAME.keyof(index);
if(str.length() > 0) {
result.bytes = new uint8_t[str.length()];
}
for(size_t i = 0; i < str.length(); ++i) {
result.bytes[i] = str[i];
}
result.length = str.length();
return result;
}
std::string name_keyof_internal(size_t index)
{
return DB_NAME.keyof(index);
}
extern "C" void name_release(Str data)
{
if(data.bytes != nullptr) {
delete[] data.bytes;
}
}

View File

@ -0,0 +1,34 @@
const size_t MASK_TEMPORARY = (size_t(-1) >> 1) + 1;
Reference refr_resolve(Reference addr)
// Converts a reference into a reference of the contained address.
//
{
Reference result = addr;
if(result.type & ~MASK_TEMPORARY == Type::TYPE_NULL) {
if(result.address != nullptr) {
result = *reinterpret_cast<Reference*>(result.address);
}
else {
result = Reference {0};
}
}
return result;
}
Reference refr_make_temporary(Reference refr)
{
refr.type |= MASK_TEMPORARY;
return refr;
}
bool refr_is_temporary(Reference refr)
{
return (refr.type & MASK_TEMPORARY) != 0;
}
Reference refr_restore(Reference refr)
{
refr.type &= ~MASK_TEMPORARY;
return refr;
}

139
src/runtime/runtime/type.cc Normal file
View File

@ -0,0 +1,139 @@
extern "C" size_t type_outer(size_t type_id, size_t key)
{
type_id &= ~MASK_TEMPORARY;
return DB_TYPE.outer(type_id, key);
}
extern "C" size_t type_inner(size_t type_id)
{
type_id &= ~MASK_TEMPORARY;
return DB_TYPE.inner(type_id);
}
extern "C" size_t type_key(size_t type_id)
{
type_id &= ~MASK_TEMPORARY;
return DB_TYPE.key(type_id);
}
extern "C" size_t type_innerkey(size_t type_id)
{
type_id &= ~MASK_TEMPORARY;
return DB_TYPE.key(DB_TYPE.inner(type_id));
}
extern "C" size_t type_size(size_t type_id)
{
type_id &= ~MASK_TEMPORARY;
if(DB_TYPE.has(type_id)) {
size_t type = DB_TYPE.key(type_id);
switch(type) {
case Type::TYPE_NULL: return 0;
case Type::TYPE_VARYING: return sizeof(Reference);
case Type::TYPE_BOOLEAN: return sizeof(Type::Boolean);
case Type::TYPE_NATURAL: return sizeof(Type::Natural);
case Type::TYPE_INTEGER: return sizeof(Type::Integer);
case Type::TYPE_SIGNIFICANT: return sizeof(Type::Significant);
case Type::TYPE_DECIMAL: return sizeof(Type::Decimal);
case Type::TYPE_BLOCK: return type_innerkey(type_id);
case Type::TYPE_SEQUENCE: return sizeof(Type::Sequence);
case Type::TYPE_ARRAY: {
size_t length = DB_TYPE.inner(type_id);
size_t inner = DB_TYPE.inner(length);
if(inner == Type::TYPE_NULL) {
return sizeof(Reference);
}
else {
return static_cast<size_t>(DB_TYPE.key(length)) * type_size(inner);
}
}
case Type::TYPE_LIST:
case Type::TYPE_SPARSE:
case Type::TYPE_RECORD:
{
size_t innerkey = type_innerkey(type_id);
if(innerkey == Type::TYPE_NULL) {
return sizeof(Reference);
}
else {
switch(type) {
case Type::TYPE_LIST: return sizeof(Type::List);
case Type::TYPE_SPARSE: return sizeof(Type::Sparse);
case Type::TYPE_RECORD: {
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
if(binding != nullptr) {
return binding->size;
}
}
}
}
}
case Type::TYPE_SCHEMA: return sizeof(Type::Schema);
default: return 0;
}
}
return 0;
}
size_t type_alignment(size_t type_id)
{
type_id &= ~MASK_TEMPORARY;
if(DB_TYPE.has(type_id)) {
size_t type = DB_TYPE.key(type_id);
switch(type) {
case Type::TYPE_NULL: return 0;
case Type::TYPE_BOOLEAN: return sizeof(Type::Boolean);
case Type::TYPE_NATURAL: return sizeof(Type::Natural);
case Type::TYPE_INTEGER: return sizeof(Type::Integer);
case Type::TYPE_SIGNIFICANT: return sizeof(Type::Significant);
case Type::TYPE_DECIMAL: return sizeof(Type::Decimal);
case Type::TYPE_BLOCK: return sizeof(uint8_t);
case Type::TYPE_ARRAY: return type_alignment(type_inner(type_id));
case Type::TYPE_VARYING:
case Type::TYPE_SEQUENCE:
case Type::TYPE_LIST:
case Type::TYPE_SPARSE:
case Type::TYPE_SCHEMA:
return sizeof(size_t);
case Type::TYPE_RECORD: {
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
return (binding != nullptr)? binding->alignment : 0;
}
}
}
return 0;
}
extern "C" size_t type_hasinner(size_t type_id)
{
type_id &= ~MASK_TEMPORARY;
return kind_hasinner(type_key(type_id));
}
extern "C" size_t kind_hasinner(size_t kind)
{
switch(kind) {
case Type::TYPE_ARRAY:
return 2;
case Type::TYPE_DECIMAL:
case Type::TYPE_BLOCK:
case Type::TYPE_LIST:
case Type::TYPE_SPARSE:
case Type::TYPE_RECORD:
return 1;
}
return 0;
}
extern "C" size_t type_sanitize(size_t type_id)
{
return type_id & ~MASK_TEMPORARY;
}

View File

@ -1,129 +1,129 @@
#ifndef H_NameTree #ifndef H_NameTree
#define H_NameTree #define H_NameTree
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <string> #include <string>
class NameTree { class NameTree {
public: public:
struct Node { struct Node {
std::string prefix; std::string prefix;
size_t parent; size_t parent;
std::vector<size_t> children; std::vector<size_t> children;
Node(const std::string& prefix, size_t parent); Node(const std::string& prefix, size_t parent);
}; };
NameTree(); NameTree();
~NameTree(); ~NameTree();
size_t indexof(const std::string& value); size_t indexof(const std::string& value);
std::string keyof(size_t) const; std::string keyof(size_t) const;
private: private:
std::vector<Node> m_nodes; std::vector<Node> m_nodes;
}; };
NameTree::Node::Node(const std::string& prefix, size_t parent) NameTree::Node::Node(const std::string& prefix, size_t parent)
:prefix(prefix), parent(parent) { } :prefix(prefix), parent(parent) { }
NameTree::NameTree() NameTree::NameTree()
{ {
m_nodes.push_back(Node("", 0)); m_nodes.push_back(Node("", 0));
} }
NameTree::~NameTree() NameTree::~NameTree()
{ } { }
size_t NameTree::indexof(const std::string& key) size_t NameTree::indexof(const std::string& key)
{ {
size_t current = 0; size_t current = 0;
size_t index = 0; size_t index = 0;
// descend node tree until key is found // descend node tree until key is found
while(index < key.length()) { while(index < key.length()) {
Node& node = m_nodes[current]; Node& node = m_nodes[current];
// search child nodes for first character match // search child nodes for first character match
bool find = false; bool find = false;
for(size_t list_index = 0; list_index < node.children.size(); ++list_index) { for(size_t list_index = 0; list_index < node.children.size(); ++list_index) {
size_t child_index = node.children[list_index]; size_t child_index = node.children[list_index];
Node& child = m_nodes[child_index]; Node& child = m_nodes[child_index];
// match extent of key to child prefix // match extent of key to child prefix
if(child.prefix[0] == key[index]) { if(child.prefix[0] == key[index]) {
index++; index++;
find = true; find = true;
size_t prefix_index = 1; size_t prefix_index = 1;
for(; prefix_index < child.prefix.length() && index < key.length(); prefix_index++ && index++) { for(; prefix_index < child.prefix.length() && index < key.length(); prefix_index++ && index++) {
// check whether prefixes are equal // check whether prefixes are equal
if(child.prefix[prefix_index] != key[index]) { break; } if(child.prefix[prefix_index] != key[index]) { break; }
} }
// if prefix matches, continue to child node // if prefix matches, continue to child node
if(prefix_index == child.prefix.length()) { if(prefix_index == child.prefix.length()) {
current = child_index; current = child_index;
break; break;
} }
// otherwise, branch prefix and create node for key // otherwise, branch prefix and create node for key
else { else {
// create intermediate node, retaining node index of original // create intermediate node, retaining node index of original
m_nodes.push_back(Node(m_nodes[child_index].prefix.substr(0, prefix_index), current)); m_nodes.push_back(Node(m_nodes[child_index].prefix.substr(0, prefix_index), current));
size_t intermediate_index = m_nodes.size() - 1; size_t intermediate_index = m_nodes.size() - 1;
m_nodes[current].children[list_index] = intermediate_index; m_nodes[current].children[list_index] = intermediate_index;
m_nodes[intermediate_index].children.push_back(child_index); m_nodes[intermediate_index].children.push_back(child_index);
// update child node // update child node
m_nodes[child_index].prefix = m_nodes[child_index].prefix.substr(prefix_index); m_nodes[child_index].prefix = m_nodes[child_index].prefix.substr(prefix_index);
m_nodes[child_index].parent = intermediate_index; m_nodes[child_index].parent = intermediate_index;
// create branching node if value is not prefix // create branching node if value is not prefix
if(index != key.length()) { if(index != key.length()) {
m_nodes.push_back(Node(key.substr(index), intermediate_index)); m_nodes.push_back(Node(key.substr(index), intermediate_index));
m_nodes[intermediate_index].children.push_back(m_nodes.size() - 1); m_nodes[intermediate_index].children.push_back(m_nodes.size() - 1);
} }
return m_nodes.size() - 1; return m_nodes.size() - 1;
} }
} }
} }
// if first character is not found, create new child // if first character is not found, create new child
if(!find) { if(!find) {
m_nodes.push_back(Node(key.substr(index), current)); m_nodes.push_back(Node(key.substr(index), current));
m_nodes[current].children.push_back(m_nodes.size() - 1); m_nodes[current].children.push_back(m_nodes.size() - 1);
return m_nodes.size() - 1; return m_nodes.size() - 1;
} }
} }
return current; return current;
} }
std::string NameTree::keyof(size_t id) const std::string NameTree::keyof(size_t id) const
{ {
size_t length = 0; size_t length = 0;
std::string out; std::string out;
if(id < m_nodes.size()) { if(id < m_nodes.size()) {
for(size_t current = id; current != 0;) { for(size_t current = id; current != 0;) {
length += m_nodes[current].prefix.length(); length += m_nodes[current].prefix.length();
current = m_nodes[current].parent; current = m_nodes[current].parent;
} }
out = std::string(length, 0); out = std::string(length, 0);
size_t index = length - 1; size_t index = length - 1;
for(size_t current = id; current != 0;) { for(size_t current = id; current != 0;) {
size_t prefix_length = m_nodes[current].prefix.length() - 1; size_t prefix_length = m_nodes[current].prefix.length() - 1;
for(size_t i = 0; i < m_nodes[current].prefix.length(); ++i) { for(size_t i = 0; i < m_nodes[current].prefix.length(); ++i) {
out[index--] = m_nodes[current].prefix[prefix_length - i]; out[index--] = m_nodes[current].prefix[prefix_length - i];
} }
current = m_nodes[current].parent; current = m_nodes[current].parent;
} }
} }
return out; return out;
} }
#endif #endif

View File

@ -1,81 +1,81 @@
#ifndef H_POOL #ifndef H_POOL
#define H_POOL #define H_POOL
template <typename T> template <typename T>
class Pool { class Pool {
public: public:
Pool() Pool()
{ {
m_next = 0; m_next = 0;
} }
~Pool() ~Pool()
{ } { }
size_t add(const T& data) size_t add(const T& data)
{ {
size_t location = m_next; size_t location = m_next;
if(m_next == m_nodes.size()) { if(m_next == m_nodes.size()) {
m_nodes.push_back(Node()); m_nodes.push_back(Node());
m_next++; m_next++;
m_nodes[location].active = true; m_nodes[location].active = true;
m_nodes[location].data.value = data; m_nodes[location].data.value = data;
} }
else { else {
m_nodes[location].active = true; m_nodes[location].active = true;
m_next = m_nodes[location].data.addr; m_next = m_nodes[location].data.addr;
m_nodes[location].data.value = data; m_nodes[location].data.value = data;
} }
return location + 1; return location + 1;
} }
void remove(size_t id) void remove(size_t id)
{ {
if(has(id)) { if(has(id)) {
size_t index = id - 1; size_t index = id - 1;
m_nodes[index].active = false; m_nodes[index].active = false;
m_nodes[index].data.addr = m_next; m_nodes[index].data.addr = m_next;
m_next = index; m_next = index;
} }
} }
bool has(size_t id) bool has(size_t id)
{ {
if(id > 0 && id <= m_nodes.size()) { if(id > 0 && id <= m_nodes.size()) {
if(m_nodes[id - 1].active) { if(m_nodes[id - 1].active) {
return true; return true;
} }
} }
return false; return false;
} }
bool get(size_t id, T& data) bool get(size_t id, T& data)
{ {
if(has(id)) { if(has(id)) {
data = m_nodes[id - 1].data.value; data = m_nodes[id - 1].data.value;
return true; return true;
} }
return false; return false;
} }
private: private:
struct Node { struct Node {
bool active; bool active;
union { union {
T value; T value;
size_t addr; size_t addr;
} data; } data;
Node() { Node() {
active = false; active = false;
data.addr = 0; data.addr = 0;
} }
}; };
std::vector<Node> m_nodes; std::vector<Node> m_nodes;
size_t m_next; size_t m_next;
}; };
#endif #endif

View File

@ -1,93 +1,99 @@
#include "rawlist.h" #include "rawlist.h"
uint8_t* rawlist_insert(RawList& list, size_t offset, size_t index) uint8_t* rawlist_insert(RawList& list, size_t offset, size_t index)
{ {
if(list.length == list.capacity) { rawlist_reserve(list, offset, (list.capacity == 0) + list.capacity * 2); } if(list.length == list.capacity) { rawlist_reserve(list, offset, (list.capacity == 0) + list.capacity * 2); }
if(index > list.length) { index = list.length; } if(index > list.length) { index = list.length; }
// shift elements back until index is reached // shift elements back until index is reached
for(size_t i = list.length; i > index; --i) { for(size_t i = list.length; i > index; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset); memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
} }
list.length++; list.length++;
return rawlist_cell(list, offset, index); return rawlist_cell(list, offset, index);
} }
void rawlist_remove(RawList& list, size_t offset, size_t index) void rawlist_remove(RawList& list, size_t offset, size_t index)
{ {
if(index > list.length) { index = list.length - 1; } if(index > list.length) { index = list.length - 1; }
// shift elements back until index is reached // shift elements back until index is reached
for(size_t i = index; i < list.length - 1; ++i) { for(size_t i = index; i < list.length - 1; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset); memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
} }
list.length--; list.length--;
memset(rawlist_cell(list, offset, list.length), 0, offset); memset(rawlist_cell(list, offset, list.length), 0, offset);
} }
void rawlist_reorder(RawList& list, size_t offset, size_t from, size_t to) void rawlist_reorder(RawList& list, size_t offset, size_t from, size_t to)
{ {
// ensure there is a trailing cell in which to swap moving data // ensure there is a trailing cell in which to swap moving data
if(list.length == list.capacity) { rawlist_reserve(list, offset, list.capacity * 2); } if(list.length == list.capacity) { rawlist_reserve(list, offset, list.capacity * 2); }
if(from > list.length) { from = list.length - 1; } if(from > list.length) { from = list.length - 1; }
if(to > list.length) { to = list.length - 1; } if(to > list.length) { to = list.length - 1; }
if(from != to) { if(from != to) {
// move data to unused cell // move data to unused cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset); memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
if(from < to) { if(from < to) {
for(size_t i = from; i < to; ++i) { for(size_t i = from; i < to; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset); memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
} }
} }
else if(from > to) { else if(from > to) {
for(size_t i = from; i > to; --i) { for(size_t i = from; i > to; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset); memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
} }
} }
// move data to target cell and clear swap cell // move data to target cell and clear swap cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset); memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
memset(rawlist_cell(list, offset, list.length), 0, offset); memset(rawlist_cell(list, offset, list.length), 0, offset);
} }
} }
inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index) inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index)
{ {
if(index < list.capacity) { if(index < list.capacity) {
return list.data + (offset * index); return list.data + (offset * index);
} }
else { else {
return nullptr; return nullptr;
} }
} }
void rawlist_reserve(RawList& list, size_t offset, size_t capacity) void rawlist_reserve(RawList& list, size_t offset, size_t capacity)
{ {
if(capacity > list.capacity) { if(capacity > list.capacity) {
size_t block_size = offset * capacity; size_t block_size = offset * capacity;
void* old_data = list.data; void* old_data = list.data;
list.data = reinterpret_cast<uint8_t*>(malloc(block_size)); list.data = reinterpret_cast<uint8_t*>(malloc(block_size));
memset(list.data, 0, block_size); memset(list.data, 0, block_size);
if(old_data != nullptr) { if(old_data != nullptr) {
memcpy(list.data, old_data, offset * list.length); memcpy(list.data, old_data, offset * list.length);
free(old_data); free(old_data);
} }
list.capacity = capacity; list.capacity = capacity;
} }
} }
void rawlist_clear(RawList& list) void rawlist_resize(RawList& list, size_t offset, size_t capacity)
{ {
if(list.data != nullptr) { rawlist_reserve(list, offset, capacity);
free(list.data); list.length = list.capacity;
} }
list.capacity = 0;
list.length = 0; void rawlist_clear(RawList& list)
list.data = nullptr; {
} if(list.data != nullptr) {
free(list.data);
}
list.capacity = 0;
list.length = 0;
list.data = nullptr;
}

View File

@ -1,20 +1,21 @@
#ifndef RAWLIST_H #ifndef RAWLIST_H
#define RAWLIST_H #define RAWLIST_H
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
struct RawList { struct RawList {
size_t offset; size_t offset;
size_t capacity; size_t capacity;
size_t length; size_t length;
uint8_t* data; uint8_t* data;
}; };
uint8_t* rawlist_insert(RawList& list, size_t offset, size_t index); uint8_t* rawlist_insert(RawList& list, size_t offset, size_t index);
void rawlist_remove(RawList& list, size_t offset, size_t index); void rawlist_remove(RawList& list, size_t offset, size_t index);
inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index); inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index);
void rawlist_reserve(RawList& list, size_t offset, size_t capacity); void rawlist_reserve(RawList& list, size_t offset, size_t capacity);
void rawlist_clear(RawList& list); void rawlist_resize(RawList& list, size_t offset, size_t capacity);
void rawlist_clear(RawList& list);
#endif
#endif

View File

@ -1,170 +1,170 @@
#ifndef H_SPARSELIST #ifndef H_SPARSELIST
#define H_SPARSELIST #define H_SPARSELIST
#include <vector> #include <vector>
template <typename T> template <typename T>
class SparseList { class SparseList {
public: public:
SparseList() SparseList()
{ } { }
~SparseList() ~SparseList()
{ } { }
size_t length() const size_t length() const
{ {
m_data.size(); m_data.size();
} }
void set(size_t index, const T& value) void set(size_t index, const T& value)
{ {
// find first header with bounds less than index // find first header with bounds less than index
size_t header_index = 0; size_t header_index = 0;
for(; header_index < m_headers.size() && index > (m_headers[header_index].start + m_headers[header_index].length); ++header_index) { } for(; header_index < m_headers.size() && index > (m_headers[header_index].start + m_headers[header_index].length); ++header_index) { }
Header header {0}; Header header {0};
if(header_index == m_headers.size()) { if(header_index == m_headers.size()) {
// append header to end // append header to end
header.start = index; header.start = index;
header.length = 1; header.length = 1;
header.index = m_data.size(); header.index = m_data.size();
m_data.push_back(value); m_data.push_back(value);
m_headers.push_back(header); m_headers.push_back(header);
} else { } else {
if(index < m_headers[header_index].start) { if(index < m_headers[header_index].start) {
// insert header before current // insert header before current
header.start = index; header.start = index;
header.length = 1; header.length = 1;
header.index = m_headers[header_index].index; header.index = m_headers[header_index].index;
m_data.insert(m_data.begin() + m_headers[header_index].index, value); m_data.insert(m_data.begin() + m_headers[header_index].index, value);
m_headers.insert(m_headers.begin() + header_index, header); m_headers.insert(m_headers.begin() + header_index, header);
for(size_t i = header_index + 1; i < m_headers.size(); ++i) { for(size_t i = header_index + 1; i < m_headers.size(); ++i) {
m_headers[i].index++; m_headers[i].index++;
} }
} else { } else {
size_t offset = index - m_headers[header_index].start; size_t offset = index - m_headers[header_index].start;
if(offset < m_headers[header_index].length) { if(offset < m_headers[header_index].length) {
// update existing value // update existing value
m_data[m_headers[header_index].index + offset] = value; m_data[m_headers[header_index].index + offset] = value;
} else { } else {
// append value to current header // append value to current header
m_data.insert(m_data.begin() + (m_headers[header_index].index + offset), value); m_data.insert(m_data.begin() + (m_headers[header_index].index + offset), value);
m_headers[header_index].length += 1; m_headers[header_index].length += 1;
for(size_t i = header_index + 1; i < m_headers.size(); ++i) { for(size_t i = header_index + 1; i < m_headers.size(); ++i) {
m_headers[i].index++; m_headers[i].index++;
} }
} }
} }
// join headers if ranges intersect // join headers if ranges intersect
if(header_index + 1 < m_headers.size()) { if(header_index + 1 < m_headers.size()) {
if(m_headers[header_index + 1].start == m_headers[header_index].start + m_headers[header_index].length) { if(m_headers[header_index + 1].start == m_headers[header_index].start + m_headers[header_index].length) {
m_headers[header_index].length += m_headers[header_index + 1].length; m_headers[header_index].length += m_headers[header_index + 1].length;
m_headers.erase(m_headers.begin() + (header_index + 1)); m_headers.erase(m_headers.begin() + (header_index + 1));
} }
} }
} }
} }
void unset(size_t index) void unset(size_t index)
{ {
// find first header with bounds less than index // find first header with bounds less than index
size_t header_index = 0; size_t header_index = 0;
for(; header_index < m_headers.size() && index > (m_headers[header_index].start + m_headers[header_index].length - 1); ++header_index) { } for(; header_index < m_headers.size() && index > (m_headers[header_index].start + m_headers[header_index].length - 1); ++header_index) { }
Header header {0}; Header header {0};
if(header_index < m_headers.size() && index >= m_headers[header_index].start) { if(header_index < m_headers.size() && index >= m_headers[header_index].start) {
size_t offset = index - m_headers[header_index].start; size_t offset = index - m_headers[header_index].start;
size_t data_index = m_headers[header_index].index + offset; size_t data_index = m_headers[header_index].index + offset;
if(offset == 0) { if(offset == 0) {
// shift start of range // shift start of range
m_headers[header_index].start++; m_headers[header_index].start++;
} else if(offset < m_headers[header_index].length - 1) { } else if(offset < m_headers[header_index].length - 1) {
// split header at index // split header at index
header.start = index + 1; header.start = index + 1;
header.length = m_headers[header_index].length - offset - 1; header.length = m_headers[header_index].length - offset - 1;
header.index = m_headers[header_index].index + offset + 1; header.index = m_headers[header_index].index + offset + 1;
m_headers[header_index].length = offset + 1; m_headers[header_index].length = offset + 1;
m_headers.insert(m_headers.begin() + (header_index + 1), header); m_headers.insert(m_headers.begin() + (header_index + 1), header);
} }
m_data.erase(m_data.begin() + data_index); m_data.erase(m_data.begin() + data_index);
m_headers[header_index].length--; m_headers[header_index].length--;
for(size_t i = header_index + 1; i < m_headers.size(); ++i) { for(size_t i = header_index + 1; i < m_headers.size(); ++i) {
m_headers[i].index--; m_headers[i].index--;
} }
if(m_headers[header_index].length == 0) { if(m_headers[header_index].length == 0) {
m_headers.erase(m_headers.begin() + header_index); m_headers.erase(m_headers.begin() + header_index);
} }
} }
} }
bool has(size_t index) const bool has(size_t index) const
{ {
return find_header(index) != m_headers.size(); return find_header(index) != m_headers.size();
} }
T* get(size_t index) T* get(size_t index)
{ {
size_t header_index = find_header(index); size_t header_index = find_header(index);
if(header_index < m_headers.size()) { if(header_index < m_headers.size()) {
size_t offset = index - m_headers[header_index].start; size_t offset = index - m_headers[header_index].start;
return &m_data[m_headers[header_index].index + offset]; return &m_data[m_headers[header_index].index + offset];
} }
return nullptr; return nullptr;
} }
std::vector<size_t> indices() const std::vector<size_t> indices() const
{ {
std::vector<size_t> result; std::vector<size_t> result;
for(size_t h = 0; h < m_headers.size(); ++h) { for(size_t h = 0; h < m_headers.size(); ++h) {
for(size_t i = 0; i < m_headers[h].length; ++i) { for(size_t i = 0; i < m_headers[h].length; ++i) {
result.push_back(m_headers[h].start + i); result.push_back(m_headers[h].start + i);
} }
} }
return result; return result;
} }
private: private:
struct Header { struct Header {
size_t start; size_t start;
size_t length; size_t length;
size_t index; size_t index;
}; };
size_t find_header(size_t index) const size_t find_header(size_t index) const
{ {
size_t bound_lower = 0; size_t bound_lower = 0;
size_t bound_upper = m_headers.size(); size_t bound_upper = m_headers.size();
size_t header_index = 0; size_t header_index = 0;
while(bound_lower != bound_upper) { while(bound_lower != bound_upper) {
header_index = bound_lower + ((bound_upper - bound_lower) / 2); header_index = bound_lower + ((bound_upper - bound_lower) / 2);
if(index >= m_headers[header_index].start && index < (m_headers[header_index].start + m_headers[header_index].length)) { if(index >= m_headers[header_index].start && index < (m_headers[header_index].start + m_headers[header_index].length)) {
return header_index; return header_index;
} else if(index < m_headers[header_index].start) { } else if(index < m_headers[header_index].start) {
// update upper bound // update upper bound
bound_upper = header_index; bound_upper = header_index;
} else { } else {
// update lower bound // update lower bound
bound_lower = header_index + 1; bound_lower = header_index + 1;
} }
} }
return m_headers.size(); return m_headers.size();
} }
size_t m_root; size_t m_root;
std::vector<Header> m_headers; std::vector<Header> m_headers;
std::vector<T> m_data; std::vector<T> m_data;
}; };
#endif #endif

View File

@ -1,83 +1,96 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include "sparselist.h"
#include "rawlist.h" extern "C" struct Reference {
size_t type;
extern "C" struct Reference { uint8_t* address;
size_t type; };
uint8_t* address;
}; namespace Type {
namespace Type { enum {
TYPE_NULL = 0x00,
namespace Tag { TYPE_BOOLEAN = 0x01,
enum { /* ... */
Null = 0x00, TYPE_BYTE = 0x04,
Varying = 0x01, TYPE_CHAR = 0x05,
Boolean = 0x02, /* ... */
Natural = 0x10, TYPE_NATURAL = 0x08,
Integer = 0x11, TYPE_INTEGER = 0x09,
Decimal = 0x12, TYPE_DECIMAL = 0x0A,
Significant = 0x13, TYPE_SIGNIFICANT = 0x0B,
Block = 0x1e, TYPE_COMPLEX = 0x0C,
Sequence = 0x1f, /* ... */
Array = 0x22, TYPE_RANGE = 0x0F,
List = 0x23, TYPE_BLOCK = 0x10,
Sparse = 0x24, TYPE_SEQUENCE = 0x11,
Record = 0x7e, /* ... */
Schema = 0x7f, TYPE_VARYING = 0x20,
}; TYPE_OPTIONAL = 0x21,
} TYPE_ARRAY = 0x22,
TYPE_LIST = 0x23,
typedef bool Boolean; TYPE_BAG = 0x24,
typedef uint64_t Natural; TYPE_SPARSE = 0x25,
typedef int64_t Integer; TYPE_TRIE = 0x26,
typedef int64_t Decimal; TYPE_MAP = 0x27,
typedef double Significant; TYPE_TREE = 0x28,
TYPE_GRAPH = 0x29,
struct Sequence { /* ... */
RawList data; TYPE_ENUM = 0x7d,
}; TYPE_RECORD = 0x7e,
TYPE_SCHEMA = 0x7f,
struct List { };
RawList data;
}; typedef bool Boolean;
typedef uint64_t Natural;
extern "C" struct SparseHeader { typedef int64_t Integer;
size_t start; typedef int64_t Decimal;
size_t length; typedef double Significant;
size_t index;
}; struct Sequence {
RawList data;
struct Sparse { };
RawList header;
RawList data; struct List {
}; RawList data;
};
struct Schema {
struct Mapping { extern "C" struct SparseHeader {
size_t key; size_t start;
size_t index; size_t length;
}; size_t index;
};
RawList data;
RawList map; struct Sparse {
}; RawList header;
RawList data;
struct SchemaBinding { };
struct Row {
size_t key; struct Schema {
size_t type; struct Mapping {
size_t offset; size_t key;
}; size_t index;
Reference object;
size_t binding; };
size_t alignment;
size_t size; RawList data;
size_t references; RawList map;
};
SparseList<size_t> map;
std::vector<Row> data; struct SchemaBinding {
}; struct Row {
size_t key;
} size_t type;
size_t offset;
};
size_t binding;
size_t alignment;
size_t size;
size_t references;
SparseList<size_t> map;
std::vector<Row> data;
};
}

View File

@ -1,82 +1,82 @@
#ifndef H_TYPETREE #ifndef H_TYPETREE
#define H_TYPETREE #define H_TYPETREE
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
class TypeTree { class TypeTree {
public: public:
struct Node { struct Node {
size_t key; size_t key;
size_t parent; size_t parent;
std::vector<size_t> children; std::vector<size_t> children;
Node(size_t key, size_t parent); Node(size_t key, size_t parent);
}; };
TypeTree(); TypeTree();
~TypeTree(); ~TypeTree();
bool has(size_t id); bool has(size_t id);
size_t outer(size_t id, size_t type); size_t outer(size_t id, size_t type);
size_t key(size_t id); size_t key(size_t id);
size_t inner(size_t id); size_t inner(size_t id);
private: private:
std::vector<Node> m_nodes; std::vector<Node> m_nodes;
}; };
TypeTree::Node::Node(size_t key, size_t parent) :key(key), parent(parent) { } TypeTree::Node::Node(size_t key, size_t parent) :key(key), parent(parent) { }
TypeTree::TypeTree() TypeTree::TypeTree()
{ {
m_nodes.push_back(Node(0, 0)); m_nodes.push_back(Node(0, 0));
} }
TypeTree::~TypeTree() TypeTree::~TypeTree()
{ } { }
bool TypeTree::has(size_t id) bool TypeTree::has(size_t id)
{ {
return id < m_nodes.size(); return id < m_nodes.size();
} }
size_t TypeTree::outer(size_t id, size_t key) size_t TypeTree::outer(size_t id, size_t key)
{ {
size_t find = 0; size_t find = 0;
if(key != 0 && id < m_nodes.size()) { if(key != 0 && id < m_nodes.size()) {
Node& node = m_nodes[id]; Node& node = m_nodes[id];
for(size_t child : node.children) { for(size_t child : node.children) {
if(m_nodes[child].key == key) { if(m_nodes[child].key == key) {
find = child; find = child;
break; break;
} }
} }
if(find == 0) { if(find == 0) {
m_nodes.push_back(Node(key, id)); m_nodes.push_back(Node(key, id));
find = m_nodes.size() - 1; find = m_nodes.size() - 1;
m_nodes[id].children.push_back(find); m_nodes[id].children.push_back(find);
} }
} }
return find; return find;
} }
size_t TypeTree::key(size_t id) size_t TypeTree::key(size_t id)
{ {
if(id > 0 && id < m_nodes.size()) { if(id > 0 && id < m_nodes.size()) {
return m_nodes[id].key; return m_nodes[id].key;
} }
return 0; return 0;
} }
size_t TypeTree::inner(size_t id) size_t TypeTree::inner(size_t id)
{ {
if(id > 0 && id < m_nodes.size()) { if(id > 0 && id < m_nodes.size()) {
return m_nodes[id].parent; return m_nodes[id].parent;
} }
return 0; return 0;
} }
#endif #endif

View File

@ -1,25 +0,0 @@
//pub type Class = usize;
pub const NULL :usize = 0x00;
pub const VARYING :usize = 0x01;
pub const BOOLEAN :usize = 0x02;
pub const NATURAL :usize = 0x10;
pub const INTEGER :usize = 0x11;
pub const DECIMAL :usize = 0x12;
pub const SIGNIFICANT :usize = 0x13;
//pub const COMPLEX :usize = 0x14;
//pub const RANGE :usize = 0x1c;
//pub const CHAR :usize = 0x1d;
pub const BLOCK :usize = 0x1e;
pub const SEQUENCE :usize = 0x1f;
//pub const OPTIONAL :usize = 0x20;
//pub const SET :usize = 0x21;
pub const ARRAY :usize = 0x22;
pub const LIST :usize = 0x23;
pub const SPARSE :usize = 0x24;
//pub const TRIE :usize = 0x25;
//pub const MAP :usize = 0x26;
//pub const TREE :usize = 0x27;
//pub const GRAPH :usize = 0x28;
pub const RECORD :usize = 0x7e;
pub const SCHEMA :usize = 0x7f;

30
src/types.rs Normal file
View File

@ -0,0 +1,30 @@
pub const TYPE_NULL :usize = 0x00;
pub const TYPE_BOOLEAN :usize = 0x01;
/* ... */
pub const TYPE_BYTE :usize = 0x04;
pub const TYPE_CHAR :usize = 0x05;
/* ... */
pub const TYPE_NATURAL :usize = 0x08;
pub const TYPE_INTEGER :usize = 0x09;
pub const TYPE_DECIMAL :usize = 0x0A;
pub const TYPE_SIGNIFICANT :usize = 0x0B;
pub const TYPE_COMPLEX :usize = 0x0C;
/* ... */
pub const TYPE_RANGE :usize = 0x0F;
pub const TYPE_BLOCK :usize = 0x10;
pub const TYPE_SEQUENCE :usize = 0x11;
/* ... */
pub const TYPE_VARYING :usize = 0x20;
pub const TYPE_OPTIONAL :usize = 0x21;
pub const TYPE_ARRAY :usize = 0x22;
pub const TYPE_LIST :usize = 0x23;
pub const TYPE_BAG :usize = 0x24;
pub const TYPE_SPARSE :usize = 0x25;
pub const TYPE_TRIE :usize = 0x26;
pub const TYPE_MAP :usize = 0x27;
pub const TYPE_TREE :usize = 0x28;
pub const TYPE_GRAPH :usize = 0x29;
/* ... */
pub const TYPE_ENUM :usize = 0x7d;
pub const TYPE_RECORD :usize = 0x7e;
pub const TYPE_SCHEMA :usize = 0x7f;

125
src/util/binary.rs Normal file
View File

@ -0,0 +1,125 @@
//mod typetree; pub use typetree::TypeTree;
//mod memory; pub use memory::Memory;
fn pack_count_leading_ones(data:u8) -> usize
{
(data == 0xff) as usize
+ (data >= 0xfe) as usize
+ (data >= 0xfc) as usize
+ (data >= 0xf8) as usize
+ (data >= 0xf0) as usize
+ (data >= 0xe0) as usize
+ (data >= 0xc0) as usize
+ (data >= 0x80) as usize
}
fn pack_encode_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
}
fn pack_data(size:usize, data:u64, sign:bool) -> Vec<u8>
{
let mut data = data;
let mut buffer :Vec<u8> = vec![0];
let mut header_size = size - 1;
let mut buffer_size = size;
if header_size >= 8 {
buffer.append(&mut pack_natural(header_size as u64));
buffer_size += buffer.len() - 1;
header_size = 8;
}
buffer.resize(buffer_size, 0);
buffer[0] = ((0xFF00 >> header_size) & 0xFF) as u8;
for i in 1..buffer_size + 1 {
buffer[buffer_size - i] |= (data & 0xFF) as u8;
data >>= 8;
}
if sign {
match header_size {
8 => { buffer[buffer_size - (size - 1)] |= 0x80; }
7 => { buffer[1] |= 0x80; }
_ => { buffer[0] |= 1 << 6 - header_size; }
}
}
return buffer;
}
pub fn pack_natural(data:u64) -> Vec<u8>
{
pack_data(pack_encode_size(data, false), data, false)
}
pub fn pack_integer(data:i64) -> Vec<u8>
{
let mut udata :u64 = data as u64;
let negative :bool = data < 0;
if negative { udata = !udata; }
pack_data(pack_encode_size(udata, true), udata, negative)
}
fn unpack_data(data:&Vec<u8>, index:&mut usize, signed:bool) -> u64
{
let mut result :u64 = 0;
let mut negative = false;
if *index < data.len() {
let mut pack_size = pack_count_leading_ones(data[*index]);
if pack_size < 7 {
result = (((data[*index] as u64) << pack_size) & 0xFF) >> pack_size;
if signed {
let sign_mask = 1 << (6 - pack_size);
negative = (result & sign_mask) != 0;
result &= !sign_mask;
}
*index += 1;
}
else {
*index += 1;
if pack_size == 8 {
pack_size = unpack_natural(&data, index) as usize;
}
pack_size -= 1;
result = data[*index] as u64;
if signed {
negative = (result & 0x80) != 0;
result &= 0x7F;
}
*index += 1;
}
for _ in 1..pack_size + 1 {
result <<= 8;
result += data[*index] as u64;
*index += 1;
}
if negative { result = !result; }
}
return result;
}
pub fn unpack_natural(data:&Vec<u8>, index:&mut usize) -> u64
{
unpack_data(data, index, false)
}
pub fn unpack_integer(data:&Vec<u8>, index:&mut usize) -> i64
{
unpack_data(data, index, true) as i64
}

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

@ -0,0 +1,137 @@
macro_rules! impl_ops_numeric {
($clas:ty, $param:ty, $repr:ty) => {
impl std::ops::Add<$param> for $clas {
type Output = Self;
fn add(self, other:$param) -> Self { Self::new().with(self.get::<$repr>() + other as $repr) }
}
impl std::ops::Sub<$param> for $clas {
type Output = Self;
fn sub(self, other:$param) -> Self { Self::new().with(self.get::<$repr>() - other as $repr) }
}
impl std::ops::Mul<$param> for $clas {
type Output = Self;
fn mul(self, other:$param) -> Self { Self::new().with(self.get::<$repr>() * other as $repr) }
}
impl std::ops::Div<$param> for $clas {
type Output = Self;
fn div(self, other:$param) -> Self { Self::new().with(self.get::<$repr>() / other as $repr) }
}
impl std::ops::Rem<$param> for $clas {
type Output = Self;
fn rem(self, other:$param) -> Self { Self::new().with(self.get::<$repr>() % other as $repr) }
}
impl std::ops::AddAssign<$param> for $clas {
fn add_assign(&mut self, other:$param) { self.set(self.get::<$repr>() + other as $repr) }
}
impl std::ops::SubAssign<$param> for $clas {
fn sub_assign(&mut self, other:$param) { self.set(self.get::<$repr>() - other as $repr) }
}
impl std::ops::MulAssign<$param> for $clas {
fn mul_assign(&mut self, other:$param) { self.set(self.get::<$repr>() * other as $repr) }
}
impl std::ops::DivAssign<$param> for $clas {
fn div_assign(&mut self, other:$param) { self.set(self.get::<$repr>() / other as $repr) }
}
impl std::ops::RemAssign<$param> for $clas {
fn rem_assign(&mut self, other:$param) { self.set(self.get::<$repr>() % other as $repr) }
}
impl std::cmp::PartialEq<$param> for $clas {
fn eq(&self, other:&$param) -> bool { self.get::<$repr>() == *other as $repr }
fn ne(&self, other:&$param) -> bool { self.get::<$repr>() != *other as $repr }
}
impl std::cmp::PartialOrd<$param> for $clas {
fn partial_cmp(&self, other:&$param) -> Option<std::cmp::Ordering>
{ self.get::<$repr>().partial_cmp(&(*other as $repr)) }
fn lt(&self, other:&$param) -> bool { self.get::<$repr>() < *other as $repr }
fn le(&self, other:&$param) -> bool { self.get::<$repr>() <= *other as $repr }
fn gt(&self, other:&$param) -> bool { self.get::<$repr>() > *other as $repr }
fn ge(&self, other:&$param) -> bool { self.get::<$repr>() >= *other as $repr }
}
impl From<$param> for $clas { fn from(value: $param) -> Self { Self::new().with(value) } }
impl Into<$param> for $clas { fn into(self) -> $param { self.get::<$param>() } }
}
}
macro_rules! impl_ops_numeric_self {
($clas:ty, $repr:ty) => {
impl std::ops::Add<$clas> for $clas {
type Output = Self;
fn add(self, other:$clas) -> Self { Self::new().with(self.get::<$repr>() + other.get::<$repr>()) }
}
impl std::ops::Sub<$clas> for $clas {
type Output = Self;
fn sub(self, other:$clas) -> Self { Self::new().with(self.get::<$repr>() - other.get::<$repr>()) }
}
impl std::ops::Mul<$clas> for $clas {
type Output = Self;
fn mul(self, other:$clas) -> Self { Self::new().with(self.get::<$repr>() * other.get::<$repr>()) }
}
impl std::ops::Div<$clas> for $clas {
type Output = Self;
fn div(self, other:$clas) -> Self { Self::new().with(self.get::<$repr>() / other.get::<$repr>()) }
}
impl std::ops::Rem<$clas> for $clas {
type Output = Self;
fn rem(self, other:$clas) -> Self { Self::new().with(self.get::<$repr>() % other.get::<$repr>()) }
}
impl std::ops::AddAssign<$clas> for $clas {
fn add_assign(&mut self, other:$clas) { self.set(self.get::<$repr>() + other.get::<$repr>()) }
}
impl std::ops::SubAssign<$clas> for $clas {
fn sub_assign(&mut self, other:$clas) { self.set(self.get::<$repr>() - other.get::<$repr>()) }
}
impl std::ops::MulAssign<$clas> for $clas {
fn mul_assign(&mut self, other:$clas) { self.set(self.get::<$repr>() * other.get::<$repr>()) }
}
impl std::ops::DivAssign<$clas> for $clas {
fn div_assign(&mut self, other:$clas) { self.set(self.get::<$repr>() / other.get::<$repr>()) }
}
impl std::ops::RemAssign<$clas> for $clas {
fn rem_assign(&mut self, other:$clas) { self.set(self.get::<$repr>() % other.get::<$repr>()) }
}
impl std::cmp::PartialEq<$clas> for $clas {
fn eq(&self, other:&$clas) -> bool { self.get::<$repr>() == other.get::<$repr>() }
fn ne(&self, other:&$clas) -> bool { self.get::<$repr>() != other.get::<$repr>() }
}
impl std::cmp::PartialOrd<$clas> for $clas {
fn partial_cmp(&self, _other:&$clas) -> Option<std::cmp::Ordering>
{ None }
fn lt(&self, other:&$clas) -> bool { self.get::<$repr>() < other.get::<$repr>() }
fn le(&self, other:&$clas) -> bool { self.get::<$repr>() <= other.get::<$repr>() }
fn gt(&self, other:&$clas) -> bool { self.get::<$repr>() > other.get::<$repr>() }
fn ge(&self, other:&$clas) -> bool { self.get::<$repr>() >= other.get::<$repr>() }
}
}
}
macro_rules! impl_ops_numeric_all {
($clas:ty, $repr:ty) => {
use crate::util::macros::{impl_ops_numeric, impl_ops_numeric_self};
impl_ops_numeric!($clas, i128, $repr);
impl_ops_numeric!($clas, i64, $repr);
impl_ops_numeric!($clas, i32, $repr);
impl_ops_numeric!($clas, i16, $repr);
impl_ops_numeric!($clas, i8, $repr);
impl_ops_numeric!($clas, u128, $repr);
impl_ops_numeric!($clas, u64, $repr);
impl_ops_numeric!($clas, u32, $repr);
impl_ops_numeric!($clas, u16, $repr);
impl_ops_numeric!($clas, u8, $repr);
impl_ops_numeric!($clas, f64, $repr);
impl_ops_numeric!($clas, f32, $repr);
impl_ops_numeric_self!($clas, $repr);
}
}
pub(crate) use impl_ops_numeric;
pub(crate) use impl_ops_numeric_self;
pub(crate) use impl_ops_numeric_all;

View File

@ -1,125 +1,2 @@
//mod typetree; pub use typetree::TypeTree; pub mod binary;
//mod memory; pub use memory::Memory; pub mod macros;
fn pack_count_leading_ones(data:u8) -> usize
{
(data == 0xff) as usize
+ (data >= 0xfe) as usize
+ (data >= 0xfc) as usize
+ (data >= 0xf8) as usize
+ (data >= 0xf0) as usize
+ (data >= 0xe0) as usize
+ (data >= 0xc0) as usize
+ (data >= 0x80) as usize
}
fn pack_encode_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
}
fn pack_data(size:usize, data:u64, sign:bool) -> Vec<u8>
{
let mut data = data;
let mut buffer :Vec<u8> = vec![0];
let mut header_size = size - 1;
let mut buffer_size = size;
if header_size >= 8 {
buffer.append(&mut pack_natural(header_size as u64));
buffer_size += buffer.len() - 1;
header_size = 8;
}
buffer.resize(buffer_size, 0);
buffer[0] = ((0xFF00 >> header_size) & 0xFF) as u8;
for i in 1..buffer_size + 1 {
buffer[buffer_size - i] |= (data & 0xFF) as u8;
data >>= 8;
}
if sign {
match header_size {
8 => { buffer[buffer_size - (size - 1)] |= 0x80; }
7 => { buffer[1] |= 0x80; }
_ => { buffer[0] |= 1 << 6 - header_size; }
}
}
return buffer;
}
pub fn pack_natural(data:u64) -> Vec<u8>
{
pack_data(pack_encode_size(data, false), data, false)
}
pub fn pack_integer(data:i64) -> Vec<u8>
{
let mut udata :u64 = data as u64;
let negative :bool = data < 0;
if negative { udata = !udata; }
pack_data(pack_encode_size(udata, true), udata, negative)
}
fn unpack_data(data:&Vec<u8>, index:&mut usize, signed:bool) -> u64
{
let mut result :u64 = 0;
let mut negative = false;
if *index < data.len() {
let mut pack_size = pack_count_leading_ones(data[*index]);
if pack_size < 7 {
result = (((data[*index] as u64) << pack_size) & 0xFF) >> pack_size;
if signed {
let sign_mask = 1 << (6 - pack_size);
negative = (result & sign_mask) != 0;
result &= !sign_mask;
}
*index += 1;
}
else {
*index += 1;
if pack_size == 8 {
pack_size = unpack_natural(&data, index) as usize;
}
pack_size -= 1;
result = data[*index] as u64;
if signed {
negative = (result & 0x80) != 0;
result &= 0x7F;
}
*index += 1;
}
for _ in 1..pack_size + 1 {
result <<= 8;
result += data[*index] as u64;
*index += 1;
}
if negative { result = !result; }
}
return result;
}
pub fn unpack_natural(data:&Vec<u8>, index:&mut usize) -> u64
{
unpack_data(data, index, false)
}
pub fn unpack_integer(data:&Vec<u8>, index:&mut usize) -> i64
{
unpack_data(data, index, true) as i64
}