use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fs::File;
use std::io::{BufReader, BufWriter};
use std::path::Path;
use std::vec;
use strsim::levenshtein;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Post {
pub id: usize,
pub command: String,
pub comment: String,
}
impl Post {
pub fn new(id: usize, command: String, comment: String) -> Self {
Self {
id,
command,
comment,
}
}
}
pub fn write_it(filename: &str, post: &Vec<Post>) -> Result<(), Box<dyn Error>> {
let file = File::create(filename)?;
let writer = BufWriter::new(file);
serde_json::to_writer_pretty(writer, post)?;
Ok(())
}
pub fn read_it(filename: &str) -> Result<Vec<Post>, Box<dyn Error>> {
if !Path::new(filename).exists() {
return Ok(Vec::new());
}
let file = File::open(filename)?;
let reader = BufReader::new(file);
let posts = serde_json::from_reader(reader)?;
Ok(posts)
}
pub fn create_it(
command: String,
comment: String,
posts: &mut Vec<Post>,
) -> Result<(), Box<dyn Error>> {
let last_id = match posts.last() {
Some(value) => value.id + 1,
None => 0,
};
let post = Post::new(last_id, command, comment);
posts.push(post);
Ok(())
}
pub fn search_it<'a>(needle: &str, haystack: &'a [Post]) -> Vec<&'a Post> {
if needle.is_empty() {
return Vec::new();
}
let nedl = needle.to_lowercase();
let mut scoreboard: Vec<(usize, usize)> = vec![];
let mut sorted_matches: Vec<&Post> = vec![];
for (index, post) in haystack.iter().enumerate() {
let hay: Vec<char> = format!("{}{}", post.command, post.comment)
.to_lowercase()
.chars()
.collect();
let mut score: usize = nedl.chars().count();
for window in hay.windows(needle.len()) {
let wind: String = window.iter().collect();
let cscore = levenshtein(&nedl, &wind);
if cscore < score {
score = cscore;
}
}
scoreboard.push((score, index));
}
scoreboard.sort_by_key(|t| t.0);
for scores in scoreboard {
sorted_matches.push(&haystack[scores.1]);
}
sorted_matches
}