1use crate::{CopyRange, DefaultBuildHasher, Index};
2#[cfg(feature = "serde")]
3use crate::{RangeWrapper, SnapshotRangeWrapper};
4#[cfg(feature = "serde")]
5use alloc::format;
6#[cfg(any(feature = "serde", not(feature = "sync")))]
7use alloc::string::String;
8#[cfg(any(feature = "serde", not(feature = "sync")))]
9use alloc::vec::Vec;
10#[cfg(feature = "sync")]
11use appendvec::{AppendStr, AppendVec};
12use core::cmp::Ordering;
13use core::fmt::Debug;
14use core::hash::{BuildHasher, Hash, Hasher};
15use core::marker::PhantomData;
16#[cfg(feature = "debug")]
17use core::sync::atomic::{self, AtomicUsize};
18#[cfg(feature = "sync")]
19use dashtable::DashTable;
20#[cfg(feature = "sync")]
21use dashtable::{Entry, EntryMut};
22#[cfg(feature = "get-size2")]
23use get_size2::{GetSize, GetSizeTracker};
24#[cfg(not(feature = "sync"))]
25use hashbrown::HashTable;
26#[cfg(not(feature = "sync"))]
27use hashbrown::hash_table::Entry;
28#[cfg(feature = "postcard-schema")]
29use postcard_schema::Schema;
30#[cfg(feature = "postcard-schema")]
31use postcard_schema::schema::{DataModelType, NamedType};
32#[cfg(feature = "serde")]
33use serde::de::{DeserializeSeed, Error, SeqAccess, Visitor};
34#[cfg(feature = "serde")]
35use serde::ser::SerializeTuple;
36#[cfg(feature = "serde")]
37use serde::{Deserialize, Deserializer, Serialize, Serializer};
38#[cfg(feature = "serde")]
39use serde_cow::CowStr;
40
41pub struct InternedStr<H = DefaultBuildHasher, I = u32> {
43 id: I,
44 _phantom: PhantomData<fn() -> H>,
45}
46
47impl<H, I: Index> Default for InternedStr<H, I> {
48 fn default() -> Self {
49 Self::new(I::MAX)
50 }
51}
52
53impl<H, I: Index> Debug for InternedStr<H, I> {
54 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55 f.debug_tuple("I").field(&self.id).finish()
56 }
57}
58
59impl<H, I: Index> Clone for InternedStr<H, I> {
60 fn clone(&self) -> Self {
61 *self
62 }
63}
64
65impl<H, I: Index> Copy for InternedStr<H, I> {}
66
67impl<H, I: Index> PartialEq for InternedStr<H, I> {
68 fn eq(&self, other: &Self) -> bool {
69 self.id.eq(&other.id)
70 }
71}
72
73impl<H, I: Index> Eq for InternedStr<H, I> {}
74
75impl<H, I: Index> PartialOrd for InternedStr<H, I> {
76 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77 Some(self.cmp(other))
78 }
79}
80
81impl<H, I: Index> Ord for InternedStr<H, I> {
82 fn cmp(&self, other: &Self) -> Ordering {
83 self.id.cmp(&other.id)
84 }
85}
86
87impl<H, I: Index> Hash for InternedStr<H, I> {
88 fn hash<G>(&self, state: &mut G)
89 where
90 G: Hasher,
91 {
92 self.id.hash(state);
93 }
94}
95
96#[cfg(feature = "get-size2")]
97impl<H, I> GetSize for InternedStr<H, I>
98where
99 I: GetSize,
100{
101 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
102 self.id.get_heap_size_with_tracker(tracker)
103 }
104}
105
106#[cfg(feature = "raw")]
107impl<H, I> InternedStr<H, I> {
108 pub fn from_id(id: I) -> Self {
114 Self::new(id)
115 }
116}
117
118#[cfg(feature = "raw")]
119impl<H, I: Index> InternedStr<H, I> {
120 pub fn id(&self) -> I {
126 self.id
127 }
128}
129
130impl<H, I> InternedStr<H, I> {
131 pub(crate) fn new(id: I) -> Self {
132 Self {
133 id,
134 _phantom: PhantomData,
135 }
136 }
137}
138
139impl<H, I: Index> InternedStr<H, I> {
140 pub(crate) fn id_(&self) -> I {
141 self.id
142 }
143}
144
145#[cfg(feature = "serde")]
146impl<H, I> Serialize for InternedStr<H, I>
147where
148 I: Serialize,
149{
150 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
151 where
152 S: Serializer,
153 {
154 self.id.serialize(serializer)
155 }
156}
157
158#[cfg(feature = "postcard-schema")]
159impl<H, I> Schema for InternedStr<H, I>
160where
161 I: Schema,
162{
163 const SCHEMA: &'static NamedType = &NamedType {
164 name: "InternedStr",
165 ty: &DataModelType::NewtypeStruct(I::SCHEMA),
166 };
167}
168
169#[cfg(feature = "serde")]
170impl<'de, H, I> Deserialize<'de> for InternedStr<H, I>
171where
172 I: Deserialize<'de>,
173{
174 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
175 where
176 D: Deserializer<'de>,
177 {
178 let id = I::deserialize(deserializer)?;
179 Ok(Self::new(id))
180 }
181}
182
183#[cfg_attr(feature = "get-size2", derive(GetSize))]
184struct RangeVecStr<I> {
185 #[cfg(not(feature = "sync"))]
186 vec: String,
187 #[cfg(feature = "sync")]
188 vec: AppendStr,
189 #[cfg(not(feature = "sync"))]
190 ranges: Vec<CopyRange<I>>,
191 #[cfg(feature = "sync")]
192 ranges: AppendVec<CopyRange<I>>,
193}
194
195impl<I: Index> RangeVecStr<I> {
196 fn lookup_bytes(&self, id: I) -> &[u8] {
197 let range = self.ranges[id.to_usize()];
198 let range = range.start.to_usize()..range.end.to_usize();
199 #[cfg(not(feature = "sync"))]
200 return &self.vec.as_bytes()[range];
201 #[cfg(feature = "sync")]
202 return self.vec.get_bytes(range);
203 }
204
205 fn try_lookup_bytes(&self, id: I) -> Option<&[u8]> {
206 let i = id.to_usize();
207 #[cfg(not(feature = "sync"))]
208 let range = self.ranges.get(i)?;
209 #[cfg(feature = "sync")]
210 let range = self.ranges.try_index(i)?;
211 let range = range.start.to_usize()..range.end.to_usize();
212 #[cfg(not(feature = "sync"))]
213 return Some(&self.vec.as_bytes()[range]);
214 #[cfg(feature = "sync")]
215 return Some(self.vec.get_bytes(range));
216 }
217
218 fn lookup_str(&self, id: I) -> &str {
219 let range = self.ranges[id.to_usize()];
220 let range = range.start.to_usize()..range.end.to_usize();
221 &self.vec[range]
222 }
223
224 fn try_lookup_str(&self, id: I) -> Option<&str> {
225 let i = id.to_usize();
226 #[cfg(not(feature = "sync"))]
227 let range = self.ranges.get(i)?;
228 #[cfg(feature = "sync")]
229 let range = self.ranges.try_index(i)?;
230 let range = range.start.to_usize()..range.end.to_usize();
231 Some(&self.vec[range])
232 }
233
234 fn iter(&self) -> impl ExactSizeIterator<Item = &str> {
235 self.ranges
236 .iter()
237 .map(|&range| &self.vec[range.start.to_usize()..range.end.to_usize()])
238 }
239
240 fn iter_bytes(&self) -> impl ExactSizeIterator<Item = &[u8]> {
241 #[cfg(not(feature = "sync"))]
242 let bytes = self.vec.as_bytes();
243 self.ranges.iter().map(|&range| {
244 #[cfg(not(feature = "sync"))]
245 return &bytes[range.start.to_usize()..range.end.to_usize()];
246 #[cfg(feature = "sync")]
247 return self
248 .vec
249 .get_bytes(range.start.to_usize()..range.end.to_usize());
250 })
251 }
252
253 #[cfg(feature = "sync")]
254 fn try_push_str(&self, value: &str) -> Option<I> {
255 let range = self.vec.try_push_str(value, I::MAX.to_usize())?;
256 let range = I::from_usize(range.start)..I::from_usize(range.end);
257
258 let id = self.ranges.try_push(range.into(), I::MAX.to_usize())?;
259 Some(I::from_usize(id))
260 }
261
262 fn try_push_str_mut(&mut self, value: &str) -> Option<I> {
263 #[cfg(not(feature = "sync"))]
264 let range = {
265 let start = self.vec.len();
266 Self::check_slice_limit(start, value.len())?;
267 self.vec.push_str(value);
268 let end = self.vec.len();
269 start..end
270 };
271 #[cfg(feature = "sync")]
272 let range = self.vec.try_push_str_mut(value, I::MAX.to_usize())?;
273 let range = I::from_usize(range.start)..I::from_usize(range.end);
274
275 #[cfg(not(feature = "sync"))]
276 let id = {
277 let id = self.ranges.len();
278 if id > I::MAX.to_usize() {
279 return None;
280 }
281 self.ranges.push(range.into());
282 id
283 };
284 #[cfg(feature = "sync")]
285 let id = self.ranges.try_push_mut(range.into(), I::MAX.to_usize())?;
286 Some(I::from_usize(id))
287 }
288
289 #[cfg(not(feature = "sync"))]
290 #[inline(always)]
291 fn check_slice_limit(start: usize, len: usize) -> Option<()> {
292 let limit = I::MAX.to_usize();
293 if len > limit || start > limit - len {
294 None
295 } else {
296 Some(())
297 }
298 }
299
300 fn truncate(&mut self, len: usize) {
301 self.ranges.truncate(len);
302 let max_index = self
303 .ranges
304 .iter()
305 .map(|range| range.end.to_usize())
306 .max()
307 .unwrap_or(0);
308 self.vec.truncate(max_index);
309 }
310}
311
312pub struct ArenaStr<H = DefaultBuildHasher, I = u32> {
314 rangevec: RangeVecStr<I>,
315 #[cfg(not(feature = "sync"))]
316 map: HashTable<I>,
317 #[cfg(feature = "sync")]
318 map: DashTable<I>,
319 hasher: H,
320 #[cfg(feature = "debug")]
321 references: AtomicUsize,
322}
323
324impl<H, I> Clone for ArenaStr<H, I>
325where
326 H: Default + BuildHasher,
327 I: Index,
328{
329 fn clone(&self) -> Self {
330 let iter = self.iter_();
331 let mut arena = Self::with_capacity(iter.len(), self.bytes());
332 for s in iter {
333 arena.push(s);
334 }
335 arena
336 }
337}
338
339impl<H, I> ArenaStr<H, I>
340where
341 H: Default,
342 I: Index,
343{
344 pub fn with_capacity(strings: usize, bytes: usize) -> Self {
353 match Self::try_with_capacity(strings, bytes) {
354 Some(x) => x,
355 None => panic!(
356 "Cannot allocate an ArenaStr with capacity for {strings} strings of {bytes} bytes with indices up to {}",
357 I::MAX.to_usize()
358 ),
359 }
360 }
361
362 pub fn try_with_capacity(strings: usize, bytes: usize) -> Option<Self> {
368 if (strings != 0 && strings - 1 > I::MAX.to_usize()) || bytes > I::MAX.to_usize() {
369 return None;
370 }
371 Some(Self {
372 #[cfg(not(feature = "sync"))]
373 rangevec: RangeVecStr {
374 vec: String::with_capacity(bytes),
375 ranges: Vec::with_capacity(strings),
376 },
377 #[cfg(feature = "sync")]
378 rangevec: RangeVecStr {
379 vec: AppendStr::try_with_capacity(bytes)?,
380 ranges: AppendVec::try_with_capacity(strings)?,
381 },
382 #[cfg(not(feature = "sync"))]
383 map: HashTable::with_capacity(strings),
384 #[cfg(feature = "sync")]
385 map: DashTable::with_capacity(strings),
386 hasher: H::default(),
387 #[cfg(feature = "debug")]
388 references: AtomicUsize::new(0),
389 })
390 }
391}
392
393impl<H, I> ArenaStr<H, I> {
394 pub fn strings(&self) -> usize {
400 self.rangevec.ranges.len()
401 }
402
403 pub fn bytes(&self) -> usize {
409 self.rangevec.vec.len()
410 }
411
412 pub fn is_empty(&self) -> bool {
418 self.strings() == 0
419 }
420
421 pub fn snapshot(&self) -> SnapshotStr<'_, H, I> {
429 SnapshotStr {
430 arena: self,
431 mark: self.strings(),
432 }
433 }
434}
435
436impl<H, I: Index> ArenaStr<H, I> {
437 #[cfg(feature = "raw")]
447 pub fn iter(&self) -> impl ExactSizeIterator<Item = &str> {
448 self.rangevec.iter()
449 }
450
451 fn iter_(&self) -> impl ExactSizeIterator<Item = &str> {
452 self.rangevec.iter()
453 }
454
455 #[cfg(feature = "raw")]
463 pub fn iter_bytes(&self) -> impl ExactSizeIterator<Item = &[u8]> {
464 self.rangevec.iter_bytes()
465 }
466
467 fn iter_bytes_(&self) -> impl ExactSizeIterator<Item = &[u8]> {
468 self.rangevec.iter_bytes()
469 }
470}
471
472impl<H, I> ArenaStr<H, I>
473where
474 H: BuildHasher,
475 I: Index,
476{
477 pub fn find(&self, value: &str) -> Option<InternedStr<H, I>> {
486 let hash = self.hasher.hash_one(value);
487 self.map
488 .find(hash, |&i| self.lookup_str(i) == value)
489 .map(|id| InternedStr::new(*id))
490 }
491
492 pub fn find_mut(&mut self, value: &str) -> Option<InternedStr<H, I>> {
502 let hash = self.hasher.hash_one(value);
503 #[cfg(not(feature = "sync"))]
504 return self
505 .map
506 .find(hash, |&i| self.lookup_str(i) == value)
507 .map(|id| InternedStr::new(*id));
508 #[cfg(feature = "sync")]
509 return self
510 .map
511 .find_mut(hash, |&i| self.rangevec.lookup_str(i) == value)
512 .map(|id| InternedStr::new(*id));
513 }
514
515 #[cfg(feature = "raw")]
521 pub fn push_mut(&mut self, value: &str) -> I {
522 self.push(value)
523 }
524}
525
526impl<H, I> Default for ArenaStr<H, I>
527where
528 H: Default,
529{
530 fn default() -> Self {
531 Self {
532 #[cfg(not(feature = "sync"))]
533 rangevec: RangeVecStr {
534 vec: String::new(),
535 ranges: Vec::new(),
536 },
537 #[cfg(feature = "sync")]
538 rangevec: RangeVecStr {
539 vec: AppendStr::new(),
540 ranges: AppendVec::new(),
541 },
542 #[cfg(not(feature = "sync"))]
543 map: HashTable::new(),
544 #[cfg(feature = "sync")]
545 map: DashTable::new(),
546 hasher: H::default(),
547 #[cfg(feature = "debug")]
548 references: AtomicUsize::new(0),
549 }
550 }
551}
552
553impl<H, I: Index> Debug for ArenaStr<H, I> {
554 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
555 fmt.debug_list().entries(self.iter_()).finish()
556 }
557}
558
559impl<H, I: Index> PartialEq for ArenaStr<H, I> {
560 fn eq(&self, other: &Self) -> bool {
561 self.iter_bytes_().eq(other.iter_bytes_())
562 }
563}
564
565impl<H, I: Index> Eq for ArenaStr<H, I> {}
566
567#[cfg(feature = "get-size2")]
568impl<H, I> GetSize for ArenaStr<H, I>
569where
570 I: GetSize,
571{
572 fn get_heap_size_with_tracker<Tr: GetSizeTracker>(&self, tracker: Tr) -> (usize, Tr) {
573 let (size_vec, tracker) = GetSize::get_heap_size_with_tracker(&self.rangevec, tracker);
574 let (size_map, tracker) = GetSize::get_heap_size_with_tracker(&self.map, tracker);
575 (size_vec + size_map, tracker)
576 }
577}
578
579#[cfg(all(feature = "debug", feature = "std"))]
580impl<H, I> ArenaStr<H, I> {
581 pub fn print_summary(&self, prefix: &str, title: &str, total_bytes: usize) {
583 let strings = self.rangevec.ranges.len();
584 let references = self.references();
585 let estimated_bytes = self.get_size();
586 println!(
587 "{}[{:.02}%] {} interner: {} objects | {} bytes ({:.02} bytes/object) | {} references ({:.02} refs/object)",
588 prefix,
589 estimated_bytes as f64 * 100.0 / total_bytes as f64,
590 title,
591 strings,
592 estimated_bytes,
593 estimated_bytes as f64 / strings as f64,
594 references,
595 references as f64 / strings as f64,
596 );
597 }
598}
599
600#[cfg(feature = "debug")]
601impl<H, I> ArenaStr<H, I> {
602 pub fn references(&self) -> usize {
607 self.references.load(atomic::Ordering::Relaxed)
608 }
609}
610
611impl<H, I> ArenaStr<H, I>
612where
613 H: BuildHasher,
614 I: Index,
615{
616 #[cfg(feature = "sync")]
629 pub fn intern(&self, value: &str) -> InternedStr<H, I> {
630 match self.try_intern(value) {
631 Some(x) => x,
632 None => panic!("Cannot intern in a full ArenaStr"),
633 }
634 }
635
636 #[cfg(feature = "sync")]
648 pub fn try_intern(&self, value: &str) -> Option<InternedStr<H, I>> {
649 let hash = self.hasher.hash_one(value);
650 let entry = self.map.entry(
651 hash,
652 |&i| self.lookup_str(i) == value,
653 |&i| self.hasher.hash_one(self.lookup_str(i)),
654 );
655 let id = match entry {
656 Entry::Occupied(e) => *e.get(),
657 Entry::Vacant(e) => {
658 let id = self.rangevec.try_push_str(value)?;
659 *e.insert(id).get()
660 }
661 };
662
663 #[cfg(feature = "debug")]
664 self.references.fetch_add(1, atomic::Ordering::Relaxed);
665 Some(InternedStr::new(id))
666 }
667
668 pub fn intern_mut(&mut self, value: &str) -> InternedStr<H, I> {
682 match self.try_intern_mut(value) {
683 Some(x) => x,
684 None => panic!("Cannot intern in a full ArenaStr"),
685 }
686 }
687
688 pub fn try_intern_mut(&mut self, value: &str) -> Option<InternedStr<H, I>> {
700 let hash = self.hasher.hash_one(value);
701 #[cfg(not(feature = "sync"))]
702 let id = {
703 let entry = self.map.entry(
704 hash,
705 |&i| self.rangevec.lookup_str(i) == value,
706 |&i| self.hasher.hash_one(self.rangevec.lookup_str(i)),
707 );
708 match entry {
709 Entry::Occupied(e) => *e.get(),
710 Entry::Vacant(e) => {
711 let id = self.rangevec.try_push_str_mut(value)?;
712 *e.insert(id).get()
713 }
714 }
715 };
716 #[cfg(feature = "sync")]
717 let id = {
718 let entry = self.map.entry_mut(
719 hash,
720 |&i| self.rangevec.lookup_str(i) == value,
721 |&i| self.hasher.hash_one(self.rangevec.lookup_str(i)),
722 );
723 match entry {
724 EntryMut::Occupied(e) => *e.get(),
725 EntryMut::Vacant(e) => {
726 let id = self.rangevec.try_push_str_mut(value)?;
727 *e.insert(id).get()
728 }
729 }
730 };
731
732 #[cfg(feature = "debug")]
733 {
734 *self.references.get_mut() += 1;
735 }
736 Some(InternedStr::new(id))
737 }
738
739 pub(crate) fn push(&mut self, value: &str) -> I {
750 match self.try_push(value) {
751 Some(x) => x,
752 None => panic!("Cannot intern in a full ArenaStr"),
753 }
754 }
755
756 pub(crate) fn try_push(&mut self, value: &str) -> Option<I> {
765 let hash = self.hasher.hash_one(value);
766 let id = self.rangevec.try_push_str_mut(value)?;
767 #[cfg(not(feature = "sync"))]
768 self.map.insert_unique(hash, id, |&i| {
769 self.hasher.hash_one(self.rangevec.lookup_str(i))
770 });
771 #[cfg(feature = "sync")]
772 self.map.insert_unique_mut(hash, id, |&i| {
773 self.hasher.hash_one(self.rangevec.lookup_str(i))
774 });
775
776 #[cfg(feature = "debug")]
777 {
778 *self.references.get_mut() += 1;
779 }
780 Some(id)
781 }
782}
783
784impl<H, I: Index> ArenaStr<H, I> {
785 pub fn lookup(&self, interned: InternedStr<H, I>) -> &str {
801 self.lookup_str(interned.id)
802 }
803
804 pub fn try_lookup(&self, interned: InternedStr<H, I>) -> Option<&str> {
816 self.rangevec.try_lookup_str(interned.id)
817 }
818
819 pub fn lookup_bytes(&self, interned: InternedStr<H, I>) -> &[u8] {
832 self.rangevec.lookup_bytes(interned.id)
833 }
834
835 pub fn try_lookup_bytes(&self, interned: InternedStr<H, I>) -> Option<&[u8]> {
844 self.rangevec.try_lookup_bytes(interned.id)
845 }
846
847 fn lookup_str(&self, id: I) -> &str {
848 self.rangevec.lookup_str(id)
849 }
850}
851
852impl<H, I> ArenaStr<H, I>
853where
854 H: BuildHasher,
855 I: Index,
856{
857 pub fn truncate(&mut self, snapshot: SnapshotStrMark<H, I>) {
863 if self.rangevec.ranges.len() <= snapshot.mark {
864 return;
865 }
866
867 for range in self.rangevec.ranges.iter().skip(snapshot.mark) {
868 let value: &str = &self.rangevec.vec[range.start.to_usize()..range.end.to_usize()];
869 let hash = self.hasher.hash_one(value);
870 #[cfg(not(feature = "sync"))]
871 if let Entry::Occupied(entry) = self.map.entry(
872 hash,
873 |&i| self.rangevec.lookup_str(i) == value,
874 |&i| self.hasher.hash_one(self.rangevec.lookup_str(i)),
875 ) {
876 entry.remove();
877 }
878 #[cfg(feature = "sync")]
879 if let EntryMut::Occupied(entry) = self.map.entry_mut(
880 hash,
881 |&i| self.rangevec.lookup_str(i) == value,
882 |&i| self.hasher.hash_one(self.rangevec.lookup_str(i)),
883 ) {
884 entry.remove();
885 }
886 }
887
888 self.rangevec.truncate(snapshot.mark);
889 }
890}
891
892#[cfg(feature = "serde")]
893impl<H, I> Serialize for ArenaStr<H, I>
894where
895 I: Index + Serialize,
896{
897 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
898 where
899 S: Serializer,
900 {
901 let mut tuple = serializer.serialize_tuple(2)?;
902
903 let ranges = RangeWrapper::new(&self.rangevec.ranges);
904 tuple.serialize_element(&ranges)?;
905
906 let (ranges_len, total_len) = ranges.into_parts();
907 tuple.serialize_element(&ArenaStrWrapper {
908 ranges_len,
909 total_len,
910 rangevec: &self.rangevec,
911 })?;
912
913 tuple.end()
914 }
915}
916
917#[cfg(feature = "postcard-schema")]
918impl<H, I> Schema for ArenaStr<H, I>
919where
920 I: Schema,
921{
922 const SCHEMA: &'static NamedType = &NamedType {
923 name: "ArenaStr",
924 ty: &DataModelType::Tuple(&[
925 &NamedType {
926 name: "",
927 ty: &DataModelType::Seq(I::SCHEMA),
928 },
929 &NamedType {
930 name: "",
931 ty: &DataModelType::String,
932 },
933 ]),
934 };
935}
936
937#[cfg(feature = "serde")]
938struct ArenaStrWrapper<'a, I> {
939 ranges_len: I,
940 total_len: I,
941 rangevec: &'a RangeVecStr<I>,
942}
943
944#[cfg(feature = "serde")]
945impl<'a, I> Serialize for ArenaStrWrapper<'a, I>
946where
947 I: Index,
948{
949 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
950 where
951 S: Serializer,
952 {
953 let mut string = String::with_capacity(self.total_len.to_usize());
955 for range in self.rangevec.ranges.iter().take(self.ranges_len.to_usize()) {
956 let s = &self.rangevec.vec[range.start.to_usize()..range.end.to_usize()];
957 string.push_str(s);
958 }
959
960 serializer.serialize_str(&string)
961 }
962}
963
964#[cfg(feature = "serde")]
965impl<'de, H, I> Deserialize<'de> for ArenaStr<H, I>
966where
967 H: Default + BuildHasher,
968 I: Index + Deserialize<'de>,
969{
970 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
971 where
972 D: Deserializer<'de>,
973 {
974 deserializer.deserialize_tuple(2, ArenaStrVisitor::new())
975 }
976}
977
978#[cfg(feature = "serde")]
979struct ArenaStrVisitor<H, I> {
980 _phantom: PhantomData<fn() -> ArenaStr<H, I>>,
981}
982
983#[cfg(feature = "serde")]
984impl<H, I> ArenaStrVisitor<H, I> {
985 fn new() -> Self {
986 Self {
987 _phantom: PhantomData,
988 }
989 }
990}
991
992#[cfg(feature = "serde")]
993impl<'de, H, I> Visitor<'de> for ArenaStrVisitor<H, I>
994where
995 H: Default + BuildHasher,
996 I: Index + Deserialize<'de>,
997{
998 type Value = ArenaStr<H, I>;
999
1000 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1001 formatter.write_str("a pair of values")
1002 }
1003
1004 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1005 where
1006 A: SeqAccess<'de>,
1007 {
1008 let sizes: Vec<I> = seq
1009 .next_element()?
1010 .ok_or_else(|| A::Error::invalid_length(0, &self))?;
1011 let string: CowStr = seq
1012 .next_element()?
1013 .ok_or_else(|| A::Error::invalid_length(1, &self))?;
1014
1015 let mut arena =
1016 ArenaStr::try_with_capacity(sizes.len(), string.0.len()).ok_or_else(|| {
1017 Error::custom(format!(
1018 "Cannot create an ArenaStr with capacity for {} strings of {} bytes",
1019 sizes.len(),
1020 string.0.len()
1021 ))
1022 })?;
1023
1024 let mut start = 0;
1025 for size in sizes {
1026 let size = size.to_usize();
1027 arena
1028 .try_push(&string.0[start..start + size])
1029 .ok_or(Error::custom(
1030 "ArenaStr is full, cannot push more values to it",
1031 ))?;
1032 start += size;
1033 }
1034
1035 Ok(arena)
1036 }
1037}
1038
1039pub struct SnapshotStrMark<H = DefaultBuildHasher, I = u32> {
1044 mark: usize,
1045 _phantom: PhantomData<fn() -> ArenaStr<H, I>>,
1046}
1047
1048impl<H, I> Default for SnapshotStrMark<H, I> {
1049 fn default() -> Self {
1050 Self {
1051 mark: 0,
1052 _phantom: PhantomData,
1053 }
1054 }
1055}
1056
1057impl<H, I> Clone for SnapshotStrMark<H, I> {
1058 fn clone(&self) -> Self {
1059 *self
1060 }
1061}
1062
1063impl<H, I> Copy for SnapshotStrMark<H, I> {}
1064
1065pub struct SnapshotStr<'a, H = DefaultBuildHasher, I = u32> {
1070 #[cfg_attr(not(feature = "serde"), expect(dead_code))]
1071 arena: &'a ArenaStr<H, I>,
1072 mark: usize,
1073}
1074
1075impl<H, I> SnapshotStr<'_, H, I> {
1076 pub fn mark(&self) -> SnapshotStrMark<H, I> {
1078 SnapshotStrMark {
1079 mark: self.mark,
1080 _phantom: PhantomData,
1081 }
1082 }
1083
1084 #[cfg(feature = "serde")]
1086 pub fn diff(&self, start: SnapshotStrMark<H, I>) -> SnapshotStrDiff<'_, H, I> {
1087 SnapshotStrDiff {
1088 arena: self.arena,
1089 start: start.mark,
1090 end: self.mark,
1091 }
1092 }
1093}
1094
1095#[cfg(feature = "serde")]
1100pub struct SnapshotStrDiff<'a, H = DefaultBuildHasher, I = u32> {
1101 arena: &'a ArenaStr<H, I>,
1102 start: usize,
1103 end: usize,
1104}
1105
1106#[cfg(feature = "serde")]
1107impl<H, I> Serialize for SnapshotStrDiff<'_, H, I>
1108where
1109 I: Index + Serialize,
1110{
1111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1112 where
1113 S: Serializer,
1114 {
1115 let mut tuple = serializer.serialize_tuple(2)?;
1116
1117 let ranges = SnapshotRangeWrapper::new(&self.arena.rangevec.ranges, self.start, self.end);
1118 tuple.serialize_element(&ranges)?;
1119
1120 let total_len = ranges.into_inner();
1121 tuple.serialize_element(&SnapshotArenaStrWrapper {
1122 total_len,
1123 start: self.start,
1124 end: self.end,
1125 rangevec: &self.arena.rangevec,
1126 })?;
1127
1128 tuple.end()
1129 }
1130}
1131
1132#[cfg(all(feature = "serde", feature = "postcard-schema"))]
1133impl<H, I> Schema for SnapshotStrDiff<'_, H, I>
1134where
1135 I: Schema,
1136{
1137 const SCHEMA: &'static NamedType = &NamedType {
1138 name: "SnapshotStrDiff",
1139 ty: &DataModelType::Tuple(&[
1140 &NamedType {
1141 name: "",
1142 ty: &DataModelType::Seq(I::SCHEMA),
1143 },
1144 &NamedType {
1145 name: "",
1146 ty: &DataModelType::String,
1147 },
1148 ]),
1149 };
1150}
1151
1152#[cfg(feature = "serde")]
1153struct SnapshotArenaStrWrapper<'a, I> {
1154 total_len: I,
1155 start: usize,
1156 end: usize,
1157 rangevec: &'a RangeVecStr<I>,
1158}
1159
1160#[cfg(feature = "serde")]
1161impl<'a, I> Serialize for SnapshotArenaStrWrapper<'a, I>
1162where
1163 I: Index,
1164{
1165 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1166 where
1167 S: Serializer,
1168 {
1169 let mut string = String::with_capacity(self.total_len.to_usize());
1171 for range in self.rangevec.ranges.iter().take(self.end).skip(self.start) {
1172 let s = &self.rangevec.vec[range.start.to_usize()..range.end.to_usize()];
1173 string.push_str(s);
1174 }
1175
1176 serializer.serialize_str(&string)
1177 }
1178}
1179
1180#[cfg(feature = "serde")]
1183pub struct ExtendArenaStr<'a, H = DefaultBuildHasher, I = u32> {
1184 arena: &'a mut ArenaStr<H, I>,
1185}
1186
1187#[cfg(feature = "serde")]
1188impl<'a, H, I> ExtendArenaStr<'a, H, I> {
1189 pub fn new(arena: &'a mut ArenaStr<H, I>) -> Self {
1191 Self { arena }
1192 }
1193}
1194
1195#[cfg(feature = "serde")]
1196impl<'de, H, I> DeserializeSeed<'de> for ExtendArenaStr<'_, H, I>
1197where
1198 H: Default + BuildHasher,
1199 I: Index + Deserialize<'de>,
1200{
1201 type Value = ();
1202
1203 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1204 where
1205 D: Deserializer<'de>,
1206 {
1207 deserializer.deserialize_tuple(2, ExtendArenaStrVisitor { arena: self.arena })
1208 }
1209}
1210
1211#[cfg(feature = "serde")]
1212struct ExtendArenaStrVisitor<'a, H, I> {
1213 arena: &'a mut ArenaStr<H, I>,
1214}
1215
1216#[cfg(feature = "serde")]
1217impl<'de, H, I> Visitor<'de> for ExtendArenaStrVisitor<'_, H, I>
1218where
1219 H: Default + BuildHasher,
1220 I: Index + Deserialize<'de>,
1221{
1222 type Value = ();
1223
1224 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1225 formatter.write_str("a pair of values")
1226 }
1227
1228 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1229 where
1230 A: SeqAccess<'de>,
1231 {
1232 let sizes: Vec<I> = seq
1233 .next_element()?
1234 .ok_or_else(|| A::Error::invalid_length(0, &self))?;
1235 let string: CowStr = seq
1236 .next_element()?
1237 .ok_or_else(|| A::Error::invalid_length(1, &self))?;
1238
1239 let mut start = 0;
1240 for size in sizes {
1241 let size = size.to_usize();
1242 self.arena
1243 .try_push(&string.0[start..start + size])
1244 .ok_or(Error::custom(
1245 "ArenaStr is full, cannot push more values to it",
1246 ))?;
1247 start += size;
1248 }
1249
1250 Ok(())
1251 }
1252}
1253
1254#[cfg(all(feature = "delta", feature = "serde"))]
1255mod delta {
1256 use super::*;
1257 use crate::{Accumulator, DeltaEncoding};
1258 use alloc::boxed::Box;
1259 use core::marker::PhantomData;
1260 use serde::ser::SerializeSeq;
1261 use serde_cow::CowBytes;
1262
1263 impl<H, I, Accum> Serialize for DeltaEncoding<&ArenaStr<H, I>, Accum>
1264 where
1265 I: Index + Serialize,
1266 Accum: Accumulator<Value = str, Storage = Box<str>, DeltaStorage = Box<[u8]>>,
1267 {
1268 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1269 where
1270 S: Serializer,
1271 {
1272 let mut tuple = serializer.serialize_tuple(2)?;
1273
1274 let ranges = RangeWrapper::new(&self.rangevec.ranges);
1275 tuple.serialize_element(&ranges)?;
1276
1277 let (ranges_len, total_len) = ranges.into_parts();
1278 tuple.serialize_element(&ArenaStrWrapper {
1279 ranges_len,
1280 total_len,
1281 rangevec: &self.map_ref(|arena| &arena.rangevec),
1282 })?;
1283
1284 tuple.end()
1285 }
1286 }
1287
1288 #[cfg(feature = "postcard-schema")]
1289 impl<H, I, Accum> Schema for DeltaEncoding<&ArenaStr<H, I>, Accum>
1290 where
1291 I: Schema,
1292 Accum: Accumulator<Value = str, Storage = Box<str>, DeltaStorage = Box<[u8]>>,
1293 {
1294 const SCHEMA: &'static NamedType = &NamedType {
1295 name: "DeltaEncoding<ArenaStr>",
1296 ty: &DataModelType::Tuple(&[
1297 &NamedType {
1298 name: "",
1299 ty: &DataModelType::Seq(I::SCHEMA),
1300 },
1301 &NamedType {
1302 name: "",
1303 ty: &DataModelType::ByteArray,
1304 },
1305 ]),
1306 };
1307 }
1308
1309 struct ArenaStrWrapper<'a, I, Accum> {
1310 ranges_len: I,
1311 total_len: I,
1312 rangevec: &'a DeltaEncoding<&'a RangeVecStr<I>, Accum>,
1313 }
1314
1315 impl<'a, I, Accum> Serialize for ArenaStrWrapper<'a, I, Accum>
1316 where
1317 I: Index,
1318 Accum: Accumulator<Value = str, Storage = Box<str>, DeltaStorage = Box<[u8]>>,
1319 {
1320 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1321 where
1322 S: Serializer,
1323 {
1324 let mut seq = serializer.serialize_seq(Some(self.total_len.to_usize()))?;
1325
1326 let mut acc = Accum::default();
1327 for range in self.rangevec.ranges.iter().take(self.ranges_len.to_usize()) {
1328 let slice = &self.rangevec.vec[range.start.to_usize()..range.end.to_usize()];
1329 let delta = acc.fold(slice);
1330 assert_eq!(
1331 delta.len(),
1332 slice.len(),
1333 "Invalid Accumulator implementation for DeltaEncoding of ArenaStr: delta length must match source string length (in bytes)"
1334 );
1335 for d in delta {
1336 seq.serialize_element(&d)?;
1337 }
1338 }
1339
1340 seq.end()
1341 }
1342 }
1343
1344 impl<'de, H, I, Accum> Deserialize<'de> for DeltaEncoding<ArenaStr<H, I>, Accum>
1345 where
1346 H: Default + BuildHasher,
1347 I: Index + Deserialize<'de>,
1348 Accum: Accumulator<Value = str, Storage = Box<str>, Delta = [u8]>,
1349 {
1350 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1351 where
1352 D: Deserializer<'de>,
1353 {
1354 deserializer.deserialize_tuple(2, DeltaArenaStrVisitor::new())
1355 }
1356 }
1357
1358 struct DeltaArenaStrVisitor<H, I, Accum> {
1359 _phantom: PhantomData<fn() -> ArenaStr<H, I>>,
1360 _accum: PhantomData<Accum>,
1361 }
1362
1363 impl<H, I, Accum> DeltaArenaStrVisitor<H, I, Accum> {
1364 fn new() -> Self {
1365 Self {
1366 _phantom: PhantomData,
1367 _accum: PhantomData,
1368 }
1369 }
1370 }
1371
1372 impl<'de, H, I, Accum> Visitor<'de> for DeltaArenaStrVisitor<H, I, Accum>
1373 where
1374 H: Default + BuildHasher,
1375 I: Index + Deserialize<'de>,
1376 Accum: Accumulator<Value = str, Storage = Box<str>, Delta = [u8]>,
1377 {
1378 type Value = DeltaEncoding<ArenaStr<H, I>, Accum>;
1379
1380 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1381 formatter.write_str("a pair of values")
1382 }
1383
1384 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1385 where
1386 A: SeqAccess<'de>,
1387 {
1388 let sizes: Vec<I> = seq
1389 .next_element()?
1390 .ok_or_else(|| A::Error::invalid_length(0, &self))?;
1391 let bytes: CowBytes = seq
1392 .next_element()?
1393 .ok_or_else(|| A::Error::invalid_length(1, &self))?;
1394
1395 let mut arena =
1396 ArenaStr::try_with_capacity(sizes.len(), bytes.0.len()).ok_or_else(|| {
1397 Error::custom(format!(
1398 "Cannot create an ArenaStr with capacity for {} strings of {} bytes",
1399 sizes.len(),
1400 bytes.0.len()
1401 ))
1402 })?;
1403
1404 let mut acc = Accum::default();
1405 let mut start = 0;
1406 for size in sizes {
1407 let size = size.to_usize();
1408 let delta = &bytes.0[start..start + size];
1409 let string = acc.unfold(delta);
1410 assert_eq!(
1411 delta.len(),
1412 string.len(),
1413 "Invalid Accumulator implementation for DeltaEncoding of ArenaSlice: delta length must match destination string length (in bytes)"
1414 );
1415 arena.try_push(&string).ok_or(Error::custom(
1416 "ArenaStr is full, cannot push more values to it",
1417 ))?;
1418 start += size;
1419 }
1420
1421 Ok(DeltaEncoding {
1422 inner: arena,
1423 _phantom: PhantomData,
1424 })
1425 }
1426 }
1427}
1428
1429#[cfg(test)]
1430mod test {
1431 use super::*;
1432 #[cfg(all(feature = "delta", feature = "serde"))]
1433 use crate::{Accumulator, DeltaEncoding};
1434 #[cfg(feature = "sync")]
1435 use std::thread;
1436
1437 #[cfg(feature = "postcard-schema")]
1438 #[test]
1439 fn test_schemas() {
1440 assert_eq!(
1441 InternedStr::<DefaultBuildHasher>::SCHEMA,
1442 &NamedType {
1443 name: "InternedStr",
1444 ty: &DataModelType::NewtypeStruct(&NamedType {
1445 name: "u32",
1446 ty: &DataModelType::U32,
1447 }),
1448 }
1449 );
1450 assert_eq!(
1451 ArenaStr::<DefaultBuildHasher>::SCHEMA,
1452 &NamedType {
1453 name: "ArenaStr",
1454 ty: &DataModelType::Tuple(&[
1455 &NamedType {
1456 name: "",
1457 ty: &DataModelType::Seq(&NamedType {
1458 name: "u32",
1459 ty: &DataModelType::U32,
1460 }),
1461 },
1462 &NamedType {
1463 name: "",
1464 ty: &DataModelType::String,
1465 }
1466 ]),
1467 }
1468 );
1469 #[cfg(feature = "serde")]
1470 assert_eq!(
1471 SnapshotStrDiff::<DefaultBuildHasher>::SCHEMA,
1472 &NamedType {
1473 name: "SnapshotStrDiff",
1474 ty: &DataModelType::Tuple(&[
1475 &NamedType {
1476 name: "",
1477 ty: &DataModelType::Seq(&NamedType {
1478 name: "u32",
1479 ty: &DataModelType::U32,
1480 }),
1481 },
1482 &NamedType {
1483 name: "",
1484 ty: &DataModelType::String,
1485 }
1486 ]),
1487 }
1488 );
1489 }
1490
1491 fn make_utf8_string(i: usize) -> String {
1492 let mut i = i as u32;
1493 let mut s = String::new();
1494 while i != 0 {
1495 let j = i % (64 + 26);
1496 let c = if j < 64 {
1497 char::from_u32(0x410 + j).expect("Invalid Unicode value")
1499 } else {
1500 char::from_u32(b'a' as u32 + j - 64).expect("Invalid Unicode value")
1501 };
1502 i /= 64 + 26;
1503 s.push(c);
1504 }
1505 s
1506 }
1507
1508 #[test]
1509 fn test_utf8_string() {
1510 assert_eq!(make_utf8_string(0), "");
1511 assert_eq!(make_utf8_string(0).len(), 0);
1512 assert_eq!(make_utf8_string(5), "Е");
1513 assert_eq!(make_utf8_string(5).len(), 2);
1514 assert_eq!(make_utf8_string(25), "Щ");
1515 assert_eq!(make_utf8_string(25).len(), 2);
1516 assert_eq!(make_utf8_string(125), "гБ");
1517 assert_eq!(make_utf8_string(125).len(), 4);
1518 assert_eq!(make_utf8_string(625), "vЖ");
1519 assert_eq!(make_utf8_string(625).len(), 3);
1520 assert_eq!(make_utf8_string(3125), "bв");
1521 assert_eq!(make_utf8_string(3125).len(), 3);
1522 assert_eq!(make_utf8_string(15625), "чtБ");
1523 assert_eq!(make_utf8_string(15625).len(), 5);
1524 assert_eq!(make_utf8_string(78125), "ЕъЙ");
1525 assert_eq!(make_utf8_string(78125).len(), 6);
1526 assert_eq!(make_utf8_string(390625), "ЩФр");
1527 assert_eq!(make_utf8_string(390625).len(), 6);
1528 assert_eq!(make_utf8_string(1953125), "гЛэВ");
1529 assert_eq!(make_utf8_string(1953125).len(), 8);
1530 assert_eq!(make_utf8_string(9765625), "vшгН");
1531 assert_eq!(make_utf8_string(9765625).len(), 7);
1532 }
1533
1534 #[test]
1535 fn test_lookup() {
1536 let mut arena: ArenaStr = ArenaStr::default();
1537
1538 let empty = arena.intern_mut("");
1539 let a = arena.intern_mut("a");
1540 let b = arena.intern_mut("bb");
1541 let c = arena.intern_mut("ccc");
1542 let d = arena.intern_mut("dddd");
1543 let e = arena.intern_mut("eeeee");
1544
1545 assert_eq!(arena.lookup(empty), "");
1546 assert_eq!(arena.lookup(a), "a");
1547 assert_eq!(arena.lookup(b), "bb");
1548 assert_eq!(arena.lookup(c), "ccc");
1549 assert_eq!(arena.lookup(d), "dddd");
1550 assert_eq!(arena.lookup(e), "eeeee");
1551 }
1552
1553 #[cfg(feature = "sync")]
1554 #[test]
1555 fn test_intern_lookup() {
1556 let arena: ArenaStr = ArenaStr::default();
1557 for i in 0..100 {
1558 assert_eq!(arena.intern(&make_utf8_string(i)).id.to_usize(), i);
1559 }
1560 for i in 0..100 {
1561 assert_eq!(
1562 arena.lookup(InternedStr::new(Index::from_usize(i))),
1563 &make_utf8_string(i)
1564 );
1565 }
1566 }
1567
1568 #[test]
1569 fn test_intern_mut_lookup() {
1570 let mut arena: ArenaStr = ArenaStr::default();
1571 for i in 0..100 {
1572 assert_eq!(arena.intern_mut(&make_utf8_string(i)).id.to_usize(), i);
1573 }
1574 for i in 0..100 {
1575 assert_eq!(
1576 arena.lookup(InternedStr::new(Index::from_usize(i))),
1577 &make_utf8_string(i)
1578 );
1579 }
1580 }
1581
1582 #[cfg(all(feature = "raw", not(miri)))]
1583 const NUM_ITERS: usize = 100;
1584 #[cfg(all(feature = "raw", miri))]
1585 const NUM_ITERS: usize = 20;
1586 #[cfg(all(feature = "raw", not(miri)))]
1587 const NUM_VALUES: usize = 50;
1588 #[cfg(all(feature = "raw", miri))]
1589 const NUM_VALUES: usize = 10;
1590
1591 #[cfg(feature = "raw")]
1592 #[test]
1593 fn test_push_mut_same_value_works() {
1594 let mut arena: ArenaStr = ArenaStr::default();
1595 for i in 0..NUM_ITERS {
1596 for j in 0..NUM_VALUES {
1597 let s = make_utf8_string(j);
1598 assert_eq!(arena.push_mut(&s).to_usize(), i * NUM_VALUES + j);
1599 let id = arena.intern_mut(&s).id;
1600 let id = id.to_usize();
1601 assert_eq!(id % NUM_VALUES, j);
1602 assert!(id / NUM_VALUES <= i);
1603 }
1604 }
1605 for i in 0..NUM_ITERS {
1606 for j in 0..NUM_VALUES {
1607 assert_eq!(
1608 arena.lookup(InternedStr::new(Index::from_usize(i * NUM_VALUES + j))),
1609 &make_utf8_string(j)
1610 );
1611 }
1612 }
1613 }
1614
1615 #[cfg(feature = "sync")]
1616 const NUM_READERS: usize = 4;
1617 #[cfg(feature = "sync")]
1618 const NUM_WRITERS: usize = 4;
1619 #[cfg(all(feature = "sync", not(miri)))]
1620 const NUM_ITEMS: usize = 1_000_000;
1621 #[cfg(all(feature = "sync", miri))]
1622 const NUM_ITEMS: usize = 100;
1623
1624 #[cfg(feature = "sync")]
1625 #[test]
1626 fn test_intern_lookup_concurrent_reads() {
1627 let arena: ArenaStr = ArenaStr::default();
1628 thread::scope(|s| {
1629 for _ in 0..NUM_READERS {
1630 s.spawn(|| {
1631 loop {
1632 let len = arena.strings();
1633 if len > 0 {
1634 let last = len - 1;
1635 assert_eq!(
1636 arena.lookup(InternedStr::new(Index::from_usize(last))),
1637 &make_utf8_string(last)
1638 );
1639 if len == NUM_ITEMS {
1640 break;
1641 }
1642 }
1643 }
1644 });
1645 }
1646 s.spawn(|| {
1647 for j in 0..NUM_ITEMS {
1648 assert_eq!(arena.intern(&make_utf8_string(j)).id.to_usize(), j);
1649 }
1650 });
1651 });
1652 }
1653
1654 #[cfg(feature = "sync")]
1655 #[test]
1656 fn test_intern_lookup_concurrent_writes() {
1657 let arena: ArenaStr = ArenaStr::default();
1658 thread::scope(|s| {
1659 s.spawn(|| {
1660 loop {
1661 let len = arena.strings();
1662 if len > 0 {
1663 let last = len - 1;
1664 assert_eq!(
1665 arena.lookup(InternedStr::new(Index::from_usize(last))),
1666 &make_utf8_string(last)
1667 );
1668 if len == NUM_ITEMS {
1669 break;
1670 }
1671 }
1672 }
1673 });
1674 for _ in 0..NUM_WRITERS {
1675 s.spawn(|| {
1676 for j in 0..NUM_ITEMS {
1677 assert_eq!(arena.intern(&make_utf8_string(j)).id.to_usize(), j);
1678 }
1679 });
1680 }
1681 });
1682 }
1683
1684 #[cfg(feature = "sync")]
1685 #[test]
1686 fn test_intern_lookup_concurrent_readwrites() {
1687 let arena: ArenaStr = ArenaStr::default();
1688 thread::scope(|s| {
1689 for _ in 0..NUM_READERS {
1690 s.spawn(|| {
1691 loop {
1692 let len = arena.strings();
1693 if len > 0 {
1694 let last = len - 1;
1695 assert_eq!(
1696 arena.lookup(InternedStr::new(Index::from_usize(last))),
1697 &make_utf8_string(last)
1698 );
1699 if len == NUM_ITEMS {
1700 break;
1701 }
1702 }
1703 }
1704 });
1705 }
1706 for _ in 0..NUM_WRITERS {
1707 s.spawn(|| {
1708 for j in 0..NUM_ITEMS {
1709 assert_eq!(arena.intern(&make_utf8_string(j)).id.to_usize(), j);
1710 }
1711 });
1712 }
1713 });
1714 }
1715
1716 #[test]
1717 fn test_truncate() {
1718 let mut arena: ArenaStr = ArenaStr::default();
1719
1720 let empty = arena.intern_mut("");
1721 let a = arena.intern_mut("a");
1722 let b = arena.intern_mut("bb");
1723 let c = arena.intern_mut("ccc");
1724 let snapshot = arena.snapshot().mark();
1725
1726 arena.intern_mut("dddd");
1727 arena.intern_mut("eeeee");
1728
1729 arena.truncate(snapshot);
1730 assert_eq!(arena.strings(), 4);
1731 assert_eq!(arena.lookup(empty), "");
1732 assert_eq!(arena.lookup(a), "a");
1733 assert_eq!(arena.lookup(b), "bb");
1734 assert_eq!(arena.lookup(c), "ccc");
1735
1736 let f = arena.intern_mut("ffffff");
1737 let g = arena.intern_mut("ggggggg");
1738
1739 assert_eq!(arena.strings(), 6);
1740 assert_eq!(arena.lookup(empty), "");
1741 assert_eq!(arena.lookup(a), "a");
1742 assert_eq!(arena.lookup(b), "bb");
1743 assert_eq!(arena.lookup(c), "ccc");
1744 assert_eq!(arena.lookup(f), "ffffff");
1745 assert_eq!(arena.lookup(g), "ggggggg");
1746 }
1747
1748 #[cfg(feature = "serde")]
1749 #[test]
1750 fn test_serde_postcard() {
1751 let mut arena: ArenaStr = ArenaStr::default();
1752
1753 let empty = arena.intern_mut("");
1754 let a = arena.intern_mut("a");
1755 let b = arena.intern_mut("bb");
1756 let c = arena.intern_mut("ccc");
1757 let d = arena.intern_mut("dddd");
1758 let e = arena.intern_mut("eeeee");
1759
1760 assert_eq!(arena.strings(), 6);
1761 assert!(arena.bytes() >= 15);
1762
1763 let serialized_arena = postcard::to_stdvec(&arena).expect("Failed to serialize arena");
1764 assert_eq!(
1765 serialized_arena,
1766 vec![
1767 6, 0, 1, 2, 3, 4, 5, 15, b'a', b'b', b'b', b'c', b'c', b'c', b'd', b'd', b'd',
1768 b'd', b'e', b'e', b'e', b'e', b'e'
1769 ]
1770 );
1771 let new_arena: ArenaStr =
1772 postcard::from_bytes(&serialized_arena).expect("Failed to deserialize arena");
1773 assert_eq!(new_arena, arena);
1774
1775 assert_eq!(new_arena.strings(), 6);
1776 assert_eq!(new_arena.bytes(), 15);
1777
1778 let serialized_handles = postcard::to_stdvec(&[empty, a, b, c, d, e])
1779 .expect("Failed to serialize interned handles");
1780 assert_eq!(serialized_handles, vec![0, 1, 2, 3, 4, 5]);
1781 let new_handles: [InternedStr; 6] = postcard::from_bytes(&serialized_handles)
1782 .expect("Failed to deserialize interned handles");
1783 assert_eq!(new_handles, [empty, a, b, c, d, e]);
1784
1785 assert_eq!(new_arena.lookup(empty), "");
1786 assert_eq!(new_arena.lookup(a), "a");
1787 assert_eq!(new_arena.lookup(b), "bb");
1788 assert_eq!(new_arena.lookup(c), "ccc");
1789 assert_eq!(new_arena.lookup(d), "dddd");
1790 assert_eq!(new_arena.lookup(e), "eeeee");
1791 }
1792
1793 #[cfg(feature = "serde")]
1794 #[test]
1795 fn test_serde_json() {
1796 let mut arena: ArenaStr = ArenaStr::default();
1797
1798 let empty = arena.intern_mut("");
1799 let a = arena.intern_mut("a");
1800 let b = arena.intern_mut("bb");
1801 let c = arena.intern_mut("ccc");
1802 let d = arena.intern_mut("dddd");
1803 let e = arena.intern_mut("eeeee");
1804
1805 assert_eq!(arena.strings(), 6);
1806 assert!(arena.bytes() >= 15);
1807
1808 let serialized_arena = serde_json::to_string(&arena).expect("Failed to serialize arena");
1809 assert_eq!(serialized_arena, r#"[[0,1,2,3,4,5],"abbcccddddeeeee"]"#);
1810 let new_arena: ArenaStr =
1811 serde_json::from_str(&serialized_arena).expect("Failed to deserialize arena");
1812 assert_eq!(new_arena, arena);
1813
1814 assert_eq!(new_arena.strings(), 6);
1815 assert_eq!(new_arena.bytes(), 15);
1816
1817 let serialized_handles = serde_json::to_string(&[empty, a, b, c, d, e])
1818 .expect("Failed to serialize interned handles");
1819 assert_eq!(serialized_handles, "[0,1,2,3,4,5]");
1820 let new_handles: [InternedStr; 6] = serde_json::from_str(&serialized_handles)
1821 .expect("Failed to deserialize interned handles");
1822 assert_eq!(new_handles, [empty, a, b, c, d, e]);
1823 }
1824
1825 #[cfg(all(feature = "delta", feature = "serde"))]
1826 #[derive(Default)]
1827 struct StringAccumulator {
1828 previous: Vec<u8>,
1829 }
1830
1831 #[cfg(all(feature = "delta", feature = "serde"))]
1832 impl Accumulator for StringAccumulator {
1833 type Value = str;
1834 type Storage = Box<str>;
1835 type Delta = [u8];
1836 type DeltaStorage = Box<[u8]>;
1837
1838 fn fold(&mut self, v: &Self::Value) -> Self::DeltaStorage {
1839 let mut delta = Vec::with_capacity(v.len());
1840 for (i, byte) in v.bytes().enumerate() {
1841 delta.push(byte ^ self.previous.get(i).copied().unwrap_or(0));
1842 }
1843 self.previous = v.into();
1844 delta.into()
1845 }
1846
1847 fn unfold(&mut self, d: &Self::Delta) -> Self::Storage {
1848 let mut value = Vec::with_capacity(d.len());
1849 for (i, byte) in d.iter().enumerate() {
1850 value.push(byte ^ self.previous.get(i).copied().unwrap_or(0));
1851 }
1852 self.previous = value.clone();
1853 String::from_utf8(value)
1854 .expect("Invalid UTF-8 encoding")
1855 .into()
1856 }
1857 }
1858
1859 #[cfg(all(feature = "delta", feature = "serde"))]
1860 #[test]
1861 fn test_serde_delta() {
1862 let mut arena: ArenaStr = ArenaStr::default();
1863
1864 let empty = arena.intern_mut("");
1865 let a = arena.intern_mut("a");
1866 let b = arena.intern_mut("bb");
1867 let c = arena.intern_mut("ccc");
1868 let d = arena.intern_mut("dddd");
1869 let e = arena.intern_mut("eeeee");
1870
1871 assert_eq!(arena.strings(), 6);
1872 assert!(arena.bytes() >= 15);
1873
1874 let delta_encoded: DeltaEncoding<&ArenaStr, StringAccumulator> = DeltaEncoding::new(&arena);
1875 let serialized_arena =
1876 postcard::to_stdvec(&delta_encoded).expect("Failed to serialize arena");
1877 assert_eq!(
1878 serialized_arena,
1879 vec![
1880 6, 0, 1, 2, 3, 4, 5, 15, 97, 3, 98, 1, 1, 99, 7, 7, 7, 100, 1, 1, 1, 1, 101
1881 ]
1882 );
1883 let delta_encoded: DeltaEncoding<ArenaStr, StringAccumulator> =
1884 postcard::from_bytes(&serialized_arena).expect("Failed to deserialize arena");
1885 let new_arena = delta_encoded.into_inner();
1886
1887 assert_eq!(new_arena.strings(), 6);
1888 assert_eq!(new_arena.bytes(), 15);
1889
1890 let serialized_handles = postcard::to_stdvec(&[empty, a, b, c, d, e])
1891 .expect("Failed to serialize interned handles");
1892 assert_eq!(serialized_handles, vec![0, 1, 2, 3, 4, 5]);
1893 let new_handles: [InternedStr; 6] = postcard::from_bytes(&serialized_handles)
1894 .expect("Failed to deserialize interned handles");
1895 assert_eq!(new_handles, [empty, a, b, c, d, e]);
1896
1897 assert_eq!(new_arena.lookup(empty), "");
1898 assert_eq!(new_arena.lookup(a), "a");
1899 assert_eq!(new_arena.lookup(b), "bb");
1900 assert_eq!(new_arena.lookup(c), "ccc");
1901 assert_eq!(new_arena.lookup(d), "dddd");
1902 assert_eq!(new_arena.lookup(e), "eeeee");
1903 }
1904}