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