diff --git a/crates/build/re_types_builder/src/codegen/rust/api.rs b/crates/build/re_types_builder/src/codegen/rust/api.rs
index 2880f8c00077..c80138f4810e 100644
--- a/crates/build/re_types_builder/src/codegen/rust/api.rs
+++ b/crates/build/re_types_builder/src/codegen/rust/api.rs
@@ -284,6 +284,15 @@ fn quote_struct(
let quoted_repr_clause = quote_meta_clause_from_obj(obj, ATTR_RUST_REPR, "repr");
let quoted_custom_clause = quote_meta_clause_from_obj(obj, ATTR_RUST_CUSTOM_CLAUSE, "");
+ // Eager archetypes must always derive Default.
+ let quoted_eager_derive_default_clause = (obj.is_eager_rust_archetype()
+ && !quoted_derive_clause.to_string().contains("Default"))
+ .then(|| {
+ quote! {
+ #[derive(Default)]
+ }
+ });
+
let quoted_fields = fields
.iter()
.map(|obj_field| ObjectFieldTokenizer(reporter, obj, obj_field).quoted(objects));
@@ -353,6 +362,7 @@ fn quote_struct(
#quoted_doc
#quoted_derive_clone_debug
#quoted_derive_clause
+ #quoted_eager_derive_default_clause
#quoted_repr_clause
#quoted_custom_clause
#quoted_deprecation_notice
@@ -1731,7 +1741,7 @@ fn quote_builder_from_obj(reporter: &Reporter, objects: &Objects, obj: &Object)
}
});
- let eager_with_methods = optional.iter().map(|field| {
+ let eager_with_methods = required.iter().chain(optional.iter()).map(|field| {
// fn with_*()
let field_name = format_ident!("{}", field.name);
let descr_fn_name = format_ident!("descriptor_{field_name}");
@@ -1760,8 +1770,47 @@ fn quote_builder_from_obj(reporter: &Reporter, objects: &Objects, obj: &Object)
}
});
+ let partial_update_methods = obj.is_eager_rust_archetype().then(|| {
+ let update_fields_doc =
+ quote_doc_line(&format!("Update only some specific fields of a `{name}`."));
+ let clear_fields_doc = quote_doc_line(&format!("Clear all the fields of a `{name}`."));
+
+ let fields = required.iter().chain(optional.iter()).map(|field| {
+ let field_name = format_ident!("{}", field.name);
+ let descr_fn_name = format_ident!("descriptor_{field_name}");
+ let (typ, _) = quote_field_type_from_typ(&field.typ, true);
+ quote! {
+ #field_name: Some(SerializedComponentBatch::new(
+ #typ::arrow_empty(),
+ Self::#descr_fn_name(),
+ ))
+ }
+ });
+
+ quote! {
+ #update_fields_doc
+ #[inline]
+ pub fn update_fields() -> Self {
+ Self::default()
+ }
+
+ #clear_fields_doc
+ #[inline]
+ pub fn clear_fields() -> Self {
+ use ::re_types_core::Loggable as _;
+ Self {
+ #(#fields),*
+ }
+ }
+ }
+ });
+
let with_methods = if obj.is_eager_rust_archetype() {
- quote!(#(#eager_with_methods)*)
+ quote! {
+ #partial_update_methods
+
+ #(#eager_with_methods)*
+ }
} else {
quote!(#(#native_with_methods)*)
};
diff --git a/crates/store/re_types/src/archetypes/points3d.rs b/crates/store/re_types/src/archetypes/points3d.rs
index cd9ed1edb7b2..c540dcdc24a6 100644
--- a/crates/store/re_types/src/archetypes/points3d.rs
+++ b/crates/store/re_types/src/archetypes/points3d.rs
@@ -94,7 +94,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult};
///
///
///
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Default)]
pub struct Points3D {
/// All the 3D positions at which the point cloud shows points.
pub positions: Option,
@@ -382,6 +382,58 @@ impl Points3D {
}
}
+ /// Update only some specific fields of a `Points3D`.
+ #[inline]
+ pub fn update_fields() -> Self {
+ Self::default()
+ }
+
+ /// Clear all the fields of a `Points3D`.
+ #[inline]
+ pub fn clear_fields() -> Self {
+ use ::re_types_core::Loggable as _;
+ Self {
+ positions: Some(SerializedComponentBatch::new(
+ crate::components::Position3D::arrow_empty(),
+ Self::descriptor_positions(),
+ )),
+ radii: Some(SerializedComponentBatch::new(
+ crate::components::Radius::arrow_empty(),
+ Self::descriptor_radii(),
+ )),
+ colors: Some(SerializedComponentBatch::new(
+ crate::components::Color::arrow_empty(),
+ Self::descriptor_colors(),
+ )),
+ labels: Some(SerializedComponentBatch::new(
+ crate::components::Text::arrow_empty(),
+ Self::descriptor_labels(),
+ )),
+ show_labels: Some(SerializedComponentBatch::new(
+ crate::components::ShowLabels::arrow_empty(),
+ Self::descriptor_show_labels(),
+ )),
+ class_ids: Some(SerializedComponentBatch::new(
+ crate::components::ClassId::arrow_empty(),
+ Self::descriptor_class_ids(),
+ )),
+ keypoint_ids: Some(SerializedComponentBatch::new(
+ crate::components::KeypointId::arrow_empty(),
+ Self::descriptor_keypoint_ids(),
+ )),
+ }
+ }
+
+ /// All the 3D positions at which the point cloud shows points.
+ #[inline]
+ pub fn with_positions(
+ mut self,
+ positions: impl IntoIterator- >,
+ ) -> Self {
+ self.positions = try_serialize_field(Self::descriptor_positions(), positions);
+ self
+ }
+
/// Optional radii for the points, effectively turning them into circles.
#[inline]
pub fn with_radii(
diff --git a/crates/store/re_types_core/src/loggable.rs b/crates/store/re_types_core/src/loggable.rs
index 0be4bdcc9bf2..dab5fa39086d 100644
--- a/crates/store/re_types_core/src/loggable.rs
+++ b/crates/store/re_types_core/src/loggable.rs
@@ -25,6 +25,12 @@ pub trait Loggable: 'static + Send + Sync + Clone + Sized + SizeBytes {
/// The underlying [`arrow::datatypes::DataType`], excluding datatype extensions.
fn arrow_datatype() -> arrow::datatypes::DataType;
+ // Returns an empty Arrow array that matches this `Loggable`'s underlying datatype.
+ #[inline]
+ fn arrow_empty() -> arrow::array::ArrayRef {
+ arrow::array::new_empty_array(&Self::arrow_datatype())
+ }
+
/// Given an iterator of owned or reference values to the current [`Loggable`], serializes
/// them into an Arrow array.
///