use std::ptr as StdPtr;
use std::sync::atomic::{AtomicPtr, Ordering};
use seize::Collector;
use super::{InlineSuffixBag, SuffixBagCell};
#[derive(Debug)]
pub struct SideCarUtils;
impl SideCarUtils {
pub unsafe fn retire_suffix_bag_cell(ptr: *mut SuffixBagCell, _collector: &Collector) {
unsafe { drop(Box::from_raw(ptr)) };
}
}
#[derive(Debug)]
#[repr(C)]
pub struct SuffixSidecar {
pub(crate) inline: InlineSuffixBag,
pub(crate) external: AtomicPtr<SuffixBagCell>,
}
impl SuffixSidecar {
#[must_use]
pub const fn new() -> Self {
Self {
inline: InlineSuffixBag::new(),
external: AtomicPtr::new(StdPtr::null_mut()),
}
}
}
#[cfg(test)]
impl SuffixSidecar {
pub fn get(&self, slot: usize) -> Option<&[u8]> {
if let Some(suffix) = self.inline.get(slot) {
return Some(suffix);
}
let external: *mut SuffixBagCell = self.external.load(Ordering::Acquire);
if external.is_null() {
None
} else {
unsafe { (*external).as_ref() }.get(slot)
}
}
#[expect(clippy::mut_from_ref, reason = "Interior mutability via UnsafeCell")]
pub unsafe fn ensure_external(&self) -> &mut super::SuffixBag {
let ptr: *mut SuffixBagCell = self.external.load(Ordering::Acquire);
if !ptr.is_null() {
return unsafe { (*ptr).as_mut() };
}
let new_cell: Box<SuffixBagCell> = Box::default();
let new_ptr: *mut SuffixBagCell = Box::into_raw(new_cell);
self.external.store(new_ptr, Ordering::Release);
unsafe { (*new_ptr).as_mut() }
}
pub fn has_suffix(&self, slot: usize) -> bool {
if self.inline.has_suffix(slot) {
return true;
}
let external: *mut SuffixBagCell = self.external.load(Ordering::Acquire);
if external.is_null() {
false
} else {
unsafe { (*external).as_ref() }.has_suffix(slot)
}
}
}
impl Default for SuffixSidecar {
fn default() -> Self {
Self::new()
}
}
impl Drop for SuffixSidecar {
fn drop(&mut self) {
let external: *mut SuffixBagCell = self.external.load(Ordering::Acquire);
if !external.is_null() {
unsafe {
drop(Box::from_raw(external));
}
}
}
}
unsafe impl Send for SuffixSidecar {}
unsafe impl Sync for SuffixSidecar {}