Implement Schema encode/decode, reorganize tests, update README.

This commit is contained in:
yukirij 2023-08-24 11:59:47 -07:00
parent 7f49567022
commit cd6342192e
15 changed files with 287 additions and 192 deletions

View File

@ -621,8 +621,6 @@ Returns the key of the element at the specified index.
## Schema ## Schema
Definition of an abstract structure composed of named items. Definition of an abstract structure composed of named items.
> Encode/decode not implemented.
`with(members:Vec<(&str, usize)>) -> Schema` `with(members:Vec<(&str, usize)>) -> Schema`
Produces a schema with the provided member assignments. Produces a schema with the provided member assignments.

View File

@ -14,25 +14,27 @@ use crate::{
Varying, Varying,
Boolean, Boolean,
Natural, Integer, Natural, Integer,
//Significant,
Block, Sequence, Block, Sequence,
Array, List, Array, List,
Record, Record,
Schema,
}; };
use crate::util; use crate::util;
pub fn encode_tag(addr:Reference) -> Vec<u8> pub fn encode_tag(type_id:usize) -> Vec<u8>
{ {
let mut type_id = addr.class; let mut tid = type_id;
let mut result = Vec::<u8>::new(); let mut result = Vec::<u8>::new();
let mut remaining :usize = 1; let mut remaining :usize = 1;
while remaining > 0 { while remaining > 0 {
result.append(&mut util::pack_natural(unsafe {type_key(type_id)} as u64)); result.append(&mut util::pack_natural(unsafe {type_key(tid)} as u64));
remaining -= 1; remaining -= 1;
if remaining == 0 { if remaining == 0 {
remaining += unsafe {type_hasinner(type_id)}; remaining += unsafe {type_hasinner(tid)};
} }
type_id = unsafe {type_inner(type_id)}; tid = unsafe {type_inner(tid)};
} }
return result; return result;
} }
@ -54,6 +56,9 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
tag::INTEGER => { tag::INTEGER => {
result.append(&mut &mut util::pack_integer(Integer::from(addr).unwrap().get() as i64)); result.append(&mut &mut util::pack_integer(Integer::from(addr).unwrap().get() as i64));
} }
tag::SIGNIFICANT => {
result.append(&mut vec![0]);
}
tag::BLOCK => { tag::BLOCK => {
result.append(&mut Block::from(addr).unwrap().get()); result.append(&mut Block::from(addr).unwrap().get());
} }
@ -119,6 +124,19 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
} }
} }
} }
tag::SCHEMA => {
let data = Schema::from(addr).unwrap();
result.append(&mut util::pack_natural(data.length() as u64));
for i in 0..data.length() {
result.append(&mut encode_tag(data.get(i).unwrap()));
let mut key = Vec::from(data.keyof(i).unwrap().as_bytes());
result.append(&mut util::pack_natural(key.len() as u64));
result.append(&mut key);
}
}
_ => { } _ => { }
} }
return result; return result;
@ -126,7 +144,7 @@ pub fn encode_data(addr:Reference) -> Vec<u8>
pub fn encode(addr:Reference) -> Vec<u8> pub fn encode(addr:Reference) -> Vec<u8>
{ {
let mut result = encode_tag(addr); let mut result = encode_tag(addr.class);
result.append(&mut encode_data(addr)); result.append(&mut encode_data(addr));
return result; return result;
} }
@ -173,6 +191,9 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Typ
tag::INTEGER => { tag::INTEGER => {
return Ok(Type::Integer(Integer::with(unpack_integer(data, index)))); return Ok(Type::Integer(Integer::with(unpack_integer(data, index))));
} }
tag::SIGNIFICANT => {
return Err(())
}
tag::BLOCK => { tag::BLOCK => {
let size = unsafe {type_innerkey(type_id)}; let size = unsafe {type_innerkey(type_id)};
let mut bytes = Vec::<u8>::with_capacity(size); let mut bytes = Vec::<u8>::with_capacity(size);
@ -281,6 +302,36 @@ pub fn decode_data(data:&Vec<u8>, type_id:usize, index:&mut usize) -> Result<Typ
Err(_) => Err(()), Err(_) => Err(()),
} }
} }
tag::SCHEMA => {
let mut result = Schema::new();
let length = util::unpack_natural(data, index) as usize;
for _ in 0..length {
let class :usize;
match decode_tag(data, index) {
Ok(tag) => { class = tag; }
Err(_) => { return Err(()); }
}
let key_length = util::unpack_natural(data, index) as usize;
let mut key_bytes = Vec::<u8>::with_capacity(key_length);
for _ in 0..key_length {
if *index < data.len() {
key_bytes.push(data[*index]);
*index += 1;
}
else {
return Err(());
}
}
let key = String::from_utf8(key_bytes).unwrap();
result.assign(&key, class);
}
return Ok(Type::Schema(result));
}
_ => { } _ => { }
} }

View File

