Repository: qdrant/qdrant
File: lib/segment/src/index/field_index/immutable_point_to_values.rs (Rust)

Code before:
    /// `u32` is used instead of `usize` because it's more RAM efficient —
    /// we can expect that we will never have more than 4 billion values per segment.
    Slice { start: u32, count: u32 },
}

impl<N> Default for PointValueEntry<N> {
    /// Default represents "no values" — an empty slice.
    fn default() -> Self {
        PointValueEntry::Slice { start: 0, count: 0 }
    }
}

/// Flattened points-to-values map.
///
/// An analogue of `Vec<Vec<N>>` but more RAM efficient:
/// - Points with exactly **one** value store it inline in the entry (no container overhead).
/// - Points with **zero** or **multiple** values store them in a shared, contiguous `Vec<N>`.
///
/// This structure doesn't support adding new values, only removing.
/// It's used in immutable field indices like `ImmutableMapIndex`, `ImmutableNumericIndex`, etc.
#[derive(Debug, Clone, Default)]
pub struct ImmutablePointToValues<N: Default> {
    /// Per-point entry describing where (or how) its values are stored.
    /// Indexed by `PointOffsetType`.
    point_entries: Vec<PointValueEntry<N>>,
    /// Shared container holding values for points that have zero or multiple values.
    /// Single-value points are **not** stored here — they live inline in `point_entries`.
    values_container: Vec<N>,
}

impl<N: Default> ImmutablePointToValues<N> {
    pub fn new(src: Vec<Vec<N>>) -> Self {
        let mut point_entries = Vec::with_capacity(src.len());

        // Only values from empty or multi-value points go into the container.
        let container_capacity = src
            .iter()
            .filter(|values| values.len() != 1)
            .fold(0, |acc, values| acc + values.len());
        let mut values_container = Vec::with_capacity(container_capacity);

        for values in src {
            if values.len() == 1 {
                // Single value — store inline, skip container entirely.
                let value = values.into_iter().next().expect("length checked above");
                point_entries.push(PointValueEntry::Single(value));
            } else {
                // Zero or multiple values — store in container, record slice location.
                let start = values_container.len() as u32;
                let count = values.len() as u32;
                point_entries.push(PointValueEntry::Slice { start, count });

Review comment (suggestion):
```suggestion
    /// Shared container holding values for points that have multiple values.
```

Code after:
    /// `u32` is used instead of `usize` because it's more RAM efficient —
    /// we can expect that we will never have more than 4 billion values per segment.
    Slice { start: u32, count: u32 },
}

impl<N> Default for PointValueEntry<N> {
    /// Default represents "no values" — an empty slice.
    fn default() -> Self {
        PointValueEntry::Slice { start: 0, count: 0 }
    }
}

/// Flattened points-to-values map.
///
/// An analogue of `Vec<Vec<N>>` but more RAM efficient:
/// - Points with exactly **one** value store it inline in the entry (no container overhead).
/// - Points with **zero** or **multiple** values store them in a shared, contiguous `Vec<N>`.
///
/// This structure doesn't support adding new values, only removing.
/// It's used in immutable field indices like `ImmutableMapIndex`, `ImmutableNumericIndex`, etc.
#[derive(Debug, Clone, Default)]
pub struct ImmutablePointToValues<N: Default> {
    /// Per-point entry describing where (or how) its values are stored.
    /// Indexed by `PointOffsetType`.
    point_entries: Vec<PointValueEntry<N>>,
    /// Shared container holding values for points that have multiple values.
    /// Single-value points are **not** stored here — they live inline in `point_entries`.
    values_container: Vec<N>,
}

impl<N: Default> ImmutablePointToValues<N> {
    pub fn new(src: Vec<Vec<N>>) -> Self {
        let mut point_entries = Vec::with_capacity(src.len());

        // Only values from multi-value points go into the container.
        let container_capacity = src
            .iter()
            .map(|values| values.len())
            .filter(|&size| size > 1)
            .sum();
        let mut values_container = Vec::with_capacity(container_capacity);

        for values in src {
            match values.len() {
                // Zero values — store inline
                0 => {
                    point_entries.push(PointValueEntry::default());
                }
                // Single value — store inline, skip container entirely
                1 => {
                    let value = values.into_iter().next().expect("length checked above");