qdrant-edge 0.7.0

A lightweight, in-process vector search engine designed for embedded devices, autonomous systems, and mobile agents.
Documentation
use std::borrow::Cow;

use super::{MmapFile, read};
use crate::common::generic_consts::{AccessPattern, Random, Sequential};
use crate::common::universal_io::{
    BorrowedReadPipeline, Item, OwnedReadPipeline, ReadRange, Result, UniversalIoError,
    UniversalRead, UserData,
};

pub struct BorrowedMmapReadPipeline<'file, T, U> {
    result: Option<(U, &'file [T])>,
}

impl<'file, T, U> BorrowedReadPipeline<'file, T, U> for BorrowedMmapReadPipeline<'file, T, U>
where
    T: Item,
    U: UserData,
{
    type File = MmapFile;

    fn new() -> Result<Self> {
        Ok(Self { result: None })
    }

    fn can_schedule(&mut self) -> bool {
        self.result.is_none()
    }

    fn schedule<P>(&mut self, user_data: U, file: &'file MmapFile, range: ReadRange) -> Result<()>
    where
        P: AccessPattern,
    {
        if self.result.is_some() {
            return Err(UniversalIoError::QueueIsFull);
        }

        self.result = Some((user_data, read(file.as_bytes::<P>(), range)?));
        Ok(())
    }

    fn wait(&mut self) -> Result<Option<(U, Cow<'file, [T]>)>> {
        let result = self.result.take();
        Ok(result.map(|(user_data, items)| (user_data, Cow::Borrowed(items))))
    }
}

#[derive(Debug)]
pub struct OwnedMmapReadPipeline<T, U> {
    file: MmapFile,
    pending: Option<(U, ReadRange, bool)>,
    _phantom: std::marker::PhantomData<T>,
}

impl<T, U> OwnedReadPipeline<T, U> for OwnedMmapReadPipeline<T, U>
where
    T: Item,
    U: UserData,
{
    type File = MmapFile;

    fn new(file: MmapFile) -> Result<Self> {
        Ok(Self {
            file,
            pending: None,
            _phantom: std::marker::PhantomData,
        })
    }

    fn can_schedule(&mut self) -> bool {
        self.pending.is_none()
    }

    fn schedule<P>(&mut self, user_data: U, range: ReadRange) -> Result<()>
    where
        P: AccessPattern,
    {
        if self.pending.is_some() {
            return Err(UniversalIoError::QueueIsFull);
        }
        self.pending = Some((user_data, range, P::IS_SEQUENTIAL));
        Ok(())
    }

    fn schedule_whole(&mut self, user_data: U) -> Result<()> {
        let length = self.file.len::<T>()?;
        self.schedule::<Sequential>(
            user_data,
            ReadRange {
                byte_offset: 0,
                length,
            },
        )
    }

    fn wait(&mut self) -> Result<Option<(U, Cow<'_, [T]>)>> {
        let Some((user_data, range, is_sequential)) = self.pending.take() else {
            return Ok(None);
        };
        let bytes = if is_sequential {
            self.file.as_bytes::<Sequential>()
        } else {
            self.file.as_bytes::<Random>()
        };
        Ok(Some((user_data, Cow::Borrowed(read::<T>(bytes, range)?))))
    }
}