use std::io;
use io::Write;
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct Candidate {
score: u32,
content: String,
}
pub fn lines2candidates<I, F>(
lines: I,
target: String,
tgt2score: F,
) -> impl Iterator<Item = Result<Candidate, io::Error>>
where
I: Iterator<Item = Result<String, io::Error>>,
F: Fn(&str, String) -> Result<Candidate, io::Error>,
{
lines.map(move |rline| {
let line: String = rline?;
let cand: Candidate = tgt2score(&target, line)?;
Ok(cand)
})
}
pub fn zip2score(tgt: &str, line: String) -> Result<Candidate, io::Error> {
let tc = tgt.chars();
let lc = line.chars();
let zipped = tc.zip(lc);
let filtered = zipped.filter(|pair| {
let (t, l) = pair;
t.eq(l)
});
let cnt: usize = filtered.count();
let score: u32 = cnt.try_into().ok().unwrap_or(u32::MAX);
Ok(Candidate {
score,
content: line,
})
}
pub fn lines2candidates_zip2score<I>(
lines: I,
target: String,
) -> impl Iterator<Item = Result<Candidate, io::Error>>
where
I: Iterator<Item = Result<String, io::Error>>,
{
lines2candidates(lines, target, zip2score)
}
pub struct Ltsv {
pub sep1: String,
pub sep2: String,
}
impl Default for Ltsv {
fn default() -> Self {
Self {
sep1: ":".into(),
sep2: "\t".into(),
}
}
}
impl Ltsv {
pub fn into_candidate_writer<W>(
self,
mut wtr: W,
) -> impl FnMut(&Candidate) -> Result<(), io::Error>
where
W: Write,
{
move |c: &Candidate| {
let score: u32 = c.score;
let line: &str = &c.content;
let csep: &str = &self.sep1;
let tsep: &str = &self.sep2;
writeln!(&mut wtr, "score{csep}{score}{tsep}line{csep}{line}")
}
}
}
pub fn candidates2writer<I, W>(ic: I, mut cwtr: W) -> impl FnOnce() -> Result<(), io::Error>
where
I: Iterator<Item = Result<Candidate, io::Error>>,
W: FnMut(&Candidate) -> Result<(), io::Error>,
{
move || {
for rc in ic {
let c: Candidate = rc?;
cwtr(&c)?;
}
Ok(())
}
}