Backed out 5 changesets (bug 1890092, bug 1888683) for causing build bustages & crash...
[gecko.git] / third_party / rust / uniffi_bindgen / src / macro_metadata / ci.rs
blob7ce6c3a70ba8e707f4ad89e170c917d2d0e0199e
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 use crate::interface::{CallbackInterface, ComponentInterface, Enum, Record, Type};
6 use anyhow::{bail, Context};
7 use uniffi_meta::{
8     create_metadata_groups, group_metadata, EnumMetadata, ErrorMetadata, Metadata, MetadataGroup,
9 };
11 /// Add Metadata items to the ComponentInterface
12 ///
13 /// This function exists to support the transition period where the `uniffi::export` macro can only
14 /// handle some components.  This means that crates need to continue using UDL files to define the
15 /// parts of the components that aren't supported yet.
16 ///
17 /// To make things work, we generate a `ComponentInterface` from the UDL file, then combine it with
18 /// the `Metadata` items that the macro creates.
19 pub fn add_to_ci(
20     iface: &mut ComponentInterface,
21     metadata_items: Vec<Metadata>,
22 ) -> anyhow::Result<()> {
23     let mut group_map = create_metadata_groups(&metadata_items);
24     group_metadata(&mut group_map, metadata_items)?;
25     for group in group_map.into_values() {
26         if group.items.is_empty() {
27             continue;
28         }
29         if group.namespace.name != iface.namespace() {
30             let crate_name = group.namespace.crate_name;
31             bail!("Found metadata items from crate `{crate_name}`.  Use the `--library` to generate bindings for multiple crates")
32         }
33         add_group_to_ci(iface, group)?;
34     }
36     Ok(())
39 /// Add items from a MetadataGroup to a component interface
40 pub fn add_group_to_ci(iface: &mut ComponentInterface, group: MetadataGroup) -> anyhow::Result<()> {
41     if group.namespace.name != iface.namespace() {
42         bail!(
43             "Namespace mismatch: {} - {}",
44             group.namespace.name,
45             iface.namespace()
46         );
47     }
49     for item in group.items {
50         add_item_to_ci(iface, item)?
51     }
53     iface
54         .derive_ffi_funcs()
55         .context("Failed to derive FFI functions")?;
56     iface
57         .check_consistency()
58         .context("ComponentInterface consistency error")?;
59     Ok(())
62 fn add_enum_to_ci(
63     iface: &mut ComponentInterface,
64     meta: EnumMetadata,
65     is_flat: bool,
66 ) -> anyhow::Result<()> {
67     let ty = Type::Enum {
68         name: meta.name.clone(),
69         module_path: meta.module_path.clone(),
70     };
71     iface.types.add_known_type(&ty)?;
73     let enum_ = Enum::try_from_meta(meta, is_flat)?;
74     iface.add_enum_definition(enum_)?;
75     Ok(())
78 fn add_item_to_ci(iface: &mut ComponentInterface, item: Metadata) -> anyhow::Result<()> {
79     match item {
80         Metadata::Namespace(_) => unreachable!(),
81         Metadata::UdlFile(_) => (),
82         Metadata::Func(meta) => {
83             iface.add_function_definition(meta.into())?;
84         }
85         Metadata::Constructor(meta) => {
86             iface.add_constructor_meta(meta)?;
87         }
88         Metadata::Method(meta) => {
89             iface.add_method_meta(meta)?;
90         }
91         Metadata::Record(meta) => {
92             let ty = Type::Record {
93                 name: meta.name.clone(),
94                 module_path: meta.module_path.clone(),
95             };
96             iface.types.add_known_type(&ty)?;
97             let record: Record = meta.try_into()?;
98             iface.add_record_definition(record)?;
99         }
100         Metadata::Enum(meta) => {
101             let flat = meta.variants.iter().all(|v| v.fields.is_empty());
102             add_enum_to_ci(iface, meta, flat)?;
103         }
104         Metadata::Object(meta) => {
105             iface.types.add_known_type(&Type::Object {
106                 module_path: meta.module_path.clone(),
107                 name: meta.name.clone(),
108                 imp: meta.imp,
109             })?;
110             iface.add_object_meta(meta)?;
111         }
112         Metadata::UniffiTrait(meta) => {
113             iface.add_uniffitrait_meta(meta)?;
114         }
115         Metadata::CallbackInterface(meta) => {
116             iface.types.add_known_type(&Type::CallbackInterface {
117                 module_path: meta.module_path.clone(),
118                 name: meta.name.clone(),
119             })?;
120             iface.add_callback_interface_definition(CallbackInterface::new(
121                 meta.name,
122                 meta.module_path,
123             ));
124         }
125         Metadata::TraitMethod(meta) => {
126             iface.add_trait_method_meta(meta)?;
127         }
128         Metadata::Error(meta) => {
129             iface.note_name_used_as_error(meta.name());
130             match meta {
131                 ErrorMetadata::Enum { enum_, is_flat } => {
132                     add_enum_to_ci(iface, enum_, is_flat)?;
133                 }
134             };
135         }
136         Metadata::CustomType(meta) => {
137             iface.types.add_known_type(&Type::Custom {
138                 module_path: meta.module_path.clone(),
139                 name: meta.name,
140                 builtin: Box::new(meta.builtin),
141             })?;
142         }
143     }
144     Ok(())