summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs')
-rw-r--r--third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs109
1 files changed, 109 insertions, 0 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs b/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs
new file mode 100644
index 0000000000..f3759cf6fa
--- /dev/null
+++ b/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs
@@ -0,0 +1,109 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use anyhow::Result;
+use askama::Template;
+use std::borrow::Borrow;
+
+use super::interface::*;
+use heck::{ToShoutySnakeCase, ToSnakeCase};
+
+#[derive(Template)]
+#[template(syntax = "rs", escape = "none", path = "scaffolding_template.rs")]
+pub struct RustScaffolding<'a> {
+ ci: &'a ComponentInterface,
+ udl_base_name: &'a str,
+}
+impl<'a> RustScaffolding<'a> {
+ pub fn new(ci: &'a ComponentInterface, udl_base_name: &'a str) -> Self {
+ Self { ci, udl_base_name }
+ }
+}
+mod filters {
+ use super::*;
+
+ pub fn type_rs(type_: &Type) -> Result<String, askama::Error> {
+ Ok(match type_ {
+ Type::Int8 => "i8".into(),
+ Type::UInt8 => "u8".into(),
+ Type::Int16 => "i16".into(),
+ Type::UInt16 => "u16".into(),
+ Type::Int32 => "i32".into(),
+ Type::UInt32 => "u32".into(),
+ Type::Int64 => "i64".into(),
+ Type::UInt64 => "u64".into(),
+ Type::Float32 => "f32".into(),
+ Type::Float64 => "f64".into(),
+ Type::Boolean => "bool".into(),
+ Type::String => "String".into(),
+ Type::Bytes => "Vec<u8>".into(),
+ Type::Timestamp => "std::time::SystemTime".into(),
+ Type::Duration => "std::time::Duration".into(),
+ Type::Enum { name, .. } | Type::Record { name, .. } => format!("r#{name}"),
+ Type::Object { name, imp, .. } => {
+ format!("std::sync::Arc<{}>", imp.rust_name_for(name))
+ }
+ Type::CallbackInterface { name, .. } => format!("Box<dyn r#{name}>"),
+ Type::ForeignExecutor => "::uniffi::ForeignExecutor".into(),
+ Type::Optional { inner_type } => {
+ format!("std::option::Option<{}>", type_rs(inner_type)?)
+ }
+ Type::Sequence { inner_type } => format!("std::vec::Vec<{}>", type_rs(inner_type)?),
+ Type::Map {
+ key_type,
+ value_type,
+ } => format!(
+ "std::collections::HashMap<{}, {}>",
+ type_rs(key_type)?,
+ type_rs(value_type)?
+ ),
+ Type::Custom { name, .. } => format!("r#{name}"),
+ Type::External {
+ name,
+ kind: ExternalKind::Interface,
+ ..
+ } => format!("::std::sync::Arc<r#{name}>"),
+ Type::External { name, .. } => format!("r#{name}"),
+ })
+ }
+
+ // Map a type to Rust code that specifies the FfiConverter implementation.
+ //
+ // This outputs something like `<MyStruct as Lift<crate::UniFfiTag>>`
+ pub fn ffi_trait(type_: &Type, trait_name: &str) -> Result<String, askama::Error> {
+ Ok(match type_ {
+ Type::External {
+ name,
+ kind: ExternalKind::Interface,
+ ..
+ } => {
+ format!("<::std::sync::Arc<r#{name}> as ::uniffi::{trait_name}<crate::UniFfiTag>>")
+ }
+ _ => format!(
+ "<{} as ::uniffi::{trait_name}<crate::UniFfiTag>>",
+ type_rs(type_)?
+ ),
+ })
+ }
+
+ pub fn return_type<T: Callable>(callable: &T) -> Result<String, askama::Error> {
+ let return_type = match callable.return_type() {
+ Some(t) => type_rs(&t)?,
+ None => "()".to_string(),
+ };
+ match callable.throws_type() {
+ Some(t) => type_rs(&t)?,
+ None => "()".to_string(),
+ };
+ Ok(match callable.throws_type() {
+ Some(e) => format!("::std::result::Result<{return_type}, {}>", type_rs(&e)?),
+ None => return_type,
+ })
+ }
+
+ // Turns a `crate-name` into the `crate_name` the .rs code needs to specify.
+ pub fn crate_name_rs(nm: &str) -> Result<String, askama::Error> {
+ Ok(format!("r#{}", nm.to_string().to_snake_case()))
+ }
+}