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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//! The different layouts used by [`ArcSlice`] and [`ArcSliceMut`].
//!
//! A layout defines how the data is stored, impacting memory size and the behavior
//! of some operations like `clone`.
//!
//! Almost all layouts are compatible with each other: [`ArcSlice::with_layout`] and
//! [`ArcSliceMut::with_layout`] allows to update the layout used, often at zero cost. See
//! [`FromLayout`].
//!
//! [`ArcSlice`] and [`ArcSliceMut`] have a default layout, which can be overridden using
//! [crate features](crate#features).
//!
//! ## Which layout to choose
//!
//! The default layout, [`ArcLayout`], should support most of the use cases efficiently.
//! The other layouts are designed to support some particular buffers without allocating an inner
//! Arc:
//! - [`BoxedSliceLayout`] and [`VecLayout`] are intended for boxed slice/vector buffers,
//! and should be used only when clones are unlikely;
//! - [`RawLayout`] should be used with [`Arc`] and other raw buffers.
//!
//! Since layout primarily affects [`ArcSlice`]/[`ArcSliceMut`] instantiation, libraries generally
//! don’t need to worry about it: they can either accept the default layout or use a generic one
//! in public APIs, and expose the most appropriate layout in their return types. Libraries should not
//! override the default layout using [crate features], as it would impact every other crates.
//! <br>
//! Binaries should use the default layout, adapting it to the use case using [crate features].
//!
//! In any case, layout choice is primarily a performance concern and should be supported by
//! measurement.
//!
//! ## Layouts summary
//!
//! | Layout | `ArcSlice` size | static/empty slices support | arbitrary buffers support | cloning may allocate | optimized for |
//! |--------------------|--------------------------|-----------------------------|---------------------------|----------------------|--------------------|
//! | `ArcLayout` | `3 * size_of::<usize>()` | yes (optional) | yes (optional) | no | regular `ArcSlice` |
//! | `BoxedSliceLayout` | `3 * size_of::<usize>()` | yes | yes | yes | `Box<[T]>` |
//! | `VecLayout` | `4 * size_of::<usize>()` | yes | yes | yes | `Vec<T>` |
//! | `RawLayout` | `4 * size_of::<usize>()` | yes | yes | no | `RawBuffer` |
//!
//! [crate feature]: crate#features
//! [`Arc`]: alloc::sync::Arc
use crate::;
/// A layout, which defines how [`ArcSlice`] data is stored.
/// A layout, which defines how [`ArcSliceMut`] data is stored.
/// A layout that supports arbitrary buffers, such as [`Vec`](alloc::vec::Vec),
/// shared memory regions, ffi buffers, etc.
///
/// It enables [`ArcSlice::from_buffer`]/[`ArcSliceMut::from_buffer`] and derived methods.
/// A layout that supports static slices without inner Arc allocation.
///
/// It enables [`ArcSlice::new`] and [`ArcSlice::from_static`]. Additionally, empty subslices are
/// stored as static slices to avoid Arc clone/drop overhead.
/// A layout that supports [`clone`](ArcSlice::clone) without allocating.
/// A layout that supports [`truncate`](ArcSlice::truncate) without allocating.
/// The default and most optimized layout.
///
/// It aims to be more performant than other layouts for supported operations,
/// though other layouts may support a broader range of use cases.
/// It takes two generic boolean parameters, whose defaults can be overridden via compilation
/// features:
/// - `ANY_BUFFER`, default to false, if it supports arbitrary buffer;
/// - `STATIC`, default to false, if it supports static slices without allocations; it
/// enables [`Default`] implementation for [`ArcSlice`], as well as const constructors.
///
/// Other layouts support arbitrary buffers and static slices out of the box, but this flexibility
/// comes at a cost. `ArcLayout` focuses instead on providing the most optimized implementation
/// adapted to each use case.
/// ```rust
/// # use core::mem::size_of;
/// # use arc_slice::{layout::ArcLayout, ArcBytes, ArcBytesMut};
/// assert_eq!(size_of::<ArcBytes<ArcLayout>>(), 3 * size_of::<usize>());
/// assert_eq!(size_of::<ArcBytesMut<ArcLayout>>(), 4 * size_of::<usize>());
/// ```
},
const STATIC: bool = ,
>;
/// Enables storing a boxed slice into an [`ArcSlice`] without requiring the allocation of an inner
/// Arc, as long as there is a single instance.
///
/// As soon as the [`ArcSlice`] is cloned (or subsliced), then an inner Arc is allocated. As a
/// consequence, when [`oom-handling` feature](crate#features) is not enabled,
/// `ArcSlice<S, BoxedSliceLayout>` doesn't implement [`Clone`].
/// <br>
/// When initializing an [`ArcSlice`] with a vector, there will be no Arc allocation if the
/// vector has no spare capacity.
/// ```rust
/// # use core::mem::size_of;
/// # use arc_slice::{layout::BoxedSliceLayout, ArcBytes};
/// assert_eq!(
/// size_of::<ArcBytes<BoxedSliceLayout>>(),
/// 3 * size_of::<usize>()
/// );
/// ```
;
/// Enables storing a vector into an [`ArcSlice`] without requiring the allocation of an inner Arc,
/// as long as there is a single instance.
///
/// As soon as the [`ArcSlice`] is cloned (or subsliced), then an inner Arc is allocated. As a
/// consequence, when [`oom-handling` feature](crate#features) is not enabled,
/// `ArcSlice<S, VecLayout>` doesn't implement [`Clone`].
/// ```rust
/// # use core::mem::size_of;
/// # use arc_slice::{layout::VecLayout, ArcBytes, ArcBytesMut};
/// assert_eq!(size_of::<ArcBytes<VecLayout>>(), 4 * size_of::<usize>());
/// assert_eq!(size_of::<ArcBytesMut<VecLayout>>(), 4 * size_of::<usize>());
/// ```
;
/// Enables storing a [`RawBuffer`], without requiring the allocation of an inner Arc.
/// ```rust
/// # use core::mem::size_of;
/// # use arc_slice::{layout::RawLayout, ArcBytes};
/// assert_eq!(size_of::<ArcBytes<RawLayout>>(), 4 * size_of::<usize>());
/// ```
///
/// [`RawBuffer`]: crate::buffer::RawBuffer
;
/// A layout that can be converted from another one.
///
/// As long as a layout implement [`AnyBufferLayout`], every other layout can be converted to it.
/// This conversion is often very cheap, when the default `ArcSlice` buffer is used, but it may
/// require to allocate an Arc when to arbitrary buffers specially supported by the input layout.
/// For example, converting `ArcSlice<S, BoxedSliceLayout>` to `ArcSlice<S, ArcLayout<true>>` might
/// allocate an `Arc` if a boxed slice was store inlined.
///
/// `ArcLayout<false>` doesn't implement [`AnyBufferLayout`], so it cannot straightforwardly be
/// converted from other layouts, as it may not support the underlying buffer. However, the actual
/// underlying buffer may be compatible, for example, an `ArcSlice<S, VecLayout>` backed by an
/// Arc buffer can in fact be converted to an`ArcSlice<S, ArcLayout<false>>`. Fallible conversions
/// like [`ArcSlice::try_with_layout`]/[`ArcSliceMut::try_freeze`]/etc. can be used to handle this
/// edge case.
cfg_if!
cfg_if!