commit 1c1f51c8fcad81d39a85c6449300710a53cad117 Author: kageru Date: Sat May 18 15:06:42 2019 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f0e3bca --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ad61e54 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "rust-fzf" +version = "0.1.0" + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..dc423ec --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rust-fzf" +version = "0.1.0" +authors = ["kageru "] +edition = "2018" + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..8b9d305 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,91 @@ +pub fn filter_substring<'a>(needle: &str, haystack: &Vec<&'a str>) -> Vec<&'a str> { + return haystack + .iter() + .filter(|s| s.contains(needle)) + .cloned() + .collect(); +} + +pub fn filter_subsequence<'a>(needle: &str, haystack: &Vec<&'a str>) -> Vec<&'a str> { + return haystack + .iter() + .filter(|s| is_subsequence(needle, s)) + .cloned() + .collect(); +} + +fn is_subsequence(needle: &str, string: &str) -> bool { + // we need to explicitly convert here to iterate over chars + // (UTF-8, so possibly multiple bytes long) + let mut chars = string.chars(); + let needle_chars = needle.chars(); + for nc in needle_chars { + loop { + match chars.next() { + Some(current) => { + // if the character matches, break and continue with the next nc + if current == nc { + break; + } + } + _ => return false + } + } + } + true +} + +#[cfg(test)] +mod tests { + use crate::{ + filter_substring, + filter_subsequence + }; + + #[test] + fn test_filter_substring_single() { + let needle = "sdf"; + let hay = vec!["asdf", "qwer"]; + let expected = vec!["asdf"]; + assert_eq!(filter_substring(&needle, &hay), expected); + } + + #[test] + fn test_filter_substring_none() { + let needle = "sdf"; + let hay = vec!["qwertz"]; + let expected: Vec<&str> = Vec::new(); + assert_eq!(filter_substring(&needle, &hay), expected); + } + + #[test] + fn test_filter_substring_multiple() { + let needle = "sdf"; + let hay = vec!["asdf", "asd", "sdfg", "dfgh"]; + let expected = vec!["asdf", "sdfg"]; + assert_eq!(filter_substring(&needle, &hay), expected); + } + + #[test] + fn test_filter_subsequence_single() { + let needle = "asa"; + let hay = vec!["aaass", "aasda"]; + let expected = vec!["aasda"]; + assert_eq!(filter_subsequence(&needle, &hay), expected); + } + + #[test] + fn test_filter_subsequence_none() { + let needle = "asa"; + let hay = vec!["aas"]; + let expected: Vec<&str> = Vec::new(); + assert_eq!(filter_subsequence(&needle, &hay), expected); + } + + #[test] + fn test_filter_subsequence_multiple() { + let needle = "asa"; + let hay = vec!["asa", "assa", "qwerafwfsferfssaas"]; + assert_eq!(filter_subsequence(&needle, &hay), hay); + } +}