Impl enc/dec routines for internal structures

next
Sayan Nandan 1 year ago
parent 026b5ef0d2
commit 29457c6b89
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -26,7 +26,7 @@
mod dml;
mod index;
mod model;
pub(in crate::engine) mod model;
pub(in crate::engine) mod query_meta;
mod space;
mod util;

@ -324,7 +324,6 @@ impl Field {
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Layer {
tag: FullTag,
config: [usize; 2],
}
impl Layer {
@ -376,19 +375,18 @@ impl Layer {
pub fn tag(&self) -> FullTag {
self.tag
}
#[cfg(test)]
pub fn new_test(tag: FullTag, config: [usize; 2]) -> Self {
Self::new(tag, config)
pub fn new_empty_props(tag: FullTag) -> Self {
Self::new(tag)
}
#[inline(always)]
fn compute_index(&self, dc: &Datacell) -> usize {
self.tag.tag_class().word() * (dc.is_null() as usize)
}
const fn new(tag: FullTag, config: [usize; 2]) -> Self {
Self { tag, config }
const fn new(tag: FullTag) -> Self {
Self { tag }
}
const fn empty(tag: FullTag) -> Self {
Self::new(tag, [0; 2])
Self::new(tag)
}
fn hf(key: &[u8], v: [u8; 7]) -> u16 {
let mut tot = 0;

@ -48,8 +48,8 @@ mod validation {
.cloned()
.collect::<Vec<Field>>(),
[
Field::new([Layer::new_test(FullTag::STR, [0; 2])].into(), false),
Field::new([Layer::new_test(FullTag::BIN, [0; 2])].into(), false)
Field::new([Layer::new_empty_props(FullTag::STR)].into(), false),
Field::new([Layer::new_empty_props(FullTag::BIN)].into(), false)
]
);
assert_eq!(
@ -72,8 +72,8 @@ mod validation {
.cloned()
.collect::<Vec<Field>>(),
[
Field::new([Layer::new_test(FullTag::BIN, [0; 2])].into(), false),
Field::new([Layer::new_test(FullTag::STR, [0; 2])].into(), false),
Field::new([Layer::new_empty_props(FullTag::BIN)].into(), false),
Field::new([Layer::new_empty_props(FullTag::STR)].into(), false),
]
);
assert_eq!(

@ -62,6 +62,54 @@ pub enum TagSelector {
List = 13,
}
impl TagSelector {
pub const fn max_dscr() -> u8 {
Self::List.d()
}
pub const fn into_full(self) -> FullTag {
FullTag::new(self.tag_class(), self, self.tag_unique())
}
pub const unsafe fn from_raw(v: u8) -> Self {
core::mem::transmute(v)
}
pub const fn tag_unique(&self) -> TagUnique {
[
TagUnique::Illegal,
TagUnique::UnsignedInt,
TagUnique::UnsignedInt,
TagUnique::UnsignedInt,
TagUnique::UnsignedInt,
TagUnique::SignedInt,
TagUnique::SignedInt,
TagUnique::SignedInt,
TagUnique::SignedInt,
TagUnique::Illegal,
TagUnique::Illegal,
TagUnique::Bin,
TagUnique::Str,
TagUnique::Illegal,
][self.d() as usize]
}
pub const fn tag_class(&self) -> TagClass {
[
TagClass::Bool,
TagClass::UnsignedInt,
TagClass::UnsignedInt,
TagClass::UnsignedInt,
TagClass::UnsignedInt,
TagClass::SignedInt,
TagClass::SignedInt,
TagClass::SignedInt,
TagClass::SignedInt,
TagClass::Float,
TagClass::Float,
TagClass::Bin,
TagClass::Str,
TagClass::List,
][self.d() as usize]
}
}
#[repr(u8)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
pub enum TagUnique {

@ -293,7 +293,7 @@ impl<T, const N: usize> Extend<T> for VInline<N, T> {
}
#[cfg(test)]
impl<T, const N: usize> From<[T; N]> for VInline<N, T> {
impl<T, const M: usize, const N: usize> From<[T; N]> for VInline<M, T> {
fn from(a: [T; N]) -> Self {
a.into_iter().collect()
}

@ -26,6 +26,9 @@
//! High level interfaces
#[cfg(test)]
mod tests;
use {
crate::{
engine::{
@ -99,6 +102,37 @@ impl PersistDictEntryDscr {
spec
*/
pub fn enc<Obj: PersistObjectHlIO>(buf: &mut VecU8, obj: &Obj) {
obj.pe_obj_hlio_enc(buf)
}
pub fn enc_buf<Obj: PersistObjectHlIO>(obj: &Obj) -> Vec<u8> {
let mut buf = vec![];
enc(&mut buf, obj);
buf
}
pub fn dec<Obj: PersistObjectHlIO>(scanner: &mut BufferedScanner) -> SDSSResult<Obj::DType> {
if Obj::pe_obj_hlio_dec_ver(scanner) {
unsafe { Ok(Obj::pe_obj_hlio_dec(scanner).unwrap_unchecked()) }
} else {
Err(SDSSError::InternalDecodeStructureCorrupted)
}
}
pub fn dec_buf<Obj: PersistObjectHlIO>(buf: &[u8]) -> SDSSResult<Obj::DType> {
let mut scanner = BufferedScanner::new(buf);
dec::<Obj>(&mut scanner)
}
/// Any object that can persist
pub trait PersistObjectHlIO: Sized {
type DType;
fn pe_obj_hlio_enc(&self, buf: &mut VecU8);
fn pe_obj_hlio_dec_ver(scanner: &BufferedScanner) -> bool;
unsafe fn pe_obj_hlio_dec(scanner: &mut BufferedScanner) -> SDSSResult<Self::DType>;
}
/// metadata spec for a persist dict
pub trait PersistDictEntryMetadata {
/// Verify the state of scanner to ensure that it complies with the metadata
@ -247,7 +281,7 @@ pub fn decode_dict<Pd: PersistDict>(
}
/*
impls
dict impls
*/
pub struct DGEntryMD {
@ -438,18 +472,91 @@ impl PersistDict for DictGeneric {
}
}
#[test]
fn t_dict() {
let dict: DictGeneric = into_dict! {
"hello" => Datacell::new_str("world".into()),
"omg a null?" => Datacell::null(),
"a big fat dict" => DictEntryGeneric::Map(into_dict!(
"with a value" => Datacell::new_uint(1002),
"and a null" => Datacell::null(),
/*
persist obj impls
*/
use crate::engine::{
core::model::{Field, Layer},
data::tag::{FullTag, TagSelector},
mem::VInline,
};
struct POByteBlockFullTag(FullTag);
impl PersistObjectHlIO for POByteBlockFullTag {
type DType = FullTag;
fn pe_obj_hlio_enc(&self, buf: &mut VecU8) {
buf.extend(self.0.tag_selector().d().u64_bytes_le())
}
fn pe_obj_hlio_dec_ver(scanner: &BufferedScanner) -> bool {
scanner.has_left(sizeof!(u64))
}
unsafe fn pe_obj_hlio_dec(scanner: &mut BufferedScanner) -> SDSSResult<FullTag> {
let dscr = scanner.next_u64_le();
if dscr > TagSelector::max_dscr() as u64 {
return Err(SDSSError::InternalDecodeStructureCorruptedPayload);
}
Ok(TagSelector::from_raw(dscr as u8).into_full())
}
}
impl PersistObjectHlIO for Layer {
type DType = Layer;
fn pe_obj_hlio_enc(&self, buf: &mut VecU8) {
// [8B: type sig][8B: empty property set]
POByteBlockFullTag(self.tag()).pe_obj_hlio_enc(buf);
buf.extend(0u64.to_le_bytes());
}
fn pe_obj_hlio_dec_ver(scanner: &BufferedScanner) -> bool {
scanner.has_left(sizeof!(u64) * 2)
}
unsafe fn pe_obj_hlio_dec(scanner: &mut BufferedScanner) -> SDSSResult<Self::DType> {
let type_sel = scanner.next_u64_le();
let prop_set_arity = scanner.next_u64_le();
if (type_sel > TagSelector::List.d() as u64) | (prop_set_arity != 0) {
return Err(SDSSError::InternalDecodeStructureCorruptedPayload);
}
Ok(Layer::new_empty_props(
TagSelector::from_raw(type_sel as u8).into_full(),
))
};
let encoded = encode_dict::<DictGeneric>(&dict);
let mut scanner = BufferedScanner::new(&encoded);
let decoded = decode_dict::<DictGeneric>(&mut scanner).unwrap();
assert_eq!(dict, decoded);
}
}
impl PersistObjectHlIO for Field {
type DType = Self;
fn pe_obj_hlio_enc(&self, buf: &mut VecU8) {
// [null][prop_c][layer_c]
buf.push(self.is_nullable() as u8);
buf.extend(0u64.to_le_bytes());
buf.extend(self.layers().len().u64_bytes_le());
for layer in self.layers() {
PersistObjectHlIO::pe_obj_hlio_enc(layer, buf);
}
}
fn pe_obj_hlio_dec_ver(scanner: &BufferedScanner) -> bool {
scanner.has_left((sizeof!(u64) * 2) + 1)
}
unsafe fn pe_obj_hlio_dec(scanner: &mut BufferedScanner) -> SDSSResult<Self::DType> {
let nullable = scanner.next_byte();
let prop_c = scanner.next_u64_le();
let layer_cnt = scanner.next_u64_le();
let mut layers = VInline::new();
let mut fin = false;
while (!scanner.eof())
& (layers.len() as u64 != layer_cnt)
& (Layer::pe_obj_hlio_dec_ver(scanner))
& !fin
{
let l = Layer::pe_obj_hlio_dec(scanner)?;
fin = l.tag().tag_class() != TagClass::List;
layers.push(l);
}
let field = Field::new(layers, nullable == 1);
if (field.layers().len() as u64 == layer_cnt) & (nullable <= 1) & (prop_c == 0) & fin {
Ok(field)
} else {
Err(SDSSError::InternalDecodeStructureCorrupted)
}
}
}

@ -0,0 +1,66 @@
/*
* Created on Sun Aug 13 2023
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use crate::engine::{
core::model::{Field, Layer},
data::{
cell::Datacell,
dict::{DictEntryGeneric, DictGeneric},
},
storage::v1::rw::BufferedScanner,
};
#[test]
fn dict() {
let dict: DictGeneric = into_dict! {
"hello" => Datacell::new_str("world".into()),
"omg a null?" => Datacell::null(),
"a big fat dict" => DictEntryGeneric::Map(into_dict!(
"with a value" => Datacell::new_uint(1002),
"and a null" => Datacell::null(),
))
};
let encoded = super::encode_dict::<DictGeneric>(&dict);
let mut scanner = BufferedScanner::new(&encoded);
let decoded = super::decode_dict::<DictGeneric>(&mut scanner).unwrap();
assert_eq!(dict, decoded);
}
#[test]
fn layer() {
let layer = Layer::list();
let encoded = super::enc_buf(&layer);
let dec = super::dec_buf::<Layer>(&encoded).unwrap();
assert_eq!(layer, dec);
}
#[test]
fn field() {
let field = Field::new([Layer::list(), Layer::uint64()].into(), true);
let encoded = super::enc_buf(&field);
let dec = super::dec_buf::<Field>(&encoded).unwrap();
assert_eq!(field, dec);
}
Loading…
Cancel
Save