rs-sim-basic 0.1.0

Simple CLI to print similarity score of the lines.
Documentation
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(())
    }
}