1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! 浮点和整数格式使用的共享实用工具。
#![doc(hidden)]
#![unstable(
    feature = "numfmt",
    reason = "internal routines only exposed for testing",
    issue = "none"
)]

/// 格式化的零件。
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Part<'a> {
    /// 给定零位数。
    Zero(usize),
    /// 字面量数字,最多 5 位。
    Num(u16),
    /// 给定字节的逐字副本。
    Copy(&'a [u8]),
}

impl<'a> Part<'a> {
    /// 返回给定部分的确切字节长度。
    pub fn len(&self) -> usize {
        match *self {
            Part::Zero(nzeroes) => nzeroes,
            Part::Num(v) => {
                if v < 1_000 {
                    if v < 10 {
                        1
                    } else if v < 100 {
                        2
                    } else {
                        3
                    }
                } else {
                    if v < 10_000 { 4 } else { 5 }
                }
            }
            Part::Copy(buf) => buf.len(),
        }
    }

    /// 将零件写入提供的缓冲区。
    /// 返回写入的字节数,如果缓冲区不足,则返回 `None`。
    /// (它可能仍会将部分写入的字节保留在缓冲区中; 不要依赖于此。)
    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
        let len = self.len();
        if out.len() >= len {
            match *self {
                Part::Zero(nzeroes) => {
                    for c in &mut out[..nzeroes] {
                        *c = b'0';
                    }
                }
                Part::Num(mut v) => {
                    for c in out[..len].iter_mut().rev() {
                        *c = b'0' + (v % 10) as u8;
                        v /= 10;
                    }
                }
                Part::Copy(buf) => {
                    out[..buf.len()].copy_from_slice(buf);
                }
            }
            Some(len)
        } else {
            None
        }
    }
}

/// 包含一个或多个部分的格式化结果。
/// 可以将其写入字节缓冲区或转换为分配的字符串。
#[allow(missing_debug_implementations)]
#[derive(Clone)]
pub struct Formatted<'a> {
    /// 表示符号 (`""`,`"-"` 或 `"+"`) 的字节切片。
    pub sign: &'static str,
    /// 在符号和可选的零填充之后要渲染的格式化部分。
    pub parts: &'a [Part<'a>],
}

impl<'a> Formatted<'a> {
    /// 返回组合格式结果的确切字节长度。
    pub fn len(&self) -> usize {
        let mut len = self.sign.len();
        for part in self.parts {
            len += part.len();
        }
        len
    }

    /// 将所有格式化的部分写入提供的缓冲区。
    /// 返回写入的字节数,如果缓冲区不足,则返回 `None`。
    /// (它可能仍会将部分写入的字节保留在缓冲区中; 不要依赖于此。)
    pub fn write(&self, out: &mut [u8]) -> Option<usize> {
        if out.len() < self.sign.len() {
            return None;
        }
        out[..self.sign.len()].copy_from_slice(self.sign.as_bytes());

        let mut written = self.sign.len();
        for part in self.parts {
            let len = part.write(&mut out[written..])?;
            written += len;
        }
        Some(written)
    }
}