pub mod any;
pub mod string;
pub mod bytes;
pub mod numbers;
pub mod bool;
pub mod geo;
pub mod dec;
pub mod ulid;
pub mod uuid;
pub mod option;
pub mod date;
use crate::{collection::NP_Collection, pointer::dec::NP_Dec};
use crate::NP_Parsed_Schema;
use crate::{json_flex::NP_JSON};
use crate::memory::{NP_Size, NP_Memory};
use crate::NP_Error;
use crate::{schema::{NP_TypeKeys}, collection::{map::NP_Map, table::NP_Table, list::NP_List, tuple::NP_Tuple}, utils::{print_path}};
use alloc::{boxed::Box, string::String, vec::Vec, borrow::ToOwned};
use bytes::NP_Bytes;
use any::NP_Any;
use self::{date::NP_Date, geo::NP_Geo, option::NP_Option, ulid::NP_ULID, uuid::NP_UUID};
#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub enum NP_PtrKinds {
None,
Standard { addr: usize },
MapItem {
addr: usize, next: usize, key: usize
},
TableItem {
addr: usize, next: usize, i: u8
},
ListItem {
addr: usize, next: usize, i: u16
},
TupleItem {
addr: usize, i: u8
},
}
impl NP_PtrKinds {
pub fn get_value_addr(&self) -> usize {
match self {
NP_PtrKinds::None => { 0 },
NP_PtrKinds::Standard { addr } => { *addr },
NP_PtrKinds::MapItem { addr, key: _, next: _ } => { *addr },
NP_PtrKinds::TableItem { addr, i: _, next: _ } => { *addr },
NP_PtrKinds::ListItem { addr, i:_ , next: _ } => { *addr },
NP_PtrKinds::TupleItem { addr, i:_ } => { *addr }
}
}
}
#[doc(hidden)]
pub trait NP_Value<'value> {
fn type_idx() -> (u8, String, NP_TypeKeys);
fn self_type_idx(&self) -> (u8, String, NP_TypeKeys);
fn schema_to_json(_schema_ptr: &NP_Parsed_Schema)-> Result<NP_JSON, NP_Error>;
fn set_value(_pointer: &mut NP_Ptr<'value>, _value: Box<&Self>) -> Result<(), NP_Error> where Self: NP_Value<'value> {
let mut message = "This type (".to_owned();
message.push_str(") doesn't support .set()!");
Err(NP_Error::new(message.as_str()))
}
fn into_value(_pointer: NP_Ptr<'value>) -> Result<Option<Box<Self>>, NP_Error> where Self: NP_Value<'value> {
let message = "This type doesn't support into!".to_owned();
Err(NP_Error::new(message.as_str()))
}
fn to_json(_pointer: &'value NP_Ptr<'value>) -> NP_JSON;
fn get_size(_pointer: &'value NP_Ptr<'value>) -> Result<usize, NP_Error>;
fn do_compact(from_ptr: NP_Ptr<'value>, to_ptr: &'value mut NP_Ptr<'value>) -> Result<(), NP_Error> where Self: NP_Value<'value> {
match Self::into_value(from_ptr)? {
Some(x) => {
Self::set_value(to_ptr, Box::new(&*x))?;
},
None => { }
}
Ok(())
}
fn schema_default(_schema: &NP_Parsed_Schema) -> Option<Box<Self>>;
fn from_json_to_schema(_json_schema: &NP_JSON) -> Result<Option<(Vec<u8>, NP_Parsed_Schema)>, NP_Error>;
fn from_bytes_to_schema(_address: usize, _bytes: &Vec<u8>) -> NP_Parsed_Schema;
}
#[doc(hidden)]
#[derive(Debug)]
pub struct NP_Ptr<'ptr> {
pub kind: NP_PtrKinds,
pub schema: &'ptr Box<NP_Parsed_Schema>,
pub address: usize,
pub memory: &'ptr NP_Memory,
pub parent: NP_Ptr_Collection<'ptr>,
pub helper: NP_Iterator_Helper<'ptr>
}
#[doc(hidden)]
#[derive(Debug, Clone)]
pub enum NP_Ptr_Collection<'coll> {
None,
List { address: usize, head: usize, tail: usize },
Map { address: usize, head: usize, length: u16 },
Table { address: usize, head: usize, schema: &'coll Box<NP_Parsed_Schema> },
Tuple { address: usize, length: usize, schema: &'coll Box<NP_Parsed_Schema> }
}
#[doc(hidden)]
#[derive(Debug, Clone)]
pub enum NP_Iterator_Helper<'it> {
None,
List { index: u16, prev_addr: usize, next_addr: usize, next_index: u16 },
Table { index: u8, column: &'it str, prev_addr: usize, skip_step: bool },
Map { key_addr: usize , prev_addr: usize, key: Option<String> },
Tuple { index: u8 }
}
impl<'it> NP_Iterator_Helper <'it> {
pub fn clone(&self) -> Self {
match self {
NP_Iterator_Helper::None => NP_Iterator_Helper::None,
NP_Iterator_Helper::List { index, prev_addr, next_index, next_addr} => {
NP_Iterator_Helper::List { index: *index, prev_addr: *prev_addr, next_index: *next_index, next_addr: *next_addr}
},
NP_Iterator_Helper::Table { index, column, prev_addr, skip_step} => {
NP_Iterator_Helper::Table { index: *index, column: *column, prev_addr: *prev_addr, skip_step: *skip_step}
},
NP_Iterator_Helper::Map { key_addr, prev_addr, key} => {
NP_Iterator_Helper::Map { key_addr: *key_addr, prev_addr: *prev_addr, key: key.clone()}
},
NP_Iterator_Helper::Tuple { index } => {
NP_Iterator_Helper::Tuple { index: *index }
}
}
}
}
impl<'ptr> NP_Ptr<'ptr> {
pub fn get_here<T>(&self) -> Result<Option<T>, NP_Error> where T: Default + NP_Value<'ptr> {
Ok(match T::into_value(self.clone())? {
Some (x) => {
Some(*x)
},
None => {
match T::schema_default(&self.schema) {
Some(x) => Some(*x),
None => None
}
}
})
}
pub fn clone(&self) -> Self {
NP_Ptr {
kind: self.kind,
schema: self.schema,
address: self.address,
memory: self.memory,
parent: self.parent.clone(),
helper: self.helper.clone()
}
}
pub fn set_here<T>(&'ptr mut self, value: T) -> Result<(), NP_Error> where T: NP_Value<'ptr> {
T::set_value(self, Box::new(&value))
}
pub fn _new_standard_ptr(address: usize, schema: &'ptr Box<NP_Parsed_Schema>, memory: &'ptr NP_Memory) -> Self {
NP_Ptr {
address: address,
kind: NP_PtrKinds::Standard { addr: memory.read_address(address) },
memory: memory,
schema: schema,
parent: NP_Ptr_Collection::None,
helper: NP_Iterator_Helper::None
}
}
pub fn _new_collection_item_ptr(address: usize, schema: &'ptr Box<NP_Parsed_Schema>, memory: &'ptr NP_Memory, parent: NP_Ptr_Collection<'ptr>, helper: NP_Iterator_Helper<'ptr>) -> Self {
let b_bytes = &memory.read_bytes();
NP_Ptr {
address: address,
kind: match parent {
NP_Ptr_Collection::Table { address: _, head: _, schema: _} => {
NP_PtrKinds::TableItem {
addr: memory.read_address(address),
next: memory.read_address_offset(address, 4, 2, 1),
i: if address == 0 { 0 } else { match &memory.size {
NP_Size::U32 => b_bytes[address + 8],
NP_Size::U16 => b_bytes[address + 4],
NP_Size::U8 => b_bytes[address + 2]
}},
}
},
NP_Ptr_Collection::List { address: _, head: _, tail: _} => {
NP_PtrKinds::ListItem {
addr: memory.read_address(address),
next: memory.read_address_offset(address, 4, 2, 1),
i: if address == 0 { 0 } else { match &memory.size {
NP_Size::U32 => u16::from_be_bytes(*memory.get_2_bytes(address + 8).unwrap_or(&[0; 2])),
NP_Size::U16 => u16::from_be_bytes(*memory.get_2_bytes(address + 4).unwrap_or(&[0; 2])),
NP_Size::U8 => u8::from_be_bytes([memory.get_1_byte(address + 2).unwrap_or(0)]) as u16
}}
}
},
NP_Ptr_Collection::Map { address: _, head: _, length: _} => {
NP_PtrKinds::MapItem {
addr: memory.read_address(address),
next: memory.read_address_offset(address, 4, 2, 1),
key: memory.read_address_offset(address, 8, 4, 2)
}
},
_ => { panic!() }
},
memory: memory,
schema: schema,
parent,
helper
}
}
pub fn has_value(&self) -> bool {
if self.address == 0 || self.kind.get_value_addr() == 0 {
return false;
}
return true;
}
pub fn clear_here(&self) -> bool {
if self.address != 0 {
self.memory.set_value_address(self.address, 0, &self.kind);
true
} else {
false
}
}
pub fn _deep_delete(self, path: Vec<&str>, path_index: usize) -> Result<bool, NP_Error> {
if let Some(x) = self._deep_get(path, path_index)? {
Ok(x.clear_here())
} else {
Ok(false)
}
}
#[allow(unused_mut)]
pub fn _deep_set(mut self, path: Vec<&str>, path_index: usize) -> Result<NP_Ptr<'ptr>, NP_Error> {
if path.len() == path_index {
return Ok(self);
}
let type_data = self.schema.into_type_data();
match type_data.2 {
NP_TypeKeys::Table => {
let table = NP_Table::into_value(self)?.unwrap();
let col = NP_Table::commit_pointer(table.select_mv(&path[path_index], None))?;
return col._deep_set(path, path_index + 1);
},
NP_TypeKeys::Map => {
let map = NP_Map::into_value(self)?.unwrap();
let col = NP_Map::commit_pointer(map.select_mv(String::from(path[path_index]), false))?;
return col._deep_set(path, path_index + 1);
},
NP_TypeKeys::List => {
let list = NP_List::into_value(self)?.unwrap();
let list_key_int = (&path[path_index]).parse::<u16>();
match list_key_int {
Ok(x) => {
let col = NP_List::commit_pointer(list.select_mv(x))?;
return col._deep_set(path, path_index + 1);
},
Err(_e) => {
let mut err = String::from("Can't query list with string, need number! Path: \n");
err.push_str(print_path(&path, path_index).as_str());
Err(NP_Error::new(err))
}
}
},
NP_TypeKeys::Tuple => {
let tuple = NP_Tuple::into_value(self)?.unwrap();
let list_key = &path[path_index];
let list_key_int = list_key.parse::<u8>();
match list_key_int {
Ok(x) => {
let col = tuple.select_mv(x)?;
return col._deep_set(path, path_index + 1);
},
Err(_e) => {
let mut err = String::from("Can't query tuple with string, need number! Path: \n");
err.push_str(print_path(&path, path_index).as_str());
Err(NP_Error::new(err))
}
}
},
_ => {
if path.len() != path_index {
let mut err = "TypeError: Attempted to deep set into collection but found scalar type (".to_owned();
err.push_str(type_data.1.as_str());
err.push_str("), Path:\n");
err.push_str(print_path(&path, path_index).as_str());
return Err(NP_Error::new(err));
}
return Ok(self)
}
}
}
#[allow(unused_mut)]
pub fn _deep_set_value<X>(mut self, path: Vec<&str>, path_index: usize, value: X) -> Result<(), NP_Error> where X: NP_Value<'ptr> + Default {
let mut pointer_value = self._deep_set(path, path_index)?;
let type_data = pointer_value.schema.into_type_data();
if type_data.0 != NP_Any::type_idx().0 && type_data.0 != X::type_idx().0 {
let mut err = "TypeError: Attempted to set value for type (".to_owned();
err.push_str(X::type_idx().1.as_str());
err.push_str(") into schema of type (");
err.push_str(type_data.1.as_str());
err.push_str("}\n");
return Err(NP_Error::new(err));
}
X::set_value(&mut pointer_value, Box::new(&value))?;
Ok(())
}
pub fn _deep_get_type<X: NP_Value<'ptr> + Default>(self, path: Vec<&str>, path_index: usize) -> Result<Option<Box<X>>, NP_Error> {
let ptr = self._deep_get(path, path_index)?;
if let Some(x) = ptr {
if x.schema.into_type_data().0 != X::type_idx().0 {
let mut err = "TypeError: Attempted to set value for type (".to_owned();
err.push_str(X::type_idx().1.as_str());
err.push_str(") into schema of type (");
err.push_str(x.schema.into_type_data().1.as_str());
err.push_str(")\n");
return Err(NP_Error::new(err));
}
if x.has_value() {
X::into_value(x)
} else {
Ok(X::schema_default(x.schema))
}
} else {
Ok(None)
}
}
pub fn _deep_get(self, path: Vec<&str>, path_index: usize) -> Result<Option<NP_Ptr<'ptr>>, NP_Error> {
if path.len() == path_index {
return Ok(Some(self));
}
let type_data = self.schema.into_type_data();
match type_data.2 {
NP_TypeKeys::Table => {
let table = NP_Table::into_value(self)?.unwrap();
let table_key = path[path_index];
let col = table.select_mv(table_key, None);
col._deep_get(path, path_index + 1)
},
NP_TypeKeys::Map => {
let result = NP_Map::into_value(self)?;
match result {
Some(map) => {
let map_key = String::from(path[path_index]);
let col = map.select_mv(map_key, false);
col._deep_get(path, path_index + 1)
},
None => {
unreachable!();
}
}
},
NP_TypeKeys::List => {
let result = NP_List::into_value(self)?;
match result {
Some(list) => {
let list_key = &path[path_index];
let list_key_int = list_key.parse::<u16>();
match list_key_int {
Ok(x) => {
let col = list.clone().select_mv(x);
col._deep_get(path, path_index + 1)
},
Err(_e) => {
let mut err = String::from("Can't query list with string, need number! Path: \n");
err.push_str(print_path(&path, path_index).as_str());
Err(NP_Error::new(err))
}
}
},
None => {
unreachable!();
}
}
},
NP_TypeKeys::Tuple => {
let result = NP_Tuple::into_value(self.clone())?;
match result {
Some(tuple) => {
let list_key = &path[path_index];
let list_key_int = list_key.parse::<u8>();
match list_key_int {
Ok(x) => {
let col = tuple.select(x)?;
col._deep_get(path, path_index + 1)
},
Err(_e) => {
let mut err = String::from("Can't query tuple with string, need number! Path: \n");
err.push_str(print_path(&path, path_index).as_str());
Err(NP_Error::new(err))
}
}
},
None => {
unreachable!();
}
}
},
_ => {
return Ok(None);
}
}
}
pub fn set_default(&'ptr mut self) -> Result<(), NP_Error> {
match self.schema.into_type_data().2 {
NP_TypeKeys::None => { },
NP_TypeKeys::Any => { },
NP_TypeKeys::UTF8String => {
String::set_value(self, Box::new(&String::default()))?;
},
NP_TypeKeys::Bytes => {
NP_Bytes::set_value(self, Box::new(&NP_Bytes::default()))?;
},
NP_TypeKeys::Int8 => {
i8::set_value(self, Box::new(&i8::default()))?;
},
NP_TypeKeys::Int16 => {
i16::set_value(self, Box::new(&i16::default()))?;
},
NP_TypeKeys::Int32 => {
i32::set_value(self, Box::new(&i32::default()))?;
},
NP_TypeKeys::Int64 => {
i64::set_value(self, Box::new(&i64::default()))?;
},
NP_TypeKeys::Uint8 => {
u8::set_value(self, Box::new(&u8::default()))?;
},
NP_TypeKeys::Uint16 => {
u16::set_value(self, Box::new(&u16::default()))?;
},
NP_TypeKeys::Uint32 => {
u32::set_value(self, Box::new(&u32::default()))?;
},
NP_TypeKeys::Uint64 => {
u64::set_value(self, Box::new(&u64::default()))?;
},
NP_TypeKeys::Float => {
f32::set_value(self, Box::new(&f32::default()))?;
},
NP_TypeKeys::Double => {
f64::set_value(self, Box::new(&f64::default()))?;
},
NP_TypeKeys::Decimal => {
NP_Dec::set_value(self, Box::new(&NP_Dec::default()))?;
},
NP_TypeKeys::Boolean => {
bool::set_value(self, Box::new(&bool::default()))?;
},
NP_TypeKeys::Geo => {
NP_Geo::set_value(self, Box::new(&NP_Geo::default()))?;
},
NP_TypeKeys::Uuid => {
NP_UUID::set_value(self, Box::new(&NP_UUID::default()))?;
},
NP_TypeKeys::Ulid => {
NP_ULID::set_value(self, Box::new(&NP_ULID::default()))?;
},
NP_TypeKeys::Date => {
NP_Date::set_value(self, Box::new(&NP_Date::default()))?;
},
NP_TypeKeys::Enum => {
NP_Option::set_value(self, Box::new(&NP_Option::default()))?;
},
NP_TypeKeys::Table => {
},
NP_TypeKeys::Map => {
},
NP_TypeKeys::List => {
},
NP_TypeKeys::Tuple => {
}
};
Ok(())
}
pub fn calc_size(&self) -> Result<usize, NP_Error> {
if self.address == 0 {
return Ok(0);
}
let base_size = self.memory.ptr_size(&self.kind);
if self.kind.get_value_addr() == 0 {
return Ok(base_size);
}
let type_size = match self.schema.into_type_data().2 {
NP_TypeKeys::None => { Ok(0) },
NP_TypeKeys::Any => { Ok(0) },
NP_TypeKeys::UTF8String => { String::get_size(self) },
NP_TypeKeys::Bytes => { NP_Bytes::get_size(self) },
NP_TypeKeys::Int8 => { i8::get_size(self) },
NP_TypeKeys::Int16 => { i16::get_size(self) },
NP_TypeKeys::Int32 => { i32::get_size(self) },
NP_TypeKeys::Int64 => { i64::get_size(self) },
NP_TypeKeys::Uint8 => { u8::get_size(self) },
NP_TypeKeys::Uint16 => { u16::get_size(self) },
NP_TypeKeys::Uint32 => { u32::get_size(self) },
NP_TypeKeys::Uint64 => { u64::get_size(self) },
NP_TypeKeys::Float => { f32::get_size(self) },
NP_TypeKeys::Double => { f64::get_size(self) },
NP_TypeKeys::Decimal => { NP_Dec::get_size(self) },
NP_TypeKeys::Boolean => { bool::get_size(self) },
NP_TypeKeys::Geo => { NP_Geo::get_size(self) },
NP_TypeKeys::Uuid => { NP_UUID::get_size(self) },
NP_TypeKeys::Ulid => { NP_ULID::get_size(self) },
NP_TypeKeys::Date => { NP_Date::get_size(self) },
NP_TypeKeys::Enum => { NP_Option::get_size(self) },
NP_TypeKeys::Table => { NP_Table::get_size(self) },
NP_TypeKeys::Map => { NP_Map::get_size(self) },
NP_TypeKeys::List => { NP_List::get_size(self) },
NP_TypeKeys::Tuple => { NP_Tuple::get_size(self) }
}?;
Ok(type_size + base_size)
}
pub fn json_encode(&self) -> NP_JSON {
if self.kind.get_value_addr() == 0 {
return NP_JSON::Null;
}
let type_key = self.schema.into_type_data().2;
match type_key {
NP_TypeKeys::None => { NP_JSON::Null },
NP_TypeKeys::Any => { NP_JSON::Null },
NP_TypeKeys::UTF8String => { String::to_json(self) },
NP_TypeKeys::Bytes => { NP_Bytes::to_json(self) },
NP_TypeKeys::Int8 => { i8::to_json(self) },
NP_TypeKeys::Int16 => { i16::to_json(self) },
NP_TypeKeys::Int32 => { i32::to_json(self) },
NP_TypeKeys::Int64 => { i64::to_json(self) },
NP_TypeKeys::Uint8 => { u8::to_json(self) },
NP_TypeKeys::Uint16 => { u16::to_json(self) },
NP_TypeKeys::Uint32 => { u32::to_json(self) },
NP_TypeKeys::Uint64 => { u64::to_json(self) },
NP_TypeKeys::Float => { f32::to_json(self) },
NP_TypeKeys::Double => { f64::to_json(self) },
NP_TypeKeys::Decimal => { NP_Dec::to_json(self) },
NP_TypeKeys::Boolean => { bool::to_json(self) },
NP_TypeKeys::Geo => { NP_Geo::to_json(self) },
NP_TypeKeys::Uuid => { NP_UUID::to_json(self) },
NP_TypeKeys::Ulid => { NP_ULID::to_json(self) },
NP_TypeKeys::Date => { NP_Date::to_json(self) },
NP_TypeKeys::Enum => { NP_Option::to_json(self) },
NP_TypeKeys::Table => { NP_Table::to_json(self) },
NP_TypeKeys::Map => { NP_Map::to_json(self) },
NP_TypeKeys::List => { NP_List::to_json(self) },
NP_TypeKeys::Tuple => { NP_Tuple::to_json(self) }
}
}
#[doc(hidden)]
pub fn compact(self, copy_to: &'ptr mut NP_Ptr<'ptr>) -> Result<(), NP_Error> {
if self.address == 0 || self.kind.get_value_addr() == 0 {
return Ok(());
}
match **self.schema {
NP_Parsed_Schema::Any { sortable: _, i:_ } => { Ok(()) }
NP_Parsed_Schema::UTF8String { sortable: _, i:_, size:_, default:_ } => { String::do_compact(self, copy_to) }
NP_Parsed_Schema::Bytes { sortable: _, i:_, size:_, default:_ } => { NP_Bytes::do_compact(self, copy_to) }
NP_Parsed_Schema::Int8 { sortable: _, i:_, default: _ } => { i8::do_compact(self, copy_to) }
NP_Parsed_Schema::Int16 { sortable: _, i:_ , default: _ } => { i16::do_compact(self, copy_to) }
NP_Parsed_Schema::Int32 { sortable: _, i:_ , default: _ } => { i32::do_compact(self, copy_to) }
NP_Parsed_Schema::Int64 { sortable: _, i:_ , default: _ } => { i64::do_compact(self, copy_to) }
NP_Parsed_Schema::Uint8 { sortable: _, i:_ , default: _ } => { u8::do_compact(self, copy_to) }
NP_Parsed_Schema::Uint16 { sortable: _, i:_ , default: _ } => { u16::do_compact(self, copy_to) }
NP_Parsed_Schema::Uint32 { sortable: _, i:_ , default: _ } => { u32::do_compact(self, copy_to) }
NP_Parsed_Schema::Uint64 { sortable: _, i:_ , default: _ } => { u64::do_compact(self, copy_to) }
NP_Parsed_Schema::Float { sortable: _, i:_ , default: _ } => { f32::do_compact(self, copy_to) }
NP_Parsed_Schema::Double { sortable: _, i:_ , default: _ } => { f64::do_compact(self, copy_to) }
NP_Parsed_Schema::Decimal { sortable: _, i:_, exp:_, default:_ } => { NP_Dec::do_compact(self, copy_to) }
NP_Parsed_Schema::Boolean { sortable: _, i:_, default:_ } => { bool::do_compact(self, copy_to) }
NP_Parsed_Schema::Geo { sortable: _, i:_, default:_, size:_ } => { NP_Geo::do_compact(self, copy_to) }
NP_Parsed_Schema::Uuid { sortable: _, i:_ } => { NP_UUID::do_compact(self, copy_to) }
NP_Parsed_Schema::Ulid { sortable: _, i:_ } => { NP_ULID::do_compact(self, copy_to) }
NP_Parsed_Schema::Date { sortable: _, i:_, default:_ } => { NP_Date::do_compact(self, copy_to) }
NP_Parsed_Schema::Enum { sortable: _, i:_, default:_, choices: _ } => { NP_Option::do_compact(self, copy_to) }
NP_Parsed_Schema::Table { sortable: _, i:_, columns:_ } => { NP_Table::do_compact(self, copy_to) }
NP_Parsed_Schema::Map { sortable: _, i:_, value:_ } => { NP_Map::do_compact(self, copy_to) }
NP_Parsed_Schema::List { sortable: _, i:_, of:_ } => { NP_List::do_compact(self, copy_to) }
NP_Parsed_Schema::Tuple { sortable: _, i:_, values:_ } => { NP_Tuple::do_compact(self, copy_to) }
_ => { panic!() }
}
}
}