diff --git a/Cargo.lock b/Cargo.lock index 4bdae32d3de6..805870373290 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6531,6 +6531,7 @@ dependencies = [ "re_tracing", "re_tuid", "serde", + "similar-asserts", "thiserror 1.0.65", ] diff --git a/crates/store/re_types_core/Cargo.toml b/crates/store/re_types_core/Cargo.toml index 93b4cfc65bac..a8b7afa08014 100644 --- a/crates/store/re_types_core/Cargo.toml +++ b/crates/store/re_types_core/Cargo.toml @@ -63,6 +63,7 @@ serde = { workspace = true, optional = true } [dev-dependencies] criterion.workspace = true +similar-asserts.workspace = true [lib] bench = false diff --git a/crates/store/re_types_core/src/as_components.rs b/crates/store/re_types_core/src/as_components.rs new file mode 100644 index 000000000000..249ec9b0b83b --- /dev/null +++ b/crates/store/re_types_core/src/as_components.rs @@ -0,0 +1,557 @@ +use crate::{ + ComponentBatch, ComponentBatchCowWithDescriptor, LoggableBatch as _, ResultExt as _, + SerializationResult, +}; + +/// Describes the interface for interpreting an object as a bundle of [`Component`]s. +/// +/// ## Custom bundles +/// +/// While, in most cases, component bundles are code generated from our [IDL definitions], +/// it is possible to manually extend existing bundles, or even implement fully custom ones. +/// +/// All [`AsComponents`] methods are optional to implement, with the exception of +/// [`AsComponents::as_component_batches`], which describes how the bundle can be interpreted +/// as a set of [`ComponentBatch`]es: arrays of components that are ready to be serialized. +/// +/// Have a look at our [Custom Data Loader] example to learn more about handwritten bundles. +/// +/// [IDL definitions]: https://github.com/rerun-io/rerun/tree/latest/crates/store/re_types/definitions/rerun +/// [Custom Data Loader]: https://github.com/rerun-io/rerun/blob/latest/examples/rust/custom_data_loader +/// [`Component`]: [crate::Component] +pub trait AsComponents { + /// Exposes the object's contents as a set of [`ComponentBatch`]s. + /// + /// This is the main mechanism for easily extending builtin archetypes or even writing + /// fully custom ones. + /// Have a look at our [Custom Data Loader] example to learn more about extending archetypes. + /// + /// Implementers of [`AsComponents`] get one last chance to override the tags in the + /// [`ComponentDescriptor`], see [`ComponentBatchCowWithDescriptor::descriptor_override`]. + /// + /// [Custom Data Loader]: https://github.com/rerun-io/rerun/tree/latest/examples/rust/custom_data_loader + // + // NOTE: Don't bother returning a CoW here: we need to dynamically discard optional components + // depending on their presence (or lack thereof) at runtime anyway. + fn as_component_batches(&self) -> Vec>; + + // --- + + /// Serializes all non-null [`Component`]s of this bundle into Arrow arrays. + /// + /// The default implementation will simply serialize the result of [`Self::as_component_batches`] + /// as-is, which is what you want in 99.9% of cases. + /// + /// [`Component`]: [crate::Component] + #[inline] + fn to_arrow( + &self, + ) -> SerializationResult> { + self.as_component_batches() + .into_iter() + .map(|comp_batch| { + comp_batch + .to_arrow() + .map(|array| { + let field = arrow::datatypes::Field::new( + comp_batch.name().to_string(), + array.data_type().clone(), + false, + ); + (field, array) + }) + .with_context(comp_batch.name()) + }) + .collect() + } + + /// Serializes all non-null [`Component`]s of this bundle into Arrow2 arrays. + /// + /// The default implementation will simply serialize the result of [`Self::as_component_batches`] + /// as-is, which is what you want in 99.9% of cases. + #[inline] + fn to_arrow2( + &self, + ) -> SerializationResult)>> + { + self.as_component_batches() + .into_iter() + .map(|comp_batch| { + comp_batch + .to_arrow2() + .map(|array| { + let field = arrow2::datatypes::Field::new( + comp_batch.name().to_string(), + array.data_type().clone(), + false, + ); + (field, array) + }) + .with_context(comp_batch.name()) + }) + .collect() + } +} + +impl AsComponents for dyn ComponentBatch { + #[inline] + fn as_component_batches(&self) -> Vec> { + vec![ComponentBatchCowWithDescriptor::new(self)] + } +} + +impl AsComponents for [&dyn ComponentBatch; N] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .map(|batch| ComponentBatchCowWithDescriptor::new(*batch)) + .collect() + } +} + +impl AsComponents for [Box; N] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .map(|batch| ComponentBatchCowWithDescriptor::new(&**batch)) + .collect() + } +} + +impl AsComponents for &[&dyn ComponentBatch] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .map(|batch| ComponentBatchCowWithDescriptor::new(*batch)) + .collect() + } +} + +impl AsComponents for &[Box] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .map(|batch| ComponentBatchCowWithDescriptor::new(&**batch)) + .collect() + } +} + +impl AsComponents for Vec<&dyn ComponentBatch> { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .map(|batch| ComponentBatchCowWithDescriptor::new(*batch)) + .collect() + } +} + +impl AsComponents for Vec> { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .map(|batch| ComponentBatchCowWithDescriptor::new(&**batch)) + .collect() + } +} + +impl AsComponents for [AS; N] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for [&dyn AsComponents; N] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for [Box; N] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for &[AS] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for &[&dyn AsComponents] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for &[Box] { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for Vec { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for Vec<&dyn AsComponents> { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +impl AsComponents for Vec> { + #[inline] + fn as_component_batches(&self) -> Vec> { + self.iter() + .flat_map(|as_components| as_components.as_component_batches()) + .collect() + } +} + +// --- + +// NOTE: These needs to not be tests in order for doc-tests to work. + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let _ = (&comp as &dyn re_types_core::AsComponents).as_component_batches(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn single_ascomponents() {} + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let _ = (&[comp] as &dyn re_types_core::AsComponents).as_component_batches(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn single_ascomponents_wrapped() { + // This is non-sense (and more importantly: dangerous): a single component shouldn't be able to + // autocast straight to a collection of batches. +} + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let _ = (&[comp, comp, comp] as &dyn re_types_core::AsComponents).as_component_batches(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn single_ascomponents_wrapped_many() { + // This is non-sense (and more importantly: dangerous): a single component shouldn't be able to + // autocast straight to a collection of batches. +} + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let comps = vec![comp, comp, comp]; +/// let _ = (&comps as &dyn re_types_core::AsComponents).as_component_batches(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn many_ascomponents() {} + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let comps = vec![comp, comp, comp]; +/// let _ = (&[comps] as &dyn re_types_core::AsComponents).as_component_batches(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn many_ascomponents_wrapped() {} + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let comps = vec![comp, comp, comp]; +/// let _ = (&[comps] as &dyn re_types_core::ComponentBatch).to_arrow(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn many_componentbatch_wrapped() {} + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let comps = vec![comp, comp, comp]; +/// let _ = (&[comps.clone(), comps.clone(), comps.clone()] as &dyn re_types_core::AsComponents).as_component_batches(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn many_ascomponents_wrapped_many() {} + +/// ```compile_fail +/// let comp = re_types_core::components::ClearIsRecursive::default(); +/// let comps = vec![comp, comp, comp]; +/// let _ = (&[comps.clone(), comps.clone(), comps.clone()] as &dyn re_types_core::ComponentBatch).to_arrow(); +/// ``` +#[allow(dead_code)] +#[allow(rustdoc::private_doc_tests)] // doc-tests are the only way to assert failed compilation +fn many_componentbatch_wrapped_many() {} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use arrow::array::{ + types::UInt32Type, Array as ArrowArray, PrimitiveArray as ArrowPrimitiveArray, + }; + use similar_asserts::assert_eq; + + use crate::LoggableBatch; + + #[derive(Clone, Copy, Debug, PartialEq, Eq, bytemuck::Pod, bytemuck::Zeroable)] + #[repr(transparent)] + pub struct MyColor(pub u32); + + crate::macros::impl_into_cow!(MyColor); + + impl re_byte_size::SizeBytes for MyColor { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self(_) = self; + 0 + } + } + + impl crate::Loggable for MyColor { + fn arrow2_datatype() -> arrow2::datatypes::DataType { + arrow2::datatypes::DataType::UInt32 + } + + fn to_arrow2_opt<'a>( + data: impl IntoIterator>>>, + ) -> crate::SerializationResult> + where + Self: 'a, + { + use crate::datatypes::UInt32; + UInt32::to_arrow2_opt( + data.into_iter() + .map(|opt| opt.map(Into::into).map(|c| UInt32(c.0))), + ) + } + + fn from_arrow2_opt( + data: &dyn arrow2::array::Array, + ) -> crate::DeserializationResult>> { + use crate::datatypes::UInt32; + Ok(UInt32::from_arrow2_opt(data)? + .into_iter() + .map(|opt| opt.map(|v| Self(v.0))) + .collect()) + } + } + + impl crate::Component for MyColor { + fn descriptor() -> crate::ComponentDescriptor { + crate::ComponentDescriptor::new("example.MyColor") + } + } + + #[allow(dead_code)] + fn data() -> (MyColor, MyColor, MyColor, Vec) { + let red = MyColor(0xDD0000FF); + let green = MyColor(0x00DD00FF); + let blue = MyColor(0x0000DDFF); + let colors = vec![red, green, blue]; + (red, green, blue, colors) + } + + #[test] + fn single_ascomponents_howto() -> anyhow::Result<()> { + let (red, _, _, _) = data(); + + let got = { + let red = &red as &dyn crate::ComponentBatch; + let got: Result, _> = (&[red] as &dyn crate::AsComponents) + .as_component_batches() + .into_iter() + .map(|batch| batch.to_arrow()) + .collect(); + got? + }; + let expected = vec![ + Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc, + ]; + assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn single_componentbatch() -> anyhow::Result<()> { + let (red, _, _, _) = data(); + + // A single component should autocast to a batch with a single instance. + let got = (&red as &dyn crate::ComponentBatch).to_arrow()?; + let expected = + Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc; + similar_asserts::assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn single_ascomponents_wrapped_howto() -> anyhow::Result<()> { + let (red, _, _, _) = data(); + + let got = { + let red = &red as &dyn crate::ComponentBatch; + let got: Result, _> = (&[red] as &dyn crate::AsComponents) + .as_component_batches() + .into_iter() + .map(|batch| batch.to_arrow()) + .collect(); + got? + }; + let expected = vec![ + Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc, + ]; + assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn single_componentbatch_wrapped() -> anyhow::Result<()> { + let (red, _, _, _) = data(); + + // Nothing out of the ordinary here, a slice of components is indeed a batch. + let got = (&[red] as &dyn crate::ComponentBatch).to_arrow()?; + let expected = + Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc; + similar_asserts::assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn single_ascomponents_wrapped_many_howto() -> anyhow::Result<()> { + let (red, green, blue, _) = data(); + + let got = { + let red = &red as &dyn crate::ComponentBatch; + let green = &green as &dyn crate::ComponentBatch; + let blue = &blue as &dyn crate::ComponentBatch; + let got: Result, _> = (&[red, green, blue] as &dyn crate::AsComponents) + .as_component_batches() + .into_iter() + .map(|batch| batch.to_arrow()) + .collect(); + got? + }; + let expected = vec![ + Arc::new(ArrowPrimitiveArray::::from(vec![red.0])) as Arc, + Arc::new(ArrowPrimitiveArray::::from(vec![green.0])) as Arc, + Arc::new(ArrowPrimitiveArray::::from(vec![blue.0])) as Arc, + ]; + assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn single_componentbatch_wrapped_many() -> anyhow::Result<()> { + let (red, green, blue, _) = data(); + + // Nothing out of the ordinary here, a slice of components is indeed a batch. + let got = (&[red, green, blue] as &dyn crate::ComponentBatch).to_arrow()?; + let expected = Arc::new(ArrowPrimitiveArray::::from(vec![ + red.0, green.0, blue.0, + ])) as Arc; + similar_asserts::assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn many_componentbatch() -> anyhow::Result<()> { + let (red, green, blue, colors) = data(); + + // Nothing out of the ordinary here, a batch is indeed a batch. + let got = (&colors as &dyn crate::ComponentBatch).to_arrow()?; + let expected = Arc::new(ArrowPrimitiveArray::::from(vec![ + red.0, green.0, blue.0, + ])) as Arc; + similar_asserts::assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn many_ascomponents_wrapped_howto() -> anyhow::Result<()> { + let (red, green, blue, colors) = data(); + + let got = { + let colors = &colors as &dyn crate::ComponentBatch; + let got: Result, _> = (&[colors] as &dyn crate::AsComponents) + .as_component_batches() + .into_iter() + .map(|batch| batch.to_arrow()) + .collect(); + got? + }; + let expected = vec![Arc::new(ArrowPrimitiveArray::::from(vec![ + red.0, green.0, blue.0, + ])) as Arc]; + assert_eq!(&expected, &got); + + Ok(()) + } + + #[test] + fn many_ascomponents_wrapped_many_howto() -> anyhow::Result<()> { + let (red, green, blue, colors) = data(); + + // Nothing out of the ordinary here, a collection of batches is indeed a collection of batches. + let got = { + let colors = &colors as &dyn crate::ComponentBatch; + let got: Result, _> = (&[colors, colors, colors] as &dyn crate::AsComponents) + .as_component_batches() + .into_iter() + .map(|batch| batch.to_arrow()) + .collect(); + got? + }; + let expected = vec![ + Arc::new(ArrowPrimitiveArray::::from(vec![ + red.0, green.0, blue.0, + ])) as Arc, + Arc::new(ArrowPrimitiveArray::::from(vec![ + red.0, green.0, blue.0, + ])) as Arc, + Arc::new(ArrowPrimitiveArray::::from(vec![ + red.0, green.0, blue.0, + ])) as Arc, + ]; + assert_eq!(&expected, &got); + + Ok(()) + } +} diff --git a/crates/store/re_types_core/src/lib.rs b/crates/store/re_types_core/src/lib.rs index 356d086c4e0e..c631ebc35b65 100644 --- a/crates/store/re_types_core/src/lib.rs +++ b/crates/store/re_types_core/src/lib.rs @@ -23,251 +23,12 @@ /// Number of decimals shown for all float display methods. pub const DEFAULT_DISPLAY_DECIMALS: usize = 3; -/// Describes the interface for interpreting an object as a bundle of [`Component`]s. -/// -/// ## Custom bundles -/// -/// While, in most cases, component bundles are code generated from our [IDL definitions], -/// it is possible to manually extend existing bundles, or even implement fully custom ones. -/// -/// All [`AsComponents`] methods are optional to implement, with the exception of -/// [`AsComponents::as_component_batches`], which describes how the bundle can be interpreted -/// as a set of [`ComponentBatch`]es: arrays of components that are ready to be serialized. -/// -/// Have a look at our [Custom Data Loader] example to learn more about handwritten bundles. -/// -/// [IDL definitions]: https://github.com/rerun-io/rerun/tree/latest/crates/store/re_types/definitions/rerun -/// [Custom Data Loader]: https://github.com/rerun-io/rerun/blob/latest/examples/rust/custom_data_loader -pub trait AsComponents { - /// Exposes the object's contents as a set of [`ComponentBatch`]s. - /// - /// This is the main mechanism for easily extending builtin archetypes or even writing - /// fully custom ones. - /// Have a look at our [Custom Data Loader] example to learn more about extending archetypes. - /// - /// Implementers of [`AsComponents`] get one last chance to override the tags in the - /// [`ComponentDescriptor`], see [`ComponentBatchCowWithDescriptor::descriptor_override`]. - /// - /// [Custom Data Loader]: https://github.com/rerun-io/rerun/tree/latest/examples/rust/custom_data_loader - // - // NOTE: Don't bother returning a CoW here: we need to dynamically discard optional components - // depending on their presence (or lack thereof) at runtime anyway. - fn as_component_batches(&self) -> Vec>; - - // --- - - /// Serializes all non-null [`Component`]s of this bundle into Arrow arrays. - /// - /// The default implementation will simply serialize the result of [`Self::as_component_batches`] - /// as-is, which is what you want in 99.9% of cases. - #[inline] - fn to_arrow( - &self, - ) -> SerializationResult> { - self.as_component_batches() - .into_iter() - .map(|comp_batch| { - comp_batch - .to_arrow() - .map(|array| { - let field = arrow::datatypes::Field::new( - comp_batch.name().to_string(), - array.data_type().clone(), - false, - ); - (field, array) - }) - .with_context(comp_batch.name()) - }) - .collect() - } - - /// Serializes all non-null [`Component`]s of this bundle into Arrow2 arrays. - /// - /// The default implementation will simply serialize the result of [`Self::as_component_batches`] - /// as-is, which is what you want in 99.9% of cases. - #[inline] - fn to_arrow2( - &self, - ) -> SerializationResult)>> - { - self.as_component_batches() - .into_iter() - .map(|comp_batch| { - comp_batch - .to_arrow2() - .map(|array| { - let field = arrow2::datatypes::Field::new( - comp_batch.name().to_string(), - array.data_type().clone(), - false, - ); - (field, array) - }) - .with_context(comp_batch.name()) - }) - .collect() - } -} - -impl AsComponents for C { - #[inline] - fn as_component_batches(&self) -> Vec> { - vec![ComponentBatchCowWithDescriptor::new( - self as &dyn ComponentBatch, - )] - } -} - -impl AsComponents for dyn ComponentBatch { - #[inline] - fn as_component_batches(&self) -> Vec> { - vec![ComponentBatchCowWithDescriptor::new(self)] - } -} - -impl AsComponents for [&dyn ComponentBatch; N] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .map(|batch| ComponentBatchCowWithDescriptor::new(*batch)) - .collect() - } -} - -impl AsComponents for [Box; N] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .map(|batch| ComponentBatchCowWithDescriptor::new(&**batch)) - .collect() - } -} - -impl AsComponents for &[&dyn ComponentBatch] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .map(|batch| ComponentBatchCowWithDescriptor::new(*batch)) - .collect() - } -} - -impl AsComponents for &[Box] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .map(|batch| ComponentBatchCowWithDescriptor::new(&**batch)) - .collect() - } -} - -impl AsComponents for Vec<&dyn ComponentBatch> { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .map(|batch| ComponentBatchCowWithDescriptor::new(*batch)) - .collect() - } -} - -impl AsComponents for Vec> { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .map(|batch| ComponentBatchCowWithDescriptor::new(&**batch)) - .collect() - } -} - -impl AsComponents for [AS; N] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for [&dyn AsComponents; N] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for [Box; N] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for &[AS] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for &[&dyn AsComponents] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for &[Box] { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for Vec { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for Vec<&dyn AsComponents> { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -impl AsComponents for Vec> { - #[inline] - fn as_component_batches(&self) -> Vec> { - self.iter() - .flat_map(|as_components| as_components.as_component_batches()) - .collect() - } -} - -// --- - mod archetype; mod arrow_buffer; pub mod arrow_helpers; mod arrow_string; pub mod arrow_zip_validity; +mod as_components; mod component_descriptor; mod loggable; mod loggable_batch; @@ -283,6 +44,7 @@ pub use self::{ }, arrow_buffer::ArrowBuffer, arrow_string::ArrowString, + as_components::AsComponents, component_descriptor::ComponentDescriptor, loggable::{ Component, ComponentName, ComponentNameSet, DatatypeName, Loggable, diff --git a/crates/top/re_sdk/src/recording_stream.rs b/crates/top/re_sdk/src/recording_stream.rs index 7c6e38fff335..7551dc9cca40 100644 --- a/crates/top/re_sdk/src/recording_stream.rs +++ b/crates/top/re_sdk/src/recording_stream.rs @@ -2625,26 +2625,6 @@ mod tests { vec![row0, row1, row2] } - // See for context. - #[test] - fn allows_ascomponents_unsized() { - let labels = [ - MyLabel("a".into()), - MyLabel("b".into()), - MyLabel("c".into()), - ]; - - let (rec, _mem) = RecordingStreamBuilder::new("rerun_example_test_ascomponents_unsized") - .default_enabled(false) - .enabled(false) - .memory() - .unwrap(); - - // This call used to *not* compile due to a lack of `?Sized` bounds. - rec.log("labels", &labels as &dyn crate::AsComponents) - .unwrap(); - } - // See for context. #[test] fn allows_componentbatch_unsized() { diff --git a/docs/snippets/all/archetypes/mesh3d_partial_updates.rs b/docs/snippets/all/archetypes/mesh3d_partial_updates.rs index 791428f62e52..f3d2533b886a 100644 --- a/docs/snippets/all/archetypes/mesh3d_partial_updates.rs +++ b/docs/snippets/all/archetypes/mesh3d_partial_updates.rs @@ -26,7 +26,7 @@ fn main() -> Result<(), Box> { (glam::Vec3::from(vertex_positions[1]) * factor).into(), (glam::Vec3::from(vertex_positions[2]) * factor).into(), ]; - rec.log("triangle", &vertex_positions)?; + rec.log("triangle", &vertex_positions as &dyn rerun::ComponentBatch)?; } Ok(())