use arrow::array::Array as _;
use crate::Loggable as _;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ChunkId(pub(crate) re_tuid::Tuid);
impl std::fmt::Display for ChunkId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "chunk_{}", self.0)
}
}
#[derive(thiserror::Error, Debug)]
#[error("Invalid ChunkId: {0}")]
pub struct InvalidChunkIdError(String);
impl std::str::FromStr for ChunkId {
type Err = InvalidChunkIdError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let tuid_str = if let Some((namespace, tuid_str)) = s.split_once('_') {
if namespace == "chunk" {
tuid_str
} else {
return Err(InvalidChunkIdError(format!(
"Expected chunk_ prefix, got {s:?}"
)));
}
} else {
s
};
re_tuid::Tuid::from_str(tuid_str)
.map(Self)
.map_err(|err| InvalidChunkIdError(format!("Invalid TUID: {err}")))
}
}
impl ChunkId {
pub const ZERO: Self = Self(re_tuid::Tuid::ZERO);
pub const MAX: Self = Self(re_tuid::Tuid::MAX);
#[expect(clippy::new_without_default)]
#[inline]
pub fn new() -> Self {
Self(re_tuid::Tuid::new())
}
#[inline]
pub fn from_tuid(tuid: re_tuid::Tuid) -> Self {
Self(tuid)
}
#[inline]
pub fn as_tuid(&self) -> re_tuid::Tuid {
self.0
}
#[must_use]
#[inline]
pub fn next(&self) -> Self {
Self(self.0.next())
}
#[must_use]
#[inline]
pub fn incremented_by(&self, n: u64) -> Self {
Self(self.0.incremented_by(n))
}
#[inline]
pub fn from_u128(id: u128) -> Self {
Self(re_tuid::Tuid::from_u128(id))
}
}
impl re_byte_size::SizeBytes for ChunkId {
#[inline]
fn heap_size_bytes(&self) -> u64 {
0
}
#[inline]
fn is_pod() -> bool {
true
}
}
impl std::ops::Deref for ChunkId {
type Target = re_tuid::Tuid;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for ChunkId {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
crate::delegate_arrow_tuid!(ChunkId as "rerun.controls.ChunkId");
#[repr(C, align(1))]
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
bytemuck::AnyBitPattern,
bytemuck::NoUninit,
)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct RowId(pub(crate) re_tuid::Tuid);
impl std::fmt::Display for RowId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "row_{}", self.0)
}
}
#[derive(thiserror::Error, Debug)]
#[error("Invalid RowId: {0}")]
pub struct InvalidRowIdError(String);
impl std::str::FromStr for RowId {
type Err = InvalidRowIdError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let tuid_str = if let Some((namespace, tuid_str)) = s.split_once('_') {
if namespace == "row" {
tuid_str
} else {
return Err(InvalidRowIdError(format!(
"Expected row_ prefix, got {s:?}"
)));
}
} else {
s
};
re_tuid::Tuid::from_str(tuid_str)
.map(Self)
.map_err(|err| InvalidRowIdError(format!("Invalid TUID: {err}")))
}
}
impl RowId {
pub const ZERO: Self = Self(re_tuid::Tuid::ZERO);
pub const MAX: Self = Self(re_tuid::Tuid::MAX);
#[expect(clippy::new_without_default)]
#[inline]
pub fn new() -> Self {
Self(re_tuid::Tuid::new())
}
#[inline]
pub fn from_tuid(tuid: re_tuid::Tuid) -> Self {
Self(tuid)
}
#[inline]
pub fn as_tuid(&self) -> re_tuid::Tuid {
self.0
}
#[must_use]
#[inline]
pub fn next(&self) -> Self {
Self(self.0.next())
}
#[must_use]
#[inline]
pub fn incremented_by(&self, n: u64) -> Self {
Self(self.0.incremented_by(n))
}
#[inline]
pub fn from_u128(id: u128) -> Self {
Self(re_tuid::Tuid::from_u128(id))
}
pub fn arrow_from_slice(slice: &[Self]) -> arrow::array::FixedSizeBinaryArray {
crate::tuids_to_arrow(bytemuck::cast_slice(slice))
}
pub fn slice_from_arrow(array: &arrow::array::FixedSizeBinaryArray) -> &[Self] {
debug_assert_eq!(array.data_type(), &Self::arrow_datatype());
bytemuck::cast_slice(array.value_data())
}
}
impl re_byte_size::SizeBytes for RowId {
#[inline]
fn heap_size_bytes(&self) -> u64 {
0
}
#[inline]
fn is_pod() -> bool {
true
}
}
impl std::ops::Deref for RowId {
type Target = re_tuid::Tuid;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for RowId {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
crate::delegate_arrow_tuid!(RowId as "rerun.controls.RowId");
#[test]
fn test_row_id_parse() {
let tuid: re_tuid::Tuid = "182342300C5F8C327a7b4a6e5a379ac4".parse().unwrap();
assert_eq!(
RowId(tuid).to_string(),
"row_182342300C5F8C327a7b4a6e5a379ac4"
);
assert_eq!(
"182342300C5F8C327a7b4a6e5a379ac4"
.parse::<RowId>()
.unwrap()
.0,
tuid
);
assert_eq!(
"row_182342300C5F8C327a7b4a6e5a379ac4"
.parse::<RowId>()
.unwrap()
.0,
tuid
);
assert!(
"chunk_182342300C5F8C327a7b4a6e5a379ac4"
.parse::<RowId>()
.is_err()
);
}