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}