fmt.rs - source
Description: Source of the Rust file `library/core/src/num/fmt.rs`.

#
core/num/
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(Copy, Clone, PartialEq, Eq, 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(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 exact byte length of combined formatted result.
    72    pub fn len(&self) -> usize {
    73        self.sign.len() + self.parts.iter().map(|part| part.len()).sum::<usize>()
    74    }
    75
    76    /// Writes all formatted parts into the supplied buffer.
    77    /// Returns the number of written bytes, or `None` if the buffer is not enough.
    78    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
    79    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
    80        out.get_mut(..self.sign.len())?.copy_from_slice(self.sign.as_bytes());
    81
    82        let mut written = self.sign.len();
    83        for part in self.parts {
    84            let len = part.write(&mut out[written..])?;
    85            written += len;
    86        }
    87        Some(written)
    88    }
    89}