Skip to main content

lb_tantivy/schema/document/
value.rs

1use std::fmt::Debug;
2use std::net::Ipv6Addr;
3
4use common::DateTime;
5
6use crate::tokenizer::PreTokenizedString;
7
8/// A single field value.
9pub trait Value<'a>: Send + Sync + Debug {
10    /// The child value type returned by this doc value.
11    /// The iterator for walking through the elements within the array.
12    type ArrayIter: Iterator<Item = Self>;
13    /// The visitor walking through the key-value pairs within
14    /// the object.
15    type ObjectIter: Iterator<Item = (&'a str, Self)>;
16
17    /// Returns the field value represented by an enum which borrows it's data.
18    fn as_value(&self) -> ReferenceValue<'a, Self>;
19
20    #[inline]
21    /// If the Value is a leaf, returns the associated leaf. Returns None otherwise.
22    fn as_leaf(&self) -> Option<ReferenceValueLeaf<'a>> {
23        if let ReferenceValue::Leaf(val) = self.as_value() {
24            Some(val)
25        } else {
26            None
27        }
28    }
29
30    #[inline]
31    /// If the Value is a String, returns the associated str. Returns None otherwise.
32    fn as_str(&self) -> Option<&'a str> {
33        self.as_leaf().and_then(|leaf| leaf.as_str())
34    }
35
36    #[inline]
37    /// If the Value is a u64, returns the associated u64. Returns None otherwise.
38    fn as_u64(&self) -> Option<u64> {
39        self.as_leaf().and_then(|leaf| leaf.as_u64())
40    }
41
42    #[inline]
43    /// If the Value is a i64, returns the associated i64. Returns None otherwise.
44    fn as_i64(&self) -> Option<i64> {
45        self.as_leaf().and_then(|leaf| leaf.as_i64())
46    }
47
48    #[inline]
49    /// If the Value is a f64, returns the associated f64. Returns None otherwise.
50    fn as_f64(&self) -> Option<f64> {
51        self.as_leaf().and_then(|leaf| leaf.as_f64())
52    }
53
54    #[inline]
55    /// If the Value is a datetime, returns the associated datetime. Returns None otherwise.
56    fn as_datetime(&self) -> Option<DateTime> {
57        self.as_leaf().and_then(|leaf| leaf.as_datetime())
58    }
59
60    #[inline]
61    /// If the Value is a IP address, returns the associated IP. Returns None otherwise.
62    fn as_ip_addr(&self) -> Option<Ipv6Addr> {
63        self.as_leaf().and_then(|leaf| leaf.as_ip_addr())
64    }
65
66    #[inline]
67    /// If the Value is a bool, returns the associated bool. Returns None otherwise.
68    fn as_bool(&self) -> Option<bool> {
69        self.as_leaf().and_then(|leaf| leaf.as_bool())
70    }
71
72    #[inline]
73    /// If the Value is a pre-tokenized string, returns the associated string. Returns None
74    /// otherwise.
75    fn as_pre_tokenized_text(&self) -> Option<Box<PreTokenizedString>> {
76        self.as_leaf()
77            .and_then(|leaf| leaf.into_pre_tokenized_text())
78    }
79
80    #[inline]
81    /// If the Value is a bytes value, returns the associated set of bytes. Returns None otherwise.
82    fn as_bytes(&self) -> Option<&'a [u8]> {
83        self.as_leaf().and_then(|leaf| leaf.as_bytes())
84    }
85
86    #[inline]
87    /// If the Value is a facet, returns the associated facet. Returns None otherwise.
88    fn as_facet(&self) -> Option<&'a str> {
89        self.as_leaf().and_then(|leaf| leaf.as_facet())
90    }
91
92    #[inline]
93    /// Returns the iterator over the array if the Value is an array.
94    fn as_array(&self) -> Option<Self::ArrayIter> {
95        if let ReferenceValue::Array(val) = self.as_value() {
96            Some(val)
97        } else {
98            None
99        }
100    }
101
102    #[inline]
103    /// Returns the iterator over the object if the Value is an object.
104    fn as_object(&self) -> Option<Self::ObjectIter> {
105        if let ReferenceValue::Object(val) = self.as_value() {
106            Some(val)
107        } else {
108            None
109        }
110    }
111}
112
113/// A enum representing a leaf value for tantivy to index.
114#[derive(Clone, Debug, PartialEq)]
115pub enum ReferenceValueLeaf<'a> {
116    /// A null value.
117    Null,
118    /// The str type is used for any text information.
119    Str(&'a str),
120    /// Unsigned 64-bits Integer `u64`
121    U64(u64),
122    /// Signed 64-bits Integer `i64`
123    I64(i64),
124    /// 64-bits Float `f64`
125    F64(f64),
126    /// Date/time with nanoseconds precision
127    Date(DateTime),
128    /// Facet string needs to match the format of
129    /// [Facet::encoded_str](crate::schema::Facet::encoded_str).
130    Facet(&'a str),
131    /// Arbitrarily sized byte array
132    Bytes(&'a [u8]),
133    /// IpV6 Address. Internally there is no IpV4, it needs to be converted to `Ipv6Addr`.
134    IpAddr(Ipv6Addr),
135    /// Bool value
136    Bool(bool),
137    /// Pre-tokenized str type,
138    PreTokStr(Box<PreTokenizedString>),
139}
140
141impl From<u64> for ReferenceValueLeaf<'_> {
142    #[inline]
143    fn from(value: u64) -> Self {
144        ReferenceValueLeaf::U64(value)
145    }
146}
147
148impl From<i64> for ReferenceValueLeaf<'_> {
149    #[inline]
150    fn from(value: i64) -> Self {
151        ReferenceValueLeaf::I64(value)
152    }
153}
154
155impl From<f64> for ReferenceValueLeaf<'_> {
156    #[inline]
157    fn from(value: f64) -> Self {
158        ReferenceValueLeaf::F64(value)
159    }
160}
161
162impl From<bool> for ReferenceValueLeaf<'_> {
163    #[inline]
164    fn from(value: bool) -> Self {
165        ReferenceValueLeaf::Bool(value)
166    }
167}
168
169impl<'a> From<&'a str> for ReferenceValueLeaf<'a> {
170    #[inline]
171    fn from(value: &'a str) -> Self {
172        ReferenceValueLeaf::Str(value)
173    }
174}
175
176impl<'a> From<&'a [u8]> for ReferenceValueLeaf<'a> {
177    #[inline]
178    fn from(value: &'a [u8]) -> Self {
179        ReferenceValueLeaf::Bytes(value)
180    }
181}
182
183impl From<DateTime> for ReferenceValueLeaf<'_> {
184    #[inline]
185    fn from(value: DateTime) -> Self {
186        ReferenceValueLeaf::Date(value)
187    }
188}
189
190impl From<Ipv6Addr> for ReferenceValueLeaf<'_> {
191    #[inline]
192    fn from(value: Ipv6Addr) -> Self {
193        ReferenceValueLeaf::IpAddr(value)
194    }
195}
196
197impl From<PreTokenizedString> for ReferenceValueLeaf<'_> {
198    #[inline]
199    fn from(val: PreTokenizedString) -> Self {
200        ReferenceValueLeaf::PreTokStr(Box::new(val))
201    }
202}
203
204impl<'a, T: Value<'a> + ?Sized> From<ReferenceValueLeaf<'a>> for ReferenceValue<'a, T> {
205    #[inline]
206    fn from(value: ReferenceValueLeaf<'a>) -> Self {
207        match value {
208            ReferenceValueLeaf::Null => ReferenceValue::Leaf(ReferenceValueLeaf::Null),
209            ReferenceValueLeaf::Str(val) => ReferenceValue::Leaf(ReferenceValueLeaf::Str(val)),
210            ReferenceValueLeaf::U64(val) => ReferenceValue::Leaf(ReferenceValueLeaf::U64(val)),
211            ReferenceValueLeaf::I64(val) => ReferenceValue::Leaf(ReferenceValueLeaf::I64(val)),
212            ReferenceValueLeaf::F64(val) => ReferenceValue::Leaf(ReferenceValueLeaf::F64(val)),
213            ReferenceValueLeaf::Date(val) => ReferenceValue::Leaf(ReferenceValueLeaf::Date(val)),
214            ReferenceValueLeaf::Facet(val) => ReferenceValue::Leaf(ReferenceValueLeaf::Facet(val)),
215            ReferenceValueLeaf::Bytes(val) => ReferenceValue::Leaf(ReferenceValueLeaf::Bytes(val)),
216            ReferenceValueLeaf::IpAddr(val) => {
217                ReferenceValue::Leaf(ReferenceValueLeaf::IpAddr(val))
218            }
219            ReferenceValueLeaf::Bool(val) => ReferenceValue::Leaf(ReferenceValueLeaf::Bool(val)),
220            ReferenceValueLeaf::PreTokStr(val) => {
221                ReferenceValue::Leaf(ReferenceValueLeaf::PreTokStr(val))
222            }
223        }
224    }
225}
226
227impl<'a> ReferenceValueLeaf<'a> {
228    #[inline]
229    /// Returns if the value is `null` or not.
230    pub fn is_null(&self) -> bool {
231        matches!(self, Self::Null)
232    }
233
234    #[inline]
235    /// If the Value is a String, returns the associated str. Returns None otherwise.
236    pub fn as_str(&self) -> Option<&'a str> {
237        if let Self::Str(val) = self {
238            Some(val)
239        } else {
240            None
241        }
242    }
243
244    #[inline]
245    /// If the Value is a u64, returns the associated u64. Returns None otherwise.
246    pub fn as_u64(&self) -> Option<u64> {
247        if let Self::U64(val) = self {
248            Some(*val)
249        } else {
250            None
251        }
252    }
253
254    #[inline]
255    /// If the Value is a i64, returns the associated i64. Returns None otherwise.
256    pub fn as_i64(&self) -> Option<i64> {
257        if let Self::I64(val) = self {
258            Some(*val)
259        } else {
260            None
261        }
262    }
263
264    #[inline]
265    /// If the Value is a f64, returns the associated f64. Returns None otherwise.
266    pub fn as_f64(&self) -> Option<f64> {
267        if let Self::F64(val) = self {
268            Some(*val)
269        } else {
270            None
271        }
272    }
273
274    #[inline]
275    /// If the Value is a datetime, returns the associated datetime. Returns None otherwise.
276    pub fn as_datetime(&self) -> Option<DateTime> {
277        if let Self::Date(val) = self {
278            Some(*val)
279        } else {
280            None
281        }
282    }
283
284    #[inline]
285    /// If the Value is a IP address, returns the associated IP. Returns None otherwise.
286    pub fn as_ip_addr(&self) -> Option<Ipv6Addr> {
287        if let Self::IpAddr(val) = self {
288            Some(*val)
289        } else {
290            None
291        }
292    }
293
294    #[inline]
295    /// If the Value is a bool, returns the associated bool. Returns None otherwise.
296    pub fn as_bool(&self) -> Option<bool> {
297        if let Self::Bool(val) = self {
298            Some(*val)
299        } else {
300            None
301        }
302    }
303
304    #[inline]
305    /// If the Value is a pre-tokenized string, consumes it and returns the string.
306    /// Returns None otherwise.
307    pub fn into_pre_tokenized_text(self) -> Option<Box<PreTokenizedString>> {
308        if let Self::PreTokStr(val) = self {
309            Some(val)
310        } else {
311            None
312        }
313    }
314
315    #[inline]
316    /// If the Value is a bytes value, returns the associated set of bytes. Returns None otherwise.
317    pub fn as_bytes(&self) -> Option<&'a [u8]> {
318        if let Self::Bytes(val) = self {
319            Some(val)
320        } else {
321            None
322        }
323    }
324
325    #[inline]
326    /// If the Value is a facet, returns the associated facet. Returns None otherwise.
327    pub fn as_facet(&self) -> Option<&'a str> {
328        if let Self::Facet(val) = self {
329            Some(val)
330        } else {
331            None
332        }
333    }
334}
335
336/// A enum representing a value for tantivy to index.
337#[derive(Clone, Debug, PartialEq)]
338pub enum ReferenceValue<'a, V>
339where V: Value<'a> + ?Sized
340{
341    /// A null value.
342    Leaf(ReferenceValueLeaf<'a>),
343    /// A an array containing multiple values.
344    Array(V::ArrayIter),
345    /// A nested / dynamic object.
346    Object(V::ObjectIter),
347}
348
349impl<'a, V> ReferenceValue<'a, V>
350where V: Value<'a>
351{
352    #[inline]
353    /// Returns if the value is `null` or not.
354    pub fn is_null(&self) -> bool {
355        matches!(self, Self::Leaf(ReferenceValueLeaf::Null))
356    }
357
358    #[inline]
359    /// If the Value is a leaf, returns the associated leaf. Returns None otherwise.
360    pub fn as_leaf(&self) -> Option<&ReferenceValueLeaf<'a>> {
361        if let Self::Leaf(val) = self {
362            Some(val)
363        } else {
364            None
365        }
366    }
367
368    #[inline]
369    /// If the Value is a leaf, consume it and return the leaf. Returns None otherwise.
370    pub fn into_leaf(self) -> Option<ReferenceValueLeaf<'a>> {
371        if let Self::Leaf(val) = self {
372            Some(val)
373        } else {
374            None
375        }
376    }
377
378    #[inline]
379    /// If the Value is a String, returns the associated str. Returns None otherwise.
380    pub fn as_str(&self) -> Option<&'a str> {
381        self.as_leaf().and_then(|leaf| leaf.as_str())
382    }
383
384    #[inline]
385    /// If the Value is a u64, returns the associated u64. Returns None otherwise.
386    pub fn as_u64(&self) -> Option<u64> {
387        self.as_leaf().and_then(|leaf| leaf.as_u64())
388    }
389
390    #[inline]
391    /// If the Value is a i64, returns the associated i64. Returns None otherwise.
392    pub fn as_i64(&self) -> Option<i64> {
393        self.as_leaf().and_then(|leaf| leaf.as_i64())
394    }
395
396    #[inline]
397    /// If the Value is a f64, returns the associated f64. Returns None otherwise.
398    pub fn as_f64(&self) -> Option<f64> {
399        self.as_leaf().and_then(|leaf| leaf.as_f64())
400    }
401
402    #[inline]
403    /// If the Value is a datetime, returns the associated datetime. Returns None otherwise.
404    pub fn as_datetime(&self) -> Option<DateTime> {
405        self.as_leaf().and_then(|leaf| leaf.as_datetime())
406    }
407
408    #[inline]
409    /// If the Value is a IP address, returns the associated IP. Returns None otherwise.
410    pub fn as_ip_addr(&self) -> Option<Ipv6Addr> {
411        self.as_leaf().and_then(|leaf| leaf.as_ip_addr())
412    }
413
414    #[inline]
415    /// If the Value is a bool, returns the associated bool. Returns None otherwise.
416    pub fn as_bool(&self) -> Option<bool> {
417        self.as_leaf().and_then(|leaf| leaf.as_bool())
418    }
419
420    #[inline]
421    /// If the Value is a pre-tokenized string, consumes it and returns the string.
422    /// Returns None otherwise.
423    pub fn into_pre_tokenized_text(self) -> Option<Box<PreTokenizedString>> {
424        self.into_leaf()
425            .and_then(|leaf| leaf.into_pre_tokenized_text())
426    }
427
428    #[inline]
429    /// If the Value is a bytes value, returns the associated set of bytes. Returns None otherwise.
430    pub fn as_bytes(&self) -> Option<&'a [u8]> {
431        self.as_leaf().and_then(|leaf| leaf.as_bytes())
432    }
433
434    #[inline]
435    /// If the Value is a facet, returns the associated facet. Returns None otherwise.
436    pub fn as_facet(&self) -> Option<&'a str> {
437        self.as_leaf().and_then(|leaf| leaf.as_facet())
438    }
439
440    #[inline]
441    /// Returns true if the Value is an array.
442    pub fn is_array(&self) -> bool {
443        matches!(self, Self::Array(_))
444    }
445
446    #[inline]
447    /// Returns true if the Value is an object.
448    pub fn is_object(&self) -> bool {
449        matches!(self, Self::Object(_))
450    }
451}