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}