Skip to main content

skl/
types.rs

1use core::ops::{Add, AddAssign, Sub, SubAssign};
2
3use arbitrary_int::{u27, u5, Number, TryNewError};
4pub use dbutils::buffer::*;
5
6const MAX_U5: u8 = (1 << 5) - 1;
7const MAX_U27: u32 = (1 << 27) - 1;
8
9/// Version, used for MVCC purpose, it is a 56-bit unsigned integer.
10pub type Version = u64;
11
12/// The information of the `SkipMap`, which can be used to reconstruct the `SkipMap`.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub struct Header {
15  meta_offset: u32,
16  head_node_offset: u32,
17  tail_node_offset: u32,
18}
19
20impl Header {
21  /// Returns a new `Meta` with the given meta, head node, and tail node offsets.
22  #[inline]
23  pub const fn new(meta_offset: u32, head_node_offset: u32, tail_node_offset: u32) -> Self {
24    Self {
25      meta_offset,
26      head_node_offset,
27      tail_node_offset,
28    }
29  }
30
31  /// Returns the meta offset of the `SkipMap`.
32  #[inline]
33  pub const fn meta_offset(&self) -> u32 {
34    self.meta_offset
35  }
36
37  /// Returns the head node offset of the `SkipMap`.
38  #[inline]
39  pub const fn head_node_offset(&self) -> u32 {
40    self.head_node_offset
41  }
42
43  /// Returns the tail node offset of the `SkipMap`.
44  #[inline]
45  pub const fn tail_node_offset(&self) -> u32 {
46    self.tail_node_offset
47  }
48}
49
50pub(crate) mod internal {
51  use core::{ptr::NonNull, sync::atomic::Ordering};
52
53  use crate::ref_counter::RefCounter;
54
55  /// A pointer to a value in the `SkipMap`.
56  #[derive(Debug)]
57  pub struct ValuePointer {
58    pub(crate) value_offset: u32,
59    pub(crate) value_len: u32,
60  }
61
62  impl Clone for ValuePointer {
63    fn clone(&self) -> Self {
64      *self
65    }
66  }
67
68  impl Copy for ValuePointer {}
69
70  impl ValuePointer {
71    #[inline]
72    pub(crate) const fn new(value_offset: u32, value_len: u32) -> Self {
73      Self {
74        value_offset,
75        value_len,
76      }
77    }
78  }
79
80  bitflags::bitflags! {
81    #[derive(Debug, Copy, Clone, Eq, PartialEq)]
82    pub struct Flags: u8 {
83      /// Indicates that the wal is muliple version.
84      const MULTIPLE_VERSION = 0b0000_0001;
85    }
86  }
87
88  /// A reference counter for [`Meta`](crate::allocator::Meta).
89  #[doc(hidden)]
90  pub(crate) struct RefMeta<M, R: RefCounter> {
91    unify: bool,
92    meta: NonNull<M>,
93    ref_counter: R,
94  }
95
96  impl<M: core::fmt::Debug, R: RefCounter> core::fmt::Debug for RefMeta<M, R> {
97    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98      f.debug_struct("RefMeta")
99        .field("meta", unsafe { &*self.meta.as_ptr() })
100        .field("refs", &self.ref_counter.load(Ordering::Acquire))
101        .field("unify", &self.unify)
102        .finish()
103    }
104  }
105
106  impl<M, R: RefCounter> core::ops::Deref for RefMeta<M, R> {
107    type Target = M;
108
109    #[inline]
110    fn deref(&self) -> &Self::Target {
111      unsafe { self.meta.as_ref() }
112    }
113  }
114
115  impl<M, R: RefCounter> core::ops::DerefMut for RefMeta<M, R> {
116    #[inline]
117    fn deref_mut(&mut self) -> &mut Self::Target {
118      unsafe { self.meta.as_mut() }
119    }
120  }
121
122  impl<M, R> RefMeta<M, R>
123  where
124    R: RefCounter,
125  {
126    #[inline]
127    pub(crate) fn new(meta: NonNull<M>, unify: bool) -> Self {
128      Self {
129        meta,
130        ref_counter: R::new(),
131        unify,
132      }
133    }
134
135    #[inline]
136    pub(crate) fn refs(&self) -> usize {
137      self.ref_counter.load(Ordering::Acquire)
138    }
139  }
140
141  impl<M, R: RefCounter> Clone for RefMeta<M, R> {
142    #[inline]
143    fn clone(&self) -> Self {
144      let old_size = self.ref_counter.fetch_add(Ordering::Release);
145      if old_size > usize::MAX >> 1 {
146        dbutils::abort();
147      }
148
149      // Safety:
150      // The ptr is always non-null, and the data is only deallocated when the
151      // last Arena is dropped.
152      Self {
153        meta: self.meta,
154        ref_counter: self.ref_counter.clone(),
155        unify: self.unify,
156      }
157    }
158  }
159
160  impl<M, R: RefCounter> Drop for RefMeta<M, R> {
161    fn drop(&mut self) {
162      if self.ref_counter.fetch_sub(Ordering::Release) != 1 {
163        return;
164      }
165
166      if self.unify {
167        return;
168      }
169
170      unsafe {
171        // This fence is needed to prevent reordering of use of the data and
172        // deletion of the data.  Because it is marked `Release`, the decreasing
173        // of the reference count synchronizes with this `Acquire` fence. This
174        // means that use of the data happens before decreasing the reference
175        // count, which happens before this fence, which happens before the
176        // deletion of the data.
177        //
178        // As explained in the [Boost documentation][1],
179        //
180        // > It is important to enforce any possible access to the object in one
181        // > thread (through an existing reference) to *happen before* deleting
182        // > the object in a different thread. This is achieved by a "release"
183        // > operation after dropping a reference (any access to the object
184        // > through this reference must obviously happened before), and an
185        // > "acquire" operation before deleting the object.
186        //
187        // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
188        //
189        // Thread sanitizer does not support atomic fences. Use an atomic load
190        // instead.
191        self.ref_counter.load(Ordering::Acquire);
192        // Drop the data
193        let _ = std::boxed::Box::from_raw(self.meta.as_ptr());
194      }
195    }
196  }
197}
198
199macro_rules! impl_eq_and_ord {
200  ($name:ident($inner:ident < $upper:ident) -> [$($target:ident),+ $(,)?]) => {
201    $(
202      paste::paste! {
203        impl PartialEq<$target> for $name {
204          #[inline]
205          fn eq(&self, other: &$target) -> bool {
206            let val: $upper = self.0.into();
207            val.eq(&(*other as $upper))
208          }
209        }
210
211        impl PartialOrd<$target> for $name {
212          #[inline]
213          fn partial_cmp(&self, other: &$target) -> Option<core::cmp::Ordering> {
214            let val: $upper = self.0.into();
215            val.partial_cmp(&(*other as $upper))
216          }
217        }
218      }
219    )*
220  };
221}
222
223macro_rules! impl_signed_eq_and_ord {
224  ($name:ident($inner:ident < $upper:ident) -> [$($target:ident),+ $(,)?]) => {
225    $(
226      paste::paste! {
227        impl PartialEq<$target> for $name {
228          #[inline]
229          fn eq(&self, other: &$target) -> bool {
230            let val: $upper = self.0.into();
231            (val as i64).eq(&(*other as i64))
232          }
233        }
234
235        impl PartialOrd<$target> for $name {
236          #[inline]
237          fn partial_cmp(&self, other: &$target) -> Option<core::cmp::Ordering> {
238            let val: $upper = self.0.into();
239            (val as i64).partial_cmp(&(*other as i64))
240          }
241        }
242
243        impl PartialEq<$name> for $target {
244          #[inline]
245          fn eq(&self, other: &$name) -> bool {
246            let val: $upper = other.0.into();
247            (*self as i64).eq(&(val as i64))
248          }
249        }
250
251        impl PartialOrd<$name> for $target {
252          #[inline]
253          fn partial_cmp(&self, other: &$name) -> Option<core::cmp::Ordering> {
254            let val: $upper = other.0.into();
255            (*self as i64).partial_cmp(&(val as i64))
256          }
257        }
258      }
259    )*
260  };
261}
262
263macro_rules! impl_ops_for_ux_wrapper {
264  ($name:ident($inner:ident < $upper:ident) -> [$($target:ident),+ $(,)?]) => {
265    $(
266      paste::paste! {
267        impl Add<$target> for $name {
268          type Output = Self;
269
270          fn add(self, rhs: $target) -> Self::Output {
271            let res = rhs as $upper + $upper::from(self.0);
272
273            if res > [<MAX_ $inner:upper>] {
274              panic!("attempt to add with overflow");
275            }
276
277            Self($inner::new(res))
278          }
279        }
280
281        impl AddAssign<$target> for $name {
282          fn add_assign(&mut self, rhs: $target) {
283            let res = rhs as $upper + $upper::from(self.0);
284
285            if res > [<MAX_ $inner:upper>] {
286              panic!("attempt to add with overflow");
287            }
288
289            self.0 = $inner::new(res);
290          }
291        }
292
293        impl Sub<$target> for $name {
294          type Output = Self;
295
296          fn sub(self, rhs: $target) -> Self::Output {
297            let res = rhs as $upper - $upper::from(self.0);
298
299            if res > [<MAX_ $inner:upper>] {
300              panic!("attempt to substract with overflow");
301            }
302
303            Self($inner::new(res))
304          }
305        }
306
307        impl SubAssign<$target> for $name {
308          fn sub_assign(&mut self, rhs: $target) {
309            let res = rhs as $upper - $upper::from(self.0);
310
311            if res > [<MAX_ $inner:upper>] {
312              panic!("attempt to substract with overflow");
313            }
314
315            self.0 = $inner::new(res);
316          }
317        }
318      }
319    )*
320  };
321}
322
323macro_rules! impl_try_from_for_ux_wrapper {
324  ($name:ident($inner:ident < $upper:ident) -> [$($target:ident),+ $(,)?]) => {
325    $(
326      paste::paste! {
327        impl TryFrom<$target> for $name {
328          type Error = TryNewError;
329
330          #[inline]
331          fn try_from(value: $target) -> Result<Self, Self::Error> {
332            $inner::try_new(value as $upper).map(Self)
333          }
334        }
335
336        impl $name {
337          #[doc = "Try to create a" $name " from the given `" $target "`"]
338          #[inline]
339          pub fn [< try_from_ $target >](val: $target) -> Result<Self, TryNewError> {
340            $inner::try_new(val as $upper).map(Self)
341          }
342
343          #[doc = " Creates a new " $name " from the given `" $target "`."]
344          ///
345          /// # Panics
346          #[doc = "- If the given value is greater than `" $inner "::MAX`."]
347          #[inline]
348          pub const fn [< from_ $target _unchecked>](val: $target) -> Self {
349            Self($inner::new(val as $upper))
350          }
351        }
352      }
353    )*
354  };
355}
356
357macro_rules! impl_from_for_ux_wrapper {
358  ($name:ident($inner:ident < $upper:ident) -> [$($target:ident),+ $(,)?]) => {
359    $(
360      paste::paste! {
361        impl From<$target> for $name {
362          #[inline]
363          fn from(version: $target) -> Self {
364            Self($inner::from(version))
365          }
366        }
367
368        impl $name {
369          #[doc = "Creates a new " $name " from the given `" $target "`."]
370          #[inline]
371          pub const fn [< from_ $target>](version: $target) -> Self {
372            Self($inner::new(version as $upper))
373          }
374        }
375      }
376    )*
377  };
378}
379
380macro_rules! impl_into_for_ux_wrapper {
381  ($name:ident($inner:ident < $upper:ident) -> [$($target:ident),+ $(,)?]) => {
382    $(
383      paste::paste! {
384        impl From<$name> for $target {
385          #[inline]
386          fn from(version: $name) -> Self {
387            version.[< to_ $target>]()
388          }
389        }
390
391        impl $name {
392          #[doc = "Converts the " $name " to a `" $target "`."]
393          #[inline]
394          pub fn [< to_ $target>](&self) -> $target {
395            let val: $upper = self.0.into();
396            val as $target
397          }
398        }
399      }
400    )*
401  };
402}
403
404macro_rules! ux_wrapper {
405  (
406    $(
407      $([$meta:meta])*
408      $name:ident($inner:ident < $upper:ident) {
409        min: $min:expr,
410        default: $default:expr,
411        $(bits: $bits:expr,)?
412        $(ord: [$($ord_target:ident),* $(,)?],)?
413        $(signed_ord: [$($signed_ord_target:ident),* $(,)?],)?
414        $(ops: [$($ops_target:ident),* $(,)?],)?
415        $(try_from: [$($try_from_target:ident),* $(,)?],)?
416        $(from: [$($from_target:ident),* $(,)?],)?
417        $(into: [$($into_target:ident),* $(,)?],)?
418      }
419    ),+ $(,)?
420  ) => {
421    $(
422      $(#[$meta])*
423      #[derive(
424        Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
425      )]
426      pub struct $name($inner);
427
428      impl core::fmt::Display for $name {
429        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
430          write!(f, "{}", self.0)
431        }
432      }
433
434      paste::paste! {
435        impl $name {
436          #[doc = "The maximum value of the " $name "."]
437          pub const MAX: Self = Self($inner::MAX);
438
439          #[doc = "The minimum value of the " $name "."]
440          pub const MIN: Self = Self($inner::new($min));
441
442          #[doc = "Creates a new " $name " with the default value."]
443          #[inline]
444          pub const fn new() -> Self {
445            Self($inner::new($default))
446          }
447
448          #[doc = "Creates a new " $name " with the given value."]
449          #[doc = ""]
450          #[doc = "## Panics"]
451          #[doc = "If the given value is greater than `" $inner "::MAX`."]
452          #[inline]
453          pub const fn with(val: $upper) -> Self {
454            Self($inner::new(val))
455          }
456
457          /// Checked integer addition. Computes `self + rhs`, returning `None` if overflow occurred.
458          #[inline]
459          pub fn checked_add(self, rhs: Self) -> Option<Self> {
460            self.0.checked_add(rhs.0).map(Self)
461          }
462
463          /// Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred.
464          #[inline]
465          pub fn checked_sub(self, rhs: Self) -> Option<Self> {
466            self.0.checked_sub(rhs.0).and_then(|val| {
467              if val < $inner::new($min) {
468                None
469              } else {
470                Some(Self(val))
471              }
472            })
473          }
474
475          /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the type.
476          #[inline]
477          pub fn wrapping_add(self, rhs: Self) -> Self {
478            Self(self.0.wrapping_add(rhs.0).max($inner::new($min)))
479          }
480
481          /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the boundary of the type.
482          #[inline]
483          pub fn wrapping_sub(self, rhs: Self) -> Self {
484            let val = self.0.wrapping_sub(rhs.0);
485            if val < $inner::MIN {
486              Self::MAX
487            } else {
488              Self(val)
489            }
490          }
491
492          $(
493            /// Create a native endian integer value from its representation as a byte array in big endian.
494            #[inline]
495            pub const fn from_be_bytes(bytes: [u8; { $bits >> 3 }]) -> Self {
496              Self(UInt::<$upper, $bits>::from_be_bytes(bytes))
497            }
498
499            /// Create a native endian integer value from its representation as a byte array in little endian.
500            #[inline]
501            pub const fn from_le_bytes(bytes: [u8; { $bits >> 3 }]) -> Self {
502              Self(UInt::<$upper, $bits>::from_le_bytes(bytes))
503            }
504
505            /// Returns the native endian representation of the integer as a byte array in big endian.
506            #[inline]
507            pub const fn to_be_bytes(self) -> [u8; { $bits >> 3 }] {
508              self.0.to_be_bytes()
509            }
510
511            /// Returns the native endian representation of the integer as a byte array in little endian.
512            #[inline]
513            pub const fn to_le_bytes(self) -> [u8; { $bits >> 3 }] {
514              self.0.to_le_bytes()
515            }
516          )?
517        }
518      }
519
520      impl Default for $name {
521        #[inline]
522        fn default() -> Self {
523          Self($inner::new($default))
524        }
525      }
526
527      $(
528        impl From<[u8; { $bits >> 3 }]> for $name {
529          #[inline]
530          fn from(bytes: [u8; { $bits >> 3 }]) -> Self {
531            Self($inner::from_be_bytes(bytes))
532          }
533        }
534
535        impl From<$name> for [u8; { $bits >> 3 }] {
536          #[inline]
537          fn from(value: $name) -> Self {
538            value.to_be_bytes()
539          }
540        }
541      )?
542
543      impl From<$inner> for $name {
544        #[inline]
545        fn from(val: $inner) -> Self {
546          Self(val)
547        }
548      }
549
550      impl From<$name> for $inner {
551        #[inline]
552        fn from(value: $name) -> Self {
553          value.0
554        }
555      }
556
557      impl Add for $name {
558        type Output = Self;
559
560        #[inline]
561        fn add(self, rhs: Self) -> Self::Output {
562          Self(self.0.checked_add(rhs.0).expect("attempt to add with overflow"))
563        }
564      }
565
566      impl AddAssign for $name {
567        #[inline]
568        fn add_assign(&mut self, rhs: Self) {
569          self.0 = self.0.checked_add(rhs.0).expect("attempt to add with overflow");
570        }
571      }
572
573      impl Sub for $name {
574        type Output = Self;
575
576        fn sub(self, rhs: Self) -> Self::Output {
577          let val = self.0.checked_sub(rhs.0).expect("attempt to subtract with overflow");
578          if val < $inner::MIN {
579            panic!("attempt to subtract with overflow");
580          }
581
582          Self(val)
583        }
584      }
585
586      impl SubAssign for $name {
587        fn sub_assign(&mut self, rhs: Self) {
588          let val = self.0.checked_sub(rhs.0).expect("attempt to subtract with overflow");
589          if val < $inner::MIN {
590            panic!("attempt to subtract with overflow");
591          }
592          self.0 = val;
593        }
594      }
595
596      $(impl_eq_and_ord!($name($inner < $upper) -> [$($ord_target),*]);)?
597
598      $(impl_signed_eq_and_ord!($name($inner < $upper) -> [$($signed_ord_target),*]);)?
599
600      $(impl_ops_for_ux_wrapper!($name($inner < $upper) -> [$($ops_target),*]);)?
601
602      $(impl_try_from_for_ux_wrapper!($name($inner < $upper) -> [$($try_from_target),*]);)?
603
604      $(impl_from_for_ux_wrapper!($name($inner < $upper) -> [$($from_target),*]);)?
605
606      $(impl_into_for_ux_wrapper!($name($inner < $upper) -> [$($into_target),*]);)?
607    )*
608  };
609}
610
611ux_wrapper! {
612  [doc = "Height which is used to configure the maximum tower height of a skiplist, it is a 5-bit unsigned integer."]
613  Height(u5 < u8) {
614    min: 1,
615    default: 20,
616    ord: [u8, u16, u32, u64, usize],
617    signed_ord: [i8, i16, i32, i64, isize],
618    ops: [u8, u16, u32, u64, usize],
619    try_from: [u8, u16, u32, u64, usize],
620    into: [u8, u16, u32, u64, usize, u128],
621  },
622  [doc = "KeySize which is used to represent a length of a key stored in the skiplist, it is a 27-bit unsigned integer."]
623  KeySize(u27 < u32) {
624    min: 0,
625    default: u16::MAX as u32,
626    ord: [u8, u16, u32, u64, usize],
627    signed_ord: [i8, i16, i32, i64, isize],
628    ops: [u8, u16, u32, u64, usize],
629    try_from: [u32, usize],
630    from: [u8, u16],
631    into: [u32, u64, usize],
632  },
633}
634
635dbutils::builder!(
636  /// A value builder for the `SkipMap`s, which requires the value size for accurate allocation and a closure to build the value.
637  pub ValueBuilder;
638  /// A key builder for the `SkipMap`s, which requires the key size for accurate allocation and a closure to build the key.
639  pub KeyBuilder;
640);