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 //! # Basic typesystem for defining a component interface.
7 //! This module provides the "API-level" typesystem of a UniFFI Rust Component, that is,
8 //! the types provided by the Rust implementation and consumed callers of the foreign language
9 //! bindings. Think "objects" and "enums" and "records".
11 //! The [`Type`] enum represents high-level types that would appear in the public API of
12 //! a component, such as enums and records as well as primitives like ints and strings.
13 //! The Rust code that implements a component, and the foreign language bindings that consume it,
14 //! will both typically deal with such types as their core concern.
16 //! As a developer working on UniFFI itself, you're likely to spend a fair bit of time thinking
17 //! about how these API-level types map into the lower-level types of the FFI layer as represented
18 //! by the [`ffi::FfiType`](super::ffi::FfiType) enum, but that's a detail that is invisible to end users.
22 #[derive(Debug, Copy, Clone, Eq, PartialEq, Checksum, Ord, PartialOrd)]
29 /// Return the fully qualified name which should be used by Rust code for
30 /// an object with the given name.
31 /// Includes `r#`, traits get a leading `dyn`. If we ever supported associated types, then
32 /// this would also include them.
33 pub fn rust_name_for(&self, name: &str) -> String {
34 if self == &ObjectImpl::Trait {
35 format!("dyn r#{name}")
41 // uniffi_meta and procmacro support tend to carry around `is_trait` bools. This makes that
42 // mildly less painful
43 pub fn from_is_trait(is_trait: bool) -> Self {
52 #[derive(Debug, Clone, Copy, Eq, PartialEq, Checksum, Ord, PartialOrd)]
53 pub enum ExternalKind {
55 // Either a record or enum
59 /// Represents all the different high-level types that can be used in a component interface.
60 /// At this level we identify user-defined types by name, without knowing any details
61 /// of their internal structure apart from what type of thing they are (record, enum, etc).
62 #[derive(Debug, Clone, Eq, PartialEq, Checksum, Ord, PartialOrd)]
81 // The module path to the object
83 // The name in the "type universe"
85 // How the object is implemented.
89 // Types defined in the component API, each of which has a string name.
102 // Structurally recursive types.
104 inner_type: Box<Type>,
107 inner_type: Box<Type>,
111 value_type: Box<Type>,
113 // An FfiConverter we `use` from an external crate
117 #[checksum_ignore] // The namespace is not known generating scaffolding.
120 tagged: bool, // does its FfiConverter use <UniFFITag>?
122 // Custom type on the scaffolding side
131 pub fn iter_types(&self) -> TypeIterator<'_> {
132 let nested_types = match self {
133 Type::Optional { inner_type } | Type::Sequence { inner_type } => {
134 inner_type.iter_types()
139 } => Box::new(key_type.iter_types().chain(value_type.iter_types())),
140 _ => Box::new(std::iter::empty()),
142 Box::new(std::iter::once(self).chain(nested_types))
146 // A trait so various things can turn into a type.
147 pub trait AsType: core::fmt::Debug {
148 fn as_type(&self) -> Type;
151 impl AsType for Type {
152 fn as_type(&self) -> Type {
157 // Needed to handle &&Type and &&&Type values, which we sometimes end up with in the template code
158 impl<T, C> AsType for T
160 T: std::ops::Deref<Target = C> + std::fmt::Debug,
163 fn as_type(&self) -> Type {
164 self.deref().as_type()
168 /// An abstract type for an iterator over &Type references.
170 /// Ideally we would not need to name this type explicitly, and could just
171 /// use an `impl Iterator<Item = &Type>` on any method that yields types.
172 pub type TypeIterator<'a> = Box<dyn Iterator<Item = &'a Type> + 'a>;