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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright Materialize, Inc. and contributors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE file at the
// root of this repository, or online at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Flat container utilities

use flatcontainer::{Push, Region, ReserveItems};

/// Associate a type with a flat container region.
pub trait MzRegionPreference: 'static {
    /// The owned type of the container.
    type Owned;
    /// A region that can hold `Self`.
    type Region: for<'a> Region<Owned = Self::Owned>
        + Push<Self::Owned>
        + for<'a> Push<<Self::Region as Region>::ReadItem<'a>>
        + for<'a> ReserveItems<<Self::Region as Region>::ReadItem<'a>>;
}

/// Opinion indicating that the contents of a collection should be stored in an
/// [`OwnedRegion`](flatcontainer::OwnedRegion). This is most useful to force types to a region
/// that doesn't copy individual elements to a nested region, like the
/// [`SliceRegion`](flatcontainer::SliceRegion) does.
#[derive(Debug)]
pub struct OwnedRegionOpinion<T>(std::marker::PhantomData<T>);

mod tuple {
    use flatcontainer::impls::tuple::*;
    use paste::paste;

    use crate::flatcontainer::MzRegionPreference;

    macro_rules! tuple_flatcontainer {
        ($($name:ident)+) => (
            paste! {
                impl<$($name: MzRegionPreference),*> MzRegionPreference for ($($name,)*) {
                    type Owned = ($($name::Owned,)*);
                    type Region = [<Tuple $($name)* Region >]<$($name::Region,)*>;
                }
            }
        )
    }

    tuple_flatcontainer!(A);
    tuple_flatcontainer!(A B);
    tuple_flatcontainer!(A B C);
    tuple_flatcontainer!(A B C D);
    tuple_flatcontainer!(A B C D E);
}

mod copy {
    use flatcontainer::MirrorRegion;

    use crate::flatcontainer::MzRegionPreference;

    macro_rules! implement_for {
        ($index_type:ty) => {
            impl MzRegionPreference for $index_type {
                type Owned = Self;
                type Region = MirrorRegion<Self>;
            }
        };
    }

    implement_for!(());
    implement_for!(bool);
    implement_for!(char);

    implement_for!(u8);
    implement_for!(u16);
    implement_for!(u32);
    implement_for!(u64);
    implement_for!(u128);
    implement_for!(usize);

    implement_for!(i8);
    implement_for!(i16);
    implement_for!(i32);
    implement_for!(i64);
    implement_for!(i128);
    implement_for!(isize);

    implement_for!(f32);
    implement_for!(f64);

    implement_for!(std::num::Wrapping<i8>);
    implement_for!(std::num::Wrapping<i16>);
    implement_for!(std::num::Wrapping<i32>);
    implement_for!(std::num::Wrapping<i64>);
    implement_for!(std::num::Wrapping<i128>);
    implement_for!(std::num::Wrapping<isize>);

    implement_for!(std::time::Duration);
}

mod vec {
    use flatcontainer::OwnedRegion;

    use crate::flatcontainer::{MzRegionPreference, OwnedRegionOpinion};

    impl<T: Clone + 'static> MzRegionPreference for OwnedRegionOpinion<Vec<T>> {
        type Owned = Vec<T>;
        type Region = OwnedRegion<T>;
    }
}

impl<T: MzRegionPreference> MzRegionPreference for Option<T> {
    type Owned = <flatcontainer::OptionRegion<T::Region> as Region>::Owned;
    type Region = flatcontainer::OptionRegion<T::Region>;
}