Add basic impl for `DictGeneric`

next
Sayan Nandan 1 year ago
parent 7346035a27
commit b6d5ad1c75
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -30,15 +30,16 @@ use {
crate::{
engine::{
data::{
dict::DictEntryGeneric,
cell::Datacell,
dict::{DictEntryGeneric, DictGeneric},
tag::{DataTag, TagClass},
},
idx::{AsKey, AsValue},
storage::v1::{rw::BufferedScanner, SDSSError, SDSSResult},
},
util::EndianQW,
util::{copy_slice_to_array as memcpy, EndianQW},
},
std::collections::HashMap,
std::{cmp, collections::HashMap, mem},
};
type VecU8 = Vec<u8>;
@ -123,12 +124,15 @@ pub trait PersistDict {
/// enc md for an entry
fn enc_entry_metadata(buf: &mut VecU8, key: &Self::Key, val: &Self::Value);
/// dec the entry metadata
/// SAFETY: Must have passed entry pretest
unsafe fn dec_entry_metadata(scanner: &mut BufferedScanner) -> Option<Self::Metadata>;
// entry (coupled)
/// enc a packed entry
fn enc_entry_coupled(buf: &mut VecU8, key: &Self::Key, val: &Self::Value);
/// dec a packed entry
fn dec_entry_coupled(
/// SAFETY: must have verified metadata with src (unless explicitly skipped with the `DEC_VERIFY_MD_WITH_SRC_STANDALONE`)
/// flag
unsafe fn dec_entry_coupled(
scanner: &mut BufferedScanner,
md: Self::Metadata,
) -> Option<(Self::Key, Self::Value)>;
@ -136,11 +140,15 @@ pub trait PersistDict {
/// enc key for a normal entry
fn enc_key(buf: &mut VecU8, key: &Self::Key);
/// dec normal entry key
fn dec_key(scanner: &mut BufferedScanner, md: &Self::Metadata) -> Option<Self::Key>;
/// SAFETY: must have verified metadata with src (unless explicitly skipped with the `DEC_VERIFY_MD_WITH_SRC_STANDALONE`)
/// flag
unsafe fn dec_key(scanner: &mut BufferedScanner, md: &Self::Metadata) -> Option<Self::Key>;
/// enc val for a normal entry
fn enc_val(buf: &mut VecU8, val: &Self::Value);
/// dec normal entry val
fn dec_val(scanner: &mut BufferedScanner, md: &Self::Metadata) -> Option<Self::Value>;
/// SAFETY: must have verified metadata with src (unless explicitly skipped with the `DEC_VERIFY_MD_WITH_SRC_STANDALONE`)
/// flag
unsafe fn dec_val(scanner: &mut BufferedScanner, md: &Self::Metadata) -> Option<Self::Value>;
}
/*
@ -148,18 +156,22 @@ pub trait PersistDict {
*/
pub fn encode_dict<Pd: PersistDict>(dict: &HashMap<Pd::Key, Pd::Value>) -> Vec<u8> {
let mut buf = Vec::new();
let mut v = vec![];
_encode_dict::<Pd>(&mut v, dict);
v
}
fn _encode_dict<Pd: PersistDict>(buf: &mut VecU8, dict: &HashMap<Pd::Key, Pd::Value>) {
buf.extend(dict.len().u64_bytes_le());
for (key, val) in dict {
Pd::enc_entry_metadata(&mut buf, key, val);
Pd::enc_entry_metadata(buf, key, val);
if Pd::ENC_COUPLED {
Pd::enc_entry_coupled(&mut buf, key, val);
Pd::enc_entry_coupled(buf, key, val);
} else {
Pd::enc_key(&mut buf, key);
Pd::enc_val(&mut buf, val);
Pd::enc_key(buf, key);
Pd::enc_val(buf, val);
}
}
buf
}
pub fn decode_dict<Pd: PersistDict>(
@ -193,7 +205,10 @@ pub fn decode_dict<Pd: PersistDict>(
let k;
let v;
if Pd::DEC_COUPLED {
match Pd::dec_entry_coupled(scanner, md) {
match unsafe {
// UNSAFE(@ohsayan): verified metadata
Pd::dec_entry_coupled(scanner, md)
} {
Some((_k, _v)) => {
k = _k;
v = _v;
@ -201,7 +216,10 @@ pub fn decode_dict<Pd: PersistDict>(
None => return Err(SDSSError::InternalDecodeStructureCorruptedPayload),
}
} else {
match (Pd::dec_key(scanner, &md), Pd::dec_val(scanner, &md)) {
match unsafe {
// UNSAFE(@ohsayan): verified metadata
(Pd::dec_key(scanner, &md), Pd::dec_val(scanner, &md))
} {
(Some(_k), Some(_v)) => {
k = _k;
v = _v;
@ -219,3 +237,128 @@ pub fn decode_dict<Pd: PersistDict>(
Err(SDSSError::InternalDecodeStructureIllegalData)
}
}
/*
impls
*/
pub struct DGEntryMD {
klen: usize,
dscr: u8,
}
impl DGEntryMD {
fn decode(data: [u8; 9]) -> Self {
Self {
klen: u64::from_le_bytes(memcpy(&data[..8])) as usize,
dscr: data[8],
}
}
fn encode(klen: usize, dscr: u8) -> [u8; 9] {
let mut ret = [0u8; 9];
ret[..8].copy_from_slice(&klen.u64_bytes_le());
ret[8] = dscr;
ret
}
}
impl PersistDictEntryMetadata for DGEntryMD {
fn verify_with_src(&self, scanner: &BufferedScanner) -> bool {
static EXPECT_ATLEAST: [u8; 4] = [0, 1, 8, 8]; // PAD to align
let lbound_rem = self.klen + EXPECT_ATLEAST[cmp::min(self.dscr, 4) as usize] as usize;
scanner.has_left(lbound_rem) & (self.dscr <= PersistDictEntryDscr::Dict.value_u8())
}
}
impl PersistDict for DictGeneric {
type Key = Box<str>;
type Value = DictEntryGeneric;
type Metadata = DGEntryMD;
const ENC_COUPLED: bool = true;
const DEC_ENTRYMD_INFALLIBLE: bool = true;
const DEC_COUPLED: bool = false;
const DEC_VERIFY_MD_WITH_SRC_STANDALONE: bool = true;
fn metadec_pretest_routine(_: &BufferedScanner) -> bool {
true
}
fn metadec_pretest_entry(scanner: &BufferedScanner) -> bool {
scanner.has_left(sizeof!(u64) + 1)
}
fn enc_entry_metadata(buf: &mut VecU8, key: &Self::Key, _: &Self::Value) {
buf.extend(key.len().u64_bytes_le());
}
unsafe fn dec_entry_metadata(scanner: &mut BufferedScanner) -> Option<Self::Metadata> {
Some(Self::Metadata::decode(scanner.next_chunk()))
}
fn enc_entry_coupled(buf: &mut VecU8, key: &Self::Key, val: &Self::Value) {
match val {
DictEntryGeneric::Null => {
buf.push(PersistDictEntryDscr::Null.value_u8());
buf.extend(key.as_bytes())
}
DictEntryGeneric::Map(map) => {
buf.push(PersistDictEntryDscr::Dict.value_u8());
buf.extend(key.as_bytes());
_encode_dict::<Self>(buf, map);
}
DictEntryGeneric::Lit(dc) => {
buf.push(
PersistDictEntryDscr::translate_from_class(dc.tag().tag_class()).value_u8()
* (!dc.is_null() as u8),
);
buf.extend(key.as_bytes());
fn encode_element(buf: &mut VecU8, dc: &Datacell) {
unsafe {
use TagClass::*;
match dc.tag().tag_class() {
Bool if dc.is_init() => buf.push(dc.read_bool() as u8),
Bool => {}
UnsignedInt | SignedInt | Float => {
buf.extend(dc.read_uint().to_le_bytes())
}
Str | Bin => {
let slc = dc.read_bin();
buf.extend(slc.len().u64_bytes_le());
buf.extend(slc);
}
List => {
let lst = dc.read_list().read();
buf.extend(lst.len().u64_bytes_le());
for item in lst.iter() {
encode_element(buf, item);
}
}
}
}
}
encode_element(buf, dc);
}
}
}
unsafe fn dec_entry_coupled(
_: &mut BufferedScanner,
_: Self::Metadata,
) -> Option<(Self::Key, Self::Value)> {
unimplemented!()
}
fn enc_key(_: &mut VecU8, _: &Self::Key) {
unimplemented!()
}
unsafe fn dec_key(scanner: &mut BufferedScanner, md: &Self::Metadata) -> Option<Self::Key> {
String::from_utf8(scanner.next_chunk_variable(md.klen).to_owned())
.map(|s| s.into_boxed_str())
.ok()
}
fn enc_val(_: &mut VecU8, _: &Self::Value) {
unimplemented!()
}
unsafe fn dec_val(scanner: &mut BufferedScanner, md: &Self::Metadata) -> Option<Self::Value> {
unsafe fn decode_element(
_: &mut BufferedScanner,
_: PersistDictEntryDscr,
) -> Option<DictEntryGeneric> {
todo!()
}
decode_element(scanner, mem::transmute(md.dscr))
}
}

@ -35,7 +35,7 @@ use {
std::{
fs::File,
io::{Read, Seek, SeekFrom, Write},
ptr,
ptr, slice,
},
};
@ -219,13 +219,32 @@ impl<'a> BufferedScanner<'a> {
pub fn eof(&self) -> bool {
self.remaining() == 0
}
unsafe fn _incr(&mut self, by: usize) {
self.i += by;
}
}
impl<'a> BufferedScanner<'a> {
pub unsafe fn next_u64_le(&mut self) -> u64 {
let mut b = [0u8; sizeof!(u64)];
ptr::copy_nonoverlapping(self._cursor(), b.as_mut_ptr(), sizeof!(u64));
self.i += sizeof!(u64);
self._incr(sizeof!(u64));
u64::from_le_bytes(b)
}
pub unsafe fn next_chunk<const N: usize>(&mut self) -> [u8; N] {
let mut b = [0u8; N];
ptr::copy_nonoverlapping(self._cursor(), b.as_mut_ptr(), N);
self._incr(N);
b
}
pub unsafe fn next_chunk_variable(&mut self, size: usize) -> &[u8] {
let r = slice::from_raw_parts(self._cursor(), size);
self._incr(size);
r
}
pub unsafe fn next_byte(&mut self) -> u8 {
let r = *self._cursor();
self._incr(1);
r
}
}

Loading…
Cancel
Save