const_format/
macros.rs

1#[macro_use]
2mod assertions;
3
4#[macro_use]
5#[cfg(feature = "fmt")]
6mod call_debug_fmt;
7
8#[macro_use]
9mod constructors;
10
11#[macro_use]
12mod helper_macros;
13
14#[macro_use]
15mod fmt_macros;
16
17#[macro_use]
18#[cfg(feature = "fmt")]
19mod impl_fmt;
20
21#[macro_use]
22mod map_ascii_case;
23
24#[macro_use]
25mod str_methods;
26
27/// For returning early on an error, otherwise evaluating to `()`.
28///
29/// # Example
30///
31/// ```rust
32///
33/// use const_format::{Error, StrWriter};
34/// use const_format::{try_, writec};
35///
36/// const fn write_stuff(buffer: &mut StrWriter) -> Result<&[u8], Error> {
37///     try_!(writec!(buffer, "Foo{},Bar{},Baz{},", 8u32, 13u32, 21u32));
38///     Ok(buffer.as_bytes_alt())
39/// }
40///
41/// let mut buffer = StrWriter::new([0; 32]);
42/// assert_eq!(write_stuff(&mut buffer)?, "Foo8,Bar13,Baz21,".as_bytes());
43///
44/// # Ok::<(), Error>(())
45/// ```
46#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
47#[cfg(feature = "fmt")]
48#[macro_export]
49macro_rules! try_ {
50    ($e:expr) => {
51        if let $crate::pmr::Err(e) = $e {
52            return $crate::pmr::Err(e);
53        }
54    };
55}
56
57/// Equivalent to `Result::unwrap`, for use with [`const_format::Error`] errors.
58///
59/// You can use this when you know for certain that no error will happen.
60///
61/// [`const_format::Error`]: ./fmt/enum.Error.html
62///
63/// # Example
64///
65/// ```rust
66///
67/// use const_format::{StrWriter, unwrap, writec};
68///
69/// const CAP: usize = 11;
70/// const TEXT: &str = {
71///     const S: &StrWriter = &{
72///         let mut writer = StrWriter::new([0; CAP]);
73///         unwrap!(writec!(writer, "foo bar baz"));
74///         writer
75///     };
76///     S.as_str_alt()
77/// };
78/// assert_eq!(TEXT, "foo bar baz")
79///
80/// ```
81#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
82#[cfg(feature = "fmt")]
83#[macro_export]
84macro_rules! unwrap {
85    ($e:expr $(,)*) => {
86        match $e {
87            $crate::pmr::Ok(x) => x,
88            $crate::pmr::Err(error) => $crate::Error::unwrap(&error),
89        }
90    };
91}
92
93/// Equivalent to `Result::unwrap_or_else` but allows returning from the enclosing function.
94///
95/// # Examples
96///
97/// ### Early return
98///
99/// ```rust
100///
101/// use const_format::unwrap_or_else;
102///
103/// const fn unwrap_square(number: Result<u32, u32>) -> u64 {
104///     let n = unwrap_or_else!(number, |n| return n as u64 ) as u64;
105///     n * n
106/// }
107///
108/// assert_eq!(unwrap_square(Ok(10)), 100);
109/// assert_eq!(unwrap_square(Ok(30)), 900);
110/// assert_eq!(unwrap_square(Err(100)), 100);
111///
112/// ```
113///
114/// ### As unwrap_or
115///
116/// ```rust
117///
118/// use const_format::{AsciiStr, unwrap_or_else};
119///
120/// const FOO: AsciiStr = unwrap_or_else!(AsciiStr::new(b"AB\x80"), |_| AsciiStr::empty() );
121///
122/// const BAR: AsciiStr = unwrap_or_else!(AsciiStr::new(b"bar"), |_| loop{} );
123///
124/// assert_eq!(FOO.as_str(), "");
125/// assert_eq!(BAR.as_str(), "bar");
126///
127/// ```
128#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
129#[cfg(feature = "fmt")]
130#[macro_export]
131macro_rules! unwrap_or_else {
132    ($e:expr, |$($error:ident)? $(_)*| $orelse:expr ) => {
133        match $e {
134            $crate::pmr::Ok(x) => x,
135            $crate::pmr::Err($($error,)?..) => $orelse,
136        }
137    };
138}
139
140/// Coerces a reference to a type that has a `const_*_fmt` method.
141///
142/// # Behavior
143///
144/// For arrays it coerces them into a slice, and wraps them in a [`PWrapper`].
145///
146/// For std types, it wraps them in a [`PWrapper`], which implements the
147/// `const_*_fmt` methods.
148///
149/// For non-std types, it just returns back the same reference.
150///
151/// # Example
152///
153/// ```rust
154///
155/// use const_format::{
156///     for_examples::Unit,
157///     Formatter, FormattingFlags, PWrapper, StrWriter,
158///     coerce_to_fmt,
159/// };
160///
161/// const CAP: usize = 128;
162/// const fn make_strwriter() -> StrWriter<[u8; CAP]> {
163///     let mut writer = StrWriter::new([0; CAP]);
164///     let mut fmt = Formatter::from_sw(&mut writer, FormattingFlags::NEW);
165///
166///     // This is equivalent to the `PWrapper::slice(&[0u8, 1])` below
167///     let _ = coerce_to_fmt!([0u8, 1]).const_debug_fmt(&mut fmt);
168///     let _ = fmt.write_str(",");
169///
170///     let _ = PWrapper::slice(&[0u8, 1]).const_debug_fmt(&mut fmt);
171///     let _ = fmt.write_str(",");
172///
173///
174///     // This is equivalent to the `PWrapper(100u32)` line
175///     let _ = coerce_to_fmt!(100u32).const_debug_fmt(&mut fmt);
176///     let _ = fmt.write_str(",");
177///
178///     let _ = PWrapper(100u32).const_debug_fmt(&mut fmt);
179///     let _ = fmt.write_str(",");
180///
181///
182///     // This is equivalent to the `Unit.const_debug_fmt(&mut fmt)` line
183///     let _ = coerce_to_fmt!(Unit).const_debug_fmt(&mut fmt);
184///
185///
186///     let _ = fmt.write_str(",");
187///     let _ = Unit.const_debug_fmt(&mut fmt);
188///
189///     writer
190/// }
191///
192/// const TEXT: &str = {
193///     const TEXT_: &StrWriter = &make_strwriter();
194///     TEXT_.as_str_alt()
195/// };
196///
197/// assert_eq!(TEXT, "[0, 1],[0, 1],100,100,Unit,Unit");
198///
199/// ```
200///
201/// [`PWrapper`]: ./struct.PWrapper.html
202#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
203#[cfg(feature = "fmt")]
204#[macro_export]
205macro_rules! coerce_to_fmt {
206    ($reference:expr) => {{
207        match $reference {
208            ref reference => {
209                let marker = $crate::pmr::IsAFormatMarker::NEW;
210                if false {
211                    marker.infer_type(reference);
212                }
213                marker.coerce(marker.unreference(reference))
214            }
215        }
216    }};
217}
218
219/// Converts a `&'static StrWriter` to a `&'static str`, in a `const`/`static` initializer.
220///
221/// This is usable in `const` or `static` initializers,
222/// but not inside of `const fn`s.
223///
224/// **Deprecated:** This macro is deprecated because
225/// the [`StrWriter::as_str_alt`](crate::StrWriter::as_str_alt) method
226/// allows converting a`&'static StrWriter` to a `&'static str`.
227///
228/// # Runtime
229///
230/// If the "rust_1_64" feature is disabled,
231/// this takes time proportional to `$expr.capacity() - $expr.len()`.
232///
233/// If the "rust_1_64" feature is enabled, it takes constant time to run.
234///
235/// # Example
236///
237/// ```rust
238///
239/// use const_format::StrWriter;
240/// use const_format::{strwriter_as_str, unwrap, writec};
241///
242///
243/// const CAP: usize = 128;
244///
245/// const __STR: &StrWriter = &{
246///     let mut writer =  StrWriter::new([0; CAP]);
247///
248///     // Writing the array with debug formatting, and the integers with hexadecimal formatting.
249///     unwrap!(writec!(writer, "{:x}", [3u32, 5, 8, 13, 21, 34]));
250///
251///     writer
252/// };
253///
254/// const STR: &str = strwriter_as_str!(__STR);
255///
256/// fn main() {
257///     assert_eq!(STR, "[3, 5, 8, d, 15, 22]");
258/// }
259/// ```
260///
261#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
262#[cfg(feature = "fmt")]
263#[deprecated(since = "0.2.19", note = "Use `StrWriter::as_str_alt` instead")]
264#[macro_export]
265macro_rules! strwriter_as_str {
266    ($expr:expr) => {
267        unsafe {
268            let writer: &'static $crate::StrWriter = $expr;
269            #[allow(clippy::transmute_bytes_to_str)]
270            $crate::__priv_transmute_bytes_to_str!(writer.as_bytes_alt())
271        }
272    };
273}
274
275#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
276#[cfg(feature = "fmt")]
277macro_rules! conditionally_const {
278    (
279        feature = $feature:literal;
280        $(
281            $( #[$meta:meta] )*
282            $vis:vis fn $fn_name:ident ($($params:tt)*) -> $ret:ty $block:block
283        )*
284    ) => (
285        $(
286            $(#[$meta])*
287            #[cfg(feature = $feature)]
288            $vis const fn $fn_name ($($params)*) -> $ret $block
289
290            $(#[$meta])*
291            #[cfg(not(feature = $feature))]
292            $vis fn $fn_name ($($params)*) -> $ret $block
293        )*
294    )
295}
296
297#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
298#[cfg(feature = "fmt")]
299macro_rules! std_kind_impl {
300    (
301        impl[$($impl:tt)*] $self:ty
302        $(where[ $($where_:tt)* ])?
303    )=>{
304        impl<$($impl)*> $crate::pmr::FormatMarker for $self
305        where
306            $($($where_)*)?
307        {
308            type Kind = $crate::pmr::IsStdKind;
309            type This = Self;
310        }
311
312        impl<$($impl)* __T> $crate::pmr::IsAFormatMarker<$crate::pmr::IsStdKind, $self, __T>
313        where
314            $($($where_)*)?
315        {
316            #[inline(always)]
317            pub const fn coerce(self, reference: &$self) -> $crate::pmr::PWrapper<$self> {
318                $crate::pmr::PWrapper(*reference)
319            }
320        }
321    }
322}
323
324#[macro_export]
325#[doc(hidden)]
326macro_rules! __priv_transmute_bytes_to_str {
327    ($bytes:expr) => {{
328        let bytes: &'static [$crate::pmr::u8] = $bytes;
329        let string: &'static $crate::pmr::str = {
330            $crate::__hidden_utils::PtrToRef {
331                ptr: bytes as *const [$crate::pmr::u8] as *const str,
332            }
333            .reff
334        };
335        string
336    }};
337}
338
339#[macro_export]
340#[doc(hidden)]
341macro_rules! __priv_transmute_raw_bytes_to_str {
342    ($bytes:expr) => {{
343        let bytes: *const [$crate::pmr::u8] = $bytes;
344        let string: &'static $crate::pmr::str = {
345            $crate::__hidden_utils::PtrToRef {
346                ptr: bytes as *const str,
347            }
348            .reff
349        };
350        string
351    }};
352}