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