use arrow::datatypes::{DataType as ArrowDatatype, Field as ArrowField};
use re_log_types::{ComponentPath, EntityPath};
use re_types_core::{ArchetypeFieldName, ArchetypeName, ComponentDescriptor, ComponentName};
use crate::{ArrowFieldMetadata, MetadataExt as _, MissingFieldMetadata};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ComponentColumnDescriptor {
pub store_datatype: ArrowDatatype,
pub entity_path: EntityPath,
pub archetype_name: Option<ArchetypeName>,
pub archetype_field_name: Option<ArchetypeFieldName>,
pub component_name: ComponentName,
pub is_static: bool,
pub is_indicator: bool,
pub is_tombstone: bool,
pub is_semantically_empty: bool,
}
impl PartialOrd for ComponentColumnDescriptor {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ComponentColumnDescriptor {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let Self {
entity_path,
archetype_name,
archetype_field_name,
component_name,
store_datatype: _,
is_static: _,
is_indicator: _,
is_tombstone: _,
is_semantically_empty: _,
} = self;
entity_path
.cmp(&other.entity_path)
.then_with(|| archetype_name.cmp(&other.archetype_name))
.then_with(|| archetype_field_name.cmp(&other.archetype_field_name))
.then_with(|| component_name.cmp(&other.component_name))
}
}
impl std::fmt::Display for ComponentColumnDescriptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {
entity_path,
archetype_name,
archetype_field_name,
component_name,
store_datatype: _,
is_static,
is_indicator: _,
is_tombstone: _,
is_semantically_empty: _,
} = self;
let descriptor = ComponentDescriptor {
archetype_name: *archetype_name,
archetype_field_name: *archetype_field_name,
component_name: *component_name,
};
let s = format!("{entity_path}@{}", descriptor.short_name());
if *is_static {
f.write_fmt(format_args!("|{s}|"))
} else {
f.write_str(&s)
}
}
}
impl From<ComponentColumnDescriptor> for re_types_core::ComponentDescriptor {
#[inline]
fn from(descr: ComponentColumnDescriptor) -> Self {
Self {
archetype_name: descr.archetype_name,
archetype_field_name: descr.archetype_field_name,
component_name: descr.component_name,
}
}
}
impl From<&ComponentColumnDescriptor> for re_types_core::ComponentDescriptor {
#[inline]
fn from(descr: &ComponentColumnDescriptor) -> Self {
Self {
archetype_name: descr.archetype_name,
archetype_field_name: descr.archetype_field_name,
component_name: descr.component_name,
}
}
}
impl ComponentColumnDescriptor {
pub fn component_path(&self) -> ComponentPath {
ComponentPath {
entity_path: self.entity_path.clone(),
component_name: self.component_name,
}
}
#[inline]
pub fn matches(&self, entity_path: &EntityPath, component_name: &str) -> bool {
&self.entity_path == entity_path && self.component_name.matches(component_name)
}
fn metadata(&self) -> ArrowFieldMetadata {
let Self {
entity_path,
archetype_name,
archetype_field_name,
component_name,
store_datatype: _,
is_static,
is_indicator,
is_tombstone,
is_semantically_empty,
} = self;
[
Some(("rerun.kind".to_owned(), "data".to_owned())),
Some(("rerun.entity_path".to_owned(), entity_path.to_string())),
archetype_name.map(|name| ("rerun.archetype".to_owned(), name.short_name().to_owned())),
archetype_field_name
.as_ref()
.map(|name| ("rerun.archetype_field".to_owned(), name.to_string())),
Some((
"rerun.component".to_owned(),
component_name.short_name().to_owned(),
)),
(*is_static).then_some(("rerun.is_static".to_owned(), "yes".to_owned())),
(*is_indicator).then_some(("rerun.is_indicator".to_owned(), "yes".to_owned())),
(*is_tombstone).then_some(("rerun.is_tombstone".to_owned(), "yes".to_owned())),
(*is_semantically_empty)
.then_some(("rerun.is_semantically_empty".to_owned(), "yes".to_owned())),
]
.into_iter()
.flatten()
.collect()
}
#[inline]
pub fn returned_datatype(&self) -> ArrowDatatype {
self.store_datatype.clone()
}
#[inline]
pub fn to_arrow_field(&self) -> ArrowField {
let entity_path = &self.entity_path;
let descriptor = ComponentDescriptor {
archetype_name: self.archetype_name,
archetype_field_name: self.archetype_field_name,
component_name: self.component_name,
};
ArrowField::new(
format!("{}:{}", entity_path, descriptor.component_name.short_name()),
self.returned_datatype(),
true, )
.with_metadata(self.metadata())
}
}
impl TryFrom<&ArrowField> for ComponentColumnDescriptor {
type Error = MissingFieldMetadata;
fn try_from(field: &ArrowField) -> Result<Self, Self::Error> {
Ok(Self {
store_datatype: field.data_type().clone(),
entity_path: EntityPath::parse_forgiving(field.get_or_err("rerun.entity_path")?),
archetype_name: field.get_opt("rerun.archetype").map(|x| x.into()),
archetype_field_name: field.get_opt("rerun.archetype_field").map(|x| x.into()),
component_name: field.get_or_err("rerun.component")?.into(),
is_static: field.get_bool("rerun.is_static"),
is_indicator: field.get_bool("rerun.is_indicator"),
is_tombstone: field.get_bool("rerun.is_tombstone"),
is_semantically_empty: field.get_bool("rerun.is_semantically_empty"),
})
}
}