@ -102,7 +102,7 @@ impl Schema {
unsafe { schema_unmap(self.addr, key_index); } unsafe { schema_unmap(self.addr, key_index); }
} }
pub fn indexof(&mut self, key:&str) -> Option<usize> pub fn indexof(&self, key:&str) -> Option<usize>
{ {
let key_index = name_indexof(key); let key_index = name_indexof(key);
let result = unsafe {schema_indexof(self.addr, key_index)}; let result = unsafe {schema_indexof(self.addr, key_index)};
@ -114,7 +114,7 @@ impl Schema {
} }
} }
pub fn keyof(&mut self, index:usize) -> Option<String> pub fn keyof(&self, index:usize) -> Option<String>
{ {
let result = unsafe {schema_keyof(self.addr, index)}; let result = unsafe {schema_keyof(self.addr, index)};
if result != 0 { if result != 0 {

View File

@ -20,14 +20,15 @@ pub fn test() {
]).bind(MAGAZINE_ROW); ]).bind(MAGAZINE_ROW);
// define schema "Magazine" // define schema "Magazine"
Schema::with(vec![ let magazine = Schema::with(vec![
("Capacity", natural()), ("Capacity", natural()),
("Quantity", natural()), ("Quantity", natural()),
("Content", list(record(MAGAZINE_ROW))), ("Content", list(record(MAGAZINE_ROW))),
]).bind(MAGAZINE); ]);
magazine.bind(MAGAZINE);
// create record "Magazine" // create record "Magazine"
let data = Record::with(MAGAZINE, vec![ let _data = Record::with(MAGAZINE, vec![
("Capacity", *Natural::with(30)), ("Capacity", *Natural::with(30)),
("Quantity", *Natural::with(25)), ("Quantity", *Natural::with(25)),
("Content", *List::with(record(MAGAZINE_ROW), vec![ ("Content", *List::with(record(MAGAZINE_ROW), vec![
@ -43,10 +44,10 @@ pub fn test() {
]).unwrap(); ]).unwrap();
// encode record // encode record
let out = encode(*data); let out = encode(*magazine);
// write encoding to file // write encoding to file
let mut file = File::create("dat.szn").unwrap(); let mut file = File::create("target/dat.szn").unwrap();
file.write_all(&out).ok(); file.write_all(&out).ok();
// print hex series of encoding // print hex series of encoding
@ -54,6 +55,19 @@ pub fn test() {
for byte in &out { for byte in &out {
print!("{:02x} ", *byte); print!("{:02x} ", *byte);
} println!(""); } println!("");
match decode(&out, &mut 0) {
Ok(t) => match t {
Type::Schema(data) => {
println!("len: {}", data.length());
for i in 0..data.length() {
println!("'{}': {} ({:02x})", data.keyof(i).unwrap(), data.get(i).unwrap(), kind(data.get(i).unwrap()));
}
}
_ => { println!("not expected"); }
}
Err(_) => { println!("failed"); }
}
} }
#[cfg(test)] #[cfg(test)]

38
src/tests/array.rs Normal file
View File

@ -0,0 +1,38 @@
use crate::*;
#[test]
fn array_initialize()
{
let _data = Array::new(4, natural());
}
#[test]
fn array_from()
{
}
#[test]
fn array_with()
{
}
#[test]
fn array_length()
{
}
#[test]
fn array_at()
{
}
#[test]
fn array_set()
{
}

17
src/tests/block.rs Normal file
View File

@ -0,0 +1,17 @@
use crate::*;
#[test]
fn block_initialize()
{
let value = Block::new(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.");
}
#[test]
fn block_set_get()
{
let mut value = Block::new(4);
value.set(vec![1, 2, 3, 4]);
assert_eq!(vec![1, 2, 3, 4], value.get(), "Block::set([1,2,3,4]) has value of [1,2,3,4].");
}

25
src/tests/boolean.rs Normal file
View File

@ -0,0 +1,25 @@
use crate::*;
#[test]
fn boolean_initialize()
{
let value = Boolean::new();
assert_eq!(false, value.get(), "Boolean::new() produces value of false.");
}
#[test]
fn boolean_with()
{
assert_eq!(false, Boolean::with(false).get(), "Boolean::with(false) produces value of false.");
assert_eq!(true, Boolean::with(true).get(), "Boolean::with(true) produces value of true.");
}
#[test]
fn boolean_set_get()
{
let mut value = Boolean::new();
value.set(true);
assert_eq!(true, value.get(), "Boolean.set(true) produces value of true.");
value.set(false);
assert_eq!(false, value.get(), "Boolean.set(false) produces value of false.");
}

18
src/tests/integer.rs Normal file
View File

@ -0,0 +1,18 @@
use crate::*;
#[test]
fn integer_initialize()
{
let value = Integer::new();
assert_eq!(0, value.get(), "Integer::new() produces value of 0.");
}
#[test]
fn integer_set_get()
{
let mut value = Integer::new();
value.set(-273);
assert_eq!(-273, value.get(), "Integer.set(-273) produces value of -273.");
value.set(100);
assert_eq!(100, value.get(), "Integer.set(100) produces value of 100.");
}

View File

@ -1,140 +1,5 @@
use crate::*; use crate::*;
#[test]
fn boolean_initialize()
{
let value = Boolean::new();
assert_eq!(false, value.get(), "Boolean::new() produces value of false.");
}
#[test]
fn boolean_with()
{
assert_eq!(false, Boolean::with(false).get(), "Boolean::with(false) produces value of false.");
assert_eq!(true, Boolean::with(true).get(), "Boolean::with(true) produces value of true.");
}
#[test]
fn boolean_set_get()
{
let mut value = Boolean::new();
value.set(true);
assert_eq!(true, value.get(), "Boolean.set(true) produces value of true.");
value.set(false);
assert_eq!(false, value.get(), "Boolean.set(false) produces value of false.");
}
#[test]
fn natural_initialize()
{
let value = Natural::new();
assert_eq!(0, value.get(), "Natural::new() produces value of 0.");
}
#[test]
fn natural_set_get()
{
let mut value = Natural::new();
value.set(12);
assert_eq!(12, value.get(), "Natural.set(12) produces value of 12.");
value.set(38695);
assert_eq!(38695, value.get(), "Natural.set(38695) produces value of 38695.");
}
#[test]
fn integer_initialize()
{
let value = Integer::new();
assert_eq!(0, value.get(), "Integer::new() produces value of 0.");
}
#[test]
fn integer_set_get()
{
let mut value = Integer::new();
value.set(-273);
assert_eq!(-273, value.get(), "Integer.set(-273) produces value of -273.");
value.set(100);
assert_eq!(100, value.get(), "Integer.set(100) produces value of 100.");
}
#[test]
fn block_initialize()
{
let value = Block::new(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.");
}
#[test]
fn block_set_get()
{
let mut value = Block::new(4);
value.set(vec![1, 2, 3, 4]);
assert_eq!(vec![1, 2, 3, 4], value.get(), "Block::set([1,2,3,4]) has value of [1,2,3,4].");
}
#[test]
fn sequence_initialize()
{
let value = Sequence::new();
assert_eq!(0, value.size(), "Sequence::new() has length 0.");
}
#[test]
fn sequence_set_get_raw()
{
let mut value = Sequence::new();
value.set_raw(vec![0, 1, 2, 3, 2, 1]);
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].");
}
#[test]
fn sequence_set_get_str()
{
let mut value = Sequence::new();
value.set("hello");
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] #[test]
fn list_initialize() fn list_initialize()
{ {
@ -267,45 +132,3 @@ fn list_reserve()
list.reserve(capacity); list.reserve(capacity);
assert_eq!(capacity, list.capacity(), "List has updated 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()
{
}

10
src/tests/mod.rs Normal file
View File

@ -0,0 +1,10 @@
mod boolean;
mod natural;
mod integer;
mod block;
mod sequence;
mod array;
mod list;
mod sparse;
mod schema;
mod record;

18
src/tests/natural.rs Normal file
View File

@ -0,0 +1,18 @@
use crate::*;
#[test]
fn natural_initialize()
{
let value = Natural::new();
assert_eq!(0, value.get(), "Natural::new() produces value of 0.");
}
#[test]
fn natural_set_get()
{
let mut value = Natural::new();
value.set(12);
assert_eq!(12, value.get(), "Natural.set(12) produces value of 12.");
value.set(38695);
assert_eq!(38695, value.get(), "Natural.set(38695) produces value of 38695.");
}

41
src/tests/record.rs Normal file
View File

@ -0,0 +1,41 @@
use crate::*;
#[test]
fn record_initialize()
{
Schema::with(vec![
]).bind(20);
let _data = Record::new(20);
}
#[test]
fn record_from()
{
}
#[test]
fn record_with()
{
}
#[test]
fn record_with_values()
{
}
#[test]
fn record_at()
{
}
#[test]
fn record_set()
{
}

8
src/tests/schema.rs Normal file
View File

@ -0,0 +1,8 @@
use crate::*;
#[test]
fn schema_initialize()
{
let _data = Schema::new();
}

26
src/tests/sequence.rs Normal file
View File

@ -0,0 +1,26 @@
use crate::*;
#[test]
fn sequence_initialize()
{
let value = Sequence::new();
assert_eq!(0, value.size(), "Sequence::new() has length 0.");
}
#[test]
fn sequence_set_get_raw()
{
let mut value = Sequence::new();
value.set_raw(vec![0, 1, 2, 3, 2, 1]);
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].");
}
#[test]
fn sequence_set_get_str()
{
let mut value = Sequence::new();
value.set("hello");
assert_eq!(5, value.size(), "Sequence.set(hello) has length 5.");
assert_eq!(String::from("hello"), value.get(), "Sequence.set(hello) produces value hello.");
}

8
src/tests/sparse.rs Normal file
View File

@ -0,0 +1,8 @@
use crate::*;
#[test]
fn sparse_initialize()
{
let data = Sparse::new(natural());
assert_eq!(0, data.length(), "New list has length of 0.");
}