#![cfg_attr(test, feature(test))]
extern crate libc;
extern crate nix;
use std::{
alloc::{alloc, dealloc, Layout},
error, fmt,
mem::{size_of, MaybeUninit},
ptr,
};
use nix::errno::Errno;
pub const GREATER: &str = ">";
pub const GREATER_EQUAL: &str = ">=";
pub const LESSER: &str = "<";
pub const LESSER_EQUAL: &str = "<=";
pub const EQUAL: &str = "=";
pub const BEGIN: &str = "^";
pub const END: &str = "$";
pub const RAX_NODE_MAX_SIZE: libc::c_int = (1 << 29) - 1;
pub const RAX_STACK_STATIC_ITEMS: libc::c_int = 32;
pub const RAX_ITER_STATIC_LEN: libc::c_int = 128;
pub const RAX_ITER_JUST_SEEKED: libc::c_int = 1 << 0;
pub const RAX_ITER_EOF: libc::c_int = 1 << 1;
pub const RAX_ITER_SAFE: libc::c_int = 1 << 2;
pub unsafe fn allocator() -> (
extern "C" fn(size: libc::size_t) -> *mut u8,
extern "C" fn(ptr: *mut libc::c_void, size: libc::size_t) -> *mut u8,
extern "C" fn(ptr: *mut libc::c_void),
) {
(rax_malloc, rax_realloc, rax_free)
}
pub unsafe fn set_allocator(
malloc: extern "C" fn(size: libc::size_t) -> *mut u8,
realloc: extern "C" fn(ptr: *mut libc::c_void, size: libc::size_t) -> *mut u8,
free: extern "C" fn(ptr: *mut libc::c_void),
) {
rax_malloc = malloc;
rax_realloc = realloc;
rax_free = free;
}
#[derive(Debug)]
pub enum RaxError {
Generic(GenericError),
OutOfMemory(),
}
impl RaxError {
pub fn generic(message: &str) -> RaxError {
RaxError::Generic(GenericError::new(message))
}
}
pub struct RaxMap<K: RaxKey, V> {
pub rax: *mut rax,
phantom: std::marker::PhantomData<(K, V)>,
}
impl<K: RaxKey, V> Drop for RaxMap<K, V> {
fn drop(&mut self) {
unsafe {
raxFreeWithCallback(self.rax, RaxFreeWithCallbackWrapper::<V>);
}
}
}
unsafe impl<K: RaxKey + Send, V: Send> Send for RaxMap<K, V> {}
unsafe impl<K: RaxKey + Sync, V: Sync> Sync for RaxMap<K, V> {}
impl<K: RaxKey, V> Default for RaxMap<K, V> {
fn default() -> Self {
Self::new()
}
}
impl<K: RaxKey, V> RaxMap<K, V> {
pub fn new() -> RaxMap<K, V> {
#[expect(clippy::disallowed_methods)]
Self::try_new().expect("raxNew: out of memory")
}
pub fn try_new() -> Result<RaxMap<K, V>, RaxError> {
let ptr = unsafe { raxNew() };
if ptr.is_null() {
return Err(RaxError::OutOfMemory());
}
Ok(RaxMap {
rax: ptr,
phantom: std::marker::PhantomData,
})
}
pub fn len(&self) -> u64 {
unsafe { raxSize(self.rax) }
}
pub fn size(&self) -> u64 {
unsafe { raxSize(self.rax) }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn show(&self) {
unsafe { raxShow(self.rax) }
}
pub fn insert_null(&mut self, key: K) -> Result<Option<V>, RaxError> {
unsafe {
let old: &mut *mut u8 = &mut ptr::null_mut();
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxInsert(
self.rax,
ptr,
len,
std::ptr::null_mut(),
old,
);
if r == 0 && Errno::last() == Errno::ENOMEM {
Err(RaxError::OutOfMemory())
} else if old.is_null() {
Ok(None)
} else {
let old_ptr = *old as *mut V;
let value = ptr::read(old_ptr);
let layout = Layout::new::<V>();
if layout.size() != 0 {
dealloc(old_ptr as *mut u8, layout);
}
Ok(Some(value))
}
}
}
pub fn try_insert(&mut self, key: K, data: V) -> Result<Option<V>, RaxError> {
let value_ptr = try_alloc_value(data).map_err(|_| RaxError::OutOfMemory())?;
unsafe {
let old: &mut *mut u8 = &mut ptr::null_mut();
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxTryInsert(
self.rax,
ptr,
len,
value_ptr as *mut u8,
old,
);
if r == 0 {
let value = ptr::read(value_ptr);
let layout = Layout::new::<V>();
if layout.size() != 0 {
dealloc(value_ptr as *mut u8, layout);
}
if Errno::last() == Errno::ENOMEM {
Err(RaxError::OutOfMemory())
} else {
Ok(Some(value))
}
} else if old.is_null() {
Ok(None)
} else {
let old_ptr = *old as *mut V;
let value = ptr::read(old_ptr);
let layout = Layout::new::<V>();
if layout.size() != 0 {
dealloc(old_ptr as *mut u8, layout);
}
Ok(Some(value))
}
}
}
pub unsafe fn try_insert_ptr(
&mut self,
key: K,
value: *mut u8,
) -> Result<Option<*mut u8>, RaxError> {
let old: &mut *mut u8 = &mut ptr::null_mut();
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxTryInsert(
self.rax,
ptr, len, value, old,
);
if r == 0 {
if Errno::last() == Errno::ENOMEM {
Err(RaxError::OutOfMemory())
} else {
Ok(Some(value))
}
} else if old.is_null() {
Ok(None)
} else {
Ok(Some(*old))
}
}
pub fn insert(&mut self, key: K, data: V) -> Result<Option<V>, RaxError> {
let value_ptr = try_alloc_value(data).map_err(|_| RaxError::OutOfMemory())?;
unsafe {
let old: &mut *mut u8 = &mut ptr::null_mut();
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxInsert(
self.rax,
ptr,
len,
value_ptr as *mut u8,
old,
);
if r == 0 && Errno::last() == Errno::ENOMEM {
dealloc_value(value_ptr);
Err(RaxError::OutOfMemory())
} else if old.is_null() {
Ok(None)
} else {
let old_ptr = *old as *mut V;
let value = ptr::read(old_ptr);
let layout = Layout::new::<V>();
if layout.size() != 0 {
dealloc(old_ptr as *mut u8, layout);
}
Ok(Some(value))
}
}
}
pub unsafe fn insert_ptr(
&mut self,
key: K,
value: *mut u8,
) -> Result<Option<*mut u8>, RaxError> {
let old: &mut *mut u8 = &mut ptr::null_mut();
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxInsert(
self.rax,
ptr, len, value, old,
);
if r == 0 && Errno::last() == Errno::ENOMEM {
Err(RaxError::OutOfMemory())
} else if old.is_null() {
Ok(None)
} else {
Ok(Some(*old))
}
}
pub fn remove(&mut self, key: K) -> (bool, Option<V>) {
unsafe {
let old: &mut *mut u8 = &mut ptr::null_mut();
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxRemove(self.rax, ptr, len, old);
if old.is_null() {
(r == 1, None)
} else {
let old_ptr = *old as *mut V;
let value = ptr::read(old_ptr);
let layout = Layout::new::<V>();
if layout.size() != 0 {
dealloc(old_ptr as *mut u8, layout);
}
(r == 1, Some(value))
}
}
}
pub fn find_exists(&self, key: K) -> (bool, Option<&V>) {
unsafe {
let k = key.encode();
let (ptr, len) = k.to_buf();
let value = raxFind(self.rax, ptr, len);
if value.is_null() {
(true, None)
} else if value == raxNotFound {
(false, None)
} else {
(true, Some(&*(value as *const V)))
}
}
}
pub fn find(&self, key: K) -> Option<&V> {
unsafe {
let k = key.encode();
let (ptr, len) = k.to_buf();
let value = raxFind(self.rax, ptr, len);
if value.is_null() || value == raxNotFound {
None
} else {
Some(&*(value as *const V))
}
}
}
pub fn get(&self, key: K) -> Option<&V> {
unsafe {
let k = key.encode();
let (ptr, len) = k.to_buf();
let value = raxFind(self.rax, ptr, len);
if value.is_null() || value == raxNotFound {
None
} else {
Some(&*(value as *const V))
}
}
}
pub fn exists(&self, key: K) -> bool {
unsafe {
let k = key.encode();
let (ptr, len) = k.to_buf();
let value = raxFind(self.rax, ptr, len);
!(value.is_null() || value == raxNotFound)
}
}
pub fn seek_min<F>(&mut self, f: F)
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_min();
f(self, &mut iter)
}
}
pub fn seek_min_result<R, F>(&mut self, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_min();
f(self, &mut iter)
}
}
pub fn seek_max<F>(&mut self, f: F)
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_max();
f(self, &mut iter)
}
}
pub fn seek_max_result<R, F>(&mut self, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_max();
f(self, &mut iter)
}
}
pub fn seek<F>(&mut self, op: &str, key: K, f: F)
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek(op, key);
f(self, &mut iter)
}
}
pub fn seek_result<R, F>(&mut self, op: &str, key: K, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek(op, key);
f(self, &mut iter)
}
}
pub fn iter<F>(&mut self, f: F)
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
f(self, &mut iter)
}
}
pub fn iter_result<F, R>(&mut self, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxMap<K, V>, &mut RaxIterator<K, V>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
f(self, &mut iter)
}
}
}
pub struct RaxSet<K: RaxKey> {
rax: *mut rax,
_marker: std::marker::PhantomData<K>,
}
impl<K: RaxKey> Drop for RaxSet<K> {
fn drop(&mut self) {
unsafe { raxFree(self.rax) }
}
}
unsafe impl<K: RaxKey + Send> Send for RaxSet<K> {}
unsafe impl<K: RaxKey + Sync> Sync for RaxSet<K> {}
impl<K: RaxKey> Default for RaxSet<K> {
fn default() -> Self {
Self::new()
}
}
impl<K: RaxKey> RaxSet<K> {
pub fn new() -> RaxSet<K> {
#[expect(clippy::disallowed_methods)]
Self::try_new().expect("raxNew: out of memory")
}
pub fn try_new() -> Result<RaxSet<K>, RaxError> {
let ptr = unsafe { raxNew() };
if ptr.is_null() {
return Err(RaxError::OutOfMemory());
}
Ok(RaxSet {
rax: ptr,
_marker: std::marker::PhantomData,
})
}
pub fn len(&self) -> u64 {
unsafe { raxSize(self.rax) }
}
pub fn size(&self) -> u64 {
unsafe { raxSize(self.rax) }
}
pub fn show(&self) {
unsafe { raxShow(self.rax) }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn insert(&mut self, key: K) -> Result<bool, RaxError> {
unsafe {
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxTryInsert(
self.rax,
ptr,
len,
std::ptr::null_mut(),
std::ptr::null_mut(),
);
if r == 0 {
if Errno::last() == Errno::ENOMEM {
Err(RaxError::OutOfMemory())
} else {
Ok(false)
}
} else {
Ok(true)
}
}
}
pub fn remove(&mut self, key: K) -> bool {
unsafe {
let k = key.encode();
let (ptr, len) = k.to_buf();
let r = raxRemove(self.rax, ptr, len, &mut std::ptr::null_mut());
r == 1
}
}
pub fn exists(&self, key: K) -> bool {
unsafe {
let k = key.encode();
let (ptr, len) = k.to_buf();
let value = raxFind(self.rax, ptr, len);
value != raxNotFound
}
}
pub fn seek_min<F>(&mut self, f: F)
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_min();
f(self, &mut iter)
}
}
pub fn seek_min_result<R, F>(&mut self, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_min();
f(self, &mut iter)
}
}
pub fn seek_max<F>(&mut self, f: F)
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_max();
f(self, &mut iter)
}
}
pub fn seek_max_result<R, F>(&mut self, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek_max();
f(self, &mut iter)
}
}
pub fn seek<F>(&mut self, op: &str, key: K, f: F)
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek(op, key);
f(self, &mut iter)
}
}
pub fn seek_result<R, F>(&mut self, op: &str, key: K, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter.seek(op, key);
f(self, &mut iter)
}
}
pub fn iter<F>(&mut self, f: F)
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>),
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
f(self, &mut iter)
}
}
pub fn iter_result<F, R>(&mut self, f: F) -> Result<R, RaxError>
where
F: Fn(&mut RaxSet<K>, &mut RaxIterator<K, usize>) -> Result<R, RaxError>,
{
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, usize>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, self.rax);
let mut iter = iter.assume_init();
iter.fixup();
f(self, &mut iter)
}
}
}
pub trait RaxKey<RHS = Self>: Clone + Default + std::fmt::Debug {
type Output: RaxKey;
fn encode(self) -> Self::Output;
fn to_buf(&self) -> (*const u8, usize);
unsafe fn from_buf(ptr: *const u8, len: usize) -> RHS;
}
impl RaxKey for f32 {
type Output = u32;
fn encode(self) -> Self::Output {
self.to_bits().to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(
self as *const _ as *const u8,
std::mem::size_of::<Self::Output>(),
)
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> f32 {
assert_eq!(len, std::mem::size_of::<f32>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe {
f32::from_bits(u32::from_be(
*(ptr as *mut [u8; std::mem::size_of::<Self::Output>()] as *mut u32),
))
}
}
}
impl RaxKey for f64 {
type Output = u64;
fn encode(self) -> Self::Output {
self.to_bits().to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> f64 {
assert_eq!(len, std::mem::size_of::<f64>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe {
f64::from_bits(u64::from_be(
*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut u64),
))
}
}
}
impl RaxKey for isize {
type Output = isize;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> isize {
assert_eq!(len, std::mem::size_of::<isize>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { isize::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut isize)) }
}
}
impl RaxKey for usize {
type Output = usize;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(
self as *const _ as *const u8,
std::mem::size_of::<Self::Output>(),
)
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> usize {
assert_eq!(len, std::mem::size_of::<usize>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe {
usize::from_be(*(ptr as *mut [u8; std::mem::size_of::<Self::Output>()] as *mut usize))
}
}
}
impl RaxKey for i16 {
type Output = i16;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> Self {
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { i16::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut i16)) }
}
}
impl RaxKey for u16 {
type Output = u16;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> u16 {
assert_eq!(len, std::mem::size_of::<u16>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { u16::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut u16)) }
}
}
impl RaxKey for i32 {
type Output = i32;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> i32 {
assert_eq!(len, std::mem::size_of::<i32>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { i32::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut i32)) }
}
}
impl RaxKey for u32 {
type Output = u32;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> u32 {
assert_eq!(len, std::mem::size_of::<u32>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { u32::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut u32)) }
}
}
impl RaxKey for i64 {
type Output = i64;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> i64 {
assert_eq!(len, std::mem::size_of::<i64>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { i64::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut i64)) }
}
}
impl RaxKey for u64 {
type Output = u64;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> u64 {
assert_eq!(len, std::mem::size_of::<u64>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { u64::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut u64)) }
}
}
impl RaxKey for i128 {
type Output = i128;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> i128 {
assert_eq!(len, std::mem::size_of::<i128>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { i128::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut i128)) }
}
}
impl RaxKey for u128 {
type Output = u128;
fn encode(self) -> Self::Output {
self.to_be()
}
fn to_buf(&self) -> (*const u8, usize) {
(self as *const _ as *const u8, size_of::<Self::Output>())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> u128 {
assert_eq!(len, std::mem::size_of::<u128>());
if len != size_of::<Self::Output>() {
return Self::default();
}
unsafe { u128::from_be(*(ptr as *mut [u8; size_of::<Self::Output>()] as *mut u128)) }
}
}
impl RaxKey for Vec<u8> {
type Output = Vec<u8>;
fn encode(self) -> Vec<u8> {
self
}
fn to_buf(&self) -> (*const u8, usize) {
(self.as_ptr(), self.len())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> Vec<u8> {
unsafe { std::slice::from_raw_parts(ptr, len).to_vec() }
}
}
impl<'a> RaxKey for &'a [u8] {
type Output = &'a [u8];
fn encode(self) -> &'a [u8] {
self
}
fn to_buf(&self) -> (*const u8, usize) {
(self.as_ptr(), self.len())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> &'a [u8] {
unsafe { std::slice::from_raw_parts(ptr, len) }
}
}
impl<'a> RaxKey for &'a str {
type Output = &'a str;
fn encode(self) -> Self::Output {
self
}
fn to_buf(&self) -> (*const u8, usize) {
((*self).as_ptr(), self.len())
}
unsafe fn from_buf(ptr: *const u8, len: usize) -> &'a str {
unsafe { std::str::from_utf8(std::slice::from_raw_parts(ptr, len)).unwrap_or_default() }
}
}
#[repr(C)]
pub struct RaxIterator<K: RaxKey, V> {
pub flags: libc::c_int,
pub rt: *mut rax,
pub key: *mut u8,
pub data: *mut libc::c_void,
pub key_len: libc::size_t,
pub key_max: libc::size_t,
pub key_static_string: [u8; 128],
pub node: *mut raxNode,
pub stack: raxStack,
pub node_cb: Option<raxNodeCallback>,
_marker: std::marker::PhantomData<(K, V)>,
}
impl<K: RaxKey, V> Drop for RaxIterator<K, V> {
fn drop(&mut self) {
unsafe {
if self.key_max == RAX_ITER_STATIC_LEN as usize {
self.key = self.key_static_string.as_mut_ptr();
}
if self.stack.maxitems == RAX_STACK_STATIC_ITEMS as usize {
self.stack.stack = self.stack.static_items.as_mut_ptr();
}
raxStop(&raw mut *self as *mut raxIterator);
}
}
}
impl<K: RaxKey, V: 'static> Iterator for RaxIterator<K, V> {
type Item = (K, Option<&'static V>);
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if raxNext(&raw mut *self as *mut raxIterator) == 1 {
let data: *mut libc::c_void = self.data;
if data.is_null() {
None
} else {
let val = data as *const V;
if val.is_null() {
Some((self.key(), None))
} else {
Some((self.key(), Some(&*val)))
}
}
} else {
None
}
}
}
}
impl<K: RaxKey, V: 'static> DoubleEndedIterator for RaxIterator<K, V> {
fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if raxPrev(&raw mut *self as *mut raxIterator) == 1 {
let data: *mut libc::c_void = self.data;
if data.is_null() {
None
} else {
let val = data as *const V;
if val.is_null() {
Some((self.key(), None))
} else {
Some((self.key(), Some(&*val)))
}
}
} else {
None
}
}
}
}
impl<K: RaxKey, V> RaxIterator<K, V> {
pub fn new(r: RaxMap<K, V>) -> RaxIterator<K, V> {
unsafe {
let mut iter = MaybeUninit::<RaxIterator<K, V>>::uninit();
raxStart(iter.as_mut_ptr() as *mut raxIterator, r.rax);
let mut iter = iter.assume_init();
iter.fixup();
iter
}
}
pub fn print_ptr(&self) {
println!("ptr = {:p}", self);
println!("ptr = {:p}", self as *const _ as *const raxIterator);
}
pub fn seek_min(&mut self) -> bool {
unsafe {
if raxSeek(
&raw mut *self as *mut raxIterator,
BEGIN.as_ptr(),
std::ptr::null(),
0,
) == 1
{
self.forward()
} else {
false
}
}
}
pub fn seek_max(&mut self) -> bool {
unsafe {
if raxSeek(
&raw mut *self as *mut raxIterator,
END.as_ptr(),
std::ptr::null(),
0,
) == 1
{
self.back()
} else {
false
}
}
}
pub fn back(&mut self) -> bool {
unsafe { raxPrev(&raw mut *self as *mut raxIterator) == 1 }
}
pub fn forward(&mut self) -> bool {
unsafe { raxNext(&raw mut *self as *mut raxIterator) == 1 }
}
pub fn key(&self) -> K {
unsafe { K::from_buf(self.key, self.key_len) }
}
pub fn key_bytes(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.key, self.key_len) }
}
pub fn value(&self) -> Option<&V> {
unsafe {
let data: *mut libc::c_void = self.data;
if data.is_null() {
None
} else {
Some(&*(data as *const V))
}
}
}
pub fn lesser(&mut self, key: K) -> bool {
self.seek(LESSER, key)
}
pub fn lesser_equal(&mut self, key: K) -> bool {
self.seek(LESSER_EQUAL, key)
}
pub fn greater(&mut self, key: K) -> bool {
self.seek(GREATER, key)
}
pub fn greater_equal(&mut self, key: K) -> bool {
self.seek(GREATER_EQUAL, key)
}
pub fn seek(&mut self, op: &str, key: K) -> bool {
unsafe {
let k = key.encode();
let (p, len) = k.to_buf();
raxSeek(&raw mut *self as *mut raxIterator, op.as_ptr(), p, len) == 1
&& self.flags & RAX_ITER_EOF != 0
}
}
pub fn seek_raw(&mut self, op: &str, key: K) -> i32 {
unsafe {
let k = key.encode();
let (p, len) = k.to_buf();
raxSeek(&raw mut *self as *mut raxIterator, op.as_ptr(), p, len)
}
}
pub fn seek_bytes(&mut self, op: &str, ele: &[u8]) -> bool {
unsafe {
raxSeek(
&raw mut *self as *mut raxIterator,
op.as_ptr(),
ele.as_ptr(),
ele.len() as libc::size_t,
) == 1
}
}
pub fn eof(&self) -> bool {
self.flags & RAX_ITER_EOF != 0
}
pub fn fixup(&mut self) {
self.key = self.key_static_string.as_mut_ptr();
self.stack.stack = self.stack.static_items.as_mut_ptr();
}
}
impl fmt::Display for RaxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
RaxError::Generic(ref err) => write!(f, "{err}"),
RaxError::OutOfMemory() => write!(f, "out of memory"),
}
}
}
impl error::Error for RaxError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
RaxError::Generic(ref err) => Some(err),
RaxError::OutOfMemory() => Some(self),
}
}
}
#[derive(Debug)]
pub struct GenericError {
message: String,
}
impl GenericError {
pub fn new(message: &str) -> GenericError {
GenericError {
message: String::from(message),
}
}
}
impl fmt::Display for GenericError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Store error: {}", self.message)
}
}
impl error::Error for GenericError {}
fn try_alloc_value<T>(value: T) -> Result<*mut T, T> {
let layout = Layout::new::<T>();
unsafe {
let ptr = if layout.size() == 0 {
ptr::NonNull::<T>::dangling().as_ptr()
} else {
let raw = alloc(layout);
if raw.is_null() {
return Err(value);
}
raw as *mut T
};
ptr.write(value);
Ok(ptr)
}
}
unsafe fn dealloc_value<T>(ptr: *mut T) {
ptr::drop_in_place(ptr);
let layout = Layout::new::<T>();
if layout.size() != 0 {
dealloc(ptr as *mut u8, layout);
}
}
#[repr(C)]
pub struct rax;
#[repr(C)]
pub struct raxNode;
#[repr(C)]
pub struct raxStack {
stack: *mut *mut libc::c_void,
items: libc::size_t,
maxitems: libc::size_t,
static_items: [*mut libc::c_void; 32],
oom: libc::c_int,
}
#[repr(C)]
pub struct raxIterator;
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
extern "C" fn RaxFreeWithCallbackWrapper<V>(v: *mut libc::c_void) {
unsafe {
dealloc_value(v as *mut V);
}
}
#[allow(non_camel_case_types)]
type raxNodeCallback = extern "C" fn(v: *mut libc::c_void);
type RaxFreeCallback = extern "C" fn(v: *mut libc::c_void);
#[allow(improper_ctypes)]
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
#[link(name = "rax", kind = "static")]
extern "C" {
pub static raxNotFound: *mut u8;
pub static mut rax_malloc: extern "C" fn(size: libc::size_t) -> *mut u8;
pub static mut rax_realloc:
extern "C" fn(ptr: *mut libc::c_void, size: libc::size_t) -> *mut u8;
pub static mut rax_free: extern "C" fn(ptr: *mut libc::c_void);
pub fn raxIteratorSize() -> libc::c_int;
pub fn raxNew() -> *mut rax;
pub fn raxFree(rax: *mut rax);
pub fn raxFreeWithCallback(rax: *mut rax, callback: RaxFreeCallback);
pub fn raxInsert(
rax: *mut rax,
s: *const u8,
len: libc::size_t,
data: *const u8,
old: &mut *mut u8,
) -> libc::c_int;
pub fn raxTryInsert(
rax: *mut rax,
s: *const u8,
len: libc::size_t,
data: *const u8,
old: *mut *mut u8,
) -> libc::c_int;
pub fn raxRemove(
rax: *mut rax,
s: *const u8,
len: libc::size_t,
old: &mut *mut u8,
) -> libc::c_int;
pub fn raxFind(rax: *mut rax, s: *const u8, len: libc::size_t) -> *mut u8;
pub fn raxIteratorNew(rt: *mut rax) -> *mut raxIterator;
pub fn raxStart(it: *mut raxIterator, rt: *mut rax);
pub fn raxSeek(
it: *mut raxIterator,
op: *const u8,
ele: *const u8,
len: libc::size_t,
) -> libc::c_int;
pub fn raxNext(it: *mut raxIterator) -> libc::c_int;
pub fn raxPrev(it: *mut raxIterator) -> libc::c_int;
pub fn raxRandomWalk(it: *mut raxIterator, steps: libc::size_t) -> libc::c_int;
pub fn raxCompare(
it: *mut raxIterator,
op: *const u8,
key: *mut u8,
key_len: libc::size_t,
) -> libc::c_int;
pub fn raxStop(it: *mut raxIterator);
pub fn raxEOF(it: *mut raxIterator) -> libc::c_int;
pub fn raxShow(rax: *mut rax);
pub fn raxSize(rax: *mut rax) -> u64;
}
#[cfg(test)]
mod tests {
extern crate test;
use std::{
self,
default::Default,
fmt,
time::{Duration, Instant},
};
use super::*;
extern "C" fn rax_malloc_hook(size: libc::size_t) -> *mut u8 {
unsafe {
println!("malloc");
libc::malloc(size) as *mut u8
}
}
extern "C" fn rax_realloc_hook(ptr: *mut libc::c_void, size: libc::size_t) -> *mut u8 {
unsafe {
println!("realloc");
libc::realloc(ptr, size) as *mut u8
}
}
extern "C" fn rax_free_hook(ptr: *mut libc::c_void) {
unsafe {
println!("free");
libc::free(ptr)
}
}
pub struct MyMsg<'a>(&'a str);
impl<'a> Drop for MyMsg<'a> {
fn drop(&mut self) {
println!("dropped -> {}", self.0);
}
}
#[derive(Clone, Copy)]
pub struct Stopwatch {
start_time: Option<Instant>,
elapsed: Duration,
}
impl Default for Stopwatch {
fn default() -> Stopwatch {
Stopwatch {
start_time: None,
elapsed: Duration::from_secs(0),
}
}
}
impl fmt::Display for Stopwatch {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
return write!(f, "{}ms", self.elapsed_ms());
}
}
#[expect(unused)]
impl Stopwatch {
pub fn new() -> Stopwatch {
let sw: Stopwatch = Default::default();
return sw;
}
pub fn start_new() -> Stopwatch {
let mut sw = Stopwatch::new();
sw.start();
return sw;
}
pub fn start(&mut self) {
self.start_time = Some(Instant::now());
}
pub fn stop(&mut self) {
self.elapsed = self.elapsed();
self.start_time = None;
}
pub fn reset(&mut self) {
self.elapsed = Duration::from_secs(0);
self.start_time = None;
}
pub fn restart(&mut self) {
self.reset();
self.start();
}
pub fn is_running(&self) -> bool {
return self.start_time.is_some();
}
pub fn elapsed(&self) -> Duration {
match self.start_time {
Some(t1) => {
return t1.elapsed() + self.elapsed;
}
None => {
return self.elapsed;
}
}
}
pub fn elapsed_ms(&self) -> i64 {
let dur = self.elapsed();
return (dur.as_secs() * 1000 + (dur.subsec_nanos() / 1000000) as u64) as i64;
}
}
#[test]
fn bench() {
let ops = 1000000;
println!("{} operations per function", ops);
for _ in 0..2 {
println!();
println!("Gets...");
{
let r = &mut RaxSet::<u64>::new();
for x in 0..2000 {
r.insert(x).expect("whoops!");
}
let sw = Stopwatch::start_new();
for _po in 0..ops {
r.exists(1601);
}
println!("RaxSet::get {}ms", sw.elapsed_ms());
}
{
let r = &mut RaxMap::<u64, &str>::new();
for x in 0..2000 {
r.insert_null(x).expect("whoops!");
}
match r.find(1601) {
Some(v) => println!("{}", v),
None => {}
}
let sw = Stopwatch::start_new();
for _po in 0..ops {
r.find(1601);
}
println!("RaxMap::get {}ms", sw.elapsed_ms());
}
{
let r = &mut RaxMap::<u64, &str>::new();
for x in 0..2000 {
r.insert_null(x).expect("whoops!");
}
let sw = Stopwatch::start_new();
for _po in 0..ops {
r.iter(|_, iter| {
iter.seek(EQUAL, 1601);
});
}
println!("RaxCursor:seek {}ms", sw.elapsed_ms());
}
{
let r = &mut std::collections::HashSet::<u64>::new();
for x in 0..2000 {
r.insert(x);
}
let sw = Stopwatch::start_new();
let xx = 300;
for _po in 0..ops {
r.get(&xx);
}
println!("HashSet::get {}ms", sw.elapsed_ms());
}
{
let r = &mut std::collections::HashMap::<u64, &str>::new();
for x in 0..2000 {
r.insert(x, "");
}
let sw = Stopwatch::start_new();
let xx = 300;
for _po in 0..ops {
r.get(&xx);
}
println!("HashMap::get {}ms", sw.elapsed_ms());
}
{
let r = &mut std::collections::BTreeSet::<u64>::new();
for x in 0..2000 {
r.insert(x);
}
let sw = Stopwatch::start_new();
let xx = 300;
for _po in 0..ops {
r.get(&xx);
}
println!("BTreeSet::get {}ms", sw.elapsed_ms());
}
{
let r = &mut std::collections::BTreeMap::<u64, &str>::new();
for x in 0..2000 {
r.insert(x, "");
}
let sw = Stopwatch::start_new();
let xx = 300;
for _po in 0..ops {
r.get(&xx);
}
println!("BTreeMap::get {}ms", sw.elapsed_ms());
}
println!();
println!("Inserts...");
{
let r = &mut RaxMap::<u64, &str>::new();
let sw = Stopwatch::start_new();
for x in 0..ops {
r.insert(x, "").expect("whoops!");
}
println!("RaxMap::insert {}ms", sw.elapsed_ms());
}
{
let r = &mut RaxSet::<u64>::new();
let sw = Stopwatch::start_new();
for x in 0..ops {
r.insert(x).expect("whoops!");
}
println!("RaxSet::insert {}ms", sw.elapsed_ms());
}
{
let r = &mut std::collections::BTreeSet::<u64>::new();
let sw = Stopwatch::start_new();
for x in 0..ops {
r.insert(x);
}
println!("BTreeSet::insert {}ms", sw.elapsed_ms());
}
{
let r = &mut std::collections::BTreeMap::<u64, &str>::new();
let sw = Stopwatch::start_new();
for x in 0..ops {
r.insert(x, "");
}
println!("BTreeMap::insert {}ms", sw.elapsed_ms());
}
{
let r = &mut std::collections::HashMap::<u64, &str>::new();
let sw = Stopwatch::start_new();
for x in 0..ops {
r.insert(x, "");
}
println!("HashMap::insert {}ms", sw.elapsed_ms());
}
}
}
#[test]
fn bench_rax_find() {
for _ in 0..10 {
let r = &mut RaxMap::<u64, &str>::new();
for x in 0..2000 {
r.insert_null(x).expect("whoops!");
}
match r.find(1601) {
Some(v) => println!("{}", v),
None => {}
}
let sw = Stopwatch::start_new();
for _po in 0..1000000 {
r.find(1601);
}
println!("Thing took {}ms", sw.elapsed_ms());
}
}
#[test]
fn bench_rax_cur_find() {
for _ in 0..10 {
let r = &mut RaxMap::<u64, &str>::new();
for x in 0..2000 {
r.insert_null(x).expect("whoops!");
}
match r.find(1601) {
Some(v) => println!("{}", v),
None => {}
}
let sw = Stopwatch::start_new();
for _po in 0..1000000 {
r.iter(|_, iter| {
iter.seek(EQUAL, 1601);
});
}
println!("RaxMap::cursor_find {}ms", sw.elapsed_ms());
}
}
#[test]
fn bench_rax_insert() {
for _ in 0..10 {
let r = &mut RaxMap::<u64, &str>::new();
let sw = Stopwatch::start_new();
for x in 0..1000000 {
r.insert(x, "").expect("whoops!");
}
println!("RaxMap::insert {}ms", sw.elapsed_ms());
println!("Size {}", r.size());
}
}
#[test]
fn bench_rax_insert_show() {
let r = &mut RaxMap::<u64, &str>::new();
let sw = Stopwatch::start_new();
for x in 0..100 {
r.insert(x, "").expect("whoops!");
}
r.show();
println!("RaxMap::insert {}ms", sw.elapsed_ms());
assert_eq!(r.size(), 100);
}
#[test]
fn bench_rax_replace() {
let ops = 1000000;
for _ in 0..2 {
let r = &mut RaxMap::<u64, &str>::new();
for x in 0..ops {
r.insert(x, "").expect("whoops!");
}
let sw = Stopwatch::start_new();
for x in 0..ops {
r.insert(x, "").expect("whoops!");
}
println!("RaxMap::replace {}ms", sw.elapsed_ms());
assert_eq!(r.size(), ops);
}
}
#[test]
fn key_str() {
unsafe {
set_allocator(rax_malloc_hook, rax_realloc_hook, rax_free_hook);
}
let mut r = RaxMap::<&str, MyMsg>::new();
let key = "hello-way";
r.insert(key, MyMsg("world 80")).expect("whoops!");
r.insert("hello-war", MyMsg("world 80")).expect("whoops!");
r.insert("hello-wares", MyMsg("world 80")).expect("whoops!");
r.insert("hello", MyMsg("world 100")).expect("whoops!");
{
match r.find("hello") {
Some(v) => println!("Found {}", v.0),
None => println!("Not Found"),
}
}
r.show();
r.iter(|_, iter| {
if !iter.seek_min() {
return;
}
while iter.forward() {
println!("{}", iter.key());
}
if !iter.seek_max() {
return;
}
while iter.back() {
println!("{}", iter.key());
}
});
}
#[test]
fn key_f64() {
println!("sizeof(Rax) {}", std::mem::size_of::<RaxMap<f64, MyMsg>>());
let mut r = RaxMap::<f64, MyMsg>::new();
r.insert(100.01, MyMsg("world 100")).expect("whoops!");
r.insert(80.20, MyMsg("world 80")).expect("whoops!");
r.insert(100.00, MyMsg("world 200")).expect("whoops!");
r.insert(99.10, MyMsg("world 1")).expect("whoops!");
r.show();
r.iter(|_, iter| {
iter.seek_min();
while iter.forward() {
println!("{}", iter.key());
}
iter.seek_max();
while iter.back() {
println!("{}", iter.key());
}
});
}
#[test]
fn key_u64() {
println!("sizeof(Rax) {}", std::mem::size_of::<RaxMap<u64, MyMsg>>());
let mut r = RaxMap::<u64, MyMsg>::new();
r.insert(100, MyMsg("world 100")).expect("whoops!");
r.insert(80, MyMsg("world 80")).expect("whoops!");
r.insert(200, MyMsg("world 200")).expect("whoops!");
r.insert(1, MyMsg("world 1")).expect("whoops!");
r.show();
r.seek_min(|_, it| {
for (key, value) in it.rev() {
println!("Key Len = {}", key);
println!("Data = {}", value.unwrap().0);
}
});
}
}