git.delta.rocks / jrsonnet / refs/commits / 4f4be44d138e

difftreelog

source

crates/jrsonnet-interner/src/lib.rs2.3 KiBsourcehistory
1use gcmodule::Trace;2use rustc_hash::FxHashMap;3use serde::{Deserialize, Serialize};4use std::{5	borrow::Cow,6	cell::RefCell,7	fmt::{self, Display},8	hash::{BuildHasherDefault, Hash, Hasher},9	ops::Deref,10	rc::Rc,11};1213#[derive(Clone, PartialOrd, Ord, Eq)]14pub struct IStr(Rc<str>);15impl Trace for IStr {16	fn is_type_tracked() -> bool {17		false18	}19}2021impl Deref for IStr {22	type Target = str;2324	fn deref(&self) -> &Self::Target {25		&self.026	}27}2829impl PartialEq for IStr {30	fn eq(&self, other: &Self) -> bool {31		// It is ok, since all IStr should be inlined into same pool32		Rc::ptr_eq(&self.0, &other.0)33	}34}3536impl PartialEq<str> for IStr {37	fn eq(&self, other: &str) -> bool {38		&self.0 as &str == other39	}40}4142impl Hash for IStr {43	fn hash<H: Hasher>(&self, state: &mut H) {44		state.write_usize(Rc::as_ptr(&self.0) as *const () as usize)45	}46}4748impl Drop for IStr {49	fn drop(&mut self) {50		// First reference - current object, second - POOL51		if Rc::strong_count(&self.0) <= 2 {52			let _result = STR_POOL.try_with(|pool| pool.borrow_mut().remove(&self.0));53		}54	}55}5657impl fmt::Debug for IStr {58	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {59		write!(f, "{:?}", &self.0)60	}61}6263impl Display for IStr {64	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {65		f.write_str(&self.0)66	}67}6869thread_local! {70	static STR_POOL: RefCell<FxHashMap<Rc<str>, ()>> = RefCell::new(FxHashMap::with_capacity_and_hasher(200, BuildHasherDefault::default()));71}7273impl From<&str> for IStr {74	fn from(str: &str) -> Self {75		IStr(STR_POOL.with(|pool| {76			let mut pool = pool.borrow_mut();77			if let Some((k, _)) = pool.get_key_value(str) {78				k.clone()79			} else {80				let rc: Rc<str> = str.into();81				pool.insert(rc.clone(), ());82				rc83			}84		}))85	}86}8788impl From<String> for IStr {89	fn from(str: String) -> Self {90		(&str as &str).into()91	}92}9394impl<'i> From<Cow<'i, str>> for IStr {95	fn from(c: Cow<'i, str>) -> Self {96		(&c as &str).into()97	}98}99100impl Serialize for IStr {101	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>102	where103		S: serde::Serializer,104	{105		(&self.0 as &str).serialize(serializer)106	}107}108109impl<'de> Deserialize<'de> for IStr {110	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>111	where112		D: serde::Deserializer<'de>,113	{114		let s = <&str>::deserialize(deserializer)?;115		Ok(s.into())116	}117}