fixed_typed_arena/
options.rs

1/*
2 * Copyright (C) 2022 taylor.fish <contact@taylor.fish>
3 *
4 * This file is part of fixed-typed-arena.
5 *
6 * fixed-typed-arena is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * fixed-typed-arena is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with fixed-typed-arena. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20//! Arena options.
21
22use alloc::sync::Arc;
23use core::convert::Infallible;
24use core::marker::PhantomData;
25use core::mem::MaybeUninit;
26
27/// Re-exported for backward compatibility.
28#[doc(hidden)]
29pub use integral_constant::{Bool, Usize};
30
31mod detail {
32    pub trait ChunkSizePriv<T> {
33        type Array;
34    }
35
36    pub trait SupportsPositionsPriv {
37        type Rc: Clone + Send + Sync;
38        fn init_rc(_rc: &mut Option<Self::Rc>) {}
39    }
40
41    pub trait MutablePriv {}
42}
43
44pub(crate) use detail::*;
45
46/// Trait bound on [`ArenaOptions::ChunkSize`].
47pub trait ChunkSize<T>: ChunkSizePriv<T> {}
48
49impl<T, const N: usize> ChunkSize<T> for Usize<N> {}
50impl<T, const N: usize> ChunkSizePriv<T> for Usize<N> {
51    type Array = [MaybeUninit<T>; N];
52}
53
54/// Trait bound on [`ArenaOptions::SupportsPositions`].
55pub trait SupportsPositions: SupportsPositionsPriv {}
56
57impl SupportsPositions for Bool<false> {}
58impl SupportsPositions for Bool<true> {}
59
60impl SupportsPositionsPriv for Bool<false> {
61    type Rc = Infallible;
62}
63
64impl SupportsPositionsPriv for Bool<true> {
65    type Rc = Arc<()>;
66
67    fn init_rc(rc: &mut Option<Self::Rc>) {
68        rc.get_or_insert_with(Arc::default);
69    }
70}
71
72/// Trait bound on [`ArenaOptions::Mutable`].
73pub trait Mutable: MutablePriv {}
74
75impl Mutable for Bool<false> {}
76impl Mutable for Bool<true> {}
77impl<const B: bool> MutablePriv for Bool<B> {}
78
79mod sealed {
80    pub trait Sealed {}
81}
82
83/// Arena options trait.
84///
85/// This is a sealed trait; use the [`Options`] type, which implements this
86/// trait.
87pub trait ArenaOptions<T>: sealed::Sealed {
88    /// The number of elements of type `T` that each chunk can hold.
89    ///
90    /// *Default:* 16
91    type ChunkSize: ChunkSize<T>;
92
93    /// If true, enables the use of [`Position`]s, allowing methods like
94    /// [`IterMut::as_position`] and [`Arena::iter_mut_at`] to be called, at
95    /// the cost of using slightly more memory.
96    ///
97    /// *Default:* false
98    ///
99    /// [`Position`]: crate::iter::Position
100    /// [`IterMut::as_position`]: crate::iter::IterMut::as_position
101    /// [`Arena::iter_mut_at`]: crate::arena::Arena::iter_mut_at
102    type SupportsPositions: SupportsPositions;
103
104    /// If true, the arena is able to return mutable references.
105    ///
106    /// *Default:* true
107    type Mutable: Mutable;
108}
109
110/// Arena options.
111///
112/// This type implements [`ArenaOptions`]. Const parameters correspond to
113/// associated types in [`ArenaOptions`] as follows; see those associated types
114/// for documentation:
115///
116/// Const parameter      | Associated type
117/// -------------------- | -----------------------------------
118/// `CHUNK_SIZE`         | [`ArenaOptions::ChunkSize`]
119/// `SUPPORTS_POSITIONS` | [`ArenaOptions::SupportsPositions`]
120/// `MUTABLE`            | [`ArenaOptions::Mutable`]
121#[rustfmt::skip]
122pub type Options<
123    const CHUNK_SIZE: usize = 16,
124    const SUPPORTS_POSITIONS: bool = false,
125    const MUTABLE: bool = true,
126> = TypedOptions<
127    Usize<CHUNK_SIZE>,
128    Bool<SUPPORTS_POSITIONS>,
129    Bool<MUTABLE>,
130>;
131
132/// Like [`Options`], but uses types instead of const parameters.
133///
134/// [`Options`] is actually a type alias of this type.
135#[allow(clippy::type_complexity)]
136#[rustfmt::skip]
137pub struct TypedOptions<
138    ChunkSize = Usize<16>,
139    SupportsPositions = Bool<false>,
140    Mutable = Bool<true>,
141>(PhantomData<fn() -> (
142    ChunkSize,
143    SupportsPositions,
144    Mutable,
145)>);
146
147#[rustfmt::skip]
148impl<
149    ChunkSize,
150    SupportsPositions,
151    Mutable,
152> sealed::Sealed for TypedOptions<
153    ChunkSize,
154    SupportsPositions,
155    Mutable,
156> {}
157
158#[rustfmt::skip]
159impl<
160    T,
161    ChunkSize: self::ChunkSize<T>,
162    SupportsPositions: self::SupportsPositions,
163    Mutable: self::Mutable,
164> ArenaOptions<T> for TypedOptions<
165    ChunkSize,
166    SupportsPositions,
167    Mutable,
168> {
169    type ChunkSize = ChunkSize;
170    type SupportsPositions = SupportsPositions;
171    type Mutable = Mutable;
172}