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#[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#[cfg(not(feature = "serde"))]
32pub trait Index: Copy {}
33#[cfg(not(feature = "serde"))]
34impl<T: Copy> Index for T {}
35
36pub trait Region: Default {
44 type Owned;
46
47 type ReadItem<'a>: IntoOwned<'a, Owned = Self::Owned>
49 where
50 Self: 'a;
51
52 type Index: Index;
55
56 fn merge_regions<'a>(regions: impl Iterator<Item = &'a Self> + Clone) -> Self
58 where
59 Self: 'a;
60
61 #[must_use]
64 fn index(&self, index: Self::Index) -> Self::ReadItem<'_>;
65
66 fn reserve_regions<'a, I>(&mut self, regions: I)
68 where
69 Self: 'a,
70 I: Iterator<Item = &'a Self> + Clone;
71
72 fn clear(&mut self);
74
75 fn heap_size<F: FnMut(usize, usize)>(&self, callback: F);
77
78 #[must_use]
80 fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b>
81 where
82 Self: 'a;
83}
84
85pub trait RegionPreference {
95 type Owned;
97 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
106pub trait Push<T>: Region {
108 #[must_use]
111 fn push(&mut self, item: T) -> Self::Index;
112}
113
114pub trait ReserveItems<T>: Region {
118 fn reserve_items<I>(&mut self, items: I)
120 where
121 I: Iterator<Item = T> + Clone;
122}
123
124pub trait IntoOwned<'a> {
131 type Owned;
133 #[must_use]
135 fn into_owned(self) -> Self::Owned;
136 fn clone_onto(self, other: &mut Self::Owned);
138 #[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#[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 indices: Vec<R::Index>,
170 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 #[inline]
196 #[must_use]
197 pub fn default_impl<T: RegionPreference<Region = R>>() -> Self {
198 Self::default()
199 }
200
201 #[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 #[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 #[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 #[inline]
236 #[must_use]
237 pub fn get(&self, offset: usize) -> R::ReadItem<'_> {
238 self.region.index(self.indices[offset])
239 }
240
241 #[inline]
243 #[must_use]
244 pub fn len(&self) -> usize {
245 self.indices.len()
246 }
247
248 #[inline]
250 #[must_use]
251 pub fn is_empty(&self) -> bool {
252 self.indices.is_empty()
253 }
254
255 #[must_use]
257 pub fn capacity(&self) -> usize {
258 self.indices.capacity()
259 }
260
261 #[inline]
263 pub fn reserve(&mut self, additional: usize) {
264 self.indices.reserve(additional);
265 }
266
267 #[inline]
269 pub fn clear(&mut self) {
270 self.indices.clear();
271 self.region.clear();
272 }
273
274 #[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 #[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 #[inline]
294 pub fn iter(&self) -> Iter<'_, R> {
295 self.into_iter()
296 }
297
298 #[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
329pub struct Iter<'a, R: Region> {
332 inner: std::slice::Iter<'a, R::Index>,
334 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#[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 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 fn _test_reborrow<R>(item: R::ReadItem<'_>, owned: &R::Owned)
633 where
634 R: Region,
635 for<'a> R::ReadItem<'a>: Eq,
636 {
637 let _ = R::reborrow(item) == R::reborrow(IntoOwned::borrow_as(owned));
647 }
648}