Add index key

next
Sayan Nandan 1 year ago
parent 87adc1046d
commit 554a478917
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -0,0 +1,276 @@
/*
* Created on Sun Apr 09 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/>.
*
*/
#[cfg(test)]
use crate::{engine::data::spec::Dataspec1D, util::test_utils};
use {
crate::engine::{
core::model::cell::Datacell,
data::{
lit::LitIR,
spec::DataspecMeta1D,
tag::{DataTag, TagUnique},
},
idx::meta::Comparable,
mem::{self, NativeDword, SystemDword},
},
core::{
fmt,
hash::{Hash, Hasher},
mem::ManuallyDrop,
slice, str,
},
};
pub struct PrimaryIndexKey {
tag: TagUnique,
data: NativeDword,
}
impl PrimaryIndexKey {
pub unsafe fn read_uint(&self) -> u64 {
self.data.load_qw()
}
pub fn uint(&self) -> Option<u64> {
(self.tag == TagUnique::UnsignedInt).then_some(unsafe {
// UNSAFE(@ohsayan): verified tag
self.read_uint()
})
}
pub unsafe fn read_sint(&self) -> i64 {
self.data.load_qw() as _
}
pub fn sint(&self) -> Option<i64> {
(self.tag == TagUnique::SignedInt).then_some(unsafe {
// UNSAFE(@ohsayan): verified tag
self.read_sint()
})
}
pub unsafe fn read_bin(&self) -> &[u8] {
self.vdata()
}
pub fn bin(&self) -> Option<&[u8]> {
(self.tag == TagUnique::Bin).then(|| unsafe {
// UNSAFE(@ohsayan): verified tag
self.read_bin()
})
}
pub unsafe fn read_str(&self) -> &str {
str::from_utf8_unchecked(self.vdata())
}
pub fn str(&self) -> Option<&str> {
(self.tag == TagUnique::Str).then(|| unsafe {
// UNSAFE(@ohsayan): verified tag
self.read_str()
})
}
}
impl PrimaryIndexKey {
pub fn try_from_dc(dc: Datacell) -> Option<Self> {
Self::check(&dc).then(|| unsafe { Self::new_from_dc(dc) })
}
/// ## Safety
///
/// Make sure that the [`Datacell`] is an eligible candidate key (ensuring uniqueness constraints + allocation correctness).
///
/// If you violate this:
/// - You might leak memory
/// - You might segfault
/// - Even if you escape both, it will produce incorrect results which is something you DO NOT want in an index
pub unsafe fn new_from_dc(dc: Datacell) -> Self {
debug_assert!(Self::check(&dc));
let tag = dc.tag().tag_unique();
let dc = ManuallyDrop::new(dc);
let dword = unsafe {
// UNSAFE(@ohsayan): this doesn't do anything "bad" by itself. needs the construction to be broken for it to do something silly
dc.as_raw()
}
.load_double();
Self {
tag,
data: unsafe {
// UNSAFE(@ohsayan): Perfectly safe since we're tranforming it and THIS will not by itself crash anything
core::mem::transmute(dword)
},
}
}
pub fn check(dc: &Datacell) -> bool {
dc.tag().tag_unique().is_unique()
}
pub fn check_opt(dc: &Option<Datacell>) -> bool {
dc.as_ref().map(Self::check).unwrap_or(false)
}
/// ## Safety
/// If you mess up construction, everything will fall apart
pub unsafe fn new(tag: TagUnique, data: NativeDword) -> Self {
Self { tag, data }
}
fn __compute_vdata_offset(&self) -> [usize; 2] {
let [len, data] = self.data.load_double();
let actual_len = len * (self.tag >= TagUnique::Bin) as usize;
[data, actual_len]
}
fn vdata(&self) -> &[u8] {
let [data, actual_len] = self.__compute_vdata_offset();
unsafe {
// UNSAFE(@ohsayan): Safe, due to construction
slice::from_raw_parts(data as *const u8, actual_len)
}
}
fn vdata_mut(&mut self) -> &mut [u8] {
let [data, actual_len] = self.__compute_vdata_offset();
unsafe {
// UNSAFE(@ohsayan): safe due to construction
slice::from_raw_parts_mut(data as *mut u8, actual_len)
}
}
}
impl Drop for PrimaryIndexKey {
fn drop(&mut self) {
if let TagUnique::Bin | TagUnique::Str = self.tag {
unsafe {
// UNSAFE(@ohsayan): Aliasing, sole owner and correct initialization
let vdata = self.vdata_mut();
mem::dealloc_array(vdata.as_mut_ptr(), vdata.len());
}
}
}
}
impl PartialEq for PrimaryIndexKey {
fn eq(&self, other: &Self) -> bool {
let [data_1, data_2] = [self.data.load_double()[0], other.data.load_double()[0]];
((self.tag == other.tag) & (data_1 == data_2)) && self.vdata() == other.vdata()
}
}
impl Eq for PrimaryIndexKey {}
impl Hash for PrimaryIndexKey {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.tag.hash(hasher);
self.vdata().hash(hasher);
}
}
impl<'a> PartialEq<LitIR<'a>> for PrimaryIndexKey {
fn eq(&self, key: &LitIR<'a>) -> bool {
debug_assert!(key.kind().tag_unique().is_unique());
self.tag == key.kind().tag_unique() && self.vdata() == key.__vdata()
}
}
impl<'a> Comparable<LitIR<'a>> for PrimaryIndexKey {
fn cmp_eq(&self, key: &LitIR<'a>) -> bool {
self == key
}
}
impl fmt::Debug for PrimaryIndexKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut dbg_struct = f.debug_struct("PrimaryIndexKey");
dbg_struct.field("tag", &self.tag);
macro_rules! fmt {
($($mtch:ident => $expr:expr),* $(,)?) => {
match self.tag {
$(TagUnique::$mtch => dbg_struct.field("data", &($expr.unwrap())),)*
TagUnique::Illegal => panic!("found illegal value. check ctor."),
}
};
}
fmt!(
UnsignedInt => self.uint(),
SignedInt => self.sint(),
Bin => self.bin(),
Str => self.str(),
);
dbg_struct.finish()
}
}
#[test]
fn check_pk_wrong_type() {
let data = [
Datacell::from(false),
Datacell::from(100),
Datacell::from(-100),
Datacell::from(10.11),
Datacell::from("hello"),
Datacell::from("hello".as_bytes()),
Datacell::from([]),
];
for datum in data {
let tag = datum.tag();
let candidate = PrimaryIndexKey::try_from_dc(datum);
if tag.tag_unique() == TagUnique::Illegal {
assert!(candidate.is_none(), "{:?}", &candidate);
} else {
assert!(candidate.is_some(), "{:?}", &candidate);
}
}
}
#[test]
fn check_pk_eq_hash() {
let state = test_utils::randomstate();
let data = [
Datacell::from(100),
Datacell::from(-100),
Datacell::from("binary".as_bytes()),
Datacell::from("string"),
];
for datum in data {
let pk1 = PrimaryIndexKey::try_from_dc(datum.clone()).unwrap();
let pk2 = PrimaryIndexKey::try_from_dc(datum).unwrap();
assert_eq!(pk1, pk2);
assert_eq!(
test_utils::hash_rs(&state, &pk1),
test_utils::hash_rs(&state, &pk2)
);
}
}
#[test]
fn check_pk_lit_eq_hash() {
let state = test_utils::randomstate();
let data = [
LitIR::UnsignedInt(100),
LitIR::SignedInt(-100),
LitIR::Bin(b"binary bro"),
LitIR::Str("string bro"),
];
for litir in data {
let pk = PrimaryIndexKey::try_from_dc(Datacell::from(litir.clone())).unwrap();
assert_eq!(pk, litir);
assert_eq!(
test_utils::hash_rs(&state, &litir),
test_utils::hash_rs(&state, &pk)
);
}
}

