use re_chunk::{ComponentIdentifier, ComponentType};
use re_sdk_types::{ComponentDescriptor, ComponentSet};
use crate::typed_entity_collections::DatatypeMatch;
pub type DatatypeSet = std::collections::BTreeSet<arrow::datatypes::DataType>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SingleRequiredComponentConstraint {
target_component: ComponentIdentifier,
semantic_type: ComponentType,
physical_types: DatatypeSet,
allow_static_data: bool,
}
impl From<SingleRequiredComponentConstraint> for VisualizabilityConstraints {
fn from(req: SingleRequiredComponentConstraint) -> Self {
Self::SingleRequiredComponent(req)
}
}
impl SingleRequiredComponentConstraint {
pub fn new<C: re_sdk_types::Component>(
target_component_descriptor: &ComponentDescriptor,
) -> Self {
re_log::debug_assert_eq!(
target_component_descriptor.component_type,
Some(C::name()),
"Component type doesn't match target descriptor's type.",
);
Self {
target_component: target_component_descriptor.component,
semantic_type: C::name(),
physical_types: std::iter::once(C::arrow_datatype()).collect(),
allow_static_data: true,
}
}
pub fn with_additional_physical_types(
mut self,
additional_types: impl IntoIterator<Item = arrow::datatypes::DataType>,
) -> Self {
self.physical_types.extend(additional_types);
self
}
pub fn with_allow_static_data(mut self, allow: bool) -> Self {
self.allow_static_data = allow;
self
}
pub fn target_component(&self) -> ComponentIdentifier {
self.target_component
}
pub fn allow_static_data(&self) -> bool {
self.allow_static_data
}
pub fn physical_types(&self) -> &DatatypeSet {
&self.physical_types
}
pub(crate) fn check_datatype_match(
&self,
known_enum_types: &nohash_hasher::IntSet<ComponentType>,
incoming_arrow_datatype: &arrow::datatypes::DataType,
incoming_component_type: Option<ComponentType>,
incoming_component: ComponentIdentifier,
) -> Option<DatatypeMatch> {
use re_lenses_core::extract_nested_fields;
let is_physical_match = self.physical_types.contains(incoming_arrow_datatype);
let is_semantic_match = incoming_component_type == Some(self.semantic_type);
let incoming_is_enum =
incoming_component_type.is_some_and(|ct| known_enum_types.contains(&ct));
let constraint_is_enum = known_enum_types.contains(&self.semantic_type);
if (incoming_is_enum || constraint_is_enum) && !is_semantic_match {
return None;
}
match (is_physical_match, is_semantic_match) {
(false, false) => {
extract_nested_fields(incoming_arrow_datatype, |dt| {
self.physical_types.contains(dt)
})
.map(|selectors| DatatypeMatch::PhysicalDatatypeOnly {
arrow_datatype: incoming_arrow_datatype.clone(),
component_type: incoming_component_type,
selectors: selectors.into(),
})
}
(true, false) => Some(DatatypeMatch::PhysicalDatatypeOnly {
arrow_datatype: incoming_arrow_datatype.clone(),
component_type: incoming_component_type,
selectors: Vec::new(),
}),
(true, true) => Some(DatatypeMatch::NativeSemantics {
arrow_datatype: incoming_arrow_datatype.clone(),
component_type: incoming_component_type,
}),
(false, true) => {
re_log::warn_once!(
"Component {incoming_component:?} matched semantic type {:?} but none of the expected physical arrow types {incoming_arrow_datatype:?} for this semantic type.",
self.semantic_type,
);
None
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BufferAndFormatConstraint {
buffer_target: ComponentIdentifier,
buffer_semantic_type: ComponentType,
format_target: ComponentIdentifier,
format_semantic_type: ComponentType,
format_arrow_datatype: arrow::datatypes::DataType,
}
impl BufferAndFormatConstraint {
pub fn new<Buffer: re_sdk_types::Component, Format: re_sdk_types::Component>(
buffer_descriptor: &ComponentDescriptor,
format_descriptor: &ComponentDescriptor,
) -> Self {
re_log::debug_assert_eq!(
buffer_descriptor.component_type,
Some(Buffer::name()),
"Buffer component type doesn't match descriptor's type.",
);
re_log::debug_assert_eq!(
format_descriptor.component_type,
Some(Format::name()),
"Format component type doesn't match descriptor's type.",
);
Self::new_with_type(
buffer_descriptor.component,
Buffer::name(),
format_descriptor.component,
Format::name(),
Format::arrow_datatype(),
)
}
pub fn new_with_type(
buffer_target: ComponentIdentifier,
buffer_semantic_type: ComponentType,
format_target: ComponentIdentifier,
format_semantic_type: ComponentType,
format_arrow_datatype: arrow::datatypes::DataType,
) -> Self {
Self {
buffer_target,
buffer_semantic_type,
format_target,
format_semantic_type,
format_arrow_datatype,
}
}
pub fn buffer_arrow_datatype() -> arrow::datatypes::DataType {
<re_sdk_types::datatypes::Blob as re_types_core::Loggable>::arrow_datatype()
}
pub fn buffer_target(&self) -> ComponentIdentifier {
self.buffer_target
}
pub fn format_target(&self) -> ComponentIdentifier {
self.format_target
}
pub(crate) fn check_buffer_match(
&self,
incoming_arrow_datatype: &arrow::datatypes::DataType,
descriptor: &re_sdk_types::ComponentDescriptor,
) -> Option<DatatypeMatch> {
use re_lenses_core::extract_nested_fields;
let is_physical_match = *incoming_arrow_datatype == Self::buffer_arrow_datatype();
let is_semantic = descriptor.component_type == Some(self.buffer_semantic_type);
match (is_physical_match, is_semantic) {
(true, true) => Some(DatatypeMatch::NativeSemantics {
arrow_datatype: incoming_arrow_datatype.clone(),
component_type: descriptor.component_type,
}),
(true, false) => Some(DatatypeMatch::PhysicalDatatypeOnly {
arrow_datatype: incoming_arrow_datatype.clone(),
component_type: descriptor.component_type,
selectors: Vec::new(),
}),
(false, _) => {
extract_nested_fields(incoming_arrow_datatype, |dt| {
*dt == Self::buffer_arrow_datatype()
})
.map(|selectors| DatatypeMatch::PhysicalDatatypeOnly {
arrow_datatype: incoming_arrow_datatype.clone(),
component_type: descriptor.component_type,
selectors: selectors.into(),
})
}
}
}
pub(crate) fn check_format_match(
&self,
incoming_arrow_datatype: &arrow::datatypes::DataType,
descriptor: &re_sdk_types::ComponentDescriptor,
) -> bool {
*incoming_arrow_datatype == self.format_arrow_datatype
&& descriptor.component_type == Some(self.format_semantic_type)
}
}
impl From<BufferAndFormatConstraint> for VisualizabilityConstraints {
fn from(req: BufferAndFormatConstraint) -> Self {
Self::BufferAndFormat(req)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VisualizabilityConstraints {
None,
AnyBuiltinComponent(ComponentSet),
SingleRequiredComponent(SingleRequiredComponentConstraint),
BufferAndFormat(BufferAndFormatConstraint),
}