generic_arrayvec/lib.rs
1#![doc(html_root_url = "https://docs.rs/generic-arrayvec/0.4.0")]
2
3//! This crate provides interop between the [arrayvec] and [generic_array] crates, allowing you to
4//! use generic_array's [`GenericArray`] as the backing storage for the data structures in
5//! arrayvec. This lets you have vector and string types that store their contents inline, with a
6//! capacity that can be referred to in generic code.
7//!
8//! # Usage
9//!
10//! This crate exposes the type aliases [`GenericArrayVec`]s and [`GenericArrayString`], which are
11//! aliases of datatypes in the `arrayvec` crate. See the [`ArrayVec`] and [`ArrayString`] docs
12//! to learn about their functionality. Each one also has a corresponding extension trait
13//! [`GenericArrayVecExt`] and [`GenericArrayStringExt`] that provide additional constructors and
14//! conversions.
15//!
16//! ## Example
17//!
18//! ```rust
19//! use generic_arrayvec::arrayvec::Array;
20//! use generic_arrayvec::typenum::{Prod, U2, U4};
21//! use generic_arrayvec::{ArrayvecStorage, Capacity, GenericArrayVec};
22//! use std::ops::Mul;
23//!
24//! fn main() {
25//! // Create a vector of `u8`s with a capacity of 4.
26//! let mut arr = GenericArrayVec::<u8, U4>::new();
27//! assert_eq!(arr.capacity(), 4);
28//!
29//! // Add some elements to it.
30//! arr.push(1);
31//! arr.push(2);
32//! arr.push(3);
33//! assert_eq!(&arr[..], &[1, 2, 3]);
34//!
35//! // To demonstrate generic bounds, we call our `double()` function, which is defined below.
36//! // This function returns a new vector with double the capacity of the input vector.
37//! // The new vector contains two copies of the input vector's items.
38//! let doubled = double(&arr);
39//! assert_eq!(&doubled[..], &[1, 2, 3, 1, 2, 3]);
40//! assert_eq!(doubled.capacity(), 8);
41//! }
42//!
43//! fn double<N>(original: &GenericArrayVec<u8, N>) -> GenericArrayVec<u8, Prod<N, U2>>
44//! where
45//! // Boilerplate bounds for the input array.
46//! N: Capacity<u8>,
47//! ArrayvecStorage<u8, N>: Array<Item = u8>,
48//!
49//! // Boilerplate bounds for the output array. Note it's the same as above, but
50//! // `N` -> `Prod<N, U2>`.
51//! Prod<N, U2>: Capacity<u8>,
52//! ArrayvecStorage<u8, Prod<N, U2>>: Array<Item = u8>,
53//!
54//! N: Mul<U2>,
55//! {
56//! let mut new = GenericArrayVec::<u8, Prod<N, U2>>::new();
57//!
58//! // These `unwrap()`s can never fail.
59//! new.try_extend_from_slice(original.as_slice()).unwrap();
60//! new.try_extend_from_slice(original.as_slice()).unwrap();
61//!
62//! new
63//! }
64//! ```
65//!
66//! ## `where` bound boilerplate
67//!
68//! When working with a [`GenericArrayVec<T, N>`] where `T` and/or `N` are not concrete types, you
69//! will need to always include certain bounds in your `where` clauses, or you will get a compile
70//! error. This dummy function shows how to specify them:
71//!
72//! ```rust
73//! use generic_arrayvec::arrayvec::Array;
74//! use generic_arrayvec::{ArrayvecStorage, Capacity, GenericArrayVec};
75//!
76//! fn f<T, N>(_arr: GenericArrayVec<T, N>)
77//! where
78//! N: Capacity<T>,
79//! ArrayvecStorage<T, N>: Array<Item = T>,
80//! {
81//! }
82//! ```
83//!
84//! And this is how you specify them for [`GenericArrayString<N>`]:
85//!
86//! ```rust
87//! use generic_arrayvec::arrayvec::Array;
88//! use generic_arrayvec::{ArrayvecStorage, Capacity, GenericArrayString};
89//!
90//! fn f<N>(_arr: GenericArrayString<N>)
91//! where
92//! N: Capacity<u8>,
93//! N::ArrayType: Copy,
94//! ArrayvecStorage<u8, N>: Array<Item = u8>,
95//! {
96//! }
97//! ```
98
99#![no_std]
100#![warn(
101 rust_2018_idioms,
102 deprecated_in_future,
103 macro_use_extern_crate,
104 missing_debug_implementations,
105 unused_qualifications
106)]
107
108pub use arrayvec;
109pub use generic_array::{self, typenum};
110
111use arrayvec::{Array, ArrayString, ArrayVec, CapacityError};
112use core::str::Utf8Error;
113use generic_array::typenum::{IsLess, U1, U2, U256, U4294967296, U65536};
114use generic_array::{ArrayLength, GenericArray};
115use plumbing::{ArrayvecStorageRaw, IndexForCapacity, PickIndexBreakpointsForCapacity};
116
117/// Low-level implementation details you shouldn't need to touch.
118pub mod plumbing;
119
120/// A [`GenericArray`]-backed [`ArrayVec`].
121pub type GenericArrayVec<T, N> = ArrayVec<ArrayvecStorage<T, N>>;
122
123/// A [`GenericArray`]-backed [`ArrayString`].
124pub type GenericArrayString<N> = ArrayString<ArrayvecStorage<u8, N>>;
125
126/// A wrapper around a [`GenericArray`] that implements the [`Array`] trait from the arrayvec
127/// crate, allowing it to be used as the backing store for [`ArrayVec`] and [`ArrayString`].
128///
129/// You likely won't need to interact with this type directly, except in `where` clauses when
130/// working with [`GenericArrayVec`] and [`GenericArrayString`]; see their docs for details.
131pub type ArrayvecStorage<T, N> = ArrayvecStorageRaw<T, N, IndexForCapacity<N>>;
132
133/// A trait implemented by `typenum`'s unsigned integers, which lets them be used to define the
134/// capacity of [`GenericArrayVec`]/[`GenericArrayString`].
135pub trait Capacity<T>:
136 ArrayLength<T>
137 + PickIndexBreakpointsForCapacity
138 + IsLess<U1>
139 + IsLess<U2>
140 + IsLess<U256>
141 + IsLess<U65536>
142 + IsLess<U4294967296>
143{
144}
145
146impl<N, T> Capacity<T> for N where
147 N: ArrayLength<T>
148 + PickIndexBreakpointsForCapacity
149 + IsLess<U1>
150 + IsLess<U2>
151 + IsLess<U256>
152 + IsLess<U65536>
153 + IsLess<U4294967296>
154{
155}
156
157/// Extension trait for [`GenericArrayVec`].
158///
159/// See its impl on [`GenericArrayVec`] for more info.
160pub trait GenericArrayVecExt<T, N>
161where
162 N: Capacity<T>,
163 ArrayvecStorage<T, N>: Array,
164{
165 fn generic_from<A>(arr: A) -> GenericArrayVec<T, N>
166 where
167 A: Into<GenericArray<T, N>>;
168
169 fn into_generic_array(self) -> Result<GenericArray<T, N>, Self>
170 where
171 Self: Sized;
172}
173
174impl<T, N> GenericArrayVecExt<T, N> for GenericArrayVec<T, N>
175where
176 N: Capacity<T>,
177 ArrayvecStorage<T, N>: Array,
178{
179 /// Creates a `GenericArrayVec` from an array or `GenericArray`.
180 ///
181 /// ```rust
182 /// use generic_arrayvec::{GenericArrayVec, GenericArrayVecExt};
183 ///
184 /// let vec = GenericArrayVec::generic_from([2, 4, 6, 8]);
185 ///
186 /// assert_eq!(vec.len(), 4);
187 /// assert_eq!(vec.capacity(), 4);
188 /// ```
189 fn generic_from<A>(arr: A) -> GenericArrayVec<T, N>
190 where
191 A: Into<GenericArray<T, N>>,
192 {
193 ArrayVec::from(ArrayvecStorage::from(arr.into()))
194 }
195
196 /// Returns the inner `GenericArray`, if `self` is full to its capacity.
197 ///
198 /// **Errors** if `self` is not filled to capacity.
199 ///
200 /// ```rust
201 /// use generic_arrayvec::typenum::U5;
202 /// use generic_arrayvec::{GenericArrayVec, GenericArrayVecExt};
203 ///
204 /// let mut vec = GenericArrayVec::<i32, U5>::new();
205 /// vec.push(0);
206 /// vec.extend(1..5);
207 ///
208 /// let generic_array = vec.into_generic_array().unwrap();
209 ///
210 /// assert_eq!(&*generic_array, &[0, 1, 2, 3, 4][..]);
211 /// ```
212 fn into_generic_array(self) -> Result<GenericArray<T, N>, Self> {
213 Ok(self.into_inner()?.into_inner())
214 }
215}
216
217/// Extension trait for [`GenericArrayString`].
218///
219/// See its impl on [`GenericArrayString`] for more info.
220pub trait GenericArrayStringExt<N>
221where
222 N: Capacity<u8>,
223 ArrayvecStorage<u8, N>: Array<Item = u8>,
224
225 N::ArrayType: Copy,
226{
227 fn generic_from(string: &str) -> Result<GenericArrayString<N>, CapacityError<&str>>;
228
229 fn generic_from_byte_string<A>(byte_string: &A) -> Result<GenericArrayString<N>, Utf8Error>
230 where
231 A: Into<GenericArray<u8, N>> + AsRef<[u8]>;
232}
233
234impl<N> GenericArrayStringExt<N> for GenericArrayString<N>
235where
236 N: Capacity<u8>,
237 ArrayvecStorage<u8, N>: Array<Item = u8>,
238
239 N::ArrayType: Copy,
240{
241 /// Creates a `GenericArrayString` from a `str`.
242 ///
243 /// Capacity is inferred from the type parameter.
244 ///
245 /// **Errors** if the capacity is not large enough to fit the string.
246 ///
247 /// ```rust
248 /// use generic_arrayvec::typenum::U10;
249 /// use generic_arrayvec::{GenericArrayString, GenericArrayStringExt};
250 ///
251 /// let string = GenericArrayString::<U10>::generic_from("hello").unwrap();
252 ///
253 /// assert_eq!(string.len(), 5);
254 /// assert_eq!(string.capacity(), 10);
255 /// ```
256 fn generic_from(string: &str) -> Result<GenericArrayString<N>, CapacityError<&str>> {
257 ArrayString::from(string)
258 }
259
260 /// Creates a `GenericArrayString` from a byte string.
261 ///
262 /// The `GenericArrayString`'s length and capacity will be equal to the input byte string.
263 ///
264 /// **Errors** if the byte string is not valid UTF-8.
265 ///
266 /// # Examples
267 ///
268 /// From a byte string literal:
269 ///
270 /// ```rust
271 /// use generic_arrayvec::{GenericArrayString, GenericArrayStringExt};
272 ///
273 /// let string = GenericArrayString::generic_from_byte_string(b"hello").unwrap();
274 ///
275 /// assert_eq!(string.len(), 5);
276 /// assert_eq!(string.capacity(), 5);
277 /// ```
278 ///
279 /// From a byte-holding `GenericArray`:
280 ///
281 /// ```rust
282 /// use generic_arrayvec::generic_array::GenericArray;
283 /// use generic_arrayvec::{GenericArrayString, GenericArrayStringExt};
284 ///
285 /// let arr = GenericArray::from([b'h', b'i']);
286 /// let string = GenericArrayString::generic_from_byte_string(&arr).unwrap();
287 ///
288 /// assert_eq!(string.len(), 2);
289 /// assert_eq!(string.capacity(), 2);
290 /// ```
291 fn generic_from_byte_string<A>(byte_string: &A) -> Result<GenericArrayString<N>, Utf8Error>
292 where
293 A: Into<GenericArray<u8, N>> + AsRef<[u8]>,
294 {
295 ArrayString::from_byte_string(&ArrayvecStorage::from(GenericArray::clone_from_slice(
296 byte_string.as_ref(),
297 )))
298 }
299}
300
301mod private {
302 #[allow(missing_debug_implementations)]
303 pub enum Sealed {}
304}