1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! # intern_lang
//!
//! Fast string and symbol interning — identifier comparisons become integer
//! comparisons.
//!
//! `intern-lang` maps each distinct string to a small, copyable [`Symbol`],
//! stores the bytes once in a contiguous backing store, and hands back integer
//! handles. A compiler front-end interns every identifier once, then compares and
//! passes symbols instead of strings: a name comparison becomes an integer
//! comparison, and a name in an AST node costs four bytes instead of an owned
//! `String`. It is the deduplication layer beneath a lexer and a symbol table,
//! and it owns interning and nothing else — no lexing, no scoping, no I/O.
//!
//! ## At a glance
//!
//! - [`Interner`] — the single-threaded interner. [`intern`](Interner::intern)
//! deduplicates and returns a stable [`Symbol`];
//! [`resolve`](Interner::resolve) borrows the bytes back out of the store.
//! - [`Symbol`] — a four-byte `Copy` handle whose equality, ordering, and hashing
//! are integer operations.
//! - [`ConcurrentInterner`] — a thread-safe interner many threads can intern into
//! at once, sharing one symbol space (requires the `std` feature).
//! - [`Lookup`] — the read-side trait both interners implement, so generic code
//! can accept either.
//!
//! ## Example
//!
//! ```
//! use intern_lang::Interner;
//!
//! let mut interner = Interner::new();
//!
//! // Interning the same string twice yields the same symbol...
//! let a = interner.intern("while");
//! let b = interner.intern("while");
//! assert_eq!(a, b);
//!
//! // ...and distinct strings yield distinct symbols.
//! let c = interner.intern("for");
//! assert_ne!(a, c);
//!
//! // Comparing names is now an integer compare; resolving borrows the bytes.
//! assert_eq!(interner.resolve(a), Some("while"));
//! assert_eq!(interner.resolve(c), Some("for"));
//! ```
//!
//! ## `no_std`
//!
//! The crate is `no_std`-compatible: it relies only on `alloc`, never on the
//! standard library. The default `std` feature is additive. Disable default
//! features to build for a `no_std` target.
extern crate alloc;
pub use ConcurrentInterner;
pub use InternError;
pub use Interner;
pub use Lookup;
pub use Symbol;