Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor InstanceId #999

Merged
merged 17 commits into from
Jan 31, 2023
167 changes: 0 additions & 167 deletions crates/re_data_store/src/instance.rs

This file was deleted.

158 changes: 158 additions & 0 deletions crates/re_data_store/src/instance_path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
use std::hash::Hash;

use re_log_types::{component_types::Instance, EntityPath, EntityPathHash};

use crate::log_db::EntityDb;

// ----------------------------------------------------------------------------

/// The path to either a specific instance of an entity, or the whole entity (splat).
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct InstancePath {
pub entity_path: EntityPath,

/// If this is a concrete instance, what instance index are we?
///
/// If we refer to all instance, [`Instance::SPLAT`] is used.
pub instance_index: Instance,
}

impl InstancePath {
/// Indicate the whole entity (all instances of it) - i.e. a splat.
///
/// For instance: the whole point cloud, rather than a specific point.
#[inline]
pub fn entity_splat(entity_path: EntityPath) -> Self {
Self {
entity_path,
instance_index: Instance::SPLAT,
}
}

/// Indicate a specific instance of the entity,
/// e.g. a specific point in a point cloud entity.
#[inline]
pub fn instance(entity_path: EntityPath, instance_index: Instance) -> Self {
Self {
entity_path,
instance_index,
}
}

/// Do we refer to the whole entity (all instances of it)?
///
/// For instance: the whole point cloud, rather than a specific point.
#[inline]
pub fn is_splat(&self) -> bool {
self.instance_index.is_splat()
}

#[inline]
pub fn hash(&self) -> InstancePathHash {
InstancePathHash {
entity_path_hash: self.entity_path.hash(),
instance_index: self.instance_index,
}
}
}

impl std::fmt::Display for InstancePath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.instance_index.is_splat() {
self.entity_path.fmt(f)
} else {
format!("{}[{}]", self.entity_path, self.instance_index).fmt(f)
}
}
}

// ----------------------------------------------------------------------------

/// Hashes of the components of an [`InstancePath`].
///
/// This is unique to either a specific instance of an entity, or the whole entity (splat).
#[derive(Clone, Copy, Debug, Eq)]
pub struct InstancePathHash {
pub entity_path_hash: EntityPathHash,

/// If this is a concrete instance, what instance index are we?
///
/// If we refer to all instance, [`Instance::SPLAT`] is used.
///
/// Note that this is NOT hashed, because we don't need to (it's already small).
pub instance_index: Instance,
}

impl std::hash::Hash for InstancePathHash {
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
state.write_u64(self.entity_path_hash.hash64());
state.write_u64(self.instance_index.0);
}
}

impl std::cmp::PartialEq for InstancePathHash {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.entity_path_hash == other.entity_path_hash
&& self.instance_index == other.instance_index
}
}

impl InstancePathHash {
pub const NONE: Self = Self {
entity_path_hash: EntityPathHash::NONE,
instance_index: Instance::SPLAT,
};

/// Indicate the whole entity (all instances of it) - i.e. a splat.
///
/// For instance: the whole point cloud, rather than a specific point.
#[inline]
pub fn entity_splat(entity_path: &EntityPath) -> Self {
Self {
entity_path_hash: entity_path.hash(),
instance_index: Instance::SPLAT,
}
}

/// Indicate a specific instance of the entity,
/// e.g. a specific point in a point cloud entity.
#[inline]
pub fn instance(entity_path: &EntityPath, instance_index: Instance) -> Self {
Self {
entity_path_hash: entity_path.hash(),
instance_index,
}
}

#[inline]
pub fn is_some(&self) -> bool {
self.entity_path_hash.is_some()
}

#[inline]
pub fn is_none(&self) -> bool {
self.entity_path_hash.is_none()
}

pub fn resolve(&self, entity_db: &EntityDb) -> Option<InstancePath> {
let entity_path = entity_db
.entity_path_from_hash(&self.entity_path_hash)
.cloned()?;

let instance_index = self.instance_index;

Some(InstancePath {
entity_path,
instance_index,
})
}
}

impl Default for InstancePathHash {
fn default() -> Self {
Self::NONE
}
}
4 changes: 2 additions & 2 deletions crates/re_data_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

pub mod entity_properties;
pub mod entity_tree;
mod instance;
mod instance_path;
pub mod log_db;

pub use entity_properties::*;
pub use entity_tree::*;
pub use instance::*;
pub use instance_path::*;
pub use log_db::LogDb;

use re_log_types::msg_bundle;
Expand Down
30 changes: 25 additions & 5 deletions crates/re_log_types/src/component_types/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use arrow2_convert::{ArrowDeserialize, ArrowField, ArrowSerialize};

use crate::msg_bundle::Component;

/// The Instance used to identify an entity within a batch
/// A number used to specify a specific instance in an entity.
///
/// Each entity can have many component of the same type.
/// These are identified with [`Instance`].
///
/// ```
/// use re_log_types::component_types::Instance;
Expand All @@ -29,14 +32,31 @@ use crate::msg_bundle::Component;
pub struct Instance(pub u64);

impl Instance {
/// A special value indicating that this [`Instance]` is referring to all instances,
/// for instance all points in a point cloud entity.
emilk marked this conversation as resolved.
Show resolved Hide resolved
///
/// In some contexts it is also used to mean no instances.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems unexpected and probably needs a few more words.

The fact that InstancePathHash::None happens to specify SPLAT makes sense.

Are there other contexts where SPLAT means none?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the comment. It wasn't even correct. Even in an InstancePath, SPLAT means "all the instances of the entity".

pub const SPLAT: Self = Self(u64::MAX);

/// Are we referring to all instances of the entity (e.g. all points in a point cloud entity)?
///
/// The opposite of [`Self::is_specific`].
#[inline]
pub fn splat() -> Instance {
Self(u64::MAX)
pub fn is_splat(self) -> bool {
self == Self::SPLAT
}

/// Are we referring to a specific instance of the entity (e.g. a specific point in a point cloud)?
///
/// The opposite of [`Self::is_splat`].
#[inline]
pub fn is_splat(&self) -> bool {
self.0 == u64::MAX
pub fn is_specific(self) -> bool {
self != Self::SPLAT
}

/// Returns `None` if splat, otherwise the index.
pub fn specific_index(self) -> Option<Instance> {
self.is_specific().then_some(self)
}
}

Expand Down
Loading