1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! A region that stores options.

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{Containerized, CopyOnto, Region, ReserveItems};

impl<T: Containerized> Containerized for Option<T> {
    type Region = OptionRegion<T::Region>;
}

/// A region to hold [`Option`]s.
///
/// # Examples
///
/// The region can hold options:
/// ```
/// # use flatcontainer::{Containerized, CopyOnto, OptionRegion, Region};
/// let mut r = <OptionRegion<<u8 as Containerized>::Region>>::default();
///
/// let some_index = Some(123).copy_onto(&mut r);
/// // Type annotations required for `None`:
/// let none_index = Option::<u8>::None.copy_onto(&mut r);
///
/// assert_eq!(Some(123), r.index(some_index));
/// assert_eq!(None, r.index(none_index));
/// ```
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct OptionRegion<R> {
    inner: R,
}

impl<R: Region> Region for OptionRegion<R> {
    type ReadItem<'a> = Option<R::ReadItem<'a>> where Self: 'a;
    type Index = Option<R::Index>;

    fn merge_regions<'a>(regions: impl Iterator<Item = &'a Self> + Clone) -> Self
    where
        Self: 'a,
    {
        Self {
            inner: R::merge_regions(regions.map(|r| &r.inner)),
        }
    }

    #[inline]
    fn index(&self, index: Self::Index) -> Self::ReadItem<'_> {
        index.map(|t| self.inner.index(t))
    }

    #[inline]
    fn reserve_regions<'a, I>(&mut self, regions: I)
    where
        Self: 'a,
        I: Iterator<Item = &'a Self> + Clone,
    {
        self.inner.reserve_regions(regions.map(|r| &r.inner));
    }

    #[inline]
    fn clear(&mut self) {
        self.inner.clear();
    }

    fn heap_size<F: FnMut(usize, usize)>(&self, callback: F) {
        self.inner.heap_size(callback);
    }
}

impl<T, TR> CopyOnto<OptionRegion<TR>> for Option<T>
where
    TR: Region,
    T: CopyOnto<TR>,
{
    #[inline]
    fn copy_onto(self, target: &mut OptionRegion<TR>) -> <OptionRegion<TR> as Region>::Index {
        self.map(|t| t.copy_onto(&mut target.inner))
    }
}

impl<'a, T: 'a, TR> CopyOnto<OptionRegion<TR>> for &'a Option<T>
where
    TR: Region,
    &'a T: CopyOnto<TR>,
{
    #[inline]
    fn copy_onto(self, target: &mut OptionRegion<TR>) -> <OptionRegion<TR> as Region>::Index {
        self.as_ref().map(|t| t.copy_onto(&mut target.inner))
    }
}

impl<'a, T: 'a, TR> ReserveItems<OptionRegion<TR>> for &'a Option<T>
where
    TR: Region,
    &'a T: ReserveItems<TR>,
{
    fn reserve_items<I>(target: &mut OptionRegion<TR>, items: I)
    where
        I: Iterator<Item = Self> + Clone,
    {
        ReserveItems::reserve_items(&mut target.inner, items.flat_map(|r| r.as_ref()));
    }
}