interning 0.2.3

A Simple Thread-Lcoal and Global Interning Library
Documentation
use stable_hash::fast_stable_hash;
use std::fmt::{Debug, Display};
use std::hash::Hash;

pub const HASH_LEN_MASK: u8 = 0x80;

#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Copy)]
pub struct InternedStringHash([u8; 8]);
impl Display for InternedStringHash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.is_inlined() {
            write!(f, "{}", self.get_inlined_str())
        } else {
            write!(f, "{:x}", self.hash())
        }
    }
}
impl Debug for InternedStringHash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "InternedStringHash({})", self)
    }
}
impl InternedStringHash {
    pub fn new(hash: u64) -> Self {
        let mut bytes = [0; 8];
        bytes.copy_from_slice(&hash.to_be_bytes());
        Self(bytes)
    }
    pub fn from_str(s: &str) -> Self {
        if s.len() >= 8 {
            let mut hash = (fast_stable_hash(&s) as u64).to_be_bytes();
            hash[0] = 0;
            Self::from_bytes(hash)
        } else {
            let mut hash = [0u8; 8];
            hash[0] = HASH_LEN_MASK | (s.len() as u8);
            hash[1..=s.len()].copy_from_slice(s.as_bytes());
            Self::from_bytes(hash)
        }
    }
    pub fn empty() -> Self {
        Self([0; 8])
    }
    pub fn from_bytes(bytes: [u8; 8]) -> Self {
        Self(bytes)
    }
    pub fn hash(&self) -> u64 {
        u64::from_be_bytes(self.0)
    }
    pub fn is_inlined(&self) -> bool {
        self.0[0] != 0
    }
    pub fn set_inline_len(&mut self, len: usize) {
        debug_assert!(len < 7);
        self.0[0] = HASH_LEN_MASK | len as u8;
    }
    pub fn get_inlined_len(&self) -> usize {
        debug_assert!(self.is_inlined());
        (self.0[0] ^ HASH_LEN_MASK) as usize
    }
    pub fn get_inlined_str(&self) -> &str {
        debug_assert!(self.is_inlined());
        let len = self.get_inlined_len();
        let ptr = self.0.as_ptr();
        let ptr = unsafe { ptr.add(1) };
        unsafe { std::str::from_utf8_unchecked(std::slice::from_raw_parts(ptr, len)) }
    }
}
#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_small_strings() {
        let s = "hello";
        let interned = InternedStringHash::from_str(s);
        assert_eq!(interned.get_inlined_str(), s);
        let interned = InternedStringHash::from_str(s);
        assert_eq!(interned.get_inlined_str(), s);
    }
}