re_server 0.31.0

A Rerun server implementation backed by an in-memory store
Documentation
use re_log_types::{ComponentPath, EntryId};
use re_protos::EntryName;
use re_protos::common::v1alpha1::ext::SegmentId;

#[derive(thiserror::Error, Debug)]
#[expect(clippy::enum_variant_names)]
pub enum Error {
    #[error(transparent)]
    IoError(#[from] std::io::Error),

    #[error(transparent)]
    StoreLoadError(#[from] re_entity_db::StoreLoadError),

    #[error("Invalid entry name: {0}")]
    InvalidEntryName(#[from] re_protos::InvalidEntryNameError),

    #[error("Entry name '{0}' already exists")]
    DuplicateEntryNameError(EntryName),

    #[error("Entry id '{0}' already exists")]
    DuplicateEntryIdError(EntryId),

    #[error("Entry name '{0}' not found")]
    EntryNameNotFound(EntryName),

    #[error("Entry id '{0}' not found")]
    EntryIdNotFound(EntryId),

    #[error("Segment '{segment_id}' not found in dataset '{entry_id}'")]
    SegmentIdNotFound {
        segment_id: SegmentId,
        entry_id: EntryId,
    },

    #[error("Layer '{layer_name}' not found in segment '{segment_id}' of dataset '{entry_id}'")]
    LayerNameNotFound {
        layer_name: String,
        segment_id: SegmentId,
        entry_id: EntryId,
    },

    #[error("Layer '{0}' already exists")]
    LayerAlreadyExists(String),

    #[error("Component path '{0}' not found")]
    ComponentPathNotFound(ComponentPath),

    #[error("Index '{0}' already exists")]
    IndexAlreadyExists(String),

    #[error(transparent)]
    DataFusionError(#[from] datafusion::error::DataFusionError),

    #[error(transparent)]
    ArrowError(#[from] arrow::error::ArrowError),

    #[cfg(feature = "lance")]
    #[error(transparent)]
    LanceError(#[from] lance::Error),

    #[error("Indexing error: {0}")]
    IndexingError(String),

    #[error("Error loading RRD: {0}")]
    RrdLoadingError(anyhow::Error),

    #[error("Failed to encode chunk key: {0}")]
    FailedToEncodeChunkKey(String),

    #[error("Failed to decode chunk key: {0}")]
    FailedToDecodeChunkKey(String),

    #[error("Invalid chunk key: {0}")]
    InvalidChunkKey(String),

    #[error("Failed to extract properties: {0:#?}")]
    FailedToExtractProperties(String),

    #[error("{0}")]
    SchemaConflict(String),

    #[error("Table storage already exists at location: {0}")]
    TableStorageAlreadyExists(String),
}

impl Error {
    #[inline]
    pub fn failed_to_extract_properties(err: impl std::error::Error) -> Self {
        Self::FailedToExtractProperties(err.to_string())
    }
}

impl From<Error> for tonic::Status {
    fn from(err: Error) -> Self {
        match &err {
            Error::IoError(err) => Self::internal(format!("IO error: {err:#}")),
            Error::StoreLoadError(err) => Self::internal(format!("Store load error: {err:#}")),

            Error::EntryIdNotFound(_)
            | Error::EntryNameNotFound(_)
            | Error::SegmentIdNotFound { .. }
            | Error::LayerNameNotFound { .. }
            | Error::ComponentPathNotFound(_)
            | Error::InvalidChunkKey(_) => Self::not_found(format!("{err:#}")),

            Error::DataFusionError(err) => Self::internal(format!("DataFusion error: {err:#}")),
            Error::ArrowError(err) => Self::internal(format!("Arrow error: {err:#}")),
            #[cfg(feature = "lance")]
            Error::LanceError(err) => Self::internal(format!("Lance error: {err:#}")),
            Error::RrdLoadingError(err) => Self::internal(format!("{err:#}")),

            Error::FailedToDecodeChunkKey(_) => Self::invalid_argument(format!("{err:#}")),
            Error::FailedToEncodeChunkKey(_) | Error::FailedToExtractProperties(_) => {
                Self::internal(format!("{err:#}"))
            }

            Error::InvalidEntryName(_) => Self::invalid_argument(format!("{err:#}")),

            Error::DuplicateEntryNameError(_)
            | Error::DuplicateEntryIdError(_)
            | Error::LayerAlreadyExists(_)
            | Error::IndexAlreadyExists(_)
            | Error::TableStorageAlreadyExists(_) => Self::already_exists(format!("{err:#}")),

            Error::IndexingError(_) => Self::internal(format!("Indexing error: {err:#}")),

            Error::SchemaConflict(_) => Self::invalid_argument(format!("{err:#}")),
        }
    }
}