Skip to main content

lb_tantivy/schema/
bytes_options.rs

1use std::ops::BitOr;
2
3use serde::{Deserialize, Serialize};
4
5use super::flags::{FastFlag, IndexedFlag, SchemaFlagList, StoredFlag};
6/// Define how a bytes field should be handled by tantivy.
7#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(from = "BytesOptionsDeser")]
9pub struct BytesOptions {
10    indexed: bool,
11    fieldnorms: bool,
12    fast: bool,
13    stored: bool,
14}
15
16/// For backward compatibility we add an intermediary to interpret the
17/// lack of fieldnorms attribute as "true" if and only if indexed.
18///
19/// (Downstream, for the moment, this attribute is not used if not indexed...)
20/// Note that: newly serialized NumericOptions will include the new attribute.
21#[derive(Deserialize)]
22struct BytesOptionsDeser {
23    indexed: bool,
24    #[serde(default)]
25    fieldnorms: Option<bool>,
26    fast: bool,
27    stored: bool,
28}
29
30impl From<BytesOptionsDeser> for BytesOptions {
31    fn from(deser: BytesOptionsDeser) -> Self {
32        BytesOptions {
33            indexed: deser.indexed,
34            fieldnorms: deser.fieldnorms.unwrap_or(deser.indexed),
35            fast: deser.fast,
36            stored: deser.stored,
37        }
38    }
39}
40
41impl BytesOptions {
42    /// Returns true if the value is indexed.
43    #[inline]
44    pub fn is_indexed(&self) -> bool {
45        self.indexed
46    }
47
48    /// Returns true if and only if the value is normed.
49    #[inline]
50    pub fn fieldnorms(&self) -> bool {
51        self.fieldnorms
52    }
53
54    /// Returns true if the value is a fast field.
55    #[inline]
56    pub fn is_fast(&self) -> bool {
57        self.fast
58    }
59
60    /// Returns true if the value is stored.
61    #[inline]
62    pub fn is_stored(&self) -> bool {
63        self.stored
64    }
65
66    /// Set the field as indexed.
67    ///
68    /// Setting an integer as indexed will generate
69    /// a posting list for each value taken by the integer.
70    #[must_use]
71    pub fn set_indexed(mut self) -> BytesOptions {
72        self.indexed = true;
73        self
74    }
75
76    /// Set the field as normed.
77    ///
78    /// Setting an integer as normed will generate
79    /// the fieldnorm data for it.
80    #[must_use]
81    pub fn set_fieldnorms(mut self) -> BytesOptions {
82        self.fieldnorms = true;
83        self
84    }
85
86    /// Set the field as a fast field.
87    ///
88    /// Fast fields are designed for random access.
89    #[must_use]
90    pub fn set_fast(mut self) -> BytesOptions {
91        self.fast = true;
92        self
93    }
94
95    /// Set the field as stored.
96    ///
97    /// Only the fields that are set as *stored* are
98    /// persisted into the Tantivy's store.
99    #[must_use]
100    pub fn set_stored(mut self) -> BytesOptions {
101        self.stored = true;
102        self
103    }
104}
105
106impl<T: Into<BytesOptions>> BitOr<T> for BytesOptions {
107    type Output = BytesOptions;
108
109    fn bitor(self, other: T) -> BytesOptions {
110        let other = other.into();
111        BytesOptions {
112            indexed: self.indexed | other.indexed,
113            fieldnorms: self.fieldnorms | other.fieldnorms,
114            stored: self.stored | other.stored,
115            fast: self.fast | other.fast,
116        }
117    }
118}
119
120impl From<()> for BytesOptions {
121    fn from(_: ()) -> Self {
122        Self::default()
123    }
124}
125
126impl From<FastFlag> for BytesOptions {
127    fn from(_: FastFlag) -> Self {
128        BytesOptions {
129            indexed: false,
130            fieldnorms: false,
131            stored: false,
132            fast: true,
133        }
134    }
135}
136
137impl From<StoredFlag> for BytesOptions {
138    fn from(_: StoredFlag) -> Self {
139        BytesOptions {
140            indexed: false,
141            fieldnorms: false,
142            stored: true,
143            fast: false,
144        }
145    }
146}
147
148impl From<IndexedFlag> for BytesOptions {
149    fn from(_: IndexedFlag) -> Self {
150        BytesOptions {
151            indexed: true,
152            fieldnorms: true,
153            stored: false,
154            fast: false,
155        }
156    }
157}
158
159impl<Head, Tail> From<SchemaFlagList<Head, Tail>> for BytesOptions
160where
161    Head: Clone,
162    Tail: Clone,
163    Self: BitOr<Output = Self> + From<Head> + From<Tail>,
164{
165    fn from(head_tail: SchemaFlagList<Head, Tail>) -> Self {
166        Self::from(head_tail.head) | Self::from(head_tail.tail)
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use crate::schema::{BytesOptions, FAST, INDEXED, STORED};
173
174    #[test]
175    fn test_bytes_option_fast_flag() {
176        assert_eq!(BytesOptions::default().set_fast(), FAST.into());
177        assert_eq!(
178            BytesOptions::default().set_indexed().set_fieldnorms(),
179            INDEXED.into()
180        );
181        assert_eq!(BytesOptions::default().set_stored(), STORED.into());
182    }
183    #[test]
184    fn test_bytes_option_fast_flag_composition() {
185        assert_eq!(
186            BytesOptions::default().set_fast().set_stored(),
187            (FAST | STORED).into()
188        );
189        assert_eq!(
190            BytesOptions::default()
191                .set_indexed()
192                .set_fieldnorms()
193                .set_fast(),
194            (INDEXED | FAST).into()
195        );
196        assert_eq!(
197            BytesOptions::default()
198                .set_stored()
199                .set_fieldnorms()
200                .set_indexed(),
201            (STORED | INDEXED).into()
202        );
203    }
204
205    #[test]
206    fn test_bytes_option_fast_() {
207        assert!(!BytesOptions::default().is_stored());
208        assert!(!BytesOptions::default().is_fast());
209        assert!(!BytesOptions::default().is_indexed());
210        assert!(!BytesOptions::default().fieldnorms());
211        assert!(BytesOptions::default().set_stored().is_stored());
212        assert!(BytesOptions::default().set_fast().is_fast());
213        assert!(BytesOptions::default().set_indexed().is_indexed());
214        assert!(BytesOptions::default().set_fieldnorms().fieldnorms());
215    }
216
217    #[test]
218    fn test_bytes_options_deser_if_fieldnorm_missing_indexed_true() {
219        let json = r#"{
220            "indexed": true,
221            "fast": false,
222            "stored": false
223        }"#;
224        let bytes_options: BytesOptions = serde_json::from_str(json).unwrap();
225        assert_eq!(
226            &bytes_options,
227            &BytesOptions {
228                indexed: true,
229                fieldnorms: true,
230                fast: false,
231                stored: false
232            }
233        );
234    }
235
236    #[test]
237    fn test_bytes_options_deser_if_fieldnorm_missing_indexed_false() {
238        let json = r#"{
239            "indexed": false,
240            "stored": false,
241            "fast": false
242        }"#;
243        let bytes_options: BytesOptions = serde_json::from_str(json).unwrap();
244        assert_eq!(
245            &bytes_options,
246            &BytesOptions {
247                indexed: false,
248                fieldnorms: false,
249                fast: false,
250                stored: false
251            }
252        );
253    }
254
255    #[test]
256    fn test_bytes_options_deser_if_fieldnorm_false_indexed_true() {
257        let json = r#"{
258            "indexed": true,
259            "fieldnorms": false,
260            "fast": false,
261            "stored": false
262        }"#;
263        let bytes_options: BytesOptions = serde_json::from_str(json).unwrap();
264        assert_eq!(
265            &bytes_options,
266            &BytesOptions {
267                indexed: true,
268                fieldnorms: false,
269                fast: false,
270                stored: false
271            }
272        );
273    }
274
275    #[test]
276    fn test_bytes_options_deser_if_fieldnorm_true_indexed_false() {
277        // this one is kind of useless, at least at the moment
278        let json = r#"{
279            "indexed": false,
280            "fieldnorms": true,
281            "fast": false,
282            "stored": false
283        }"#;
284        let bytes_options: BytesOptions = serde_json::from_str(json).unwrap();
285        assert_eq!(
286            &bytes_options,
287            &BytesOptions {
288                indexed: false,
289                fieldnorms: true,
290                fast: false,
291                stored: false
292            }
293        );
294    }
295}