Refactor object interfaces.
This commit is contained in:
parent
41331e8e2b
commit
8116af305f
@ -11,6 +11,7 @@ publish = false
|
||||
cc = "1.0"
|
||||
|
||||
[dependencies]
|
||||
num = "0.4.3"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 0
|
||||
|
915
README.md
915
README.md
@ -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.
|
||||
|
||||
---
|
||||
|
@ -1 +0,0 @@
|
||||
fn main() { }
|
34
src/bin/sandbox.rs
Normal file
34
src/bin/sandbox.rs
Normal 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>());
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
83
src/interface-old/array.rs
Normal file
83
src/interface-old/array.rs
Normal 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
107
src/interface-old/block.rs
Normal 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)}; } }
|
||||
}
|
62
src/interface-old/boolean.rs
Normal file
62
src/interface-old/boolean.rs
Normal 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()
|
||||
}
|
||||
}
|
@ -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) } }
|
@ -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()
|
||||
}
|
||||
}
|
58
src/interface-old/integer.rs
Normal file
58
src/interface-old/integer.rs
Normal 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
118
src/interface-old/list.rs
Normal 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
76
src/interface-old/mod.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
57
src/interface-old/natural.rs
Normal file
57
src/interface-old/natural.rs
Normal 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)}; } }
|
||||
}
|
@ -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)}; } }
|
||||
}
|
@ -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)}; } }
|
||||
}
|
115
src/interface-old/sequence.rs
Normal file
115
src/interface-old/sequence.rs
Normal 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)}; } }
|
||||
}
|
@ -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)}; } }
|
||||
}
|
@ -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)}; } }
|
||||
}
|
@ -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(()) }
|
||||
}
|
@ -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)}; } }
|
||||
}
|
@ -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())};
|
||||
}
|
||||
}
|
||||
|
@ -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())};
|
||||
}
|
||||
}
|
||||
|
@ -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())};
|
||||
}
|
||||
}
|
||||
|
@ -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())};
|
||||
}
|
||||
}
|
||||
|
@ -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())};
|
||||
}
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
@ -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
22
src/interface/null.rs
Normal 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() }
|
||||
}
|
@ -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
86
src/interface/var.rs
Normal 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())};
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
struct Parser {
|
||||
|
||||
}
|
||||
|
||||
pub fn compile() -> Result<(),()>
|
||||
{
|
||||
Err(())
|
||||
}
|
11
src/lib.rs
11
src/lib.rs
@ -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
3
src/prelude/error.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub enum SzunError {
|
||||
MismatchedType,
|
||||
}
|
12
src/prelude/mod.rs
Normal file
12
src/prelude/mod.rs
Normal 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
33
src/prelude/reference.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
src/runtime/header/implement/array.h
Normal file
5
src/runtime/header/implement/array.h
Normal 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);
|
11
src/runtime/header/implement/block.h
Normal file
11
src/runtime/header/implement/block.h
Normal 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);
|
2
src/runtime/header/implement/boolean.h
Normal file
2
src/runtime/header/implement/boolean.h
Normal file
@ -0,0 +1,2 @@
|
||||
extern "C" void bool_set(Reference addr, Type::Boolean value);
|
||||
extern "C" Type::Boolean bool_get(Reference addr);
|
2
src/runtime/header/implement/integer.h
Normal file
2
src/runtime/header/implement/integer.h
Normal file
@ -0,0 +1,2 @@
|
||||
extern "C" void integer_set(Reference addr, Type::Integer value);
|
||||
extern "C" Type::Integer integer_get(Reference addr);
|
21
src/runtime/header/implement/list.h
Normal file
21
src/runtime/header/implement/list.h
Normal 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);
|
2
src/runtime/header/implement/natural.h
Normal file
2
src/runtime/header/implement/natural.h
Normal file
@ -0,0 +1,2 @@
|
||||
extern "C" void natural_set(Reference addr, Type::Natural value);
|
||||
extern "C" Type::Natural natural_get(Reference addr);
|
7
src/runtime/header/implement/record.h
Normal file
7
src/runtime/header/implement/record.h
Normal 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);
|
14
src/runtime/header/implement/schema.h
Normal file
14
src/runtime/header/implement/schema.h
Normal 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);
|
5
src/runtime/header/implement/sequence.h
Normal file
5
src/runtime/header/implement/sequence.h
Normal 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);
|
2
src/runtime/header/implement/significant.h
Normal file
2
src/runtime/header/implement/significant.h
Normal file
@ -0,0 +1,2 @@
|
||||
extern "C" void significant_set(Reference addr, Type::Significant value);
|
||||
extern "C" Type::Significant significant_get(Reference addr);
|
12
src/runtime/header/implement/sparse.h
Normal file
12
src/runtime/header/implement/sparse.h
Normal 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);
|
2
src/runtime/header/implement/var.h
Normal file
2
src/runtime/header/implement/var.h
Normal file
@ -0,0 +1,2 @@
|
||||
extern "C" Reference var_get(Reference addr);
|
||||
extern "C" void var_set(Reference addr, Reference source);
|
6
src/runtime/header/memory.h
Normal file
6
src/runtime/header/memory.h
Normal 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);
|
3
src/runtime/header/name.h
Normal file
3
src/runtime/header/name.h
Normal 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);
|
6
src/runtime/header/refr.h
Normal file
6
src/runtime/header/refr.h
Normal 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);
|
9
src/runtime/header/type.h
Normal file
9
src/runtime/header/type.h
Normal 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);
|
49
src/runtime/implement/array.cc
Normal file
49
src/runtime/implement/array.cc
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
134
src/runtime/implement/block.cc
Normal file
134
src/runtime/implement/block.cc
Normal 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;
|
||||
}
|
||||
}*/
|
9
src/runtime/implement/boolean.cc
Normal file
9
src/runtime/implement/boolean.cc
Normal 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));
|
||||
}
|
9
src/runtime/implement/decimal.cc
Normal file
9
src/runtime/implement/decimal.cc
Normal 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));
|
||||
}
|
9
src/runtime/implement/integer.cc
Normal file
9
src/runtime/implement/integer.cc
Normal 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));
|
||||
}
|
152
src/runtime/implement/list.cc
Normal file
152
src/runtime/implement/list.cc
Normal 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);
|
||||
}
|
9
src/runtime/implement/natural.cc
Normal file
9
src/runtime/implement/natural.cc
Normal 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));
|
||||
}
|
79
src/runtime/implement/record.cc
Normal file
79
src/runtime/implement/record.cc
Normal 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;
|
||||
}
|
216
src/runtime/implement/schema.cc
Normal file
216
src/runtime/implement/schema.cc
Normal 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);
|
||||
}
|
44
src/runtime/implement/sequence.cc
Normal file
44
src/runtime/implement/sequence.cc
Normal 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);
|
||||
}
|
9
src/runtime/implement/significant.cc
Normal file
9
src/runtime/implement/significant.cc
Normal 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));
|
||||
}
|
288
src/runtime/implement/sparse.cc
Normal file
288
src/runtime/implement/sparse.cc
Normal 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;
|
||||
}
|
29
src/runtime/implement/var.cc
Normal file
29
src/runtime/implement/var.cc
Normal 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);
|
||||
}
|
1470
src/runtime/lib.cc
1470
src/runtime/lib.cc
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
261
src/runtime/runtime/memory.cc
Normal file
261
src/runtime/runtime/memory.cc
Normal 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;
|
||||
}
|
34
src/runtime/runtime/namespace.cc
Normal file
34
src/runtime/runtime/namespace.cc
Normal 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;
|
||||
}
|
||||
}
|
34
src/runtime/runtime/refr.cc
Normal file
34
src/runtime/runtime/refr.cc
Normal 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
139
src/runtime/runtime/type.cc
Normal 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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
@ -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
|
25
src/tag.rs
25
src/tag.rs
@ -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
30
src/types.rs
Normal 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
125
src/util/binary.rs
Normal 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
137
src/util/macros.rs
Normal 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;
|
127
src/util/mod.rs
127
src/util/mod.rs
@ -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;
|
||||
|
Reference in New Issue
Block a user