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.
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.
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.
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
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>,
36 pub fn new(namespace: NamespaceMetadata) -> Self {
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());
53 e.insert(type_.clone());
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()
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());
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_)?;
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)?;
98 // Structurally recursive types.
99 Type::Optional { inner_type, .. } | Type::Sequence { inner_type, .. } => {
100 self.add_known_type(inner_type)?;
106 self.add_known_type(key_type)?;
107 self.add_known_type(value_type)?;
113 /// Add many [`Type`]s...
114 pub fn add_known_types(&mut self, types: TypeIterator<'_>) -> Result<()> {
116 self.add_known_type(t)?
121 /// Check if a [Type] is present
122 pub fn contains(&self, type_: &Type) -> bool {
123 self.all_known_types.contains(type_)
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()
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.