Skip to content

Commit

Permalink
Autogenerate tagging-compliant descriptor methods for all archetypes (#…
Browse files Browse the repository at this point in the history
…8643)

Generate methods for all archetypes that allow retrieving the
fully-qualified descriptor for any of the archetype's field.
E.g. this method returns the descriptor for the `radii` field of
`Points3D`:
```rust
impl Points3D {
    /// Returns the [`ComponentDescriptor`] for [`Self::radii`].
    #[inline]
    pub fn descriptor_radii() -> ComponentDescriptor {
        ComponentDescriptor {
            archetype_name: Some("rerun.archetypes.Points3D".into()),
            component_name: "rerun.components.Radius".into(),
            archetype_field_name: Some("radii".into()),
        }
    }
}
```

This becomes a must as we start require tags in more and more places
(e.g. partial updates APIs).

* DNM: requires #8642 
* Part of #8581
  • Loading branch information
teh-cmc authored Jan 13, 2025
1 parent c171b04 commit c80d847
Show file tree
Hide file tree
Showing 63 changed files with 4,796 additions and 5,329 deletions.
89 changes: 62 additions & 27 deletions crates/build/re_types_builder/src/codegen/rust/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,6 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream {
assert_eq!(kind, &ObjectKind::Archetype);

let display_name = re_case::to_human_case(name);
let archetype_name = &obj.fqname;
let name = format_ident!("{name}");

fn compute_component_descriptors(
Expand All @@ -1056,18 +1055,11 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream {
field
.try_get_attr::<String>(requirement_attr_value)
.map(|_| {
let Some(component_name) = field.typ.fqname() else {
panic!("Archetype field must be an object/union or an array/vector of such")
};

let archetype_name = &obj.fqname;
let archetype_name = format_ident!("{}", obj.name);
let archetype_field_name = field.snake_case_name();
let fn_name = format_ident!("descriptor_{archetype_field_name}");

quote!(ComponentDescriptor {
archetype_name: Some(#archetype_name.into()),
component_name: #component_name.into(),
archetype_field_name: Some(#archetype_field_name.into()),
})
quote!(#archetype_name::#fn_name())
})
})
.collect_vec();
Expand All @@ -1078,13 +1070,63 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream {
(num_descriptors, quoted_descriptors)
}

let all_descriptor_methods = obj
.fields
.iter()
.map(|field| {
let Some(component_name) = field.typ.fqname() else {
panic!("Archetype field must be an object/union or an array/vector of such")
};

let archetype_name = &obj.fqname;
let archetype_field_name = field.snake_case_name();

let doc = format!(
"Returns the [`ComponentDescriptor`] for [`Self::{archetype_field_name}`]."
);
let fn_name = format_ident!("descriptor_{archetype_field_name}");

quote! {
#[doc = #doc]
#[inline]
pub fn #fn_name() -> ComponentDescriptor {
ComponentDescriptor {
archetype_name: Some(#archetype_name.into()),
component_name: #component_name.into(),
archetype_field_name: Some(#archetype_field_name.into()),
}
}
}
})
.chain(std::iter::once({
let archetype_name = &obj.fqname;
let indicator_component_name = format!(
"{}Indicator",
obj.fqname.replace("archetypes", "components")
);

let doc = "Returns the [`ComponentDescriptor`] for the associated indicator component.";

quote! {
#[doc = #doc]
#[inline]
pub fn descriptor_indicator() -> ComponentDescriptor {
ComponentDescriptor {
archetype_name: Some(#archetype_name.into()),
component_name: #indicator_component_name.into(),
archetype_field_name: None,
}
}
}
}))
.collect_vec();

let archetype_name = format_ident!("{}", obj.name);
let indicator_name = format!("{}Indicator", obj.name);

let quoted_indicator_name = format_ident!("{indicator_name}");
let quoted_indicator_doc =
format!("Indicator component for the [`{name}`] [`::re_types_core::Archetype`]");
let indicator_component_name =
format!("{}Indicator", fqname.replace("archetypes", "components"));

let (num_required_descriptors, required_descriptors) =
compute_component_descriptors(obj, ATTR_RERUN_COMPONENT_REQUIRED);
Expand All @@ -1096,11 +1138,7 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream {
num_recommended_descriptors += 1;
recommended_descriptors = quote! {
#recommended_descriptors
ComponentDescriptor {
archetype_name: Some(#archetype_name.into()),
component_name: #indicator_component_name.into(),
archetype_field_name: None,
},
#archetype_name::descriptor_indicator(),
};

let num_components_docstring = quote_doc_line(&format!(
Expand Down Expand Up @@ -1160,21 +1198,14 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream {
quote!{ Some(&self.#field_name as &dyn ComponentBatch) }
};

let Some(component_name) = obj_field.typ.fqname() else {
panic!("Archetype field must be an object/union or an array/vector of such")
};
let archetype_name = &obj.fqname;
let archetype_field_name = obj_field.snake_case_name();
let descr_fn_name = format_ident!("descriptor_{archetype_field_name}");

quote! {
(#batch).map(|batch| {
::re_types_core::ComponentBatchCowWithDescriptor {
batch: batch.into(),
descriptor_override: Some(ComponentDescriptor {
archetype_name: Some(#archetype_name.into()),
archetype_field_name: Some((#archetype_field_name).into()),
component_name: (#component_name).into(),
}),
descriptor_override: Some(Self::#descr_fn_name()),
}
})

Expand Down Expand Up @@ -1261,6 +1292,10 @@ fn quote_trait_impls_for_archetype(obj: &Object) -> TokenStream {
};

quote! {
impl #name {
#(#all_descriptor_methods)*
}

static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; #num_required_descriptors]> =
once_cell::sync::Lazy::new(|| {[#required_descriptors]});

Expand Down
48 changes: 23 additions & 25 deletions crates/store/re_types/src/archetypes/annotation_context.rs

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

Loading

0 comments on commit c80d847

Please sign in to comment.