Skip to main content

blazinterner/
str.rs

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
41/// A handle to an interned value in an [`ArenaStr`].
42pub 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    /// Creates an interned value for the given index.
109    ///
110    /// This is a low-level function. You should instead use the
111    /// [`ArenaStr::intern()`] API to intern a value, unless you really know
112    /// what you're doing.
113    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    /// Obtains the underlying interning index.
121    ///
122    /// This is a low-level function. You should instead use the
123    /// [`ArenaStr::lookup()`] and [`ArenaStr::lookup_bytes()`] APIs, unless you
124    /// really know what you're doing.
125    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
312/// Interning arena for strings.
313pub 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    /// Creates a new arena with pre-allocated space to store at least the given
345    /// number of strings, totalling the given number of bytes.
346    ///
347    /// # Panics
348    ///
349    /// This function panics if the capacity exceeds the maximum allocation size
350    /// for an arena indexed by `I`. Use
351    /// [`try_with_capacity`](Self::try_with_capacity) for a fallible API.
352    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    /// Creates a new arena with pre-allocated space to store at least the given
363    /// number of strings, totalling the given number of bytes.
364    ///
365    /// This returns [`None`] if the capacity exceeds the maximum allocation
366    /// size for an arena indexed by `I`.
367    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    /// Returns the number of strings in this arena.
395    ///
396    /// Note that because [`ArenaStr`] is a concurrent data structure, this is
397    /// only a snapshot as viewed by this thread, and the result may change if
398    /// other threads are inserting values.
399    pub fn strings(&self) -> usize {
400        self.rangevec.ranges.len()
401    }
402
403    /// Returns the total number of bytes in this arena.
404    ///
405    /// Note that because [`ArenaStr`] is a concurrent data structure, this is
406    /// only a snapshot as viewed by this thread, and the result may change if
407    /// other threads are inserting values.
408    pub fn bytes(&self) -> usize {
409        self.rangevec.vec.len()
410    }
411
412    /// Checks if this arena is empty.
413    ///
414    /// Note that because [`ArenaStr`] is a concurrent data structure, this is
415    /// only a snapshot as viewed by this thread, and the result may change if
416    /// other threads are inserting values.
417    pub fn is_empty(&self) -> bool {
418        self.strings() == 0
419    }
420
421    /// Returns a snapshot of this arena.
422    ///
423    /// Note that because [`ArenaStr`] is a concurrent data structure, this is
424    /// only a snapshot as viewed by this thread.
425    ///
426    /// Snapshots can be diffed into a [`SnapshotStrDiff`], which is useful to
427    /// serialize an arena incrementally as values are added to it.
428    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    /// Returns an iterator over all strings in this arena, in indexing order.
438    ///
439    /// Note that because [`ArenaStr`] is a concurrent data structure, this is
440    /// only a snapshot. Once this iterator has been created, for performance
441    /// reasons it will not iterate over items added afterwards, even on the
442    /// same thread.
443    ///
444    /// If you only need to access byte slices,
445    /// [`iter_bytes()`](Self::iter_bytes) may be more efficient.
446    #[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    /// Returns an iterator over all strings (viewed as byte slices) in this
456    /// arena, in indexing order.
457    ///
458    /// Note that because [`ArenaStr`] is a concurrent data structure, this is
459    /// only a snapshot. Once this iterator has been created, for performance
460    /// reasons it will not iterate over items added afterwards, even on the
461    /// same thread.
462    #[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    /// Returns the given string's [`InternedStr`] handle if it is already
478    /// interned.
479    ///
480    /// Otherwise, this simply returns [`None`] without adding the string to
481    /// this arena.
482    ///
483    /// See also [`find_mut()`](Self::find_mut), which is more efficient if you
484    /// hold a mutable reference to this arena as it avoids acquiring locks.
485    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    /// Returns the given string's [`InternedStr`] handle if it is already
493    /// interned.
494    ///
495    /// Otherwise, this simply returns [`None`] without adding the string to
496    /// this arena.
497    ///
498    /// Contrary to [`find()`](Self::find), no locks are held internally because
499    /// this function already takes an exclusive mutable reference to this
500    /// arena.
501    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    /// Unconditionally push a value, without validating that it's already
516    /// interned.
517    ///
518    /// Calling this function multiple times with the same value doesn't violate
519    /// safety, but the value will be stored multiple times in the arena.
520    #[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    /// Prints a summary of the storage used by this arena to stdout.
582    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    /// Returns the total number of references to strings in this arena.
603    ///
604    /// The underlying counter is incremented each time a string is interned,
605    /// whether it was already previously in the arena or not.
606    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    /// Interns the given value in this arena.
617    ///
618    /// If the value was already interned in this arena, its interning index
619    /// will simply be returned. Otherwise it will be stored into the arena.
620    ///
621    /// See also [`intern_mut()`](Self::intern_mut), which is more efficient if
622    /// you hold a mutable reference to this arena as it avoids acquiring locks.
623    ///
624    /// # Panics
625    ///
626    /// This function panics if the arena is full (based on the index type `I`).
627    /// Use [`try_intern()`](Self::try_intern) for a fallible API.
628    #[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    /// Interns the given value in this arena.
637    ///
638    /// If the value was already interned in this arena, its interning index
639    /// will simply be returned. Otherwise it will be stored into the arena.
640    ///
641    /// This returns [`None`] if the arena is full (based on the index type
642    /// `I`).
643    ///
644    /// See also [`try_intern_mut()`](Self::try_intern_mut), which is more
645    /// efficient if you hold a mutable reference to this arena as it avoids
646    /// acquiring locks.
647    #[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    /// Interns the given value in this arena.
669    ///
670    /// If the value was already interned in this arena, its interning index
671    /// will simply be returned. Otherwise it will be stored into the arena.
672    ///
673    /// Contrary to [`intern()`](Self::intern), no locks are held internally
674    /// because this function already takes an exclusive mutable reference to
675    /// this arena.
676    ///
677    /// # Panics
678    ///
679    /// This function panics if the arena is full (based on the index type `I`).
680    /// Use [`try_intern_mut()`](Self::try_intern_mut) for a fallible API.
681    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    /// Interns the given value in this arena.
689    ///
690    /// If the value was already interned in this arena, its interning index
691    /// will simply be returned. Otherwise it will be stored into the arena.
692    ///
693    /// This returns [`None`] if the arena is full (based on the index type
694    /// `I`).
695    ///
696    /// Contrary to [`try_intern()`](Self::try_intern), no locks are held
697    /// internally because this function already takes an exclusive mutable
698    /// reference to this arena.
699    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    /// Unconditionally push a value, without validating that it's already
740    /// interned.
741    ///
742    /// Calling this function multiple times with the same value doesn't violate
743    /// safety, but the value will be stored multiple times in the arena.
744    ///
745    /// # Panics
746    ///
747    /// This function panics if the arena is full (based on the index type `I`).
748    /// Use [`try_push()`](Self::try_push) for a fallible API.
749    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    /// Unconditionally push a value, without validating that it's already
757    /// interned.
758    ///
759    /// Calling this function multiple times with the same value doesn't violate
760    /// safety, but the value will be stored multiple times in the arena.
761    ///
762    /// This returns [`None`] if the arena is full (based on the index type
763    /// `I`).
764    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    /// Retrieves the given [`InternedStr`] value from this arena.
786    ///
787    /// The caller is responsible for ensuring that the same arena was used to
788    /// intern this value, otherwise an arbitrary value will be returned or
789    /// a panic will happen.
790    ///
791    /// If you only need to access the bytes,
792    /// [`lookup_bytes()`](Self::lookup_bytes) may be more efficient.
793    ///
794    /// # Panics
795    ///
796    /// This function panics if the interned handle is out of bounds for this
797    /// arena, for example because the arena was truncated, or because the
798    /// interned handle was deserialized from untrusted data. Use
799    /// [`try_lookup`](Self::try_lookup) for a fallible API.
800    pub fn lookup(&self, interned: InternedStr<H, I>) -> &str {
801        self.lookup_str(interned.id)
802    }
803
804    /// Retrieves the given [`InternedStr`] value from this arena.
805    ///
806    /// The caller is responsible for ensuring that the same arena was used to
807    /// intern this value, otherwise an arbitrary value will be returned.
808    ///
809    /// This returns [`None`] if the interned handle is out of bounds for this
810    /// arena, for example because the arena was truncated, or because the
811    /// interned handle was deserialized from untrusted data.
812    ///
813    /// If you only need to access the bytes,
814    /// [`try_lookup_bytes()`](Self::try_lookup_bytes) may be more efficient.
815    pub fn try_lookup(&self, interned: InternedStr<H, I>) -> Option<&str> {
816        self.rangevec.try_lookup_str(interned.id)
817    }
818
819    /// Retrieves the bytes for the given [`InternedStr`] value from this arena.
820    ///
821    /// The caller is responsible for ensuring that the same arena was used to
822    /// intern this value, otherwise an arbitrary value will be returned or
823    /// a panic will happen.
824    ///
825    /// # Panics
826    ///
827    /// This function panics if the interned handle is out of bounds for this
828    /// arena, for example because the arena was truncated, or because the
829    /// interned handle was deserialized from untrusted data. Use
830    /// [`try_lookup_bytes`](Self::try_lookup_bytes) for a fallible API.
831    pub fn lookup_bytes(&self, interned: InternedStr<H, I>) -> &[u8] {
832        self.rangevec.lookup_bytes(interned.id)
833    }
834
835    /// Retrieves the bytes for the given [`InternedStr`] value from this arena.
836    ///
837    /// The caller is responsible for ensuring that the same arena was used to
838    /// intern this value, otherwise an arbitrary value will be returned.
839    ///
840    /// This returns [`None`] if the interned handle is out of bounds for this
841    /// arena, for example because the arena was truncated, or because the
842    /// interned handle was deserialized from untrusted data.
843    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    /// Truncates this interner back to the given snapshot mark.
858    ///
859    /// This is a no-op if the snapshot mark is larger than this interner (for
860    /// example because the interner was already truncated to a smaller snapshot
861    /// in the meantime).
862    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        // TODO: Make this zero-copy?
954        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
1039/// A mark indicates the position of a [`SnapshotStr`] in an [`ArenaStr`].
1040///
1041/// This allows creating a difference between two snapshots, via
1042/// [`SnapshotStr::diff()`].
1043pub 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
1065/// Snapshot of an [`ArenaStr`].
1066///
1067/// This struct is created by the [`snapshot()`](ArenaStr::snapshot) function on
1068/// [`ArenaStr`].
1069pub 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    /// Returns the position of this snapshot in the arena.
1077    pub fn mark(&self) -> SnapshotStrMark<H, I> {
1078        SnapshotStrMark {
1079            mark: self.mark,
1080            _phantom: PhantomData,
1081        }
1082    }
1083
1084    /// Returns the difference between this snapshot and a previous mark.
1085    #[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/// Difference between two snapshots of an [`ArenaStr`].
1096///
1097/// This is useful to serialize an arena incrementally as more values are added
1098/// to it.
1099#[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        // TODO: Make this zero-copy?
1170        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/// Wrapper to extend an [`ArenaStr`] incrementally, typically by deserializing
1181/// a sequence of serialized [`SnapshotStrDiff`].
1182#[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    /// Wraps the given arena to deserialize into it.
1190    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                // See https://en.wikipedia.org/wiki/Cyrillic_script_in_Unicode.
1498                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}