const_format/fmt/
str_writer_mut.rs

1use crate::{
2    formatting::{
3        hex_as_ascii, ForEscaping, FormattingFlags, HexFormatting, NumberFormatting, FOR_ESCAPING,
4    },
5    utils::{min_usize, saturate_range, Constructor},
6    wrapper_types::{AsciiStr, PWrapper},
7};
8
9use super::{Error, Formatter, StrWriter};
10
11use core::{marker::PhantomData, ops::Range};
12
13/// For writing a formatted string into a `[u8]`.
14///
15/// # Construction
16///
17/// This type can be constructed in these ways:
18///
19/// - From a `&mut StrWriter`, with the [`StrWriter::as_mut`] method.
20///
21/// - From a `&mut StrWriter<_>`, with the [`StrWriterMut::new`] constructor.
22///
23/// - From a pair of `usize` and `[u8]` mutable references,
24/// with the [`from_custom_cleared`] constructor,
25/// or the [`from_custom`] constructor.
26///
27/// # Relation to `Formatter`
28///
29/// This is the type that [`Formatter`] uses to write formatted text to a slice,
30/// sharing all the `write_*` methods,
31/// the difference is that this doesn't store `FormattingFlags`,
32/// so you must pass them to the `write_*_debug` methods.
33///
34/// # Errors
35///
36/// Every single `write_*` method returns an [`Error::NotEnoughSpace`] if
37/// there is not enough space to write the argument, leaving the string itself unmodified.
38///
39/// # Encoding type parameter
40///
41/// The `E` type parameter represents the encoding of the buffer that this
42/// StrWriterMut writes into,
43/// currently only [`Utf8Encoding`] and [`NoEncoding`] are supported.
44///
45/// # Example
46///
47/// This example demonstrates how you can write a formatted string to a `&mut [u8]`,
48/// using a `StrWriterMut`.
49///
50/// ```rust
51///
52/// use const_format::{Error, StrWriterMut, try_, writec};
53///
54/// const fn format_number(number: u32,slice: &mut [u8]) -> Result<usize, Error> {
55///     let mut len = 0;
56///     let mut writer = StrWriterMut::from_custom_cleared(slice, &mut len);
57///     
58///     try_!(writec!(writer, "{0} in binary is {0:#b}", number));
59///
60///     Ok(len)
61/// }
62///
63/// let mut slice = [0; 32];
64///
65/// let len = format_number(100, &mut slice)?;
66///
67/// assert_eq!(&slice[..len], "100 in binary is 0b1100100".as_bytes());
68///
69/// # Ok::<(), const_format::Error>(())
70/// ```
71///
72/// [`from_custom_cleared`]: #method.from_custom_cleared
73/// [`from_custom`]: #method.from_custom
74///
75/// [`Utf8Encoding`]: crate::fmt::Utf8Encoding
76/// [`NoEncoding`]: crate::fmt::NoEncoding
77/// [`Formatter`]: crate::fmt::Formatter
78/// [`Error::NotEnoughSpace`]: crate::fmt::Error::NotEnoughSpace
79///
80pub struct StrWriterMut<'w, E = Utf8Encoding> {
81    pub(super) len: &'w mut usize,
82    pub(super) buffer: &'w mut [u8],
83    pub(super) _encoding: PhantomData<Constructor<E>>,
84}
85
86macro_rules! borrow_fields {
87    ($self:ident, $len:ident, $buffer:ident) => {
88        let $len = &mut *$self.len;
89        let $buffer = &mut *$self.buffer;
90    };
91}
92
93/// Marker type indicating that the [`StrWriterMut`] is valid utf8,
94/// enabling the `as_str` method.
95///
96/// [`StrWriterMut`]: ./struct.StrWriterMut.html
97pub enum Utf8Encoding {}
98
99/// Marker type indicating that the [`StrWriterMut`] is arbitrary bytes,
100/// disabling the `as_str` method.
101///
102/// [`StrWriterMut`]: ./struct.StrWriterMut.html
103pub enum NoEncoding {}
104
105impl<'w> StrWriterMut<'w, Utf8Encoding> {
106    /// Constructs a `StrWriterMut` from a mutable reference to a `StrWriter`
107    ///
108    /// # Example
109    ///
110    /// ```rust
111    /// use const_format::{StrWriter, StrWriterMut};
112    ///
113    /// let buffer: &mut StrWriter = &mut StrWriter::new([0; 128]);
114    /// {
115    ///     let mut writer = StrWriterMut::new(buffer);
116    ///
117    ///     let _ = writer.write_str("Number: ");
118    ///     let _ = writer.write_u8_display(1);
119    /// }
120    /// assert_eq!(buffer.as_str(), "Number: 1");
121    ///
122    /// ```
123    pub const fn new(writer: &'w mut StrWriter) -> Self {
124        Self {
125            len: &mut writer.len,
126            buffer: &mut writer.buffer,
127            _encoding: PhantomData,
128        }
129    }
130}
131
132impl<'w> StrWriterMut<'w, NoEncoding> {
133    /// Construct a `StrWriterMut` from length and byte slice mutable references.
134    ///
135    /// If `length > buffer.len()` is passed, it's simply assigned the length of the buffer.
136    ///
137    /// # Example
138    ///
139    /// ```rust
140    /// use const_format::StrWriterMut;
141    ///
142    /// let mut len = 6;
143    /// let mut buffer = *b"Hello,       ";
144    ///
145    /// let mut writer = StrWriterMut::from_custom(&mut buffer, &mut len);
146    ///
147    /// writer.write_str(" world!")?;
148    ///
149    /// assert_eq!(writer.as_bytes(), b"Hello, world!");
150    /// assert_eq!(buffer, "Hello, world!".as_bytes());
151    /// assert_eq!(len, "Hello, world!".len());
152    ///
153    /// # Ok::<(), const_format::Error>(())
154    /// ```
155    pub const fn from_custom(buffer: &'w mut [u8], length: &'w mut usize) -> Self {
156        *length = min_usize(*length, buffer.len());
157
158        Self {
159            len: length,
160            buffer,
161            _encoding: PhantomData,
162        }
163    }
164}
165
166impl<'w> StrWriterMut<'w, Utf8Encoding> {
167    /// Construct a `StrWriterMut` from length and byte slice mutable references,
168    /// truncating the length to `0`.
169    ///
170    /// Using this instead of [`from_custom`](StrWriterMut::from_custom) allows
171    /// safely casting this to a `&str` with [`as_str_alt`]/[`as_str`]
172    ///
173    ///
174    /// # Example
175    ///
176    /// ```rust
177    /// use const_format::StrWriterMut;
178    ///
179    /// let mut len = 0;
180    /// let mut buffer = [0; 13];
181    ///
182    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
183    ///
184    /// writer.write_str("Hello, world!")?;
185    ///
186    /// assert_eq!(writer.as_str(), "Hello, world!");
187    /// assert_eq!(buffer, "Hello, world!".as_bytes());
188    /// assert_eq!(len, "Hello, world!".len());
189    ///
190    /// # Ok::<(), const_format::Error>(())
191    /// ```
192    ///
193    /// [`as_str_alt`]: Self::as_str_alt
194    /// [`as_str`]: Self::as_str
195    ///
196    pub const fn from_custom_cleared(buffer: &'w mut [u8], length: &'w mut usize) -> Self {
197        *length = 0;
198
199        Self {
200            len: length,
201            buffer,
202            _encoding: PhantomData,
203        }
204    }
205}
206
207impl<'w, E> StrWriterMut<'w, E> {
208    /// Accesses the underlying buffer immutably.
209    ///
210    /// # Example
211    ///
212    /// ```rust
213    /// use const_format::{StrWriter, StrWriterMut};
214    ///
215    /// let mut buffer = StrWriter::new([0; 7]);
216    /// let mut writer = StrWriterMut::new(&mut buffer);
217    /// assert_eq!(writer.buffer(), &[0; 7]);
218    ///
219    /// writer.write_str("foo")?;
220    /// assert_eq!(writer.buffer(), b"foo\0\0\0\0");
221    ///
222    /// writer.write_str("bar")?;
223    /// assert_eq!(writer.buffer(), b"foobar\0");
224    ///
225    /// # Ok::<(), const_format::Error>(())
226    /// ```
227    #[inline(always)]
228    pub const fn buffer(&self) -> &[u8] {
229        self.buffer
230    }
231
232    /// The byte length of the string this is writing.
233    ///
234    /// # Example
235    ///
236    /// ```rust
237    /// use const_format::{StrWriter, StrWriterMut};
238    ///
239    /// let mut buffer = StrWriter::new([0; 64]);
240    /// let mut writer = StrWriterMut::new(&mut buffer);
241    ///
242    /// assert_eq!(writer.len(), 0);
243    ///
244    /// writer.write_str("foo")?;
245    /// assert_eq!(writer.len(), 3);
246    ///
247    /// writer.write_str("bar")?;
248    /// assert_eq!(writer.len(), 6);
249    ///
250    /// # Ok::<(), const_format::Error>(())
251    /// ```
252    #[inline(always)]
253    pub const fn len(&self) -> usize {
254        *self.len
255    }
256
257    /// Whether the string this is writing is empty.
258    ///
259    /// # Example
260    ///
261    /// ```rust
262    /// use const_format::{StrWriter, StrWriterMut};
263    ///
264    /// let mut buffer = StrWriter::new([0; 64]);
265    /// let mut writer = StrWriterMut::new(&mut buffer);
266    ///
267    /// assert!( writer.is_empty() );
268    ///
269    /// writer.write_str("foo")?;
270    /// assert!( !writer.is_empty() );
271    ///
272    /// # Ok::<(), const_format::Error>(())
273    /// ```
274    #[inline(always)]
275    pub const fn is_empty(&self) -> bool {
276        *self.len == 0
277    }
278
279    /// The maximum byte length of the formatted text for this `StrWriterMut`.
280    ///
281    /// # Example
282    ///
283    /// ```rust
284    /// use const_format::{Error, StrWriter, StrWriterMut};
285    ///
286    /// let mut buffer = StrWriter::new([0; 64]);
287    /// let mut writer = StrWriterMut::new(&mut buffer);
288    ///
289    /// assert_eq!(writer.capacity(), 64);
290    ///
291    /// writer.write_ascii_repeated(b'A', 64)?;
292    /// assert_eq!(writer.capacity(), 64);
293    ///
294    /// assert_eq!(writer.write_str("-").unwrap_err(), Error::NotEnoughSpace);
295    /// assert_eq!(writer.capacity(), 64);
296    ///
297    /// # Ok::<(), const_format::Error>(())
298    /// ```
299    #[inline(always)]
300    pub const fn capacity(&self) -> usize {
301        self.buffer.len()
302    }
303
304    /// Checks how many more bytes can be written.
305    ///
306    /// # Example
307    ///
308    /// ```rust
309    /// use const_format::{Error, StrWriter, StrWriterMut};
310    ///
311    /// let mut buffer = StrWriter::new([0; 64]);
312    /// let mut writer = StrWriterMut::new(&mut buffer);
313    ///
314    /// assert_eq!(writer.remaining_capacity(), 64);
315    ///
316    /// writer.write_str("foo")?;
317    /// assert_eq!(writer.remaining_capacity(), 61);
318    ///
319    /// writer.write_ascii_repeated(b'a', 61)?;
320    /// assert_eq!(writer.remaining_capacity(), 0);
321    ///
322    /// assert_eq!(writer.write_str(" ").unwrap_err(), Error::NotEnoughSpace);
323    ///
324    /// # Ok::<(), const_format::Error>(())
325    /// ```
326    #[inline]
327    pub const fn remaining_capacity(&self) -> usize {
328        self.buffer.len() - *self.len
329    }
330}
331
332impl<'w> StrWriterMut<'w, Utf8Encoding> {
333    /// Truncates this `StrWriterMut` to `length`.
334    ///
335    /// If `length` is greater than the current length, this does nothing.
336    ///
337    /// # Errors
338    ///
339    /// Returns an `Error::NotOnCharBoundary` if `length` is not on a char boundary.
340    ///
341    /// # Example
342    ///
343    /// ```rust
344    /// use const_format::{Error, StrWriter, StrWriterMut};
345    ///
346    /// let mut buffer = StrWriter::new([0; 64]);
347    /// let mut writer = StrWriterMut::new(&mut buffer);
348    ///
349    /// writer.write_str("foo bâr baz");
350    /// assert_eq!(writer.as_str(), "foo bâr baz");
351    ///
352    /// assert_eq!(writer.truncate(6).unwrap_err(), Error::NotOnCharBoundary);
353    ///
354    /// writer.truncate(3)?;
355    /// assert_eq!(writer.as_str(), "foo");
356    ///
357    /// writer.write_str("ooooooo");
358    /// assert_eq!(writer.as_str(), "fooooooooo");
359    ///
360    /// # Ok::<(), const_format::Error>(())
361    /// ```
362    #[inline]
363    pub const fn truncate(&mut self, length: usize) -> Result<(), Error> {
364        if length <= *self.len {
365            if !is_valid_str_index(self.buffer, length) {
366                return Err(Error::NotOnCharBoundary);
367            }
368
369            *self.len = length;
370        }
371        Ok(())
372    }
373}
374
375impl<'w> StrWriterMut<'w, NoEncoding> {
376    /// Truncates this `StrWriterMut<'w, NoEncoding>` to `length`.
377    ///
378    /// If `length` is greater than the current length, this does nothing.
379    ///
380    /// # Example
381    ///
382    /// ```rust
383    /// use const_format::{Error, StrWriter, StrWriterMut};
384    ///
385    /// let mut buffer = [0; 32];
386    /// let mut len = 0;
387    /// let mut writer = StrWriterMut::from_custom(&mut buffer, &mut len);
388    ///
389    /// writer.write_str("foo bar baz");
390    /// assert_eq!(writer.as_bytes(), b"foo bar baz");
391    ///
392    /// // Truncating to anything larger than the length is a no-op.
393    /// writer.truncate(usize::MAX / 2);
394    /// assert_eq!(writer.as_bytes(), b"foo bar baz");
395    ///
396    /// writer.truncate(3);
397    /// assert_eq!(writer.as_bytes(), b"foo");
398    ///
399    /// writer.write_str("ooooooo");
400    /// assert_eq!(writer.as_bytes(), b"fooooooooo");
401    ///
402    /// ```
403    #[inline]
404    pub const fn truncate(&mut self, length: usize) {
405        if length < *self.len {
406            *self.len = length;
407        }
408    }
409}
410
411impl<'w, E> StrWriterMut<'w, E> {
412    /// Truncates this `StrWriterMut` to length 0.
413    ///
414    /// # Example
415    ///
416    /// ```rust
417    /// use const_format::{Error, StrWriter, StrWriterMut};
418    ///
419    /// let mut buffer = StrWriter::new([0; 64]);
420    /// let mut writer = StrWriterMut::new(&mut buffer);
421    ///
422    /// writer.write_str("foo")?;
423    /// assert_eq!(writer.as_str(), "foo");
424    ///
425    /// writer.clear();
426    /// assert_eq!(writer.as_str(), "");
427    /// assert!(writer.is_empty());
428    ///
429    /// writer.write_str("bar");
430    /// assert_eq!(writer.as_str(), "bar");
431    ///
432    /// # Ok::<(), const_format::Error>(())
433    /// ```
434
435    #[inline]
436    pub const fn clear(&mut self) {
437        *self.len = 0;
438    }
439
440    /// Gets the written part of this `StrWriterMut` as a `&[u8]`
441    ///
442    /// The slice is guaranteed to be valid utf8, so this is mostly for convenience.
443    ///
444    /// ### Runtime
445    ///
446    /// If the "rust_1_64" feature is disabled,
447    /// this takes time proportional to `self.capacity() - self.len()`.
448    ///
449    /// If the "rust_1_64" feature is enabled, it takes constant time to run.
450    ///
451    /// # Example
452    ///
453    /// ```rust
454    ///
455    /// use const_format::{StrWriter, StrWriterMut};
456    ///
457    /// let mut buffer = StrWriter::new([0; 64]);
458    /// let mut writer = StrWriterMut::new(&mut buffer);
459    ///
460    /// writer.write_str("Hello, World!");
461    ///
462    /// assert_eq!(writer.as_bytes_alt(), "Hello, World!".as_bytes());
463    ///
464    /// ```
465    #[inline(always)]
466    pub const fn as_bytes_alt(&self) -> &[u8] {
467        crate::utils::slice_up_to_len_alt(self.buffer, *self.len)
468    }
469}
470
471impl<'w> StrWriterMut<'w, Utf8Encoding> {
472    /// Gets the written part of this StrWriterMut as a `&str`
473    ///
474    /// ### Runtime
475    ///
476    /// If the "rust_1_64" feature is disabled,
477    /// this takes time proportional to `self.capacity() - self.len()`.
478    ///
479    /// If the "rust_1_64" feature is enabled, it takes constant time to run.
480    ///
481    /// # Example
482    ///
483    /// ```rust
484    ///
485    /// use const_format::{StrWriter, StrWriterMut};
486    /// use const_format::{unwrap, writec};
487    ///
488    ///
489    /// const CAP: usize = 128;
490    ///
491    /// const __STR: &StrWriter = &{
492    ///     let mut buffer =  StrWriter::new([0; CAP]);
493    ///     let mut writer = StrWriterMut::new(&mut buffer);
494    ///
495    ///     // Writing the array with debug formatting, and the integers with hexadecimal formatting.
496    ///     unwrap!(writec!(writer, "{:X}", [3u32, 5, 8, 13, 21, 34]));
497    ///
498    ///     buffer
499    /// };
500    ///
501    /// const STR: &str = __STR.as_str_alt();
502    ///
503    /// fn main() {
504    ///     assert_eq!(STR, "[3, 5, 8, D, 15, 22]");
505    /// }
506    /// ```
507    #[inline(always)]
508    pub const fn as_str_alt(&self) -> &str {
509        // All the methods that modify the buffer must ensure utf8 validity,
510        // only methods from this module need to ensure this.
511        unsafe { core::str::from_utf8_unchecked(self.as_bytes_alt()) }
512    }
513    conditionally_const! {
514        feature = "rust_1_64";
515        /// Gets the written part of this StrWriterMut as a `&str`
516        ///
517        /// ### Constness
518        ///
519        /// This can be called in const contexts by enabling the "rust_1_64" feature.
520        ///
521        /// ### Alternative
522        ///
523        /// You can also use the [`as_str_alt`](Self::as_str_alt) method,
524        /// which is always available,
525        /// but takes linear time to run when the "rust_1_64" feature
526        /// is disabled.
527        ///
528        /// # Example
529        ///
530        /// ```rust
531        ///
532        /// use const_format::{StrWriter, StrWriterMut};
533        ///
534        /// let mut buffer = StrWriter::new([0; 64]);
535        /// let mut writer = StrWriterMut::new(&mut buffer);
536        ///
537        /// writer.write_str("Hello, how are you?");
538        ///
539        /// assert_eq!(writer.as_str(), "Hello, how are you?");
540        ///
541        /// ```
542        #[inline(always)]
543        pub fn as_str(&self) -> &str {
544            // All the methods that modify the buffer must ensure utf8 validity,
545            // only methods from this module need to ensure this.
546            unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
547        }
548    }
549}
550
551impl<'w, E> StrWriterMut<'w, E> {
552    conditionally_const! {
553        feature = "rust_1_64";
554
555        /// Gets the written part of this `StrWriterMut` as a `&[u8]`
556        ///
557        /// The slice is guaranteed to be valid utf8, so this is mostly for convenience.
558        ///
559        /// ### Constness
560        ///
561        /// This can be called in const contexts by enabling the "rust_1_64" feature.
562        ///
563        /// # Example
564        ///
565        /// ```rust
566        ///
567        /// use const_format::{StrWriter, StrWriterMut};
568        ///
569        /// let mut buffer = StrWriter::new([0; 64]);
570        /// let mut writer = StrWriterMut::new(&mut buffer);
571        ///
572        /// writer.write_str("Hello, World!");
573        ///
574        /// assert_eq!(writer.as_bytes_alt(), "Hello, World!".as_bytes());
575        ///
576        /// ```
577        #[inline(always)]
578        pub fn as_bytes(&self) -> &[u8] {
579            crate::utils::slice_up_to_len(self.buffer, *self.len)
580        }
581    }
582}
583
584impl<'w, E> StrWriterMut<'w, E> {
585    /// Constructs a [`Formatter`] that writes into this `StrWriterMut`,
586    /// which can be passed to debug and display formatting methods.
587    ///
588    /// # Example
589    ///
590    /// ```rust
591    ///
592    /// use const_format::{Error, Formatter, FormattingFlags, StrWriter, StrWriterMut};
593    /// use const_format::call_debug_fmt;
594    ///
595    /// use std::ops::Range;
596    ///
597    /// const fn range_debug_fmt(
598    ///     slice: &[Range<usize>],
599    ///     f: &mut Formatter<'_>
600    /// ) -> Result<(), Error> {
601    ///     // We need this macro to debug format arrays of non-primitive types
602    ///     // Also, it implicitly returns a `const_format::Error` on error.
603    ///     call_debug_fmt!(array, slice, f);
604    ///     Ok(())
605    /// }
606    ///
607    /// let mut buffer = StrWriter::new([0; 64]);
608    /// let mut writer = StrWriterMut::new(&mut buffer);
609    ///
610    /// range_debug_fmt(
611    ///     &[0..14, 14..31, 31..48],
612    ///     &mut writer.make_formatter(FormattingFlags::new().set_binary())
613    /// )?;
614    ///    
615    /// assert_eq!(writer.as_str(), "[0..1110, 1110..11111, 11111..110000]");
616    ///
617    /// # Ok::<(), Error>(())
618    ///
619    /// ```
620    ///
621    /// [`Formatter`]: ./struct.Formatter.html
622    #[inline(always)]
623    pub const fn make_formatter(&mut self, flags: FormattingFlags) -> Formatter<'_> {
624        Formatter::from_sw_mut(
625            StrWriterMut::<NoEncoding> {
626                len: self.len,
627                buffer: self.buffer,
628                _encoding: PhantomData,
629            },
630            flags,
631        )
632    }
633
634    /// For borrowing this mutably in macros, without getting nested mutable references.
635    #[inline(always)]
636    pub const fn borrow_mutably(&mut self) -> &mut StrWriterMut<'w, E> {
637        self
638    }
639
640    /// For passing a reborrow of this `StrWriterMut` into functions,
641    /// without this you'd need to pass a mutable reference instead.
642    ///
643    /// # Example
644    ///
645    /// ```rust
646    ///
647    /// use const_format::{Error, FormattingFlags, StrWriter, StrWriterMut, call_debug_fmt};
648    ///
649    /// use std::ops::Range;
650    ///
651    /// const fn range_debug_fmt(
652    ///     slice: &[[u32; 2]],
653    ///     mut writer: StrWriterMut<'_>
654    /// ) -> Result<(), Error> {
655    ///     let mut formatter = writer.make_formatter(FormattingFlags::new().set_binary());
656    ///
657    ///     // We need this macro to debug format arrays of non-primitive types
658    ///     // Also, it implicitly returns a `const_format::Error` on error.
659    ///     call_debug_fmt!(array, slice, formatter);
660    ///     Ok(())
661    /// }
662    ///
663    /// let mut buffer = StrWriter::new([0; 64]);
664    /// let mut writer = StrWriterMut::new(&mut buffer);
665    ///
666    /// range_debug_fmt(&[[3, 5], [8, 13]], writer.reborrow())?;
667    ///    
668    /// assert_eq!(writer.as_str(), "[[11, 101], [1000, 1101]]");
669    ///
670    /// # Ok::<(), Error>(())
671    ///
672    /// ```
673    #[inline(always)]
674    pub const fn reborrow(&mut self) -> StrWriterMut<'_, E> {
675        StrWriterMut {
676            len: self.len,
677            buffer: self.buffer,
678            _encoding: PhantomData,
679        }
680    }
681
682    // Safety: You must not write invalid utf8 bytes with the returned StrWriterMut.
683    pub(crate) const unsafe fn into_byte_encoding(self) -> StrWriterMut<'w, NoEncoding> {
684        StrWriterMut {
685            len: self.len,
686            buffer: self.buffer,
687            _encoding: PhantomData,
688        }
689    }
690}
691
692/////////////////////////////////////////////////////////////////////////////////
693
694macro_rules! write_integer_fn {
695    (
696        display_attrs $display_attrs:tt
697        debug_attrs $debug_attrs:tt
698        $(($display_fn:ident, $debug_fn:ident, $sign:ident, $ty:ident, $Unsigned:ident))*
699    )=>{
700        impl<'w,E> StrWriterMut<'w,E>{
701            $(
702                write_integer_fn!{
703                    @methods
704                    display_attrs $display_attrs
705                    debug_attrs $debug_attrs
706                    $display_fn, $debug_fn, $sign, ($ty, $Unsigned), stringify!($ty)
707                }
708            )*
709        }
710
711        $(
712            write_integer_fn!{
713                @pwrapper
714                $display_fn, $debug_fn, $sign, ($ty, $Unsigned), stringify!($ty)
715            }
716        )*
717    };
718    (@pwrapper
719        $display_fn:ident,
720        $debug_fn:ident,
721        $sign:ident,
722        ($ty:ident, $Unsigned:ident),
723        $ty_name:expr
724    )=>{
725        impl PWrapper<$ty> {
726            /// Writes a
727            #[doc = $ty_name]
728            /// with Display formatting.
729            pub const fn const_display_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
730                f.$display_fn(self.0)
731            }
732
733            /// Writes a
734            #[doc = $ty_name]
735            /// with Debug formatting.
736            pub const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
737                f.$debug_fn(self.0)
738            }
739        }
740    };
741    (@methods
742        display_attrs( $(#[$display_attrs:meta])* )
743        debug_attrs( $(#[$debug_attrs:meta])* )
744        $display_fn:ident,
745        $debug_fn:ident,
746        $sign:ident,
747        ($ty:ident, $Unsigned:ident),
748        $ty_name:expr
749    )=>{
750        $(#[$display_attrs])*
751        pub const fn $display_fn(&mut self, number: $ty) -> Result<(), Error> {
752            borrow_fields!(self, this_len, this_buffer);
753
754            let n = PWrapper(number);
755            let len = n.compute_display_len(FormattingFlags::DEFAULT);
756
757            let mut cursor = *this_len + len;
758
759            if cursor > this_buffer.len() {
760                return Err(Error::NotEnoughSpace);
761            }
762
763            write_integer_fn!(@unsigned_abs $sign, n);
764
765            loop {
766                cursor-=1;
767                let digit = (n % 10) as u8;
768                this_buffer[cursor] = b'0' + digit;
769                n/=10;
770                if n == 0 { break }
771            }
772
773            write_integer_fn!(@write_sign $sign, this_len, this_buffer, number);
774
775            *this_len+=len;
776            Ok(())
777        }
778
779        $(#[$debug_attrs])*
780        pub const fn $debug_fn(
781            &mut self,
782            number: $ty,
783            flags: FormattingFlags,
784        ) -> Result<(), Error> {
785            const fn hex<E>(
786                this: &mut StrWriterMut<'_, E>,
787                n: $ty,
788                f: FormattingFlags,
789            ) -> Result<(), Error> {
790                borrow_fields!(this, this_len, this_buffer);
791
792                let is_alternate = f.is_alternate();
793                let len = PWrapper(n).hexadecimal_len(f);
794
795                let mut cursor = *this_len + len;
796
797                if cursor > this_buffer.len() {
798                    return Err(Error::NotEnoughSpace);
799                }
800
801                if is_alternate {
802                    this_buffer[*this_len] = b'0';
803                    this_buffer[*this_len + 1] = b'x';
804                }
805
806                write_integer_fn!(@as_unsigned $sign, n, $Unsigned);
807
808                loop {
809                    cursor-=1;
810                    let digit = (n & 0b1111) as u8;
811                    this_buffer[cursor] = hex_as_ascii(digit, f.hex_fmt());
812                    n >>= 4;
813                    if n == 0 { break }
814                }
815
816                *this_len+=len;
817                Ok(())
818            }
819
820            const fn binary<E>(
821                this: &mut StrWriterMut<'_, E>,
822                n: $ty,
823                f: FormattingFlags,
824            ) -> Result<(), Error> {
825                borrow_fields!(this, this_len, this_buffer);
826
827                let is_alternate = f.is_alternate();
828                let len = PWrapper(n).binary_len(f);
829
830                let mut cursor = *this_len + len;
831
832                if cursor > this_buffer.len() {
833                    return Err(Error::NotEnoughSpace);
834                }
835
836                if is_alternate {
837                    this_buffer[*this_len] = b'0';
838                    this_buffer[*this_len + 1] = b'b';
839                }
840
841                write_integer_fn!(@as_unsigned $sign, n, $Unsigned);
842
843                loop {
844                    cursor-=1;
845                    let digit = (n & 1) as u8;
846                    this_buffer[cursor] = hex_as_ascii(digit, f.hex_fmt());
847                    n >>= 1;
848                    if n == 0 { break }
849                }
850
851                *this_len+=len;
852                Ok(())
853            }
854
855            match flags.num_fmt() {
856                NumberFormatting::Decimal=>self.$display_fn(number),
857                NumberFormatting::Hexadecimal=>hex(self, number, flags),
858                NumberFormatting::Binary=>binary(self, number, flags),
859            }
860        }
861    };
862    (@unsigned_abs signed, $n:ident) => (
863        let mut $n = $n.unsigned_abs();
864    );
865    (@unsigned_abs unsigned, $n:ident) => (
866        let mut $n = $n.0;
867    );
868    (@as_unsigned signed, $n:ident, $Unsigned:ident) => (
869        let mut $n = $n as $Unsigned;
870    );
871    (@as_unsigned unsigned, $n:ident, $Unsigned:ident) => (
872        let mut $n = $n;
873    );
874    (@write_sign signed, $self_len:ident, $self_buffer:ident, $n:ident) => ({
875        if $n < 0 {
876            $self_buffer[*$self_len] = b'-';
877        }
878    });
879    (@write_sign unsigned, $self_len:ident, $self_buffer:ident, $n:ident) => ({});
880}
881
882/// Checks that a range is valid for indexing a string,
883/// assuming that the range is in-bounds, and start <= end.
884#[inline]
885const fn is_valid_str_range(s: &[u8], Range { start, end }: Range<usize>) -> bool {
886    let len = s.len();
887
888    (end == len || ((s[end] as i8) >= -0x40)) && (start == len || ((s[start] as i8) >= -0x40))
889}
890
891/// Checks that an index is valid for indexing a string,
892/// assuming that the index is in-bounds.
893#[inline]
894const fn is_valid_str_index(s: &[u8], index: usize) -> bool {
895    let len = s.len();
896
897    index == len || ((s[index] as i8) >= -0x40)
898}
899
900impl<'w, E> StrWriterMut<'w, E> {
901    /// Writes a subslice of `s` with Display formatting.
902    ///
903    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
904    ///
905    /// # Additional Errors
906    ///
907    /// This method returns `Error::NotOnCharBoundary` if the range is not
908    /// on a character boundary.
909    ///
910    /// Out of bounds range bounds are treated as being at `s.len()`,
911    /// this only returns an error on an in-bounds index that is not on a character boundary.
912    ///
913    /// # Example
914    ///
915    /// ```rust
916    /// use const_format::{FormattingFlags, StrWriterMut};
917    ///
918    /// let mut len = 0;
919    /// let mut buffer = [0; 64];
920    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
921    ///
922    /// let _ = writer.write_str_range("FOO BAR BAZ", 4..7);
923    ///
924    /// assert_eq!(writer.as_str(), "BAR");
925    ///
926    /// ```
927    ///
928    pub const fn write_str_range(&mut self, s: &str, range: Range<usize>) -> Result<(), Error> {
929        let bytes = s.as_bytes();
930        let Range { start, end } = saturate_range(bytes, &range);
931
932        if !is_valid_str_range(bytes, start..end) {
933            return Err(Error::NotOnCharBoundary);
934        }
935
936        self.write_str_inner(bytes, start, end)
937    }
938
939    /// Writes `s` with Display formatting.
940    ///
941    /// # Example
942    ///
943    /// ```rust
944    ///
945    /// use const_format::{FormattingFlags, StrWriterMut};
946    ///
947    /// let mut len = 0;
948    /// let mut buffer = [0; 64];
949    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
950    ///
951    /// let _ = writer.write_str("FOO BAR BAZ");
952    ///
953    /// assert_eq!(writer.as_str(), "FOO BAR BAZ");
954    ///
955    /// ```
956    ///
957    pub const fn write_str(&mut self, s: &str) -> Result<(), Error> {
958        let bytes = s.as_bytes();
959
960        self.write_str_inner(bytes, 0, s.len())
961    }
962
963    /// Writes `character` with Display formatting
964    ///
965    /// # Example
966    ///
967    /// ```rust
968    ///
969    /// use const_format::StrWriterMut;
970    ///
971    /// let mut len = 0;
972    /// let mut buffer = [0; 64];
973    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
974    ///
975    /// let _ = writer.write_char('3');
976    /// let _ = writer.write_char('5');
977    /// let _ = writer.write_char('8');
978    ///
979    /// assert_eq!(writer.as_str(), "358");
980    ///
981    /// ```
982    ///
983    pub const fn write_char(&mut self, character: char) -> Result<(), Error> {
984        let fmt = crate::char_encoding::char_to_display(character);
985        self.write_str_inner(fmt.encoded(), 0, fmt.len())
986    }
987
988    /// Writes a subslice of `ascii` with Display formatting.
989    ///
990    /// Out of bounds range bounds are treated as being at `s.len()`.
991    ///
992    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
993    ///
994    /// # Example
995    ///
996    /// ```rust
997    ///
998    /// use const_format::{FormattingFlags, StrWriterMut, ascii_str};
999    ///
1000    /// let mut len = 0;
1001    /// let mut buffer = [0; 64];
1002    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1003    ///
1004    /// let _ = writer.write_ascii_range(ascii_str!("FOO BAR BAZ"), 4..7);
1005    ///
1006    /// assert_eq!(writer.as_str(), "BAR");
1007    ///
1008    /// ```
1009    ///
1010    pub const fn write_ascii_range(
1011        &mut self,
1012        ascii: AsciiStr<'_>,
1013        range: Range<usize>,
1014    ) -> Result<(), Error> {
1015        let bytes = ascii.as_bytes();
1016        let Range { start, end } = saturate_range(bytes, &range);
1017
1018        self.write_str_inner(bytes, start, end)
1019    }
1020
1021    /// Writes `ascii` with Display formatting.
1022    ///
1023    /// # Example
1024    ///
1025    /// ```rust
1026    ///
1027    /// use const_format::{FormattingFlags, StrWriterMut, ascii_str};
1028    ///
1029    /// let mut len = 0;
1030    /// let mut buffer = [0; 64];
1031    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1032    ///
1033    /// let _ = writer.write_ascii(ascii_str!("FOO BAR BAZ"));
1034    ///
1035    /// assert_eq!(writer.as_str(), "FOO BAR BAZ");
1036    ///
1037    /// ```
1038    ///
1039    pub const fn write_ascii(&mut self, ascii: AsciiStr<'_>) -> Result<(), Error> {
1040        let bytes = ascii.as_bytes();
1041
1042        self.write_str_inner(bytes, 0, bytes.len())
1043    }
1044
1045    /// Writes an ascii `character`, `repeated` times.
1046    ///
1047    /// # Example
1048    ///
1049    /// ```rust
1050    ///
1051    /// use const_format::{FormattingFlags, StrWriterMut};
1052    ///
1053    /// let mut len = 0;
1054    /// let mut buffer = [0; 64];
1055    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1056    ///
1057    /// let _ = writer.write_ascii_repeated(b'A', 10);
1058    ///
1059    /// assert_eq!(writer.as_str(), "AAAAAAAAAA");
1060    ///
1061    /// ```
1062    ///
1063    pub const fn write_ascii_repeated(
1064        &mut self,
1065        mut character: u8,
1066        repeated: usize,
1067    ) -> Result<(), Error> {
1068        borrow_fields!(self, self_len, self_buffer);
1069
1070        // Truncating non-ascii u8s
1071        character &= 0b111_1111;
1072
1073        let end = *self_len + repeated;
1074
1075        if end > self_buffer.len() {
1076            return Err(Error::NotEnoughSpace);
1077        }
1078
1079        while *self_len < end {
1080            self_buffer[*self_len] = character;
1081            *self_len += 1;
1082        }
1083
1084        Ok(())
1085    }
1086
1087    #[inline(always)]
1088    const fn write_str_inner(
1089        &mut self,
1090        bytes: &[u8],
1091        mut start: usize,
1092        end: usize,
1093    ) -> Result<(), Error> {
1094        borrow_fields!(self, self_len, self_buffer);
1095
1096        let len = end - start;
1097
1098        if *self_len + len > self_buffer.len() {
1099            return Err(Error::NotEnoughSpace);
1100        }
1101
1102        while start < end {
1103            self_buffer[*self_len] = bytes[start];
1104            *self_len += 1;
1105            start += 1;
1106        }
1107
1108        Ok(())
1109    }
1110}
1111
1112/// Debug-formatted string writing
1113impl<'w, E> StrWriterMut<'w, E> {
1114    /// Writes a subslice of `s` with  Debug-like formatting.
1115    ///
1116    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
1117    ///
1118    /// # Additional Errors
1119    ///
1120    /// This method returns `Error::NotOnCharBoundary` if the range is not
1121    /// on a character boundary.
1122    ///
1123    /// Out of bounds range bounds are treated as being at `s.len()`,
1124    /// this only returns an error on an in-bounds index that is not on a character boundary.
1125    ///
1126    /// # Example
1127    ///
1128    /// ```rust
1129    ///
1130    /// use const_format::{FormattingFlags, StrWriterMut};
1131    ///
1132    /// let mut len = 0;
1133    /// let mut buffer = [0; 64];
1134    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1135    ///
1136    /// let _ = writer.write_str_range_debug("FOO\nBAR\tBAZ", 3..8);
1137    ///
1138    /// assert_eq!(writer.as_str(), r#""\nBAR\t""#);
1139    ///
1140    /// ```
1141    ///
1142    pub const fn write_str_range_debug(
1143        &mut self,
1144        s: &str,
1145        range: Range<usize>,
1146    ) -> Result<(), Error> {
1147        let bytes = s.as_bytes();
1148        let Range { start, end } = saturate_range(bytes, &range);
1149
1150        if !is_valid_str_range(bytes, start..end) {
1151            return Err(Error::NotOnCharBoundary);
1152        }
1153
1154        self.write_str_debug_inner(bytes, start, end)
1155    }
1156
1157    /// Writes `s` with Debug-like formatting.
1158    ///
1159    /// # Example
1160    ///
1161    /// ```rust
1162    ///
1163    /// use const_format::{FormattingFlags, StrWriterMut};
1164    ///
1165    /// let mut len = 0;
1166    /// let mut buffer = [0; 64];
1167    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1168    ///
1169    /// let _ = writer.write_str_debug("FOO\nBAR\tBAZ");
1170    ///
1171    /// assert_eq!(writer.as_str(), r#""FOO\nBAR\tBAZ""#);
1172    ///
1173    /// ```
1174    ///
1175    pub const fn write_str_debug(&mut self, str: &str) -> Result<(), Error> {
1176        let bytes = str.as_bytes();
1177        self.write_str_debug_inner(bytes, 0, str.len())
1178    }
1179
1180    /// Writes `character` with Debug formatting.
1181    ///
1182    /// # Example
1183    ///
1184    /// ```rust
1185    ///
1186    /// use const_format::StrWriterMut;
1187    ///
1188    /// let mut len = 0;
1189    /// let mut buffer = [0; 64];
1190    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1191    ///
1192    /// let _ = writer.write_str(" ");
1193    /// let _ = writer.write_char_debug('\\');
1194    /// let _ = writer.write_str(" ");
1195    /// let _ = writer.write_char_debug('A');
1196    /// let _ = writer.write_str(" ");
1197    /// let _ = writer.write_char_debug('0');
1198    /// let _ = writer.write_str(" ");
1199    /// let _ = writer.write_char_debug('\'');
1200    /// let _ = writer.write_str(" ");
1201    ///
1202    /// assert_eq!(writer.as_str(), r#" '\\' 'A' '0' '\'' "#);
1203    ///
1204    /// ```
1205    ///
1206    pub const fn write_char_debug(&mut self, character: char) -> Result<(), Error> {
1207        let fmt = crate::char_encoding::char_to_debug(character);
1208        self.write_str_inner(fmt.encoded(), 0, fmt.len())
1209    }
1210
1211    /// Writes a subslice of `ascii` with Debug-like formatting.
1212    ///
1213    /// Out of bounds range bounds are treated as being at `s.len()`.
1214    ///
1215    /// This is a workaround for being unable to do `&foo[start..end]` at compile time.
1216    ///
1217    /// # Example
1218    ///
1219    /// ```rust
1220    ///
1221    /// use const_format::{FormattingFlags, StrWriterMut, ascii_str};
1222    ///
1223    /// let mut len = 0;
1224    /// let mut buffer = [0; 64];
1225    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1226    ///
1227    /// let _ = writer.write_ascii_range_debug(ascii_str!("FOO\nBAR\tBAZ"), 3..8);
1228    ///
1229    /// assert_eq!(writer.as_str(), r#""\nBAR\t""#);
1230    ///
1231    /// ```
1232    ///
1233    pub const fn write_ascii_range_debug(
1234        &mut self,
1235        ascii: AsciiStr<'_>,
1236        range: Range<usize>,
1237    ) -> Result<(), Error> {
1238        let bytes = ascii.as_bytes();
1239        let Range { start, end } = saturate_range(bytes, &range);
1240
1241        self.write_str_debug_inner(bytes, start, end)
1242    }
1243
1244    /// Writes `ascii` with Debug-like formatting.
1245    ///
1246    /// # Example
1247    ///
1248    /// ```rust
1249    ///
1250    /// use const_format::{FormattingFlags, StrWriterMut, ascii_str};
1251    ///
1252    /// let mut len = 0;
1253    /// let mut buffer = [0; 64];
1254    /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1255    ///
1256    /// let _ = writer.write_ascii_debug(ascii_str!("FOO\nBAR\tBAZ"));
1257    ///
1258    /// assert_eq!(writer.as_str(), r#""FOO\nBAR\tBAZ""#);
1259    ///
1260    /// ```
1261    ///
1262    pub const fn write_ascii_debug(&mut self, ascii: AsciiStr<'_>) -> Result<(), Error> {
1263        let bytes = ascii.as_bytes();
1264        self.write_str_debug_inner(bytes, 0, bytes.len())
1265    }
1266
1267    #[inline(always)]
1268    const fn write_str_debug_inner(
1269        &mut self,
1270        bytes: &[u8],
1271        mut start: usize,
1272        end: usize,
1273    ) -> Result<(), Error> {
1274        borrow_fields!(self, self_len, self_buffer);
1275
1276        let len = end - start;
1277
1278        // + 2 for the quote characters around the string.
1279        if *self_len + len + 2 > self_buffer.len() {
1280            return Err(Error::NotEnoughSpace);
1281        }
1282
1283        // The amount of bytes available for escapes,
1284        // not counting the `writte_c`.
1285        let mut remaining_for_escapes = (self_buffer.len() - 2 - len - *self_len) as isize;
1286        let mut written = *self_len;
1287
1288        self_buffer[written] = b'"';
1289        written += 1;
1290
1291        while start != end {
1292            let c = bytes[start];
1293            let mut written_c = c;
1294
1295            let mut shifted = 0;
1296
1297            if c < 128
1298                && ({
1299                    shifted = 1 << c;
1300                    (FOR_ESCAPING.is_escaped & shifted) != 0
1301                })
1302            {
1303                self_buffer[written] = b'\\';
1304                written += 1;
1305
1306                if (FOR_ESCAPING.is_backslash_escaped & shifted) != 0 {
1307                    remaining_for_escapes -= 1;
1308                    if remaining_for_escapes < 0 {
1309                        return Err(Error::NotEnoughSpace);
1310                    }
1311                    written_c = ForEscaping::get_backslash_escape(c);
1312                } else {
1313                    remaining_for_escapes -= 3;
1314                    if remaining_for_escapes < 0 {
1315                        return Err(Error::NotEnoughSpace);
1316                    }
1317                    self_buffer[written] = b'x';
1318                    written += 1;
1319                    self_buffer[written] = hex_as_ascii(c >> 4, HexFormatting::Upper);
1320                    written += 1;
1321                    written_c = hex_as_ascii(c & 0xF, HexFormatting::Upper);
1322                };
1323            }
1324
1325            self_buffer[written] = written_c;
1326            written += 1;
1327            start += 1;
1328        }
1329
1330        self_buffer[written] = b'"';
1331        written += 1;
1332
1333        *self_len = written;
1334
1335        Ok(())
1336    }
1337}
1338
1339write_integer_fn! {
1340    display_attrs(
1341        /// Write `number` with display formatting.
1342        ///
1343        /// # Example
1344        ///
1345        /// ```rust
1346        ///
1347        /// use const_format::{Formatter, FormattingFlags, StrWriterMut, ascii_str};
1348        ///
1349        /// let mut len = 0;
1350        /// let mut buffer = [0; 64];
1351        /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1352        ///
1353        /// let _ = writer.write_u8_display(137);
1354        ///
1355        /// assert_eq!(writer.as_str(), "137");
1356        ///
1357        /// ```
1358        ///
1359    )
1360    debug_attrs(
1361        /// Writes `number` with debug formatting.
1362        ///
1363        /// # Example
1364        ///
1365        /// ```rust
1366        ///
1367        /// use const_format::{FormattingFlags, StrWriterMut};
1368        ///
1369        /// const fn debug_fmt<'a>(
1370        ///     writer: &'a mut StrWriterMut<'_>,
1371        ///     flag: FormattingFlags
1372        /// ) -> &'a str {
1373        ///     writer.clear();
1374        ///     let _ = writer.write_u8_debug(63, flag);
1375        ///     writer.as_str_alt()
1376        /// }
1377        ///
1378        /// let reg_flag = FormattingFlags::NEW.set_alternate(false);
1379        /// let alt_flag = FormattingFlags::NEW.set_alternate(true);
1380        ///
1381        /// let mut len = 0;
1382        /// let mut buffer = [0; 64];
1383        /// let mut writer = StrWriterMut::from_custom_cleared(&mut buffer, &mut len);
1384        ///
1385        /// assert_eq!(debug_fmt(&mut writer, reg_flag),                   "63"     );
1386        /// assert_eq!(debug_fmt(&mut writer, reg_flag.set_hexadecimal()), "3F"     );
1387        /// assert_eq!(debug_fmt(&mut writer, reg_flag.set_lower_hexadecimal()), "3f");
1388        /// assert_eq!(debug_fmt(&mut writer, reg_flag.set_binary()),      "111111" );
1389        /// assert_eq!(debug_fmt(&mut writer, alt_flag),                   "63"     );
1390        /// assert_eq!(debug_fmt(&mut writer, alt_flag.set_hexadecimal()), "0x3F"   );
1391        /// assert_eq!(debug_fmt(&mut writer, alt_flag.set_lower_hexadecimal()), "0x3f");
1392        /// assert_eq!(debug_fmt(&mut writer, alt_flag.set_binary()),      "0b111111");
1393        ///
1394        /// ```
1395        ///
1396    )
1397    (write_u8_display, write_u8_debug, unsigned, u8, u8)
1398}
1399write_integer_fn! {
1400    display_attrs(
1401        /// Writes `number` with display formatting
1402        ///
1403        /// For an example,
1404        /// you can look at the one for the [`write_u8_display`] method.
1405        ///
1406        /// [`write_u8_display`]: #method.write_u8_display
1407    )
1408    debug_attrs(
1409        /// Writes `number` with debug formatting.
1410        ///
1411        /// For an example,
1412        /// you can look at the one for the [`write_u8_debug`] method.
1413        ///
1414        /// [`write_u8_debug`]: #method.write_u8_debug
1415    )
1416    (write_u16_display, write_u16_debug, unsigned, u16, u16)
1417    (write_u32_display, write_u32_debug, unsigned, u32, u32)
1418    (write_u64_display, write_u64_debug, unsigned, u64, u64)
1419    (write_u128_display, write_u128_debug, unsigned, u128, u128)
1420    (write_usize_display, write_usize_debug, unsigned, usize, usize)
1421
1422    (write_i8_display, write_i8_debug, signed, i8, u8)
1423    (write_i16_display, write_i16_debug, signed, i16, u16)
1424    (write_i32_display, write_i32_debug, signed, i32, u32)
1425    (write_i64_display, write_i64_debug, signed, i64, u64)
1426    (write_i128_display, write_i128_debug, signed, i128, u128)
1427    (write_isize_display, write_isize_debug, signed, isize, usize)
1428}