-
Notifications
You must be signed in to change notification settings - Fork 678
/
lib.rs
63 lines (55 loc) · 1.71 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Source adopted from
// https://github.com/tildeio/helix-website/blob/master/crates/word_count/src/lib.rs
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use rayon::prelude::*;
/// Searches for the word, parallelized by rayon
#[pyfunction]
fn search(contents: &str, needle: &str) -> usize {
contents
.par_lines()
.map(|line| count_line(line, needle))
.sum()
}
/// Searches for a word in a classic sequential fashion
#[pyfunction]
fn search_sequential(contents: &str, needle: &str) -> usize {
contents.lines().map(|line| count_line(line, needle)).sum()
}
#[pyfunction]
fn search_sequential_allow_threads(py: Python, contents: &str, needle: &str) -> usize {
py.allow_threads(|| search_sequential(contents, needle))
}
fn matches(word: &str, needle: &str) -> bool {
let mut needle = needle.chars();
for ch in word.chars().skip_while(|ch| !ch.is_alphabetic()) {
match needle.next() {
None => {
return !ch.is_alphabetic();
}
Some(expect) => {
if ch.to_lowercase().next() != Some(expect) {
return false;
}
}
}
}
needle.next().is_none()
}
/// Count the occurences of needle in line, case insensitive
fn count_line(line: &str, needle: &str) -> usize {
let mut total = 0;
for word in line.split(' ') {
if matches(word, needle) {
total += 1;
}
}
total
}
#[pymodule]
fn word_count(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(search))?;
m.add_function(wrap_pyfunction!(search_sequential))?;
m.add_function(wrap_pyfunction!(search_sequential_allow_threads))?;
Ok(())
}