Impl enc/dec for model

next
Sayan Nandan 1 year ago
parent 6e3f26ddbd
commit 70552a5df4
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -77,6 +77,26 @@ impl PartialEq for Model {
}
impl Model {
pub fn new(
uuid: Uuid,
p_key: Box<str>,
p_tag: FullTag,
fields: UnsafeCell<Fields>,
sync_matrix: ISyncMatrix,
data: PrimaryIndex,
delta: DeltaState,
) -> Self {
Self {
uuid,
p_key,
p_tag,
fields,
sync_matrix,
data,
delta,
}
}
pub fn get_uuid(&self) -> Uuid {
self.uuid
}
@ -130,6 +150,17 @@ impl Model {
}
impl Model {
pub fn new_restore(uuid: Uuid, p_key: Box<str>, p_tag: FullTag, fields: Fields) -> Self {
Self::new(
uuid,
p_key,
p_tag,
UnsafeCell::new(fields),
ISyncMatrix::new(),
PrimaryIndex::new_empty(),
DeltaState::new_resolved(),
)
}
pub fn process_create(
CreateModel {
model_name: _,
@ -163,15 +194,7 @@ impl Model {
let last_pk = last_pk.unwrap_or(fields.stseq_ord_key().next().unwrap());
let tag = fields.st_get(last_pk).unwrap().layers()[0].tag;
if tag.tag_unique().is_unique() {
return Ok(Self {
uuid: Uuid::new(),
p_key: last_pk.into(),
p_tag: tag,
fields: UnsafeCell::new(fields),
sync_matrix: ISyncMatrix::new(),
data: PrimaryIndex::new_empty(),
delta: DeltaState::new_resolved(),
});
return Ok(Self::new_restore(Uuid::new(), last_pk.into(), tag, fields));
}
}
Err(DatabaseError::DdlModelBadDefinition)

@ -38,6 +38,14 @@ impl Uuid {
pub fn as_slice(&self) -> &[u8] {
self.data.as_bytes()
}
pub fn from_bytes(b: [u8; 16]) -> Self {
Self {
data: uuid::Uuid::from_u128_le(u128::from_le_bytes(b)),
}
}
pub fn to_le_bytes(self) -> [u8; 16] {
self.data.to_u128_le().to_le_bytes()
}
}
impl ToString for Uuid {

@ -39,6 +39,8 @@ use {
core::{borrow::Borrow, hash::Hash},
};
pub use stord::iter::IndexSTSeqDllIterOrdKV;
// re-exports
pub type IndexSTSeqCns<K, V> = stord::IndexSTSeqDll<K, V, stord::config::ConservativeConfig<K, V>>;
pub type IndexSTSeqLib<K, V> = stord::IndexSTSeqDll<K, V, stord::config::LiberalConfig<K, V>>;

@ -25,7 +25,7 @@
*/
pub(super) mod config;
mod iter;
pub(super) mod iter;
use {
self::{
@ -759,7 +759,7 @@ impl<K: AsKey, V: AsValue + PartialEq, C: Config<K, V>> PartialEq for IndexSTSeq
fn eq(&self, other: &Self) -> bool {
self.len() == other.len()
&& self
._iter_unord_kv()
._iter_ord_kv()
.all(|(k, v)| other._get(k).unwrap().eq(v))
}
}

@ -26,18 +26,19 @@
use {
super::{
dec_md, PersistDictEntryDscr, PersistMapSpec, PersistObjectHlIO, PersistObjectMD, VecU8,
VoidMetadata,
dec_md, obj::FieldMD, PersistDictEntryDscr, PersistMapSpec, PersistObjectHlIO,
PersistObjectMD, VecU8, VoidMetadata,
},
crate::{
engine::{
core::model::{Field, Layer},
data::{
cell::Datacell,
dict::DictEntryGeneric,
tag::{CUTag, DataTag, TagClass, TagUnique},
DictGeneric,
},
idx::{IndexBaseSpec, STIndex},
idx::{IndexBaseSpec, IndexSTSeqCns, STIndex, STIndexSeq},
storage::v1::{rw::BufferedScanner, SDSSError, SDSSResult},
},
util::{copy_slice_to_array as memcpy, EndianQW},
@ -70,7 +71,7 @@ where
/// Encode the dict into the given buffer
pub fn enc_dict_into_buffer<PM: PersistMapSpec>(buf: &mut VecU8, map: &PM::MapType) {
buf.extend(map.st_len().u64_bytes_le());
for (key, val) in map.st_iter_kv() {
for (key, val) in PM::_get_iter(map) {
PM::entry_md_enc(buf, key, val);
if PM::ENC_COUPLED {
PM::enc_entry(buf, key, val);
@ -179,6 +180,7 @@ impl PersistObjectMD for GenericDictEntryMD {
}
impl PersistMapSpec for GenericDictSpec {
type MapIter<'a> = std::collections::hash_map::Iter<'a, Box<str>, DictEntryGeneric>;
type MapType = DictGeneric;
type Key = Box<str>;
type Value = DictEntryGeneric;
@ -186,6 +188,9 @@ impl PersistMapSpec for GenericDictSpec {
const DEC_COUPLED: bool = false;
const ENC_COUPLED: bool = true;
const META_VERIFY_BEFORE_DEC: bool = true;
fn _get_iter<'a>(map: &'a Self::MapType) -> Self::MapIter<'a> {
map.iter()
}
fn meta_dec_collection_pretest(_: &BufferedScanner) -> bool {
true
}
@ -339,3 +344,106 @@ impl PersistMapSpec for GenericDictSpec {
unimplemented!()
}
}
pub struct FieldMapSpec;
pub struct FieldMapEntryMD {
field_id_l: u64,
field_prop_c: u64,
field_layer_c: u64,
null: u8,
}
impl FieldMapEntryMD {
const fn new(field_id_l: u64, field_prop_c: u64, field_layer_c: u64, null: u8) -> Self {
Self {
field_id_l,
field_prop_c,
field_layer_c,
null,
}
}
}
impl PersistObjectMD for FieldMapEntryMD {
const MD_DEC_INFALLIBLE: bool = true;
fn pretest_src_for_metadata_dec(scanner: &BufferedScanner) -> bool {
scanner.has_left(sizeof!(u64, 3) + 1)
}
fn pretest_src_for_object_dec(&self, scanner: &BufferedScanner) -> bool {
scanner.has_left(self.field_id_l as usize) // TODO(@ohsayan): we can enforce way more here such as atleast one field etc
}
unsafe fn dec_md_payload(scanner: &mut BufferedScanner) -> Option<Self> {
Some(Self::new(
u64::from_le_bytes(scanner.next_chunk()),
u64::from_le_bytes(scanner.next_chunk()),
u64::from_le_bytes(scanner.next_chunk()),
scanner.next_byte(),
))
}
}
impl PersistMapSpec for FieldMapSpec {
type MapIter<'a> = crate::engine::idx::IndexSTSeqDllIterOrdKV<'a, Box<str>, Field>;
type MapType = IndexSTSeqCns<Self::Key, Self::Value>;
type EntryMD = FieldMapEntryMD;
type Key = Box<str>;
type Value = Field;
const ENC_COUPLED: bool = false;
const DEC_COUPLED: bool = false;
const META_VERIFY_BEFORE_DEC: bool = true;
fn _get_iter<'a>(m: &'a Self::MapType) -> Self::MapIter<'a> {
m.stseq_ord_kv()
}
fn meta_dec_collection_pretest(_: &BufferedScanner) -> bool {
true
}
fn meta_dec_entry_pretest(scanner: &BufferedScanner) -> bool {
FieldMapEntryMD::pretest_src_for_metadata_dec(scanner)
}
fn entry_md_enc(buf: &mut VecU8, key: &Self::Key, val: &Self::Value) {
buf.extend(key.len().u64_bytes_le());
buf.extend(0u64.to_le_bytes()); // TODO(@ohsayan): props
buf.extend(val.layers().len().u64_bytes_le());
buf.push(val.is_nullable() as u8);
}
unsafe fn entry_md_dec(scanner: &mut BufferedScanner) -> Option<Self::EntryMD> {
FieldMapEntryMD::dec_md_payload(scanner)
}
fn enc_key(buf: &mut VecU8, key: &Self::Key) {
buf.extend(key.as_bytes());
}
fn enc_val(buf: &mut VecU8, val: &Self::Value) {
for layer in val.layers() {
Layer::pe_obj_hlio_enc(buf, layer)
}
}
unsafe fn dec_key(scanner: &mut BufferedScanner, md: &Self::EntryMD) -> Option<Self::Key> {
String::from_utf8(
scanner
.next_chunk_variable(md.field_id_l as usize)
.to_owned(),
)
.map(|v| v.into_boxed_str())
.ok()
}
unsafe fn dec_val(scanner: &mut BufferedScanner, md: &Self::EntryMD) -> Option<Self::Value> {
Field::pe_obj_hlio_dec(
scanner,
FieldMD::new(md.field_prop_c, md.field_layer_c, md.null),
)
.ok()
}
// unimplemented
fn enc_entry(_: &mut VecU8, _: &Self::Key, _: &Self::Value) {
unimplemented!()
}
unsafe fn dec_entry(
_: &mut BufferedScanner,
_: Self::EntryMD,
) -> Option<(Self::Key, Self::Value)> {
unimplemented!()
}
}

@ -245,7 +245,12 @@ pub fn dec_self<Obj: PersistObjectHlIO<Type = Obj>>(
/// specification for a persist map
pub trait PersistMapSpec {
/// map type
type MapType: STIndex<Self::Key, Self::Value>;
/// map iter
type MapIter<'a>: Iterator<Item = (&'a Self::Key, &'a Self::Value)>
where
Self: 'a;
/// metadata type
type EntryMD: PersistObjectMD;
/// key type (NOTE: set this to the true key type; handle any differences using the spec unless you have an entirely different
@ -259,6 +264,8 @@ pub trait PersistMapSpec {
const DEC_COUPLED: bool;
/// verify the src using the given metadata
const META_VERIFY_BEFORE_DEC: bool;
// collection misc
fn _get_iter<'a>(map: &'a Self::MapType) -> Self::MapIter<'a>;
// collection meta
/// pretest before jmp to routine for entire collection
fn meta_dec_collection_pretest(scanner: &BufferedScanner) -> bool;

@ -25,11 +25,14 @@
*/
use {
super::{dec_md, PersistObjectHlIO, PersistObjectMD, SimpleSizeMD, VecU8},
super::{dec_md, map::FieldMapSpec, PersistObjectHlIO, PersistObjectMD, SimpleSizeMD, VecU8},
crate::{
engine::{
core::model::{Field, Layer},
data::tag::{DataTag, FullTag, TagClass, TagSelector},
core::model::{Field, Layer, Model},
data::{
tag::{DataTag, FullTag, TagClass, TagSelector},
uuid::Uuid,
},
mem::VInline,
storage::v1::{rw::BufferedScanner, SDSSError, SDSSResult},
},
@ -133,7 +136,7 @@ pub struct FieldMD {
}
impl FieldMD {
const fn new(prop_c: u64, layer_c: u64, null: u8) -> Self {
pub(super) const fn new(prop_c: u64, layer_c: u64, null: u8) -> Self {
Self {
prop_c,
layer_c,
@ -200,3 +203,74 @@ impl PersistObjectHlIO for Field {
}
}
}
pub struct ModelLayout;
pub struct ModelLayoutMD {
model_uuid: Uuid,
p_key_len: u64,
p_key_tag: u64,
}
impl ModelLayoutMD {
pub(super) const fn new(model_uuid: Uuid, p_key_len: u64, p_key_tag: u64) -> Self {
Self {
model_uuid,
p_key_len,
p_key_tag,
}
}
}
impl PersistObjectMD for ModelLayoutMD {
const MD_DEC_INFALLIBLE: bool = true;
fn pretest_src_for_metadata_dec(scanner: &BufferedScanner) -> bool {
scanner.has_left(sizeof!(u64, 3) + sizeof!(u128)) // u64,3 since the fieldmap len is also there, but we don't handle it directly
}
fn pretest_src_for_object_dec(&self, scanner: &BufferedScanner) -> bool {
scanner.has_left(self.p_key_len as usize)
}
unsafe fn dec_md_payload(scanner: &mut BufferedScanner) -> Option<Self> {
Some(Self::new(
Uuid::from_bytes(scanner.next_chunk()),
u64::from_le_bytes(scanner.next_chunk()),
u64::from_le_bytes(scanner.next_chunk()),
))
}
}
impl PersistObjectHlIO for ModelLayout {
const ALWAYS_VERIFY_PAYLOAD_USING_MD: bool = true;
type Type = Model;
type Metadata = ModelLayoutMD;
fn pe_obj_hlio_enc(buf: &mut VecU8, v: &Self::Type) {
let irm = v.intent_read_model();
buf.extend(v.get_uuid().to_le_bytes());
buf.extend(v.p_key().len().u64_bytes_le());
buf.extend(v.p_tag().tag_selector().d().u64_bytes_le());
buf.extend(v.p_key().as_bytes());
super::map::enc_dict_into_buffer::<FieldMapSpec>(buf, irm.fields())
}
unsafe fn pe_obj_hlio_dec(
scanner: &mut BufferedScanner,
md: Self::Metadata,
) -> SDSSResult<Self::Type> {
let key = String::from_utf8(
scanner
.next_chunk_variable(md.p_key_len as usize)
.to_owned(),
)
.map_err(|_| SDSSError::InternalDecodeStructureCorruptedPayload)?;
let fieldmap = super::map::dec_dict::<FieldMapSpec>(scanner)?;
let ptag = if md.p_key_tag > TagSelector::max_dscr() as u64 {
return Err(SDSSError::InternalDecodeStructureCorruptedPayload);
} else {
TagSelector::from_raw(md.p_key_tag as u8)
};
Ok(Model::new_restore(
md.model_uuid,
key.into_boxed_str(),
ptag.into_full(),
fieldmap,
))
}
}

@ -25,11 +25,14 @@
*/
use crate::engine::{
core::model::{Field, Layer},
core::model::{Field, Layer, Model},
data::{
cell::Datacell,
dict::{DictEntryGeneric, DictGeneric},
tag::TagSelector,
uuid::Uuid,
},
idx::{IndexBaseSpec, IndexSTSeqCns, STIndex, STIndexSeq},
storage::v1::rw::BufferedScanner,
};
@ -68,3 +71,41 @@ fn field() {
let dec = super::dec_self::<Field>(&mut scanner).unwrap();
assert_eq!(field, dec);
}
#[test]
fn fieldmap() {
let mut fields = IndexSTSeqCns::<Box<str>, Field>::idx_init();
fields.st_insert("password".into(), Field::new([Layer::bin()].into(), false));
fields.st_insert(
"profile_pic".into(),
Field::new([Layer::bin()].into(), true),
);
let enc = super::enc::<super::map::PersistMapImpl<super::map::FieldMapSpec>>(&fields);
let mut scanner = BufferedScanner::new(&enc);
let dec =
super::dec::<super::map::PersistMapImpl<super::map::FieldMapSpec>>(&mut scanner).unwrap();
for ((orig_field_id, orig_field), (restored_field_id, restored_field)) in
fields.stseq_ord_kv().zip(dec.stseq_ord_kv())
{
assert_eq!(orig_field_id, restored_field_id);
assert_eq!(orig_field, restored_field);
}
}
#[test]
fn model() {
let uuid = Uuid::new();
let model = Model::new_restore(
uuid,
"username".into(),
TagSelector::Str.into_full(),
into_dict! {
"password" => Field::new([Layer::bin()].into(), false),
"profile_pic" => Field::new([Layer::bin()].into(), true),
},
);
let enc = super::enc::<super::obj::ModelLayout>(&model);
let mut scanner = BufferedScanner::new(&enc);
let dec = super::dec::<super::obj::ModelLayout>(&mut scanner).unwrap();
assert_eq!(model, dec);
}

Loading…
Cancel
Save