string_pool/
pool.rs

1use ::std::hash::{ Hash, Hasher };
2use ::hashbrown::HashSet;
3
4mod global;
5
6pub use global::GlobalPool;
7
8pub trait Pool: Clone {
9	type Raw;
10
11	// --- required functions ---
12
13	/// # Safety
14	///
15	/// The provided slices, when joined together using [`SlicesWrap::to_boxed_slice`],
16	/// must be valid UTF-8. Strictly speaking individual slices don't have to be
17	/// valid UTF-8, as long as the whole is, so this should _not_ be relied on,
18	/// even though it is quite likely that they will be.
19	unsafe fn raw_from_slices(&self, slices: SlicesWrap) -> Self::Raw;
20
21	fn raw_to_slice<'r>(&self, raw: &'r Self::Raw) -> &'r [u8];
22
23	// --- can-be-optimised functions ---
24	// these can be overridden if it can create a more efficient implementation
25
26	/// note to implementors: The default implementation
27	/// of this function is usually enough; however this can be overridden
28	/// for optimisation reasons.
29	///
30	/// # Safety
31	///
32	/// The provided slice must be valid UTF-8.
33	unsafe fn raw_from_slice(&self, slice: &[u8]) -> Self::Raw {
34		self.raw_from_slices(SlicesWrap(&[slice]))
35	}
36
37	/// note to implementors: The default implementation
38	/// of this function is usually enough; however this can be overridden
39	/// for optimisation reasons.
40	///
41	/// # Safety
42	///
43	/// The provided vec must be valid UTF-8.
44	unsafe fn raw_from_vec(&self, vec: Vec<u8>) -> Self::Raw {
45		self.raw_from_slice(&vec)
46	}
47
48	/// note to implementors: The default implementation
49	/// of this function is usually enough; however this can be overridden
50	/// for optimisation reasons.
51	fn raw_empty(&self) -> Self::Raw {
52		unsafe { self.raw_from_slice(&[]) }
53	}
54
55	/// note to implementors: The default implementation
56	/// of this function is usually enough; however this can be overridden
57	/// for optimisation reasons.
58	fn raw_into_vec(&self, raw: Self::Raw) -> Vec<u8> {
59		self.raw_to_slice(&raw).to_vec()
60	}
61
62	/// note to implementors: The default implementation
63	/// of this function is usually enough; however this can be overridden
64	/// for optimisation reasons.
65	fn raw_into_boxed_slice(&self, raw: Self::Raw) -> Box<[u8]> {
66		self.raw_into_vec(raw).into_boxed_slice()
67	}
68
69	/// note to implementors: The default implementation
70	/// of this function is usually enough; however this can be overridden
71	/// for optimisation reasons.
72	fn raw_clone(&self, raw: &Self::Raw) -> Self::Raw {
73		let slice = self.raw_to_slice(raw);
74		unsafe { self.raw_from_slice(slice) }
75	}
76}
77
78/// Wraps a slice of slices of bytes. This has a simple hash implementation
79/// that's just done by repeatedly calling `hash` on every u8 in sequence, to
80/// purposefully ensure that by doing the same to just one slice, or any amount of slices,
81/// there will be the same resulting hash as if you were to join the slices.
82#[derive(Debug)]
83#[repr(transparent)]
84pub struct SlicesWrap<'h>(pub &'h [&'h [u8]]);
85
86impl<'h> SlicesWrap<'h> {
87	pub fn to_vec(&self) -> Vec<u8> {
88		self.into_iter().collect()
89	}
90
91	/// Joins the slices in sequence, returning a boxed slice.
92	pub fn to_boxed_slice(&self) -> Box<[u8]> {
93		self.to_vec().into_boxed_slice()
94	}
95}
96
97impl<'h> Hash for SlicesWrap<'h> {
98	fn hash<H: Hasher>(&self, state: &mut H) {
99		self.into_iter().for_each(|b| state.write_u8(b));
100	}
101}
102
103impl<'h> IntoIterator for &SlicesWrap<'h> {
104	type Item = <SlicesWrapIter<'h> as Iterator>::Item;
105	type IntoIter = SlicesWrapIter<'h>;
106
107	fn into_iter(self) -> Self::IntoIter {
108		let mut vec = Vec::with_capacity(self.0.len());
109		self.0.iter().rev().for_each(|slice| vec.push(*slice));
110		SlicesWrapIter(vec)
111	}
112}
113
114/// Iterator for [`SlicesWrap`] that returns elements in one slice after the
115/// other in sequence. It would be the same as calling `.zip` with all the slices.
116/// Iterating through the boxed slice returned by [`SlicesWrap::to_boxed_slice`]
117/// would also yield the same sequence as if you were to iterate through this iterator.
118pub struct SlicesWrapIter<'h>(Vec<&'h [u8]>);
119
120impl<'h> Iterator for SlicesWrapIter<'h> {
121	type Item = u8;
122
123	fn next(&mut self) -> Option<u8> {
124		// if this is None
125		// we will have reached the end of the vec
126		let next_slice = self.0.pop()?;
127
128		match next_slice.iter().next() {
129			Some(item) => {
130				self.0.push(&next_slice[1..]);
131				Some(*item)
132			}
133			None => {
134				// we popped so this will start on the slice after current
135				self.next()
136			}
137		}
138	}
139
140	fn size_hint(&self) -> (usize, Option<usize>) {
141		let len = self.0.iter().map(|s| s.len()).sum();
142		(len, Some(len))
143	}
144}