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) => {
26                if v < 1_000 {
27                    if v < 10 {
28                        1
29                    } else if v < 100 {
30                        2
31                    } else {
32                        3
33                    }
34                } else {
35                    if v < 10_000 { 4 } else { 5 }
36                }
37            }
38            Part::Copy(buf) => buf.len(),
39        }
40    }
41
42    /// Writes a part into the supplied buffer.
43    /// Returns the number of written bytes, or `None` if the buffer is not enough.
44    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
45    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
46        let len = self.len();
47        if out.len() >= len {
48            match *self {
49                Part::Zero(nzeroes) => {
50                    for c in &mut out[..nzeroes] {
51                        *c = b'0';
52                    }
53                }
54                Part::Num(mut v) => {
55                    for c in out[..len].iter_mut().rev() {
56                        *c = b'0' + (v % 10) as u8;
57                        v /= 10;
58                    }
59                }
60                Part::Copy(buf) => {
61                    out[..buf.len()].copy_from_slice(buf);
62                }
63            }
64            Some(len)
65        } else {
66            None
67        }
68    }
69}
70
71/// Formatted result containing one or more parts.
72/// This can be written to the byte buffer or converted to the allocated string.
73#[allow(missing_debug_implementations)]
74#[derive(Clone)]
75pub struct Formatted<'a> {
76    /// A byte slice representing a sign, either `""`, `"-"` or `"+"`.
77    pub sign: &'static str,
78    /// Formatted parts to be rendered after a sign and optional zero padding.
79    pub parts: &'a [Part<'a>],
80}
81
82impl<'a> Formatted<'a> {
83    /// Returns the exact byte length of combined formatted result.
84    pub fn len(&self) -> usize {
85        let mut len = self.sign.len();
86        for part in self.parts {
87            len += part.len();
88        }
89        len
90    }
91
92    /// Writes all formatted parts into the supplied buffer.
93    /// Returns the number of written bytes, or `None` if the buffer is not enough.
94    /// (It may still leave partially written bytes in the buffer; do not rely on that.)
95    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
96        if out.len() < self.sign.len() {
97            return None;
98        }
99        out[..self.sign.len()].copy_from_slice(self.sign.as_bytes());
100
101        let mut written = self.sign.len();
102        for part in self.parts {
103            let len = part.write(&mut out[written..])?;
104            written += len;
105        }
106        Some(written)
107    }
108}