flatcontainer/impls/
string.rs1#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use crate::impls::slice_copy::OwnedRegion;
7use crate::{Push, Region, RegionPreference, ReserveItems};
8
9#[derive(Default, Debug)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35pub struct StringRegion<R = OwnedRegion<u8>> {
36 inner: R,
37}
38
39impl<R: Clone> Clone for StringRegion<R> {
40 fn clone(&self) -> Self {
41 Self {
42 inner: self.inner.clone(),
43 }
44 }
45
46 fn clone_from(&mut self, source: &Self) {
47 self.inner.clone_from(&source.inner);
48 }
49}
50
51impl<R> Region for StringRegion<R>
52where
53 for<'a> R: Region<ReadItem<'a> = &'a [u8]> + 'a,
54{
55 type Owned = String;
56 type ReadItem<'a> = &'a str where Self: 'a ;
57 type Index = R::Index;
58
59 #[inline]
60 fn merge_regions<'a>(regions: impl Iterator<Item = &'a Self> + Clone) -> Self
61 where
62 Self: 'a,
63 {
64 Self {
65 inner: R::merge_regions(regions.map(|r| &r.inner)),
66 }
67 }
68
69 #[inline]
70 fn index(&self, index: Self::Index) -> Self::ReadItem<'_> {
71 unsafe { std::str::from_utf8_unchecked(self.inner.index(index)) }
73 }
74
75 #[inline]
76 fn reserve_regions<'a, I>(&mut self, regions: I)
77 where
78 Self: 'a,
79 I: Iterator<Item = &'a Self> + Clone,
80 {
81 self.inner.reserve_regions(regions.map(|r| &r.inner));
82 }
83
84 #[inline]
85 fn clear(&mut self) {
86 self.inner.clear();
87 }
88
89 #[inline]
90 fn heap_size<F: FnMut(usize, usize)>(&self, callback: F) {
91 self.inner.heap_size(callback);
92 }
93
94 #[inline]
95 fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b>
96 where
97 Self: 'a,
98 {
99 item
100 }
101}
102
103impl RegionPreference for String {
104 type Owned = Self;
105 type Region = StringRegion;
106}
107
108impl RegionPreference for &str {
109 type Owned = String;
110 type Region = StringRegion;
111}
112
113impl<R> Push<String> for StringRegion<R>
114where
115 for<'a> R: Region<ReadItem<'a> = &'a [u8]> + Push<&'a [u8]> + 'a,
116{
117 #[inline]
118 fn push(&mut self, item: String) -> <StringRegion<R> as Region>::Index {
119 self.push(item.as_str())
120 }
121}
122
123impl<R> Push<&String> for StringRegion<R>
124where
125 for<'a> R: Region<ReadItem<'a> = &'a [u8]> + Push<&'a [u8]> + 'a,
126{
127 #[inline]
128 fn push(&mut self, item: &String) -> <StringRegion<R> as Region>::Index {
129 self.push(item.as_str())
130 }
131}
132
133impl<'b, R> ReserveItems<&'b String> for StringRegion<R>
134where
135 for<'a> R: Region<ReadItem<'a> = &'a [u8]> + ReserveItems<&'a [u8]> + 'a,
136{
137 #[inline]
138 fn reserve_items<I>(&mut self, items: I)
139 where
140 I: Iterator<Item = &'b String> + Clone,
141 {
142 self.reserve_items(items.map(String::as_str));
143 }
144}
145
146impl<R> Push<&str> for StringRegion<R>
147where
148 for<'a> R: Region<ReadItem<'a> = &'a [u8]> + Push<&'a [u8]> + 'a,
149{
150 #[inline]
151 fn push(&mut self, item: &str) -> <StringRegion<R> as Region>::Index {
152 self.inner.push(item.as_bytes())
153 }
154}
155
156impl<R> Push<&&str> for StringRegion<R>
157where
158 for<'a> R: Region<ReadItem<'a> = &'a [u8]> + Push<&'a [u8]> + 'a,
159{
160 #[inline]
161 fn push(&mut self, item: &&str) -> <StringRegion<R> as Region>::Index {
162 self.push(*item)
163 }
164}
165
166impl<'b, R> ReserveItems<&'b str> for StringRegion<R>
167where
168 for<'a> R: Region<ReadItem<'a> = &'a [u8]> + ReserveItems<&'a [u8]> + 'a,
169{
170 #[inline]
171 fn reserve_items<I>(&mut self, items: I)
172 where
173 I: Iterator<Item = &'b str> + Clone,
174 {
175 self.inner.reserve_items(items.map(str::as_bytes));
176 }
177}
178
179impl<'a, 'b: 'a, R> ReserveItems<&'a &'b str> for StringRegion<R>
180where
181 for<'c> R: Region<ReadItem<'c> = &'c [u8]> + ReserveItems<&'c [u8]> + 'c,
182{
183 #[inline]
184 fn reserve_items<I>(&mut self, items: I)
185 where
186 I: Iterator<Item = &'a &'b str> + Clone,
187 {
188 self.reserve_items(items.copied());
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use crate::{IntoOwned, Push, Region, ReserveItems, StringRegion};
195
196 #[test]
197 fn test_inner() {
198 let mut r = <StringRegion>::default();
199 let index = r.push("abc");
200 assert_eq!(r.index(index), "abc");
201 }
202
203 #[test]
204 fn test_reserve_items_str() {
205 let mut r = <StringRegion>::default();
206 r.reserve_items(std::iter::repeat("abc").take(1000));
207
208 let (mut cap, mut cnt) = (0, 0);
209 r.heap_size(|_, c| {
210 cap += c;
211 cnt += 1;
212 });
213
214 assert!(cap > 0);
215 assert!(cnt > 0);
216 }
217
218 #[test]
219 fn test_reserve_items_ref_str() {
220 let mut r = <StringRegion>::default();
221 r.reserve_items(std::iter::repeat(&"abc").take(1000));
222
223 let (mut cap, mut cnt) = (0, 0);
224 r.heap_size(|_, c| {
225 cap += c;
226 cnt += 1;
227 });
228
229 assert!(cap > 0);
230 assert!(cnt > 0);
231 }
232
233 #[test]
234 fn test_reserve_items_string() {
235 let mut r = <StringRegion>::default();
236 r.reserve_items(std::iter::repeat(&"abc".to_owned()).take(1000));
237
238 let (mut cap, mut cnt) = (0, 0);
239 r.heap_size(|_, c| {
240 cap += c;
241 cnt += 1;
242 });
243
244 assert!(cap > 0);
245 assert!(cnt > 0);
246 }
247
248 #[test]
249 fn owned() {
250 let mut r = <StringRegion>::default();
251
252 let idx = r.push("abc");
253 let reference = r.index(idx);
254 let owned = reference.into_owned();
255 let idx = r.push(owned);
256 assert_eq!("abc", r.index(idx));
257 }
258}