1use arrow::array::Array as _;
2
3use crate::Loggable as _;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
38#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
39pub struct ChunkId(pub(crate) re_tuid::Tuid);
40
41impl std::fmt::Display for ChunkId {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(f, "chunk_{}", self.0)
44 }
45}
46
47#[derive(thiserror::Error, Debug)]
48#[error("Invalid ChunkId: {0}")]
49pub struct InvalidChunkIdError(String);
50
51impl std::str::FromStr for ChunkId {
52 type Err = InvalidChunkIdError;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 let tuid_str = if let Some((namespace, tuid_str)) = s.split_once('_') {
56 if namespace == "chunk" {
57 tuid_str
58 } else {
59 return Err(InvalidChunkIdError(format!(
60 "Expected chunk_ prefix, got {s:?}"
61 )));
62 }
63 } else {
64 s
65 };
66
67 re_tuid::Tuid::from_str(tuid_str)
68 .map(Self)
69 .map_err(|err| InvalidChunkIdError(format!("Invalid TUID: {err}")))
70 }
71}
72
73impl ChunkId {
74 pub const ZERO: Self = Self(re_tuid::Tuid::ZERO);
75 pub const MAX: Self = Self(re_tuid::Tuid::MAX);
76
77 #[allow(clippy::new_without_default)]
79 #[inline]
80 pub fn new() -> Self {
81 Self(re_tuid::Tuid::new())
82 }
83
84 #[inline]
85 pub fn from_tuid(tuid: re_tuid::Tuid) -> Self {
86 Self(tuid)
87 }
88
89 #[inline]
90 pub fn as_tuid(&self) -> re_tuid::Tuid {
91 self.0
92 }
93
94 #[must_use]
99 #[inline]
100 pub fn next(&self) -> Self {
101 Self(self.0.next())
102 }
103
104 #[must_use]
112 #[inline]
113 pub fn incremented_by(&self, n: u64) -> Self {
114 Self(self.0.incremented_by(n))
115 }
116
117 #[inline]
118 pub fn from_u128(id: u128) -> Self {
119 Self(re_tuid::Tuid::from_u128(id))
120 }
121}
122
123impl re_byte_size::SizeBytes for ChunkId {
124 #[inline]
125 fn heap_size_bytes(&self) -> u64 {
126 0
127 }
128
129 #[inline]
130 fn is_pod() -> bool {
131 true
132 }
133}
134
135impl std::ops::Deref for ChunkId {
136 type Target = re_tuid::Tuid;
137
138 #[inline]
139 fn deref(&self) -> &Self::Target {
140 &self.0
141 }
142}
143
144impl std::ops::DerefMut for ChunkId {
145 #[inline]
146 fn deref_mut(&mut self) -> &mut Self::Target {
147 &mut self.0
148 }
149}
150
151crate::delegate_arrow_tuid!(ChunkId as "rerun.controls.ChunkId"); #[repr(C, align(1))]
200#[derive(
201 Debug,
202 Clone,
203 Copy,
204 PartialEq,
205 Eq,
206 PartialOrd,
207 Ord,
208 Hash,
209 bytemuck::AnyBitPattern,
210 bytemuck::NoUninit,
211)]
212#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
213pub struct RowId(pub(crate) re_tuid::Tuid);
214
215impl std::fmt::Display for RowId {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 write!(f, "row_{}", self.0)
218 }
219}
220
221#[derive(thiserror::Error, Debug)]
222#[error("Invalid RowId: {0}")]
223pub struct InvalidRowIdError(String);
224
225impl std::str::FromStr for RowId {
226 type Err = InvalidRowIdError;
227
228 fn from_str(s: &str) -> Result<Self, Self::Err> {
229 let tuid_str = if let Some((namespace, tuid_str)) = s.split_once('_') {
230 if namespace == "row" {
231 tuid_str
232 } else {
233 return Err(InvalidRowIdError(format!(
234 "Expected row_ prefix, got {s:?}"
235 )));
236 }
237 } else {
238 s
239 };
240
241 re_tuid::Tuid::from_str(tuid_str)
242 .map(Self)
243 .map_err(|err| InvalidRowIdError(format!("Invalid TUID: {err}")))
244 }
245}
246
247impl RowId {
248 pub const ZERO: Self = Self(re_tuid::Tuid::ZERO);
249 pub const MAX: Self = Self(re_tuid::Tuid::MAX);
250
251 #[allow(clippy::new_without_default)]
253 #[inline]
254 pub fn new() -> Self {
255 Self(re_tuid::Tuid::new())
256 }
257
258 #[inline]
259 pub fn from_tuid(tuid: re_tuid::Tuid) -> Self {
260 Self(tuid)
261 }
262
263 #[inline]
264 pub fn as_tuid(&self) -> re_tuid::Tuid {
265 self.0
266 }
267
268 #[must_use]
273 #[inline]
274 pub fn next(&self) -> Self {
275 Self(self.0.next())
276 }
277
278 #[must_use]
286 #[inline]
287 pub fn incremented_by(&self, n: u64) -> Self {
288 Self(self.0.incremented_by(n))
289 }
290
291 #[inline]
292 pub fn from_u128(id: u128) -> Self {
293 Self(re_tuid::Tuid::from_u128(id))
294 }
295
296 pub fn arrow_from_slice(slice: &[Self]) -> arrow::array::FixedSizeBinaryArray {
297 crate::tuids_to_arrow(bytemuck::cast_slice(slice))
298 }
299
300 pub fn slice_from_arrow(array: &arrow::array::FixedSizeBinaryArray) -> &[Self] {
302 debug_assert_eq!(array.data_type(), &Self::arrow_datatype());
303 bytemuck::cast_slice(array.value_data())
304 }
305}
306
307impl re_byte_size::SizeBytes for RowId {
308 #[inline]
309 fn heap_size_bytes(&self) -> u64 {
310 0
311 }
312
313 #[inline]
314 fn is_pod() -> bool {
315 true
316 }
317}
318
319impl std::ops::Deref for RowId {
320 type Target = re_tuid::Tuid;
321
322 #[inline]
323 fn deref(&self) -> &Self::Target {
324 &self.0
325 }
326}
327
328impl std::ops::DerefMut for RowId {
329 #[inline]
330 fn deref_mut(&mut self) -> &mut Self::Target {
331 &mut self.0
332 }
333}
334
335crate::delegate_arrow_tuid!(RowId as "rerun.controls.RowId");
336
337#[test]
338fn test_row_id_parse() {
339 let tuid: re_tuid::Tuid = "182342300C5F8C327a7b4a6e5a379ac4".parse().unwrap();
340
341 assert_eq!(
342 RowId(tuid).to_string(),
343 "row_182342300C5F8C327a7b4a6e5a379ac4"
344 );
345
346 assert_eq!(
347 "182342300C5F8C327a7b4a6e5a379ac4"
348 .parse::<RowId>()
349 .unwrap()
350 .0,
351 tuid
352 );
353 assert_eq!(
354 "row_182342300C5F8C327a7b4a6e5a379ac4"
355 .parse::<RowId>()
356 .unwrap()
357 .0,
358 tuid
359 );
360 assert!("chunk_182342300C5F8C327a7b4a6e5a379ac4"
361 .parse::<RowId>()
362 .is_err());
363}