Skip to main content

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