use crate::sink::Sink;
pub(crate) fn write_i64(n: i64, out: &mut dyn Sink) {
if n < 0 {
out.push_str("-");
}
write_u64(n.unsigned_abs(), out);
}
pub(crate) fn write_u64(n: u64, out: &mut dyn Sink) {
let mut buf = [0u8; 20];
out.push_str(u64_str(n, &mut buf));
}
pub(crate) fn u64_str(mut n: u64, buf: &mut [u8; 20]) -> &str {
let mut at = buf.len();
loop {
at -= 1;
#[allow(clippy::cast_possible_truncation)]
let d = (n % 10) as u8;
if let Some(b) = buf.get_mut(at) {
*b = b'0' + d;
}
n /= 10;
if n == 0 || at == 0 {
break;
}
}
let digits = buf.get(at..).unwrap_or(&[]);
core::str::from_utf8(digits).unwrap_or("")
}
#[inline]
pub(crate) fn nfc_quick(s: &str) -> bool {
s.bytes().all(|b| b < 0xCC)
}
pub(crate) fn write_escaped_literal(s: &str, out: &mut dyn Sink) {
let mut start = 0;
for (i, b) in s.bytes().enumerate() {
if b == b'\\' || b == b'|' {
out.push_str(s.get(start..i).unwrap_or(""));
out.push_str(if b == b'\\' { "\\\\" } else { "\\|" });
start = i + 1;
}
}
out.push_str(s.get(start..).unwrap_or(""));
}
#[cfg(test)]
mod tests {
extern crate std;
use alloc::string::String;
use super::{nfc_quick, write_escaped_literal, write_i64};
#[test]
fn integers() {
for n in [0i64, 7, -7, 10, 1_000_000, i64::MAX, i64::MIN] {
let mut s = String::new();
write_i64(n, &mut s);
assert_eq!(s, std::format!("{n}"));
}
}
#[test]
fn escaping() {
let mut s = String::new();
write_escaped_literal(r"C:\a|b", &mut s);
assert_eq!(s, r"C:\\a\|b");
}
#[test]
fn quick_check() {
assert!(nfc_quick("hello é"));
assert!(!nfc_quick("e\u{301}"));
assert!(!nfc_quick("\u{1e0a}"));
}
}