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}