zeppelin_embed/fts/tokenizer/
profiles.rs1use super::stopwords::StopwordList;
8use super::vocab::Vocabulary;
9use super::{FoldingForm, Segmenter, Stemmer, TokenizerConfig};
10
11#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
13#[repr(u16)]
14pub enum Profile {
15 TextDefault = 1,
20 Code = 2,
25 Voice = 3,
30}
31
32impl Profile {
33 #[must_use]
35 pub const fn id(self) -> u16 {
36 self as u16
37 }
38
39 #[must_use]
41 pub fn config(self) -> TokenizerConfig {
42 let (stopwords, stemmer, number_words) = match self {
43 Self::TextDefault => (StopwordList::LuceneEnglish, Stemmer::EnglishPorter2, true),
44 Self::Code => (StopwordList::None, Stemmer::None, false),
45 Self::Voice => (StopwordList::LuceneEnglish, Stemmer::EnglishPorter2, true),
46 };
47 let drop_single_char_parts = !matches!(self, Self::Code);
51 TokenizerConfig {
52 profile: self,
53 segmenter: Segmenter::IdentifierPreserving,
54 folding: FoldingForm::NfkcSearchFold,
55 stopwords,
56 stemmer,
57 decompose_words: true,
58 emit_catenation: true,
59 number_words,
60 drop_single_char_parts,
61 vocabulary: Vocabulary::new(),
62 }
63 }
64}
65
66#[cfg(test)]
67#[allow(clippy::expect_used, clippy::indexing_slicing, clippy::unwrap_used)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn every_profile_has_a_distinct_epoch() {
73 let epochs = [Profile::TextDefault, Profile::Code, Profile::Voice]
74 .map(|profile| profile.config().epoch());
75 assert_ne!(epochs[0], epochs[1]);
76 assert_ne!(epochs[1], epochs[2]);
77 assert_ne!(epochs[0], epochs[2]);
78 }
79
80 #[test]
81 fn the_code_profile_neither_stems_nor_drops_stopwords() {
82 let config = Profile::Code.config();
83 assert_eq!(config.stemmer, Stemmer::None);
84 assert_eq!(config.stopwords, StopwordList::None);
85 }
86
87 #[test]
88 fn profile_ids_are_stable() {
89 assert_eq!(Profile::TextDefault.id(), 1);
90 assert_eq!(Profile::Code.id(), 2);
91 assert_eq!(Profile::Voice.id(), 3);
92 }
93}