Implement encode/decode, fix bugs, update README with new functions.
This commit is contained in:
parent
c5d551bde2
commit
7addefd634
30
README.md
30
README.md
@ -78,25 +78,35 @@ Destruct and deallocate a type.
|
||||
```
|
||||
release(refer);
|
||||
```
|
||||
> Warning: To avoid access violations, `release()` should not be used with interface objects, such as Boolean.
|
||||
---
|
||||
|
||||
`transfer(dst:Reference, src:Reference) -> Result<(),()>`
|
||||
Move an object from one location to another, clearing the original.
|
||||
|
||||
---
|
||||
|
||||
`copy(dst:Reference, src:Reference) -> Result<(),()>`
|
||||
Copy the contents of an objcet to another location, keeping the original.
|
||||
|
||||
---
|
||||
|
||||
|
||||
`encode(refer:Reference) -> Vec<u8>`
|
||||
`encode_raw(refer:Reference) -> Vec<u8>`
|
||||
`encode_tag(refer:Reference) -> Vec<u8>`
|
||||
|
||||
Serializes an object into binary encoding.
|
||||
The raw variant does not produce a tag prefix for the root object.
|
||||
|
||||
> Not implemented
|
||||
---
|
||||
|
||||
`decode(data:Vec<u8>) -> Result<Reference,()>`
|
||||
`decode_raw(data:Vec<u8>, type_id:usize) -> Result<Reference,()>`
|
||||
`decode(data:&Vec<u8>, index:&mut usize) -> Result<Type,()>`
|
||||
`decode_raw(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Type,()>`
|
||||
`decode_tag(data:&Vec<u8>, index:&mut usize) -> Result<usize,()>`
|
||||
|
||||
Parses a valid binary encoding and produces the represented object.
|
||||
The raw variant does not decode a tag prefix on the root object.
|
||||
|
||||
> Not implemented
|
||||
---
|
||||
|
||||
## Language Compiler
|
||||
@ -241,7 +251,15 @@ value.set(-273);
|
||||
|
||||
|
||||
## Significant
|
||||
Stores a fixed-precision, variable-magnitude
|
||||
Stores a fixed-precision, variable-magnitude number.
|
||||
|
||||
`get() -> f64`
|
||||
|
||||
---
|
||||
|
||||
`set(value:f64)`
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Block
|
||||
|
192
src/encoding/mod.rs
Normal file
192
src/encoding/mod.rs
Normal file
@ -0,0 +1,192 @@
|
||||
use crate::{
|
||||
runtime::{
|
||||
Reference,
|
||||
kind_hasinner, type_hasinner, type_inner, type_outer,
|
||||
type_key, type_innerkey,
|
||||
},
|
||||
tag,
|
||||
Type,
|
||||
util::*,
|
||||
};
|
||||
use crate::kind;
|
||||
use crate::{
|
||||
Boolean,
|
||||
Natural, Integer,
|
||||
Block, Sequence,
|
||||
Array, List,
|
||||
Record,
|
||||
};
|
||||
use crate::util;
|
||||
|
||||
pub fn encode_tag(addr:Reference) -> Vec<u8>
|
||||
{
|
||||
let mut type_id = addr.class;
|
||||
let mut result = Vec::<u8>::new();
|
||||
let mut remaining :usize = 1;
|
||||
while remaining > 0 {
|
||||
result.append(&mut util::pack_natural(unsafe {type_key(type_id)} as u64));
|
||||
|
||||
remaining -= 1;
|
||||
if remaining == 0 {
|
||||
remaining += unsafe {type_hasinner(type_id)};
|
||||
}
|
||||
type_id = unsafe {type_inner(type_id)};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn encode_data(addr:Reference) -> Vec<u8>
|
||||
{
|
||||
let mut result = Vec::<u8>::new();
|
||||
match unsafe {type_key(addr.class)} {
|
||||
tag::BOOLEAN => {
|
||||
result.append(&mut util::pack_natural(Boolean::from(addr).unwrap().get() as u64));
|
||||
}
|
||||
tag::NATURAL => {
|
||||
result.append(&mut util::pack_natural(Natural::from(addr).unwrap().get() as u64));
|
||||
}
|
||||
tag::INTEGER => {
|
||||
result.append(&mut &mut util::pack_integer(Integer::from(addr).unwrap().get() as i64));
|
||||
}
|
||||
tag::BLOCK => {
|
||||
result.append(&mut Block::from(addr).unwrap().get());
|
||||
}
|
||||
tag::SEQUENCE => {
|
||||
let data = Sequence::from(addr).unwrap();
|
||||
result.append(&mut util::pack_natural(data.size() as u64));
|
||||
result.append(&mut data.get_raw());
|
||||
}
|
||||
tag::ARRAY => {
|
||||
let data = Array::from(addr).unwrap();
|
||||
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::LIST => {
|
||||
let data = List::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 {
|
||||
result.append(&mut encode(data.at(i)));
|
||||
}
|
||||
else {
|
||||
result.append(&mut encode_data(data.at(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
tag::RECORD => {
|
||||
let data = Record::from(addr).unwrap();
|
||||
for i in 0..data.length() {
|
||||
if kind(data.kindof(i)) == tag::VARYING {
|
||||
result.append(&mut encode(data.at(i)));
|
||||
}
|
||||
else {
|
||||
result.append(&mut encode_data(data.at(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn encode(addr:Reference) -> Vec<u8>
|
||||
{
|
||||
let mut result = encode_tag(addr);
|
||||
result.append(&mut encode_data(addr));
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn decode_tag(data:&Vec<u8>, index:&mut usize) -> Result<usize,()>
|
||||
{
|
||||
let mut tags = Vec::<usize>::new();
|
||||
let mut remaining :usize = 1;
|
||||
while remaining > 0 && *index < data.len() {
|
||||
let kind = util::unpack_natural(&data, index) as usize;
|
||||
tags.push(kind);
|
||||
|
||||
remaining -= 1;
|
||||
if remaining == 0 {
|
||||
remaining += unsafe {kind_hasinner(kind)};
|
||||
}
|
||||
}
|
||||
let mut type_id = 0;
|
||||
for i in (0..tags.len()).rev() {
|
||||
type_id = unsafe {type_outer(type_id, tags[i])};
|
||||
}
|
||||
|
||||
return if remaining == 0 { Ok(type_id) }
|
||||
else { Err(()) }
|
||||
}
|
||||
|
||||
pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Type,()>
|
||||
{
|
||||
match unsafe {type_key(type_id)} {
|
||||
tag::VARYING => {
|
||||
return decode(data, index);
|
||||
}
|
||||
tag::BOOLEAN => {
|
||||
return Ok(Type::Boolean(Boolean::with(unpack_natural(data, index) == 1)));
|
||||
}
|
||||
tag::NATURAL => {
|
||||
return Ok(Type::Natural(Natural::with(unpack_natural(data, index))));
|
||||
}
|
||||
tag::INTEGER => {
|
||||
return Ok(Type::Integer(Integer::with(unpack_integer(data, index))));
|
||||
}
|
||||
tag::BLOCK => {
|
||||
let size = unsafe {type_innerkey(type_id)};
|
||||
let mut bytes = Vec::<u8>::with_capacity(size);
|
||||
if *index + size <= data.len() {
|
||||
for _ in 0..size {
|
||||
bytes.push(data[*index]);
|
||||
*index += 1;
|
||||
}
|
||||
}
|
||||
return Ok(Type::Block(Block::with(size, bytes)));
|
||||
}
|
||||
tag::SEQUENCE => {
|
||||
let size = unpack_natural(data, index) as usize;
|
||||
let mut bytes = Vec::<u8>::with_capacity(size);
|
||||
if *index + size <= data.len() {
|
||||
for _ in 0..size {
|
||||
bytes.push(data[*index]);
|
||||
*index += 1;
|
||||
}
|
||||
}
|
||||
return Ok(Type::Sequence(Sequence::with_raw(bytes)));
|
||||
}
|
||||
tag::RECORD => {
|
||||
return match Record::new(unsafe {type_innerkey(type_id)}) {
|
||||
Ok(mut value) => {
|
||||
for i in 0..value.length() {
|
||||
match decode_data(data, value.kindof(i), index) {
|
||||
Ok(refer) => {
|
||||
value.set_at(i, refer.get());
|
||||
}
|
||||
Err(_) => return Err(())
|
||||
}
|
||||
}
|
||||
Ok(Type::Record(value))
|
||||
}
|
||||
Err(_) => Err(()),
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
|
||||
return Err(());
|
||||
}
|
||||
|
||||
pub fn decode(data:&Vec<u8>, index:&mut usize) -> Result<Type,()>
|
||||
{
|
||||
return match decode_tag(data, index) {
|
||||
Ok(type_id) => decode_data(data, type_id, index),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
@ -53,6 +53,17 @@ impl Array {
|
||||
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
|
||||
{
|
||||
unsafe {array_length(self.addr)}
|
||||
|
@ -31,7 +31,25 @@ impl Block {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn length(&self) -> usize
|
||||
pub fn with(size:usize, data:Vec<u8>) -> Self
|
||||
{
|
||||
let mut obj = Self::new(size);
|
||||
obj.set(data);
|
||||
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
|
||||
{
|
||||
unsafe {block_length(self.addr)}
|
||||
}
|
||||
|
@ -37,6 +37,17 @@ impl Boolean {
|
||||
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)
|
||||
{
|
||||
unsafe { bool_set(self.addr, value) };
|
||||
|
@ -1,6 +1,9 @@
|
||||
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 varying() -> usize { 0 }
|
||||
pub fn null() -> usize { unsafe { runtime::type_outer(0, tag::NULL) } }
|
||||
pub fn boolean() -> usize { unsafe { runtime::type_outer(0, tag::BOOLEAN) } }
|
||||
|
@ -37,6 +37,17 @@ impl Integer {
|
||||
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)
|
||||
{
|
||||
unsafe { integer_set(self.addr, value) };
|
||||
|
@ -44,6 +44,17 @@ impl List {
|
||||
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
|
||||
{
|
||||
unsafe {list_capacity(self.addr)}
|
||||
|
@ -16,27 +16,49 @@ mod schema; pub use schema::Schema;
|
||||
mod record; pub use record::Record;
|
||||
|
||||
pub enum Type {
|
||||
Varying(Varying),
|
||||
Null,
|
||||
Varying(Varying),
|
||||
Boolean(Boolean),
|
||||
Natural(Natural),
|
||||
Integer(Integer),
|
||||
Block(Block),
|
||||
Sequence(Sequence),
|
||||
Array(Array),
|
||||
List(List),
|
||||
Record(Record),
|
||||
Schema(Schema),
|
||||
}
|
||||
impl Type {
|
||||
pub fn from(addr:Reference) -> Self
|
||||
{
|
||||
match unsafe {type_key(addr.class)} {
|
||||
tag::VARYING => Type::Varying(Varying::from(addr).unwrap()),
|
||||
tag::NULL => Type::Null,
|
||||
tag::VARYING => Type::Varying(Varying::from(addr).unwrap()),
|
||||
tag::BOOLEAN => Type::Boolean(Boolean::from(addr).unwrap()),
|
||||
tag::NATURAL => Type::Natural(Natural::from(addr).unwrap()),
|
||||
tag::INTEGER => Type::Integer(Integer::from(addr).unwrap()),
|
||||
tag::BLOCK => Type::Block(Block::from(addr).unwrap()),
|
||||
tag::SEQUENCE => Type::Sequence(Sequence::from(addr).unwrap()),
|
||||
tag::ARRAY => Type::Array(Array::from(addr).unwrap()),
|
||||
tag::LIST => Type::List(List::from(addr).unwrap()),
|
||||
tag::RECORD => Type::Record(Record::from(addr).unwrap()),
|
||||
_ => Type::Null,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Reference
|
||||
{
|
||||
match &self {
|
||||
Type::Varying(obj) => **obj,
|
||||
Type::Boolean(obj) => **obj,
|
||||
Type::Natural(obj) => **obj,
|
||||
Type::Integer(obj) => **obj,
|
||||
Type::Block(obj) => **obj,
|
||||
Type::Sequence(obj) => **obj,
|
||||
Type::Array(obj) => **obj,
|
||||
Type::List(obj) => **obj,
|
||||
Type::Record(obj) => **obj,
|
||||
_ => Reference::null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,17 @@ impl Natural {
|
||||
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)
|
||||
{
|
||||
unsafe { natural_set(self.addr, value) };
|
||||
|
@ -7,6 +7,7 @@ use crate::runtime::{
|
||||
record_length,
|
||||
record_at, record_update,
|
||||
record_indexof, record_keyof,
|
||||
record_type,
|
||||
};
|
||||
use crate::tag;
|
||||
use super::record;
|
||||
@ -63,6 +64,17 @@ 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
|
||||
{
|
||||
unsafe {record_length(self.addr)}
|
||||
@ -98,17 +110,6 @@ impl Record {
|
||||
}
|
||||
}
|
||||
|
||||
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 indexof(&self, key:&str) -> Option<usize>
|
||||
{
|
||||
let key_index = name_indexof(key);
|
||||
@ -120,6 +121,22 @@ impl Record {
|
||||
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 std::ops::Deref for Record {
|
||||
type Target = Reference;
|
||||
|
@ -45,6 +45,17 @@ impl Schema {
|
||||
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
|
||||
{
|
||||
unsafe {schema_length(self.addr)}
|
||||
|
@ -33,14 +33,33 @@ impl 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();
|
||||
println!("a");
|
||||
obj.set(data);
|
||||
return obj;
|
||||
}
|
||||
|
||||
pub fn length(&self) -> usize
|
||||
pub fn detach(&mut self)
|
||||
{
|
||||
self.managed = false;
|
||||
}
|
||||
|
||||
pub fn release(mut self)
|
||||
{
|
||||
self.detach();
|
||||
unsafe { release(self.addr); }
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize
|
||||
{
|
||||
unsafe {sequence_length(self.addr)}
|
||||
}
|
||||
@ -48,6 +67,7 @@ impl Sequence {
|
||||
pub fn set_raw(&mut self, data:Vec<u8>)
|
||||
{
|
||||
unsafe { sequence_clear(self.addr); }
|
||||
println!("c {}", data.len());
|
||||
if data.len() > 0 {
|
||||
unsafe { sequence_reserve(self.addr, data.len()); }
|
||||
for i in 0..data.len() {
|
||||
@ -65,6 +85,7 @@ impl Sequence {
|
||||
{
|
||||
let length = unsafe {sequence_length(self.addr)};
|
||||
let mut result = Vec::<u8>::new();
|
||||
println!("d {}", length);
|
||||
|
||||
if length > 0 {
|
||||
result.reserve_exact(length);
|
||||
|
@ -9,3 +9,13 @@ pub fn release(addr:runtime::Reference)
|
||||
{
|
||||
unsafe {runtime::release(addr)}
|
||||
}
|
||||
|
||||
pub fn copy(_dst:runtime::Reference, _src:runtime::Reference) -> Result<(),()>
|
||||
{
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub fn transfer(_dst:runtime::Reference, _src:runtime::Reference) -> Result<(),()>
|
||||
{
|
||||
Err(())
|
||||
}
|
||||
|
@ -30,6 +30,17 @@ impl Varying {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
(unsafe {varying_get(self.addr)}).address == 0
|
||||
|
76
src/lib.rs
76
src/lib.rs
@ -3,58 +3,44 @@
|
||||
mod tag;
|
||||
mod util;
|
||||
mod runtime;
|
||||
mod interface; pub use interface::*;
|
||||
|
||||
const SCH_MAGAZINE :usize = 0x110;
|
||||
const SCH_MAGAZINE_ROW :usize = 0x111;
|
||||
mod interface;
|
||||
pub use interface::*;
|
||||
mod encoding; pub use encoding::*;
|
||||
|
||||
pub fn test() {
|
||||
Schema::with(vec![
|
||||
("type", natural()),
|
||||
("quantity", natural()),
|
||||
]).bind(SCH_MAGAZINE_ROW);
|
||||
("nat", natural()),
|
||||
("pass", block(6)),
|
||||
]).bind(9);
|
||||
Schema::with(vec![
|
||||
("size", natural()),
|
||||
("content", list(record(SCH_MAGAZINE_ROW))),
|
||||
]).bind(SCH_MAGAZINE);
|
||||
("str", sequence()),
|
||||
("int", integer()),
|
||||
("bool", boolean()),
|
||||
("rec", record(9)),
|
||||
]).bind(10);
|
||||
|
||||
let mag = Record::with(SCH_MAGAZINE, vec![
|
||||
("size", *Natural::with(30)),
|
||||
]).unwrap();
|
||||
let mut contents = List::from(mag.get("content")).unwrap();
|
||||
contents.append(*Record::with_values(SCH_MAGAZINE_ROW, vec![
|
||||
*Natural::with(2),
|
||||
*Natural::with(5),
|
||||
let out = encode(*Record::with(10, vec![
|
||||
("str", *Sequence::with("hello!")),
|
||||
("int", *Integer::with(-70)),
|
||||
("bool", *Boolean::with(true)),
|
||||
("rec", *Record::with(9, vec![
|
||||
("nat", *Natural::with(8)),
|
||||
("pass", *Block::with(6, vec![1, 2, 3, 4, 5, 6])),
|
||||
]).unwrap()),
|
||||
]).unwrap());
|
||||
contents.append(*Record::with_values(SCH_MAGAZINE_ROW, vec![
|
||||
*Natural::with(1),
|
||||
*Natural::with(25),
|
||||
]).unwrap());
|
||||
|
||||
{
|
||||
// get and remove bullet
|
||||
let mut list = List::from(mag.at(1)).unwrap();
|
||||
if list.length() > 0 {
|
||||
let row = Record::from(list.at(list.length() - 1)).unwrap();
|
||||
let mut cell = Natural::from(row.at(1)).unwrap();
|
||||
let value = cell.get();
|
||||
if value > 1 {
|
||||
cell.set(value - 1);
|
||||
} else {
|
||||
list.remove(list.length() - 1);
|
||||
match decode(&out, &mut 0) {
|
||||
Ok(ty) => match ty {
|
||||
Type::Record(rec) => {
|
||||
println!("{}", Sequence::from(rec.get("str")).unwrap().get());
|
||||
println!("{}", Integer::from(rec.get("int")).unwrap().get());
|
||||
println!("{}", Boolean::from(rec.get("bool")).unwrap().get());
|
||||
let sub = Record::from(rec.get("rec")).unwrap();
|
||||
println!("{}", Natural::from(sub.get("nat")).unwrap().get());
|
||||
println!("{:?}", Block::from(sub.get("pass")).unwrap().get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Magazine ({})",
|
||||
Natural::from(mag.at(0)).unwrap().get(),
|
||||
);
|
||||
for i in 0..contents.length() {
|
||||
let row = Record::from(contents.at(i)).unwrap();
|
||||
println!(" - {} [{}]",
|
||||
Natural::from(row.at(0)).unwrap().get(),
|
||||
Natural::from(row.at(1)).unwrap().get(),
|
||||
);
|
||||
_ => { println!("Other"); }
|
||||
},
|
||||
Err(_) => { println!("Failure"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,20 +39,40 @@ extern "C" size_t type_size(size_t type_id)
|
||||
case Type::Tag::Boolean: return sizeof(Type::Boolean);
|
||||
case Type::Tag::Natural: return sizeof(Type::Natural);
|
||||
case Type::Tag::Integer: return sizeof(Type::Integer);
|
||||
case Type::Tag::Block: return DB_TYPE.key(DB_TYPE.inner(type_id));
|
||||
case Type::Tag::Block: return type_innerkey(type_id);
|
||||
case Type::Tag::Sequence: return sizeof(Type::Sequence);
|
||||
|
||||
case Type::Tag::Array: {
|
||||
size_t length = DB_TYPE.inner(type_id);
|
||||
size_t inner = DB_TYPE.inner(length);
|
||||
return static_cast<size_t>(DB_TYPE.key(length)) * type_size(inner);
|
||||
};
|
||||
case Type::Tag::List: return sizeof(Type::List);
|
||||
case Type::Tag::Record: {
|
||||
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
|
||||
if(binding != nullptr) {
|
||||
return binding->size;
|
||||
if(inner == Type::Tag::Null) {
|
||||
return sizeof(Reference);
|
||||
}
|
||||
else {
|
||||
return static_cast<size_t>(DB_TYPE.key(length)) * type_size(inner);
|
||||
}
|
||||
}
|
||||
|
||||
case Type::Tag::List:
|
||||
case Type::Tag::Record:
|
||||
{
|
||||
size_t innerkey = type_innerkey(type_id);
|
||||
if(innerkey == Type::Tag::Null) {
|
||||
return sizeof(Reference);
|
||||
}
|
||||
else {
|
||||
switch(type) {
|
||||
case Type::Tag::List: return sizeof(Type::List);
|
||||
case Type::Tag::Record: {
|
||||
auto binding = DB_SCHEMA.get(type_innerkey(type_id));
|
||||
if(binding != nullptr) {
|
||||
return binding->size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case Type::Tag::Schema: return sizeof(Type::Schema);
|
||||
default: return 0;
|
||||
}
|
||||
@ -88,6 +108,24 @@ size_t type_alignment(size_t type_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" size_t kind_hasinner(size_t kind)
|
||||
{
|
||||
switch(kind) {
|
||||
case Type::Tag::Array:
|
||||
return 2;
|
||||
case Type::Tag::Block:
|
||||
case Type::Tag::List:
|
||||
case Type::Tag::Record:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" size_t type_hasinner(size_t type_id)
|
||||
{
|
||||
return kind_hasinner(type_key(type_id));
|
||||
}
|
||||
|
||||
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length)
|
||||
{
|
||||
std::string str(reinterpret_cast<const char*>(bytes), length);
|
||||
@ -239,18 +277,32 @@ bool copy(Reference src, Reference dst)
|
||||
case Type::Tag::Boolean:
|
||||
case Type::Tag::Natural:
|
||||
case Type::Tag::Integer:
|
||||
case Type::Tag::Block:
|
||||
{
|
||||
case Type::Tag::Block: {
|
||||
memcpy(destination.address, source.address, type_size(source.type));
|
||||
} break;
|
||||
|
||||
case Type::Tag::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);
|
||||
} break;
|
||||
|
||||
case Type::Tag::Array: {
|
||||
for(size_t i = 0; i < array_length(source); ++i) {
|
||||
copy(array_cell(source, i), array_cell(destination, i));
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type::Tag::List: {
|
||||
auto& src_list = *reinterpret_cast<Type::List*>(source.address);
|
||||
auto& dst_list = *reinterpret_cast<Type::List*>(destination.address);
|
||||
|
||||
drop(destination);
|
||||
rawlist_reserve(dst_list.data, type_size(type_inner(source.type)), src_list.data.capacity);
|
||||
dst_list.data.length = src_list.data.length;
|
||||
//dst_list.data = allocate(type_inner(source.type), src_list.capacity);
|
||||
|
||||
for(size_t i = 0; i < src_list.data.length; ++i) {
|
||||
copy(list_at(source, i), list_at(destination, i));
|
||||
@ -273,6 +325,8 @@ bool copy(Reference src, Reference dst)
|
||||
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);
|
||||
|
||||
@ -300,6 +354,20 @@ bool copy(Reference src, Reference dst)
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference resolve_addr(Reference addr)
|
||||
{
|
||||
Reference result = addr;
|
||||
if(result.type == Type::Tag::Null) {
|
||||
if(result.address != nullptr) {
|
||||
result = *reinterpret_cast<Reference*>(result.address);
|
||||
}
|
||||
else {
|
||||
result = Reference {0};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Varying //
|
||||
|
||||
@ -677,6 +745,15 @@ extern "C" size_t record_length(Reference addr)
|
||||
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};
|
||||
@ -890,6 +967,7 @@ extern "C" size_t schema_bind(Reference addr, size_t id)
|
||||
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));
|
||||
|
@ -24,9 +24,11 @@ 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 type_hasinner(size_t type_id);
|
||||
|
||||
//extern "C" size_t schema_bind(Reference addr, size_t id);
|
||||
|
||||
extern "C" size_t name_indexof(const uint8_t* bytes, size_t length);
|
||||
std::string name_keyof_internal(size_t index);
|
||||
@ -37,6 +39,8 @@ extern "C" Reference acquire(size_t type_id);
|
||||
extern "C" void release(Reference id);
|
||||
extern "C" bool copy(Reference src, Reference dst);
|
||||
|
||||
Reference resolve_addr(Reference addr);
|
||||
|
||||
// Varying //
|
||||
extern "C" Reference varying_get(Reference addr);
|
||||
extern "C" void varying_set(Reference addr, Reference source);
|
||||
@ -93,6 +97,7 @@ extern "C" void list_reserve(Reference addr, size_t capacity);
|
||||
|
||||
// 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);
|
||||
|
@ -37,6 +37,9 @@ extern "C" {
|
||||
pub fn type_outer(type_id:usize, key:usize) -> usize;
|
||||
pub fn type_inner(type_id:usize) -> usize;
|
||||
pub fn type_key(type_id:usize) -> usize;
|
||||
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_size(type_id:usize) -> usize;
|
||||
|
||||
@ -92,6 +95,7 @@ extern "C" {
|
||||
//pub fn list_count(addr:Reference, target:Reference, start:usize) -> usize;
|
||||
|
||||
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;
|
||||
|
@ -111,7 +111,7 @@ public:
|
||||
return find_header(index) != m_headers.size();
|
||||
}
|
||||
|
||||
const T* get(size_t index) const
|
||||
T* get(size_t index)
|
||||
{
|
||||
size_t header_index = find_header(index);
|
||||
if(header_index < m_headers.size()) {
|
||||
|
@ -77,6 +77,7 @@ struct SchemaBinding {
|
||||
size_t binding;
|
||||
size_t alignment;
|
||||
size_t size;
|
||||
size_t references;
|
||||
|
||||
SparseList<size_t> map;
|
||||
std::vector<Row> data;
|
||||
|
97
src/tests.rs
97
src/tests.rs
@ -62,7 +62,7 @@ fn integer_set_get()
|
||||
fn block_initialize()
|
||||
{
|
||||
let value = Block::new(8);
|
||||
assert_eq!(8, value.length(), "Block::new(8) has length of 8.");
|
||||
assert_eq!(8, value.size(), "Block::new(8) has length of 8.");
|
||||
assert_eq!(vec![0;8], value.get(), "Block::new(8) has value of 0.");
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ fn block_set_get()
|
||||
fn sequence_initialize()
|
||||
{
|
||||
let value = Sequence::new();
|
||||
assert_eq!(0, value.length(), "Sequence::new() has length 0.");
|
||||
assert_eq!(0, value.size(), "Sequence::new() has length 0.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -86,7 +86,7 @@ fn sequence_set_get_raw()
|
||||
{
|
||||
let mut value = Sequence::new();
|
||||
value.set_raw(vec![0, 1, 2, 3, 2, 1]);
|
||||
assert_eq!(6, value.length(), "Sequence.set_raw([0,1,2,3,2,1]) has length 6.");
|
||||
assert_eq!(6, value.size(), "Sequence.set_raw([0,1,2,3,2,1]) has length 6.");
|
||||
assert_eq!(vec![0,1,2,3,2,1], value.get_raw(), "Sequence.set_raw([0,1,2,3,2,1]) produces value [0,1,2,3,2,1].");
|
||||
}
|
||||
|
||||
@ -95,10 +95,46 @@ fn sequence_set_get_str()
|
||||
{
|
||||
let mut value = Sequence::new();
|
||||
value.set("hello");
|
||||
assert_eq!(5, value.length(), "Sequence.set(hello) has length 5.");
|
||||
assert_eq!(5, value.size(), "Sequence.set(hello) has length 5.");
|
||||
assert_eq!(String::from("hello"), value.get(), "Sequence.set(hello) produces value hello.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_from()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_with()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_length()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_at()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_set()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_initialize()
|
||||
{
|
||||
@ -147,7 +183,16 @@ fn list_clear()
|
||||
#[test]
|
||||
fn list_insert()
|
||||
{
|
||||
|
||||
let mut list = List::with(natural(), vec![
|
||||
*Natural::with(21),
|
||||
*Natural::with(23),
|
||||
*Natural::with(24),
|
||||
]);
|
||||
assert_eq!(3, list.length(), "List initialized with 3 elements has length of 3.");
|
||||
list.insert(1, *Natural::with(22));
|
||||
assert_eq!(21, list.length(), "First element has value of 21.");
|
||||
assert_eq!(22, list.length(), "Second element has value of 22.");
|
||||
assert_eq!(23, list.length(), "Third element has value of 23.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -222,3 +267,45 @@ fn list_reserve()
|
||||
list.reserve(capacity);
|
||||
assert_eq!(capacity, list.capacity(), "List has updated capacity.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_from()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_with()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_with_values()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_at()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_set()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schema_initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user