string_interner/backend/
string.rs1#![cfg(feature = "backends")]
2
3use super::Backend;
4use crate::{symbol::expect_valid_symbol, DefaultSymbol, Symbol};
5use alloc::{string::String, vec::Vec};
6use core::{iter::Enumerate, marker::PhantomData, slice};
7
8#[derive(Debug)]
41pub struct StringBackend<S = DefaultSymbol> {
42 ends: Vec<usize>,
43 buffer: String,
44 marker: PhantomData<fn() -> S>,
45}
46
47#[derive(Debug, Copy, Clone, PartialEq, Eq)]
49pub struct Span {
50 from: usize,
51 to: usize,
52}
53
54impl<S> PartialEq for StringBackend<S>
55where
56 S: Symbol,
57{
58 fn eq(&self, other: &Self) -> bool {
59 if self.ends.len() != other.ends.len() {
60 return false;
61 }
62 for ((_, lhs), (_, rhs)) in self.into_iter().zip(other) {
63 if lhs != rhs {
64 return false;
65 }
66 }
67 true
68 }
69}
70
71impl<S> Eq for StringBackend<S> where S: Symbol {}
72
73impl<S> Clone for StringBackend<S> {
74 fn clone(&self) -> Self {
75 Self {
76 ends: self.ends.clone(),
77 buffer: self.buffer.clone(),
78 marker: Default::default(),
79 }
80 }
81}
82
83impl<S> Default for StringBackend<S> {
84 #[cfg_attr(feature = "inline-more", inline)]
85 fn default() -> Self {
86 Self {
87 ends: Vec::default(),
88 buffer: String::default(),
89 marker: Default::default(),
90 }
91 }
92}
93
94impl<S> StringBackend<S>
95where
96 S: Symbol,
97{
98 fn next_symbol(&self) -> S {
100 expect_valid_symbol(self.ends.len())
101 }
102
103 fn span_to_str(&self, span: Span) -> &str {
105 unsafe { core::str::from_utf8_unchecked(&self.buffer.as_bytes()[span.from..span.to]) }
112 }
113
114 fn symbol_to_span(&self, symbol: S) -> Option<Span> {
116 let index = symbol.to_usize();
117 self.ends.get(index).copied().map(|to| {
118 let from = self.ends.get(index.wrapping_sub(1)).copied().unwrap_or(0);
119 Span { from, to }
120 })
121 }
122
123 unsafe fn symbol_to_span_unchecked(&self, symbol: S) -> Span {
125 let index = symbol.to_usize();
126 let to = unsafe { *self.ends.get_unchecked(index) };
129 let from = self.ends.get(index.wrapping_sub(1)).copied().unwrap_or(0);
130 Span { from, to }
131 }
132
133 fn push_string(&mut self, string: &str) -> S {
139 self.buffer.push_str(string);
140 let to = self.buffer.len();
141 let symbol = self.next_symbol();
142 self.ends.push(to);
143 symbol
144 }
145}
146
147impl<S> Backend for StringBackend<S>
148where
149 S: Symbol,
150{
151 type Symbol = S;
152 type Iter<'a>
153 = Iter<'a, S>
154 where
155 Self: 'a;
156
157 #[cfg_attr(feature = "inline-more", inline)]
158 fn with_capacity(cap: usize) -> Self {
159 let default_word_len = 5;
161 Self {
162 ends: Vec::with_capacity(cap),
163 buffer: String::with_capacity(cap * default_word_len),
164 marker: Default::default(),
165 }
166 }
167
168 #[inline]
169 fn intern(&mut self, string: &str) -> Self::Symbol {
170 self.push_string(string)
171 }
172
173 #[inline]
174 fn resolve(&self, symbol: Self::Symbol) -> Option<&str> {
175 self.symbol_to_span(symbol)
176 .map(|span| self.span_to_str(span))
177 }
178
179 fn shrink_to_fit(&mut self) {
180 self.ends.shrink_to_fit();
181 self.buffer.shrink_to_fit();
182 }
183
184 #[inline]
185 unsafe fn resolve_unchecked(&self, symbol: Self::Symbol) -> &str {
186 unsafe { self.span_to_str(self.symbol_to_span_unchecked(symbol)) }
189 }
190
191 #[inline]
192 fn iter(&self) -> Self::Iter<'_> {
193 Iter::new(self)
194 }
195}
196
197impl<'a, S> IntoIterator for &'a StringBackend<S>
198where
199 S: Symbol,
200{
201 type Item = (S, &'a str);
202 type IntoIter = Iter<'a, S>;
203
204 #[cfg_attr(feature = "inline-more", inline)]
205 fn into_iter(self) -> Self::IntoIter {
206 self.iter()
207 }
208}
209
210pub struct Iter<'a, S> {
211 backend: &'a StringBackend<S>,
212 start: usize,
213 ends: Enumerate<slice::Iter<'a, usize>>,
214}
215
216impl<'a, S> Iter<'a, S> {
217 #[cfg_attr(feature = "inline-more", inline)]
218 pub fn new(backend: &'a StringBackend<S>) -> Self {
219 Self {
220 backend,
221 start: 0,
222 ends: backend.ends.iter().enumerate(),
223 }
224 }
225}
226
227impl<'a, S> Iterator for Iter<'a, S>
228where
229 S: Symbol,
230{
231 type Item = (S, &'a str);
232
233 #[inline]
234 fn size_hint(&self) -> (usize, Option<usize>) {
235 self.ends.size_hint()
236 }
237
238 #[inline]
239 fn next(&mut self) -> Option<Self::Item> {
240 self.ends.next().map(|(id, &to)| {
241 let from = core::mem::replace(&mut self.start, to);
242 (
243 expect_valid_symbol(id),
244 self.backend.span_to_str(Span { from, to }),
245 )
246 })
247 }
248}