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}
109