Clean up enum methods

next
Sayan Nandan 1 year ago
parent 9ceaa54abd
commit 9e9a7b9c9a
No known key found for this signature in database
GPG Key ID: 42EEDF4AE9D96B54

@ -167,7 +167,7 @@ unsafe fn dc_op_str_add(dc: &Datacell, rhs: LitIR) -> (bool, Datacell) {
}
static OPERATOR: [unsafe fn(&Datacell, LitIR) -> (bool, Datacell); {
TagClass::max() * (AssignmentOperator::max() + 1)
TagClass::MAX as usize * AssignmentOperator::VARIANTS
}] = [
// bool
dc_op_bool_ass,
@ -212,7 +212,7 @@ static OPERATOR: [unsafe fn(&Datacell, LitIR) -> (bool, Datacell); {
#[inline(always)]
const fn opc(opr: TagClass, ope: AssignmentOperator) -> usize {
(AssignmentOperator::count() * opr.word()) + ope.word()
(AssignmentOperator::VARIANTS * opr.value_word()) + ope.value_word()
}
#[cfg(test)]

@ -345,7 +345,7 @@ impl Field {
// illegal states: (1) bad null (2) tags don't match
7
} else {
dc.kind().word()
dc.kind().value_word()
}
}
pub fn validate_data_fpath(&self, data: &Datacell) -> bool {
@ -368,7 +368,7 @@ impl Field {
(TagClass::List, TagClass::List) if !layers.is_empty() => {
let mut okay = unsafe {
// UNSAFE(@ohsayan): we've verified this
LVERIFY[TagClass::List.word()](layer, data)
LVERIFY[TagClass::List.value_word()](layer, data)
};
let list = unsafe {
// UNSAFE(@ohsayan): we verified tags
@ -385,7 +385,7 @@ impl Field {
(tag_a, tag_b) if tag_a == tag_b => {
unsafe {
// UNSAFE(@ohsayan): same tags; not-null for now so no extra handling required here
LVERIFY[tag_a.word()](layer, data)
LVERIFY[tag_a.value_word()](layer, data)
}
}
_ => false,
@ -452,7 +452,7 @@ impl Layer {
}
#[inline(always)]
fn compute_index(&self, dc: &Datacell) -> usize {
self.tag.tag_class().word() * (dc.is_null() as usize)
self.tag.tag_class().value_word() * (dc.is_null() as usize)
}
const fn new(tag: FullTag) -> Self {
Self { tag }
@ -523,7 +523,7 @@ unsafe fn lverify_bool(_: Layer, _: &Datacell) -> bool {
unsafe fn lverify_uint(l: Layer, d: &Datacell) -> bool {
layertrace("uint");
const MX: [u64; 4] = [u8::MAX as _, u16::MAX as _, u32::MAX as _, u64::MAX];
d.read_uint() <= MX[l.tag.tag_selector().word() - 1]
d.read_uint() <= MX[l.tag.tag_selector().value_word() - 1]
}
unsafe fn lverify_sint(l: Layer, d: &Datacell) -> bool {
layertrace("sint");
@ -533,13 +533,13 @@ unsafe fn lverify_sint(l: Layer, d: &Datacell) -> bool {
(i32::MIN as _, i32::MAX as _),
(i64::MIN, i64::MAX),
];
let (mn, mx) = MN_MX[l.tag.tag_selector().word() - 5];
let (mn, mx) = MN_MX[l.tag.tag_selector().value_word() - 5];
(d.read_sint() >= mn) & (d.read_sint() <= mx)
}
unsafe fn lverify_float(l: Layer, d: &Datacell) -> bool {
layertrace("float");
const MN_MX: [(f64, f64); 2] = [(f32::MIN as _, f32::MAX as _), (f64::MIN, f64::MAX)];
let (mn, mx) = MN_MX[l.tag.tag_selector().word() - 9];
let (mn, mx) = MN_MX[l.tag.tag_selector().value_word() - 9];
(d.read_float() >= mn) & (d.read_float() <= mx)
}
unsafe fn lverify_bin(_: Layer, _: &Datacell) -> bool {

@ -24,9 +24,7 @@
*
*/
use std::mem;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, sky_macros::EnumMethods)]
#[repr(u8)]
pub enum AssignmentOperator {
Assign = 0,
@ -35,21 +33,3 @@ pub enum AssignmentOperator {
MulAssign = 3,
DivAssign = 4,
}
impl AssignmentOperator {
pub const fn disc(&self) -> u8 {
unsafe {
// UNSAFE(@ohsayan): just go back to school already; dscr
mem::transmute(*self)
}
}
pub const fn max() -> usize {
Self::DivAssign.disc() as _
}
pub const fn word(&self) -> usize {
self.disc() as _
}
pub const fn count() -> usize {
5
}
}

@ -25,7 +25,7 @@
*/
#[repr(u8)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord, sky_macros::EnumMethods)]
pub enum TagClass {
Bool = 0,
UnsignedInt = 1,
@ -37,12 +37,8 @@ pub enum TagClass {
}
impl TagClass {
/// ☢WARNING☢: Don't forget offset
pub const fn max() -> usize {
Self::List.d() as _
}
pub const fn try_from_raw(v: u8) -> Option<Self> {
if v > Self::List.d() {
if v > Self::MAX {
return None;
}
Some(unsafe { Self::from_raw(v) })
@ -59,12 +55,12 @@ impl TagClass {
TagUnique::Bin,
TagUnique::Str,
TagUnique::Illegal,
][self.d() as usize]
][self.value_word()]
}
}
#[repr(u8)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord, sky_macros::EnumMethods)]
pub enum TagSelector {
Bool = 0,
UInt8 = 1,
@ -83,9 +79,6 @@ pub enum TagSelector {
}
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())
}
@ -108,7 +101,7 @@ impl TagSelector {
TagUnique::Bin,
TagUnique::Str,
TagUnique::Illegal,
][self.d() as usize]
][self.value_word()]
}
pub const fn tag_class(&self) -> TagClass {
[
@ -126,12 +119,12 @@ impl TagSelector {
TagClass::Bin,
TagClass::Str,
TagClass::List,
][self.d() as usize]
][self.value_word()]
}
}
#[repr(u8)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord, sky_macros::EnumMethods)]
pub enum TagUnique {
UnsignedInt = 0,
SignedInt = 1,
@ -142,7 +135,7 @@ pub enum TagUnique {
impl TagUnique {
pub const fn is_unique(&self) -> bool {
self.d() != Self::Illegal.d()
self.value_u8() != Self::Illegal.value_u8()
}
pub const fn try_from_raw(raw: u8) -> Option<Self> {
if raw > 3 {
@ -152,12 +145,6 @@ impl TagUnique {
}
}
macro_rules! d {
($($ty:ty),*) => {$(impl $ty { pub const fn d(&self) -> u8 {unsafe{::core::mem::transmute(*self)}} pub const fn word(&self) -> usize {Self::d(self) as usize} } )*}
}
d!(TagClass, TagSelector, TagUnique);
pub trait DataTag {
const BOOL: Self;
const UINT: Self;

@ -0,0 +1,85 @@
/*
* Created on Fri Sep 15 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 core::{ptr, slice};
#[derive(Debug)]
pub struct BufferedScanner<'a> {
d: &'a [u8],
i: usize,
}
impl<'a> BufferedScanner<'a> {
pub const fn new(d: &'a [u8]) -> Self {
Self { d, i: 0 }
}
pub const fn remaining(&self) -> usize {
self.d.len() - self.i
}
pub const fn consumed(&self) -> usize {
self.i
}
pub const fn cursor(&self) -> usize {
self.i
}
pub(crate) fn has_left(&self, sizeof: usize) -> bool {
self.remaining() >= sizeof
}
unsafe fn _cursor(&self) -> *const u8 {
self.d.as_ptr().add(self.i)
}
pub fn eof(&self) -> bool {
self.remaining() == 0
}
unsafe fn _incr(&mut self, by: usize) {
self.i += by;
}
pub fn current(&self) -> &[u8] {
&self.d[self.i..]
}
}
impl<'a> BufferedScanner<'a> {
pub unsafe fn next_u64_le(&mut self) -> u64 {
u64::from_le_bytes(self.next_chunk())
}
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
}
}

@ -25,6 +25,7 @@
*/
mod astr;
mod buf;
mod ll;
mod stackop;
mod uarray;
@ -36,6 +37,7 @@ mod tests;
// re-exports
pub use {
astr::AStr,
buf::BufferedScanner,
ll::CachePadded,
stackop::ByteStack,
uarray::UArray,

@ -156,7 +156,7 @@ impl<Fs: RawFSInterface> DataBatchPersistDriver<Fs> {
col_cnt: usize,
) -> Result<(), SDSSError> {
self.f
.unfsynced_write(&[MARKER_ACTUAL_BATCH_EVENT, pk_tag.d()])?;
.unfsynced_write(&[MARKER_ACTUAL_BATCH_EVENT, pk_tag.value_u8()])?;
let observed_len_bytes = observed_len.u64_bytes_le();
self.f.unfsynced_write(&observed_len_bytes)?;
self.f

@ -39,7 +39,8 @@ use {
DictGeneric,
},
idx::{IndexBaseSpec, IndexSTSeqCns, STIndex, STIndexSeq},
storage::v1::{inf, rw::BufferedScanner, SDSSError, SDSSResult},
mem::BufferedScanner,
storage::v1::{inf, SDSSError, SDSSResult},
},
util::{copy_slice_to_array as memcpy, EndianQW},
},

@ -41,7 +41,8 @@ use {
tag::{DataTag, TagClass},
},
idx::{AsKey, AsValue},
storage::v1::{rw::BufferedScanner, SDSSError, SDSSResult},
mem::BufferedScanner,
storage::v1::{SDSSError, SDSSResult},
},
std::mem,
};
@ -64,13 +65,12 @@ pub enum PersistTypeDscr {
}
impl PersistTypeDscr {
pub(super) const MAX: Self = Self::Dict;
/// translates the tag class definition into the dscr definition
pub const fn translate_from_class(class: TagClass) -> Self {
unsafe { Self::from_raw(class.d() + 1) }
unsafe { Self::from_raw(class.value_u8() + 1) }
}
pub const fn try_from_raw(v: u8) -> Option<Self> {
if v > Self::MAX.value_u8() {
if v > Self::MAX {
None
} else {
unsafe { Some(Self::from_raw(v)) }
@ -262,7 +262,7 @@ pub mod enc {
pub mod dec {
use {
super::{map, PersistMapSpec, PersistObject},
crate::engine::storage::v1::{rw::BufferedScanner, SDSSResult},
crate::engine::{mem::BufferedScanner, storage::v1::SDSSResult},
};
// obj
pub fn dec_full<Obj: PersistObject>(data: &[u8]) -> SDSSResult<Obj::OutputType> {
@ -288,7 +288,10 @@ pub mod dec {
<map::PersistMapImpl<PM> as PersistObject>::default_full_dec(scanner)
}
pub mod utils {
use crate::engine::storage::v1::{BufferedScanner, SDSSError, SDSSResult};
use crate::engine::{
mem::BufferedScanner,
storage::v1::{SDSSError, SDSSResult},
};
pub unsafe fn decode_string(s: &mut BufferedScanner, len: usize) -> SDSSResult<String> {
String::from_utf8(s.next_chunk_variable(len).to_owned())
.map_err(|_| SDSSError::InternalDecodeStructureCorruptedPayload)

@ -24,23 +24,22 @@
*
*/
use crate::engine::{core::model::delta::IRModel, data::DictGeneric};
use {
super::{PersistTypeDscr, PersistObject, VecU8},
super::{PersistObject, PersistTypeDscr, VecU8},
crate::{
engine::{
core::{
model::{Field, Layer, Model},
model::{delta::IRModel, Field, Layer, Model},
space::{Space, SpaceMeta},
},
data::{
cell::Datacell,
tag::{DataTag, TagClass, TagSelector},
uuid::Uuid,
DictGeneric,
},
mem::VInline,
storage::v1::{inf, rw::BufferedScanner, SDSSError, SDSSResult},
mem::{BufferedScanner, VInline},
storage::v1::{inf, SDSSError, SDSSResult},
},
util::EndianQW,
},
@ -111,7 +110,7 @@ impl<'a> PersistObject for LayerRef<'a> {
true
}
fn meta_enc(buf: &mut VecU8, LayerRef(layer): Self::InputType) {
buf.extend(layer.tag().tag_selector().d().u64_bytes_le());
buf.extend(layer.tag().tag_selector().value_qword().to_le_bytes());
buf.extend(0u64.to_le_bytes());
}
unsafe fn meta_dec(scanner: &mut BufferedScanner) -> SDSSResult<Self::Metadata> {
@ -119,7 +118,7 @@ impl<'a> PersistObject for LayerRef<'a> {
}
fn obj_enc(_: &mut VecU8, _: Self::InputType) {}
unsafe fn obj_dec(_: &mut BufferedScanner, md: Self::Metadata) -> SDSSResult<Self::OutputType> {
if (md.type_selector > TagSelector::List.d() as u64) | (md.prop_set_arity != 0) {
if (md.type_selector > TagSelector::List.value_qword()) | (md.prop_set_arity != 0) {
return Err(SDSSError::InternalDecodeStructureCorruptedPayload);
}
Ok(Layer::new_empty_props(
@ -253,7 +252,7 @@ impl<'a> PersistObject for ModelLayoutRef<'a> {
fn meta_enc(buf: &mut VecU8, ModelLayoutRef(v, irm): Self::InputType) {
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_tag().tag_selector().value_qword().to_le_bytes());
buf.extend(irm.fields().len().u64_bytes_le());
}
unsafe fn meta_dec(scanner: &mut BufferedScanner) -> SDSSResult<Self::Metadata> {
@ -281,7 +280,7 @@ impl<'a> PersistObject for ModelLayoutRef<'a> {
scanner,
super::map::MapIndexSizeMD(md.field_c as usize),
)?;
let ptag = if md.p_key_tag > TagSelector::max_dscr() as u64 {
let ptag = if md.p_key_tag > TagSelector::MAX as u64 {
return Err(SDSSError::InternalDecodeStructureCorruptedPayload);
} else {
TagSelector::from_raw(md.p_key_tag as u8)

@ -43,7 +43,7 @@ mod tests;
pub use {
journal::{open_journal, JournalAdapter, JournalWriter},
memfs::NullFS,
rw::{BufferedScanner, LocalFS, RawFSInterface, SDSSFileIO},
rw::{LocalFS, RawFSInterface, SDSSFileIO},
};
pub mod data_batch {
pub use super::batch_jrnl::{DataBatchPersistDriver, DataBatchRestoreDriver};

@ -40,7 +40,6 @@ use {
std::{
fs::{self, File},
io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write},
ptr, slice,
},
};
@ -439,60 +438,3 @@ impl<Fs: RawFSInterface> SDSSFileIO<Fs> {
self.read_to_buffer(&mut r).map(|_| r[0])
}
}
pub struct BufferedScanner<'a> {
d: &'a [u8],
i: usize,
}
impl<'a> BufferedScanner<'a> {
pub const fn new(d: &'a [u8]) -> Self {
Self { d, i: 0 }
}
pub const fn remaining(&self) -> usize {
self.d.len() - self.i
}
pub const fn consumed(&self) -> usize {
self.i
}
pub const fn cursor(&self) -> usize {
self.i
}
pub(crate) fn has_left(&self, sizeof: usize) -> bool {
self.remaining() >= sizeof
}
unsafe fn _cursor(&self) -> *const u8 {
self.d.as_ptr().add(self.i)
}
pub fn eof(&self) -> bool {
self.remaining() == 0
}
unsafe fn _incr(&mut self, by: usize) {
self.i += by;
}
pub fn current(&self) -> &[u8] {
&self.d[self.i..]
}
}
impl<'a> BufferedScanner<'a> {
pub unsafe fn next_u64_le(&mut self) -> u64 {
u64::from_le_bytes(self.next_chunk())
}
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
}
}

@ -32,11 +32,11 @@ use {
engine::{
core::{space::Space, GlobalNS},
data::uuid::Uuid,
mem::BufferedScanner,
storage::v1::{
self, header_meta,
inf::{self, PersistObject},
BufferedScanner, JournalAdapter, JournalWriter, LocalFS, RawFSInterface,
SDSSResult,
JournalAdapter, JournalWriter, LocalFS, RawFSInterface, SDSSResult,
},
},
util::EndianQW,

@ -35,10 +35,11 @@ use {
},
data::uuid::Uuid,
idx::{IndexST, IndexSTSeqCns, STIndex, STIndexSeq},
mem::BufferedScanner,
ql::lex::Ident,
storage::v1::{
inf::{self, map, obj, PersistObject},
BufferedScanner, SDSSError, SDSSResult,
SDSSError, SDSSResult,
},
txn::TransactionError,
},

@ -31,9 +31,10 @@ use {
core::{space::Space, GlobalNS},
data::DictGeneric,
idx::STIndex,
mem::BufferedScanner,
storage::v1::{
inf::{self, map, obj, PersistObject},
BufferedScanner, SDSSResult,
SDSSResult,
},
txn::{TransactionError, TransactionResult},
},

@ -243,14 +243,17 @@ pub fn derive_value_methods(input: TokenStream) -> TokenStream {
}
}
let repr_type = repr_type.expect("Must have repr(u8) or repr(u16) etc.");
let mut dscr_expressions = vec![];
// Ensure all variants have explicit discriminants
if let Data::Enum(data) = &ast.data {
for variant in &data.variants {
match &variant.fields {
Fields::Unit => {
if variant.discriminant.as_ref().is_none() {
panic!("All enum variants must have explicit discriminants");
}
let (_, dscr_expr) = variant
.discriminant
.as_ref()
.expect("All enum variants must have explicit discriminants");
dscr_expressions.push(dscr_expr.clone());
}
_ => panic!("All enum variants must be unit variants"),
}
@ -259,6 +262,12 @@ pub fn derive_value_methods(input: TokenStream) -> TokenStream {
panic!("This derive macro only works on enums");
}
let value_expressions = quote! {
[#(#dscr_expressions),*]
};
let variant_len = dscr_expressions.len();
let repr_type_ident = syn::Ident::new(&repr_type, proc_macro2::Span::call_site());
let repr_type_ident_func = syn::Ident::new(
&format!("value_{repr_type}"),
@ -267,9 +276,23 @@ pub fn derive_value_methods(input: TokenStream) -> TokenStream {
let gen = quote! {
impl #enum_name {
pub const MAX: #repr_type_ident = Self::max_value();
pub const VARIANTS: usize = #variant_len;
pub const fn #repr_type_ident_func(&self) -> #repr_type_ident { unsafe { core::mem::transmute(*self) } }
pub const fn value_word(&self) -> usize { self.#repr_type_ident_func() as usize }
pub const fn value_qword(&self) -> u64 { self.#repr_type_ident_func() as u64 }
pub const fn max_value() -> #repr_type_ident {
let values = #value_expressions;
let mut i = 1;
let mut max = values[0];
while i < values.len() {
if values[i] > max {
max = values[i];
}
i = i + 1;
}
max
}
}
};
gen.into()

Loading…
Cancel
Save