use arrow::array::{ArrayRef, NullArray};
use re_types::{ComponentDescriptor, ComponentType};
use crate::QueryContext;
pub enum ComponentFallbackProviderResult {
Value(ArrayRef),
ComponentNotHandled,
SerializationError(re_types::SerializationError),
}
impl<T: re_types::ComponentBatch> From<T> for ComponentFallbackProviderResult {
fn from(batch: T) -> Self {
match batch.to_arrow() {
Ok(value) => Self::Value(value),
Err(err) => Self::SerializationError(err),
}
}
}
#[derive(thiserror::Error, Debug)]
pub enum ComponentFallbackError {
#[error("Fallback value turned up to be empty when we expected a value.")]
UnexpectedEmptyFallback,
}
pub trait ComponentFallbackProvider {
fn try_provide_fallback(
&self,
ctx: &QueryContext<'_>,
component: ComponentType,
) -> ComponentFallbackProviderResult;
fn fallback_for(
&self,
ctx: &QueryContext<'_>,
component_descr: &ComponentDescriptor,
) -> ArrayRef {
let Some(component_type) = component_descr.component_type else {
re_log::warn!(
"Requested fallback for component descr {component_descr} without component type"
);
return std::sync::Arc::new(NullArray::new(0));
};
match self.try_provide_fallback(ctx, component_type) {
ComponentFallbackProviderResult::Value(value) => {
return value;
}
ComponentFallbackProviderResult::SerializationError(err) => {
re_log::error_once!(
"Arrow serialization failed trying to provide a fallback for {component_type}. Using base fallback instead: {err}"
);
}
ComponentFallbackProviderResult::ComponentNotHandled => {}
}
ctx.viewer_ctx().placeholder_for(component_type)
}
}
pub trait TypedComponentFallbackProvider<C: re_types::Component> {
fn fallback_for(&self, ctx: &QueryContext<'_>) -> C;
}
#[macro_export]
macro_rules! impl_component_fallback_provider {
($type:ty => [$($component:ty),*]) => {
impl $crate::ComponentFallbackProvider for $type {
fn try_provide_fallback(
&self,
_ctx: &$crate::QueryContext<'_>,
_component_type: re_types::ComponentType,
) -> $crate::ComponentFallbackProviderResult {
$(
if _component_type == <$component as re_types::Component>::name() {
return $crate::TypedComponentFallbackProvider::<$component>::fallback_for(self, _ctx).into();
}
)*
$crate::ComponentFallbackProviderResult::ComponentNotHandled
}
}
};
}