From 7addefd634d76f16ba00a64f1314a0ee437a9490 Mon Sep 17 00:00:00 2001 From: yukirij Date: Thu, 17 Aug 2023 23:51:03 -0700 Subject: [PATCH] Implement encode/decode, fix bugs, update README with new functions. --- README.md | 32 +++++-- src/encoding/mod.rs | 192 ++++++++++++++++++++++++++++++++++++++ src/interface/array.rs | 11 +++ src/interface/block.rs | 20 +++- src/interface/boolean.rs | 11 +++ src/interface/builder.rs | 5 +- src/interface/integer.rs | 11 +++ src/interface/list.rs | 11 +++ src/interface/mod.rs | 26 +++++- src/interface/natural.rs | 11 +++ src/interface/record.rs | 39 +++++--- src/interface/schema.rs | 11 +++ src/interface/sequence.rs | 23 ++++- src/interface/util.rs | 10 ++ src/interface/varying.rs | 11 +++ src/lib.rs | 76 ++++++--------- src/runtime/lib.cc | 100 +++++++++++++++++--- src/runtime/lib.h | 7 +- src/runtime/mod.rs | 4 + src/runtime/sparselist.h | 2 +- src/runtime/type.h | 1 + src/tests.rs | 97 ++++++++++++++++++- 22 files changed, 625 insertions(+), 86 deletions(-) create mode 100644 src/encoding/mod.rs diff --git a/README.md b/README.md index ad0a214..5772da9 100644 --- a/README.md +++ b/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` -`encode_raw(refer:Reference) -> Vec` +`encode_raw(refer:Reference) -> Vec` +`encode_tag(refer:Reference) -> Vec` Serializes an object into binary encoding. The raw variant does not produce a tag prefix for the root object. -> Not implemented --- -`decode(data:Vec) -> Result` -`decode_raw(data:Vec, type_id:usize) -> Result` +`decode(data:&Vec, index:&mut usize) -> Result` +`decode_raw(data:&Vec, type_id:usize, index:&mut usize) -> Result` +`decode_tag(data:&Vec, index:&mut usize) -> Result` 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 diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs new file mode 100644 index 0000000..78eb740 --- /dev/null +++ b/src/encoding/mod.rs @@ -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 +{ + let mut type_id = addr.class; + let mut result = Vec::::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 +{ + let mut result = Vec::::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 +{ + let mut result = encode_tag(addr); + result.append(&mut encode_data(addr)); + return result; +} + +pub fn decode_tag(data:&Vec, index:&mut usize) -> Result +{ + let mut tags = Vec::::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, type_id:usize, index:&mut usize) -> Result +{ + 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::::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::::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, index:&mut usize) -> Result +{ + return match decode_tag(data, index) { + Ok(type_id) => decode_data(data, type_id, index), + _ => Err(()), + } +} diff --git a/src/interface/array.rs b/src/interface/array.rs index 4ea1064..729712c 100644 --- a/src/interface/array.rs +++ b/src/interface/array.rs @@ -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)} diff --git a/src/interface/block.rs b/src/interface/block.rs index 1bb9791..5bb41d4 100644 --- a/src/interface/block.rs +++ b/src/interface/block.rs @@ -31,7 +31,25 @@ impl Block { } } - pub fn length(&self) -> usize + pub fn with(size:usize, data:Vec) -> 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)} } diff --git a/src/interface/boolean.rs b/src/interface/boolean.rs index c9b29e2..fbf57e1 100644 --- a/src/interface/boolean.rs +++ b/src/interface/boolean.rs @@ -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) }; diff --git a/src/interface/builder.rs b/src/interface/builder.rs index 310734d..25e432f 100644 --- a/src/interface/builder.rs +++ b/src/interface/builder.rs @@ -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) } } @@ -32,4 +35,4 @@ pub fn record(schema_id:usize) -> usize { } } -pub fn schema() -> usize { unsafe { runtime::type_outer(0, tag::SCHEMA) } } \ No newline at end of file +pub fn schema() -> usize { unsafe { runtime::type_outer(0, tag::SCHEMA) } } diff --git a/src/interface/integer.rs b/src/interface/integer.rs index f5605bb..31ddfd8 100644 --- a/src/interface/integer.rs +++ b/src/interface/integer.rs @@ -36,6 +36,17 @@ impl Integer { obj.set(value); 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) { diff --git a/src/interface/list.rs b/src/interface/list.rs index fa54c46..9e18545 100644 --- a/src/interface/list.rs +++ b/src/interface/list.rs @@ -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)} diff --git a/src/interface/mod.rs b/src/interface/mod.rs index ef6162c..406b9ea 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -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(), + } + } } diff --git a/src/interface/natural.rs b/src/interface/natural.rs index 007cb51..ad2554e 100644 --- a/src/interface/natural.rs +++ b/src/interface/natural.rs @@ -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) }; diff --git a/src/interface/record.rs b/src/interface/record.rs index 797be74..8b6378c 100644 --- a/src/interface/record.rs +++ b/src/interface/record.rs @@ -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 - { - let result = unsafe {record_keyof(self.addr, index)}; - if result != 0 { - Some(name_keyof(result)) - } - else { - None - } - } - pub fn indexof(&self, key:&str) -> Option { let key_index = name_indexof(key); @@ -120,6 +121,22 @@ impl Record { None } } + + pub fn keyof(&self, index:usize) -> Option + { + 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; diff --git a/src/interface/schema.rs b/src/interface/schema.rs index 483fe73..5acb2c3 100644 --- a/src/interface/schema.rs +++ b/src/interface/schema.rs @@ -44,6 +44,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 { diff --git a/src/interface/sequence.rs b/src/interface/sequence.rs index 53f30b4..fd8d7e6 100644 --- a/src/interface/sequence.rs +++ b/src/interface/sequence.rs @@ -33,14 +33,33 @@ impl Sequence { } } + pub fn with_raw(data:Vec) -> 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) { 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::::new(); + println!("d {}", length); if length > 0 { result.reserve_exact(length); diff --git a/src/interface/util.rs b/src/interface/util.rs index e149786..2780c64 100644 --- a/src/interface/util.rs +++ b/src/interface/util.rs @@ -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(()) +} diff --git a/src/interface/varying.rs b/src/interface/varying.rs index 4422ca3..892f98e 100644 --- a/src/interface/varying.rs +++ b/src/interface/varying.rs @@ -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 diff --git a/src/lib.rs b/src/lib.rs index 67649fe..36f893b 100644 --- a/src/lib.rs +++ b/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"); } } } diff --git a/src/runtime/lib.cc b/src/runtime/lib.cc index a0c0472..11e440b 100644 --- a/src/runtime/lib.cc +++ b/src/runtime/lib.cc @@ -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(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(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(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(source.address); + auto& dst_seq = *reinterpret_cast(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(source.address); auto& dst_list = *reinterpret_cast(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(source.address); auto& dst_schema = *reinterpret_cast(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(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(rawlist_cell(object.map, sizeof(Type::Schema::Mapping), i)); diff --git a/src/runtime/lib.h b/src/runtime/lib.h index 9d3440b..86ad74f 100644 --- a/src/runtime/lib.h +++ b/src/runtime/lib.h @@ -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); diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 68ba17a..c9b68e0 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -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; diff --git a/src/runtime/sparselist.h b/src/runtime/sparselist.h index 5f19760..69dd024 100644 --- a/src/runtime/sparselist.h +++ b/src/runtime/sparselist.h @@ -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()) { diff --git a/src/runtime/type.h b/src/runtime/type.h index 4fb86df..49ea4ab 100644 --- a/src/runtime/type.h +++ b/src/runtime/type.h @@ -77,6 +77,7 @@ struct SchemaBinding { size_t binding; size_t alignment; size_t size; + size_t references; SparseList map; std::vector data; diff --git a/src/tests.rs b/src/tests.rs index e963c94..f98d41d 100644 --- a/src/tests.rs +++ b/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() +{ + +}