Implement encode/decode, fix bugs, update README with new functions.

This commit is contained in:
yukirij 2023-08-17 23:51:03 -07:00
parent c5d551bde2
commit 7addefd634
22 changed files with 625 additions and 86 deletions

View File

@ -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
View 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(()),
}
}

View File

@ -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)}

View File

@ -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)}
}

View File

@ -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) };

View File

@ -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) } }

View File

@ -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) };

View File

@ -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)}

View File

@ -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(),
}
}
}

View File

@ -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) };

View File

@ -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;

View File

@ -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)}

View File

@ -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);

View File

@ -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(())
}

View File

@ -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

View File

@ -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"); }
}
}

View File

@ -39,13 +39,29 @@ 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);
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));
@ -53,6 +69,10 @@ extern "C" size_t type_size(size_t type_id)
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));

View File

@ -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);

View File

@ -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;

View File

@ -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()) {

View File

@ -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;

View File

@ -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()
{
}