const_format/fmt/
formatter.rs

1use crate::{
2    fmt::{Error, FormattingFlags, NoEncoding, StrWriter, StrWriterMut},
3    utils::saturate_range,
4    wrapper_types::{AsciiStr, PWrapper},
5};
6
7use core::ops::Range;
8
9////////////////////////////////////////////////////////////////////////////////
10
11/// For computing how long a formatted string would be.
12///
13/// This is what the [`formatc`] macro uses to precalculate the length of its returned `&str`.
14///
15/// # Example
16///
17/// ```rust
18///
19/// use const_format::fmt::{ComputeStrLength, Error, Formatter, FormattingFlags, StrWriter};
20/// use const_format::{try_, writec, unwrap};
21///
22/// const fn write_sum(mut f: Formatter<'_>) -> Result<(), Error> {
23///     let l = 7u8;
24///     let r = 8u8;
25///     writec!(f, "{} + {} = {}", l, r, l + r)
26/// }
27///
28/// const LEN: usize = {
29///     let mut computer = ComputeStrLength::new();
30///     unwrap!(write_sum(computer.make_formatter(FormattingFlags::NEW)));
31///     computer.len()
32/// };
33///
34/// // The type annotation coerces a `&mut StrWriter<[u8; LEN]>`
35/// // to a `&mut StrWriter<[u8]>` (the type parameter defaults to `[u8]`)
36/// let writer: &mut StrWriter = &mut StrWriter::new([0; LEN]);
37///
38/// write_sum(writer.make_formatter(FormattingFlags::NEW)).unwrap();
39///
40/// assert_eq!(writer.as_str(), "7 + 8 = 15");
41/// assert_eq!(writer.len(), LEN);
42/// assert_eq!(writer.capacity(), LEN);
43///
44/// ```
45///
46/// [`formatc`]: ../macro.formatc.html
47///
48///
49pub struct ComputeStrLength {
50    len: usize,
51}
52
53impl ComputeStrLength {
54    /// Constructs a ComputeStrLength of length 0.
55    pub const fn new() -> Self {
56        Self { len: 0 }
57    }
58
59    /// Constructs a `Formatter`,
60    /// which instead of writing to a buffer it adds the computed length into this.
61    pub const fn make_formatter(&mut self, flags: FormattingFlags) -> Formatter<'_> {
62        Formatter {
63            margin: 0,
64            flags,
65            writer: WriterBackend::Length(self),
66        }
67    }
68
69    /// Adds `len` to the calculated length.
70    pub const fn add_len(&mut self, len: usize) {
71        self.len += len;
72    }
73
74    /// The length of the string when formatted.
75    pub const fn len(&self) -> usize {
76        self.len
77    }
78
79    /// Whether the length of the computed string is zero.
80    pub const fn is_empty(&self) -> bool {
81        self.len == 0
82    }
83
84    /// For borrowing this mutably in macros,just takes and returns a `&mut Self`.
85    #[inline(always)]
86    pub const fn borrow_mutably(&mut self) -> &mut Self {
87        self
88    }
89}
90
91////////////////////////////////////////////////////////////////////////////////
92
93enum WriterBackend<'w> {
94    Str(StrWriterMut<'w, NoEncoding>),
95    Length(&'w mut ComputeStrLength),
96}
97
98////////////////////////////////////////////////////////////////////////////////
99
100/// A handle for writing formatted output.
101///
102/// `Formatter` writes utf8 encoded text, it can't be used to write arbitrary bytes.
103///
104/// # FormattingFlags
105///
106/// Types can change how they're formatted based on the value returned by `.flags()`,
107/// for more details on that you can read the documentation for [`FormattingFlags`].
108///
109/// # Construction
110///
111/// This type can be constructed in these ways:
112///
113/// - From a pair of mutable reference to a [`StrWriter`] and a [`FormattingFlags`],
114/// with the [`from_sw`] constructor.
115///
116/// - From a pair of [`StrWriterMut`] and [`FormattingFlags`],
117/// with the [`from_sw_mut`] constructor.
118///
119/// - From a [`ComputeStrLength`], by calling its
120/// [`make_formatter`](./struct.ComputeStrLength.html#method.make_formatter) method.
121/// This allows computing the length of formatted output without writing to anything.
122///
123/// - From a triple of `[u8]` and `usize` mutable references, and a [`FormattingFlags`],
124/// with the [`from_custom_cleared`] constructor,
125/// or the [`from_custom`] constructor.
126///
127/// # Errors
128///
129/// The `write_*` methods can only return an `Error::NotEnoughSpace`,
130/// when they do, the formatter was not written to, so you can try again with a shorter input.
131///
132/// In the case of the `debug_*` methods / the `Debug*` structs,
133/// they can return a `Error::NotEnoughSpace` when their `finish` method is called,
134/// not as soon as it happens.
135///
136/// # Examples
137///
138/// ### Display formatting
139///
140/// This example demonstrates how you can do display formatting with a Formatter.
141///
142/// If you want to write a braced struct/variant you can use [`DebugStruct`],
143/// or [`DebugTuple`] for tuple structs/variants.
144///
145/// ```rust
146///
147/// use const_format::{Error, Formatter, FormattingFlags, StrWriter};
148/// use const_format::{impl_fmt, try_};
149///
150/// struct Foo;
151///
152/// impl_fmt!{
153///     impl[] Foo;
154///     
155///     const fn const_display_fmt(&self, mut f: Formatter<'_>) -> Result<(), Error> {
156///         let string = "foo bar baz";
157///         try_!(f.write_u8_display(100));
158///         try_!(f.write_str(" "));
159///         try_!(f.write_str_range(string, 4..7));
160///         try_!(f.write_str("\n\n\n...figters"));
161///         Ok(())
162///     }
163/// }
164///
165/// // We have to coerce `&mut StrWriter<[u8; 256]>` to `&mut StrWriter` to call the
166/// // `make_formatter` method.
167/// let writer: &mut StrWriter = &mut StrWriter::new([0; 256]);
168///
169/// let flags = FormattingFlags::NEW.set_binary();
170///
171/// // The Display formatters from this crate don't care which NumberFormatting you pass,
172/// // they'll just write integers as decimal.
173/// Foo.const_display_fmt(writer.make_formatter(flags));
174///
175/// assert_eq!(writer.as_str(), "100 bar\n\n\n...figters");
176/// ```
177///
178/// <span id = "write_array_example"></span>
179/// ### Writing to an array
180///
181/// This example demonstrates how you can use a Formatter to write to a byte slice.
182///
183/// You can use the [`from_custom`] constructor if you need to start writing from
184/// anywhere other than 0.
185///
186/// ```rust
187///
188/// use const_format::{Error, Formatter, FormattingFlags, StrWriter};
189/// use const_format::{impl_fmt, try_, writec};
190///
191/// const fn write_int(int: u32, buffer: &mut [u8]) -> Result<usize, Error> {
192///     let mut len = 0;
193///     let mut f = Formatter::from_custom_cleared(buffer, &mut len, FormattingFlags::NEW);
194///     try_!(writec!(f, "{0},{0:x},{0:b}", int));
195///     Ok(len)
196/// }
197///
198/// let mut buffer = [0;64];
199///
200/// let written = write_int(17, &mut buffer).unwrap();
201///
202/// let string = std::str::from_utf8(&buffer[..written])
203///     .expect("Formatter only writes valid UTF8");
204///
205/// assert_eq!(string, "17,11,10001");
206///
207/// ```
208///
209///
210/// [`DebugStruct`]: crate::fmt::DebugStruct
211/// [`DebugTuple`]: crate::fmt::DebugTuple
212/// [`StrWriter`]: crate::fmt::StrWriter
213/// [`StrWriterMut`]: crate::fmt::StrWriterMut
214/// [`ComputeStrLength`]: crate::fmt::ComputeStrLength
215/// [`from_sw`]: #method.from_sw
216/// [`from_sw_mut`]: #method.from_sw_mut
217/// [`from_custom_cleared`]: #method.from_custom_cleared
218/// [`from_custom`]:  #method.from_custom
219/// [`NumberFormatting`]: crate::fmt::NumberFormatting
220/// [`FormattingFlags`]: crate::fmt::FormattingFlags
221///
222pub struct Formatter<'w> {
223    margin: u16,
224    flags: FormattingFlags,
225    writer: WriterBackend<'w>,
226}
227
228const MARGIN_STEP: u16 = 4;
229
230impl<'w> Formatter<'w> {
231    /// Constructs a `Formatter`.
232    ///
233    /// # Example
234    ///
235    /// ```rust
236    ///
237    /// use const_format::{Error, Formatter, FormattingFlags, StrWriter};
238    /// use const_format::try_;
239    ///
240    /// const fn inner(mut f: Formatter<'_>) -> Result<(), Error> {
241    ///     try_!(f.write_str_range("ABCDEF", 2..4));
242    ///     try_!(f.write_str(" N"));
243    ///     try_!(f.write_ascii_repeated(b'o', 10));
244    ///     Ok(())
245    /// }
246    ///
247    /// // We have to coerce `&mut StrWriter<[u8; 128]>` to `&mut StrWriter` to call the
248    /// // `as_str` method.
249    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 128]);
250    /// inner(Formatter::from_sw(writer, FormattingFlags::NEW)).unwrap();
251    ///
252    /// assert_eq!(writer.as_str(), "CD Noooooooooo");
253    ///
254    /// ```
255    #[inline]
256    pub const fn from_sw(writer: &'w mut StrWriter, flags: FormattingFlags) -> Self {
257        Self {
258            margin: 0,
259            flags,
260            // safety:
261            // Formatter only writes valid utf8, which is valid for both
262            // encoding type parameters that StrWriterMut can have(Utf8Encoding / NoEncoding).
263            writer: WriterBackend::Str(unsafe { writer.as_mut().into_byte_encoding() }),
264        }
265    }
266
267    /// Constructs a `Formatter`.
268    ///
269    /// # Example
270    ///
271    /// ```rust
272    ///
273    /// use const_format::{Error, Formatter, FormattingFlags, StrWriterMut};
274    /// use const_format::try_;
275    ///
276    /// const fn inner(mut f: Formatter<'_>) -> Result<(), Error> {
277    ///     try_!(f.write_str_range("DVDVDVD", 2..5));
278    ///     try_!(f.write_str(" N"));
279    ///     try_!(f.write_ascii_repeated(b'o', 10));
280    ///     Ok(())
281    /// }
282    ///
283    /// let mut len = 0;
284    /// let mut buffer = [0; 128];
285    ///
286    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
287    ///
288    /// // We need to call `.reborrow()`, because otherwise the `StrWriterMut` is moved.
289    /// inner(Formatter::from_sw_mut(writer.reborrow(), FormattingFlags::NEW)).unwrap();
290    ///
291    /// assert_eq!(writer.as_str(), "DVD Noooooooooo");
292    ///
293    /// ```
294    #[inline]
295    pub const fn from_sw_mut<E: 'static>(
296        writer: StrWriterMut<'w, E>,
297        flags: FormattingFlags,
298    ) -> Self {
299        Self {
300            margin: 0,
301            flags,
302            // safety:
303            // Formatter only writes valid utf8, which is valid for both
304            // encoding type parameters that StrWriterMut can have(Utf8Encoding / NoEncoding).
305            writer: WriterBackend::Str(unsafe { writer.into_byte_encoding() }),
306        }
307    }
308
309    /// Construct a `Formatter` from a byte slice.
310    ///
311    /// `Formatter` only writes utf8, which means that if `&buffer[..length]` is valid utf8,
312    /// then `buffer` will continue to be `utf8` after being written by the `Formatter`.
313    ///
314    /// # Example
315    ///
316    /// This example demonstrates how you can use a Formatter to write to a byte slice
317    /// that had some text written to it already.
318    ///
319    /// ```rust
320    ///
321    /// use const_format::{Error, Formatter, FormattingFlags, StrWriter};
322    /// use const_format::{impl_fmt, try_, writec};
323    ///
324    /// ///
325    /// /// # Safety
326    /// ///
327    /// /// `&buffer[..start]` must be valid utf8.
328    /// const fn write_int(
329    ///     int: u32,
330    ///     buffer: &mut [u8],
331    ///     start: usize,
332    /// ) -> Result<usize, Error> {
333    ///     let mut len = start;
334    ///     let mut f = Formatter::from_custom(buffer, &mut len, FormattingFlags::NEW);
335    ///     try_!(writec!(f, "{0},{0:x},{0:b}", int));
336    ///     Ok(len)
337    /// }
338    ///
339    /// let start_str = "The number is ";
340    /// let mut buffer = [0;64];
341    /// buffer[..start_str.len()].copy_from_slice(start_str.as_bytes());
342    ///
343    /// let new_len = write_int(20, &mut buffer, start_str.len()).unwrap();
344    ///
345    /// let string = std::str::from_utf8(&buffer[..new_len])
346    ///     .expect("Formatter only writes valid UTF8");
347    ///
348    /// assert_eq!(string, "The number is 20,14,10100");
349    ///
350    /// ```
351    #[inline]
352    pub const fn from_custom(
353        buffer: &'w mut [u8],
354        length: &'w mut usize,
355        flags: FormattingFlags,
356    ) -> Self {
357        Self {
358            margin: 0,
359            flags,
360            writer: WriterBackend::Str(StrWriterMut::from_custom(buffer, length)),
361        }
362    }
363
364    /// Construct a `Formatter`from a byte slice.
365    ///
366    /// # Example
367    ///
368    /// For an example of using this method you can look at
369    /// [the type level docs](#write_array_example)
370    ///
371    #[inline]
372    pub const fn from_custom_cleared(
373        buffer: &'w mut [u8],
374        length: &'w mut usize,
375        flags: FormattingFlags,
376    ) -> Self {
377        *length = 0;
378        Self {
379            margin: 0,
380            flags,
381            writer: WriterBackend::Str(StrWriterMut::from_custom(buffer, length)),
382        }
383    }
384
385    /// Gets the formatting flags associated with this `Formatter`.
386    #[inline(always)]
387    pub const fn flags(&self) -> FormattingFlags {
388        self.flags
389    }
390
391    /// Gets how much indentation a data structure is printed with.
392    pub const fn margin(&self) -> usize {
393        self.margin as usize
394    }
395
396    #[inline(always)]
397    const fn increment_margin(&mut self) -> &mut Self {
398        self.margin += 4;
399        self
400    }
401
402    #[inline(always)]
403    const fn decrement_margin(&mut self) {
404        self.margin -= 4;
405    }
406}
407
408impl<'w> Formatter<'w> {
409    /// For borrowing this mutably in macros,just takes and returns a `&mut Self`.
410    #[inline(always)]
411    pub const fn borrow_mutably(&mut self) -> &mut Self {
412        self
413    }
414
415    /// Constructs a reborrow of this formatter, using `flags` as the formatting flags.
416    ///
417    /// The return value inherits the margin from this Formatter.
418    ///
419    /// This method exists because the [`writec`] macro gets a formatter from any writer
420    /// by calling a `make_formatter` method.
421    ///
422    /// # Example
423    ///
424    /// This example demonstrates how you can change the flags when writing a field.
425    ///
426    /// ```rust
427    ///
428    /// use const_format::{Error, Formatter, PWrapper};
429    /// use const_format::{coerce_to_fmt, formatc, impl_fmt, try_};
430    ///
431    /// use std::ops::RangeInclusive;
432    ///
433    /// struct Foo{
434    ///     x: u32,
435    ///     y: RangeInclusive<usize>,
436    ///     z: u32,
437    /// }
438    ///
439    /// impl_fmt!{
440    ///     impl Foo;
441    ///
442    ///     pub const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
443    ///         let mut f = f.debug_struct("Foo");
444    ///         try_!(PWrapper(self.x).const_debug_fmt(f.field("x")));
445    ///         
446    ///         let mut fmt_y = f.field("y");
447    ///         let flags = fmt_y.flags().set_binary();
448    ///         try_!(coerce_to_fmt!(&self.y).const_debug_fmt(&mut fmt_y.make_formatter(flags)));
449    ///
450    ///         try_!(PWrapper(self.z).const_debug_fmt(f.field("z")));
451    ///         f.finish()
452    ///     }
453    /// }
454    ///
455    /// const FOO: Foo = Foo {
456    ///     x: 15,
457    ///     y: 16..=31,
458    ///     z: 32,
459    /// };
460    /// const S: &str = formatc!("{FOO:#?}");
461    ///
462    /// const EXPECTED: &str = "\
463    /// Foo {
464    ///     x: 15,
465    ///     y: 0b10000..=0b11111,
466    ///     z: 32,
467    /// }\
468    /// ";
469    ///
470    /// assert_eq!(S, EXPECTED);
471    /// ```
472    ///
473    /// [`writec`]: ../macro.writec.html
474    ///
475    pub const fn make_formatter(&mut self, flags: FormattingFlags) -> Formatter<'_> {
476        Formatter {
477            margin: self.margin,
478            flags,
479            writer: match &mut self.writer {
480                WriterBackend::Str(x) => WriterBackend::Str(x.reborrow()),
481                WriterBackend::Length(x) => WriterBackend::Length(x),
482            },
483        }
484    }
485
486    /// For debug writing a braced struct, or braced variant,
487    /// taking its name as a parameter
488    ///
489    /// # Examples
490    ///
491    /// For examples of using this method, you can look at the docs for [`DebugStruct`]
492    ///
493    /// [`DebugStruct`]: ./struct.DebugStruct.html
494    ///
495    #[inline]
496    pub const fn debug_struct(&mut self, name: &str) -> DebugStruct<'_, 'w> {
497        let err = self.write_str(name);
498        DebugStruct {
499            fmt: self.increment_margin(),
500            wrote_field: false,
501            err,
502        }
503    }
504
505    /// For debug writing a tuple struct, or tuple variant,taking its name as a parameter
506    ///
507    /// # Examples
508    ///
509    /// For examples of using this method, you can look at the docs for [`DebugTuple`]
510    ///
511    /// [`DebugTuple`]: ./struct.DebugTuple.html
512    ///
513    #[inline]
514    pub const fn debug_tuple(&mut self, name: &str) -> DebugTuple<'_, 'w> {
515        let err = self.write_str(name);
516        DebugTuple {
517            fmt: self.increment_margin(),
518            wrote_field: false,
519            err,
520        }
521    }
522
523    /// For debug writing a list/array.
524    ///
525    /// # Examples
526    ///
527    /// For examples of using this method, you can look at the docs for [`DebugList`]
528    ///
529    /// [`DebugList`]: ./struct.DebugList.html
530    ///
531    #[inline]
532    pub const fn debug_list(&mut self) -> DebugList<'_, 'w> {
533        DebugList {
534            fmt: self.increment_margin(),
535            wrote_field: false,
536            err: Ok(()),
537        }
538    }
539
540    /// For debug writing a set.
541    ///
542    /// # Examples
543    ///
544    /// For examples of using this method, you can look at the docs for [`DebugSet`]
545    ///
546    /// [`DebugSet`]: ./struct.DebugSet.html
547    ///
548    #[inline]
549    pub const fn debug_set(&mut self) -> DebugSet<'_, 'w> {
550        DebugSet {
551            fmt: self.increment_margin(),
552            wrote_field: false,
553            err: Ok(()),
554        }
555    }
556}
557
558////////////////////////////////////////////////////////////////////////////////
559
560macro_rules! trys {
561    ($e:expr,$self:ident) => {
562        if let result @ Err(_) = $e {
563            $self.err = result;
564        }
565    };
566}
567
568const COLON_SPACE_LEN: usize = ": ".len();
569const COMMA_SPACE_LEN: usize = ", ".len();
570const COMMA_NL_LEN: usize = ",\n".len();
571
572macro_rules! field_method_impl {
573    ($
574        self: ident, $open_space:expr, $open_newline:expr;
575        len(|$fmt_len:ident| $($write_name_len:tt)*)
576        fmt(|$writer:ident| $($write_name_fmt:tt)*)
577    ) => ({
578        match &mut $self.fmt.writer {
579            WriterBackend::Length($fmt_len)=>{
580                let $fmt_len = &mut **$fmt_len;
581
582                const OPEN_SPACE: usize = $open_space.len();
583                const OPEN_NEWLINE: usize = $open_newline.len();
584
585                let is_alternate = $self.fmt.flags.is_alternate();
586                $fmt_len.add_len(match ($self.wrote_field, is_alternate) {
587                    (false, false) => OPEN_SPACE,
588                    (false, true) => OPEN_NEWLINE + $self.fmt.margin as usize,
589                    (true , false) => COMMA_SPACE_LEN,
590                    (true , true) => COMMA_NL_LEN + $self.fmt.margin as usize,
591                });
592                $($write_name_len)*
593            }
594            WriterBackend::Str($writer)=>{
595                let $writer = &mut *$writer;
596
597                let is_alternate = $self.fmt.flags.is_alternate();
598                let sep = match ($self.wrote_field, is_alternate) {
599                    (false, false)=>$open_space,
600                    (false, true)=>$open_newline,
601                    (true, false)=>", ",
602                    (true, true)=>",\n",
603                };
604                trys!($writer.write_str(sep), $self);
605                if is_alternate {
606                    trys!($writer.write_ascii_repeated(b' ', $self.fmt.margin as usize), $self);
607                }
608                $($write_name_fmt)*
609            }
610        }
611        $self.wrote_field = true;
612
613        $self.fmt
614    })
615}
616
617macro_rules! finish_method_impl {
618    ($self: ident, $close_token:expr, $space_close:expr) => {{
619        if let result @ Err(_) = $self.err {
620            return result;
621        }
622
623        $self.fmt.decrement_margin();
624        if $self.wrote_field {
625            match &mut $self.fmt.writer {
626                WriterBackend::Length(fmt_len) => {
627                    let fmt_len = &mut **fmt_len;
628
629                    const CLOSE_TOKEN: usize = $close_token.len();
630                    const SPACE_CLOSE: usize = $space_close.len();
631
632                    if $self.fmt.flags.is_alternate() {
633                        fmt_len.add_len(COMMA_NL_LEN + $self.fmt.margin as usize + CLOSE_TOKEN);
634                    } else {
635                        fmt_len.add_len(SPACE_CLOSE);
636                    }
637                    Ok(())
638                }
639                WriterBackend::Str(writer) => {
640                    let writer = &mut *writer;
641
642                    if $self.fmt.flags.is_alternate() {
643                        try_!(writer.write_str(",\n"));
644                        try_!(writer.write_ascii_repeated(b' ', $self.fmt.margin as usize));
645                        writer.write_str($close_token)
646                    } else {
647                        writer.write_str($space_close)
648                    }
649                }
650            }
651        } else {
652            Ok(())
653        }
654    }};
655}
656
657////////////////////////////////////////////////////////////////////////////////
658
659/// A helper struct for debug formatting a braced struct, or braced variant.
660///
661/// # Example
662///
663/// This example demonstrates how you can debug format a struct,
664/// and a braced variant.
665///
666/// ```rust
667///
668/// use const_format::{Error, Formatter};
669/// use const_format::{call_debug_fmt, coerce_to_fmt, formatc, impl_fmt, try_};
670///
671/// fn main() {
672///     const STRUC: &str = formatc!("{:?}", Foo { a: 5, b: [8, 13, 21], c: "34" });
673///     const ENUM_: &str = formatc!("{:?}", Bar::Baz { d: false, e: None });
674///     
675///     assert_eq!(STRUC, "Foo { a: 5, b: [8, 13, 21], c: \"34\" }");
676///     assert_eq!(ENUM_, "Baz { d: false, e: None }");
677/// }
678///
679/// struct Foo{
680///     a: u32,
681///     b: [u32; 3],
682///     c: &'static str,
683/// }
684///
685/// enum Bar {
686///     Baz{
687///         d: bool,
688///         e: Option<bool>,
689///     }
690/// }
691///
692/// impl_fmt!{
693///     impl Foo;
694///     
695///     const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
696///         let mut f = f.debug_struct("Foo");
697///         try_!(coerce_to_fmt!(&self.a).const_debug_fmt(f.field("a")));
698///         try_!(coerce_to_fmt!(&self.b).const_debug_fmt(f.field("b")));
699///         try_!(coerce_to_fmt!(&self.c).const_debug_fmt(f.field("c")));
700///         f.finish()
701///     }
702/// }
703///
704/// impl_fmt!{
705///     impl Bar;
706///     
707///     const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
708///         match self {
709///             Bar::Baz{d, e} => {
710///                 let mut f = f.debug_struct("Baz");
711///                 
712///                 // This macro allows debug formatting some generic types that
713///                 // don't have a const_debug_fmt fn, like Options which wrap non-std types.
714///                 call_debug_fmt!(std, d, f.field("d"));
715///                 call_debug_fmt!(Option, e, f.field("e"));
716///                 
717///                 f.finish()
718///             }
719///         }
720///     }
721/// }
722///
723///
724///
725/// ```
726pub struct DebugStruct<'f, 'w> {
727    fmt: &'f mut Formatter<'w>,
728    wrote_field: bool,
729    err: Result<(), Error>,
730}
731
732impl<'f, 'w> DebugStruct<'f, 'w> {
733    /// Adds a field to the formatted output.
734    pub const fn field(&mut self, name: &str) -> &mut Formatter<'w> {
735        field_method_impl!(
736            self, " { ", " {\n";
737            len(|fmt_len|
738                fmt_len.add_len(name.len() + COLON_SPACE_LEN);
739            )
740            fmt(|writer|
741                trys!(writer.write_str(name), self);
742                trys!(writer.write_str(": "), self);
743            )
744        )
745    }
746
747    /// Finishes writing the struct/variant,
748    /// and if anything went wrong in the `field` method,returns an error.
749    pub const fn finish(self) -> Result<(), Error> {
750        finish_method_impl!(self, "}", " }")
751    }
752}
753
754////////////////////////////////////////////////////////////////////////////////
755
756/// For debug formatting a tuple struct, or tuple variant.
757///
758/// # Example
759///
760/// This example demonstrates how you can debug format a tuple struct,
761/// and an enum of tuple variants.
762///
763/// ```rust
764///
765/// use const_format::{Error, Formatter};
766/// use const_format::{call_debug_fmt, coerce_to_fmt, formatc, impl_fmt, try_};
767///
768/// fn main() {
769///     const STRUC: &str = formatc!("{:?}", Foo(5, [8, 13, 21], "34"));
770///     const ENUM_: &str = formatc!("{:?}", Bar::Baz(false, None));
771///     
772///     assert_eq!(STRUC, "Foo(5, [8, 13, 21], \"34\")");
773///     assert_eq!(ENUM_, "Baz(false, None)");
774/// }
775///
776/// struct Foo(u32, [u32; 3], &'static str);
777///
778/// enum Bar {
779///     Baz(bool, Option<bool>),
780/// }
781///
782/// impl_fmt!{
783///     impl Foo;
784///     
785///     const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
786///         let mut f = f.debug_tuple("Foo");
787///         try_!(coerce_to_fmt!(&self.0).const_debug_fmt(f.field()));
788///         try_!(coerce_to_fmt!(&self.1).const_debug_fmt(f.field()));
789///         try_!(coerce_to_fmt!(&self.2).const_debug_fmt(f.field()));
790///         f.finish()
791///     }
792/// }
793///
794/// impl_fmt!{
795///     impl Bar;
796///     
797///     const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
798///         match self {
799///             Bar::Baz(f0, f1) => {
800///                 let mut f = f.debug_tuple("Baz");
801///                 
802///                 // This macro allows debug formatting some generic types that
803///                 // don't have a const_debug_fmt fn, like Options which wrap non-std types.
804///                 call_debug_fmt!(std, f0, f.field());
805///                 call_debug_fmt!(Option, f1, f.field());
806///                 
807///                 f.finish()
808///             }
809///         }
810///     }
811/// }
812///
813///
814///
815/// ```
816pub struct DebugTuple<'f, 'w> {
817    fmt: &'f mut Formatter<'w>,
818    wrote_field: bool,
819    err: Result<(), Error>,
820}
821
822impl<'f, 'w> DebugTuple<'f, 'w> {
823    /// Adds a field to the formatted output.
824    pub const fn field(&mut self) -> &mut Formatter<'w> {
825        field_method_impl!(self, "(", "(\n"; len(|fmt_len|) fmt(|writer|) )
826    }
827
828    /// Finishes writing the tuple struct/variant,
829    /// and if anything went wrong in the `field` method,returns an error.
830    pub const fn finish(self) -> Result<(), Error> {
831        finish_method_impl!(self, ")", ")")
832    }
833}
834
835////////////////////////////////////////////////////////////////////////////////
836
837macro_rules! finish_listset_method_impl {
838    ($self: ident, $close_token:expr, $open_close:expr) => {{
839        if let result @ Err(_) = $self.err {
840            return result;
841        }
842
843        match &mut $self.fmt.writer {
844            WriterBackend::Length(fmt_len) => {
845                let fmt_len = &mut **fmt_len;
846                const CLOSE_TOKEN: usize = $close_token.len();
847                const OPEN_CLOSE: usize = $open_close.len();
848
849                $self.fmt.margin -= MARGIN_STEP;
850                if $self.wrote_field {
851                    if $self.fmt.flags.is_alternate() {
852                        fmt_len.add_len(COMMA_NL_LEN + $self.fmt.margin as usize);
853                    }
854                    fmt_len.add_len(CLOSE_TOKEN);
855                } else {
856                    fmt_len.add_len(OPEN_CLOSE);
857                }
858                Ok(())
859            }
860            WriterBackend::Str(writer) => {
861                let writer = &mut *writer;
862
863                $self.fmt.margin -= MARGIN_STEP;
864                let margin = $self.fmt.margin as usize;
865                if $self.wrote_field {
866                    if $self.fmt.flags.is_alternate() {
867                        try_!(writer.write_str(",\n"));
868                        try_!(writer.write_ascii_repeated(b' ', margin));
869                    }
870                    writer.write_str($close_token)
871                } else {
872                    writer.write_str($open_close)
873                }
874            }
875        }
876    }};
877}
878
879////////////////////////////////////////////////////////////////////////////////
880
881/// For debug formatting a list/array.
882///
883/// # Example
884///
885/// This example demonstrates how you can debug format a custom type as a list.
886///
887/// ```rust
888///
889/// use const_format::{Error, Formatter};
890/// use const_format::{formatc, impl_fmt, try_};
891///
892/// use std::ops::Range;
893///
894/// fn main() {
895///     const LIST: &str = formatc!("{:?}", RangeList(0..5));
896///     
897///     assert_eq!(LIST, "[0, 1, 2, 3, 4]");
898/// }
899///
900/// struct RangeList(Range<usize>);
901///
902/// impl_fmt!{
903///     impl RangeList;
904///     
905///     const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
906///         let mut f = f.debug_list();
907///         let mut i = self.0.start;
908///         while i < self.0.end {
909///             try_!(f.entry().write_usize_display(i));
910///             i+=1;
911///         }
912///         f.finish()
913///     }
914/// }
915///
916/// ```
917///
918pub struct DebugList<'f, 'w> {
919    fmt: &'f mut Formatter<'w>,
920    wrote_field: bool,
921    err: Result<(), Error>,
922}
923
924impl<'f, 'w> DebugList<'f, 'w> {
925    /// Adds a list entry to the formatted output
926    pub const fn entry(&mut self) -> &mut Formatter<'w> {
927        field_method_impl!(self, "[", "[\n"; len(|fmt_len|) fmt(|writer|) )
928    }
929
930    /// Finishes writing the list,
931    /// and if anything went wrong in the `entry` method,returns an error.
932    pub const fn finish(self) -> Result<(), Error> {
933        finish_listset_method_impl!(self, "]", "[]")
934    }
935}
936
937////////////////////////////////////////////////////////////////////////////////
938
939/// For debug formatting a set.
940///
941/// # Example
942///
943/// This example demonstrates how you can debug format a custom type as a set.
944///
945/// ```rust
946///
947/// use const_format::{Error, Formatter};
948/// use const_format::{formatc, impl_fmt, try_};
949///
950/// use std::ops::Range;
951///
952/// fn main() {
953///     const SET: &str = formatc!("{:?}", StrSet(&["foo", "bar", "baz"]));
954///     
955///     assert_eq!(SET, r#"{"foo", "bar", "baz"}"#);
956/// }
957///
958/// struct StrSet(&'static [&'static str]);
959///
960/// impl_fmt!{
961///     impl StrSet;
962///     
963///     const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
964///         let mut f = f.debug_set();
965///         let mut i = 0;
966///         while i < self.0.len() {
967///             try_!(f.entry().write_str_debug(self.0[i]));
968///             i+=1;
969///         }
970///         f.finish()
971///     }
972/// }
973///
974/// ```
975///
976pub struct DebugSet<'f, 'w> {
977    fmt: &'f mut Formatter<'w>,
978    wrote_field: bool,
979    err: Result<(), Error>,
980}
981
982impl<'f, 'w> DebugSet<'f, 'w> {
983    /// Adds a set entry to the formatted output
984    pub const fn entry(&mut self) -> &mut Formatter<'w> {
985        field_method_impl!(self, "{", "{\n"; len(|fmt_len|) fmt(|writer|) )
986    }
987
988    /// Finishes writing the set,
989    /// and if anything went wrong in the `entry` method,returns an error.
990    pub const fn finish(self) -> Result<(), Error> {
991        finish_listset_method_impl!(self, "}", "{}")
992    }
993}
994
995////////////////////////////////////////////////////////////////////////////////
996
997macro_rules! delegate_write_methods {
998    (
999        shared_attrs $shared_attrs:tt
1000        $(
1001            $(#[$attrs:meta])*
1002            fn $method:ident($($arg:ident: $arg_ty:ty ),* $(,)* )
1003            length = $len:expr;
1004        )*
1005    ) => (
1006        impl Formatter<'_>{
1007            $(
1008                delegate_write_methods!{
1009                    @inner
1010                    shared_attrs $shared_attrs
1011                    $(#[$attrs])*
1012                    fn $method($($arg: $arg_ty ),* )
1013                    length = $len;
1014                }
1015            )*
1016        }
1017    );
1018    (
1019        @inner
1020        shared_attrs (
1021            $( #[$shared_attrs:meta] )*
1022        )
1023        $(#[$attrs:meta])*
1024        fn $method:ident($($arg:ident: $arg_ty:ty ),* $(,)* )
1025        length = $len:expr;
1026    ) => (
1027        $( #[$shared_attrs] )*
1028        $(#[$attrs])*
1029        pub const fn $method(&mut self, $($arg: $arg_ty ),*  ) -> Result<(), Error> {
1030            match &mut self.writer {
1031                WriterBackend::Length(fmt_len)=>{
1032                    fmt_len.add_len($len);
1033                    Ok(())
1034                }
1035                WriterBackend::Str(writer)=>{
1036                    writer.$method($($arg,)*)
1037                }
1038            }
1039        }
1040    )
1041}
1042
1043delegate_write_methods! {
1044    shared_attrs()
1045
1046    /// Writes `&string[range]` into this Formatter.
1047    ///
1048    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
1049    ///
1050    /// # Example
1051    ///
1052    /// ```rust
1053    ///
1054    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1055    ///
1056    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1057    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1058    ///
1059    /// let _ = fmt.write_str_range("FOO BAR BAZ", 4..7);
1060    ///
1061    /// assert_eq!(writer.as_str(), "BAR");
1062    ///
1063    /// ```
1064    ///
1065    fn write_str_range(string: &str, range: Range<usize>)
1066    length = calculate_display_len(string.as_bytes(), &range);
1067
1068    /// Writes `string` into this Formatter.
1069    ///
1070    /// # Example
1071    ///
1072    /// ```rust
1073    ///
1074    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1075    ///
1076    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1077    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1078    ///
1079    /// let _ = fmt.write_str("FOO BAR BAZ");
1080    ///
1081    /// assert_eq!(writer.as_str(), "FOO BAR BAZ");
1082    ///
1083    /// ```
1084    ///
1085    fn write_str(string: &str)
1086    length = string.len();
1087
1088    /// Writes `character` into this Formatter.
1089    ///
1090    /// # Example
1091    ///
1092    /// ```rust
1093    ///
1094    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1095    ///
1096    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 4]);
1097    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1098    ///
1099    /// let _ = fmt.write_char('a');
1100    /// let _ = fmt.write_char('b');
1101    /// let _ = fmt.write_char('c');
1102    ///
1103    /// assert_eq!(writer.as_str(), "abc");
1104    ///
1105    /// ```
1106    ///
1107    fn write_char(character: char)
1108    length = crate::char_encoding::char_display_len(character);
1109
1110    /// Writes `&ascii[range]` into this formatter.
1111    ///
1112    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
1113    ///
1114    /// # Example
1115    ///
1116    /// ```rust
1117    ///
1118    /// use const_format::{Formatter, FormattingFlags, StrWriter, ascii_str};
1119    ///
1120    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1121    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1122    ///
1123    /// let _ = fmt.write_ascii_range(ascii_str!("FOO BAR BAZ"), 4..7);
1124    ///
1125    /// assert_eq!(writer.as_str(), "BAR");
1126    ///
1127    /// ```
1128    ///
1129    fn write_ascii_range(ascii: AsciiStr<'_>, range: Range<usize>)
1130    length = calculate_display_len(ascii.as_bytes(), &range);
1131
1132    /// Writes `ascii` into this formatter.
1133    ///
1134    /// # Example
1135    ///
1136    /// ```rust
1137    ///
1138    /// use const_format::{Formatter, FormattingFlags, StrWriter, ascii_str};
1139    ///
1140    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1141    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1142    ///
1143    /// let _ = fmt.write_ascii(ascii_str!("FOO BAR BAZ"));
1144    ///
1145    /// assert_eq!(writer.as_str(), "FOO BAR BAZ");
1146    ///
1147    /// ```
1148    ///
1149    fn write_ascii(ascii: AsciiStr<'_>)
1150    length = ascii.len();
1151
1152    /// Writes the ascii `character` into this formatter `repeated` times.
1153    ///
1154    /// If `character` is greater than 127,
1155    /// this writes `character - 128` as an ascii character.
1156    ///
1157    /// # Example
1158    ///
1159    /// ```rust
1160    ///
1161    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1162    ///
1163    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1164    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1165    ///
1166    /// let _ = fmt.write_ascii_repeated(b'A', 10);
1167    ///
1168    /// assert_eq!(writer.as_str(), "AAAAAAAAAA");
1169    ///
1170    /// ```
1171    ///
1172    fn write_ascii_repeated(character: u8,repeated: usize)
1173    length = repeated;
1174
1175    /// Writes `string` into this formatter, with debug formatting.
1176    ///
1177    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
1178    ///
1179    /// # Example
1180    ///
1181    /// ```rust
1182    ///
1183    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1184    ///
1185    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1186    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1187    ///
1188    /// let _ = fmt.write_str_range_debug("FOO\nBAR\tBAZ", 3..8);
1189    ///
1190    /// assert_eq!(writer.as_str(), r#""\nBAR\t""#);
1191    ///
1192    /// ```
1193    ///
1194    fn write_str_range_debug(string: &str, range: Range<usize>)
1195    length = calculate_display_len_debug_range(string.as_bytes(), &range);
1196
1197    /// Writes `string` into this formatter, with debug formatting.
1198    ///
1199    /// # Example
1200    ///
1201    /// ```rust
1202    ///
1203    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1204    ///
1205    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1206    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1207    ///
1208    /// let _ = fmt.write_str_debug("FOO\nBAR\tBAZ");
1209    ///
1210    /// assert_eq!(writer.as_str(), r#""FOO\nBAR\tBAZ""#);
1211    ///
1212    /// ```
1213    ///
1214    fn write_str_debug(string: &str)
1215    length = PWrapper(string.as_bytes()).compute_utf8_debug_len();
1216
1217    /// Writes `character` into this Formatter, with debug formatting.
1218    ///
1219    /// # Example
1220    ///
1221    /// ```rust
1222    ///
1223    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1224    ///
1225    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 64]);
1226    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1227    ///
1228    /// let _ = fmt.write_str(" ");
1229    /// let _ = fmt.write_char_debug('\\');
1230    /// let _ = fmt.write_str(" ");
1231    /// let _ = fmt.write_char_debug('A');
1232    /// let _ = fmt.write_str(" ");
1233    /// let _ = fmt.write_char_debug('0');
1234    /// let _ = fmt.write_str(" ");
1235    /// let _ = fmt.write_char_debug('\'');
1236    /// let _ = fmt.write_str(" ");
1237    ///
1238    /// assert_eq!(writer.as_str(), r#" '\\' 'A' '0' '\'' "#);
1239    ///
1240    /// ```
1241    ///
1242    fn write_char_debug(character: char)
1243    length = crate::char_encoding::char_debug_len(character);
1244
1245    /// Writes `&ascii[range]` into this formatter, with debug formatting.
1246    ///
1247    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
1248    ///
1249    /// # Example
1250    ///
1251    /// ```rust
1252    ///
1253    /// use const_format::{Formatter, FormattingFlags, StrWriter, ascii_str};
1254    ///
1255    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1256    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1257    ///
1258    /// let _ = fmt.write_ascii_range_debug(ascii_str!("FOO\nBAR\tBAZ"), 3..8);
1259    ///
1260    /// assert_eq!(writer.as_str(), r#""\nBAR\t""#);
1261    ///
1262    /// ```
1263    ///
1264    fn write_ascii_range_debug(ascii: AsciiStr<'_>,range: Range<usize>)
1265    length = calculate_display_len_debug_range(ascii.as_bytes(), &range);
1266
1267    /// Writes `ascii` into this formatter, with debug formatting.
1268    ///
1269    /// # Example
1270    ///
1271    /// ```rust
1272    ///
1273    /// use const_format::{Formatter, FormattingFlags, StrWriter, ascii_str};
1274    ///
1275    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1276    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1277    ///
1278    /// let _ = fmt.write_ascii_debug(ascii_str!("FOO\nBAR\tBAZ"));
1279    ///
1280    /// assert_eq!(writer.as_str(), r#""FOO\nBAR\tBAZ""#);
1281    ///
1282    /// ```
1283    ///
1284    fn write_ascii_debug(ascii: AsciiStr<'_>)
1285    length = PWrapper(ascii.as_bytes()).compute_utf8_debug_len();
1286
1287
1288    /// Write `n` with display formatting.
1289    ///
1290    /// # Example
1291    ///
1292    /// ```rust
1293    ///
1294    /// use const_format::{Formatter, FormattingFlags, StrWriter, ascii_str};
1295    ///
1296    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 16]);
1297    /// let mut fmt = writer.make_formatter(FormattingFlags::NEW);
1298    ///
1299    /// let _ = fmt.write_u8_display(13);
1300    /// let _ = fmt.write_u8_display(21);
1301    /// let _ = fmt.write_u8_display(34);
1302    ///
1303    /// assert_eq!(writer.as_str(), "132134");
1304    ///
1305    /// ```
1306    ///
1307    fn write_u8_display(n: u8)
1308    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1309}
1310
1311delegate_write_methods! {
1312    shared_attrs(
1313        /// Writes `n` with display formatting
1314        ///
1315        /// For an example,
1316        /// you can look at the one for the [`write_u8_display`] method.
1317        ///
1318        /// [`write_u8_display`]: #method.write_u8_display
1319    )
1320
1321    fn write_u16_display(n: u16)
1322    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1323
1324    fn write_u32_display(n: u32)
1325    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1326
1327    fn write_u64_display(n: u64)
1328    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1329
1330    fn write_u128_display(n: u128)
1331    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1332
1333    fn write_usize_display(n: usize)
1334    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1335
1336    fn write_i8_display(n: i8)
1337    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1338
1339    fn write_i16_display(n: i16)
1340    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1341
1342    fn write_i32_display(n: i32)
1343    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1344
1345    fn write_i64_display(n: i64)
1346    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1347
1348    fn write_i128_display(n: i128)
1349    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1350
1351    fn write_isize_display(n: isize)
1352    length = PWrapper(n).compute_display_len(FormattingFlags::NEW);
1353}
1354
1355macro_rules! delegate_integer_debug_methods {
1356    (
1357        shared_attrs $shared_attrs:tt
1358        $(
1359            $(#[$attrs:meta])*
1360            fn $method:ident($($arg:ident: $arg_ty:ty ),* $(,)* )
1361            length = |$flags:ident| $len:expr;
1362        )*
1363    ) => (
1364        impl Formatter<'_>{
1365            $(
1366                delegate_integer_debug_methods!{
1367                    @inner
1368                    shared_attrs $shared_attrs
1369                    $(#[$attrs])*
1370                    fn $method($($arg: $arg_ty ),*)
1371                    length = |$flags| $len;
1372                }
1373            )*
1374        }
1375    );
1376    (
1377        @inner
1378        shared_attrs (
1379            $( #[$shared_attrs:meta] )*
1380        )
1381        $(#[$attrs:meta])*
1382        fn $method:ident($($arg:ident: $arg_ty:ty ),* $(,)* )
1383        length = |$flags:ident| $len:expr;
1384    ) => (
1385        $( #[$shared_attrs] )*
1386        $(#[$attrs])*
1387        pub const fn $method(&mut self, $($arg: $arg_ty ),*  ) -> Result<(), Error> {
1388            let $flags = self.flags;
1389
1390            match &mut self.writer {
1391                WriterBackend::Length(fmt_len)=>{
1392                    fmt_len.add_len($len);
1393                    Ok(())
1394                }
1395                WriterBackend::Str(writer)=>{
1396                    writer.$method($($arg,)* $flags)
1397                }
1398            }
1399        }
1400    )
1401}
1402
1403delegate_integer_debug_methods! {
1404    shared_attrs()
1405
1406    /// Writes `n` with debug formatting.
1407    ///
1408    /// # Example
1409    ///
1410    /// ```rust
1411    ///
1412    /// use const_format::{Formatter, FormattingFlags, StrWriter};
1413    ///
1414    /// fn debug_fmt(writer: &mut StrWriter, flag: FormattingFlags) -> &str {
1415    ///     writer.clear();
1416    ///     let mut fmt = Formatter::from_sw(writer, flag);
1417    ///     let _ = fmt.write_u8_debug(63);
1418    ///     writer.as_str()
1419    /// }
1420    ///
1421    /// let reg_flag = FormattingFlags::NEW.set_alternate(false);
1422    /// let alt_flag = FormattingFlags::NEW.set_alternate(true);
1423    ///
1424    /// let writer: &mut StrWriter = &mut StrWriter::new([0; 64]);
1425    ///
1426    /// assert_eq!(debug_fmt(writer, reg_flag),                   "63"     );
1427    /// assert_eq!(debug_fmt(writer, reg_flag.set_hexadecimal()), "3F"     );
1428    /// assert_eq!(debug_fmt(writer, reg_flag.set_lower_hexadecimal()), "3f"     );
1429    /// assert_eq!(debug_fmt(writer, reg_flag.set_binary()),      "111111" );
1430    /// assert_eq!(debug_fmt(writer, alt_flag),                   "63"     );
1431    /// assert_eq!(debug_fmt(writer, alt_flag.set_hexadecimal()), "0x3F"   );
1432    /// assert_eq!(debug_fmt(writer, alt_flag.set_lower_hexadecimal()), "0x3f"   );
1433    /// assert_eq!(debug_fmt(writer, alt_flag.set_binary()),      "0b111111");
1434    ///
1435    /// ```
1436    ///
1437    fn write_u8_debug(n: u8)
1438    length = |flags| PWrapper(n).compute_debug_len(flags);
1439}
1440
1441delegate_integer_debug_methods! {
1442    shared_attrs(
1443        /// Writes `n` with debug formatting.
1444        ///
1445        /// For an example,
1446        /// you can look at the one for the [`write_u8_debug`] method.
1447        ///
1448        /// [`write_u8_debug`]: #method.write_u8_debug
1449    )
1450
1451    fn write_u16_debug(n: u16)
1452    length = |flags| PWrapper(n).compute_debug_len(flags);
1453
1454    fn write_u32_debug(n: u32)
1455    length = |flags| PWrapper(n).compute_debug_len(flags);
1456
1457    fn write_u64_debug(n: u64)
1458    length = |flags| PWrapper(n).compute_debug_len(flags);
1459
1460    fn write_u128_debug(n: u128)
1461    length = |flags| PWrapper(n).compute_debug_len(flags);
1462
1463    fn write_usize_debug(n: usize)
1464    length = |flags| PWrapper(n).compute_debug_len(flags);
1465
1466    fn write_i8_debug(n: i8)
1467    length = |flags| PWrapper(n).compute_debug_len(flags);
1468
1469    fn write_i16_debug(n: i16)
1470    length = |flags| PWrapper(n).compute_debug_len(flags);
1471
1472    fn write_i32_debug(n: i32)
1473    length = |flags| PWrapper(n).compute_debug_len(flags);
1474
1475    fn write_i64_debug(n: i64)
1476    length = |flags| PWrapper(n).compute_debug_len(flags);
1477
1478    fn write_i128_debug(n: i128)
1479    length = |flags| PWrapper(n).compute_debug_len(flags);
1480
1481    fn write_isize_debug(n: isize)
1482    length = |flags| PWrapper(n).compute_debug_len(flags);
1483}
1484
1485#[inline(always)]
1486const fn calculate_display_len(b: &[u8], range: &Range<usize>) -> usize {
1487    let Range { start, end } = saturate_range(b, range);
1488    end - start
1489}
1490
1491#[inline(always)]
1492const fn calculate_display_len_debug_range(b: &[u8], range: &Range<usize>) -> usize {
1493    let Range { start, end } = saturate_range(b, range);
1494    PWrapper(b).compute_utf8_debug_len_in_range(start..end)
1495}