Add Sparse, update README, remove risky methods, fix bugs.
This commit is contained in:
parent
5d82c7659b
commit
21b95b936c
73
README.md
73
README.md
@ -234,19 +234,6 @@ match Integer::from(list.at(0)) {
|
|||||||
```
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
`with(value) -> Self`
|
|
||||||
|
|
||||||
```
|
|
||||||
let b = Boolean::with(true);
|
|
||||||
```
|
|
||||||
---
|
|
||||||
|
|
||||||
`detatch()`
|
|
||||||
|
|
||||||
Prevents an allocated object from being dropped when the interface goes out of scope.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
`*Dereference -> Reference`
|
`*Dereference -> Reference`
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -372,7 +359,7 @@ Stores a constant-magnitude number with whole and decimal components.
|
|||||||
## Significant
|
## Significant
|
||||||
Stores a fixed-precision, variable-magnitude number.
|
Stores a fixed-precision, variable-magnitude number.
|
||||||
|
|
||||||
> Encode not implemented.
|
> Encode/decode not implemented.
|
||||||
|
|
||||||
`get() -> f64`
|
`get() -> f64`
|
||||||
|
|
||||||
@ -486,7 +473,7 @@ Reallocates the sequeunce to have capacity not less than the specified size.
|
|||||||
|
|
||||||
|
|
||||||
## Array
|
## Array
|
||||||
Constant-sized, ordered collection of items.
|
Constant-sized, indexed collection of items.
|
||||||
|
|
||||||
`new(length:usize, type_id:usize) -> Array`
|
`new(length:usize, type_id:usize) -> Array`
|
||||||
|
|
||||||
@ -520,7 +507,7 @@ Returns the type identifier of the contents.
|
|||||||
|
|
||||||
|
|
||||||
## List
|
## List
|
||||||
Variable-sized, ordered collection of items.
|
Variable-sized, indexed collection of items.
|
||||||
|
|
||||||
`new(type_id:usize) -> List`
|
`new(type_id:usize) -> List`
|
||||||
|
|
||||||
@ -577,9 +564,63 @@ Removes all elements from the list.
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Sparse
|
||||||
|
List of discontinuous indicies.
|
||||||
|
|
||||||
|
`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.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
## Schema
|
## Schema
|
||||||
Definition of an abstract structure composed of named items.
|
Definition of an abstract structure composed of named items.
|
||||||
|
|
||||||
|
> Encode/decode not implemented.
|
||||||
|
|
||||||
`with(members:Vec<(&str, usize)>) -> Schema`
|
`with(members:Vec<(&str, usize)>) -> Schema`
|
||||||
|
|
||||||
Produces a schema with the provided member assignments.
|
Produces a schema with the provided member assignments.
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
runtime,
|
||||||
runtime::{
|
runtime::{
|
||||||
Reference,
|
Reference,
|
||||||
kind_hasinner, type_hasinner, type_inner, type_outer,
|
kind_hasinner, type_hasinner, type_inner, type_outer,
|
||||||
type_key, type_innerkey,
|
type_key, type_innerkey, SparseHeader,
|
||||||
},
|
},
|
||||||
tag,
|
tag,
|
||||||
Type,
|
Type,
|
||||||
@ -84,6 +85,29 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tag::SPARSE => {
|
||||||
|
let data = crate::Sparse::from(addr).unwrap();
|
||||||
|
|
||||||
|
let header_length = unsafe {runtime::sparse_header_length(addr)};
|
||||||
|
|
||||||
|
result.append(&mut util::pack_natural(header_length as u64));
|
||||||
|
|
||||||
|
for i in 0..header_length {
|
||||||
|
let header = unsafe {runtime::sparse_header_data(addr, i)};
|
||||||
|
result.append(&mut util::pack_natural(header.start as u64));
|
||||||
|
result.append(&mut util::pack_natural(header.length as u64));
|
||||||
|
result.append(&mut util::pack_natural(header.index as u64));
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..data.length() {
|
||||||
|
if unsafe {type_innerkey(addr.class)} == tag::VARYING {
|
||||||
|
result.append(&mut encode(data.at(i)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.append(&mut encode_data(data.at(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
tag::RECORD => {
|
tag::RECORD => {
|
||||||
let data = Record::from(addr).unwrap();
|
let data = Record::from(addr).unwrap();
|
||||||
for i in 0..data.length() {
|
for i in 0..data.length() {
|
||||||
@ -171,6 +195,76 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Typ
|
|||||||
}
|
}
|
||||||
return Ok(Type::Sequence(Sequence::with_raw(bytes)));
|
return Ok(Type::Sequence(Sequence::with_raw(bytes)));
|
||||||
}
|
}
|
||||||
|
tag::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 {
|
||||||
|
decode(data, index)
|
||||||
|
} else {
|
||||||
|
decode_data(data, inner, index)
|
||||||
|
} {
|
||||||
|
Ok(data) => { result.set(i, data.get()); }
|
||||||
|
Err(_) => { return Err(()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Type::Array(result));
|
||||||
|
}
|
||||||
|
tag::LIST => {
|
||||||
|
let inner = unsafe {type_inner(type_id)};
|
||||||
|
let length = util::unpack_natural(data, index) as usize;
|
||||||
|
|
||||||
|
let mut result = List::new(inner);
|
||||||
|
result.reserve(length);
|
||||||
|
|
||||||
|
for _ in 0..length {
|
||||||
|
match if unsafe {type_key(inner)} == tag::VARYING {
|
||||||
|
decode(data, index)
|
||||||
|
} else {
|
||||||
|
decode_data(data, inner, index)
|
||||||
|
} {
|
||||||
|
Ok(data) => { result.append(data.get()); }
|
||||||
|
Err(_) => { return Err(()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Type::List(result));
|
||||||
|
}
|
||||||
|
tag::SPARSE => {
|
||||||
|
let inner = unsafe {type_inner(type_id)};
|
||||||
|
let mut result = crate::Sparse::new(inner);
|
||||||
|
|
||||||
|
let header_length = util::unpack_natural(data, index) as usize;
|
||||||
|
let mut headers = Vec::<SparseHeader>::with_capacity(header_length);
|
||||||
|
|
||||||
|
for _ in 0..header_length {
|
||||||
|
headers.push(runtime::SparseHeader {
|
||||||
|
start:util::unpack_natural(data, index) as usize,
|
||||||
|
length:util::unpack_natural(data, index) as usize,
|
||||||
|
index:util::unpack_natural(data, index) as usize,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for header in headers {
|
||||||
|
for i in 0..header.length {
|
||||||
|
match if unsafe {type_key(inner)} == tag::VARYING {
|
||||||
|
decode(data, index)
|
||||||
|
} else {
|
||||||
|
decode_data(data, inner, index)
|
||||||
|
} {
|
||||||
|
Ok(data) => {
|
||||||
|
result.set(header.start + i, data.get());
|
||||||
|
}
|
||||||
|
Err(_) => { return Err(()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Type::Sparse(result));
|
||||||
|
}
|
||||||
tag::RECORD => {
|
tag::RECORD => {
|
||||||
return match Record::new(unsafe {type_innerkey(type_id)}) {
|
return match Record::new(unsafe {type_innerkey(type_id)}) {
|
||||||
Ok(mut value) => {
|
Ok(mut value) => {
|
||||||
|
@ -53,17 +53,6 @@ impl Array {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn length(&self) -> usize
|
pub fn length(&self) -> usize
|
||||||
{
|
{
|
||||||
unsafe {array_length(self.addr)}
|
unsafe {array_length(self.addr)}
|
||||||
|
@ -38,17 +38,6 @@ impl Block {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> usize
|
pub fn size(&self) -> usize
|
||||||
{
|
{
|
||||||
unsafe {block_length(self.addr)}
|
unsafe {block_length(self.addr)}
|
||||||
|
@ -37,17 +37,6 @@ impl Boolean {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, value:bool)
|
pub fn set(&mut self, value:bool)
|
||||||
{
|
{
|
||||||
unsafe { bool_set(self.addr, value) };
|
unsafe { bool_set(self.addr, value) };
|
||||||
|
@ -28,6 +28,7 @@ pub fn array(size:usize, type_id:usize) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn list(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::LIST) } }
|
pub fn list(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::LIST) } }
|
||||||
|
pub fn sparse(type_id:usize) -> usize { unsafe { runtime::type_outer(type_id, tag::SPARSE) } }
|
||||||
|
|
||||||
pub fn record(schema_id:usize) -> usize {
|
pub fn record(schema_id:usize) -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -37,17 +37,6 @@ impl Integer {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, value:i64)
|
pub fn set(&mut self, value:i64)
|
||||||
{
|
{
|
||||||
unsafe { integer_set(self.addr, value) };
|
unsafe { integer_set(self.addr, value) };
|
||||||
|
@ -44,17 +44,6 @@ impl List {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn capacity(&self) -> usize
|
pub fn capacity(&self) -> usize
|
||||||
{
|
{
|
||||||
unsafe {list_capacity(self.addr)}
|
unsafe {list_capacity(self.addr)}
|
||||||
|
@ -8,11 +8,12 @@ mod varying; pub use varying::Varying;
|
|||||||
mod boolean; pub use boolean::Boolean;
|
mod boolean; pub use boolean::Boolean;
|
||||||
mod natural; pub use natural::Natural;
|
mod natural; pub use natural::Natural;
|
||||||
mod integer; pub use integer::Integer;
|
mod integer; pub use integer::Integer;
|
||||||
mod signfiicant; pub use signfiicant::Significant;
|
mod signficant; pub use signficant::Significant;
|
||||||
mod block; pub use block::Block;
|
mod block; pub use block::Block;
|
||||||
mod sequence; pub use sequence::Sequence;
|
mod sequence; pub use sequence::Sequence;
|
||||||
mod array; pub use array::Array;
|
mod array; pub use array::Array;
|
||||||
mod list; pub use list::List;
|
mod list; pub use list::List;
|
||||||
|
mod sparse; pub use sparse::Sparse;
|
||||||
mod schema; pub use schema::Schema;
|
mod schema; pub use schema::Schema;
|
||||||
mod record; pub use record::Record;
|
mod record; pub use record::Record;
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ pub enum Type {
|
|||||||
Sequence(Sequence),
|
Sequence(Sequence),
|
||||||
Array(Array),
|
Array(Array),
|
||||||
List(List),
|
List(List),
|
||||||
|
Sparse(Sparse),
|
||||||
Record(Record),
|
Record(Record),
|
||||||
Schema(Schema),
|
Schema(Schema),
|
||||||
}
|
}
|
||||||
@ -42,6 +44,7 @@ impl Type {
|
|||||||
tag::SEQUENCE => Type::Sequence(Sequence::from(addr).unwrap()),
|
tag::SEQUENCE => Type::Sequence(Sequence::from(addr).unwrap()),
|
||||||
tag::ARRAY => Type::Array(Array::from(addr).unwrap()),
|
tag::ARRAY => Type::Array(Array::from(addr).unwrap()),
|
||||||
tag::LIST => Type::List(List::from(addr).unwrap()),
|
tag::LIST => Type::List(List::from(addr).unwrap()),
|
||||||
|
tag::SPARSE => Type::Sparse(Sparse::from(addr).unwrap()),
|
||||||
tag::RECORD => Type::Record(Record::from(addr).unwrap()),
|
tag::RECORD => Type::Record(Record::from(addr).unwrap()),
|
||||||
_ => Type::Null,
|
_ => Type::Null,
|
||||||
}
|
}
|
||||||
@ -58,6 +61,7 @@ impl Type {
|
|||||||
Type::Sequence(obj) => **obj,
|
Type::Sequence(obj) => **obj,
|
||||||
Type::Array(obj) => **obj,
|
Type::Array(obj) => **obj,
|
||||||
Type::List(obj) => **obj,
|
Type::List(obj) => **obj,
|
||||||
|
Type::Sparse(obj) => **obj,
|
||||||
Type::Record(obj) => **obj,
|
Type::Record(obj) => **obj,
|
||||||
_ => Reference::null(),
|
_ => Reference::null(),
|
||||||
}
|
}
|
||||||
|
@ -37,17 +37,6 @@ impl Natural {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, value:u64)
|
pub fn set(&mut self, value:u64)
|
||||||
{
|
{
|
||||||
unsafe { natural_set(self.addr, value) };
|
unsafe { natural_set(self.addr, value) };
|
||||||
|
@ -64,17 +64,6 @@ impl Record {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn length(&self) -> usize
|
pub fn length(&self) -> usize
|
||||||
{
|
{
|
||||||
unsafe {record_length(self.addr)}
|
unsafe {record_length(self.addr)}
|
||||||
@ -116,8 +105,7 @@ impl Record {
|
|||||||
let result = unsafe {record_indexof(self.addr, key_index)};
|
let result = unsafe {record_indexof(self.addr, key_index)};
|
||||||
if result != self.length() {
|
if result != self.length() {
|
||||||
Some(result)
|
Some(result)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,17 +45,6 @@ impl Schema {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn length(&self) -> usize
|
pub fn length(&self) -> usize
|
||||||
{
|
{
|
||||||
unsafe {schema_length(self.addr)}
|
unsafe {schema_length(self.addr)}
|
||||||
|
@ -47,17 +47,6 @@ impl Sequence {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn capacity(&self) -> usize
|
pub fn capacity(&self) -> usize
|
||||||
{
|
{
|
||||||
unsafe {sequence_capacity(self.addr)}
|
unsafe {sequence_capacity(self.addr)}
|
||||||
|
@ -37,17 +37,6 @@ impl Significant {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(&mut self, value:f64)
|
pub fn set(&mut self, value:f64)
|
||||||
{
|
{
|
||||||
unsafe { significant_set(self.addr, value) };
|
unsafe { significant_set(self.addr, value) };
|
92
src/interface/sparse.rs
Normal file
92
src/interface/sparse.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use crate::runtime::{
|
||||||
|
Reference,
|
||||||
|
acquire, release,
|
||||||
|
type_key,
|
||||||
|
sparse_length,
|
||||||
|
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 from(addr:Reference) -> Result<Self,()>
|
||||||
|
{
|
||||||
|
return if(unsafe {type_key(addr.class)} == tag::SPARSE) {
|
||||||
|
Ok(Self { managed:false, addr:addr })
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pub fn with(class:usize, data:Vec<Reference>) -> Self
|
||||||
|
{
|
||||||
|
let mut obj = Self::new(class);
|
||||||
|
for item in data {
|
||||||
|
obj.insert(obj.length(), item);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
} */
|
||||||
|
|
||||||
|
pub fn length(&self) -> usize
|
||||||
|
{
|
||||||
|
unsafe {sparse_length(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)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)}; } }
|
||||||
|
}
|
@ -38,17 +38,6 @@ impl Varying {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detach(&mut self)
|
|
||||||
{
|
|
||||||
self.managed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn release(mut self)
|
|
||||||
{
|
|
||||||
self.detach();
|
|
||||||
unsafe { release(self.addr); }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_null(&self) -> bool
|
pub fn is_null(&self) -> bool
|
||||||
{
|
{
|
||||||
(unsafe {varying_get(self.addr)}).address == 0
|
(unsafe {varying_get(self.addr)}).address == 0
|
||||||
|
55
src/lib.rs
55
src/lib.rs
@ -7,24 +7,53 @@ mod interface; pub use interface::*;
|
|||||||
mod encoding; pub use encoding::*;
|
mod encoding; pub use encoding::*;
|
||||||
|
|
||||||
pub fn test() {
|
pub fn test() {
|
||||||
let mut data = Varying::new();
|
use std::fs::File;
|
||||||
data.set(*Natural::with(79));
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
const MAGAZINE :usize = 0x100;
|
||||||
|
const MAGAZINE_ROW :usize = 0x101;
|
||||||
|
|
||||||
|
// define schema "Magazine Row"
|
||||||
|
Schema::with(vec![
|
||||||
|
("Content", natural()),
|
||||||
|
("Quantity", natural()),
|
||||||
|
]).bind(MAGAZINE_ROW);
|
||||||
|
|
||||||
|
// define schema "Magazine"
|
||||||
|
Schema::with(vec![
|
||||||
|
("Capacity", natural()),
|
||||||
|
("Quantity", natural()),
|
||||||
|
("Content", list(record(MAGAZINE_ROW))),
|
||||||
|
]).bind(MAGAZINE);
|
||||||
|
|
||||||
|
// create record "Magazine"
|
||||||
|
let data = Record::with(MAGAZINE, vec![
|
||||||
|
("Capacity", *Natural::with(30)),
|
||||||
|
("Quantity", *Natural::with(25)),
|
||||||
|
("Content", *List::with(record(MAGAZINE_ROW), vec![
|
||||||
|
*Record::with(MAGAZINE_ROW, vec![
|
||||||
|
("Content", *Natural::with(15)),
|
||||||
|
("Quantity", *Natural::with(5)),
|
||||||
|
]).unwrap(),
|
||||||
|
*Record::with(MAGAZINE_ROW, vec![
|
||||||
|
("Content", *Natural::with(16)),
|
||||||
|
("Quantity", *Natural::with(20)),
|
||||||
|
]).unwrap(),
|
||||||
|
])),
|
||||||
|
]).unwrap();
|
||||||
|
|
||||||
|
// encode record
|
||||||
let out = encode(*data);
|
let out = encode(*data);
|
||||||
|
|
||||||
|
// write encoding to file
|
||||||
|
let mut file = File::create("dat.szn").unwrap();
|
||||||
|
file.write_all(&out).ok();
|
||||||
|
|
||||||
|
// print hex series of encoding
|
||||||
print!("[{}]: ", out.len());
|
print!("[{}]: ", out.len());
|
||||||
for byte in &out {
|
for byte in &out {
|
||||||
print!("{:02x} ", *byte);
|
print!("{:02x} ", *byte);
|
||||||
} println!("\n");
|
} println!("");
|
||||||
|
|
||||||
match decode(&out, &mut 0) {
|
|
||||||
Ok(ty) => match ty {
|
|
||||||
Type::Varying(data) => {
|
|
||||||
println!("Ok: {}", Natural::from(data.get()).unwrap().get());
|
|
||||||
}
|
|
||||||
_ => { println!("Other"); }
|
|
||||||
},
|
|
||||||
Err(_) => { println!("Failure"); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -55,6 +55,7 @@ extern "C" size_t type_size(size_t type_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Type::Tag::List:
|
case Type::Tag::List:
|
||||||
|
case Type::Tag::Sparse:
|
||||||
case Type::Tag::Record:
|
case Type::Tag::Record:
|
||||||
{
|
{
|
||||||
size_t innerkey = type_innerkey(type_id);
|
size_t innerkey = type_innerkey(type_id);
|
||||||
@ -64,6 +65,7 @@ extern "C" size_t type_size(size_t type_id)
|
|||||||
else {
|
else {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Type::Tag::List: return sizeof(Type::List);
|
case Type::Tag::List: return sizeof(Type::List);
|
||||||
|
case Type::Tag::Sparse: return sizeof(Type::Sparse);
|
||||||
case Type::Tag::Record: {
|
case Type::Tag::Record: {
|
||||||
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
|
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
|
||||||
if(binding != nullptr) {
|
if(binding != nullptr) {
|
||||||
@ -88,24 +90,26 @@ size_t type_alignment(size_t type_id)
|
|||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Type::Tag::Null: return 0;
|
case Type::Tag::Null: return 0;
|
||||||
case Type::Tag::Varying: return sizeof(size_t);
|
|
||||||
case Type::Tag::Boolean: return sizeof(Type::Boolean);
|
case Type::Tag::Boolean: return sizeof(Type::Boolean);
|
||||||
case Type::Tag::Natural: return sizeof(Type::Natural);
|
case Type::Tag::Natural: return sizeof(Type::Natural);
|
||||||
case Type::Tag::Integer: return sizeof(Type::Integer);
|
case Type::Tag::Integer: return sizeof(Type::Integer);
|
||||||
case Type::Tag::Significant: return sizeof(Type::Significant);
|
case Type::Tag::Significant: return sizeof(Type::Significant);
|
||||||
case Type::Tag::Block: return sizeof(uint8_t);
|
case Type::Tag::Block: return sizeof(uint8_t);
|
||||||
case Type::Tag::Sequence: return sizeof(size_t);
|
case Type::Tag::Array: return type_alignment(type_inner(type_id));
|
||||||
case Type::Tag::Array: return type_inner(type_id);
|
|
||||||
case Type::Tag::List: return sizeof(size_t);
|
case Type::Tag::Varying:
|
||||||
|
case Type::Tag::Sequence:
|
||||||
|
case Type::Tag::List:
|
||||||
|
case Type::Tag::Sparse:
|
||||||
|
case Type::Tag::Schema:
|
||||||
|
return sizeof(size_t);
|
||||||
|
|
||||||
case Type::Tag::Record: {
|
case Type::Tag::Record: {
|
||||||
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
|
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
|
||||||
if(binding != nullptr) {
|
return (binding != nullptr)? binding->alignment : 0;
|
||||||
return binding->alignment;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case Type::Tag::Schema: return sizeof(size_t);
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -117,6 +121,7 @@ extern "C" size_t kind_hasinner(size_t kind)
|
|||||||
return 2;
|
return 2;
|
||||||
case Type::Tag::Block:
|
case Type::Tag::Block:
|
||||||
case Type::Tag::List:
|
case Type::Tag::List:
|
||||||
|
case Type::Tag::Sparse:
|
||||||
case Type::Tag::Record:
|
case Type::Tag::Record:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -192,25 +197,19 @@ void drop(Reference addr)
|
|||||||
if(addr.address != nullptr) {
|
if(addr.address != nullptr) {
|
||||||
switch(type_key(addr.type)) {
|
switch(type_key(addr.type)) {
|
||||||
case Type::Tag::Varying: {
|
case Type::Tag::Varying: {
|
||||||
auto& var = *reinterpret_cast<Reference*>(addr.address);
|
varying_clear(addr);
|
||||||
if(var.address != nullptr) {
|
|
||||||
drop(var);
|
|
||||||
}
|
|
||||||
var.type = 0;
|
|
||||||
var.address = nullptr;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type::Tag::Sequence: {
|
case Type::Tag::Sequence: {
|
||||||
auto& seq = *reinterpret_cast<Type::Sequence*>(addr.address);
|
sequence_clear(addr);
|
||||||
rawlist_clear(seq.data);
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type::Tag::List: {
|
case Type::Tag::List: {
|
||||||
Type::List& list = *reinterpret_cast<Type::List*>(addr.address);
|
list_clear(addr);
|
||||||
for(size_t i = 0; i < list.data.length; ++i) {
|
} break;
|
||||||
drop(list_cell(addr, i));
|
|
||||||
}
|
case Type::Tag::Sparse: {
|
||||||
rawlist_clear(list.data);
|
sparse_clear(addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type::Tag::Record: {
|
case Type::Tag::Record: {
|
||||||
@ -303,6 +302,27 @@ extern "C" bool copy(Reference dst, Reference src)
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Type::Tag::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::Tag::Record: {
|
case Type::Tag::Record: {
|
||||||
size_t schema_id = type_innerkey(source.type);
|
size_t schema_id = type_innerkey(source.type);
|
||||||
auto binding = DB_SCHEMA.get(schema_id);
|
auto binding = DB_SCHEMA.get(schema_id);
|
||||||
@ -439,10 +459,10 @@ extern "C" void varying_clear(Reference addr)
|
|||||||
if(var.address != nullptr) {
|
if(var.address != nullptr) {
|
||||||
drop(var);
|
drop(var);
|
||||||
free(var.address);
|
free(var.address);
|
||||||
|
}
|
||||||
var.type = 0;
|
var.type = 0;
|
||||||
var.address = nullptr;
|
var.address = nullptr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Boolean //
|
// Boolean //
|
||||||
@ -669,33 +689,13 @@ extern "C" Reference list_at(Reference addr, size_t index)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*extern "C" Reference list_first(Reference addr)
|
|
||||||
{
|
|
||||||
Reference result {0};
|
|
||||||
if(type_key(addr.type) == Type::Tag::List) {
|
|
||||||
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
||||||
if(list.length > 0) {
|
|
||||||
result = list_at(addr, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*extern "C" Reference list_last(Reference addr)
|
|
||||||
{
|
|
||||||
Reference result {0};
|
|
||||||
if(type_key(addr.type) == Type::Tag::List) {
|
|
||||||
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
||||||
if(list.length > 0) {
|
|
||||||
result = list_at(addr, list.length - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
extern "C" void list_clear(Reference addr)
|
extern "C" void list_clear(Reference addr)
|
||||||
{
|
{
|
||||||
drop(addr);
|
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)
|
extern "C" void list_insert(Reference addr, size_t index, Reference source)
|
||||||
@ -706,13 +706,15 @@ extern "C" void list_insert(Reference addr, size_t index, Reference source)
|
|||||||
|
|
||||||
if(index > list.data.length) { index = list.data.length; }
|
if(index > list.data.length) { index = list.data.length; }
|
||||||
|
|
||||||
void* cell = rawlist_insert(list.data, offset, index);
|
Reference cell {0};
|
||||||
|
cell.type = inner;
|
||||||
|
cell.address = rawlist_insert(list.data, offset, index);
|
||||||
|
|
||||||
if(type_key(inner) == Type::Tag::Varying) {
|
if(type_key(inner) == Type::Tag::Varying) {
|
||||||
varying_set(list_cell(addr, index), source);
|
varying_set(cell, source);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy(list_cell(addr, index), source);
|
copy(cell, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,16 +725,15 @@ extern "C" void list_prepend(Reference addr, Reference source)
|
|||||||
|
|
||||||
extern "C" void list_append(Reference addr, Reference source)
|
extern "C" void list_append(Reference addr, Reference source)
|
||||||
{
|
{
|
||||||
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
auto& list = *reinterpret_cast<Type::List*>(addr.address);
|
||||||
list_insert(addr, list.data.length, source);
|
list_insert(addr, list.data.length, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void list_update(Reference addr, size_t index, Reference source)
|
extern "C" void list_update(Reference addr, size_t index, Reference source)
|
||||||
{
|
{
|
||||||
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
auto& list = *reinterpret_cast<Type::List*>(addr.address);
|
||||||
if(index < list.data.length) {
|
if(index < list.data.length) {
|
||||||
size_t inner = type_inner(addr.type);
|
size_t inner = type_inner(addr.type);
|
||||||
size_t offset = type_size(inner);
|
|
||||||
|
|
||||||
if(type_key(inner) == Type::Tag::Varying) {
|
if(type_key(inner) == Type::Tag::Varying) {
|
||||||
varying_set(list_cell(addr, index), source);
|
varying_set(list_cell(addr, index), source);
|
||||||
@ -743,25 +744,9 @@ extern "C" void list_update(Reference addr, size_t index, Reference source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*extern "C" void list_truncate(Reference addr, size_t maximum)
|
|
||||||
{
|
|
||||||
if(type_key(addr.type) == Type::Tag::List) {
|
|
||||||
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
||||||
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*extern "C" void list_shift(Reference addr)
|
|
||||||
{
|
|
||||||
if(type_key(addr.type) == Type::Tag::List) {
|
|
||||||
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
||||||
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
extern "C" void list_remove(Reference addr, size_t index)
|
extern "C" void list_remove(Reference addr, size_t index)
|
||||||
{
|
{
|
||||||
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
auto& list = *reinterpret_cast<Type::List*>(addr.address);
|
||||||
size_t inner = type_inner(addr.type);
|
size_t inner = type_inner(addr.type);
|
||||||
size_t offset = type_size(inner);
|
size_t offset = type_size(inner);
|
||||||
if(index < list.data.length) {
|
if(index < list.data.length) {
|
||||||
@ -772,20 +757,265 @@ extern "C" void list_remove(Reference addr, size_t index)
|
|||||||
|
|
||||||
extern "C" void list_reserve(Reference addr, size_t capacity)
|
extern "C" void list_reserve(Reference addr, size_t capacity)
|
||||||
{
|
{
|
||||||
auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
auto& list = *reinterpret_cast<Type::List*>(addr.address);
|
||||||
size_t inner = type_inner(addr.type);
|
size_t inner = type_inner(addr.type);
|
||||||
size_t offset = type_size(inner);
|
size_t offset = type_size(inner);
|
||||||
|
|
||||||
rawlist_reserve(list.data, offset, capacity);
|
rawlist_reserve(list.data, offset, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*extern "C" void list_resize(Reference addr, size_t length)
|
|
||||||
{
|
|
||||||
if(type_key(addr.type) == Type::Tag::List) {
|
|
||||||
//auto& list = (*reinterpret_cast<Type::List*>(addr.address));
|
|
||||||
|
|
||||||
|
// Sparse //
|
||||||
|
|
||||||
|
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" 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::Tag::Varying) {
|
||||||
|
result = varying_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::Tag::Varying) {
|
||||||
|
result = varying_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;
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
// Record //
|
// Record //
|
||||||
@ -833,7 +1063,8 @@ extern "C" Reference record_at(Reference addr, size_t index)
|
|||||||
extern "C" void record_update(Reference addr, size_t index, Reference source)
|
extern "C" void record_update(Reference addr, size_t index, Reference source)
|
||||||
{
|
{
|
||||||
Reference destination {0};
|
Reference destination {0};
|
||||||
auto binding = DB_SCHEMA.get(type_innerkey(addr.type));
|
size_t schid = type_innerkey(addr.type);
|
||||||
|
auto binding = DB_SCHEMA.get(schid);
|
||||||
if(binding != nullptr) {
|
if(binding != nullptr) {
|
||||||
if(index < binding->data.size()) {
|
if(index < binding->data.size()) {
|
||||||
destination.type = binding->data[index].type;
|
destination.type = binding->data[index].type;
|
||||||
@ -960,7 +1191,7 @@ 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" void schema_unmap(Reference addr, size_t key)
|
||||||
{
|
{
|
||||||
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
auto& object = (*reinterpret_cast<Type::Schema*>(addr.address));
|
||||||
for(size_t i; i < object.map.length; i++) {
|
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));
|
auto cell = reinterpret_cast<Type::Schema::Mapping*>(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i));
|
||||||
if(cell != nullptr) {
|
if(cell != nullptr) {
|
||||||
if(cell->key == key) {
|
if(cell->key == key) {
|
||||||
@ -1036,7 +1267,7 @@ extern "C" size_t schema_bind(Reference addr, size_t id)
|
|||||||
printf(" Align: %zu\n", binding.alignment);
|
printf(" Align: %zu\n", binding.alignment);
|
||||||
printf(" Data:\n");
|
printf(" Data:\n");
|
||||||
for(size_t i = 0; i < binding.data.size(); ++i) {
|
for(size_t i = 0; i < binding.data.size(); ++i) {
|
||||||
printf(" - %zu {%#x} (%zu)\n",
|
printf(" - %zu:%#x +%zu\n",
|
||||||
binding.data[i].type,
|
binding.data[i].type,
|
||||||
type_key(binding.data[i].type),
|
type_key(binding.data[i].type),
|
||||||
binding.data[i].offset
|
binding.data[i].offset
|
||||||
|
@ -69,7 +69,7 @@ extern "C" size_t block_length(Reference addr);
|
|||||||
extern "C" uint8_t block_get(Reference addr, size_t index);
|
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" void block_set(Reference addr, size_t index, uint8_t value);
|
||||||
|
|
||||||
// String //
|
// Sequence //
|
||||||
extern "C" size_t sequence_capacity(Reference addr);
|
extern "C" size_t sequence_capacity(Reference addr);
|
||||||
extern "C" size_t sequence_length(Reference addr);
|
extern "C" size_t sequence_length(Reference addr);
|
||||||
extern "C" uint8_t sequence_get(Reference addr, size_t index);
|
extern "C" uint8_t sequence_get(Reference addr, size_t index);
|
||||||
@ -102,6 +102,17 @@ extern "C" void list_remove(Reference addr, size_t index);
|
|||||||
extern "C" void list_reserve(Reference addr, size_t capacity);
|
extern "C" void list_reserve(Reference addr, size_t capacity);
|
||||||
//extern "C" void list_resize(Reference addr, size_t length);
|
//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" 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 //
|
// Record //
|
||||||
extern "C" size_t record_length(Reference addr);
|
extern "C" size_t record_length(Reference addr);
|
||||||
extern "C" size_t record_type(Reference addr, size_t index);
|
extern "C" size_t record_type(Reference addr, size_t index);
|
||||||
|
@ -28,6 +28,14 @@ pub struct Str {
|
|||||||
pub length:usize,
|
pub length:usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct SparseHeader {
|
||||||
|
pub start:usize,
|
||||||
|
pub length:usize,
|
||||||
|
pub index:usize,
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn test();
|
pub fn test();
|
||||||
|
|
||||||
@ -101,6 +109,16 @@ extern "C" {
|
|||||||
//pub fn list_find(addr:Reference, target:Reference, start:usize) -> usize;
|
//pub fn list_find(addr:Reference, target:Reference, start:usize) -> usize;
|
||||||
//pub fn list_count(addr:Reference, target:Reference, start:usize) -> usize;
|
//pub fn list_count(addr:Reference, target:Reference, start:usize) -> usize;
|
||||||
|
|
||||||
|
pub fn sparse_header_length(addr:Reference) -> usize;
|
||||||
|
pub fn sparse_header_data(addr:Reference, index:usize) -> SparseHeader;
|
||||||
|
pub fn sparse_length(addr:Reference) -> usize;
|
||||||
|
pub fn sparse_clear(addr:Reference);
|
||||||
|
pub fn sparse_get(addr:Reference, index:usize) -> Reference;
|
||||||
|
pub fn sparse_at(addr:Reference, index:usize) -> Reference;
|
||||||
|
pub fn sparse_set(addr:Reference, index:usize, source:Reference);
|
||||||
|
pub fn sparse_unset(addr:Reference, index:usize);
|
||||||
|
pub fn sparse_indexof(addr:Reference, index:usize) -> usize;
|
||||||
|
|
||||||
pub fn record_length(addr:Reference) -> usize;
|
pub fn record_length(addr:Reference) -> usize;
|
||||||
pub fn record_type(addr:Reference, index:usize) -> usize;
|
pub fn record_type(addr:Reference, index:usize) -> usize;
|
||||||
pub fn record_at(addr:Reference, index:usize) -> Reference;
|
pub fn record_at(addr:Reference, index:usize) -> Reference;
|
||||||
|
@ -83,8 +83,8 @@ size_t NameTree::indexof(const std::string& key)
|
|||||||
// create branching node if value is not prefix
|
// create branching node if value is not prefix
|
||||||
if(index != key.length()) {
|
if(index != key.length()) {
|
||||||
m_nodes.push_back(Node(key.substr(index), intermediate_index));
|
m_nodes.push_back(Node(key.substr(index), intermediate_index));
|
||||||
|
m_nodes[intermediate_index].children.push_back(m_nodes.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_nodes.size() - 1;
|
return m_nodes.size() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +97,6 @@ size_t NameTree::indexof(const std::string& key)
|
|||||||
return m_nodes.size() - 1;
|
return m_nodes.size() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "rawlist.h"
|
#include "rawlist.h"
|
||||||
|
|
||||||
void* rawlist_insert(RawList& list, size_t offset, size_t index)
|
uint8_t* rawlist_insert(RawList& list, size_t offset, size_t index)
|
||||||
{
|
{
|
||||||
if(list.length == list.capacity) { rawlist_reserve(list, offset, (list.capacity == 0) + list.capacity * 2); }
|
if(list.length == list.capacity) { rawlist_reserve(list, offset, (list.capacity == 0) + list.capacity * 2); }
|
||||||
if(index > list.length) { index = list.length; }
|
if(index > list.length) { index = list.length; }
|
||||||
|
@ -11,7 +11,7 @@ struct RawList {
|
|||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
void* rawlist_insert(RawList& list, size_t offset, size_t index);
|
uint8_t* rawlist_insert(RawList& list, size_t offset, size_t index);
|
||||||
void rawlist_remove(RawList& list, size_t offset, size_t index);
|
void rawlist_remove(RawList& list, size_t offset, size_t index);
|
||||||
inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index);
|
inline uint8_t* rawlist_cell(RawList& list, size_t offset, size_t index);
|
||||||
void rawlist_reserve(RawList& list, size_t offset, size_t capacity);
|
void rawlist_reserve(RawList& list, size_t offset, size_t capacity);
|
||||||
|
@ -14,7 +14,7 @@ public:
|
|||||||
|
|
||||||
size_t length() const
|
size_t length() const
|
||||||
{
|
{
|
||||||
|
m_data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(size_t index, const T& value)
|
void set(size_t index, const T& value)
|
||||||
|
@ -23,7 +23,7 @@ namespace Tag {
|
|||||||
Sequence = 0x1f,
|
Sequence = 0x1f,
|
||||||
Array = 0x22,
|
Array = 0x22,
|
||||||
List = 0x23,
|
List = 0x23,
|
||||||
//Sparse = 0x24,
|
Sparse = 0x24,
|
||||||
Record = 0x7e,
|
Record = 0x7e,
|
||||||
Schema = 0x7f,
|
Schema = 0x7f,
|
||||||
};
|
};
|
||||||
@ -42,21 +42,15 @@ struct List {
|
|||||||
RawList data;
|
RawList data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Sparse {
|
extern "C" struct SparseHeader {
|
||||||
struct Header {
|
|
||||||
size_t start;
|
size_t start;
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t index;
|
size_t index;
|
||||||
|
|
||||||
Header() {
|
|
||||||
start = 0;
|
|
||||||
length = 0;
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RawList data;
|
struct Sparse {
|
||||||
RawList header;
|
RawList header;
|
||||||
|
RawList data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Schema {
|
struct Schema {
|
||||||
|
@ -16,7 +16,7 @@ pub const SEQUENCE :usize = 0x1f;
|
|||||||
//pub const SET :usize = 0x21;
|
//pub const SET :usize = 0x21;
|
||||||
pub const ARRAY :usize = 0x22;
|
pub const ARRAY :usize = 0x22;
|
||||||
pub const LIST :usize = 0x23;
|
pub const LIST :usize = 0x23;
|
||||||
//pub const SPARSE :usize = 0x24;
|
pub const SPARSE :usize = 0x24;
|
||||||
//pub const TRIE :usize = 0x25;
|
//pub const TRIE :usize = 0x25;
|
||||||
//pub const MAP :usize = 0x26;
|
//pub const MAP :usize = 0x26;
|
||||||
//pub const TREE :usize = 0x27;
|
//pub const TREE :usize = 0x27;
|
||||||
|
Reference in New Issue
Block a user