use nohash_hasher::IntMap;
use crate::{
ArchetypeName, Component, ComponentDescriptor, ComponentIdentifier, SerializedComponentBatch,
reflection::ComponentDescriptorExt as _,
};
use re_types_core::{AsComponents, ComponentType, Loggable, try_serialize_field};
pub struct DynamicArchetype {
archetype_name: Option<ArchetypeName>,
batches: IntMap<ComponentIdentifier, SerializedComponentBatch>,
}
impl DynamicArchetype {
#[inline]
pub fn new(archetype_name: impl Into<ArchetypeName>) -> Self {
Self {
archetype_name: Some(archetype_name.into()),
batches: Default::default(),
}
}
pub(crate) fn new_without_archetype() -> Self {
Self {
archetype_name: None,
batches: Default::default(),
}
}
#[inline]
pub fn with_component_from_data(
mut self,
field: impl AsRef<str>,
array: arrow::array::ArrayRef,
) -> Self {
let field = field.as_ref();
let component = field.into();
self.batches.insert(
component,
SerializedComponentBatch {
array,
descriptor: {
let mut desc = ComponentDescriptor::partial(component);
if let Some(archetype_name) = self.archetype_name {
desc = desc.with_builtin_archetype(archetype_name);
}
desc
},
},
);
self
}
#[inline]
pub fn with_component<C: Component>(
self,
field: impl AsRef<str>,
loggable: impl IntoIterator<Item = impl Into<C>>,
) -> Self {
self.with_component_override(field, C::name(), loggable)
}
#[inline]
pub fn with_component_override<L: Loggable>(
mut self,
field: impl AsRef<str>,
component_type: impl Into<ComponentType>,
loggable: impl IntoIterator<Item = impl Into<L>>,
) -> Self {
let field = field.as_ref();
let component = field.into();
let mut desc =
ComponentDescriptor::partial(component).with_component_type(component_type.into());
if let Some(archetype_name) = self.archetype_name {
desc = desc.with_builtin_archetype(archetype_name);
}
try_serialize_field(desc, loggable)
.and_then(|serialized| self.batches.insert(component, serialized));
self
}
}
impl AsComponents for DynamicArchetype {
fn as_serialized_batches(&self) -> Vec<SerializedComponentBatch> {
self.batches.values().cloned().collect()
}
}
#[cfg(test)]
mod test {
use std::collections::BTreeSet;
use crate::components;
use re_types_core::datatypes::Utf8;
use super::*;
#[test]
fn with_archetype() {
let values = DynamicArchetype::new("MyExample")
.with_component::<components::Scalar>("confidence", [1.2f64, 3.4, 5.6])
.with_component_override::<Utf8>("homepage", "user.url", vec!["https://www.rerun.io"])
.with_component_from_data(
"description",
std::sync::Arc::new(arrow::array::StringArray::from(vec!["Bla bla bla…"])),
);
let actual = values
.as_serialized_batches()
.into_iter()
.map(|batch| batch.descriptor)
.collect::<BTreeSet<_>>();
assert_eq!(
actual,
[
ComponentDescriptor::partial("confidence")
.with_builtin_archetype("MyExample")
.with_component_type(components::Scalar::name()),
ComponentDescriptor::partial("homepage")
.with_component_type("user.url".into())
.with_builtin_archetype("MyExample"),
ComponentDescriptor::partial("description").with_builtin_archetype("MyExample"),
]
.into_iter()
.collect()
);
}
}