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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (C) 2016-2017 Symtern Project Contributors
//
// Licensed under the Apache License, Version 2.0 <LICENSE-Apache
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. This file may not be copied, modified, or
// distributed except according to those terms.
//! # Interner Adaptors
//!
//! Each type in this module provides some additional functionality beyond that
//! of Symtern's basic interner.
//!
//! Adaptors are wrapper types, i.e. they "wrap" another interner type, taking
//! it as a generic parameter.
//!
//! ```rust
//! use symtern::{Pool, Sym};
//! use symtern::adaptors::{Inline, InlineSym};
//!
//! type MyPool = Inline<Pool<str,u32>>;
//! type MySym = InlineSym<Sym<u32>>;
//! ```
//!
//! ## Losing symbols
//!
//! If you construct an adaptor from an existing interner, you will lose access
//! to all previously-created symbols:
//!
//! ```rust,compile_fail file="tests/compile-fail/losing-symbols.rs"
//! use symtern::prelude::*;
//! use symtern::Pool;
//! use symtern::adaptors::Inline;
//!
//! // Once we've constructed an adaptor from an existing pool, we _cannot_
//! // resolve previously-created symbols:
//! let mut basic_pool = Pool::<str,u64>::new();
//! let some_sym = basic_pool.intern("Mornin'!").expect("interning failed");
//! // After we've created `inline_pool`, consuming `basic_pool`...
//! let mut inline_pool = Inline::from(basic_pool);
//! // ...we won't be able to resolve `some_sym` because its type is
//! // incompatible with the inline pool's `resolve` method!
//! println!("{}", inline_pool.resolve(&some_sym).expect("resolution failed")); //~ ERROR mismatched types [E0308]
//! ```
//!
//! ## Inline
//!
//! By wrapping your `Pool<str, _>` type in the [`Inline`] adaptor, you can
//! create an interner optimized for short strings. When input strings are
//! under a certain length, this adaptor will store them directly in the
//! returned symbols — entirely bypassing the wrapped interner. If you
//! expect to be working with many short strings, it may perform better than
//! the basic interner.
//!
//! ```rust file="examples/combining-adaptors.rs" id="inline"
//! use symtern::prelude::*;
//! use symtern::adaptors::Inline;
//! use symtern::Pool;
//!
//! let mut pool = Inline::from(Pool::<str,u64>::new());
//!
//! if let (Ok(hello), Ok(world)) = (pool.intern("Hello"), pool.intern("World")) {
//! assert!(hello != world);
//!
//! // Since both "hello" and "world" are smaller than the pool's
//! // symbol representation (u64), neither symbol takes up any space
//! // in the pool.
//! assert!(pool.is_empty());
//! }
//! ```
//!
//! ## Luma
//!
//! The [`Luma`] adaptor uses interior mutability via `RefCell` to allow its
//! symbols to carry a lifetime parameter, which is used to prevent the pool
//! from being dropped while it is in use.
//!
//! For example, the following code will not compile because it attempts to
//! return a symbol from a temporary `Luma`-wrapped interner.
//!
//! ```rust,compile_fail file="tests/compile-fail/luma-is-lifetime-safe.rs" id="example"
//! //` id="example" {
//! use symtern::prelude::*;
//! use symtern::{Pool as Basic, Sym};
//! use symtern::adaptors::{Luma, LumaSym};
//!
//! type Pool = Luma<Basic<str, u32>>;
//!
//! /// Return a Sym from a temporary Luma-wrapped interner. This causes a compile
//! /// error because the interner, which is dropped at the end of the function, is
//! /// referenced by the returned symbol.
//! fn make_sym<'a>(s: &str) -> <&'a Pool as symtern::traits::Intern>::Output {
//! Pool::new().intern(s).unwrap() //~ ERROR borrowed value does not live long enough
//! }
//! //` }
//! ```
//!
//! [`Luma`]: struct.Luma.html
//! [`Inline`]: struct.Inline.html
pub use ;
pub use ;