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}