diff --git a/README.md b/README.md index 5772da9..d21a84c 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,8 @@ Copy the contents of an objcet to another location, keeping the original. --- +## Encoding +Encoding converts data between runtime memory and binary serialization. `encode(refer:Reference) -> Vec` `encode_raw(refer:Reference) -> Vec` @@ -138,6 +140,12 @@ let b = Boolean::with(true); ``` --- +`detatch()` + +Prevents an allocated object from being dropped when the interface goes out of scope. + +--- + `*Dereference -> Reference` ``` @@ -151,7 +159,7 @@ Stores a value of any other type. `is_null() -> bool` -Specifies whether or not the variable contains a object. +Indicates whether or not the variable contains a object. --- @@ -175,6 +183,12 @@ var.set(*Sequence::with("Hello!")); ``` --- +`clear()` + +Removes the contained object. + +--- + ## Boolean Stores the value true or false. @@ -249,16 +263,26 @@ value.set(-273); ``` --- +## Decimal +Stores a constant-magnitude number with whole and decimal components. + +> Not implemented. ## Significant Stores a fixed-precision, variable-magnitude number. +> Not implemented. + `get() -> f64` +Returns the contained value. + --- `set(value:f64)` +Replaces the contained value. + --- @@ -267,61 +291,129 @@ Constant-sized series of bytes. `new(size:usize) -> Block` +Produces a + --- -`length() -> usize` +`size() -> usize` + +Returns the size of the allocated block. --- `get() -> Vec` +Returns the contents of the block. + +--- + +`at(index:usize) -> u8` + +Returns the byte at the specified index or zero if out of bounds. + --- `set(data:Vec)` +Replaces the contents of the block up to the length of the parameter. + +--- + +`set_at(index:usize, data:u8)` + +Replaces the byte at the given index. + --- ## Sequence Variable-sized series of bytes. -`length() -> usize` +`capacity() -> usize` + +Returns the memory capacity of the sequeunce. + +--- + +`size() -> usize` + +Returns the length of the series. --- `get() -> String` +Returns a UTF-8 string representation of the series. + --- `get_raw() -> Vec` +Returns the contents of the series. + +--- + +`at(index:usize) -> u8` + +Returns the byte at the specified index or zero if out of bounds. + --- `set(data:&str)` +Replaces the contents with the byte representation of a string. + --- `set_raw(data:Vec)` +Replaces the contents with a series of bytes. + +--- + +`set_at(index:usize, data:u8)` + +Replaces a byte at the given index. + +--- + +`reserve(capacity:usize)` + +Reallocates the sequeunce to have capacity not less than the specified size. + --- ## Array Constant-sized, ordered collection of items. -`new(size:usize, type_id:usize) -> Array` +`new(length:usize, type_id:usize) -> Array` + +Produces a new array of given type and length. --- `length() -> usize` +Returns the length of the array. + --- `at(index:usize) -> Reference` +Returns a reference to the element at the given index or a null reference if out of bounds. + --- -`set(index:usize, refer:Reference)` +`set(index:usize, source:Reference)` + +Replaces the element at the given index with a copy of the source. + +--- + +`kindof() -> usize` + +Returns the type identifier of the contents. --- @@ -331,96 +423,170 @@ Variable-sized, ordered collection of items. `new(type_id:usize) -> List` ---- - -`length() -> usize` +Produces a new list of the given type. --- `capacity() -> usize` +Returns the allocated capacity of the list. + +--- + +`length() -> usize` + +Returns the length of the list. + --- `at(index:usize) -> Reference` ---- - -`set(index:usize, refer:Reference)` +Returns the object at the given index or a null reference if out of bounds. --- -`insert(index:usize, refer:Reference)` +`set(index:usize, source:Reference)` + +Replaces the object at the given index with a copy of the source. + +--- + +`insert(index:usize, source:Reference)` + +Inserts a copy of the source at a given index. --- `remove(index:usize)` +Removes the object at the given index from the list. + --- `reserve(capacity:usize)` +Reallocates the list to have capacity not less than the specified size. + --- `clear()` +Removes all elements from the list. + --- ## Schema Definition of an abstract structure composed of named items. +`with(members:Vec<(&str, usize)>) -> Schema` + +Produces a schema with the provided member assignments. + +--- + `get(index:usize) -> usize` +Returns the type identifier of the given index or zero if out of bounds. + --- `add(type_id:usize) -> usize` +Appends a member of the specified type to the schema. + --- `remove(index:usize)` +Removes the member at the given index from the schema. + --- `assign(key:&str, type_id:usize) -> usize` +Appends a member of the specified type to the schema and maps the provided string to that index. + --- `map(key:&str, index:usize)` +Maps a string to the specified index. + --- `unmap(key:&str)` +Removes a mapping of the specified string from the schema. + --- `clear()` +Removes all members and mappings from the schema. + --- `bind(id:usize)` +Submits the schema to the + --- ## Record Instance of a schema. -`new(schema_id:usize) -> Record` +`new(schema_id:usize) -> Result` + +Produces a new record of the provided schema. + +--- + +`with(schema_id:usize, data:Vec<(&str, Reference)>) -> Result` + +Produces a record of the provided schema and keyed assignments. + +--- + +`with_values(schema_id:usize, data:Vec) -> Result` + +Produces a record of the provided schema and indexed assignments. + +--- + +`length() -> usisze` + +Returns the number of elements in the record. --- `at(index:usize) -> Reference` +Returns a reference to the member at the given index. + --- `set(index:usize, source:Reference)` +Replaces the member at the given index with a copy of the source. + --- `keyof(index:usize) -> String` +Returns the string mapped to the specified index or an empty string if no mapping exists. + --- `indexof(key:&str) -> usize` +Returns the index of a mapped string or the number of elements in the record if no mapping exists. + +--- + +`kindof(index:usize) -> usize` + +Returns the type identifier of the given index. + --- diff --git a/src/interface/schema.rs b/src/interface/schema.rs index 5acb2c3..6982a79 100644 --- a/src/interface/schema.rs +++ b/src/interface/schema.rs @@ -35,10 +35,10 @@ impl Schema { } } - pub fn with(data:Vec<(&str, usize)>) -> Self + pub fn with(members:Vec<(&str, usize)>) -> Self { let mut obj = Self::new(); - for binding in data { + for binding in members { let (key, type_id) = binding; obj.assign(key, type_id); } diff --git a/src/interface/sequence.rs b/src/interface/sequence.rs index fd8d7e6..cf8bd4d 100644 --- a/src/interface/sequence.rs +++ b/src/interface/sequence.rs @@ -2,7 +2,7 @@ use crate::runtime::{ Reference, acquire, release, type_key, - sequence_length, + sequence_capacity, sequence_length, sequence_clear, sequence_reserve, sequence_get, sequence_insert, @@ -43,7 +43,6 @@ impl Sequence { pub fn with(data:&str) -> Self { let mut obj = Self::new(); - println!("a"); obj.set(data); return obj; } @@ -59,6 +58,11 @@ impl Sequence { unsafe { release(self.addr); } } + pub fn capacity(&self) -> usize + { + unsafe {sequence_capacity(self.addr)} + } + pub fn size(&self) -> usize { unsafe {sequence_length(self.addr)} @@ -67,7 +71,6 @@ 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() { @@ -85,7 +88,6 @@ 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 2780c64..4f0bf11 100644 --- a/src/interface/util.rs +++ b/src/interface/util.rs @@ -10,12 +10,14 @@ pub fn release(addr:runtime::Reference) unsafe {runtime::release(addr)} } -pub fn copy(_dst:runtime::Reference, _src:runtime::Reference) -> Result<(),()> +pub fn copy(dst:runtime::Reference, src:runtime::Reference) -> Result<(),()> { - Err(()) + if unsafe {runtime::copy(dst, src)} { Ok(()) } + else { Err(()) } } -pub fn transfer(_dst:runtime::Reference, _src:runtime::Reference) -> Result<(),()> +pub fn transfer(dst:runtime::Reference, src:runtime::Reference) -> Result<(),()> { - Err(()) + if unsafe {runtime::transfer(dst, src)} { Ok(()) } + else { Err(()) } } diff --git a/src/interface/varying.rs b/src/interface/varying.rs index 892f98e..427a77b 100644 --- a/src/interface/varying.rs +++ b/src/interface/varying.rs @@ -3,6 +3,7 @@ use crate::runtime::{ acquire, release, type_key, varying_get, varying_set, + varying_clear, }; use crate::tag; use super::varying; @@ -51,6 +52,11 @@ impl Varying { unsafe { varying_set(self.addr, source); } } + pub fn clear(&mut self) + { + unsafe { varying_clear(self.addr); } + } + pub fn get(&self) -> Reference { unsafe { varying_get(self.addr) } diff --git a/src/lib.rs b/src/lib.rs index 36f893b..c23d37c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ pub fn test() { ("rec", record(9)), ]).bind(10); - let out = encode(*Record::with(10, vec![ + let rec = Record::with(10, vec![ ("str", *Sequence::with("hello!")), ("int", *Integer::with(-70)), ("bool", *Boolean::with(true)), @@ -27,7 +27,14 @@ pub fn test() { ("nat", *Natural::with(8)), ("pass", *Block::with(6, vec![1, 2, 3, 4, 5, 6])), ]).unwrap()), - ]).unwrap()); + ]).unwrap(); + + let out = encode(*rec); + print!("[{}]: ", out.len()); + for byte in &out { + print!("{:02x} ", *byte); + } println!("\n"); + match decode(&out, &mut 0) { Ok(ty) => match ty { Type::Record(rec) => { diff --git a/src/runtime/lib.cc b/src/runtime/lib.cc index 11e440b..7e9be48 100644 --- a/src/runtime/lib.cc +++ b/src/runtime/lib.cc @@ -129,7 +129,10 @@ extern "C" size_t type_hasinner(size_t type_id) extern "C" size_t name_indexof(const uint8_t* bytes, size_t length) { std::string str(reinterpret_cast(bytes), length); - return DB_NAME.indexof(str); + if(str.size() > 0) { + return DB_NAME.indexof(str); + } + return 0; } extern "C" Str name_keyof(size_t index) @@ -243,7 +246,7 @@ extern "C" void release(Reference addr) } } -bool copy(Reference src, Reference dst) +extern "C" bool copy(Reference dst, Reference src) { if(src.address != dst.address) { Reference source = src; @@ -271,6 +274,8 @@ bool copy(Reference src, Reference dst) // copy data into destination if(source.type == destination.type) { + drop(destination); + switch(type_key(destination.type)) { case Type::Tag::Null: { } break; @@ -288,11 +293,12 @@ bool copy(Reference src, Reference dst) rawlist_clear(dst_seq.data); rawlist_reserve(dst_seq.data, sizeof(uint8_t), src_seq.data.length); memcpy(dst_seq.data.data, src_seq.data.data, sizeof(uint8_t) * src_seq.data.length); + dst_seq.data.length = src_seq.data.length; } break; case Type::Tag::Array: { for(size_t i = 0; i < array_length(source); ++i) { - copy(array_cell(source, i), array_cell(destination, i)); + copy(array_cell(destination, i), array_cell(source, i)); } } break; @@ -300,12 +306,11 @@ bool copy(Reference src, Reference dst) 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; for(size_t i = 0; i < src_list.data.length; ++i) { - copy(list_at(source, i), list_at(destination, i)); + copy(list_at(destination, i), list_at(source, i)); } } break; @@ -316,7 +321,7 @@ bool copy(Reference src, Reference dst) for(size_t i = 0; i < binding->data.size(); ++i) { auto src_cell = record_cell(source, i); auto dst_cell = record_cell(destination, i); - copy(src_cell, dst_cell); + copy(dst_cell, src_cell); } } } break; @@ -354,6 +359,43 @@ bool copy(Reference src, Reference dst) return false; } +extern "C" bool transfer(Reference dst, Reference src) +{ + if(src.address != dst.address) { + Reference source = src; + Reference destination = dst; + + // dereference varying data + if(type_key(src.type) == Type::Tag::Varying) { + source = *reinterpret_cast(src.address); + } + + // prepare destination for varying data + if(type_key(dst.type) == Type::Tag::Varying) { + auto& dest_ref = *reinterpret_cast(dst.address); + + // determine if memory can be reused, otherwise free and reallocate + if(source.type != dest_ref.type) { + if(dest_ref.address != nullptr) { + free(dest_ref.address); + dest_ref.type = Type::Tag::Null; + dest_ref.address = nullptr; + } + dest_ref = acquire(source.type); + } + } + + // copy data into destination + if(source.type == destination.type) { + drop(destination); + memcpy(destination.address, source.address, type_size(source.type)); + memset(source.address, 0, type_size(source.type)); + return true; + } + } + return false; +} + Reference resolve_addr(Reference addr) { Reference result = addr; @@ -394,7 +436,7 @@ extern "C" void varying_set(Reference addr, Reference source) var.address = allocate(source.type, 1); } - copy(source, var); + copy(var, source); } extern "C" void varying_clear(Reference addr) @@ -476,6 +518,12 @@ extern "C" void block_set(Reference addr, size_t index, uint8_t value) // Sequence // +extern "C" size_t sequence_capacity(Reference addr) +{ + Type::Sequence& seq = *reinterpret_cast(addr.address); + return seq.data.capacity; +} + extern "C" size_t sequence_length(Reference addr) { Type::Sequence& seq = *reinterpret_cast(addr.address); @@ -567,7 +615,7 @@ extern "C" void array_update(Reference addr, size_t index, Reference source) varying_set(cell, source); } else { - copy(source, cell); + copy(cell, source); } } @@ -658,7 +706,7 @@ extern "C" void list_insert(Reference addr, size_t index, Reference source) varying_set(list_cell(addr, index), source); } else { - copy(source, list_cell(addr, index)); + copy(list_cell(addr, index), source); } } @@ -684,7 +732,7 @@ extern "C" void list_update(Reference addr, size_t index, Reference source) varying_set(list_cell(addr, index), source); } else { - copy(source, list_cell(addr, index)); + copy(list_cell(addr, index), source); } } } @@ -784,7 +832,7 @@ extern "C" void record_update(Reference addr, size_t index, Reference source) if(index < binding->data.size()) { destination.type = binding->data[index].type; destination.address = addr.address + binding->data[index].offset; - copy(source, destination); + copy(destination, source); } } } diff --git a/src/runtime/lib.h b/src/runtime/lib.h index 86ad74f..3c06dde 100644 --- a/src/runtime/lib.h +++ b/src/runtime/lib.h @@ -27,6 +27,7 @@ extern "C" size_t type_key(size_t id); extern "C" size_t type_innerkey(size_t id); extern "C" size_t type_size(size_t type_id); size_t type_alignment(size_t type_id); +extern "C" size_t kind_hasinner(size_t kind); extern "C" size_t type_hasinner(size_t type_id); @@ -37,7 +38,8 @@ extern "C" Str name_keyof(size_t index); uint8_t* allocate(size_t type_id, size_t count); extern "C" Reference acquire(size_t type_id); extern "C" void release(Reference id); -extern "C" bool copy(Reference src, Reference dst); +extern "C" bool copy(Reference dst, Reference src); +extern "C" bool transfer(Reference dst, Reference src); Reference resolve_addr(Reference addr); @@ -64,6 +66,7 @@ extern "C" uint8_t block_get(Reference addr, size_t index); extern "C" void block_set(Reference addr, size_t index, uint8_t value); // String // +extern "C" size_t sequence_capacity(Reference addr); extern "C" size_t sequence_length(Reference addr); extern "C" uint8_t sequence_get(Reference addr, size_t index); extern "C" void sequence_clear(Reference addr); diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index c9b68e0..590bbb0 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -34,6 +34,9 @@ extern "C" { pub fn acquire(type_id:usize) -> Reference; pub fn release(addr:Reference); + pub fn copy(dst:Reference, src:Reference) -> bool; + pub fn transfer(dst:Reference, src:Reference) -> bool; + 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; @@ -64,6 +67,7 @@ extern "C" { pub fn block_set(addr:Reference, index:usize, data:u8); pub fn block_get(addr:Reference, index:usize) -> u8; + pub fn sequence_capacity(addr:Reference) -> usize; pub fn sequence_length(addr:Reference) -> usize; pub fn sequence_get(addr:Reference, index:usize) -> u8; pub fn sequence_clear(addr:Reference);