|
|
|
use core::{hash::Hash, ptr::NonNull};
|
|
|
|
|
|
|
|
/// Wrapper for an interned str pointer, required to
|
|
|
|
/// quickly check using a hash if a string is inside an [`Interner`][`super::Interner`].
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// This struct could cause Undefined Behaviour on:
|
|
|
|
/// - Use without ensuring the referenced memory is still allocated.
|
|
|
|
/// - Construction of an [`InternedStr`] from an invalid [`NonNull<Char>`] pointer.
|
|
|
|
/// - Construction of an [`InternedStr`] from a [`NonNull<Char>`] pointer
|
|
|
|
/// without checking if the pointed memory of the [`NonNull<Char>`] outlives
|
|
|
|
/// the [`InternedStr`].
|
|
|
|
///
|
|
|
|
/// In general, this should not be used outside of an [`Interner`][`super::Interner`].
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub(super) struct InternedStr<Char> {
|
|
|
|
ptr: NonNull<[Char]>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Char> InternedStr<Char> {
|
|
|
|
/// Create a new interned string from the given `*const u8` pointer,
|
|
|
|
/// length and encoding kind
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Not maintaining the invariants specified on the struct definition
|
|
|
|
/// could cause Undefined Behaviour.
|
|
|
|
pub(super) const unsafe fn new(ptr: NonNull<[Char]>) -> Self {
|
|
|
|
Self { ptr }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a shared reference to the underlying string.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Not maintaining the invariants specified on the struct definition
|
|
|
|
/// could cause Undefined Behaviour.
|
|
|
|
pub(super) unsafe fn as_ref(&self) -> &[Char] {
|
|
|
|
// SAFETY:
|
|
|
|
// The caller must ensure `ptr` is still valid throughout the
|
|
|
|
// lifetime of `self`.
|
|
|
|
unsafe { self.ptr.as_ref() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Char> Clone for InternedStr<Char> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Char> Copy for InternedStr<Char> {}
|
|
|
|
|
|
|
|
impl<Char> Eq for InternedStr<Char> where Char: Eq {}
|
|
|
|
|
|
|
|
impl<Char> PartialEq for InternedStr<Char>
|
|
|
|
where
|
|
|
|
Char: PartialEq,
|
|
|
|
{
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
// SAFETY: The caller must verify the invariants
|
|
|
|
// specified in the struct definition.
|
|
|
|
unsafe { self.as_ref() == other.as_ref() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Char> Hash for InternedStr<Char>
|
|
|
|
where
|
|
|
|
Char: Hash,
|
|
|
|
{
|
|
|
|
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
|
|
|
// SAFETY:
|
|
|
|
// The caller must ensure `ptr` is still valid throughout the
|
|
|
|
// lifetime of `self`.
|
|
|
|
unsafe {
|
|
|
|
self.as_ref().hash(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|