@ -0,0 +1,27 @@
/*
* Created on Sat Apr 08 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/>.
*
*/
mod key;

@ -24,6 +24,7 @@
*
*/
mod index;
mod model;
mod space;
mod util;

@ -24,25 +24,23 @@
*
*/
#[cfg(test)]
use core::mem;
use {
crate::engine::{
self,
data::{
lit::{Lit, LitIR},
spec::{Dataspec1D, DataspecMeta1D},
tag::{DataTag, TagClass},
tag::{CUTag, DataTag, TagClass},
},
mem::{NativeQword, SystemDword, WordRW},
},
core::{fmt, mem::ManuallyDrop, slice, str},
core::{fmt, mem, mem::ManuallyDrop, slice, str},
parking_lot::RwLock,
};
pub struct Datacell {
init: bool,
tag: TagClass,
tag: CUTag,
data: DataRaw,
}
@ -51,7 +49,7 @@ impl Datacell {
pub fn new_bool(b: bool) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(TagClass::Bool, DataRaw::word(SystemDword::store(b)))
Self::new(CUTag::BOOL, DataRaw::word(SystemDword::store(b)))
}
}
pub unsafe fn read_bool(&self) -> bool {
@ -70,7 +68,7 @@ impl Datacell {
pub fn new_uint(u: u64) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(TagClass::UnsignedInt, DataRaw::word(SystemDword::store(u)))
Self::new(CUTag::UINT, DataRaw::word(SystemDword::store(u)))
}
}
pub unsafe fn read_uint(&self) -> u64 {
@ -89,7 +87,7 @@ impl Datacell {
pub fn new_sint(u: i64) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(TagClass::SignedInt, DataRaw::word(SystemDword::store(u)))
Self::new(CUTag::SINT, DataRaw::word(SystemDword::store(u)))
}
}
pub unsafe fn read_sint(&self) -> i64 {
@ -108,7 +106,7 @@ impl Datacell {
pub fn new_float(f: f64) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(TagClass::Float, DataRaw::word(SystemDword::store(f)))
Self::new(CUTag::FLOAT, DataRaw::word(SystemDword::store(f)))
}
}
pub unsafe fn read_float(&self) -> f64 {
@ -129,13 +127,13 @@ impl Datacell {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(
TagClass::Bin,
DataRaw::word(SystemDword::store((md.as_mut_ptr(), md.len()))),
CUTag::BIN,
DataRaw::word(SystemDword::store((md.len(), md.as_mut_ptr()))),
)
}
}
pub unsafe fn read_bin(&self) -> &[u8] {
let (p, l) = self.load_word();
let (l, p) = self.load_word();
slice::from_raw_parts::<u8>(p, l)
}
pub fn try_bin(&self) -> Option<&[u8]> {
@ -153,13 +151,13 @@ impl Datacell {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(
TagClass::Str,
DataRaw::word(SystemDword::store((md.as_mut_ptr(), md.len()))),
CUTag::STR,
DataRaw::word(SystemDword::store((md.len(), md.as_mut_ptr()))),
)
}
}
pub unsafe fn read_str(&self) -> &str {
let (p, l) = self.load_word();
let (l, p) = self.load_word();
str::from_utf8_unchecked(slice::from_raw_parts(p, l))
}
pub fn try_str(&self) -> Option<&str> {
@ -175,7 +173,7 @@ impl Datacell {
pub fn new_list(l: Vec<Self>) -> Self {
unsafe {
// UNSAFE(@ohsayan): Correct because we are initializing Self with the correct tag
Self::new(TagClass::List, DataRaw::rwl(RwLock::new(l)))
Self::new(CUTag::LIST, DataRaw::rwl(RwLock::new(l)))
}
}
pub unsafe fn read_list(&self) -> &RwLock<Vec<Self>> {
@ -215,18 +213,19 @@ impl<'a> From<LitIR<'a>> for Datacell {
match l.kind().tag_class() {
tag if tag < TagClass::Bin => unsafe {
// UNSAFE(@ohsayan): Correct because we are using the same tag, and in this case the type doesn't need any advanced construction
let [a, b] = l.data().load_double();
Datacell::new(
l.kind().tag_class(),
CUTag::from(l.kind()),
// DO NOT RELY ON the payload's bit pattern; it's padded
DataRaw::word(SystemDword::store_qw(l.data().load_qw())),
DataRaw::word(SystemDword::store_fat(a, b)),
)
},
tag @ (TagClass::Bin | TagClass::Str) => unsafe {
TagClass::Bin | TagClass::Str => unsafe {
// UNSAFE(@ohsayan): Correct because we are using the same tag, and in this case the type requires a new heap for construction
let mut bin = ManuallyDrop::new(l.read_bin_uck().to_owned().into_boxed_slice());
Datacell::new(
tag,
DataRaw::word(SystemDword::store((bin.as_mut_ptr(), bin.len()))),
CUTag::from(l.kind()),
DataRaw::word(SystemDword::store((bin.len(), bin.as_mut_ptr()))),
)
},
_ => unsafe {
@ -261,17 +260,16 @@ impl<const N: usize> From<[Datacell; N]> for Datacell {
}
impl Datacell {
pub fn kind(&self) -> TagClass {
pub fn tag(&self) -> CUTag {
self.tag
}
pub fn kind(&self) -> TagClass {
self.tag.tag_class()
}
pub fn null() -> Self {
unsafe {
// UNSAFE(@ohsayan): This is a hack. It's safe because we set init to false
Self::_new(
TagClass::Bool,
DataRaw::word(NativeQword::store_qw(0)),
false,
)
Self::_new(CUTag::BOOL, DataRaw::word(NativeQword::store_qw(0)), false)
}
}
pub fn is_null(&self) -> bool {
@ -290,14 +288,17 @@ impl Datacell {
unsafe fn load_word<'a, T: WordRW<NativeQword, Target<'a> = T>>(&'a self) -> T {
self.data.word.ld()
}
unsafe fn _new(tag: TagClass, data: DataRaw, init: bool) -> Self {
unsafe fn _new(tag: CUTag, data: DataRaw, init: bool) -> Self {
Self { init, tag, data }
}
unsafe fn new(tag: TagClass, data: DataRaw) -> Self {
unsafe fn new(tag: CUTag, data: DataRaw) -> Self {
Self::_new(tag, data, true)
}
fn checked_tag<T>(&self, tag: TagClass, f: impl FnOnce() -> T) -> Option<T> {
((self.tag == tag) & (self.is_init())).then_some(f())
((self.kind() == tag) & (self.is_init())).then(f)
}
pub unsafe fn as_raw(&self) -> NativeQword {
mem::transmute_copy(&self.data.word)
}
}
@ -307,7 +308,7 @@ impl fmt::Debug for Datacell {
f.field("tag", &self.tag);
macro_rules! fmtdbg {
($($match:ident => $ret:expr),* $(,)?) => {
match self.tag {
match self.kind() {
$(TagClass::$match if self.is_init() => { f.field("data", &Some($ret));},)*
TagClass::Bool if self.is_null() => {f.field("data", &Option::<u8>::None);},
_ => unreachable!("incorrect state"),
@ -332,7 +333,7 @@ impl PartialEq for Datacell {
if self.is_null() {
return other.is_null();
}
match (self.tag, other.tag) {
match (self.kind(), other.kind()) {
(TagClass::Bool, TagClass::Bool) => self.bool() == other.bool(),
(TagClass::UnsignedInt, TagClass::UnsignedInt) => self.uint() == other.uint(),
(TagClass::SignedInt, TagClass::SignedInt) => self.sint() == other.sint(),
@ -375,10 +376,10 @@ impl DataRaw {
impl Drop for Datacell {
fn drop(&mut self) {
match self.tag {
match self.kind() {
TagClass::Str | TagClass::Bin => unsafe {
// UNSAFE(@ohsayan): we have checked that the cell is initialized (uninit will not satisfy this class), and we have checked its class
let (p, l) = self.load_word();
let (l, p) = self.load_word();
engine::mem::dealloc_array::<u8>(p, l)
},
TagClass::List => unsafe {
@ -393,12 +394,12 @@ impl Drop for Datacell {
#[cfg(test)]
impl Clone for Datacell {
fn clone(&self) -> Self {
let data = match self.tag {
let data = match self.kind() {
TagClass::Str | TagClass::Bin => unsafe {
// UNSAFE(@ohsayan): we have checked that the cell is initialized (uninit will not satisfy this class), and we have checked its class
let mut block = ManuallyDrop::new(self.read_bin().to_owned().into_boxed_slice());
DataRaw {
word: ManuallyDrop::new(SystemDword::store((block.as_mut_ptr(), block.len()))),
word: ManuallyDrop::new(SystemDword::store((block.len(), block.as_mut_ptr()))),
}
},
TagClass::List => unsafe {

@ -27,13 +27,15 @@
use {
super::{
spec::{Dataspec1D, DataspecMeta1D, DataspecMethods1D, DataspecRaw1D},
tag::{DataTag, FullTag},
tag::{DataTag, FullTag, TagUnique},
},
crate::engine::mem::{SpecialPaddedWord, SystemDword},
core::{
fmt,
hash::{Hash, Hasher},
marker::PhantomData,
mem::{self, ManuallyDrop},
slice,
},
};
@ -91,16 +93,16 @@ unsafe impl<'a> DataspecRaw1D for Lit<'a> {
const HEAP_STR: bool = true;
const HEAP_BIN: bool = false;
unsafe fn drop_str(&mut self) {
let [ptr, len] = self.data().load_fat();
let [len, ptr] = self.data().load_double();
drop(String::from_raw_parts(ptr as *mut u8, len, len));
}
unsafe fn drop_bin(&mut self) {}
unsafe fn clone_str(s: &str) -> Self::Target {
let new_string = ManuallyDrop::new(s.to_owned().into_boxed_str());
SystemDword::store((new_string.as_ptr(), new_string.len()))
SystemDword::store((new_string.len(), new_string.as_ptr()))
}
unsafe fn clone_bin(b: &[u8]) -> Self::Target {
SystemDword::store((b.as_ptr(), b.len()))
SystemDword::store((b.len(), b.as_ptr()))
}
}
@ -112,7 +114,7 @@ unsafe impl<'a> DataspecRaw1D for Lit<'a> {
unsafe impl<'a> Dataspec1D for Lit<'a> {
fn Str(s: Box<str>) -> Self {
let md = ManuallyDrop::new(s);
Self::new(FullTag::STR, SystemDword::store((md.as_ptr(), md.len())))
Self::new(FullTag::STR, SystemDword::store((md.len(), md.as_ptr())))
}
}
@ -172,12 +174,32 @@ direct_from! {
LitIR
*/
/// ☢TRAIT WARNING☢: The [`Hash`] implementation is strictly intended for usage with [`crate::engine::core`] components ONLY. This will FAIL and PRODUCE INCORRECT results
/// when used elsewhere
pub struct LitIR<'a> {
tag: FullTag,
data: SpecialPaddedWord,
_lt: PhantomData<&'a str>,
}
impl<'a> LitIR<'a> {
pub fn __vdata(&self) -> &[u8] {
let [vlen, data] = self.data().load_double();
let len = vlen * (self.kind().tag_unique() >= TagUnique::Bin) as usize;
unsafe {
// UNSAFE(@ohsayan): either because of static or lt
slice::from_raw_parts(data as *const u8, len)
}
}
}
impl<'a> Hash for LitIR<'a> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.tag.tag_unique().hash(state);
self.__vdata().hash(state);
}
}
impl<'a> DataspecMeta1D for LitIR<'a> {
type Target = SpecialPaddedWord;
type StringItem = &'a str;
@ -215,10 +237,10 @@ unsafe impl<'a> DataspecRaw1D for LitIR<'a> {
unsafe fn drop_str(&mut self) {}
unsafe fn drop_bin(&mut self) {}
unsafe fn clone_str(s: &str) -> Self::Target {
SystemDword::store((s.as_ptr(), s.len()))
SystemDword::store((s.len(), s.as_ptr()))
}
unsafe fn clone_bin(b: &[u8]) -> Self::Target {
SystemDword::store((b.as_ptr(), b.len()))
SystemDword::store((b.len(), b.as_ptr()))
}
}
@ -228,7 +250,7 @@ unsafe impl<'a> DataspecRaw1D for LitIR<'a> {
*/
unsafe impl<'a> Dataspec1D for LitIR<'a> {
fn Str(s: Self::StringItem) -> Self {
Self::new(FullTag::STR, SystemDword::store((s.as_ptr(), s.len())))
Self::new(FullTag::STR, SystemDword::store((s.len(), s.as_ptr())))
}
}

@ -36,8 +36,8 @@ use {
};
#[inline(always)]
fn when_then<T>(cond: bool, then: T) -> Option<T> {
cond.then_some(then)
fn when_then<T, F: FnOnce() -> T>(cond: bool, then: F) -> Option<T> {
cond.then(then)
}
/// Information about the type that implements the dataspec traits
@ -106,7 +106,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
/// Store a new binary. This function is always safe to call
#[allow(non_snake_case)]
fn Bin(b: &[u8]) -> Self {
Self::new(Self::Tag::BIN, SystemDword::store((b.as_ptr(), b.len())))
Self::new(Self::Tag::BIN, SystemDword::store((b.len(), b.as_ptr())))
}
/// Store a new string. Now, I won't talk about this one's safety because it depends on the implementor
@ -121,7 +121,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
}
/// Load a bool
fn read_bool_try(&self) -> Option<bool> {
when_then(self.kind().tag_class() == TagClass::Bool, unsafe {
when_then(self.kind().tag_class() == TagClass::Bool, || unsafe {
// UNSAFE(@ohsayan): we've verified the flag. but lol because this isn't actually unsafe
self.read_bool_uck()
})
@ -139,10 +139,13 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
}
/// Load a uint
fn read_uint_try(&self) -> Option<u64> {
when_then(self.kind().tag_class() == TagClass::UnsignedInt, unsafe {
// UNSAFE(@ohsayan): we've verified the flag. but lol because this isn't actually unsafe
self.read_uint_uck()
})
when_then(
self.kind().tag_class() == TagClass::UnsignedInt,
|| unsafe {
// UNSAFE(@ohsayan): we've verified the flag. but lol because this isn't actually unsafe
self.read_uint_uck()
},
)
}
/// Load a uint
/// ## Panics
@ -157,7 +160,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
}
/// Load a sint
fn read_sint_try(&self) -> Option<i64> {
when_then(self.kind().tag_class() == TagClass::SignedInt, unsafe {
when_then(self.kind().tag_class() == TagClass::SignedInt, || unsafe {
// UNSAFE(@ohsayan): we've verified the flag. but lol because this isn't actually unsafe
self.read_sint_uck()
})
@ -173,7 +176,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
}
/// Load a float
fn read_float_try(&self) -> Option<f64> {
when_then(self.kind().tag_class() == TagClass::Float, unsafe {
when_then(self.kind().tag_class() == TagClass::Float, || unsafe {
self.read_float_uck()
})
}
@ -187,12 +190,12 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
/// ## Safety
/// Are you a binary? Did you store it correctly? Are you a victim of segfaults?
unsafe fn read_bin_uck(&self) -> &[u8] {
let (p, l) = self.data().ld();
let (l, p) = self.data().ld();
slice::from_raw_parts(p, l)
}
/// Load a bin
fn read_bin_try(&self) -> Option<&[u8]> {
when_then(self.kind().tag_class() == TagClass::Bin, unsafe {
when_then(self.kind().tag_class() == TagClass::Bin, || unsafe {
self.read_bin_uck()
})
}
@ -210,7 +213,7 @@ pub unsafe trait Dataspec1D: DataspecMeta1D + DataspecRaw1D {
}
/// Load a str
fn read_str_try(&self) -> Option<&str> {
when_then(self.kind().tag_class() == TagClass::Str, unsafe {
when_then(self.kind().tag_class() == TagClass::Str, || unsafe {
self.read_str_uck()
})
}

@ -143,3 +143,58 @@ impl DataTag for FullTag {
self.unique
}
}
#[derive(Debug, Clone, Copy)]
pub struct CUTag {
class: TagClass,
unique: TagUnique,
}
impl PartialEq for CUTag {
fn eq(&self, other: &Self) -> bool {
self.class == other.class
}
}
macro_rules! cutag {
($class:ident, $unique:ident) => {
CUTag::new(TagClass::$class, TagUnique::$unique)
};
($class:ident) => {
CUTag::new(TagClass::$class, TagUnique::Illegal)
};
}
impl CUTag {
const fn new(class: TagClass, unique: TagUnique) -> Self {
Self { class, unique }
}
}
impl DataTag for CUTag {
const BOOL: Self = cutag!(Bool);
const UINT: Self = cutag!(UnsignedInt, UnsignedInt);
const SINT: Self = cutag!(SignedInt, SignedInt);
const FLOAT: Self = cutag!(Float);
const BIN: Self = cutag!(Bin, Bin);
const STR: Self = cutag!(Str, Str);
const LIST: Self = cutag!(List);
fn tag_class(&self) -> TagClass {
self.class
}
fn tag_selector(&self) -> TagSelector {
unimplemented!()
}
fn tag_unique(&self) -> TagUnique {
self.unique
}
}
impl From<FullTag> for CUTag {
fn from(f: FullTag) -> Self {
Self::new(f.tag_class(), f.tag_unique())
}
}

@ -26,7 +26,7 @@
#![deny(unreachable_patterns)]
mod meta;
pub mod meta;
mod mtchm;
mod stdhm;
mod stord;

@ -56,6 +56,7 @@ pub struct SpecialPaddedWord {
a: u64,
b: usize,
}
impl SpecialPaddedWord {
const fn new(a: u64, b: usize) -> Self {
Self { a, b }

@ -31,7 +31,7 @@ static ZERO_BLOCK: [u8; 0] = [];
/// Native quad pointer stack (must also be usable as a double and triple pointer stack. see [`SystemTword`] and [`SystemDword`])
pub trait SystemQword: SystemTword {
fn store_full(a: usize, b: usize, c: usize, d: usize) -> Self;
fn load_full(&self) -> [usize; 4];
fn load_quad(&self) -> [usize; 4];
fn store<'a, T>(v: T) -> Self
where
T: WordRW<Self>,
@ -49,7 +49,7 @@ pub trait SystemQword: SystemTword {
/// Native tripe pointer stack (must also be usable as a double pointer stack, see [`SystemDword`])
pub trait SystemTword: SystemDword {
fn store_full(a: usize, b: usize, c: usize) -> Self;
fn load_full(&self) -> [usize; 3];
fn load_triple(&self) -> [usize; 3];
fn store<'a, T>(v: T) -> Self
where
T: WordRW<Self>,
@ -69,7 +69,7 @@ pub trait SystemDword: Sized {
fn store_qw(u: u64) -> Self;
fn store_fat(a: usize, b: usize) -> Self;
fn load_qw(&self) -> u64;
fn load_fat(&self) -> [usize; 2];
fn load_double(&self) -> [usize; 2];
fn store<'a, T>(v: T) -> Self
where
T: WordRW<Self>,
@ -94,7 +94,7 @@ impl SystemDword for SpecialPaddedWord {
fn load_qw(&self) -> u64 {
self.a
}
fn load_fat(&self) -> [usize; 2] {
fn load_double(&self) -> [usize; 2] {
[self.a as usize, self.b]
}
}
@ -137,7 +137,7 @@ impl SystemDword for NativeDword {
x
}
#[inline(always)]
fn load_fat(&self) -> [usize; 2] {
fn load_double(&self) -> [usize; 2] {
self.0
}
}
@ -148,7 +148,7 @@ impl SystemTword for NativeTword {
Self([a, b, c])
}
#[inline(always)]
fn load_full(&self) -> [usize; 3] {
fn load_triple(&self) -> [usize; 3] {
self.0
}
}
@ -193,7 +193,7 @@ impl SystemDword for NativeTword {
x
}
#[inline(always)]
fn load_fat(&self) -> [usize; 2] {
fn load_double(&self) -> [usize; 2] {
[self.0[0], self.0[1]]
}
}
@ -202,7 +202,7 @@ impl SystemQword for NativeQword {
fn store_full(a: usize, b: usize, c: usize, d: usize) -> Self {
Self([a, b, c, d])
}
fn load_full(&self) -> [usize; 4] {
fn load_quad(&self) -> [usize; 4] {
self.0
}
}
@ -211,7 +211,7 @@ impl SystemTword for NativeQword {
fn store_full(a: usize, b: usize, c: usize) -> Self {
Self([a, b, c, 0])
}
fn load_full(&self) -> [usize; 3] {
fn load_triple(&self) -> [usize; 3] {
[self.0[0], self.0[1], self.0[2]]
}
}
@ -251,7 +251,7 @@ impl SystemDword for NativeQword {
}
ret
}
fn load_fat(&self) -> [usize; 2] {
fn load_double(&self) -> [usize; 2] {
[self.0[0], self.0[1]]
}
}
@ -318,20 +318,20 @@ impl_wordrw! {
}
[usize; 2] as SystemDword => {
|self| SystemDword::store_fat(self[0], self[1]);
|word| SystemDword::load_fat(word);
|word| SystemDword::load_double(word);
}
(*mut u8, usize) as SystemDword => {
|self| SystemDword::store_fat(self.0 as usize, self.1);
(usize, *mut u8) as SystemDword => {
|self| SystemDword::store_fat(self.0, self.1 as usize);
|word| {
let [a, b] = word.load_fat();
(a as *mut u8, b)
let [a, b] = word.load_double();
(a, b as *mut u8)
};
}
(*const u8, usize) as SystemDword => {
|self| SystemDword::store_fat(self.0 as usize, self.1);
(usize, *const u8) as SystemDword => {
|self| SystemDword::store_fat(self.0, self.1 as usize);
|word| {
let [a, b] = word.load_fat();
(a as *const u8, b)
let [a, b] = word.load_double();
(a, b as *const u8)
};
}
}

@ -24,9 +24,15 @@
*
*/
use rand::{
distributions::{uniform::SampleUniform, Alphanumeric},
Rng,
use {
rand::{
distributions::{uniform::SampleUniform, Alphanumeric},
Rng,
},
std::{
collections::hash_map::RandomState,
hash::{BuildHasher, Hash, Hasher},
},
};
// TODO(@ohsayan): Use my own PRNG algo here. Maybe my quadratic one?
@ -86,3 +92,13 @@ macro_rules! vecfuse {
v
}};
}
pub fn randomstate() -> RandomState {
RandomState::default()
}
pub fn hash_rs<T: Hash + ?Sized>(rs: &RandomState, item: &T) -> u64 {
let mut hasher = rs.build_hasher();
item.hash(&mut hasher);
hasher.finish()
}

Loading…
Cancel
Save