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"
[dependencies]
num = "0.4.3"
[profile.dev]
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
## 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
|Type|Code|Parameters|Description|
|---|---|---|---|
|Undefined|x00|--|Data is not defined|
|Varying|x01|--|Stores any data type|
|Boolean|x02|--|True or false|
|Natural|x10|--|Non-negative integers|
|Integer|x11|--|Positive and negative whole numbers|
|Decimal|x12|mantissa|Fixed-maginutide rational numbers|
|Significant|x13|--|Variable-magnitude rational numbers|
|Block|x1e|size|Constant-sized series of bytes|
|Sequence|x1f|--|Variable-sized series of bytes|
|Array|x22|size, type|Constant-sized, indexed collection|
|List|x23|type|Variable-sized, indexed collection|
|Sparse|x24|type|Variable-sized, discontinuously indexed collection|
|Record|x7e|schema|Instance of a schema|
|Schema|x7f|--|Definition of abstract structure|
|Status|Type|Code|Parameters|Description|
|---|---|---|---|---|
|x|None|x00|--|No data|
|x|Boolean|x01|--|True or false|
|x|Byte|x04|--|0-255|
|x|Char|x05|--|Unicode codepoint|
|x|Natural|x08|--|Non-negative integers|
|x|Integer|x09|--|Positive and negative whole numbers|
|x|Decimal|x0A|mantissa|Fixed-maginutide rational numbers|
|x|Significant|x0B|--|Variable-magnitude rational numbers|
|x|Complex|x0C|--|Complex number|
|x|Range|x0F|min, max|...|
|x|Block|x10|size|Constant-sized series of bytes|
|x|Sequence|x11|--|Variable-sized series of bytes|
|x|Varying|x20|--|Any data|
|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 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
`acquire(type) -> Reference`
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
## Binary Encoding
Encoding converts data between runtime memory and binary serialization.
`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.
---
## 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,
type_key, type_innerkey, SparseHeader,
},
tag,
types,
Object,
util::*,
};
@ -43,20 +43,20 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
{
let mut result = Vec::<u8>::new();
match unsafe {type_key(addr.class)} {
tag::VARYING => {
types::VARYING => {
let data = Varying::try_from(addr).unwrap();
result.append(&mut encode(data.get()));
}
tag::BOOLEAN => {
types::BOOLEAN => {
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));
}
tag::INTEGER => {
types::INTEGER => {
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 raw = Decimal::try_from(addr).unwrap().get_raw();
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_natural(fract));
}
tag::SIGNIFICANT => {
types::SIGNIFICANT => {
result.append(&mut vec![0]);
}
tag::BLOCK => {
types::BLOCK => {
result.append(&mut Block::try_from(addr).unwrap().get());
}
tag::SEQUENCE => {
types::SEQUENCE => {
let data = Sequence::try_from(addr).unwrap();
result.append(&mut util::pack_natural(data.size() as u64));
result.append(&mut data.get_raw());
}
tag::ARRAY => {
types::ARRAY => {
let data = Array::try_from(addr).unwrap();
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)));
}
else {
@ -86,11 +86,11 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
}
}
}
tag::LIST => {
types::LIST => {
let data = List::try_from(addr).unwrap();
result.append(&mut util::pack_natural(data.length() as u64));
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)));
}
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 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() {
if unsafe {type_innerkey(addr.class)} == tag::VARYING {
if unsafe {type_innerkey(addr.class)} == types::VARYING {
result.append(&mut encode(data.at(i)));
}
else {
@ -121,10 +121,10 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
}
}
}
tag::RECORD => {
types::RECORD => {
let data = Record::try_from(addr).unwrap();
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)));
}
else {
@ -132,7 +132,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
}
}
}
tag::SCHEMA => {
types::SCHEMA => {
let data = Schema::try_from(addr).unwrap();
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,()>
{
match unsafe {type_key(type_id)} {
tag::VARYING => {
types::VARYING => {
return match decode(data, index) {
Ok(value) => {
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(()),
}
}
tag::BOOLEAN => {
types::BOOLEAN => {
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))));
}
tag::INTEGER => {
types::INTEGER => {
return Ok(Object::Integer(Integer::with(unpack_integer(data, index))));
}
tag::DECIMAL => {
types::DECIMAL => {
let mantissa = unsafe {type_innerkey(type_id)};
let whole = unpack_integer(data, index);
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)));
}
tag::SIGNIFICANT => {
types::SIGNIFICANT => {
return Err(())
}
tag::BLOCK => {
types::BLOCK => {
let size = unsafe {type_innerkey(type_id)};
let mut bytes = Vec::<u8>::with_capacity(size);
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)));
}
tag::SEQUENCE => {
types::SEQUENCE => {
let size = unpack_natural(data, index) as usize;
let mut bytes = Vec::<u8>::with_capacity(size);
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)));
}
tag::ARRAY => {
types::ARRAY => {
let length = unsafe {type_innerkey(type_id)};
let inner = unsafe {type_inner(type_inner(type_id))};
let mut result = Array::new(length, inner);
for i in 0..length {
match if unsafe {type_key(inner)} == tag::VARYING {
match if unsafe {type_key(inner)} == types::VARYING {
decode(data, index)
} else {
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));
}
tag::LIST => {
types::LIST => {
let inner = unsafe {type_inner(type_id)};
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);
for _ in 0..length {
match if unsafe {type_key(inner)} == tag::VARYING {
match if unsafe {type_key(inner)} == types::VARYING {
decode(data, index)
} else {
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));
}
tag::SPARSE => {
types::SPARSE => {
let inner = unsafe {type_inner(type_id)};
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 i in 0..header.length {
match if unsafe {type_key(inner)} == tag::VARYING {
match if unsafe {type_key(inner)} == types::VARYING {
decode(data, index)
} else {
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));
}
tag::RECORD => {
types::RECORD => {
return match Record::new(unsafe {type_innerkey(type_id)}) {
Ok(mut value) => {
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(()),
}
}
tag::SCHEMA => {
types::SCHEMA => {
let mut result = Schema::new();
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::runtime;
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 null() -> usize { 0 }
pub fn varying() -> usize { unsafe { runtime::type_outer(0, tag::VARYING) } }
pub fn boolean() -> usize { unsafe { runtime::type_outer(0, tag::BOOLEAN) } }
pub fn natural() -> usize { unsafe { runtime::type_outer(0, tag::NATURAL) } }
pub fn integer() -> usize { unsafe { runtime::type_outer(0, tag::INTEGER) } }
pub fn significant() -> usize { unsafe { runtime::type_outer(0, tag::SIGNIFICANT) } }
pub fn decimal(mantissa:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(0, mantissa);
runtime::type_outer(inner_node, tag::DECIMAL)
}
}
pub fn block(size:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(0, size);
runtime::type_outer(inner_node, tag::BLOCK)
}
}
pub fn sequence() -> usize { unsafe { runtime::type_outer(0, tag::SEQUENCE) } }
pub fn array(size:usize, type_id:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(type_id, size);
runtime::type_outer(inner_node, tag::ARRAY)
}
}
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 record(schema_id:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(0, schema_id);
runtime::type_outer(inner_node, tag::RECORD)
}
}
pub fn schema() -> usize { unsafe { runtime::type_outer(0, tag::SCHEMA) } }
use crate::tag;
use crate::runtime;
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 null() -> usize { 0 }
pub fn varying() -> usize { unsafe { runtime::type_outer(0, tag::VARYING) } }
pub fn boolean() -> usize { unsafe { runtime::type_outer(0, tag::BOOLEAN) } }
pub fn natural() -> usize { unsafe { runtime::type_outer(0, tag::NATURAL) } }
pub fn integer() -> usize { unsafe { runtime::type_outer(0, tag::INTEGER) } }
pub fn significant() -> usize { unsafe { runtime::type_outer(0, tag::SIGNIFICANT) } }
pub fn decimal(mantissa:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(0, mantissa);
runtime::type_outer(inner_node, tag::DECIMAL)
}
}
pub fn block(size:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(0, size);
runtime::type_outer(inner_node, tag::BLOCK)
}
}
pub fn sequence() -> usize { unsafe { runtime::type_outer(0, tag::SEQUENCE) } }
pub fn array(size:usize, type_id:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(type_id, size);
runtime::type_outer(inner_node, tag::ARRAY)
}
}
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 record(schema_id:usize) -> usize {
unsafe {
let inner_node = runtime::type_outer(0, schema_id);
runtime::type_outer(inner_node, tag::RECORD)
}
}
pub fn schema() -> usize { unsafe { runtime::type_outer(0, tag::SCHEMA) } }

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,83 +1,78 @@
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)}; } }
}
use std::marker::PhantomData;
use crate::{
prelude::*, types,
runtime::{
acquire, release,
type_outer, type_key,
clone,
array_set, array_at,
},
};
pub struct Array<const N :usize, T: SzunType> {
address:Ref,
_data:PhantomData<T>,
}
impl<const N :usize, T: SzunType> Array<N,T> {
pub fn new() -> Self
{
Self { address:unsafe {acquire(Self::type_id())}, _data:PhantomData }
}
pub fn set<D: SzunType>(&mut self, index:usize, data:&D)
{
if self.compatible(data) {
unsafe {array_set(self.address.clone(), index, data.__to_ref())};
}
}
pub fn get(&self, index:usize) -> T
{
let refr = unsafe {array_at(self.address.clone(), index)};
if refr.is_some() {
T::__from_ref(refr)
} else { panic!("array index out of bounds"); }
}
pub fn len(&self) -> usize
{
N
}
}
impl<const N :usize, T: SzunType> SzunType for Array<N,T> {
fn type_id() -> usize {
let inner = unsafe {type_outer(T::type_id(), N)};
unsafe {type_outer(inner, types::TYPE_ARRAY)}
}
fn to_ref(self) -> Ref { self.address.clone() }
fn compatible<R: SzunType>(&self, _:&R) -> bool {
R::type_id() == T::type_id() || unsafe {type_key(T::type_id())} == types::TYPE_VARYING
}
fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(refr:Ref) -> Self { Self { address:refr, _data:PhantomData } }
}
impl<const N :usize, T: SzunType> Clone for Array<N,T> {
fn clone(&self) -> Self {
Self { address:unsafe {clone(self.address.clone())}, _data:PhantomData }
}
}
impl<const N :usize, T: SzunType> TryFrom<Ref> for Array<N,T> {
type Error = SzunError;
fn try_from(addr: Ref) -> Result<Self, Self::Error> {
if addr.class == Self::type_id() {
Ok(Self { address:addr, _data:PhantomData })
} else { Err(SzunError::MismatchedType) }
}
}
impl<const N :usize, T: SzunType> Into<Ref> for Array<N,T> { fn into(self) -> Ref { self.address.clone() } }
impl<const N :usize, T: SzunType> Drop for Array<N,T> {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

View File

@ -1,107 +1,116 @@
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::{
prelude::*, types,
runtime::{
acquire, release,
type_outer,
clone,
block_set, block_get,
},
};
use crate::tag;
use super::block;
pub struct Block {
managed:bool,
addr:Reference,
pub struct Block<const N :usize> {
address:Ref,
}
impl Block {
pub fn new(size:usize) -> Self
impl<const N :usize> Block<N> {
pub fn new() -> Self
{
Self {
managed:true,
addr:unsafe {acquire(block(size))},
Self { address:unsafe {acquire(Self::type_id())} }
}
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);
obj.set(data);
return obj;
let mut data = [0; N];
for i in 0..data.len() {
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))};
for index in 0..usize::min(data.len(), length) {
unsafe {block_set(self.addr, index, data[index])};
unsafe {block_get(self.address.clone(), 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)}
}
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)};
}
let mut value :u128 = 0;
for i in 0..N {
value <<= 8;
value |= unsafe {block_get(self.address.clone(), i)} as u128;
}
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
{
unsafe {block_get_integer(self.addr)}
}
impl<const N :usize> SzunType for Block<N> {
fn type_id() -> usize {
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
{
unsafe {block_get_field(self.addr, index, length)}
fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
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 = ();
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<const N :usize> TryFrom<Ref> for Block<N> {
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 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)}; } }
impl<const N :usize> Into<Ref> for Block<N> { fn into(self) -> Ref { self.address.clone() } }
impl<const N :usize> Drop for Block<N> {
fn drop(&mut self) {
unsafe {release(self.address.clone())};
}
}

View File

@ -1,62 +1,82 @@
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()
}
}
use crate::{
prelude::*, types,
runtime::{
acquire, release,
type_outer,
clone,
bool_set, bool_get,
},
};
pub struct Boolean {
address:Ref,
}
impl Boolean {
pub fn new() -> Self
{
Self { address:unsafe {acquire(Self::type_id())} }
}
pub fn with(mut self, data:bool) -> Self
{
self.set(data);
self
}
pub fn set(&mut self, data:bool)
{
unsafe {bool_set(self.address.clone(), data)}
}
pub fn get(&self) -> bool
{
unsafe {bool_get(self.address.clone())}
}
}
impl SzunType for Boolean {
fn type_id() -> usize { unsafe {type_outer(0, types::TYPE_BOOLEAN)} }
fn to_ref(self) -> Ref { self.address.clone() }
fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
}
pub fn boolean(data:bool) -> Boolean
{
Boolean::from(data)
}
impl Clone for Boolean {
fn clone(&self) -> Self {
Self { address:unsafe {clone(self.address.clone())} }
}
}
impl std::ops::Not for Boolean {
type Output = Self;
fn not(self) -> Self::Output {
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::{
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)}; } }
}
use crate::{
prelude::*, types,
runtime::{
acquire, release,
type_outer,
clone,
integer_set, integer_get,
},
};
pub struct Integer {
address:Ref,
}
impl Integer {
pub fn new() -> Self {
Self { address:unsafe {acquire(Self::type_id())} }
}
pub fn with<T: num::Num + num::NumCast>(mut self, data:T) -> Self
{
self.set(data);
self
}
pub fn set<T: num::Num + num::NumCast>(&mut self, data:T) {
match num::NumCast::from(data) {
Some(data) => unsafe {integer_set(self.address.clone(), data)}
None => { }
}
}
pub fn get<T: num::Num + num::NumCast>(&self) -> T {
num::NumCast::from(unsafe {integer_get(self.address.clone())}).unwrap()
}
}
impl SzunType for Integer {
fn type_id() -> usize { unsafe {type_outer(0, types::TYPE_INTEGER)} }
fn to_ref(self) -> Ref { self.address.clone() }
fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
}
pub fn integer<T: num::Num + num::NumCast>(data:T) -> Integer
{
Integer::new().with(data)
}
impl Clone for Integer {
fn clone(&self) -> Self {
Self { address:unsafe {clone(self.address.clone())} }
}
}
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::{
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)}; } }
}
use std::marker::PhantomData;
use crate::{
prelude::*, runtime::{
acquire, release, clone,
type_outer, type_key,
list_reserve, list_clear,
list_insert, list_push, list_pop,
list_at, list_back, list_set,
list_length, list_capacity,
}, types
};
pub struct List<T: SzunType> {
address:Ref,
_data:PhantomData<T>,
}
impl<T: SzunType> List<T> {
pub fn new() -> Self {
Self {
address:unsafe {acquire(Self::type_id())},
_data:PhantomData
}
}
pub fn insert<D: SzunType>(&mut self, index:usize, data:&D)
{
if index <= self.len() && self.compatible(data) {
unsafe {list_insert(self.address.clone(), index, data.__to_ref())};
}
}
pub fn push<D: SzunType>(&mut self, data:&D)
{
if self.compatible(data) {
unsafe {list_push(self.address.clone(), data.__to_ref())};
}
}
pub fn pop(&mut self) -> Option<T>
{
let refr = unsafe {list_back(self.address.clone())};
if refr.is_some() {
let result = Some(T::__from_ref(unsafe {clone(refr)}));
unsafe {list_pop(self.address.clone())};
result
} else { None }
}
pub fn set<D: SzunType>(&mut self, index:usize, data:&D)
{
if self.compatible(data) {
unsafe {list_set(self.address.clone(), index, data.__to_ref())};
}
}
pub fn clear(&mut self)
{
unsafe {list_clear(self.address.clone())};
}
pub fn reserve(&mut self, length:usize)
{
unsafe {list_reserve(self.address.clone(), length)};
}
pub fn get(&mut self, index:usize) -> T
{
let refr = unsafe {list_at(self.address.clone(), index)};
if refr.is_some() {
T::__from_ref(refr)
} else { panic!("index out of bounds: {} / {}", index, self.len()) }
}
pub fn try_get(&mut self, index:usize) -> Option<T>
{
let refr = unsafe {list_at(self.address.clone(), index)};
if refr.is_some() {
Some(T::__from_ref(refr))
} else { None }
}
pub fn len(&self) -> usize
{
unsafe {list_length(self.address.clone())}
}
pub fn capacity(&self) -> usize
{
unsafe {list_capacity(self.address.clone())}
}
}
impl<T: SzunType> SzunType for List<T> {
fn type_id() -> usize {
unsafe {type_outer(T::type_id(), types::TYPE_LIST)}
}
fn to_ref(self) -> Ref { self.address.clone() }
fn compatible<R: SzunType>(&self, _:&R) -> bool {
R::type_id() == T::type_id() || unsafe {type_key(T::type_id())} == types::TYPE_VARYING
}
fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(address:Ref) -> Self { Self { address:address, _data:PhantomData } }
}
impl<T: SzunType> Clone for List<T> {
fn clone(&self) -> Self {
Self::new()
}
}
impl<T: SzunType> TryFrom<Ref> for List<T> {
type Error = SzunError;
fn try_from(addr: Ref) -> Result<Self, Self::Error> {
if addr.class == Self::type_id() {
Ok(Self { address:addr, _data:PhantomData })
} 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};
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(),
}
}
}
mod null; pub use null::*;
mod boolean; pub use boolean::*;
mod natural; pub use natural::*;
mod integer; pub use integer::*;
mod block; pub use block::*;
mod sequence; pub use sequence::*;
mod var; pub use var::*;
mod array; pub use array::*;
mod list; pub use list::*;

View File

@ -1,57 +1,71 @@
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)}; } }
}
use crate::{
prelude::*, types,
runtime::{
acquire, release,
type_outer,
clone,
natural_set, natural_get,
},
};
pub struct Natural {
address:Ref,
}
impl Natural {
pub fn new() -> Self {
Self { address:unsafe {acquire(Self::type_id())} }
}
pub fn with<T: num::Num + num::NumCast>(mut self, data:T) -> Self {
self.set(data);
self
}
pub fn set<T: num::Num + num::NumCast>(&mut self, data:T) {
match num::NumCast::from(data) {
Some(data) => unsafe {natural_set(self.address.clone(), data)}
None => { }
}
}
pub fn get<T: num::Num + num::NumCast>(&self) -> T {
num::NumCast::from(unsafe {natural_get(self.address.clone())}).unwrap()
}
}
impl SzunType for Natural {
fn type_id() -> usize { unsafe {type_outer(0, types::TYPE_NATURAL)} }
fn to_ref(self) -> Ref { self.address.clone() }
fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
}
pub fn natural<T: num::Num + num::NumCast>(data:T) -> Natural
{
Natural::new().with(data)
}
impl Clone for Natural {
fn clone(&self) -> Self {
Self { address:unsafe {clone(self.address.clone())} }
}
}
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::{
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)}; } }
}
use crate::{
prelude::*, types,
runtime::{
acquire, release,
type_outer,
clone,
sequence_resize,
sequence_set, sequence_get,
sequence_length,
},
};
pub struct Sequence {
pub(crate) address:Ref,
}
impl Sequence {
pub fn new() -> Self
{
Self { address:unsafe {acquire(Self::type_id())} }
}
pub fn with(mut self, data:Vec<u8>) -> Self
{
self.set(data);
self
}
pub fn with_str(mut self, data:&str) -> Self
{
self.set_str(data);
self
}
pub fn set(&mut self, data:Vec<u8>)
{
unsafe {sequence_resize(self.address.clone(), data.len())};
for i in 0..data.len() {
unsafe {sequence_set(self.address.clone(), i, data[i])};
}
}
pub fn set_str(&mut self, data:&str)
{
let data = data.as_bytes();
unsafe {sequence_resize(self.address.clone(), data.len())};
for i in 0..data.len() {
unsafe {sequence_set(self.address.clone(), i, data[i])};
}
}
pub fn get(&self) -> Vec<u8>
{
let mut data = Vec::new();
for i in 0..data.len() {
data.push(unsafe {sequence_get(self.address.clone(), i)});
}
data
}
pub fn get_str(&self) -> String
{
let mut data = Vec::new();
for i in 0..self.len() {
data.push(unsafe {sequence_get(self.address.clone(), i)});
}
String::from_utf8(data).unwrap()
}
pub fn set_at(&mut self, index:usize, data:u8)
{
unsafe {sequence_set(self.address.clone(), index, data)}
}
pub fn get_at(&self, index:usize) -> u8
{
unsafe {sequence_get(self.address.clone(), index)}
}
pub fn len(&self) -> usize
{
unsafe {sequence_length(self.address.clone())}
}
}
impl SzunType for Sequence {
fn type_id() -> usize {
unsafe {type_outer(0, types::TYPE_SEQUENCE)}
}
fn to_ref(self) -> Ref { self.address.clone() }
fn compatible<T: SzunType>(&self, _:&T) -> bool { false }
fn __to_ref(&self) -> Ref { self.address.clone() }
fn __from_ref(refr:Ref) -> Self { Self { address:refr } }
}
pub fn sequence(data:Vec<u8>) -> Sequence
{
Sequence::new().with(data)
}
pub fn string(data:&str) -> Sequence
{
Sequence::new().with_str(data)
}
impl Clone for Sequence {
fn clone(&self) -> Self {
Self { address:unsafe {clone(self.address.clone())} }
}
}
impl TryFrom<Ref> for Sequence {
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 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 runtime;
mod interface; pub use interface::*;
mod encoding; pub use encoding::*;
//mod encoding; pub use encoding::*;
#[cfg(test)]
mod tests;
//#[cfg(test)] 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 <cstring>
#include "type.h"
#include "typetree.h"
#include "nametree.h"
#include "sparselist.h"
#include "rawlist.h"
#include "pool.h"
#include "util/rawlist/rawlist.h"
#include "util/sparselist.h"
#include "util/pool.h"
#include "util/type.h"
#include "util/typetree.h"
#include "util/nametree.h"
extern "C" struct Str {
uint8_t* bytes;
@ -21,128 +21,24 @@ extern Pool<Reference> DB_REFERENCE;
extern "C" void test();
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);
#include "header/refr.h"
#include "header/type.h"
#include "header/name.h"
#include "header/memory.h"
#include "header/implement/boolean.h"
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);
#include "header/implement/natural.h"
#include "header/implement/integer.h"
#include "header/implement/significant.h"
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" bool copy(Reference dst, Reference src);
extern "C" bool transfer(Reference dst, Reference src);
#include "header/implement/block.h"
#include "header/implement/sequence.h"
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 //
extern "C" Reference varying_get(Reference addr);
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);
#include "header/implement/record.h"
#include "header/implement/schema.h"

View File

@ -1,30 +1,6 @@
pub mod util;
#[repr(C)]
#[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
}
}
use crate::prelude::Ref;
#[repr(C)]
#[derive(Clone, Copy)]
@ -44,11 +20,12 @@ pub struct SparseHeader {
extern "C" {
pub fn test();
pub fn acquire(type_id:usize) -> Reference;
pub fn release(addr:Reference);
pub fn acquire(type_id:usize) -> Ref;
pub fn release(addr:Ref);
pub fn copy(dst:Reference, src:Reference) -> bool;
pub fn transfer(dst:Reference, src:Reference) -> bool;
pub fn clone(src:Ref) -> Ref;
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_inner(type_id:usize) -> usize;
@ -56,104 +33,89 @@ extern "C" {
pub fn type_innerkey(type_id:usize) -> usize;
pub fn kind_hasinner(kind: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_keyof(index:usize) -> Str;
pub fn name_release(data:Str);
pub fn varying_get(addr:Reference) -> Reference;
pub fn varying_set(addr:Reference, source:Reference);
pub fn varying_clear(addr:Reference);
pub fn bool_set(addr:Reference, data:bool);
pub fn bool_get(addr:Reference) -> bool;
pub fn bool_set(addr:Ref, data:bool);
pub fn bool_get(addr:Ref) -> bool;
pub fn natural_set(addr:Reference, data:u64);
pub fn natural_get(addr:Reference) -> u64;
pub fn natural_set(addr:Ref, data:u64);
pub fn natural_get(addr:Ref) -> u64;
pub fn integer_set(addr:Reference, data:i64);
pub fn integer_get(addr:Reference) -> i64;
pub fn integer_set(addr:Ref, data:i64);
pub fn integer_get(addr:Ref) -> i64;
pub fn decimal_set(addr:Reference, data:i64);
pub fn decimal_get(addr:Reference) -> i64;
//pub fn decimal_set(addr:Ref, data:i64);
//pub fn decimal_get(addr:Ref) -> i64;
pub fn significant_set(addr:Reference, data:f64);
pub fn significant_get(addr:Reference) -> f64;
//pub fn significant_set(addr:Ref, data:f64);
//pub fn significant_get(addr:Ref) -> f64;
pub fn block_length(addr:Reference) -> usize;
pub fn block_get(addr:Reference, index:usize) -> 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 block_get(addr:Ref, index:usize) -> u8;
pub fn block_set(addr:Ref, index:usize, data:u8);
pub fn sequence_capacity(addr:Reference) -> usize;
pub fn sequence_length(addr:Reference) -> usize;
pub fn sequence_get(addr:Reference, index:usize) -> u8;
pub fn sequence_clear(addr:Reference);
pub fn sequence_set(addr:Reference, index:usize, value:u8);
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 sequence_length(addr:Ref) -> usize;
pub fn sequence_get(addr:Ref, index:usize) -> u8;
pub fn sequence_clear(addr:Ref);
pub fn sequence_set(addr:Ref, index:usize, value:u8);
pub fn sequence_resize(addr:Ref, capacity:usize);
pub fn list_capacity(addr:Reference) -> usize;
pub fn list_length(addr:Reference) -> usize;
//pub fn list_first(addr:Reference) -> Reference;
//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 var_get(addr:Ref) -> Ref;
pub fn var_set(addr:Ref, source:Ref);
pub fn var_clear(addr:Ref);
pub fn sparse_header_length(addr:Reference) -> usize;
pub fn sparse_header_data(addr:Reference, index:usize) -> SparseHeader;
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 array_at(addr:Ref, index:usize) -> Ref;
pub fn array_set(addr:Ref, index:usize, source:Ref);
pub fn record_length(addr:Reference) -> usize;
pub fn record_type(addr:Reference, index:usize) -> usize;
pub fn record_at(addr:Reference, index:usize) -> Reference;
pub fn record_update(addr:Reference, index:usize, source:Reference);
pub fn record_keyof(addr:Reference, index:usize) -> usize;
pub fn record_indexof(addr:Reference, key:usize) -> usize;
pub fn list_capacity(addr:Ref) -> usize;
pub fn list_length(addr:Ref) -> usize;
pub fn list_front(addr:Ref) -> Ref;
pub fn list_back(addr:Ref) -> Ref;
pub fn list_at(addr:Ref, index:usize) -> Ref;
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 schema_insert(addr:Reference, index:usize, type_id:usize) -> usize;
pub fn schema_update(addr:Reference, index:usize, type_id:usize);
pub fn schema_get(addr:Reference, index:usize) -> usize;
pub fn schema_remove(addr:Reference, index:usize);
pub fn schema_clear(addr:Reference);
//pub fn schema_reorder(addr:Reference, from:usize, to:usize);
pub fn schema_map(addr:Reference, key:usize, index:usize);
pub fn schema_unmap(addr:Reference, key:usize);
pub fn schema_indexof(addr:Reference, key:usize) -> usize;
pub fn schema_keyof(addr:Reference, index:usize) -> usize;
pub fn schema_bind(addr:Reference, id:usize) -> usize;
pub fn schema_has(id:usize) -> bool;
//pub fn sparse_header_length(addr:Ref) -> usize;
//pub fn sparse_header_data(addr:Ref, index:usize) -> SparseHeader;
//pub fn sparse_length(addr:Ref) -> usize;
//pub fn sparse_clear(addr:Ref);
//pub fn sparse_first(addr:Ref) -> usize;
//pub fn sparse_next(addr:Ref) -> usize;
//pub fn sparse_last(addr:Ref) -> usize;
//pub fn sparse_get(addr:Ref, index:usize) -> Ref;
//pub fn sparse_at(addr:Ref, index:usize) -> Ref;
//pub fn sparse_set(addr:Ref, index:usize, source:Ref);
//pub fn sparse_unset(addr:Ref, index:usize);
//pub fn sparse_indexof(addr:Ref, index:usize) -> usize;
//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
#define H_NameTree
#include <cstdint>
#include <vector>
#include <string>
class NameTree {
public:
struct Node {
std::string prefix;
size_t parent;
std::vector<size_t> children;
Node(const std::string& prefix, size_t parent);
};
NameTree();
~NameTree();
size_t indexof(const std::string& value);
std::string keyof(size_t) const;
private:
std::vector<Node> m_nodes;
};
NameTree::Node::Node(const std::string& prefix, size_t parent)
:prefix(prefix), parent(parent) { }
NameTree::NameTree()
{
m_nodes.push_back(Node("", 0));
}
NameTree::~NameTree()
{ }
size_t NameTree::indexof(const std::string& key)
{
size_t current = 0;
size_t index = 0;
// descend node tree until key is found
while(index < key.length()) {
Node& node = m_nodes[current];
// search child nodes for first character match
bool find = false;
for(size_t list_index = 0; list_index < node.children.size(); ++list_index) {
size_t child_index = node.children[list_index];
Node& child = m_nodes[child_index];
// match extent of key to child prefix
if(child.prefix[0] == key[index]) {
index++;
find = true;
size_t prefix_index = 1;
for(; prefix_index < child.prefix.length() && index < key.length(); prefix_index++ && index++) {
// check whether prefixes are equal
if(child.prefix[prefix_index] != key[index]) { break; }
}
// if prefix matches, continue to child node
if(prefix_index == child.prefix.length()) {
current = child_index;
break;
}
// otherwise, branch prefix and create node for key
else {
// create intermediate node, retaining node index of original
m_nodes.push_back(Node(m_nodes[child_index].prefix.substr(0, prefix_index), current));
size_t intermediate_index = m_nodes.size() - 1;
m_nodes[current].children[list_index] = intermediate_index;
m_nodes[intermediate_index].children.push_back(child_index);
// update child node
m_nodes[child_index].prefix = m_nodes[child_index].prefix.substr(prefix_index);
m_nodes[child_index].parent = intermediate_index;
// create branching node if value is not prefix
if(index != key.length()) {
m_nodes.push_back(Node(key.substr(index), intermediate_index));
m_nodes[intermediate_index].children.push_back(m_nodes.size() - 1);
}
return m_nodes.size() - 1;
}
}
}
// if first character is not found, create new child
if(!find) {
m_nodes.push_back(Node(key.substr(index), current));
m_nodes[current].children.push_back(m_nodes.size() - 1);
return m_nodes.size() - 1;
}
}
return current;
}
std::string NameTree::keyof(size_t id) const
{
size_t length = 0;
std::string out;
if(id < m_nodes.size()) {
for(size_t current = id; current != 0;) {
length += m_nodes[current].prefix.length();
current = m_nodes[current].parent;
}
out = std::string(length, 0);
size_t index = length - 1;
for(size_t current = id; current != 0;) {
size_t prefix_length = m_nodes[current].prefix.length() - 1;
for(size_t i = 0; i < m_nodes[current].prefix.length(); ++i) {
out[index--] = m_nodes[current].prefix[prefix_length - i];
}
current = m_nodes[current].parent;
}
}
return out;
}
#endif
#ifndef H_NameTree
#define H_NameTree
#include <cstdint>
#include <vector>
#include <string>
class NameTree {
public:
struct Node {
std::string prefix;
size_t parent;
std::vector<size_t> children;
Node(const std::string& prefix, size_t parent);
};
NameTree();
~NameTree();
size_t indexof(const std::string& value);
std::string keyof(size_t) const;
private:
std::vector<Node> m_nodes;
};
NameTree::Node::Node(const std::string& prefix, size_t parent)
:prefix(prefix), parent(parent) { }
NameTree::NameTree()
{
m_nodes.push_back(Node("", 0));
}
NameTree::~NameTree()
{ }
size_t NameTree::indexof(const std::string& key)
{
size_t current = 0;
size_t index = 0;
// descend node tree until key is found
while(index < key.length()) {
Node& node = m_nodes[current];
// search child nodes for first character match
bool find = false;
for(size_t list_index = 0; list_index < node.children.size(); ++list_index) {
size_t child_index = node.children[list_index];
Node& child = m_nodes[child_index];
// match extent of key to child prefix
if(child.prefix[0] == key[index]) {
index++;
find = true;
size_t prefix_index = 1;
for(; prefix_index < child.prefix.length() && index < key.length(); prefix_index++ && index++) {
// check whether prefixes are equal
if(child.prefix[prefix_index] != key[index]) { break; }
}
// if prefix matches, continue to child node
if(prefix_index == child.prefix.length()) {
current = child_index;
break;
}
// otherwise, branch prefix and create node for key
else {
// create intermediate node, retaining node index of original
m_nodes.push_back(Node(m_nodes[child_index].prefix.substr(0, prefix_index), current));
size_t intermediate_index = m_nodes.size() - 1;
m_nodes[current].children[list_index] = intermediate_index;
m_nodes[intermediate_index].children.push_back(child_index);
// update child node
m_nodes[child_index].prefix = m_nodes[child_index].prefix.substr(prefix_index);
m_nodes[child_index].parent = intermediate_index;
// create branching node if value is not prefix
if(index != key.length()) {
m_nodes.push_back(Node(key.substr(index), intermediate_index));
m_nodes[intermediate_index].children.push_back(m_nodes.size() - 1);
}
return m_nodes.size() - 1;
}
}
}
// if first character is not found, create new child
if(!find) {
m_nodes.push_back(Node(key.substr(index), current));
m_nodes[current].children.push_back(m_nodes.size() - 1);
return m_nodes.size() - 1;
}
}
return current;
}
std::string NameTree::keyof(size_t id) const
{
size_t length = 0;
std::string out;
if(id < m_nodes.size()) {
for(size_t current = id; current != 0;) {
length += m_nodes[current].prefix.length();
current = m_nodes[current].parent;
}
out = std::string(length, 0);
size_t index = length - 1;
for(size_t current = id; current != 0;) {
size_t prefix_length = m_nodes[current].prefix.length() - 1;
for(size_t i = 0; i < m_nodes[current].prefix.length(); ++i) {
out[index--] = m_nodes[current].prefix[prefix_length - i];
}
current = m_nodes[current].parent;
}
}
return out;
}
#endif

View File

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

View File

@ -1,93 +1,99 @@
#include "rawlist.h"
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(index > list.length) { index = list.length; }
// shift elements back until index is reached
for(size_t i = list.length; i > index; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
}
list.length++;
return rawlist_cell(list, offset, index);
}
void rawlist_remove(RawList& list, size_t offset, size_t index)
{
if(index > list.length) { index = list.length - 1; }
// shift elements back until index is reached
for(size_t i = index; i < list.length - 1; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
}
list.length--;
memset(rawlist_cell(list, offset, list.length), 0, offset);
}
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
if(list.length == list.capacity) { rawlist_reserve(list, offset, list.capacity * 2); }
if(from > list.length) { from = list.length - 1; }
if(to > list.length) { to = list.length - 1; }
if(from != to) {
// move data to unused cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
if(from < to) {
for(size_t i = from; i < to; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
}
}
else if(from > to) {
for(size_t i = from; i > to; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
}
}
// move data to target cell and clear swap cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
memset(rawlist_cell(list, offset, list.length), 0, offset);
}
}
inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index)
{
if(index < list.capacity) {
return list.data + (offset * index);
}
else {
return nullptr;
}
}
void rawlist_reserve(RawList& list, size_t offset, size_t capacity)
{
if(capacity > list.capacity) {
size_t block_size = offset * capacity;
void* old_data = list.data;
list.data = reinterpret_cast<uint8_t*>(malloc(block_size));
memset(list.data, 0, block_size);
if(old_data != nullptr) {
memcpy(list.data, old_data, offset * list.length);
free(old_data);
}
list.capacity = capacity;
}
}
void rawlist_clear(RawList& list)
{
if(list.data != nullptr) {
free(list.data);
}
list.capacity = 0;
list.length = 0;
list.data = nullptr;
}
#include "rawlist.h"
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(index > list.length) { index = list.length; }
// shift elements back until index is reached
for(size_t i = list.length; i > index; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
}
list.length++;
return rawlist_cell(list, offset, index);
}
void rawlist_remove(RawList& list, size_t offset, size_t index)
{
if(index > list.length) { index = list.length - 1; }
// shift elements back until index is reached
for(size_t i = index; i < list.length - 1; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
}
list.length--;
memset(rawlist_cell(list, offset, list.length), 0, offset);
}
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
if(list.length == list.capacity) { rawlist_reserve(list, offset, list.capacity * 2); }
if(from > list.length) { from = list.length - 1; }
if(to > list.length) { to = list.length - 1; }
if(from != to) {
// move data to unused cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
if(from < to) {
for(size_t i = from; i < to; ++i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i + 1), offset);
}
}
else if(from > to) {
for(size_t i = from; i > to; --i) {
memcpy(rawlist_cell(list, offset, i), rawlist_cell(list, offset, i - 1), offset);
}
}
// move data to target cell and clear swap cell
memcpy(rawlist_cell(list, offset, from), rawlist_cell(list, offset, list.length), offset);
memset(rawlist_cell(list, offset, list.length), 0, offset);
}
}
inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index)
{
if(index < list.capacity) {
return list.data + (offset * index);
}
else {
return nullptr;
}
}
void rawlist_reserve(RawList& list, size_t offset, size_t capacity)
{
if(capacity > list.capacity) {
size_t block_size = offset * capacity;
void* old_data = list.data;
list.data = reinterpret_cast<uint8_t*>(malloc(block_size));
memset(list.data, 0, block_size);
if(old_data != nullptr) {
memcpy(list.data, old_data, offset * list.length);
free(old_data);
}
list.capacity = capacity;
}
}
void rawlist_resize(RawList& list, size_t offset, size_t capacity)
{
rawlist_reserve(list, offset, capacity);
list.length = list.capacity;
}
void rawlist_clear(RawList& list)
{
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
#define RAWLIST_H
#include <cstdlib>
#include <cstring>
struct RawList {
size_t offset;
size_t capacity;
size_t length;
uint8_t* data;
};
uint8_t* rawlist_insert(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);
void rawlist_reserve(RawList& list, size_t offset, size_t capacity);
void rawlist_clear(RawList& list);
#endif
#ifndef RAWLIST_H
#define RAWLIST_H
#include <cstdlib>
#include <cstring>
struct RawList {
size_t offset;
size_t capacity;
size_t length;
uint8_t* data;
};
uint8_t* rawlist_insert(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);
void rawlist_reserve(RawList& list, size_t offset, size_t capacity);
void rawlist_resize(RawList& list, size_t offset, size_t capacity);
void rawlist_clear(RawList& list);
#endif

View File

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

View File

@ -1,83 +1,96 @@
#include <cstdint>
#include <vector>
#include "sparselist.h"
#include "rawlist.h"
extern "C" struct Reference {
size_t type;
uint8_t* address;
};
namespace Type {
namespace Tag {
enum {
Null = 0x00,
Varying = 0x01,
Boolean = 0x02,
Natural = 0x10,
Integer = 0x11,
Decimal = 0x12,
Significant = 0x13,
Block = 0x1e,
Sequence = 0x1f,
Array = 0x22,
List = 0x23,
Sparse = 0x24,
Record = 0x7e,
Schema = 0x7f,
};
}
typedef bool Boolean;
typedef uint64_t Natural;
typedef int64_t Integer;
typedef int64_t Decimal;
typedef double Significant;
struct Sequence {
RawList data;
};
struct List {
RawList data;
};
extern "C" struct SparseHeader {
size_t start;
size_t length;
size_t index;
};
struct Sparse {
RawList header;
RawList data;
};
struct Schema {
struct Mapping {
size_t key;
size_t index;
};
RawList data;
RawList map;
};
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;
};
}
#include <cstdint>
#include <vector>
extern "C" struct Reference {
size_t type;
uint8_t* address;
};
namespace Type {
enum {
TYPE_NULL = 0x00,
TYPE_BOOLEAN = 0x01,
/* ... */
TYPE_BYTE = 0x04,
TYPE_CHAR = 0x05,
/* ... */
TYPE_NATURAL = 0x08,
TYPE_INTEGER = 0x09,
TYPE_DECIMAL = 0x0A,
TYPE_SIGNIFICANT = 0x0B,
TYPE_COMPLEX = 0x0C,
/* ... */
TYPE_RANGE = 0x0F,
TYPE_BLOCK = 0x10,
TYPE_SEQUENCE = 0x11,
/* ... */
TYPE_VARYING = 0x20,
TYPE_OPTIONAL = 0x21,
TYPE_ARRAY = 0x22,
TYPE_LIST = 0x23,
TYPE_BAG = 0x24,
TYPE_SPARSE = 0x25,
TYPE_TRIE = 0x26,
TYPE_MAP = 0x27,
TYPE_TREE = 0x28,
TYPE_GRAPH = 0x29,
/* ... */
TYPE_ENUM = 0x7d,
TYPE_RECORD = 0x7e,
TYPE_SCHEMA = 0x7f,
};
typedef bool Boolean;
typedef uint64_t Natural;
typedef int64_t Integer;
typedef int64_t Decimal;
typedef double Significant;
struct Sequence {
RawList data;
};
struct List {
RawList data;
};
extern "C" struct SparseHeader {
size_t start;
size_t length;
size_t index;
};
struct Sparse {
RawList header;
RawList data;
};
struct Schema {
struct Mapping {
size_t key;
size_t index;
Reference object;
};
RawList data;
RawList map;
};
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
#define H_TYPETREE
#include <cstdint>
#include <vector>
class TypeTree {
public:
struct Node {
size_t key;
size_t parent;
std::vector<size_t> children;
Node(size_t key, size_t parent);
};
TypeTree();
~TypeTree();
bool has(size_t id);
size_t outer(size_t id, size_t type);
size_t key(size_t id);
size_t inner(size_t id);
private:
std::vector<Node> m_nodes;
};
TypeTree::Node::Node(size_t key, size_t parent) :key(key), parent(parent) { }
TypeTree::TypeTree()
{
m_nodes.push_back(Node(0, 0));
}
TypeTree::~TypeTree()
{ }
bool TypeTree::has(size_t id)
{
return id < m_nodes.size();
}
size_t TypeTree::outer(size_t id, size_t key)
{
size_t find = 0;
if(key != 0 && id < m_nodes.size()) {
Node& node = m_nodes[id];
for(size_t child : node.children) {
if(m_nodes[child].key == key) {
find = child;
break;
}
}
if(find == 0) {
m_nodes.push_back(Node(key, id));
find = m_nodes.size() - 1;
m_nodes[id].children.push_back(find);
}
}
return find;
}
size_t TypeTree::key(size_t id)
{
if(id > 0 && id < m_nodes.size()) {
return m_nodes[id].key;
}
return 0;
}
size_t TypeTree::inner(size_t id)
{
if(id > 0 && id < m_nodes.size()) {
return m_nodes[id].parent;
}
return 0;
}
#endif
#ifndef H_TYPETREE
#define H_TYPETREE
#include <cstdint>
#include <vector>
class TypeTree {
public:
struct Node {
size_t key;
size_t parent;
std::vector<size_t> children;
Node(size_t key, size_t parent);
};
TypeTree();
~TypeTree();
bool has(size_t id);
size_t outer(size_t id, size_t type);
size_t key(size_t id);
size_t inner(size_t id);
private:
std::vector<Node> m_nodes;
};
TypeTree::Node::Node(size_t key, size_t parent) :key(key), parent(parent) { }
TypeTree::TypeTree()
{
m_nodes.push_back(Node(0, 0));
}
TypeTree::~TypeTree()
{ }
bool TypeTree::has(size_t id)
{
return id < m_nodes.size();
}
size_t TypeTree::outer(size_t id, size_t key)
{
size_t find = 0;
if(key != 0 && id < m_nodes.size()) {
Node& node = m_nodes[id];
for(size_t child : node.children) {
if(m_nodes[child].key == key) {
find = child;
break;
}
}
if(find == 0) {
m_nodes.push_back(Node(key, id));
find = m_nodes.size() - 1;
m_nodes[id].children.push_back(find);
}
}
return find;
}
size_t TypeTree::key(size_t id)
{
if(id > 0 && id < m_nodes.size()) {
return m_nodes[id].key;
}
return 0;
}
size_t TypeTree::inner(size_t id)
{
if(id > 0 && id < m_nodes.size()) {
return m_nodes[id].parent;
}
return 0;
}
#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;
//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
}
pub mod binary;
pub mod macros;