re_entity_db/
instance_path.rs1use std::hash::Hash;
2use std::str::FromStr;
3
4use re_chunk::RowId;
5use re_log_types::{DataPath, EntityPath, EntityPathHash, Instance, PathParseError};
6
7use crate::{EntityDb, VersionedInstancePath, VersionedInstancePathHash};
8
9#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
13#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
14pub struct InstancePath {
15 pub entity_path: EntityPath,
16
17 pub instance: Instance,
21}
22
23impl From<EntityPath> for InstancePath {
24 #[inline]
25 fn from(entity_path: EntityPath) -> Self {
26 Self::entity_all(entity_path)
27 }
28}
29
30impl InstancePath {
31 #[inline]
35 pub fn entity_all(entity_path: impl Into<EntityPath>) -> Self {
36 Self {
37 entity_path: entity_path.into(),
38 instance: Instance::ALL,
39 }
40 }
41
42 #[inline]
45 pub fn instance(entity_path: impl Into<EntityPath>, instance: impl Into<Instance>) -> Self {
46 Self {
47 entity_path: entity_path.into(),
48 instance: instance.into(),
49 }
50 }
51
52 #[inline]
56 pub fn is_all(&self) -> bool {
57 self.instance.is_all()
58 }
59
60 #[inline]
62 pub fn versioned(&self, row_id: RowId) -> VersionedInstancePath {
63 VersionedInstancePath {
64 instance_path: self.clone(),
65 row_id,
66 }
67 }
68
69 #[inline]
70 pub fn hash(&self) -> InstancePathHash {
71 InstancePathHash {
72 entity_path_hash: self.entity_path.hash(),
73 instance: self.instance,
74 }
75 }
76
77 pub fn kind(&self) -> &'static str {
79 if self.instance.is_specific() {
80 "Entity instance"
81 } else {
82 "Entity"
83 }
84 }
85}
86
87impl std::fmt::Display for InstancePath {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 if self.instance.is_all() {
90 self.entity_path.fmt(f)
91 } else {
92 format!("{}[{}]", self.entity_path, self.instance).fmt(f)
93 }
94 }
95}
96
97impl FromStr for InstancePath {
98 type Err = PathParseError;
99
100 fn from_str(s: &str) -> Result<Self, Self::Err> {
101 let DataPath {
102 entity_path,
103 instance,
104 component,
105 } = DataPath::from_str(s)?;
106
107 if let Some(component) = component {
108 return Err(PathParseError::UnexpectedComponent(component));
109 }
110
111 let instance = instance.unwrap_or(Instance::ALL);
112
113 Ok(Self {
114 entity_path,
115 instance,
116 })
117 }
118}
119
120#[test]
121fn test_parse_instance_path() {
122 assert_eq!(
123 InstancePath::from_str("world/points[#123]"),
124 Ok(InstancePath {
125 entity_path: EntityPath::from("world/points"),
126 instance: Instance::from(123)
127 })
128 );
129}
130
131#[derive(Clone, Copy, Eq)]
137pub struct InstancePathHash {
138 pub entity_path_hash: EntityPathHash,
139
140 pub instance: Instance,
146}
147
148impl std::fmt::Debug for InstancePathHash {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 let Self {
151 entity_path_hash,
152 instance,
153 } = self;
154 write!(
155 f,
156 "InstancePathHash({:016X}, {})",
157 entity_path_hash.hash64(),
158 instance.get()
159 )
160 }
161}
162
163impl std::hash::Hash for InstancePathHash {
164 #[inline]
165 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
166 let Self {
167 entity_path_hash,
168 instance,
169 } = self;
170
171 state.write_u64(entity_path_hash.hash64());
172 state.write_u64(instance.get());
173 }
174}
175
176impl std::cmp::PartialEq for InstancePathHash {
177 #[inline]
178 fn eq(&self, other: &Self) -> bool {
179 let Self {
180 entity_path_hash,
181 instance,
182 } = self;
183
184 entity_path_hash == &other.entity_path_hash && instance == &other.instance
185 }
186}
187
188impl InstancePathHash {
189 pub const NONE: Self = Self {
190 entity_path_hash: EntityPathHash::NONE,
191 instance: Instance::ALL,
192 };
193
194 #[inline]
198 pub fn entity_all(entity_path: &EntityPath) -> Self {
199 Self {
200 entity_path_hash: entity_path.hash(),
201 instance: Instance::ALL,
202 }
203 }
204
205 #[inline]
208 pub fn instance(entity_path: &EntityPath, instance: Instance) -> Self {
209 Self {
210 entity_path_hash: entity_path.hash(),
211 instance,
212 }
213 }
214
215 #[inline]
216 pub fn is_some(&self) -> bool {
217 self.entity_path_hash.is_some()
218 }
219
220 #[inline]
221 pub fn is_none(&self) -> bool {
222 self.entity_path_hash.is_none()
223 }
224
225 #[inline]
227 pub fn versioned(&self, row_id: RowId) -> VersionedInstancePathHash {
228 VersionedInstancePathHash {
229 instance_path_hash: *self,
230 row_id,
231 }
232 }
233
234 pub fn resolve(&self, entity_db: &EntityDb) -> Option<InstancePath> {
235 let entity_path = entity_db
236 .entity_path_from_hash(&self.entity_path_hash)
237 .cloned()?;
238
239 let instance = self.instance;
240
241 Some(InstancePath {
242 entity_path,
243 instance,
244 })
245 }
246}
247
248impl Default for InstancePathHash {
249 fn default() -> Self {
250 Self::NONE
251 }
252}