Skip to content

Commit

Permalink
Automatically generate partial update APIs for eager archetypes (#8647)
Browse files Browse the repository at this point in the history
This extends the codegen of the `attr.rust.archetype_eager` attribute so
that it automatically generates partial updates APIs for all eager
archetypes.

* DNM: requires #8646 
* Part of #8581
  • Loading branch information
teh-cmc authored Jan 13, 2025
1 parent 9f73860 commit 1b9e510
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 3 deletions.
53 changes: 51 additions & 2 deletions crates/build/re_types_builder/src/codegen/rust/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}");
Expand Down Expand Up @@ -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)*)
};
Expand Down
54 changes: 53 additions & 1 deletion crates/store/re_types/src/archetypes/points3d.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions crates/store/re_types_core/src/loggable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down

0 comments on commit 1b9e510

Please sign in to comment.