1+ //! This module helps you efficiently store and retrieve values using interning.
2+ //!
3+ //! Interning is a neat trick that keeps only one copy of identical values, saving memory
4+ //! and making comparisons super fast. Here, we provide the `Interned<T>` struct and the `Internable` trait
5+ //! to make interning easy for different data types.
6+ //!
7+ //! The `Interner` struct handles caching for common types like `String`, `PathBuf`, and `Vec<String>`,
8+ //! while the `Cache` struct acts as a write-once storage for linking computation steps with their results.
9+ //!
10+ //! # Thread Safety
11+ //!
12+ //! We use `Mutex` to make sure interning and retrieval are thread-safe. But keep in mind—once a value is
13+ //! interned, it sticks around for the entire lifetime of the program.
14+
115use std:: any:: { Any , TypeId } ;
216use std:: borrow:: Borrow ;
317use std:: cell:: RefCell ;
@@ -12,6 +26,9 @@ use std::{fmt, mem};
1226
1327use crate :: core:: builder:: Step ;
1428
29+ /// Represents an interned value of type `T`, allowing for efficient comparisons and retrieval.
30+ ///
31+ /// This struct stores a unique index referencing the interned value within an internal cache.
1532pub struct Interned < T > ( usize , PhantomData < * const T > ) ;
1633
1734impl < T : Internable + Default > Default for Interned < T > {
@@ -111,6 +128,10 @@ impl<T: Internable + Ord> Ord for Interned<T> {
111128 }
112129}
113130
131+ /// A structure for managing the interning of values of type `T`.
132+ ///
133+ /// `TyIntern<T>` maintains a mapping between values and their interned representations,
134+ /// ensuring that duplicate values are not stored multiple times.
114135struct TyIntern < T : Clone + Eq > {
115136 items : Vec < T > ,
116137 set : HashMap < T , Interned < T > > ,
@@ -123,6 +144,9 @@ impl<T: Hash + Clone + Eq> Default for TyIntern<T> {
123144}
124145
125146impl < T : Hash + Clone + Eq > TyIntern < T > {
147+ /// Interns a borrowed value, ensuring it is stored uniquely.
148+ ///
149+ /// If the value has been previously interned, the same `Interned<T>` instance is returned.
126150 fn intern_borrow < B > ( & mut self , item : & B ) -> Interned < T >
127151 where
128152 B : Eq + Hash + ToOwned < Owned = T > + ?Sized ,
@@ -138,6 +162,9 @@ impl<T: Hash + Clone + Eq> TyIntern<T> {
138162 interned
139163 }
140164
165+ /// Interns an owned value, storing it uniquely.
166+ ///
167+ /// If the value has been previously interned, the existing `Interned<T>` is returned.
141168 fn intern ( & mut self , item : T ) -> Interned < T > {
142169 if let Some ( i) = self . set . get ( & item) {
143170 return * i;
@@ -148,18 +175,27 @@ impl<T: Hash + Clone + Eq> TyIntern<T> {
148175 interned
149176 }
150177
178+ /// Retrieves a reference to the interned value associated with the given `Interned<T>` instance.
151179 fn get ( & self , i : Interned < T > ) -> & T {
152180 & self . items [ i. 0 ]
153181 }
154182}
155183
184+ /// A global interner for managing interned values of common types.
185+ ///
186+ /// This structure maintains caches for `String`, `PathBuf`, and `Vec<String>`, ensuring efficient storage
187+ /// and retrieval of frequently used values.
156188#[ derive( Default ) ]
157189pub struct Interner {
158190 strs : Mutex < TyIntern < String > > ,
159191 paths : Mutex < TyIntern < PathBuf > > ,
160192 lists : Mutex < TyIntern < Vec < String > > > ,
161193}
162194
195+ /// Defines the behavior required for a type to be internable.
196+ ///
197+ /// Types implementing this trait must provide access to a static cache and define an `intern` method
198+ /// that ensures values are stored uniquely.
163199trait Internable : Clone + Eq + Hash + ' static {
164200 fn intern_cache ( ) -> & ' static Mutex < TyIntern < Self > > ;
165201
@@ -187,11 +223,15 @@ impl Internable for Vec<String> {
187223}
188224
189225impl Interner {
226+ /// Interns a string reference, ensuring it is stored uniquely.
227+ ///
228+ /// If the string has been previously interned, the same `Interned<String>` instance is returned.
190229 pub fn intern_str ( & self , s : & str ) -> Interned < String > {
191230 self . strs . lock ( ) . unwrap ( ) . intern_borrow ( s)
192231 }
193232}
194233
234+ /// A global instance of `Interner` that caches common interned values.
195235pub static INTERNER : LazyLock < Interner > = LazyLock :: new ( Interner :: default) ;
196236
197237/// This is essentially a `HashMap` which allows storing any type in its input and
@@ -209,10 +249,12 @@ pub struct Cache(
209249) ;
210250
211251impl Cache {
252+ /// Creates a new empty cache.
212253 pub fn new ( ) -> Cache {
213254 Cache ( RefCell :: new ( HashMap :: new ( ) ) )
214255 }
215256
257+ /// Stores the result of a computation step in the cache.
216258 pub fn put < S : Step > ( & self , step : S , value : S :: Output ) {
217259 let mut cache = self . 0 . borrow_mut ( ) ;
218260 let type_id = TypeId :: of :: < S > ( ) ;
@@ -225,6 +267,7 @@ impl Cache {
225267 stepcache. insert ( step, value) ;
226268 }
227269
270+ /// Retrieves a cached result for the given step, if available.
228271 pub fn get < S : Step > ( & self , step : & S ) -> Option < S :: Output > {
229272 let mut cache = self . 0 . borrow_mut ( ) ;
230273 let type_id = TypeId :: of :: < S > ( ) ;
@@ -255,3 +298,6 @@ impl Cache {
255298 self . 0 . borrow ( ) . contains_key ( & TypeId :: of :: < S > ( ) )
256299 }
257300}
301+
302+ #[ cfg( test) ]
303+ mod tests;
0 commit comments