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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use crate::tokens;
use crate::Dictionary;
use std::borrow::Cow;
pub fn check_str<'b, 's: 'b>(
buffer: &'b str,
tokenizer: &'s tokens::Tokenizer,
dictionary: &'s dyn Dictionary,
) -> impl Iterator<Item = Typo<'b>> {
tokenizer
.parse_str(buffer)
.flat_map(move |ident| process_ident(ident, dictionary))
}
pub fn check_bytes<'b, 's: 'b>(
buffer: &'b [u8],
tokenizer: &'s tokens::Tokenizer,
dictionary: &'s dyn Dictionary,
) -> impl Iterator<Item = Typo<'b>> {
tokenizer
.parse_bytes(buffer)
.flat_map(move |ident| process_ident(ident, dictionary))
}
fn process_ident<'i, 's: 'i>(
ident: tokens::Identifier<'i>,
dictionary: &'s dyn Dictionary,
) -> impl Iterator<Item = Typo<'i>> {
match dictionary.correct_ident(ident) {
Some(crate::Status::Valid) => itertools::Either::Left(None.into_iter()),
Some(corrections) => {
let typo = Typo {
byte_offset: ident.offset(),
typo: ident.token().into(),
corrections,
};
itertools::Either::Left(Some(typo).into_iter())
}
None => itertools::Either::Right(
ident
.split()
.filter_map(move |word| process_word(word, dictionary)),
),
}
}
fn process_word<'w, 's: 'w>(
word: tokens::Word<'w>,
dictionary: &'s dyn Dictionary,
) -> Option<Typo<'w>> {
match dictionary.correct_word(word) {
Some(crate::Status::Valid) => None,
Some(corrections) => {
let typo = Typo {
byte_offset: word.offset(),
typo: word.token().into(),
corrections,
};
Some(typo)
}
None => None,
}
}
#[derive(Clone, Debug)]
pub struct Typo<'m> {
pub byte_offset: usize,
pub typo: Cow<'m, str>,
pub corrections: crate::Status<'m>,
}
impl<'m> Typo<'m> {
pub fn into_owned(self) -> Typo<'static> {
Typo {
byte_offset: self.byte_offset,
typo: Cow::Owned(self.typo.into_owned()),
corrections: self.corrections.into_owned(),
}
}
pub fn borrow(&self) -> Typo<'_> {
Typo {
byte_offset: self.byte_offset,
typo: Cow::Borrowed(self.typo.as_ref()),
corrections: self.corrections.borrow(),
}
}
}
impl<'m> Default for Typo<'m> {
fn default() -> Self {
Self {
byte_offset: 0,
typo: "".into(),
corrections: crate::Status::Invalid,
}
}
}