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)] |
11 | pub 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 | |
20 | impl<'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)] |
75 | pub 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 | |
82 | impl<'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 | |