re_sorbet/
column_descriptor.rsuse arrow::datatypes::{
DataType as ArrowDatatype, Field as ArrowField, FieldRef as ArrowFieldRef,
Fields as ArrowFields,
};
use re_log_types::EntityPath;
use re_types_core::ComponentName;
use crate::{ColumnKind, ComponentColumnDescriptor, IndexColumnDescriptor};
#[derive(thiserror::Error, Debug)]
pub enum ColumnError {
#[error(transparent)]
MissingFieldMetadata(#[from] crate::MissingFieldMetadata),
#[error(transparent)]
UnknownColumnKind(#[from] crate::UnknownColumnKind),
#[error("Unsupported column rerun.kind: {kind:?}. Expected one of: index, data")]
UnsupportedColumnKind { kind: ColumnKind },
#[error(transparent)]
UnsupportedTimeType(#[from] crate::UnsupportedTimeType),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ColumnDescriptor {
Time(IndexColumnDescriptor),
Component(ComponentColumnDescriptor),
}
impl ColumnDescriptor {
#[inline]
#[track_caller]
pub fn sanity_check(&self) {
match self {
Self::Time(_) => {}
Self::Component(descr) => descr.sanity_check(),
}
}
#[inline]
pub fn entity_path(&self) -> Option<&EntityPath> {
match self {
Self::Time(_) => None,
Self::Component(descr) => Some(&descr.entity_path),
}
}
#[inline]
pub fn component_name(&self) -> Option<&ComponentName> {
match self {
Self::Time(_) => None,
Self::Component(descr) => Some(&descr.component_name),
}
}
#[inline]
pub fn short_name(&self) -> String {
match self {
Self::Time(descr) => descr.column_name().to_owned(),
Self::Component(descr) => descr.component_name.short_name().to_owned(),
}
}
#[inline]
pub fn is_static(&self) -> bool {
match self {
Self::Time(_) => false,
Self::Component(descr) => descr.is_static,
}
}
#[inline]
pub fn arrow_datatype(&self) -> ArrowDatatype {
match self {
Self::Time(descr) => descr.datatype().clone(),
Self::Component(descr) => descr.returned_datatype(),
}
}
#[inline]
pub fn to_arrow_field(&self, batch_type: crate::BatchType) -> ArrowField {
match self {
Self::Time(descr) => descr.to_arrow_field(),
Self::Component(descr) => descr.to_arrow_field(batch_type),
}
}
#[inline]
pub fn to_arrow_fields(columns: &[Self], batch_type: crate::BatchType) -> ArrowFields {
columns
.iter()
.map(|c| c.to_arrow_field(batch_type))
.collect()
}
pub fn from_arrow_fields(
chunk_entity_path: Option<&EntityPath>,
fields: &[ArrowFieldRef],
) -> Result<Vec<Self>, ColumnError> {
fields
.iter()
.map(|field| Self::try_from_arrow_field(chunk_entity_path, field.as_ref()))
.collect()
}
}
impl ColumnDescriptor {
pub fn try_from_arrow_field(
chunk_entity_path: Option<&EntityPath>,
field: &ArrowField,
) -> Result<Self, ColumnError> {
match ColumnKind::try_from(field)? {
ColumnKind::RowId => Err(ColumnError::UnsupportedColumnKind {
kind: ColumnKind::RowId,
}),
ColumnKind::Index => Ok(Self::Time(IndexColumnDescriptor::try_from(field)?)),
ColumnKind::Component => Ok(Self::Component(
ComponentColumnDescriptor::from_arrow_field(chunk_entity_path, field),
)),
}
}
}
#[test]
fn test_schema_over_ipc() {
#![expect(clippy::disallowed_methods)] let original_columns = [
ColumnDescriptor::Time(IndexColumnDescriptor::from_timeline(
re_log_types::Timeline::log_time(),
true,
)),
ColumnDescriptor::Component(ComponentColumnDescriptor {
entity_path: re_log_types::EntityPath::from("/some/path"),
archetype_name: Some("archetype".to_owned().into()),
archetype_field_name: Some("field".to_owned().into()),
component_name: re_types_core::ComponentName::new("component"),
store_datatype: arrow::datatypes::DataType::Int64,
is_static: true,
is_tombstone: false,
is_semantically_empty: false,
is_indicator: true,
}),
];
let original_schema = arrow::datatypes::Schema::new(ColumnDescriptor::to_arrow_fields(
&original_columns,
crate::BatchType::Dataframe,
));
let ipc_bytes = crate::ipc_from_schema(&original_schema).unwrap();
let recovered_schema = crate::schema_from_ipc(&ipc_bytes).unwrap();
assert_eq!(recovered_schema.as_ref(), &original_schema);
let recovered_columns =
ColumnDescriptor::from_arrow_fields(None, &recovered_schema.fields).unwrap();
assert_eq!(recovered_columns, original_columns);
}