flatcontainer/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3
4use std::borrow::Borrow;
5use std::fmt::{Debug, Formatter};
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10pub mod impls;
11
12pub use impls::columns::ColumnsRegion;
13pub use impls::mirror::MirrorRegion;
14pub use impls::option::OptionRegion;
15pub use impls::result::ResultRegion;
16pub use impls::slice::SliceRegion;
17pub use impls::slice_copy::OwnedRegion;
18pub use impls::string::StringRegion;
19
20/// An index into a region. Automatically implemented for relevant types.
21///
22/// We require an index to be [`Copy`] and to support serde.
23#[cfg(feature = "serde")]
24pub trait Index: Copy + Serialize + for<'a> Deserialize<'a> {}
25#[cfg(feature = "serde")]
26impl<T: Copy + Serialize + for<'a> Deserialize<'a>> Index for T {}
27
28/// An index into a region. Automatically implemented for relevant types.
29///
30/// We require an index to be [`Copy`].
31#[cfg(not(feature = "serde"))]
32pub trait Index: Copy {}
33#[cfg(not(feature = "serde"))]
34impl<T: Copy> Index for T {}
35
36/// A region to absorb presented data and present it as a type with a lifetime.
37///
38/// This type absorbs data and provides an index to look up an equivalent representation
39/// of this data at a later time. It is up to an implementation to select the appropriate
40/// presentation of the data, and what data it can absorb.
41///
42/// Implement the [`Push`] trait for all types that can be copied into a region.
43pub trait Region: Default {
44    /// An owned type that can be constructed from a read item.
45    type Owned;
46
47    /// The type of the data that one gets out of the container.
48    type ReadItem<'a>: IntoOwned<'a, Owned = Self::Owned>
49    where
50        Self: 'a;
51
52    /// The type to index into the container. Should be treated
53    /// as an opaque type, even if known.
54    type Index: Index;
55
56    /// Construct a region that can absorb the contents of `regions` in the future.
57    fn merge_regions<'a>(regions: impl Iterator<Item = &'a Self> + Clone) -> Self
58    where
59        Self: 'a;
60
61    /// Index into the container. The index must be obtained by
62    /// pushing data into the container.
63    #[must_use]
64    fn index(&self, index: Self::Index) -> Self::ReadItem<'_>;
65
66    /// Ensure that the region can absorb the items of `regions` without reallocation
67    fn reserve_regions<'a, I>(&mut self, regions: I)
68    where
69        Self: 'a,
70        I: Iterator<Item = &'a Self> + Clone;
71
72    /// Remove all elements from this region, but retain allocations if possible.
73    fn clear(&mut self);
74
75    /// Heap size, size - capacity
76    fn heap_size<F: FnMut(usize, usize)>(&self, callback: F);
77
78    /// Converts a read item into one with a narrower lifetime.
79    #[must_use]
80    fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b>
81    where
82        Self: 'a;
83}
84
85/// A trait to let types express a default container type and an owned type, which can
86/// be used to define regions in simpler terms.
87///
88/// # Example
89///
90/// ```
91/// # use flatcontainer::{FlatStack, RegionPreference};
92/// let _ = FlatStack::<<((Vec<String>, &[usize]), Option<String>, Result<u8, u16>) as RegionPreference>::Region>::default();
93/// ```
94pub trait RegionPreference {
95    /// The owned type of the region.
96    type Owned;
97    /// The recommended container type.
98    type Region: Region<Owned = Self::Owned>;
99}
100
101impl<T: RegionPreference + ?Sized> RegionPreference for &T {
102    type Owned = T::Owned;
103    type Region = T::Region;
104}
105
106/// Push an item `T` into a region.
107pub trait Push<T>: Region {
108    /// Push `item` into self, returning an index that allows to look up the
109    /// corresponding read item.
110    #[must_use]
111    fn push(&mut self, item: T) -> Self::Index;
112}
113
114/// Reserve space in the receiving region.
115///
116/// Closely related to [`Push`], but separate because target type is likely different.
117pub trait ReserveItems<T>: Region {
118    /// Ensure that the region can absorb `items` without reallocation.
119    fn reserve_items<I>(&mut self, items: I)
120    where
121        I: Iterator<Item = T> + Clone;
122}
123
124/// A reference type corresponding to an owned type, supporting conversion in each direction.
125///
126/// This trait can be implemented by a GAT, and enables owned types to be borrowed as a GAT.
127/// This trait is analogous to `ToOwned`, but not as prescriptive. Specifically, it avoids the
128/// requirement that the other trait implement `Borrow`, for which a borrow must result in a
129/// `&'self Borrowed`, which cannot move the lifetime into a GAT borrowed type.
130pub trait IntoOwned<'a> {
131    /// Owned type into which this type can be converted.
132    type Owned;
133    /// Conversion from an instance of this type to the owned type.
134    #[must_use]
135    fn into_owned(self) -> Self::Owned;
136    /// Clones `self` onto an existing instance of the owned type.
137    fn clone_onto(self, other: &mut Self::Owned);
138    /// Borrows an owned instance as oneself.
139    #[must_use]
140    fn borrow_as(owned: &'a Self::Owned) -> Self;
141}
142
143impl<'a, T: ToOwned + ?Sized> IntoOwned<'a> for &'a T {
144    type Owned = T::Owned;
145    #[inline]
146    fn into_owned(self) -> Self::Owned {
147        self.to_owned()
148    }
149    #[inline]
150    fn clone_onto(self, other: &mut Self::Owned) {
151        <T as ToOwned>::clone_into(self, other)
152    }
153    #[inline]
154    fn borrow_as(owned: &'a Self::Owned) -> Self {
155        owned.borrow()
156    }
157}
158
159/// A container for indices into a region.
160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
161#[cfg_attr(
162    feature = "serde",
163    serde(
164        bound = "R: Serialize + for<'a> Deserialize<'a>, R::Index: Serialize + for<'a> Deserialize<'a>"
165    )
166)]
167pub struct FlatStack<R: Region> {
168    /// The indices, which we use to lookup items in the region.
169    indices: Vec<R::Index>,
170    /// A region to index into.
171    region: R,
172}
173
174impl<R: Region> Default for FlatStack<R> {
175    #[inline]
176    fn default() -> Self {
177        Self {
178            indices: Vec::default(),
179            region: R::default(),
180        }
181    }
182}
183
184impl<R: Region> Debug for FlatStack<R>
185where
186    for<'a> R::ReadItem<'a>: Debug,
187{
188    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
189        f.debug_list().entries(self.iter()).finish()
190    }
191}
192
193impl<R: Region> FlatStack<R> {
194    /// Default implementation based on the preference of type `T`.
195    #[inline]
196    #[must_use]
197    pub fn default_impl<T: RegionPreference<Region = R>>() -> Self {
198        Self::default()
199    }
200
201    /// Returns a flat stack that can absorb `capacity` indices without reallocation.
202    ///
203    /// Prefer [`Self::merge_capacity`] over this function to also pre-size the regions.
204    #[must_use]
205    pub fn with_capacity(capacity: usize) -> Self {
206        Self {
207            indices: Vec::with_capacity(capacity),
208            region: R::default(),
209        }
210    }
211
212    /// Returns a flat stack that can absorb the contents of `iter` without reallocation.
213    #[must_use]
214    pub fn merge_capacity<'a, I: Iterator<Item = &'a Self> + Clone + 'a>(stacks: I) -> Self
215    where
216        R: 'a,
217    {
218        Self {
219            indices: Vec::with_capacity(stacks.clone().map(|s| s.indices.len()).sum()),
220            region: R::merge_regions(stacks.map(|r| &r.region)),
221        }
222    }
223
224    /// Appends the element to the back of the stack.
225    #[inline]
226    pub fn copy<T>(&mut self, item: T)
227    where
228        R: Push<T>,
229    {
230        let index = self.region.push(item);
231        self.indices.push(index);
232    }
233
234    /// Returns the element at the `offset` position.
235    #[inline]
236    #[must_use]
237    pub fn get(&self, offset: usize) -> R::ReadItem<'_> {
238        self.region.index(self.indices[offset])
239    }
240
241    /// Returns the number of indices in the stack.
242    #[inline]
243    #[must_use]
244    pub fn len(&self) -> usize {
245        self.indices.len()
246    }
247
248    /// Returns `true` if the stack contains no elements.
249    #[inline]
250    #[must_use]
251    pub fn is_empty(&self) -> bool {
252        self.indices.is_empty()
253    }
254
255    /// Returns the total number of indices the stack can hold without reallocation.
256    #[must_use]
257    pub fn capacity(&self) -> usize {
258        self.indices.capacity()
259    }
260
261    /// Reserves space to hold `additional` indices.
262    #[inline]
263    pub fn reserve(&mut self, additional: usize) {
264        self.indices.reserve(additional);
265    }
266
267    /// Remove all elements while possibly retaining allocations.
268    #[inline]
269    pub fn clear(&mut self) {
270        self.indices.clear();
271        self.region.clear();
272    }
273
274    /// Reserve space for the items returned by the iterator.
275    #[inline]
276    pub fn reserve_items<T>(&mut self, items: impl Iterator<Item = T> + Clone)
277    where
278        R: ReserveItems<T>,
279    {
280        ReserveItems::reserve_items(&mut self.region, items);
281    }
282
283    /// Reserve space for the regions returned by the iterator.
284    #[inline]
285    pub fn reserve_regions<'a>(&mut self, regions: impl Iterator<Item = &'a R> + Clone)
286    where
287        R: 'a,
288    {
289        self.region.reserve_regions(regions);
290    }
291
292    /// Iterate the items in this stack.
293    #[inline]
294    pub fn iter(&self) -> Iter<'_, R> {
295        self.into_iter()
296    }
297
298    /// Heap size, size - capacity
299    #[inline]
300    pub fn heap_size<F: FnMut(usize, usize)>(&self, mut callback: F) {
301        use crate::impls::offsets::OffsetContainer;
302        self.region.heap_size(&mut callback);
303        OffsetContainer::heap_size(&self.indices, callback);
304    }
305}
306
307impl<T, R: Region + Push<T>> Extend<T> for FlatStack<R> {
308    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
309        let iter = iter.into_iter();
310        self.reserve(iter.size_hint().0);
311        for item in iter {
312            self.indices.push(self.region.push(item));
313        }
314    }
315}
316
317impl<'a, R: Region> IntoIterator for &'a FlatStack<R> {
318    type Item = R::ReadItem<'a>;
319    type IntoIter = Iter<'a, R>;
320
321    fn into_iter(self) -> Self::IntoIter {
322        Iter {
323            inner: self.indices.iter(),
324            region: &self.region,
325        }
326    }
327}
328
329/// An iterator over [`FlatStack`]. The iterator yields [`Region::ReadItem`] elements, which
330/// it obtains by looking up indices.
331pub struct Iter<'a, R: Region> {
332    /// Iterator over indices.
333    inner: std::slice::Iter<'a, R::Index>,
334    /// Region to map indices to read items.
335    region: &'a R,
336}
337
338impl<'a, R: Region> Iterator for Iter<'a, R> {
339    type Item = R::ReadItem<'a>;
340
341    fn next(&mut self) -> Option<Self::Item> {
342        self.inner.next().map(|idx| self.region.index(*idx))
343    }
344
345    fn size_hint(&self) -> (usize, Option<usize>) {
346        self.inner.size_hint()
347    }
348}
349
350impl<R: Region> ExactSizeIterator for Iter<'_, R> {}
351
352impl<R: Region> Clone for Iter<'_, R> {
353    fn clone(&self) -> Self {
354        Self {
355            inner: self.inner.clone(),
356            region: self.region,
357        }
358    }
359}
360
361impl<R: Region + Push<T>, T> FromIterator<T> for FlatStack<R> {
362    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
363        let iter = iter.into_iter();
364        let mut c = Self::with_capacity(iter.size_hint().0);
365        c.extend(iter);
366        c
367    }
368}
369
370impl<R: Region + Clone> Clone for FlatStack<R> {
371    fn clone(&self) -> Self {
372        Self {
373            region: self.region.clone(),
374            indices: self.indices.clone(),
375        }
376    }
377
378    fn clone_from(&mut self, source: &Self) {
379        self.region.clone_from(&source.region);
380        self.indices.clone_from(&source.indices);
381    }
382}
383
384/// A type to wrap and copy iterators onto regions.
385///
386/// This only exists to avoid blanket implementations that might conflict with more specific
387/// implementations offered by some regions.
388#[repr(transparent)]
389#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
390pub struct CopyIter<I>(pub I);
391
392#[cfg(test)]
393mod tests {
394    use crate::impls::deduplicate::{CollapseSequence, ConsecutiveOffsetPairs};
395    use crate::impls::tuple::TupleARegion;
396
397    use super::*;
398
399    fn copy<R: Region + Push<T>, T>(r: &mut R, item: T) -> R::Index {
400        r.push(item)
401    }
402
403    #[test]
404    fn test_readme() {
405        let r: Result<_, u16> = Ok("abc");
406        let mut c = FlatStack::default_impl::<Result<&str, u16>>();
407        c.copy(r);
408        assert_eq!(r, c.get(0));
409    }
410
411    #[test]
412    fn test_slice_string_onto() {
413        let mut c = <StringRegion>::default();
414        let index = c.push("abc".to_string());
415        assert_eq!("abc", c.index(index));
416        let index = c.push("def");
417        assert_eq!("def", c.index(index));
418    }
419
420    #[test]
421    fn test_container_string() {
422        let mut c = FlatStack::default_impl::<String>();
423        c.copy(&"abc".to_string());
424        assert_eq!("abc", c.get(0));
425        c.copy("def");
426        assert_eq!("def", c.get(1));
427    }
428
429    #[test]
430    fn test_vec() {
431        let mut c = <SliceRegion<MirrorRegion<_>>>::default();
432        let slice = &[1u8, 2, 3];
433        let idx = c.push(slice);
434        assert!(slice.iter().copied().eq(c.index(idx)));
435    }
436
437    #[test]
438    fn test_vec_onto() {
439        let mut c = <SliceRegion<MirrorRegion<u8>>>::default();
440        let slice = &[1u8, 2, 3][..];
441        let idx = c.push(slice);
442        assert!(slice.iter().copied().eq(c.index(idx)));
443    }
444
445    #[test]
446    fn test_result() {
447        let r: Result<_, u16> = Ok("abc");
448        let mut c = <ResultRegion<StringRegion, MirrorRegion<_>>>::default();
449        let idx = copy(&mut c, r);
450        assert_eq!(r, c.index(idx));
451    }
452
453    #[test]
454    fn all_types() {
455        fn test_copy<T, R: Region + Clone>(t: T)
456        where
457            for<'a> R: Push<T> + Push<<R as Region>::ReadItem<'a>>,
458            // Make sure that types are debug, even if we don't use this in the test.
459            for<'a> R::ReadItem<'a>: Debug,
460        {
461            let mut c = FlatStack::default();
462            c.copy(t);
463
464            let mut cc = c.clone();
465            cc.copy(c.get(0));
466
467            c.clear();
468
469            let mut r = R::default();
470            let _ = r.push(cc.get(0));
471
472            c.reserve_regions(std::iter::once(&r));
473
474            let mut c = FlatStack::merge_capacity(std::iter::once(&c));
475            c.copy(cc.get(0));
476        }
477
478        test_copy::<_, StringRegion>(&"a".to_string());
479        test_copy::<_, StringRegion>("a".to_string());
480        test_copy::<_, StringRegion>("a");
481
482        test_copy::<_, MirrorRegion<()>>(());
483        test_copy::<_, MirrorRegion<()>>(&());
484        test_copy::<_, MirrorRegion<bool>>(true);
485        test_copy::<_, MirrorRegion<bool>>(&true);
486        test_copy::<_, MirrorRegion<char>>(' ');
487        test_copy::<_, MirrorRegion<char>>(&' ');
488        test_copy::<_, MirrorRegion<u8>>(0u8);
489        test_copy::<_, MirrorRegion<u8>>(&0u8);
490        test_copy::<_, MirrorRegion<u16>>(0u16);
491        test_copy::<_, MirrorRegion<u16>>(&0u16);
492        test_copy::<_, MirrorRegion<u32>>(0u32);
493        test_copy::<_, MirrorRegion<u32>>(&0u32);
494        test_copy::<_, MirrorRegion<u64>>(0u64);
495        test_copy::<_, MirrorRegion<u64>>(&0u64);
496        test_copy::<_, MirrorRegion<u128>>(0u128);
497        test_copy::<_, MirrorRegion<u128>>(&0u128);
498        test_copy::<_, MirrorRegion<usize>>(0usize);
499        test_copy::<_, MirrorRegion<usize>>(&0usize);
500        test_copy::<_, MirrorRegion<i8>>(0i8);
501        test_copy::<_, MirrorRegion<i8>>(&0i8);
502        test_copy::<_, MirrorRegion<i16>>(0i16);
503        test_copy::<_, MirrorRegion<i16>>(&0i16);
504        test_copy::<_, MirrorRegion<i32>>(0i32);
505        test_copy::<_, MirrorRegion<i32>>(&0i32);
506        test_copy::<_, MirrorRegion<i64>>(0i64);
507        test_copy::<_, MirrorRegion<i64>>(&0i64);
508        test_copy::<_, MirrorRegion<i128>>(0i128);
509        test_copy::<_, MirrorRegion<i128>>(&0i128);
510        test_copy::<_, MirrorRegion<isize>>(0isize);
511        test_copy::<_, MirrorRegion<isize>>(&0isize);
512        test_copy::<_, MirrorRegion<f32>>(0f32);
513        test_copy::<_, MirrorRegion<f32>>(&0f32);
514        test_copy::<_, MirrorRegion<f64>>(0f64);
515        test_copy::<_, MirrorRegion<f64>>(&0f64);
516        test_copy::<_, MirrorRegion<std::num::Wrapping<i8>>>(std::num::Wrapping(0i8));
517        test_copy::<_, MirrorRegion<std::num::Wrapping<i8>>>(&std::num::Wrapping(0i8));
518        test_copy::<_, MirrorRegion<std::num::Wrapping<i16>>>(std::num::Wrapping(0i16));
519        test_copy::<_, MirrorRegion<std::num::Wrapping<i16>>>(&std::num::Wrapping(0i16));
520        test_copy::<_, MirrorRegion<std::num::Wrapping<i32>>>(std::num::Wrapping(0i32));
521        test_copy::<_, MirrorRegion<std::num::Wrapping<i32>>>(&std::num::Wrapping(0i32));
522        test_copy::<_, MirrorRegion<std::num::Wrapping<i64>>>(std::num::Wrapping(0i64));
523        test_copy::<_, MirrorRegion<std::num::Wrapping<i64>>>(&std::num::Wrapping(0i64));
524        test_copy::<_, MirrorRegion<std::num::Wrapping<i128>>>(std::num::Wrapping(0i128));
525        test_copy::<_, MirrorRegion<std::num::Wrapping<i128>>>(&std::num::Wrapping(0i128));
526        test_copy::<_, MirrorRegion<std::num::Wrapping<isize>>>(std::num::Wrapping(0isize));
527        test_copy::<_, MirrorRegion<std::num::Wrapping<isize>>>(&std::num::Wrapping(0isize));
528
529        test_copy::<_, ResultRegion<MirrorRegion<u8>, MirrorRegion<u8>>>(Result::<u8, u8>::Ok(0));
530        test_copy::<_, ResultRegion<MirrorRegion<u8>, MirrorRegion<u8>>>(&Result::<u8, u8>::Ok(0));
531        test_copy::<_, ResultRegion<MirrorRegion<u8>, MirrorRegion<u8>>>(Result::<u8, u8>::Err(0));
532        test_copy::<_, ResultRegion<MirrorRegion<u8>, MirrorRegion<u8>>>(&Result::<u8, u8>::Err(0));
533
534        test_copy::<_, SliceRegion<MirrorRegion<u8>>>([0u8].as_slice());
535        test_copy::<_, SliceRegion<MirrorRegion<u8>>>(vec![0u8]);
536        test_copy::<_, SliceRegion<MirrorRegion<u8>>>(&vec![0u8]);
537
538        test_copy::<_, SliceRegion<StringRegion>>(["a"].as_slice());
539        test_copy::<_, SliceRegion<StringRegion>>(vec!["a"]);
540        test_copy::<_, SliceRegion<StringRegion>>(&vec!["a"]);
541
542        test_copy::<_, SliceRegion<TupleARegion<StringRegion>>>([("a",)].as_slice());
543        test_copy::<_, SliceRegion<TupleARegion<StringRegion>>>(vec![("a",)]);
544        test_copy::<_, SliceRegion<TupleARegion<StringRegion>>>(&vec![("a",)]);
545
546        test_copy::<_, OwnedRegion<_>>([0u8].as_slice());
547        test_copy::<_, OwnedRegion<_>>(&[0u8].as_slice());
548
549        test_copy::<_, <(u8, u8) as RegionPreference>::Region>((1, 2));
550        test_copy::<_, <(u8, u8) as RegionPreference>::Region>(&(1, 2));
551
552        test_copy::<_, ConsecutiveOffsetPairs<OwnedRegion<_>>>([1, 2, 3].as_slice());
553
554        test_copy::<_, CollapseSequence<OwnedRegion<_>>>([1, 2, 3].as_slice());
555        test_copy::<_, CollapseSequence<OwnedRegion<_>>>(&[1, 2, 3]);
556
557        test_copy::<_, OptionRegion<StringRegion>>(Some("abc"));
558        test_copy::<_, OptionRegion<StringRegion>>(&Some("abc"));
559        test_copy::<_, OptionRegion<StringRegion>>(Option::<&'static str>::None);
560        test_copy::<_, OptionRegion<StringRegion>>(&Option::<&'static str>::None);
561
562        test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
563            Result::<&'static str, u8>::Ok("abc"),
564        );
565        test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
566            &Result::<&'static str, u8>::Ok("abc"),
567        );
568        test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
569            Result::<&'static str, u8>::Err(1),
570        );
571        test_copy::<_, ResultRegion<StringRegion, MirrorRegion<u8>>>(
572            Result::<&'static str, u8>::Err(2),
573        );
574    }
575
576    #[test]
577    fn slice_region_read_item() {
578        fn is_clone<T: Clone>(_: &T) {}
579
580        let mut c = FlatStack::<SliceRegion<MirrorRegion<u8>>>::default();
581        c.copy(vec![1, 2, 3]);
582
583        let mut r = SliceRegion::<MirrorRegion<u8>>::default();
584        let idx = r.push([1, 2, 3]);
585        let read_item = r.index(idx);
586        is_clone(&read_item);
587        let _read_item3 = read_item;
588        assert_eq!(vec![1, 2, 3], read_item.into_iter().collect::<Vec<_>>());
589    }
590
591    #[test]
592    fn nested_slice_copy() {
593        let mut c = FlatStack::default_impl::<[[[[[u8; 1]; 1]; 1]; 1]; 1]>();
594
595        c.copy([[[[[1]]]]]);
596        c.copy(&[[[[[1]]]]]);
597        c.copy(&[[[[[&1]]]]]);
598        c.copy([[[[[&1]]]]]);
599        c.copy([[&[[[&1]]]]]);
600        c.copy([[[[[1]]; 1]; 1]; 1]);
601        c.copy(&[[[[[1; 1]; 1]; 1]; 1]; 1]);
602        c.copy(&[[[[[&1; 1]; 1]; 1]; 1]; 1]);
603        c.copy([[[[[&1; 1]; 1]; 1]; 1]; 1]);
604        c.copy([[&[[[&1; 1]; 1]; 1]; 1]; 1]);
605        c.copy([[vec![[[1; 1]; 1]; 1]; 1]; 1]);
606        c.copy(&[[vec![[[1; 1]; 1]; 1]; 1]; 1]);
607        c.copy(&[[vec![[[&1; 1]; 1]; 1]; 1]; 1]);
608        c.copy([[[vec![[&1; 1]; 1]; 1]; 1]; 1]);
609        c.copy([[&vec![[[&1; 1]; 1]; 1]; 1]; 1]);
610    }
611
612    #[test]
613    fn test_owned() {
614        fn owned_roundtrip<R, O>(region: &mut R, index: R::Index)
615        where
616            for<'a> R: Region + Push<<<R as Region>::ReadItem<'a> as IntoOwned<'a>>::Owned>,
617            for<'a> R::ReadItem<'a>: IntoOwned<'a, Owned = O> + Eq + Debug,
618        {
619            let item = region.index(index);
620            let owned = item.into_owned();
621            let index2 = region.push(owned);
622            let item = region.index(index);
623            assert_eq!(item, region.index(index2));
624        }
625
626        let mut c = <StringRegion>::default();
627        let index = c.push("abc".to_string());
628        owned_roundtrip::<StringRegion, String>(&mut c, index);
629    }
630
631    /// Test that items and owned variants can be reborrowed to shorten their lifetimes.
632    fn _test_reborrow<R>(item: R::ReadItem<'_>, owned: &R::Owned)
633    where
634        R: Region,
635        for<'a> R::ReadItem<'a>: Eq,
636    {
637        // The following line requires `reborrow` because otherwise owned must outlive '_.
638        // fn _test_reborrow<R>(item: R::ReadItem<'_>, owned: &R::Owned) where R: Region, for<'a> R::ReadItem<'a>: Eq {
639        //                      ----                          - let's call the lifetime of this reference `'1`
640        //                      |
641        //                      has type `<R as Region>::ReadItem<'2>`
642        //     // The following line requires `reborrow` because otherwise owned must outlive '_.
643        //     let _ = item == IntoOwned::borrow_as(owned);
644        //                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
645        // let _ = item == IntoOwned::borrow_as(owned);
646        let _ = R::reborrow(item) == R::reborrow(IntoOwned::borrow_as(owned));
647    }
648}