git.delta.rocks / jrsonnet / refs/commits / 11643ec5f009

difftreelog

source

crates/jrsonnet-interner/src/lib.rs2.5 KiBsourcehistory
1use std::{2	borrow::Cow,3	cell::RefCell,4	convert::TryFrom,5	fmt::{self, Display},6	hash::{BuildHasherDefault, Hash, Hasher},7	ops::Deref,8	rc::Rc,9	str::Utf8Error,10};1112use gcmodule::Trace;13use rustc_hash::FxHashMap;14use serde::{Deserialize, Serialize};1516#[derive(Clone, PartialOrd, Ord, Eq)]17pub struct IStr(Rc<str>);18impl Trace for IStr {19	fn is_type_tracked() -> bool {20		false21	}22}2324impl Deref for IStr {25	type Target = str;2627	fn deref(&self) -> &Self::Target {28		&self.029	}30}3132impl PartialEq for IStr {33	fn eq(&self, other: &Self) -> bool {34		// It is ok, since all IStr should be inlined into same pool35		Rc::ptr_eq(&self.0, &other.0)36	}37}3839impl PartialEq<str> for IStr {40	fn eq(&self, other: &str) -> bool {41		&self.0 as &str == other42	}43}4445impl Hash for IStr {46	fn hash<H: Hasher>(&self, state: &mut H) {47		state.write_usize(Rc::as_ptr(&self.0) as *const () as usize)48	}49}5051impl Drop for IStr {52	fn drop(&mut self) {53		// First reference - current object, second - POOL54		if Rc::strong_count(&self.0) <= 2 {55			let _result = STR_POOL.try_with(|pool| pool.borrow_mut().remove(&self.0));56		}57	}58}5960impl fmt::Debug for IStr {61	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {62		write!(f, "{:?}", &self.0)63	}64}6566impl Display for IStr {67	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {68		f.write_str(&self.0)69	}70}7172thread_local! {73	static STR_POOL: RefCell<FxHashMap<Rc<str>, ()>> = RefCell::new(FxHashMap::with_capacity_and_hasher(200, BuildHasherDefault::default()));74}7576impl From<&str> for IStr {77	fn from(str: &str) -> Self {78		IStr(STR_POOL.with(|pool| {79			let mut pool = pool.borrow_mut();80			if let Some((k, _)) = pool.get_key_value(str) {81				k.clone()82			} else {83				let rc: Rc<str> = str.into();84				pool.insert(rc.clone(), ());85				rc86			}87		}))88	}89}9091impl TryFrom<&[u8]> for IStr {92	type Error = Utf8Error;9394	fn try_from(value: &[u8]) -> Result<Self, Self::Error> {95		let str = std::str::from_utf8(value)?;96		Ok(str.into())97	}98}99100impl From<String> for IStr {101	fn from(str: String) -> Self {102		(&str as &str).into()103	}104}105106impl<'i> From<Cow<'i, str>> for IStr {107	fn from(c: Cow<'i, str>) -> Self {108		(&c as &str).into()109	}110}111112impl Serialize for IStr {113	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>114	where115		S: serde::Serializer,116	{117		(&self.0 as &str).serialize(serializer)118	}119}120121impl<'de> Deserialize<'de> for IStr {122	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>123	where124		D: serde::Deserializer<'de>,125	{126		let s = <&str>::deserialize(deserializer)?;127		Ok(s.into())128	}129}