summavy/fastfield/
readers.rs

1use std::net::Ipv6Addr;
2use std::sync::Arc;
3
4use fastfield_codecs::{open, open_u128, Column};
5
6use super::multivalued::MultiValuedFastFieldReader;
7use crate::directory::{CompositeFile, FileSlice};
8use crate::fastfield::{BytesFastFieldReader, FastFieldNotAvailableError, FastValue};
9use crate::schema::{Cardinality, Field, FieldType, Schema};
10use crate::space_usage::PerFieldSpaceUsage;
11use crate::{DateTime, TantivyError};
12
13/// Provides access to all of the BitpackedFastFieldReader.
14///
15/// Internally, `FastFieldReaders` have preloaded fast field readers,
16/// and just wraps several `HashMap`.
17#[derive(Clone)]
18pub struct FastFieldReaders {
19    schema: Schema,
20    fast_fields_composite: CompositeFile,
21}
22#[derive(Eq, PartialEq, Debug)]
23pub(crate) enum FastType {
24    I64,
25    U64,
26    U128,
27    F64,
28    Bool,
29    Date,
30}
31
32pub(crate) fn type_and_cardinality(field_type: &FieldType) -> Option<(FastType, Cardinality)> {
33    match field_type {
34        FieldType::U64(options) => options
35            .get_fastfield_cardinality()
36            .map(|cardinality| (FastType::U64, cardinality)),
37        FieldType::I64(options) => options
38            .get_fastfield_cardinality()
39            .map(|cardinality| (FastType::I64, cardinality)),
40        FieldType::F64(options) => options
41            .get_fastfield_cardinality()
42            .map(|cardinality| (FastType::F64, cardinality)),
43        FieldType::Bool(options) => options
44            .get_fastfield_cardinality()
45            .map(|cardinality| (FastType::Bool, cardinality)),
46        FieldType::Date(options) => options
47            .get_fastfield_cardinality()
48            .map(|cardinality| (FastType::Date, cardinality)),
49        FieldType::Facet(_) => Some((FastType::U64, Cardinality::MultiValues)),
50        FieldType::Str(options) if options.is_fast() => {
51            Some((FastType::U64, Cardinality::MultiValues))
52        }
53        FieldType::IpAddr(options) => options
54            .get_fastfield_cardinality()
55            .map(|cardinality| (FastType::U128, cardinality)),
56        _ => None,
57    }
58}
59
60impl FastFieldReaders {
61    pub(crate) fn new(schema: Schema, fast_fields_composite: CompositeFile) -> FastFieldReaders {
62        FastFieldReaders {
63            schema,
64            fast_fields_composite,
65        }
66    }
67
68    pub(crate) fn space_usage(&self) -> PerFieldSpaceUsage {
69        self.fast_fields_composite.space_usage()
70    }
71
72    #[doc(hidden)]
73    pub fn fast_field_data(&self, field: Field, idx: usize) -> crate::Result<FileSlice> {
74        self.fast_fields_composite
75            .open_read_with_idx(field, idx)
76            .ok_or_else(|| {
77                let field_name = self.schema.get_field_entry(field).name();
78                TantivyError::SchemaError(format!("Field({}) data was not found", field_name))
79            })
80    }
81
82    fn check_type(
83        &self,
84        field: Field,
85        expected_fast_type: FastType,
86        expected_cardinality: Cardinality,
87    ) -> crate::Result<()> {
88        let field_entry = self.schema.get_field_entry(field);
89        let (fast_type, cardinality) =
90            type_and_cardinality(field_entry.field_type()).ok_or_else(|| {
91                crate::TantivyError::SchemaError(format!(
92                    "Field {:?} is not a fast field.",
93                    field_entry.name()
94                ))
95            })?;
96        if fast_type != expected_fast_type {
97            return Err(crate::TantivyError::SchemaError(format!(
98                "Field {:?} is of type {:?}, expected {:?}.",
99                field_entry.name(),
100                fast_type,
101                expected_fast_type
102            )));
103        }
104        if cardinality != expected_cardinality {
105            return Err(crate::TantivyError::SchemaError(format!(
106                "Field {:?} is of cardinality {:?}, expected {:?}.",
107                field_entry.name(),
108                cardinality,
109                expected_cardinality
110            )));
111        }
112        Ok(())
113    }
114
115    pub(crate) fn typed_fast_field_reader_with_idx<TFastValue: FastValue>(
116        &self,
117        field: Field,
118        index: usize,
119    ) -> crate::Result<Arc<dyn Column<TFastValue>>> {
120        let fast_field_slice = self.fast_field_data(field, index)?;
121        let bytes = fast_field_slice.read_bytes()?;
122        let column = fastfield_codecs::open(bytes)?;
123        Ok(column)
124    }
125
126    pub(crate) fn typed_fast_field_reader<TFastValue: FastValue>(
127        &self,
128        field: Field,
129    ) -> crate::Result<Arc<dyn Column<TFastValue>>> {
130        self.typed_fast_field_reader_with_idx(field, 0)
131    }
132
133    pub(crate) fn typed_fast_field_multi_reader<TFastValue: FastValue>(
134        &self,
135        field: Field,
136    ) -> crate::Result<MultiValuedFastFieldReader<TFastValue>> {
137        let idx_reader = self.typed_fast_field_reader(field)?;
138        let vals_reader = self.typed_fast_field_reader_with_idx(field, 1)?;
139        Ok(MultiValuedFastFieldReader::open(idx_reader, vals_reader))
140    }
141
142    /// Returns the `u64` fast field reader reader associated with `field`.
143    ///
144    /// If `field` is not a u64 fast field, this method returns an Error.
145    pub fn u64(&self, field: Field) -> crate::Result<Arc<dyn Column<u64>>> {
146        self.check_type(field, FastType::U64, Cardinality::SingleValue)?;
147        self.typed_fast_field_reader(field)
148    }
149
150    /// Returns the `ip` fast field reader reader associated to `field`.
151    ///
152    /// If `field` is not a u128 fast field, this method returns an Error.
153    pub fn ip_addr(&self, field: Field) -> crate::Result<Arc<dyn Column<Ipv6Addr>>> {
154        self.check_type(field, FastType::U128, Cardinality::SingleValue)?;
155        let bytes = self.fast_field_data(field, 0)?.read_bytes()?;
156        Ok(open_u128::<Ipv6Addr>(bytes)?)
157    }
158
159    /// Returns the `ip` fast field reader reader associated to `field`.
160    ///
161    /// If `field` is not a u128 fast field, this method returns an Error.
162    pub fn ip_addrs(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<Ipv6Addr>> {
163        self.check_type(field, FastType::U128, Cardinality::MultiValues)?;
164        let idx_reader: Arc<dyn Column<u64>> = self.typed_fast_field_reader(field)?;
165
166        let bytes = self.fast_field_data(field, 1)?.read_bytes()?;
167        let vals_reader = open_u128::<Ipv6Addr>(bytes)?;
168
169        Ok(MultiValuedFastFieldReader::open(idx_reader, vals_reader))
170    }
171
172    /// Returns the `u128` fast field reader reader associated to `field`.
173    ///
174    /// If `field` is not a u128 fast field, this method returns an Error.
175    pub(crate) fn u128(&self, field: Field) -> crate::Result<Arc<dyn Column<u128>>> {
176        self.check_type(field, FastType::U128, Cardinality::SingleValue)?;
177        let bytes = self.fast_field_data(field, 0)?.read_bytes()?;
178        Ok(open_u128::<u128>(bytes)?)
179    }
180
181    /// Returns the `u128` multi-valued fast field reader reader associated to `field`.
182    ///
183    /// If `field` is not a u128 multi-valued fast field, this method returns an Error.
184    pub fn u128s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<u128>> {
185        self.check_type(field, FastType::U128, Cardinality::MultiValues)?;
186        let idx_reader: Arc<dyn Column<u64>> = self.typed_fast_field_reader(field)?;
187
188        let bytes = self.fast_field_data(field, 1)?.read_bytes()?;
189        let vals_reader = open_u128::<u128>(bytes)?;
190
191        Ok(MultiValuedFastFieldReader::open(idx_reader, vals_reader))
192    }
193
194    /// Returns the `u64` fast field reader reader associated with `field`, regardless of whether
195    /// the given field is effectively of type `u64` or not.
196    ///
197    /// If not, the fastfield reader will returns the u64-value associated with the original
198    /// FastValue.
199    pub fn u64_lenient(&self, field: Field) -> crate::Result<Arc<dyn Column<u64>>> {
200        self.typed_fast_field_reader(field)
201    }
202
203    /// Returns the `i64` fast field reader reader associated with `field`.
204    ///
205    /// If `field` is not a i64 fast field, this method returns an Error.
206    pub fn i64(&self, field: Field) -> crate::Result<Arc<dyn Column<i64>>> {
207        self.check_type(field, FastType::I64, Cardinality::SingleValue)?;
208        self.typed_fast_field_reader(field)
209    }
210
211    /// Returns the `date` fast field reader reader associated with `field`.
212    ///
213    /// If `field` is not a date fast field, this method returns an Error.
214    pub fn date(&self, field: Field) -> crate::Result<Arc<dyn Column<DateTime>>> {
215        self.check_type(field, FastType::Date, Cardinality::SingleValue)?;
216        self.typed_fast_field_reader(field)
217    }
218
219    /// Returns the `f64` fast field reader reader associated with `field`.
220    ///
221    /// If `field` is not a f64 fast field, this method returns an Error.
222    pub fn f64(&self, field: Field) -> crate::Result<Arc<dyn Column<f64>>> {
223        self.check_type(field, FastType::F64, Cardinality::SingleValue)?;
224        self.typed_fast_field_reader(field)
225    }
226
227    /// Returns the `bool` fast field reader reader associated with `field`.
228    ///
229    /// If `field` is not a bool fast field, this method returns an Error.
230    pub fn bool(&self, field: Field) -> crate::Result<Arc<dyn Column<bool>>> {
231        self.check_type(field, FastType::Bool, Cardinality::SingleValue)?;
232        self.typed_fast_field_reader(field)
233    }
234
235    /// Returns a `u64s` multi-valued fast field reader reader associated with `field`.
236    ///
237    /// If `field` is not a u64 multi-valued fast field, this method returns an Error.
238    pub fn u64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<u64>> {
239        self.check_type(field, FastType::U64, Cardinality::MultiValues)?;
240        self.typed_fast_field_multi_reader(field)
241    }
242
243    /// Returns a `u64s` multi-valued fast field reader reader associated with `field`, regardless
244    /// of whether the given field is effectively of type `u64` or not.
245    ///
246    /// If `field` is not a u64 multi-valued fast field, this method returns an Error.
247    pub fn u64s_lenient(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<u64>> {
248        self.typed_fast_field_multi_reader(field)
249    }
250
251    /// Returns a `i64s` multi-valued fast field reader reader associated with `field`.
252    ///
253    /// If `field` is not a i64 multi-valued fast field, this method returns an Error.
254    pub fn i64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<i64>> {
255        self.check_type(field, FastType::I64, Cardinality::MultiValues)?;
256        self.typed_fast_field_multi_reader(field)
257    }
258
259    /// Returns a `f64s` multi-valued fast field reader reader associated with `field`.
260    ///
261    /// If `field` is not a f64 multi-valued fast field, this method returns an Error.
262    pub fn f64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<f64>> {
263        self.check_type(field, FastType::F64, Cardinality::MultiValues)?;
264        self.typed_fast_field_multi_reader(field)
265    }
266
267    /// Returns a `bools` multi-valued fast field reader reader associated with `field`.
268    ///
269    /// If `field` is not a bool multi-valued fast field, this method returns an Error.
270    pub fn bools(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<bool>> {
271        self.check_type(field, FastType::Bool, Cardinality::MultiValues)?;
272        self.typed_fast_field_multi_reader(field)
273    }
274
275    /// Returns a `time::OffsetDateTime` multi-valued fast field reader reader associated with
276    /// `field`.
277    ///
278    /// If `field` is not a `time::OffsetDateTime` multi-valued fast field, this method returns an
279    /// Error.
280    pub fn dates(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<DateTime>> {
281        self.check_type(field, FastType::Date, Cardinality::MultiValues)?;
282        self.typed_fast_field_multi_reader(field)
283    }
284
285    /// Returns the `bytes` fast field reader associated with `field`.
286    ///
287    /// If `field` is not a bytes fast field, returns an Error.
288    pub fn bytes(&self, field: Field) -> crate::Result<BytesFastFieldReader> {
289        let field_entry = self.schema.get_field_entry(field);
290        if let FieldType::Bytes(bytes_option) = field_entry.field_type() {
291            if !bytes_option.is_fast() {
292                return Err(crate::TantivyError::SchemaError(format!(
293                    "Field {:?} is not a fast field.",
294                    field_entry.name()
295                )));
296            }
297            let fast_field_idx_file = self.fast_field_data(field, 0)?;
298            let fast_field_idx_bytes = fast_field_idx_file.read_bytes()?;
299            let idx_reader = open(fast_field_idx_bytes)?;
300            let data = self.fast_field_data(field, 1)?;
301            BytesFastFieldReader::open(idx_reader, data)
302        } else {
303            Err(FastFieldNotAvailableError::new(field_entry).into())
304        }
305    }
306}