1/// Concatenates constants of primitive types into a `&'static str`.
2///
3/// Each argument is stringified after evaluating it, so `concatcp!(1u8 + 3) == "4"`
4///
5/// [For **examples** look here](#examples)
6///
7/// `concatcp` stands for "concatenate constants (of) primitives"
8///
9/// # Limitations
10///
11/// This macro can only take constants of these types as inputs:
12///
13/// - `&str`
14///
15/// - `i*`/`u*` (all the primitive integer types).
16///
17/// - `char`
18///
19/// - `bool`
20///
21/// This macro also shares
22/// [the limitations described in here](./index.html#macro-limitations)
23/// as well.
24///
25/// # Examples
26///
27/// ### Literal arguments
28///
29///
30/// ```rust
31/// use const_format::concatcp;
32///
33/// const MSG: &str = concatcp!(2u8, "+", 2u8, '=', 2u8 + 2);
34///
35/// assert_eq!(MSG, "2+2=4");
36///
37/// ```
38///
39/// ### `const` arguments
40///
41/// ```rust
42/// use const_format::concatcp;
43///
44/// const PASSWORD: &str = "password";
45///
46/// const fn times() -> u64 { 10 }
47///
48/// const MSG: &str =
49/// concatcp!("The password is \"", PASSWORD, "\", you can only guess ", times(), " times.");
50///
51/// assert_eq!(MSG, r#"The password is "password", you can only guess 10 times."#);
52///
53/// ```
54///
55#[macro_export]
56macro_rules! concatcp {
57 ()=>{""};
58 ($($arg: expr),* $(,)?)=>(
59 $crate::pmr::__AssertStr {x:{
60 use $crate::__cf_osRcTFl4A;
61 $crate::pmr::__concatcp_impl!{
62 $( ( $arg ), )*
63 }
64 }}.x
65 );
66}
67
68#[doc(hidden)]
69#[macro_export]
70macro_rules! __concatcp_inner {
71 ($variables:expr) => {{
72 #[doc(hidden)]
73 const ARR_LEN: usize = $crate::pmr::PArgument::calc_len($variables);
74
75 #[doc(hidden)]
76 const CONCAT_ARR: &$crate::pmr::LenAndArray<[u8; ARR_LEN]> =
77 &$crate::pmr::__priv_concatenate($variables);
78
79 #[doc(hidden)]
80 #[allow(clippy::transmute_ptr_to_ptr)]
81 const CONCAT_STR: &str = unsafe {
82 // This transmute truncates the length of the array to the amound of written bytes.
83 let slice =
84 $crate::pmr::transmute::<&[u8; ARR_LEN], &[u8; CONCAT_ARR.len]>(&CONCAT_ARR.array);
85
86 $crate::__priv_transmute_bytes_to_str!(slice)
87 };
88 CONCAT_STR
89 }};
90}
91
92////////////////////////////////////////////////////////////////////////////////
93
94/// Formats constants of primitive types into a `&'static str`
95///
96/// [For **examples** look here](#examples)
97///
98/// `formatcp` stands for "format constants (of) primitives"
99///
100/// # Syntax
101///
102/// This macro uses a limited version of the syntax from the standard library [`format`] macro,
103/// it can do these things:
104///
105/// - Take positional arguments: `formatcp!("{}{0}", "hello" )`
106///
107/// - Take named arguments: `formatcp!("{a}{a}", a = "hello" )`
108///
109/// - Use constants from scope as arguments: `formatcp!("{FOO}")`<br>
110/// equivalent to the [`format_args_implicits` RFC]
111///
112/// - Use Debug-like formatting (eg: `formatcp!("{:?}", "hello" )`:<br>
113/// Similar to how `Debug` formatting in the standard library works,
114/// except that it does not escape unicode characters.
115///
116/// - Use LowerHex formatting (eg: `formatcp!("{:x}", "hello" )`):<br>
117/// Formats numbers as lowercase hexadecimal.
118/// The alternate version (written as `"{:#x}"`) prefixes the number with `0x`
119///
120/// - Use UpperHex formatting (eg: `formatcp!("{:X}", "hello" )`):<br>
121/// Formats numbers as capitalized hexadecimal.
122/// The alternate version (written as `"{:#X}"`) prefixes the number with `0x`
123///
124/// - Use Binary formatting (eg: `formatcp!("{:b}", "hello" )`)<br>
125/// The alternate version (written as `"{:#b}"`) prefixes the number with `0b`
126///
127/// - Use Display formatting: `formatcp!("{}", "hello" )`
128///
129///
130/// # Limitations
131///
132/// This macro can only take constants of these types as inputs:
133///
134/// - `&str`
135///
136/// - `i*`/`u*` (all the primitive integer types).
137///
138/// - `char`
139///
140/// - `bool`
141///
142/// This macro also shares
143/// [the limitations described in here](./index.html#macro-limitations)
144/// as well.
145///
146/// # Formating behavior
147///
148/// ### Debug-like
149///
150/// The `{:?}` formatter formats things similarly to how Debug does it.
151///
152/// For `&'static str` it does these things:
153/// - Prepend and append the double quote character (`"`).
154/// - Escape the `'\t'`,`'\n'`,`'\r'`,`'\\'`, `'\''`, and`'\"'` characters.
155/// - Escape control characters with `\xYY`,
156/// where `YY` is the hexadecimal value of the control character.
157///
158/// Example:
159/// ```
160/// use const_format::formatcp;
161///
162/// assert_eq!(formatcp!("{:?}", r#" \ " ó "#), r#"" \\ \" ó ""#);
163/// ```
164///
165/// For `char` it does these things:
166/// - Prepend and append the single quote character (`'`).
167/// - Uses the same escapes as `&'static str`.
168///
169/// ### Display
170///
171/// The `{}`/`{:}` formatter produces the same output as in [`format`].
172///
173///
174/// # Examples
175///
176/// ### Implicit argument
177///
178/// ```rust
179/// use const_format::formatcp;
180///
181/// const NAME: &str = "John";
182///
183/// const MSG: &str = formatcp!("Hello {NAME}, your name is {} bytes long", NAME.len());
184///
185/// assert_eq!(MSG, "Hello John, your name is 4 bytes long");
186///
187/// ```
188///
189/// ### Repeating arguments
190///
191/// ```rust
192/// use const_format::formatcp;
193///
194/// const MSG: &str = formatcp!("{0}{S}{0}{S}{0}", "SPAM", S = " ");
195///
196/// assert_eq!(MSG, "SPAM SPAM SPAM");
197///
198/// ```
199///
200/// ### Debug-like and Display formatting
201///
202/// ```rust
203/// use const_format::formatcp;
204///
205/// {
206/// const TEXT: &str = r#"hello " \ world"#;
207/// const MSG: &str = formatcp!("{TEXT}____{TEXT:?}");
208///
209/// assert_eq!(MSG, r#"hello " \ world____"hello \" \\ world""#);
210/// }
211/// {
212/// const CHARS: &str = formatcp!("{0:?} - {0} - {1} - {1:?}", '"', '👀');
213///
214/// assert_eq!(CHARS, r#"'\"' - " - 👀 - '👀'"#);
215/// }
216/// ```
217///
218/// ### Additional specifiers
219///
220/// `const_format` macros don't support width, fill, alignment, sign,
221/// or precision specifiers.
222///
223/// [`format`]: https://doc.rust-lang.org/std/macro.format.html
224///
225/// [`format_args_implicits` RFC]:
226/// https://github.com/rust-lang/rfcs/blob/master/text/2795-format-args-implicit-identifiers.md
227///
228///
229#[macro_export]
230macro_rules! formatcp {
231 ($format_string:expr $( $(, $expr:expr )+ )? $(,)? ) => (
232 $crate::pmr::__AssertStr {x:{
233 use $crate::__cf_osRcTFl4A;
234
235 $crate::pmr::__formatcp_impl!(
236 ($format_string)
237 $(, $($expr,)+)?
238 )
239 }}.x
240 );
241}
242
243////////////////////////////////////////////////////////////////////////////////
244
245/// Concatenates constants of standard library and/or user-defined types into a `&'static str`.
246///
247/// User defined types must implement the [`FormatMarker`] trait and
248/// and have a `const_display_fmt` method (as described in the trait) to be concatenated.
249///
250/// # Stable equivalent
251///
252/// For an equivalent macro which can be used in stable Rust,
253/// but can only concatenate primitive types,
254/// you can use the [`concatcp`](crate::concatcp) macro.
255///
256/// # Limitations
257///
258/// This macro has [the limitations described in here](./index.html#macro-limitations).
259///
260/// # Examples
261///
262/// ### With standard library types
263///
264/// ```rust
265/// #![feature(const_mut_refs)]
266///
267/// use const_format::concatc;
268///
269/// assert_eq!(concatc!("There is ", 99u8, " monkeys!"), "There is 99 monkeys!");
270///
271/// ```
272///
273/// ### With user-defined types
274///
275/// ```rust
276/// #![feature(const_mut_refs)]
277///
278/// use const_format::{Formatter, Sliced, concatc, impl_fmt};
279///
280/// const STRING: &str = "foo bar baz";
281///
282/// assert_eq!(concatc!(Sliced(STRING, 4..7), ' ', Foo), "bar table");
283///
284/// struct Foo;
285///
286/// impl_fmt!{
287/// impl Foo;
288/// const fn const_display_fmt(&self, fmt: &mut Formatter<'_>) -> const_format::Result {
289/// fmt.write_str("table")
290/// }
291/// }
292/// ```
293///
294///
295/// [`FormatMarker`]: ./marker_traits/trait.FormatMarker.html
296///
297#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
298#[cfg(feature = "fmt")]
299#[macro_export]
300macro_rules! concatc {
301 ()=>{""};
302 ($($anything:tt)*)=>(
303 $crate::pmr::__AssertStr {x:{
304 use $crate::__cf_osRcTFl4A;
305
306 $crate::__concatc_expr!(($($anything)*) ($($anything)*))
307 as &'static $crate::pmr::str
308 }}.x
309 )
310}
311
312#[doc(hidden)]
313#[cfg(feature = "fmt")]
314#[macro_export]
315macro_rules! __concatc_expr {
316 (($($arg: expr),* $(,)?) ($($span:tt)*) )=>({
317 const fn fmt_NHPMWYD3NJA(
318 mut fmt: $crate::fmt::Formatter<'_>,
319 ) -> $crate::Result {
320 use $crate::coerce_to_fmt as __cf_coerce_to_fmt;
321 use $crate::pmr::respan_to as __cf_respan_to;
322 use $crate::try_ as __cf_try;
323
324 $({
325 let __cf_respan_to!(($arg) fmt) = &mut fmt;
326 __cf_respan_to!(($arg)
327 __cf_try!(__cf_coerce_to_fmt!($arg).const_display_fmt(fmt))
328 );
329 })*
330
331 $crate::pmr::Ok(())
332 }
333
334 $crate::__concatc_inner!(fmt_NHPMWYD3NJA, true, $($span)*)
335 })
336}
337
338#[doc(hidden)]
339#[macro_export]
340macro_rules! __concatc_inner {
341 ($debug_fmt_fn:ident, $cond:expr, $($span:tt)*) => {{
342 const fn len_nhpmwyd3nj() -> usize {
343 if $cond {
344 let mut strlen = __cf_osRcTFl4A::pmr::ComputeStrLength::new();
345 let fmt = strlen.make_formatter(__cf_osRcTFl4A::FormattingFlags::NEW);
346 match $debug_fmt_fn(fmt) {
347 __cf_osRcTFl4A::pmr::Ok(()) => strlen.len(),
348 __cf_osRcTFl4A::pmr::Err(_) => 0,
349 }
350 } else {
351 0
352 }
353 }
354
355 const LEN_NHPMWYD3NJA: usize = len_nhpmwyd3nj();
356
357 const fn str_writer_nhpmwyd3nja(
358 ) -> __cf_osRcTFl4A::msg::ErrorTupleAndStrWriter<[u8; LEN_NHPMWYD3NJA]> {
359 let mut writer = __cf_osRcTFl4A::pmr::StrWriter::new([0; LEN_NHPMWYD3NJA]);
360 let error = if $cond {
361 $debug_fmt_fn(__cf_osRcTFl4A::pmr::Formatter::from_sw(
362 &mut writer,
363 __cf_osRcTFl4A::FormattingFlags::NEW,
364 ))
365 } else {
366 __cf_osRcTFl4A::pmr::Ok(())
367 };
368
369 __cf_osRcTFl4A::msg::ErrorTupleAndStrWriter {
370 error: __cf_osRcTFl4A::msg::ErrorTuple::new(error, &writer),
371 writer,
372 }
373 }
374
375 const STR_WRITER_NHPMWYD3NJA: &__cf_osRcTFl4A::msg::ErrorTupleAndStrWriter<
376 [u8; LEN_NHPMWYD3NJA],
377 > = &str_writer_nhpmwyd3nja();
378
379 const _: __cf_osRcTFl4A::msg::Ok = <<__cf_osRcTFl4A::msg::ErrorPicker<
380 [(); STR_WRITER_NHPMWYD3NJA.error.error_variant],
381 [(); STR_WRITER_NHPMWYD3NJA.error.capacity],
382 > as __cf_osRcTFl4A::msg::ErrorAsType>::Type>::NEW;
383
384 const STR_NHPMWYD3NJA: &str = STR_WRITER_NHPMWYD3NJA.writer.unsize().as_str_alt();
385
386 STR_NHPMWYD3NJA
387 }};
388}
389
390////////////////////////////////////////////////////////////////////////////////
391
392/// Formats constants of standard library and/or user-defined types into a `&'static str`.
393///
394/// User-defined types must implement the [`FormatMarker`] trait
395/// (as described in the docs for that trait) to be usable with this macro.
396///
397/// # Stable equivalent
398///
399/// For an equivalent macro which can be used in stable Rust,
400/// but can only format primitive types,
401/// you can use the [`formatcp`](crate::formatcp) macro.
402///
403/// # Syntax
404///
405/// This macro uses the syntax described in
406/// [the const_format::fmt module](./fmt/index.html#fmtsyntax)
407///
408/// # Limitations
409///
410/// This macro has [the limitations described in here](./index.html#macro-limitations).
411///
412/// # Example
413///
414/// ```rust
415/// #![feature(const_mut_refs)]
416///
417/// use const_format::for_examples::Point3;
418/// use const_format::formatc;
419///
420/// // Formatting a non-std struct.
421/// const POINT: &str = formatc!("{:?}", Point3{x: 8, y: 13, z: 21});
422///
423/// // Formatting a number as decimal, hexadecimal, and binary
424/// const NUMBER: &str = formatc!("{0},{0:x},{0:b}", 10u8);
425///
426/// // Formatting the numbers in an array as decimal, hexadecimal, and binary.
427/// // You can use the name of cnstants from scope, as well as named arguments.
428/// const ARR: &[u32] = &[9, 25];
429/// const ARRAY: &str = formatc!("{ARR:?},{ARR:X},{ARR:b}");
430///
431///
432/// assert_eq!(POINT, "Point3 { x: 8, y: 13, z: 21 }");
433/// assert_eq!(NUMBER, "10,a,1010");
434/// assert_eq!(ARRAY, "[9, 25],[9, 19],[1001, 11001]");
435///
436/// ```
437///
438/// ### Custom formatting.
439///
440/// This example demonstrates how you can access the [`Formatter`] in arguments
441/// to do custom formatting.
442///
443/// For more details on this you can look
444/// [in the fmt module](./fmt/index.html#custom-formatting-section).
445///
446/// ```rust
447/// #![feature(const_mut_refs)]
448///
449/// use const_format::for_examples::Point3;
450/// use const_format::{formatc, try_};
451///
452/// const P: Point3 = Point3{x: 5, y: 13, z: 21};
453///
454/// const STR: &str = formatc!("{0};{0:#X};{0:#b}", |fmt|{
455/// try_!(fmt.write_u32_debug(P.x));
456/// try_!(fmt.write_str(" "));
457/// try_!(fmt.write_u32_debug(P.y));
458/// try_!(fmt.write_char('.'));
459/// });
460///
461/// assert_eq!(STR, "5 13.;0x5 0xD.;0b101 0b1101.");
462///
463/// ```
464/// [`Formatter`]: crate::fmt::Formatter
465/// [`FormatMarker`]: crate::marker_traits::FormatMarker
466///
467///
468#[macro_export]
469#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
470#[cfg(feature = "fmt")]
471macro_rules! formatc {
472 ($format_string:expr $( $(, $expr:expr )+ )? $(,)? ) => (
473 $crate::pmr::__AssertStr {x:{
474 use $crate::__cf_osRcTFl4A;
475
476 $crate::pmr::__formatc_impl!{
477 ($format_string)
478 $(, $($expr,)+)?
479 }
480 }}.x
481 );
482}
483
484/// Writes some formatted standard library and/or user-defined types into a buffer.
485///
486/// This macro evaluates to a `Result<(), const_format::Error>` which must be handled.
487///
488/// # Syntax
489///
490/// The syntax is similar to that of other formatting macros in this crate:
491///
492/// ```ìgnore
493/// ẁritec!(
494/// writer_expression,
495/// "formatting literal",
496/// positional_arg_0_expression,
497/// positional_arg_1_expression,
498/// named_arg_foo = expression,
499/// named_arg_bar = expression,
500/// )
501/// ```
502///
503/// The syntax is otherwise the same as described in
504/// [the `const_format::fmt` module](./fmt/index.html#fmtsyntax).
505///
506/// # Writers
507///
508/// The first argument must be a type that implements the [`WriteMarker`] trait,
509/// and has these inherent methods:
510/// ```ignore
511/// const fn borrow_mutably(&mut self) -> &mut Self
512/// const fn make_formatter(&mut self, flags: FormattingFlags) -> Formatter<'_>
513/// ```
514///
515/// [This example](#custom-writable-example) below shows how to use this macro
516/// with a custom type.
517///
518/// # Limitations
519///
520/// Integer arguments must have a type inferrable from context,
521/// [more details in the Integer arguments section](./index.html#integer-args).
522///
523/// # Examples
524///
525/// ### Ẁriting a Display impl.
526///
527/// ```
528/// #![feature(const_mut_refs)]
529///
530/// use const_format::{Error, Formatter, StrWriter};
531/// use const_format::{impl_fmt, try_, writec};
532///
533/// pub struct Foo(u32, &'static str);
534///
535/// impl_fmt!{
536/// impl Foo;
537/// pub const fn const_display_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
538/// try_!(writec!(f, "{},", self.0));
539/// try_!(writec!(f, "{:?};", self.1));
540/// Ok(())
541/// }
542/// }
543///
544/// // Coerces the `&mut StrWriter<[u8; 128]>` to `&mut StrWriter<[u8]>`.
545/// // This is necessary because the `as_str` method is defined for `StrWriter<[u8]>`.
546/// let writer: &mut StrWriter = &mut StrWriter::new([0; 128]);
547/// writec!(writer, "{}", Foo(100, "bar"))?;
548///
549/// assert_eq!(writer.as_str(), r#"100,"bar";"#);
550///
551/// # Ok::<(), const_format::Error>(())
552/// ```
553///
554/// <span id="custom-writable-example"></span>
555/// ### Writing to a custom type
556///
557/// This example demonstrates how you can use the `ẁritec` macro with a custom type,
558/// in this case it's a buffer that is cleared every time it's written.
559///
560/// ```rust
561/// #![feature(const_mut_refs)]
562///
563/// use const_format::marker_traits::{IsNotAStrWriter, WriteMarker};
564/// use const_format::{Formatter, FormattingFlags};
565/// use const_format::writec;
566///
567/// const ARRAY_CAP: usize = 20;
568/// struct Array {
569/// len: usize,
570/// arr: [u8; ARRAY_CAP],
571/// }
572///
573/// impl WriteMarker for Array{
574/// type Kind = IsNotAStrWriter;
575/// type This = Self;
576/// }
577///
578/// impl Array {
579/// // Gets the part of the array that has been written to.
580/// pub const fn as_bytes(&self) -> &[u8] {
581/// const_format::utils::slice_up_to_len_alt(&self.arr, self.len)
582/// }
583///
584/// pub const fn borrow_mutably(&mut self) -> &mut Self {
585/// self
586/// }
587///
588/// pub const fn make_formatter(&mut self, flags: FormattingFlags) -> Formatter<'_> {
589/// Formatter::from_custom_cleared(&mut self.arr, &mut self.len, flags)
590/// }
591/// }
592///
593///
594/// let mut buffer = Array{ arr: [0; ARRAY_CAP], len: 0 };
595///
596/// writec!(buffer, "{:?}", [3u8, 5, 8, 13, 21])?;
597/// assert_eq!(buffer.as_bytes(), b"[3, 5, 8, 13, 21]");
598///
599/// writec!(buffer, "{}{}", "Hello, world!", 100u16)?;
600/// assert_eq!(buffer.as_bytes(), b"Hello, world!100");
601///
602/// # Ok::<(), const_format::Error>(())
603/// ```
604///
605/// ### Custom formatting.
606///
607/// This example demonstrates how you can access the [`Formatter`] in arguments
608/// to do custom formatting.
609///
610/// Note that `return` inside arguments returns from the function around the `writec`.
611///
612/// For more details on this you can look
613/// [in the fmt module](./fmt/index.html#custom-formatting-section).
614///
615/// ```rust
616/// #![feature(const_mut_refs)]
617///
618/// use const_format::for_examples::Point3;
619/// use const_format::{StrWriter, call_debug_fmt, try_, writec};
620///
621/// const P: Point3 = Point3{x: 5, y: 13, z: 21};
622///
623/// let writer: &mut StrWriter = &mut StrWriter::new([0; 128]);
624///
625/// writec!(
626/// writer,
627/// "The options are: {}, and {}",
628/// |fmt| call_debug_fmt!(Option, Some(P), fmt),
629/// |fmt| call_debug_fmt!(Option, None::<Point3>, fmt),
630/// )?;
631///
632/// assert_eq!(writer.as_str(), "The options are: Some(Point3 { x: 5, y: 13, z: 21 }), and None");
633///
634/// # Ok::<(), const_format::Error>(())
635/// ```
636///
637/// ### Locals in the format string
638///
639/// This example demonstrates how you can format local variables,
640/// by using their identifiers in the format string.
641///
642/// ```rust
643/// #![feature(const_mut_refs)]
644///
645/// use const_format::{Formatter, FormattingFlags, StrWriter, try_, writec};
646///
647/// const fn writeit(mut fmt: Formatter<'_>, foo: u32, bar: &str) -> const_format::Result {
648/// try_!(writec!(fmt, "{foo},{foo:?},{foo:#x},{foo:#b};"));
649/// try_!(writec!(fmt, "{bar},{bar:?}"));
650/// Ok(())
651/// }
652///
653/// let writer: &mut StrWriter = &mut StrWriter::new([0; 128]);
654///
655/// writeit(writer.make_formatter(FormattingFlags::NEW), 100, "hello")?;
656///
657/// assert_eq!(writer.as_str(), r#"100,100,0x64,0b1100100;hello,"hello""#);
658///
659/// # Ok::<(), const_format::Error>(())
660/// ```
661///
662/// [`Formatter`]: ./fmt/struct.Formatter.html
663/// [`WriteMarker`]: ./marker_traits/trait.WriteMarker.html
664///
665///
666///
667///
668#[macro_export]
669#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
670#[cfg(feature = "fmt")]
671macro_rules! writec {
672 ( $writer:expr, $format_string:expr $( $(, $expr:expr )+ )? $(,)? ) => ({
673 use $crate::__cf_osRcTFl4A;
674
675 $crate::pmr::__writec_impl!{
676 ($writer)
677 ($format_string)
678 $(, $($expr,)+)?
679 }
680 });
681}
682