milli_core/heed_codec/facet/
mod.rs

1mod field_doc_id_facet_codec;
2mod ordered_f64_codec;
3
4use std::borrow::Cow;
5use std::convert::TryFrom;
6use std::marker::PhantomData;
7
8use heed::types::DecodeIgnore;
9use heed::{BoxedError, BytesDecode, BytesEncode};
10use roaring::RoaringBitmap;
11
12pub use self::field_doc_id_facet_codec::FieldDocIdFacetCodec;
13pub use self::ordered_f64_codec::OrderedF64Codec;
14use super::StrRefCodec;
15use crate::{CboRoaringBitmapCodec, BEU16};
16
17pub type FieldDocIdFacetF64Codec = FieldDocIdFacetCodec<OrderedF64Codec>;
18pub type FieldDocIdFacetStringCodec = FieldDocIdFacetCodec<StrRefCodec>;
19pub type FieldDocIdFacetIgnoreCodec = FieldDocIdFacetCodec<DecodeIgnore>;
20
21pub type FieldIdCodec = BEU16;
22
23/// Tries to split a slice in half at the given middle point,
24/// `None` if the slice is too short.
25pub fn try_split_at(slice: &[u8], mid: usize) -> Option<(&[u8], &[u8])> {
26    if slice.len() >= mid {
27        Some(slice.split_at(mid))
28    } else {
29        None
30    }
31}
32
33/// The key in the [`facet_id_string_docids` and `facet_id_f64_docids`][`Index::facet_id_string_docids`]
34/// databases.
35#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] // TODO: try removing PartialOrd and Ord
36pub struct FacetGroupKey<T> {
37    pub field_id: u16,
38    pub level: u8,
39    pub left_bound: T,
40}
41
42/// The value in the [`facet_id_string_docids` and `facet_id_f64_docids`][`Index::facet_id_string_docids`]
43/// databases.
44#[derive(Debug)]
45pub struct FacetGroupValue {
46    pub size: u8,
47    pub bitmap: RoaringBitmap,
48}
49
50#[derive(Debug)]
51pub struct FacetGroupLazyValue<'b> {
52    pub size: u8,
53    pub bitmap_bytes: &'b [u8],
54}
55
56pub struct FacetGroupKeyCodec<T> {
57    _phantom: PhantomData<T>,
58}
59
60impl<'a, T> heed::BytesEncode<'a> for FacetGroupKeyCodec<T>
61where
62    T: BytesEncode<'a>,
63    T::EItem: Sized,
64{
65    type EItem = FacetGroupKey<T::EItem>;
66
67    fn bytes_encode(value: &'a Self::EItem) -> Result<Cow<'a, [u8]>, BoxedError> {
68        let mut v = vec![];
69        v.extend_from_slice(&value.field_id.to_be_bytes());
70        v.extend_from_slice(&[value.level]);
71
72        let bound = T::bytes_encode(&value.left_bound)?;
73        v.extend_from_slice(&bound);
74
75        Ok(Cow::Owned(v))
76    }
77}
78
79impl<'a, T> heed::BytesDecode<'a> for FacetGroupKeyCodec<T>
80where
81    T: BytesDecode<'a>,
82{
83    type DItem = FacetGroupKey<T::DItem>;
84
85    fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
86        let fid = u16::from_be_bytes(<[u8; 2]>::try_from(&bytes[0..=1])?);
87        let level = bytes[2];
88        let bound = T::bytes_decode(&bytes[3..])?;
89        Ok(FacetGroupKey { field_id: fid, level, left_bound: bound })
90    }
91}
92
93pub struct FacetGroupValueCodec;
94
95impl<'a> heed::BytesEncode<'a> for FacetGroupValueCodec {
96    type EItem = FacetGroupValue;
97
98    fn bytes_encode(value: &'a Self::EItem) -> Result<Cow<'a, [u8]>, BoxedError> {
99        let mut v = vec![value.size];
100        CboRoaringBitmapCodec::serialize_into_vec(&value.bitmap, &mut v);
101        Ok(Cow::Owned(v))
102    }
103}
104
105impl<'a> heed::BytesDecode<'a> for FacetGroupValueCodec {
106    type DItem = FacetGroupValue;
107
108    fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
109        let size = bytes[0];
110        let bitmap = CboRoaringBitmapCodec::deserialize_from(&bytes[1..])?;
111        Ok(FacetGroupValue { size, bitmap })
112    }
113}
114
115pub struct FacetGroupLazyValueCodec;
116
117impl<'a> heed::BytesDecode<'a> for FacetGroupLazyValueCodec {
118    type DItem = FacetGroupLazyValue<'a>;
119
120    fn bytes_decode(bytes: &'a [u8]) -> Result<Self::DItem, BoxedError> {
121        Ok(FacetGroupLazyValue { size: bytes[0], bitmap_bytes: &bytes[1..] })
122    }
123}