Skip to main content

core/num/imp/
fmt.rs

1//! Shared utilities used by both float and integer formatting.
2#![doc(hidden)]
3#![unstable(
4    feature = "numfmt",
5    reason = "internal routines only exposed for testing",
6    issue = "none"
7)]
8
9/// Formatted parts.
10#[derive(#[automatically_derived]
impl<'a> crate::marker::Copy for Part<'a> { }Copy, #[automatically_derived]
impl<'a> crate::clone::Clone for Part<'a> {
    #[inline]
    fn clone(&self) -> Part<'a> {
        let _: crate::clone::AssertParamIsClone<usize>;
        let _: crate::clone::AssertParamIsClone<u16>;
        let _: crate::clone::AssertParamIsClone<&'a [u8]>;
        *self
    }
}Clone, #[automatically_derived]
impl<'a> crate::cmp::PartialEq for Part<'a> {
    #[inline]
    fn eq(&self, other: &Part<'a>) -> bool {
        let __self_discr = crate::intrinsics::discriminant_value(self);
        let __arg1_discr = crate::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Part::Zero(__self_0), Part::Zero(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Part::Num(__self_0), Part::Num(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Part::Copy(__self_0), Part::Copy(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { crate::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl<'a> crate::cmp::Eq for Part<'a> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: crate::cmp::AssertParamIsEq<usize>;
        let _: crate::cmp::AssertParamIsEq<u16>;
        let _: crate::cmp::AssertParamIsEq<&'a [u8]>;
    }
}Eq, #[automatically_derived]
impl<'a> crate::fmt::Debug for Part<'a> {
    #[inline]
    fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
        match self {
            Part::Zero(__self_0) =>
                crate::fmt::Formatter::debug_tuple_field1_finish(f, "Zero",
                    &__self_0),
            Part::Num(__self_0) =>
                crate::fmt::Formatter::debug_tuple_field1_finish(f, "Num",
                    &__self_0),
            Part::Copy(__self_0) =>
                crate::fmt::Formatter::debug_tuple_field1_finish(f, "Copy",
                    &__self_0),
        }
    }
}Debug)]
11pub enum Part<'a> {
12    /// Given number of zero digits.
13    Zero(usize),
14    /// A literal number up to 5 digits.
15    Num(u16),
16    /// A verbatim copy of given bytes.
17    Copy(&'a [u8]),
18}
19
20impl<'a> Part<'a> {
21    /// Returns the exact byte length of given part.
22    pub fn len(&self) -> usize {
23        match *self {
24            Part::Zero(nzeroes) => nzeroes,
25            Part::Num(v) => v.checked_ilog10().unwrap_or_default() as usize + 1,
26            Part::Copy(buf) => buf.len(),
27        }
28    }
29
30    /// Writes a part into the supplied buffer.
31    /// Returns the number of written bytes, or `None` if the buffer is not enough.
32    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
33    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
34        let len = self.len();
35        if out.len() >= len {
36            match *self {
37                Part::Zero(nzeroes) => {
38                    for c in &mut out[..nzeroes] {
39                        *c = b'0';
40                    }
41                }
42                Part::Num(mut v) => {
43                    for c in out[..len].iter_mut().rev() {
44                        *c = b'0' + (v % 10) as u8;
45                        v /= 10;
46                    }
47                }
48                Part::Copy(buf) => {
49                    out[..buf.len()].copy_from_slice(buf);
50                }
51            }
52            Some(len)
53        } else {
54            None
55        }
56    }
57}
58
59/// Formatted result containing one or more parts.
60/// This can be written to the byte buffer or converted to the allocated string.
61#[allow(missing_debug_implementations)]
62#[derive(#[automatically_derived]
#[allow(missing_debug_implementations)]
impl<'a> crate::clone::Clone for Formatted<'a> {
    #[inline]
    fn clone(&self) -> Formatted<'a> {
        Formatted {
            sign: crate::clone::Clone::clone(&self.sign),
            parts: crate::clone::Clone::clone(&self.parts),
        }
    }
}Clone)]
63pub struct Formatted<'a> {
64    /// A byte slice representing a sign, either `""`, `"-"` or `"+"`.
65    pub sign: &'static str,
66    /// Formatted parts to be rendered after a sign and optional zero padding.
67    pub parts: &'a [Part<'a>],
68}
69
70impl<'a> Formatted<'a> {
71    /// Returns the byte length of combined formatted result.
72    ///
73    /// Saturates at `usize::MAX` if the actual length is larger.
74    ///
75    /// This matters on 16-bit targets, where exponential formatting can exceed
76    /// `usize::MAX` by emitting `u16::MAX` trailing zeroes plus `"1."` / `"e0"`.
77    pub fn len(&self) -> usize {
78        self.parts.iter().fold(self.sign.len(), |len, part| len.saturating_add(part.len()))
79    }
80
81    /// Writes all formatted parts into the supplied buffer.
82    /// Returns the number of written bytes, or `None` if the buffer is not enough.
83    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
84    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
85        out.get_mut(..self.sign.len())?.copy_from_slice(self.sign.as_bytes());
86
87        let mut written = self.sign.len();
88        for part in self.parts {
89            let len = part.write(&mut out[written..])?;
90            written += len;
91        }
92        Some(written)
93    }
94}