use std::io::{self, Write};
use std::str::FromStr;
use crate::corpus::{
FIELD_ALT_NAME, FIELD_BIDI, FIELD_BLOCK, FIELD_CATEGORY, FIELD_COMBINING, FIELD_DECIMAL,
FIELD_DECOMP, FIELD_DIGIT, FIELD_GLYPH, FIELD_ICON_SET, FIELD_LOWERCASE, FIELD_MIRRORED,
FIELD_NUMERIC, FIELD_SOURCE, FIELD_TITLECASE, FIELD_UPPERCASE, Idx, codepoint, entry_name,
entry_str,
};
pub enum Format {
Plain,
Pretty,
Tsv,
}
impl FromStr for Format {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"plain" => Ok(Self::Plain),
"pretty" => Ok(Self::Pretty),
"tsv" => Ok(Self::Tsv),
_ => Err("unknown format; use plain, pretty, or tsv"),
}
}
}
pub fn print_entry(w: &mut impl Write, idx: Idx, fmt: &Format) -> io::Result<()> {
match fmt {
Format::Plain => writeln!(w, "{}", entry_str(idx, FIELD_GLYPH)),
Format::Pretty => writeln!(
w,
"{}\tU+{:04X}\t{}\t{}",
entry_str(idx, FIELD_GLYPH),
codepoint(idx),
entry_name(idx),
entry_str(idx, FIELD_BLOCK),
),
Format::Tsv => writeln!(
w,
"{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
codepoint(idx),
entry_str(idx, FIELD_GLYPH),
entry_name(idx),
entry_str(idx, FIELD_SOURCE),
entry_str(idx, FIELD_CATEGORY),
entry_str(idx, FIELD_COMBINING),
entry_str(idx, FIELD_BIDI),
entry_str(idx, FIELD_DECOMP),
entry_str(idx, FIELD_DECIMAL),
entry_str(idx, FIELD_DIGIT),
entry_str(idx, FIELD_NUMERIC),
entry_str(idx, FIELD_MIRRORED),
entry_str(idx, FIELD_ALT_NAME),
entry_str(idx, FIELD_UPPERCASE),
entry_str(idx, FIELD_LOWERCASE),
entry_str(idx, FIELD_TITLECASE),
entry_str(idx, FIELD_BLOCK),
entry_str(idx, FIELD_ICON_SET),
),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::corpus::lookup;
fn sample_idx() -> Idx {
lookup(0x0041).expect("A should be in corpus")
}
#[test]
fn format_from_str_plain() {
let f: Format = "plain".parse().expect("plain is valid");
assert!(matches!(f, Format::Plain));
}
#[test]
fn format_from_str_pretty() {
let f: Format = "pretty".parse().expect("pretty is valid");
assert!(matches!(f, Format::Pretty));
}
#[test]
fn format_from_str_tsv() {
let f: Format = "tsv".parse().expect("tsv is valid");
assert!(matches!(f, Format::Tsv));
}
#[test]
fn format_from_str_invalid() {
assert!("badger".parse::<Format>().is_err());
}
#[test]
fn print_plain_format() {
let idx = sample_idx();
let mut buf = Vec::new();
print_entry(&mut buf, idx, &Format::Plain).expect("write should succeed");
let s = String::from_utf8(buf).expect("buf should be utf-8");
assert_eq!(s, "A\n");
}
#[test]
fn print_pretty_format() {
let idx = sample_idx();
let mut buf = Vec::new();
print_entry(&mut buf, idx, &Format::Pretty).expect("write should succeed");
let s = String::from_utf8(buf).expect("buf should be utf-8");
assert_eq!(s, "A\tU+0041\tLATIN CAPITAL LETTER A\tBasic Latin\n");
}
#[test]
fn print_tsv_format() {
let idx = sample_idx();
let mut buf = Vec::new();
print_entry(&mut buf, idx, &Format::Tsv).expect("write should succeed");
let s = String::from_utf8(buf).expect("buf should be utf-8");
assert!(s.starts_with("65\tA\tLATIN CAPITAL LETTER A\tunicode"));
assert!(s.ends_with("\tBasic Latin\t\n"));
}
}