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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! Drop-in replacement for builtin `[T; N]` arrays, using [`Nat`] for the length
//!
//! The API is structured in the following way:
//! - Appropriate types implement [`Array`], which is an unsafe marker trait signifying that the
//! implementor is a contiguous sequence of items.
//! - [`ArrApi`] is a `repr(transparent)` wrapper for [`Array`] implementors that has the actual
//! methods on it.
//! - [`Arr`] and [`CopyArr`] are the actual equivalents to `[T; N]`; they take an item type and
//! a length as generic arguments. They are type aliases for inner array types wrapped in [`ArrApi`].
//! - [`ArrVec`] and [`ArrDeq`] are [`Vec`] and [`std::collections::VecDeque`] equivalents backed
//! by arbitrary array types.
//!
//! # Oversized arrays
//! Because [`Nat`] is not restricted to the values of a [`usize`], it is possible to have array
//! types that have a [`Length`] exceeding [`usize::MAX`]. These arrays can only exist when the
//! item type is zero-sized, as they would otherwise exceed the object size limit of [`isize::MAX`].
//!
//! While these arrays can exist, they are only partially supported and many methods/impls will panic
//! when interacting with them. These methods/impls have a line in their documentation stating that
//! oversized arrays are unsupported.
//!
//! [`Nat`]: crate::Nat
//! [`Length`]: Array::Length
use crateinternals;
/// Trait for arrays whose length is measured as a [`Nat`](crate::Nat).
///
/// Implementors of this trait are contiguous chunks of memory, consisting of `Length` fields of
/// type `Item`, with the same alignment of `Item`.
///
/// Note that [`MaybeUninit<A>`](std::mem::MaybeUninit) implements this trait for array types `A`
/// and acts as an adapter that wraps the item type of `A` in `MaybeUninit`.
///
/// # Safety
/// Currently, this trait is sealed.
///
/// The guarantees made by types implementing [`Array`] with `Item = T` and `Length = N` include the following:
/// - Must have the same layout as an equivalent `[T; N]` builtin array. If `N > usize::MAX` (only
/// relevant for ZSTs), they still act as if there was such an array type.
/// - Arrays have no additional safety requirements over builtin arrays whatsoever. In particular:
/// - They have the same semantics as the equivalent builtin array with respect to arbitrary auto traits,
/// assuming there is no manual implementation from the crate declaring the trait.
/// - They also have the same semantics as the equivalent builtin array with respect to drop glue.
/// They never have a [`Drop`] implementation and only have the drop glue from their item type.
/// When the array is dropped, exactly `N` instances of `T` are dropped
/// ([in order](https://doc.rust-lang.org/reference/destructors.html)), even if `N > usize::MAX`.
/// - Note that together with the point about the layout, this is sufficient to perform arbitrary
/// casts and transmutes between equivalent array types. See the [`arr_api`] module.
/// - `MaybeUninit<[T; N]>` and `[MaybeUninit<T>; N]` are considered equivalent for the purposes of
/// this trait.
/// - Arrays of arrays are equivalent to their flattened versions, e.g. `[[i32; 4]; 3]` is
/// equivalent to `[i32; 12]`, which is equivalent to `[[i32; 3]; 4]`.
pub unsafe
pub use crate*;
/// A newtype adapter for an array implementor that the API relating to arrays.
///
/// The struct has a second generic parameter which is always the item of the array.
/// This gives better lifetime inference for the item type. Some methods, such as
/// [`Self::each_ref`], would not compile without it.
/// Adapter that turns two arrays with the same item type into one long array.
///
/// This is just a `repr(C)` pair.
;
/// Adapter that turns an array of arrays into one long array of items.
;
/// A wrapper for a [`MaybeUninit`](core::mem::MaybeUninit) array that acts as a [`Vec`]
/// (with limited capacity), as well as a drop guard for the initialized items.
///
/// # Drop implementation
/// This type currently has drop glue that does nothing except drop its elements, regardless
/// of whether the item type needs to be dropped.
/// This may be annoying in some `const` code as there is currently no way to make the `Drop`
/// implementation `const` for item types that can be dropped in `const`.
///
/// These workarounds exist:
/// - Using [`drop_items`]/[`assert_empty`](Self::assert_empty) if it's just a local variable
/// that needs to be dropped.
/// - Wrapping this type in [`ManuallyDrop`](core::mem::ManuallyDrop) if the item type is known
/// to have no drop glue. The contents of [`ManuallyDrop`](core::mem::ManuallyDrop) can be
/// accessed in `const` using [`const_util::mem::man_drop_mut`].
/// - Using [`Arr`]/[`CopyArr`] instead if the item type has a default value, or a layout niche
/// with [`Option`].
///
/// # Oversized arrays
/// [Oversized arrays](crate::array#oversized-arrays) are never supported. Attempting to create
/// such an [`ArrVecApi`] results in a panic at runtime. Note that this is not guaranteed and
/// may be relaxed in the future.
;
/// Alias for [`ArrVecApi`] around [`Arr`].
pub type ArrVec<T, N> = ;
/// A wrapper for a [`MaybeUninit`](core::mem::MaybeUninit) array that acts as a
/// [`VecDeque`](std::collections::VecDeque) (with limited capacity), as well as
/// a drop guard for the initialized items.
///
/// Note that unlike [`ArrApi`], all methods on this type may panic if the array length
/// exceeds [`usize::MAX`], without explicitly mentioning this in their docs.
///
/// # Drop implementation
/// See [`ArrVecApi#drop-implementation`]
;
/// Alias for [`ArrDeqApi`] around [`Arr`].
pub type ArrDeq<T, N> = ;
/// Helper macro that drops an [`ArrApi`], [`ArrVecApi`] or [`ArrDeqApi`], including in
/// const contexts, by dropping each of its items.
///
/// Currently, dropping in const contexts is only possible if the item type does
/// not have any drop glue or implementation. This macro is preferrable over
/// [`core::mem::forget`] in that it will give a compile error if the item type
/// cannot be dropped in the current context.
///
/// Once `const Destruct` bounds become stabilized, this macro can be rewritten
/// to drop the items in place.
///
/// # Examples
/// ```
/// use gnat::array::*;
/// const fn double_each<A: Array<Item = i32>>(vec: ArrVecApi<A>) -> ArrVecApi<A> {
/// let mut out = ArrVecApi::new();
/// let mut input = vec.as_slice();
/// while let [next, rest @ ..] = input {
/// out.push(*next * 2);
/// input = rest;
/// }
/// drop_items!(vec);
/// out
/// }
/// ```
};
}
pub use __drop_items as drop_items;
pub
pub