Added runtime definitions, reorganized code structure.
This commit is contained in:
parent
4a7700b6ee
commit
b4277d2c6f
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -2,10 +2,17 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "szun"
|
name = "szun"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cc",
|
||||||
"util",
|
"util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -8,3 +8,4 @@ publish = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
stdu = { package = "util", git = "https://git.yukiri.dev/Yukiri/util.git" }
|
stdu = { package = "util", git = "https://git.yukiri.dev/Yukiri/util.git" }
|
||||||
|
cc = "1.0"
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
Project: Kirisame
|
||||||
https://ykr.info/license/
|
https://ykr.info/license/
|
||||||
|
33
README.md
Normal file
33
README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Suzu Data Notation
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
|Tag|Type|Data|
|
||||||
|
|---|---|
|
||||||
|
|**Tags**| | |
|
||||||
|
|01|Null|No data|
|
||||||
|
|02|Boolean|True (02) or False (03)|
|
||||||
|
|**Primitives**| | |
|
||||||
|
|10|Natural|Integer on [0, inf)|
|
||||||
|
|11|Integer|Integer on (-inf, inf)|
|
||||||
|
|12|Decimal|Floating-point number|
|
||||||
|
|13|Complex|Floating-point number with imaginary component|
|
||||||
|
|**Compounds**| | |
|
||||||
|
|1c|Range| |
|
||||||
|
|1d|Char|Natural representing character code|
|
||||||
|
|1e|Block|Fixed-length series of bytes|
|
||||||
|
|1f|String|Variable-length series of bytes|
|
||||||
|
|**Containers**| | |
|
||||||
|
|20|Option| |
|
||||||
|
|21|Set|Unordered, unique collection of elements|
|
||||||
|
|22|Array|Fixed-length, ordered collection of elements|
|
||||||
|
|23|List|Variable-length, ordered collection of elements|
|
||||||
|
|24|Sparse|Discontinuous, ordered collection of elements|
|
||||||
|
|25|Map|Mapping of elements onto elements|
|
||||||
|
|26|Trie|Mapping of string onto elements|
|
||||||
|
|27|Tree| |
|
||||||
|
|28|Graph| |
|
||||||
|
|**Objects**| | |
|
||||||
|
|3e|Record| |
|
||||||
|
|3f|Schema| |
|
||||||
|
|40+|User-defined| |
|
6
build.rs
Normal file
6
build.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
fn main() {
|
||||||
|
cc::Build::new()
|
||||||
|
.cpp(true)
|
||||||
|
.file("src/runtime/lib.cc")
|
||||||
|
.compile("lib_runtime.a");
|
||||||
|
}
|
@ -6,7 +6,14 @@
|
|||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"rust-analyzer.linkedProjects": [
|
"rust-analyzer.linkedProjects": [
|
||||||
|
".\\Cargo.toml",
|
||||||
|
".\\Cargo.toml",
|
||||||
|
".\\Cargo.toml",
|
||||||
".\\Cargo.toml"
|
".\\Cargo.toml"
|
||||||
]
|
],
|
||||||
|
"rust-analyzer.showUnlinkedFileNotification": false,
|
||||||
|
"files.associations": {
|
||||||
|
"xstring": "cpp"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,6 @@
|
|||||||
fn main()
|
fn main()
|
||||||
{
|
{
|
||||||
/* let mut sz = szun::init();
|
let sz = szun::init();
|
||||||
|
//let ptr = sz.boolean();
|
||||||
let ob = sz.string("false");
|
|
||||||
let enc = sz.encode(ob).unwrap();
|
|
||||||
|
|
||||||
for b in enc { print!("{:02x}", b); } print!("\n"); */
|
|
||||||
}
|
}
|
||||||
|
216
src/lib-old.rs
Normal file
216
src/lib-old.rs
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod util;
|
||||||
|
pub mod tag;
|
||||||
|
|
||||||
|
type Handle = u64;
|
||||||
|
pub use tag::Class;
|
||||||
|
|
||||||
|
pub fn init() -> Instance { Instance::new() }
|
||||||
|
|
||||||
|
fn mask_tag (tag:Class) -> Handle { (tag as u64) << 56 }
|
||||||
|
fn unmask_tag (handle:Handle) -> Class { (handle >> 56) as Class }
|
||||||
|
fn handle_id (handle:Handle) -> usize { (handle & !mask_tag(0xff)) as usize }
|
||||||
|
|
||||||
|
struct Container<T> {
|
||||||
|
pub class:usize,
|
||||||
|
pub data:T,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Instance {
|
||||||
|
scope:stdu::Trie<Handle>,
|
||||||
|
type_tree:util::TypeTree,
|
||||||
|
pool_boolean:stdu::Pool<bool>,
|
||||||
|
pool_natural:stdu::Pool<u64>,
|
||||||
|
pool_integer:stdu::Pool<i64>,
|
||||||
|
pool_block:stdu::Pool<Vec<u8>>,
|
||||||
|
pool_string:stdu::Pool<String>,
|
||||||
|
pool_option:stdu::Pool<Container<Option<Handle>>>,
|
||||||
|
pool_array:stdu::Pool<Container<Vec<Handle>>>,
|
||||||
|
pool_list:stdu::Pool<Container<Vec<Handle>>>,
|
||||||
|
pool_sparse:stdu::Pool<Container<stdu::Sparse<Handle>>>,
|
||||||
|
}
|
||||||
|
impl Instance {
|
||||||
|
pub(crate) fn new() -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
scope:stdu::Trie::<Handle>::new(),
|
||||||
|
type_tree:util::TypeTree::new(),
|
||||||
|
pool_boolean:stdu::Pool::<bool>::new(),
|
||||||
|
pool_natural:stdu::Pool::<u64>::new(),
|
||||||
|
pool_integer:stdu::Pool::<i64>::new(),
|
||||||
|
pool_block:stdu::Pool::<Vec<u8>>::new(),
|
||||||
|
pool_string:stdu::Pool::<String>::new(),
|
||||||
|
pool_option:stdu::Pool::<Container<Option<Handle>>>::new(),
|
||||||
|
pool_array:stdu::Pool::<Container<Vec<Handle>>>::new(),
|
||||||
|
pool_list:stdu::Pool::<Container<Vec<Handle>>>::new(),
|
||||||
|
pool_sparse:stdu::Pool::<Container<stdu::Sparse<Handle>>>::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* DATA CONSTRUCTORS */
|
||||||
|
|
||||||
|
pub fn boolean(&mut self, value:bool) -> Handle {
|
||||||
|
mask_tag(tag::BOOLEAN) + self.pool_boolean.add(value) as Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn natural(&mut self, value:u64) -> Handle {
|
||||||
|
mask_tag(tag::NATURAL) + self.pool_natural.add(value) as Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn integer(&mut self, value:i64) -> Handle {
|
||||||
|
mask_tag(tag::INTEGER) + self.pool_integer.add(value) as Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block(&mut self, value:&Vec<u8>) -> Handle {
|
||||||
|
mask_tag(tag::BLOCK) + self.pool_block.add(value.clone()) as Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string(&mut self, value:&str) -> Handle {
|
||||||
|
mask_tag(tag::STRING) + self.pool_string.add(value.to_string()) as Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ENCODING/DECODING */
|
||||||
|
|
||||||
|
fn encode_tags(tags:Vec<Class>) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut encoded = Vec::<u8>::with_capacity(16);
|
||||||
|
for tag in tags {
|
||||||
|
encoded.append(&mut util::pack_natural(tag as u64));
|
||||||
|
}
|
||||||
|
return encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_parts(&self, handle:Handle) -> Result<(Vec<Class>, Vec<u8>), ()>
|
||||||
|
{
|
||||||
|
let mut tags = Vec::<Class>::with_capacity(3);
|
||||||
|
let mut encoded = Vec::<u8>::with_capacity(64);
|
||||||
|
|
||||||
|
match unmask_tag(handle) {
|
||||||
|
tag::NULL => {
|
||||||
|
tags.push(tag::NULL);
|
||||||
|
}
|
||||||
|
tag::BOOLEAN => match self.pool_boolean.get(handle_id(handle)) {
|
||||||
|
Some(value) => {
|
||||||
|
tags.push(tag::BOOLEAN + *value as Class);
|
||||||
|
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
tag::NATURAL => match self.pool_natural.get(handle_id(handle)) {
|
||||||
|
Some(value) => {
|
||||||
|
tags.push(tag::NATURAL);
|
||||||
|
encoded.append(&mut util::pack_natural(*value));
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
tag::INTEGER => match self.pool_integer.get(handle_id(handle)) {
|
||||||
|
Some(value) => {
|
||||||
|
tags.push(tag::INTEGER);
|
||||||
|
encoded.append(&mut util::pack_integer(*value));
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
tag::BLOCK => match self.pool_block.get(handle_id(handle)) {
|
||||||
|
Some(data) => {
|
||||||
|
tags.push(tag::BLOCK);
|
||||||
|
for b in data {
|
||||||
|
encoded.push(*b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
tag::STRING => match self.pool_string.get(handle_id(handle)) {
|
||||||
|
Some(data) => {
|
||||||
|
tags.push(tag::STRING);
|
||||||
|
let mut bytes = Vec::<u8>::from(data.as_bytes());
|
||||||
|
encoded.append(&mut util::pack_natural(bytes.len() as u64));
|
||||||
|
encoded.append(&mut bytes);
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
tag::ARRAY => match self.pool_array.get(handle_id(handle)) {
|
||||||
|
Some(_object) => {
|
||||||
|
tags.push(tag::ARRAY);
|
||||||
|
//tags.append(&mut object.class.clone());
|
||||||
|
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
tag::LIST => match self.pool_list.get(handle_id(handle)) {
|
||||||
|
Some(_object) => {
|
||||||
|
tags.push(tag::LIST);
|
||||||
|
//tags.append(&mut object.class.clone());
|
||||||
|
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
tag::SPARSE => match self.pool_sparse.get(handle_id(handle)) {
|
||||||
|
Some(_object) => {
|
||||||
|
tags.push(tag::SPARSE);
|
||||||
|
//tags.append(&mut object.class.clone());
|
||||||
|
|
||||||
|
// lookup table
|
||||||
|
|
||||||
|
|
||||||
|
// data table
|
||||||
|
|
||||||
|
}
|
||||||
|
None => { return Err(()); }
|
||||||
|
}
|
||||||
|
_ => { return Err(()); }
|
||||||
|
}
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode_data(&self, handle:Handle) -> Result<Vec<u8>,()>
|
||||||
|
{
|
||||||
|
match self.encode_parts(handle) {
|
||||||
|
Ok((_, encoded)) => Ok(encoded),
|
||||||
|
Err(_) => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode(&self, handle:Handle) -> Result<Vec<u8>,()>
|
||||||
|
{
|
||||||
|
match self.encode_parts(handle) {
|
||||||
|
Ok((tags, data)) => {
|
||||||
|
let prefix = Self::encode_tags(tags);
|
||||||
|
let mut encoded = Vec::<u8>::with_capacity(prefix.len() + data.len());
|
||||||
|
for b in prefix { encoded.push(b); }
|
||||||
|
for b in data { encoded.push(b); }
|
||||||
|
|
||||||
|
Ok(encoded)
|
||||||
|
}
|
||||||
|
Err(_) => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_tags(data:&Vec<u8>, index:&mut usize) -> Vec<Class>
|
||||||
|
{
|
||||||
|
let mut tags = Vec::<Class>::new();
|
||||||
|
while *index < data.len() {
|
||||||
|
let tag = util::unpack_natural(data, index) as Class;
|
||||||
|
tags.push(tag);
|
||||||
|
match tag {
|
||||||
|
tag::ARRAY | tag::LIST | tag::SPARSE |tag::RECORD => { }
|
||||||
|
_ => { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode(&mut self, data:&Vec<u8>) -> Result<Handle,()>
|
||||||
|
{
|
||||||
|
let mut index :usize = 0;
|
||||||
|
let tags = Self::decode_tags(data, &mut index);
|
||||||
|
|
||||||
|
for tag in tags {
|
||||||
|
println!("{}", tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
279
src/lib.rs
279
src/lib.rs
@ -1,233 +1,66 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
|
mod representation;
|
||||||
|
|
||||||
pub fn init() -> Interface { Interface::new() }
|
pub struct Instance {
|
||||||
|
classes:util::TypeTree,
|
||||||
|
schemas:stdu::Sparse<usize>,
|
||||||
|
memory:Vec<u8>,
|
||||||
|
}
|
||||||
|
impl Instance {
|
||||||
|
/* Constructors */
|
||||||
|
// pub fn boolean(&mut self, data:bool) -> Result<PTR,ERR>
|
||||||
|
// pub fn natural(&mut self, data:u64) -> Result<PTR,ERR>
|
||||||
|
// pub fn integer(&mut self, data:i64) -> Result<PTR,ERR>
|
||||||
|
// pub fn float(&mut self, data:f64) -> Result<PTR,ERR>
|
||||||
|
// pub fn block(&mut self, size:usize, data:Vec<u8>) -> Result<PTR,ERR>
|
||||||
|
// pub fn string(&mut self, data:String) -> Result<PTR,ERR>
|
||||||
|
|
||||||
type Class = u8;
|
/* Casters */
|
||||||
type Handle = u64;
|
// pub fn as_bool(&self, PTR) -> Result<bool,ERR>
|
||||||
|
// pub fn as_uint(&self, PTR) -> Result<u64,ERR>
|
||||||
|
// pub fn as_int(&self, PTR) -> Result<i64,ERR>
|
||||||
|
// pub fn as_float(&self, PTR) -> Result<f64,ERR>
|
||||||
|
// pub fn as_bytes(&self, PTR) -> Result<Vec<u8>,ERR>
|
||||||
|
// pub fn as_string(&self, PTR) -> Result<String,ERR>
|
||||||
|
// pub fn as_list(&self, PTR) -> Result<Vec<PTR>,ERR>
|
||||||
|
|
||||||
const TAG_UNDEFINED :Class = 0x00;
|
/* Access */
|
||||||
const TAG_NULL :Class = 0x01;
|
// pub fn with(&self, INDEX) -> Result<CONTEXT,ERR>
|
||||||
const TAG_BOOLEAN :Class = 0x02;
|
// pub fn size(&self, PTR) -> Result<usize,ERR>
|
||||||
//...
|
// pub fn len(&self, PTR) -> Result<usize,ERR>
|
||||||
const TAG_NATURAL :Class = 0x10;
|
// pub fn into(&self, PTR, INDEX) -> Result<PTR,ERR>
|
||||||
const TAG_INTEGER :Class = 0x11;
|
|
||||||
const TAG_DECIMAL :Class = 0x12;
|
|
||||||
//...
|
|
||||||
const TAG_BLOCK :Class = 0x1e;
|
|
||||||
const TAG_STRING :Class = 0x1f;
|
|
||||||
const TAG_OPTION :Class = 0x20;
|
|
||||||
const TAG_SET :Class = 0x21;
|
|
||||||
const TAG_ARRAY :Class = 0x22;
|
|
||||||
const TAG_LIST :Class = 0x23;
|
|
||||||
const TAG_SPARSE :Class = 0x24;
|
|
||||||
const TAG_MAP :Class = 0x25;
|
|
||||||
const TAG_TREE :Class = 0x26;
|
|
||||||
const TAG_GRAPH :Class = 0x27;
|
|
||||||
//...
|
|
||||||
const TAG_RECORD :Class = 0x3e;
|
|
||||||
const TAG_SCHEMA :Class = 0x3f;
|
|
||||||
|
|
||||||
fn mask_tag (tag:Class) -> Handle { (tag as u64) << 56 }
|
/* Modifiers */
|
||||||
fn unmask_tag (handle:Handle) -> Class { (handle >> 56) as Class }
|
// pub fn set(&mut self, dest:PTR, src:PTR)
|
||||||
fn handle_id (handle:Handle) -> usize { (handle & !mask_tag(0xff)) as usize }
|
// pub fn unset(&mut self, dest:PTR, src:PTR)
|
||||||
|
// pub fn insert(&mut self, dest:PTR, index:usize)
|
||||||
|
// pub fn remove(&mut self, dest:PTR, index:usize)
|
||||||
|
|
||||||
struct Container<T> {
|
/* Translation */
|
||||||
pub class:Vec<Class>,
|
// pub fn encode(&self, PTR) -> Result<Vec<u8>,ERR>
|
||||||
pub data:T,
|
// pub fn decode(&mut self) -> Result<PTR,ERR>
|
||||||
|
|
||||||
|
fn acquire_memory()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release_memory()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store_integer(&mut self, address:usize, value:i64)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Interface {
|
pub fn init(size:usize) -> Instance
|
||||||
pool_boolean:stdu::Pool<bool>,
|
{
|
||||||
pool_natural:stdu::Pool<u64>,
|
Instance {
|
||||||
pool_integer:stdu::Pool<i64>,
|
classes:util::TypeTree::new(),
|
||||||
pool_block:stdu::Pool<Vec<u8>>,
|
schemas:stdu::Sparse::<usize>::new(),
|
||||||
pool_string:stdu::Pool<String>,
|
memory:vec![0; size],
|
||||||
pool_option:stdu::Pool<Container<Option<Handle>>>,
|
|
||||||
pool_array:stdu::Pool<Container<Vec<Handle>>>,
|
|
||||||
pool_list:stdu::Pool<Container<Vec<Handle>>>,
|
|
||||||
pool_sparse:stdu::Pool<Container<stdu::Sparse<Handle>>>,
|
|
||||||
}
|
|
||||||
impl Interface {
|
|
||||||
pub(crate) fn new() -> Self
|
|
||||||
{
|
|
||||||
Self {
|
|
||||||
pool_boolean:stdu::Pool::<bool>::new(),
|
|
||||||
pool_natural:stdu::Pool::<u64>::new(),
|
|
||||||
pool_integer:stdu::Pool::<i64>::new(),
|
|
||||||
pool_block:stdu::Pool::<Vec<u8>>::new(),
|
|
||||||
pool_string:stdu::Pool::<String>::new(),
|
|
||||||
pool_option:stdu::Pool::<Container<Option<Handle>>>::new(),
|
|
||||||
pool_array:stdu::Pool::<Container<Vec<Handle>>>::new(),
|
|
||||||
pool_list:stdu::Pool::<Container<Vec<Handle>>>::new(),
|
|
||||||
pool_sparse:stdu::Pool::<Container<stdu::Sparse<Handle>>>::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* DATA CONSTRUCTORS */
|
|
||||||
|
|
||||||
pub fn boolean(&mut self, value:bool) -> Handle {
|
|
||||||
mask_tag(TAG_BOOLEAN) + self.pool_boolean.add(value) as Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn natural(&mut self, value:u64) -> Handle {
|
|
||||||
mask_tag(TAG_NATURAL) + self.pool_natural.add(value) as Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn integer(&mut self, value:i64) -> Handle {
|
|
||||||
mask_tag(TAG_INTEGER) + self.pool_integer.add(value) as Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block(&mut self, value:&Vec<u8>) -> Handle {
|
|
||||||
mask_tag(TAG_BLOCK) + self.pool_block.add(value.clone()) as Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string(&mut self, value:&str) -> Handle {
|
|
||||||
mask_tag(TAG_STRING) + self.pool_string.add(value.to_string()) as Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ENCODING/DECODING */
|
|
||||||
|
|
||||||
fn encode_tags(tags:Vec<Class>) -> Vec<u8>
|
|
||||||
{
|
|
||||||
let mut encoded = Vec::<u8>::with_capacity(16);
|
|
||||||
for tag in tags {
|
|
||||||
encoded.append(&mut util::pack_natural(tag as u64));
|
|
||||||
}
|
|
||||||
return encoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encode_parts(&self, handle:Handle) -> Result<(Vec<Class>, Vec<u8>), ()>
|
|
||||||
{
|
|
||||||
let mut tags = Vec::<Class>::with_capacity(3);
|
|
||||||
let mut encoded = Vec::<u8>::with_capacity(64);
|
|
||||||
|
|
||||||
match unmask_tag(handle) {
|
|
||||||
TAG_NULL => {
|
|
||||||
tags.push(TAG_NULL);
|
|
||||||
}
|
|
||||||
TAG_BOOLEAN => match self.pool_boolean.get(handle_id(handle)) {
|
|
||||||
Some(value) => {
|
|
||||||
tags.push(TAG_BOOLEAN + *value as Class);
|
|
||||||
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
TAG_NATURAL => match self.pool_natural.get(handle_id(handle)) {
|
|
||||||
Some(value) => {
|
|
||||||
tags.push(TAG_NATURAL);
|
|
||||||
encoded.append(&mut util::pack_natural(*value));
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
TAG_INTEGER => match self.pool_integer.get(handle_id(handle)) {
|
|
||||||
Some(value) => {
|
|
||||||
tags.push(TAG_INTEGER);
|
|
||||||
encoded.append(&mut util::pack_integer(*value));
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
TAG_BLOCK => match self.pool_block.get(handle_id(handle)) {
|
|
||||||
Some(data) => {
|
|
||||||
tags.push(TAG_BLOCK);
|
|
||||||
for b in data {
|
|
||||||
encoded.push(*b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
TAG_STRING => match self.pool_string.get(handle_id(handle)) {
|
|
||||||
Some(data) => {
|
|
||||||
tags.push(TAG_STRING);
|
|
||||||
let mut bytes = Vec::<u8>::from(data.as_bytes());
|
|
||||||
encoded.append(&mut util::pack_natural(bytes.len() as u64));
|
|
||||||
encoded.append(&mut bytes);
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
TAG_ARRAY => match self.pool_array.get(handle_id(handle)) {
|
|
||||||
Some(object) => {
|
|
||||||
tags.push(TAG_ARRAY);
|
|
||||||
tags.append(&mut object.class.clone());
|
|
||||||
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
TAG_LIST => match self.pool_list.get(handle_id(handle)) {
|
|
||||||
Some(object) => {
|
|
||||||
tags.push(TAG_LIST);
|
|
||||||
tags.append(&mut object.class.clone());
|
|
||||||
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
TAG_SPARSE => match self.pool_sparse.get(handle_id(handle)) {
|
|
||||||
Some(object) => {
|
|
||||||
tags.push(TAG_SPARSE);
|
|
||||||
tags.append(&mut object.class.clone());
|
|
||||||
|
|
||||||
// lookup table
|
|
||||||
|
|
||||||
|
|
||||||
// data table
|
|
||||||
|
|
||||||
}
|
|
||||||
None => { return Err(()); }
|
|
||||||
}
|
|
||||||
_ => { return Err(()); }
|
|
||||||
}
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encode_data(&self, handle:Handle) -> Result<Vec<u8>,()>
|
|
||||||
{
|
|
||||||
match self.encode_parts(handle) {
|
|
||||||
Ok((_, encoded)) => Ok(encoded),
|
|
||||||
Err(_) => Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encode(&self, handle:Handle) -> Result<Vec<u8>,()>
|
|
||||||
{
|
|
||||||
match self.encode_parts(handle) {
|
|
||||||
Ok((tags, data)) => {
|
|
||||||
let prefix = Self::encode_tags(tags);
|
|
||||||
let mut encoded = Vec::<u8>::with_capacity(prefix.len() + data.len());
|
|
||||||
for b in prefix { encoded.push(b); }
|
|
||||||
for b in data { encoded.push(b); }
|
|
||||||
|
|
||||||
Ok(encoded)
|
|
||||||
}
|
|
||||||
Err(_) => Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decode_tags(data:&Vec<u8>, index:&mut usize) -> Vec<Class>
|
|
||||||
{
|
|
||||||
let mut tags = Vec::<Class>::new();
|
|
||||||
while *index < data.len() {
|
|
||||||
let tag = util::unpack_natural(data, index) as Class;
|
|
||||||
tags.push(tag);
|
|
||||||
match tag {
|
|
||||||
TAG_ARRAY | TAG_LIST | TAG_SPARSE |TAG_RECORD => { }
|
|
||||||
_ => { break; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decode(&mut self, data:&Vec<u8>) -> Result<Handle,()>
|
|
||||||
{
|
|
||||||
let mut index :usize = 0;
|
|
||||||
let tags = Self::decode_tags(data, &mut index);
|
|
||||||
|
|
||||||
for tag in tags {
|
|
||||||
println!("{}", tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
src/runtime/lib.cc
Normal file
23
src/runtime/lib.cc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void* acquire(uint16_t type)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case Type::Tag::Boolean: return malloc(1);
|
||||||
|
case Type::Tag::Natural: return malloc(8);
|
||||||
|
case Type::Tag::Integer: return malloc(8);
|
||||||
|
default: return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void release(void* address)
|
||||||
|
{
|
||||||
|
if(address != nullptr) {
|
||||||
|
free(address);
|
||||||
|
}
|
||||||
|
}
|
41
src/runtime/lib.h
Normal file
41
src/runtime/lib.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "type.h"
|
||||||
|
#include "typetree.h"
|
||||||
|
#include "nametree.h"
|
||||||
|
|
||||||
|
extern TypeTree DB_TYPE;
|
||||||
|
extern NameTree DB_NAME;
|
||||||
|
|
||||||
|
struct List {
|
||||||
|
uint64_t capacity;
|
||||||
|
uint64_t length;
|
||||||
|
void* data;
|
||||||
|
|
||||||
|
void* allocate(size_t size);
|
||||||
|
|
||||||
|
List();
|
||||||
|
~List();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Schema {
|
||||||
|
struct Row {
|
||||||
|
uint16_t type;
|
||||||
|
uint16_t offset;
|
||||||
|
};
|
||||||
|
struct Node {
|
||||||
|
uint16_t keyword;
|
||||||
|
uint16_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t capacity;
|
||||||
|
uint16_t length;
|
||||||
|
|
||||||
|
Node* nodes;
|
||||||
|
Row* members;
|
||||||
|
|
||||||
|
Schema();
|
||||||
|
~Schema();
|
||||||
|
|
||||||
|
void* allocate();
|
||||||
|
};
|
3
src/runtime/mod.rs
Normal file
3
src/runtime/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
extern "C" {
|
||||||
|
fn acquire() -> usize;
|
||||||
|
}
|
122
src/runtime/nametree.h
Normal file
122
src/runtime/nametree.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#ifndef H_NameTree
|
||||||
|
#define H_NameTree
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class NameTree {
|
||||||
|
public:
|
||||||
|
struct Node {
|
||||||
|
std::string prefix;
|
||||||
|
size_t parent;
|
||||||
|
std::vector<size_t> children;
|
||||||
|
|
||||||
|
Node(const std::string& prefix, size_t parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
NameTree();
|
||||||
|
~NameTree();
|
||||||
|
|
||||||
|
size_t lookup(const std::string& value);
|
||||||
|
std::string get(size_t) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Node> m_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
NameTree::Node::Node(const std::string& prefix, size_t parent)
|
||||||
|
:prefix(prefix), parent(parent) { }
|
||||||
|
|
||||||
|
NameTree::NameTree()
|
||||||
|
{
|
||||||
|
m_nodes.push_back(Node("", 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
NameTree::~NameTree()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
size_t NameTree::lookup(const std::string& value)
|
||||||
|
{
|
||||||
|
size_t current = 0;
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
while(index < value.length()) {
|
||||||
|
Node& node = m_nodes[current];
|
||||||
|
|
||||||
|
size_t find = 0;
|
||||||
|
for(size_t ci = 0; ci < node.children.size(); ++ci) {
|
||||||
|
size_t child = node.children[ci];
|
||||||
|
if(value[index] == m_nodes[child].prefix[0]) {
|
||||||
|
size_t prefix_index = 0;
|
||||||
|
for(; prefix_index < m_nodes[child].prefix.length() && index < value.length(); prefix_index++ && index++) {
|
||||||
|
if(m_nodes[child].prefix[prefix_index] != value[index]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(prefix_index == m_nodes[child].prefix.length()) {
|
||||||
|
current = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
find = child;
|
||||||
|
|
||||||
|
// create intermediate node
|
||||||
|
m_nodes.push_back(Node(m_nodes[child].prefix.substr(0, prefix_index), child));
|
||||||
|
m_nodes[current].children[ci] = m_nodes.size() - 1;
|
||||||
|
m_nodes[m_nodes.size() - 1].children.push_back(child);
|
||||||
|
|
||||||
|
// update child node
|
||||||
|
m_nodes[child].parent = m_nodes.size() - 1;
|
||||||
|
|
||||||
|
// create branching node if value is not prefix
|
||||||
|
if(index != value.length()) {
|
||||||
|
m_nodes.push_back(Node(value.substr(index), child));
|
||||||
|
find = m_nodes.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return find;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(find == 0) {
|
||||||
|
// add suffix to new node pointing to value
|
||||||
|
m_nodes.push_back(Node(value.substr(index), current));
|
||||||
|
find = m_nodes.size() - 1;
|
||||||
|
node.children.push_back(find);
|
||||||
|
return find;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NameTree::get(size_t id) const
|
||||||
|
{
|
||||||
|
size_t length = 0;
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
if(id < m_nodes.size()) {
|
||||||
|
for(size_t current = id; current != 0;) {
|
||||||
|
length += m_nodes[current].prefix.length();
|
||||||
|
current = m_nodes[current].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = std::string(length, '\0');
|
||||||
|
size_t index = length - 1;
|
||||||
|
|
||||||
|
for(size_t current = id; current != 0;) {
|
||||||
|
size_t prefix_length = m_nodes[current].prefix.length() - 1;
|
||||||
|
for(size_t i = 0; i < m_nodes[current].prefix.length(); ++i) {
|
||||||
|
out[index--] = m_nodes[current].prefix[prefix_length - i];
|
||||||
|
}
|
||||||
|
current = m_nodes[current].parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
43
src/runtime/type.h
Normal file
43
src/runtime/type.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Type {
|
||||||
|
|
||||||
|
enum Tag {
|
||||||
|
Null = 0x01,
|
||||||
|
Boolean = 0x02,
|
||||||
|
Natural = 0x10,
|
||||||
|
Integer = 0x11,
|
||||||
|
Block = 0x1e,
|
||||||
|
String = 0x1f,
|
||||||
|
Set = 0x21,
|
||||||
|
Array = 0x22,
|
||||||
|
List = 0x23,
|
||||||
|
Trie = 0x27,
|
||||||
|
Map = 0x28,
|
||||||
|
Record = 0x4e,
|
||||||
|
Schema = 0x4f,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Info {
|
||||||
|
uint16_t Tag;
|
||||||
|
uint16_t Size;
|
||||||
|
|
||||||
|
Info(uint16_t tag, uint16_t size)
|
||||||
|
:Tag(tag), Size(size) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
const Info Null (Tag::Null, 0);
|
||||||
|
const Info Boolean (Tag::Boolean, 0);
|
||||||
|
const Info Natural (Tag::Natural, 8);
|
||||||
|
const Info Integer (Tag::Integer, 8);
|
||||||
|
const Info Block (Tag::Block, -1);
|
||||||
|
const Info String (Tag::String, -1);
|
||||||
|
const Info Set (Tag::Set, -1);
|
||||||
|
const Info Array (Tag::Array, -1);
|
||||||
|
const Info List (Tag::List, -1);
|
||||||
|
const Info Trie (Tag::Trie, -1);
|
||||||
|
const Info Map (Tag::Map, -1);
|
||||||
|
const Info Record (Tag::Record, -1);
|
||||||
|
const Info Schema (Tag::Schema, -1);
|
||||||
|
|
||||||
|
}
|
80
src/runtime/typetree.h
Normal file
80
src/runtime/typetree.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#ifndef H_TYPETREE
|
||||||
|
#define H_TYPETREE
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class TypeTree {
|
||||||
|
public:
|
||||||
|
struct Node {
|
||||||
|
uint16_t type;
|
||||||
|
size_t parent;
|
||||||
|
std::vector<size_t> children;
|
||||||
|
|
||||||
|
Node(uint16_t type, size_t parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeTree();
|
||||||
|
~TypeTree();
|
||||||
|
|
||||||
|
size_t get(size_t id, uint16_t type);
|
||||||
|
uint16_t type(size_t id);
|
||||||
|
size_t parent(size_t id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Node> m_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeTree::Node::Node(uint16_t type, size_t parent) :type(type), parent(parent) { }
|
||||||
|
|
||||||
|
TypeTree::TypeTree()
|
||||||
|
{
|
||||||
|
m_nodes.push_back(Node(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeTree::~TypeTree()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
size_t TypeTree::get(size_t id, uint16_t type)
|
||||||
|
{
|
||||||
|
size_t find = 0;
|
||||||
|
|
||||||
|
if(id < m_nodes.size())
|
||||||
|
{
|
||||||
|
Node& node = m_nodes[id];
|
||||||
|
|
||||||
|
for(size_t child : node.children) {
|
||||||
|
if(m_nodes[child].type == type) {
|
||||||
|
find = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(find == 0) {
|
||||||
|
m_nodes.push_back(Node(type, id));
|
||||||
|
find = m_nodes.size() - 1;
|
||||||
|
|
||||||
|
node.children.push_back(find);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return find;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t TypeTree::type(size_t id)
|
||||||
|
{
|
||||||
|
if(id > 0 && id < m_nodes.size()) {
|
||||||
|
return m_nodes[id].type;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TypeTree::parent(size_t id)
|
||||||
|
{
|
||||||
|
if(id > 0 && id < m_nodes.size()) {
|
||||||
|
return m_nodes[id].parent;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
29
src/tag.rs
Normal file
29
src/tag.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
pub type Class = u16;
|
||||||
|
|
||||||
|
pub const VARYING :Class = 0x00;
|
||||||
|
pub const NULL :Class = 0x01;
|
||||||
|
pub const BOOLEAN :Class = 0x02;
|
||||||
|
//...
|
||||||
|
pub const NATURAL :Class = 0x10;
|
||||||
|
pub const INTEGER :Class = 0x11;
|
||||||
|
pub const DECIMAL :Class = 0x12;
|
||||||
|
pub const FLOAT :Class = 0x13;
|
||||||
|
pub const COMPLEX :Class = 0x14;
|
||||||
|
//...
|
||||||
|
pub const RANGE :Class = 0x1c;
|
||||||
|
pub const CHAR :Class = 0x1d;
|
||||||
|
pub const BLOCK :Class = 0x1e;
|
||||||
|
pub const STRING :Class = 0x1f;
|
||||||
|
pub const OPTION :Class = 0x20;
|
||||||
|
pub const SET :Class = 0x21;
|
||||||
|
pub const ARRAY :Class = 0x22;
|
||||||
|
pub const LIST :Class = 0x23;
|
||||||
|
pub const SPARSE :Class = 0x24;
|
||||||
|
pub const MAP :Class = 0x25;
|
||||||
|
pub const TRIE :Class = 0x26;
|
||||||
|
pub const TREE :Class = 0x27;
|
||||||
|
pub const GRAPH :Class = 0x28;
|
||||||
|
//...
|
||||||
|
pub const RECORD :Class = 0x3e;
|
||||||
|
pub const SCHEMA :Class = 0x3f;
|
||||||
|
pub const USER :Class = 0x40;
|
42
src/util/memory.rs
Normal file
42
src/util/memory.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
pub struct Memory {
|
||||||
|
data:Vec<u8>,
|
||||||
|
}
|
||||||
|
impl Memory {
|
||||||
|
pub fn new(size:usize) -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
data:vec![0; size],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate(&mut self, size:usize) -> Result<usize,()>
|
||||||
|
{
|
||||||
|
if size < self.data.len() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free(&mut self, address:usize)
|
||||||
|
{
|
||||||
|
if address < self.data.len() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> usize { self.data.len() }
|
||||||
|
|
||||||
|
pub fn resize(&mut self, size:usize) -> Result<(),()>
|
||||||
|
// Modifies the size of memory available for allocation.
|
||||||
|
// Fails if memory could not be allocated or resize conflicts with allocated memory.
|
||||||
|
{
|
||||||
|
let new_data = vec![0; size];
|
||||||
|
let mut index = 0;
|
||||||
|
|
||||||
|
while index < self.data.len() && index < new_data.len() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,6 @@
|
|||||||
|
mod typetree; pub use typetree::TypeTree;
|
||||||
|
mod memory; pub use memory::Memory;
|
||||||
|
|
||||||
fn pack_count_leading_ones(data:u8) -> usize
|
fn pack_count_leading_ones(data:u8) -> usize
|
||||||
{
|
{
|
||||||
(data == 0xff) as usize
|
(data == 0xff) as usize
|
||||||
|
96
src/util/typetree.rs
Normal file
96
src/util/typetree.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
struct Node {
|
||||||
|
pub class:u32,
|
||||||
|
pub parent:usize,
|
||||||
|
pub children:stdu::Sparse<usize>,
|
||||||
|
}
|
||||||
|
impl Node {
|
||||||
|
pub fn new(class:u32, parent:usize) -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
class:class,
|
||||||
|
parent:parent,
|
||||||
|
children:stdu::Sparse::<usize>::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypeTree {
|
||||||
|
data:stdu::Pool<Node>,
|
||||||
|
}
|
||||||
|
impl TypeTree {
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
data:stdu::Pool::<Node>::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, hierarchy:&Vec<u32>) -> usize
|
||||||
|
// add
|
||||||
|
//
|
||||||
|
{
|
||||||
|
let mut node = 0;
|
||||||
|
for class in hierarchy {
|
||||||
|
match self.data.get(node) {
|
||||||
|
Some(parent) => match parent.children.get(*class as usize) {
|
||||||
|
Some(child) => {
|
||||||
|
node = *child;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let new_node = self.data.add(Node::new(*class, node));
|
||||||
|
self.data.get_mut(node).unwrap().children.set(*class as usize, new_node);
|
||||||
|
node = new_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => { return 0; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, id:usize, class:u32) -> Result<usize,()>
|
||||||
|
// wrap an existing type
|
||||||
|
//
|
||||||
|
{
|
||||||
|
let new_node = self.data.add(Node::new(class, id));
|
||||||
|
return match self.data.get_mut(id) {
|
||||||
|
Some(node) => {
|
||||||
|
node.children.set(class as usize, new_node);
|
||||||
|
Ok(new_node)
|
||||||
|
}
|
||||||
|
None => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inner(&self, id:usize) -> Option<usize>
|
||||||
|
// returns an inner type if one exists
|
||||||
|
//
|
||||||
|
{
|
||||||
|
return match self.data.get(id) {
|
||||||
|
Some(node) => {
|
||||||
|
if node.parent == 0 { None }
|
||||||
|
else { Some(node.parent) }
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_node(&self, hierarchy:&Vec<u32>) -> (usize, usize)
|
||||||
|
// finds the last existing node in the hierarchy
|
||||||
|
{
|
||||||
|
let mut index :usize = 0;
|
||||||
|
let mut current :usize = 0;
|
||||||
|
for i in 0..hierarchy.len() {
|
||||||
|
match self.data.get(current).unwrap().children.get(hierarchy[i] as usize) {
|
||||||
|
Some(child) => {
|
||||||
|
current = *child;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return (index, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0, 0);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user