1 | //! Defines the pipeline which processes text for inclusion in the index. Most users do not need |
2 | //! to use this module directly. |
3 | |
4 | use serde::ser::{Serialize, SerializeSeq, Serializer}; |
5 | |
6 | pub trait PipelineFn { |
7 | fn name(&self) -> String; |
8 | |
9 | fn filter(&self, token: String) -> Option<String>; |
10 | } |
11 | |
12 | #[derive (Clone)] |
13 | pub struct FnWrapper(pub String, pub fn(String) -> Option<String>); |
14 | |
15 | impl PipelineFn for FnWrapper { |
16 | fn name(&self) -> String { |
17 | self.0.clone() |
18 | } |
19 | |
20 | fn filter(&self, token: String) -> Option<String> { |
21 | (self.1)(token) |
22 | } |
23 | } |
24 | |
25 | /// A sequence of `PipelineFn`s which are run on tokens to prepare them for searching. |
26 | #[derive (Deserialize)] |
27 | pub struct Pipeline { |
28 | #[serde(skip_deserializing)] |
29 | pub queue: Vec<Box<dyn PipelineFn>>, |
30 | } |
31 | |
32 | impl Serialize for Pipeline { |
33 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
34 | where |
35 | S: Serializer, |
36 | { |
37 | let mut seq: ::SerializeSeq = serializer.serialize_seq(len:Some(self.queue.len()))?; |
38 | for elem: &Box in &self.queue { |
39 | seq.serialize_element(&elem.name())?; |
40 | } |
41 | seq.end() |
42 | } |
43 | } |
44 | |
45 | impl Pipeline { |
46 | /// Run the Pipeline against the given vector of tokens. The returned vector may be shorter |
47 | /// than the input if a pipeline function returns `None` for a token. |
48 | pub fn run(&self, tokens: Vec<String>) -> Vec<String> { |
49 | let mut ret: Vec = vec![]; |
50 | for token: String in tokens { |
51 | let mut token: Option = Some(token); |
52 | for func: &Box in &self.queue { |
53 | if let Some(t: String) = token { |
54 | token = func.filter(token:t); |
55 | } else { |
56 | break; |
57 | } |
58 | } |
59 | if let Some(t: String) = token { |
60 | ret.push(t); |
61 | } |
62 | } |
63 | ret |
64 | } |
65 | } |
66 | |