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}