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}