Backed out 5 changesets (bug 1890092, bug 1888683) for causing build bustages & crash...
[gecko.git] / third_party / rust / uniffi_bindgen / src / interface / universe.rs
blobe69d86e44faf3c024001bba7ced9465fac7da897
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 //! The set of all [`Type`]s used in a component interface is represented by a `TypeUniverse`,
6 //! which can be used by the bindings generator code to determine what type-related helper
7 //! functions to emit for a given component.
8 //!
9 use anyhow::Result;
10 use std::{collections::hash_map::Entry, collections::BTreeSet, collections::HashMap};
12 pub use uniffi_meta::{AsType, ExternalKind, NamespaceMetadata, ObjectImpl, Type, TypeIterator};
14 /// The set of all possible types used in a particular component interface.
15 ///
16 /// Every component API uses a finite number of types, including primitive types, API-defined
17 /// types like records and enums, and recursive types such as sequences of the above. Our
18 /// component API doesn't support fancy generics so this is a finitely-enumerable set, which
19 /// is useful to be able to operate on explicitly.
20 ///
21 /// You could imagine this struct doing some clever interning of names and so-on in future,
22 /// to reduce the overhead of passing around [Type] instances. For now we just do a whole
23 /// lot of cloning.
24 #[derive(Debug, Default)]
25 pub(crate) struct TypeUniverse {
26     /// The unique prefixes that we'll use for namespacing when exposing this component's API.
27     pub namespace: NamespaceMetadata,
29     // Named type definitions (including aliases).
30     type_definitions: HashMap<String, Type>,
31     // All the types in the universe, by canonical type name, in a well-defined order.
32     all_known_types: BTreeSet<Type>,
35 impl TypeUniverse {
36     pub fn new(namespace: NamespaceMetadata) -> Self {
37         Self {
38             namespace,
39             ..Default::default()
40         }
41     }
43     /// Add the definition of a named [Type].
44     fn add_type_definition(&mut self, name: &str, type_: &Type) -> Result<()> {
45         match self.type_definitions.entry(name.to_string()) {
46             Entry::Occupied(o) => {
47                 // all conflicts have been resolved by now in udl.
48                 // I doubt procmacros could cause this?
49                 assert_eq!(type_, o.get());
50                 Ok(())
51             }
52             Entry::Vacant(e) => {
53                 e.insert(type_.clone());
54                 Ok(())
55             }
56         }
57     }
59     /// Get the [Type] corresponding to a given name, if any.
60     pub(super) fn get_type_definition(&self, name: &str) -> Option<Type> {
61         self.type_definitions.get(name).cloned()
62     }
64     /// Add a [Type] to the set of all types seen in the component interface.
65     pub fn add_known_type(&mut self, type_: &Type) -> Result<()> {
66         // Types are more likely to already be known than not, so avoid unnecessary cloning.
67         if !self.all_known_types.contains(type_) {
68             self.all_known_types.insert(type_.to_owned());
69         }
70         match type_ {
71             Type::UInt8 => self.add_type_definition("u8", type_)?,
72             Type::Int8 => self.add_type_definition("i8", type_)?,
73             Type::UInt16 => self.add_type_definition("u16", type_)?,
74             Type::Int16 => self.add_type_definition("i16", type_)?,
75             Type::UInt32 => self.add_type_definition("i32", type_)?,
76             Type::Int32 => self.add_type_definition("u32", type_)?,
77             Type::UInt64 => self.add_type_definition("u64", type_)?,
78             Type::Int64 => self.add_type_definition("i64", type_)?,
79             Type::Float32 => self.add_type_definition("f32", type_)?,
80             Type::Float64 => self.add_type_definition("f64", type_)?,
81             Type::Boolean => self.add_type_definition("bool", type_)?,
82             Type::String => self.add_type_definition("string", type_)?,
83             Type::Bytes => self.add_type_definition("bytes", type_)?,
84             Type::Timestamp => self.add_type_definition("timestamp", type_)?,
85             Type::Duration => self.add_type_definition("duration", type_)?,
86             Type::ForeignExecutor => {
87                 self.add_type_definition("ForeignExecutor", type_)?;
88             }
89             Type::Object { name, .. }
90             | Type::Record { name, .. }
91             | Type::Enum { name, .. }
92             | Type::CallbackInterface { name, .. }
93             | Type::External { name, .. } => self.add_type_definition(name, type_)?,
94             Type::Custom { name, builtin, .. } => {
95                 self.add_type_definition(name, type_)?;
96                 self.add_known_type(builtin)?;
97             }
98             // Structurally recursive types.
99             Type::Optional { inner_type, .. } | Type::Sequence { inner_type, .. } => {
100                 self.add_known_type(inner_type)?;
101             }
102             Type::Map {
103                 key_type,
104                 value_type,
105             } => {
106                 self.add_known_type(key_type)?;
107                 self.add_known_type(value_type)?;
108             }
109         }
110         Ok(())
111     }
113     /// Add many [`Type`]s...
114     pub fn add_known_types(&mut self, types: TypeIterator<'_>) -> Result<()> {
115         for t in types {
116             self.add_known_type(t)?
117         }
118         Ok(())
119     }
121     /// Check if a [Type] is present
122     pub fn contains(&self, type_: &Type) -> bool {
123         self.all_known_types.contains(type_)
124     }
126     /// Iterator over all the known types in this universe.
127     pub fn iter_known_types(&self) -> impl Iterator<Item = &Type> {
128         self.all_known_types.iter()
129     }
132 #[cfg(test)]
133 mod test_type_universe {
134     // All the useful functionality of the `TypeUniverse` struct
135     // is tested as part of the `TypeFinder` and `TypeResolver` test suites.