use re_entity_db::{EntityDb, InstancePath};
use re_log_types::{ComponentPath, DataPath, EntityPath};
use crate::{ContainerId, SpaceViewId};
#[derive(Clone, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
pub enum Item {
AppId(re_log_types::ApplicationId),
DataSource(re_smart_channel::SmartChannelSource),
StoreId(re_log_types::StoreId),
ComponentPath(ComponentPath),
SpaceView(SpaceViewId),
InstancePath(InstancePath),
DataResult(SpaceViewId, InstancePath),
Container(ContainerId),
}
impl Item {
pub fn entity_path(&self) -> Option<&EntityPath> {
match self {
Self::AppId(_)
| Self::DataSource(_)
| Self::SpaceView(_)
| Self::Container(_)
| Self::StoreId(_) => None,
Self::ComponentPath(component_path) => Some(&component_path.entity_path),
Self::InstancePath(instance_path) | Self::DataResult(_, instance_path) => {
Some(&instance_path.entity_path)
}
}
}
}
impl From<SpaceViewId> for Item {
#[inline]
fn from(space_view_id: SpaceViewId) -> Self {
Self::SpaceView(space_view_id)
}
}
impl From<ComponentPath> for Item {
#[inline]
fn from(component_path: ComponentPath) -> Self {
Self::ComponentPath(component_path)
}
}
impl From<EntityPath> for Item {
#[inline]
fn from(entity_path: EntityPath) -> Self {
Self::InstancePath(InstancePath::from(entity_path))
}
}
impl From<InstancePath> for Item {
#[inline]
fn from(instance_path: InstancePath) -> Self {
Self::InstancePath(instance_path)
}
}
impl std::str::FromStr for Item {
type Err = re_log_types::PathParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let DataPath {
entity_path,
instance,
component_name,
} = DataPath::from_str(s)?;
match (instance, component_name) {
(Some(instance), Some(_component_name)) => {
Err(re_log_types::PathParseError::UnexpectedInstance(instance))
}
(Some(instance), None) => Ok(Self::InstancePath(InstancePath::instance(
entity_path,
instance,
))),
(None, Some(component_name)) => Ok(Self::ComponentPath(ComponentPath {
entity_path,
component_name,
})),
(None, None) => Ok(Self::InstancePath(InstancePath::entity_all(entity_path))),
}
}
}
impl std::fmt::Debug for Item {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::AppId(app_id) => app_id.fmt(f),
Self::DataSource(data_source) => data_source.fmt(f),
Self::StoreId(store_id) => store_id.fmt(f),
Self::ComponentPath(s) => s.fmt(f),
Self::SpaceView(s) => write!(f, "{s:?}"),
Self::InstancePath(path) => write!(f, "{path}"),
Self::DataResult(space_view_id, instance_path) => {
write!(f, "({space_view_id:?}, {instance_path}")
}
Self::Container(tile_id) => write!(f, "(tile: {tile_id:?})"),
}
}
}
impl Item {
pub fn kind(&self) -> &'static str {
match self {
Self::AppId(_) => "Application",
Self::DataSource(_) => "Data source",
Self::StoreId(store_id) => match store_id.kind {
re_log_types::StoreKind::Recording => "Recording ID",
re_log_types::StoreKind::Blueprint => "Blueprint ID",
},
Self::InstancePath(instance_path) => {
if instance_path.instance.is_specific() {
"Entity instance"
} else {
"Entity"
}
}
Self::ComponentPath(_) => "Entity component",
Self::SpaceView(_) => "View",
Self::Container(_) => "Container",
Self::DataResult(_, instance_path) => {
if instance_path.instance.is_specific() {
"Data result instance"
} else {
"Data result entity"
}
}
}
}
}
pub fn resolve_mono_instance_path_item(
entity_db: &EntityDb,
query: &re_chunk_store::LatestAtQuery,
item: &Item,
) -> Item {
match item {
Item::InstancePath(instance_path) => {
Item::InstancePath(resolve_mono_instance_path(entity_db, query, instance_path))
}
Item::DataResult(space_view_id, instance_path) => Item::DataResult(
*space_view_id,
resolve_mono_instance_path(entity_db, query, instance_path),
),
Item::AppId(_)
| Item::DataSource(_)
| Item::StoreId(_)
| Item::ComponentPath(_)
| Item::SpaceView(_)
| Item::Container(_) => item.clone(),
}
}
pub fn resolve_mono_instance_path(
entity_db: &EntityDb,
query: &re_chunk_store::LatestAtQuery,
instance: &re_entity_db::InstancePath,
) -> re_entity_db::InstancePath {
re_tracing::profile_function!();
if instance.instance.get() == 0 {
let engine = entity_db.storage_engine();
let Some(component_names) = engine
.store()
.all_components_on_timeline(&query.timeline(), &instance.entity_path)
else {
return re_entity_db::InstancePath::entity_all(instance.entity_path.clone());
};
for component_name in component_names {
if let Some(array) = engine
.cache()
.latest_at(query, &instance.entity_path, [component_name])
.component_batch_raw(&component_name)
{
if array.len() > 1 {
return instance.clone();
}
}
}
return re_entity_db::InstancePath::entity_all(instance.entity_path.clone());
}
instance.clone()
}