non_empty_slice/
macros.rs

1//! Macros for creating non-empty vectors and slices.
2
3#[doc(hidden)]
4pub mod import {
5    pub use core::compile_error;
6
7    #[cfg(feature = "std")]
8    pub use std::vec;
9
10    #[cfg(all(not(feature = "std"), feature = "alloc"))]
11    pub use alloc::vec;
12
13    pub use non_zero_size::const_size;
14}
15
16/// Constructs [`NonEmptyVec<T>`] containing the provided arguments.
17///
18/// # Examples
19///
20/// Providing no arguments results in compile-time errors:
21///
22/// ```compile_fail
23/// use non_empty_slice::non_empty_vec;
24///
25/// let never = non_empty_vec![];
26/// ```
27///
28/// Providing one argument:
29///
30/// ```
31/// use non_empty_slice::non_empty_vec;
32///
33/// let single = non_empty_vec![13];
34/// ```
35///
36/// Providing argument implementing [`Clone`] and non-zero count of type [`Size`]:
37///
38/// ```
39/// use non_empty_slice::non_empty_vec;
40/// use non_zero_size::const_size;
41///
42/// let repeated = non_empty_vec![13; const_size!(42)];
43/// ```
44///
45/// Equivalently, one can use:
46///
47/// ```
48/// use non_empty_slice::non_empty_vec;
49///
50/// let repeated = non_empty_vec![13; const 42];
51/// ```
52///
53/// Finally, providing multiple arguments:
54///
55/// ```
56/// use non_empty_slice::non_empty_vec;
57///
58/// let nice = non_empty_vec![13, 42, 69];
59/// ```
60///
61/// [`NonEmptyVec<T>`]: crate::vec::NonEmptyVec
62/// [`Size`]: non_zero_size::Size
63#[macro_export]
64#[cfg(any(feature = "std", feature = "alloc"))]
65macro_rules! non_empty_vec {
66    () => {
67        $crate::macros::import::compile_error!("expected non-empty arguments");
68    };
69    ($value: expr $(,)?) => {
70        $crate::vec::NonEmptyVec::single($value)
71    };
72    ($value: expr; const $count: expr) => {
73        $crate::non_empty_vec!($value; $crate::macros::import::const_size!($count))
74    };
75    ($value: expr; $count: expr) => {
76        $crate::vec::NonEmptyVec::repeat($value, $count)
77    };
78    ($value: expr, $($rest: expr),+ $(,)?) => {{
79        let vector = $crate::macros::import::vec![$value, $($rest),+];
80
81        // SAFETY: the vector is guaranteed to be non-empty due to the macro pattern
82        let output = unsafe { $crate::vec::NonEmptyVec::new_unchecked(vector) };
83
84        output
85    }};
86}
87
88/// Constructs [`NonEmptySlice`] from the given slice, panicking if it is empty.
89///
90/// [`NonEmptySlice`]: crate::slice::NonEmptySlice
91#[macro_export]
92macro_rules! non_empty_slice {
93    ($slice: expr) => {
94        $crate::slice::NonEmptySlice::from_slice($slice).expect($crate::slice::EMPTY_SLICE)
95    };
96}
97
98/// Similar to [`non_empty_slice!`], but constructs [`NonEmptyBytes`].
99///
100/// # Examples
101///
102/// Simple usage:
103///
104/// ```
105/// use non_empty_slice::non_empty_bytes;
106///
107/// let nekit = non_empty_bytes!(b"nekit");
108/// ```
109///
110/// Panicking if the bytes are empty:
111///
112/// ```should_panic
113/// use non_empty_slice::non_empty_bytes;
114///
115/// let never = non_empty_bytes!(b"");
116/// ```
117///
118/// Compilation failure in `const` contexts:
119///
120/// ```compile_fail
121/// use non_empty_slice::non_empty_bytes;
122///
123/// let never = const { non_empty_bytes!(b"") };
124/// ```
125///
126/// [`NonEmptyBytes`]: crate::slice::NonEmptyBytes
127#[macro_export]
128macro_rules! non_empty_bytes {
129    ($bytes: expr) => {
130        $crate::slice::NonEmptyBytes::from_slice($bytes).expect($crate::slice::EMPTY_SLICE)
131    };
132}
133
134/// Similar to [`non_empty_slice!`] but for `const` contexts.
135///
136/// Note that the provided expression must be const-evaluatable, else the compilation will fail.
137#[macro_export]
138macro_rules! const_non_empty_slice {
139    ($slice: expr) => {
140        const { $crate::non_empty_slice!($slice) }
141    };
142}
143
144/// Similar to [`non_empty_bytes!`] but for `const` contexts.
145///
146/// Note that the provided expression must be const-evaluatable, else the compilation will fail.
147///
148/// # Examples
149///
150/// ```
151/// use non_empty_slice::const_non_empty_bytes;
152///
153/// let message = const_non_empty_bytes!(b"Hello, world!");
154/// ```
155///
156/// Failing compilation on empty bytes:
157///
158/// ```compile_fail
159/// use non_empty_slice::const_non_empty_bytes;
160///
161/// let never = const_non_empty_bytes!(b"");
162/// ```
163#[macro_export]
164macro_rules! const_non_empty_bytes {
165    ($bytes: expr) => {
166        const { $crate::non_empty_bytes!($bytes) }
167    };
168}