use std::fmt::Write;
use std::u16;
use std::u32;
pub(crate) const BSLASH: u8 = b'\\';
pub(crate) const BSLASH_U16: u16 = BSLASH as u16;
const SURROGATE_OFFSET: i64 = 0x1_0000 - (0xD800 << 10) - 0xDC00;
pub(crate) fn to_utf32(v: &[u16]) -> u32 {
if v.len() == 1 {
v[0] as u32
} else if v.len() == 2 {
let lead = v[0] as i64;
let trail = v[1] as i64;
((lead << 10) + trail + SURROGATE_OFFSET) as u32
} else {
panic!("invalid len: {}", v.len());
}
}
pub(crate) fn escape_u8(dst: &mut String, encoder: &super::Encoder, b: u8) {
match b {
b'\\' => dst.push_str(r"\\"),
b'\t' => {
if encoder.encode_tab {
dst.push_str("\\t");
} else {
dst.push(b as char);
}
}
b'\n' => {
if encoder.encode_line_feed {
dst.push_str("\\n");
} else {
dst.push(b as char);
}
}
b'\r' => {
if encoder.encode_cariage {
dst.push_str("\\r");
} else {
dst.push(b as char);
}
}
_ => write!(dst, r"\x{:0>2X}", b).unwrap(),
}
}
pub(crate) fn escape_u16(dst: &mut String, c16: u16) {
write!(dst, r"\u{:0>6X}", c16).unwrap();
}
#[cfg(test)]
mod tests {
use super::*;
fn assert_conversions(s: &str, expect_suplimental: bool) {
let mut got_suplimental = false;
for c in s.chars() {
let mut expected = [0_u16; 2];
let mut c16 = [0_u16; 2];
let expected = c.encode_utf16(&mut expected);
let c16 = c.encode_utf16(&mut c16);
if expected.len() == 2 {
got_suplimental = true
}
assert_eq!(expected, c16);
let c32 = to_utf32(c16);
assert_eq!(c as u32, c32);
}
assert_eq!(expect_suplimental, got_suplimental);
}
#[test]
fn sanity_utf_conversion() {
assert_conversions("foo bar", false);
assert_conversions("foo bar", false);
assert_conversions("¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ", false);
assert_conversions(" ʰ ʱ ʲ ʳ ʴ ʵ ʶ ʷ ʸ ʹ ʺ ʻ", false);
assert_conversions("܀ ܁ ܂ ܃ ܄ ܅ ܆ ܇ ܈ ܉ ܊ ܋ ܌ ܍ ", false);
assert_conversions("Ꭰ Ꭱ Ꭲ Ꭳ Ꭴ Ꭵ Ꭶ Ꭷ Ꭸ Ꭹ", false);
assert_conversions("ἀ ἁ ἂ ἃ ἄ ἅ ἆ ἇ Ἀ Ἁ", false);
assert_conversions(" ‐ ", false);
assert_conversions("‑ ‒ – — ― ‖ ‗ ‘ ’ ‚ ‛ “", false);
assert_conversions(" ⃐ ⃑ ⃒ ⃓ ⃔ ⃕ ⃖ ⃗ ⃘ ⃙ ⃚ ⃛ ⃜ ⃝ ⃞ ⃟ ⃠ ⃡ ⃢ ⃣ ⃤ ⃥ ⃦ ⃧ ⃨ ⃩ ⃪ ", false);
assert_conversions("⟰ ⟱ ⟲ ⟳ ⟴ ⟵ ⟶ ⟷ ⟸ ⟹ ⟺ ⟻ ⟼ ⟽ ⟾ ⟿", false);
assert_conversions(
"𠜎 𠜎 𠜱 𠜱 𠝹 𠝹 𠱓 𠱓 𠱸 𠱸 𠲖 𠲖 𠳏 𠳏 𠳕 𠳕 𠴕 𠴕 𠵼 𠵼 𠵿 𠵿 𠸎 𠸎 𠸏 𠸏",
true,
);
}
}