forked from mozilla/uniffi-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unit of code: Swift backend (mozilla#1042)
* Swift backend written in rust, builds with cargo build * Generated swift bindings compile and all tests pass * Tidy read and writes and compounds * Tidy up miscellaneous and object types * Tidy up primitive types templates * Tidy up unimplemented callback interfaces * Tidy up enums * Remove dead code * cargo fmt * Tidy error types * Rebase after landing kotlin PR * Make RustBufferHelper.swift like RustBufferHelper.kt
- Loading branch information
Showing
24 changed files
with
1,646 additions
and
684 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
121 changes: 121 additions & 0 deletions
121
uniffi_bindgen/src/bindings/swift/gen_swift/callback_interface.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/* 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 std::fmt; | ||
|
||
use crate::bindings::backend::{CodeDeclaration, CodeOracle, CodeType, Literal}; | ||
use crate::interface::{CallbackInterface, ComponentInterface}; | ||
use askama::Template; | ||
|
||
#[allow(unused_imports)] | ||
use super::filters; | ||
pub struct CallbackInterfaceCodeType { | ||
id: String, | ||
} | ||
|
||
impl CallbackInterfaceCodeType { | ||
pub fn new(_id: String) -> Self { | ||
unimplemented!("Callbacks are not supported in Swift yet") | ||
} | ||
} | ||
|
||
impl CodeType for CallbackInterfaceCodeType { | ||
fn type_label(&self, oracle: &dyn CodeOracle) -> String { | ||
oracle.class_name(&self.id) | ||
} | ||
|
||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String { | ||
format!("CallbackInterface{}", self.type_label(oracle)) | ||
} | ||
|
||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String { | ||
unreachable!(); | ||
} | ||
|
||
fn lower(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lower()", oracle.var_name(nm)) | ||
} | ||
|
||
fn write( | ||
&self, | ||
oracle: &dyn CodeOracle, | ||
nm: &dyn fmt::Display, | ||
target: &dyn fmt::Display, | ||
) -> String { | ||
format!("{}.write(into: {})", oracle.var_name(nm), target) | ||
} | ||
|
||
fn lift(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lift({})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn read(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.read(from: {})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> { | ||
None | ||
} | ||
} | ||
|
||
#[derive(Template)] | ||
#[template( | ||
syntax = "swift", | ||
escape = "none", | ||
path = "CallbackInterfaceTemplate.swift" | ||
)] | ||
pub struct SwiftCallbackInterface { | ||
inner: CallbackInterface, | ||
} | ||
|
||
impl SwiftCallbackInterface { | ||
pub fn new(inner: CallbackInterface, _ci: &ComponentInterface) -> Self { | ||
Self { inner } | ||
} | ||
pub fn inner(&self) -> &CallbackInterface { | ||
&self.inner | ||
} | ||
} | ||
|
||
impl CodeDeclaration for SwiftCallbackInterface { | ||
fn initialization_code(&self, _oracle: &dyn CodeOracle) -> Option<String> { | ||
None | ||
} | ||
|
||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> { | ||
Some(self.render().unwrap()) | ||
} | ||
|
||
fn imports(&self, _oracle: &dyn CodeOracle) -> Option<Vec<String>> { | ||
None | ||
} | ||
} | ||
|
||
#[derive(Template)] | ||
#[template( | ||
syntax = "swift", | ||
escape = "none", | ||
path = "CallbackInterfaceRuntime.swift" | ||
)] | ||
pub struct SwiftCallbackInterfaceRuntime { | ||
is_needed: bool, | ||
} | ||
|
||
impl SwiftCallbackInterfaceRuntime { | ||
pub fn new(ci: &ComponentInterface) -> Self { | ||
Self { | ||
is_needed: !ci.iter_callback_interface_definitions().is_empty(), | ||
} | ||
} | ||
} | ||
|
||
impl CodeDeclaration for SwiftCallbackInterfaceRuntime { | ||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> { | ||
if !self.is_needed { | ||
None | ||
} else { | ||
Some(self.render().unwrap()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* 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 crate::bindings::backend::{CodeOracle, CodeType, Literal, TypeIdentifier}; | ||
use paste::paste; | ||
use std::fmt; | ||
|
||
#[allow(unused_imports)] | ||
use super::filters; | ||
|
||
fn render_literal(oracle: &dyn CodeOracle, literal: &Literal, inner: &TypeIdentifier) -> String { | ||
match literal { | ||
Literal::Null => "nil".into(), | ||
Literal::EmptySequence => "[]".into(), | ||
Literal::EmptyMap => "[:]".into(), | ||
|
||
// For optionals | ||
_ => oracle.find(inner).literal(oracle, literal), | ||
} | ||
} | ||
|
||
macro_rules! impl_code_type_for_compound { | ||
($T:ty, $type_label_pattern:literal, $canonical_name_pattern:literal) => { | ||
paste! { | ||
pub struct $T { | ||
inner: TypeIdentifier, | ||
} | ||
|
||
impl $T { | ||
pub fn new(inner: TypeIdentifier, _outer: TypeIdentifier) -> Self { | ||
Self { inner } | ||
} | ||
fn inner(&self) -> &TypeIdentifier { | ||
&self.inner | ||
} | ||
} | ||
|
||
impl CodeType for $T { | ||
fn type_label(&self, oracle: &dyn CodeOracle) -> String { | ||
format!($type_label_pattern, oracle.find(self.inner()).type_label(oracle)) | ||
} | ||
|
||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String { | ||
format!($canonical_name_pattern, oracle.find(self.inner()).canonical_name(oracle)) | ||
} | ||
|
||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String { | ||
render_literal(oracle, &literal, self.inner()) | ||
} | ||
|
||
fn lower(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lower()", oracle.var_name(nm)) | ||
} | ||
|
||
fn write(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display, target: &dyn fmt::Display) -> String { | ||
format!("{}.write(into: {})", oracle.var_name(nm), target) | ||
} | ||
|
||
fn lift(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lift({})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn read(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.read(from: {})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> { | ||
Some( | ||
format!("// Helper code for {} is found in RustBufferHelper.swift", self.type_label(oracle)) | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl_code_type_for_compound!(OptionalCodeType, "{}?", "Option{}"); | ||
|
||
impl_code_type_for_compound!(SequenceCodeType, "[{}]", "Sequence{}"); | ||
|
||
impl_code_type_for_compound!(MapCodeType, "[String: {}]", "Map{}"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* 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 std::fmt; | ||
|
||
use crate::bindings::backend::{CodeDeclaration, CodeOracle, CodeType, Literal}; | ||
use crate::interface::{ComponentInterface, Enum}; | ||
use askama::Template; | ||
|
||
use super::filters; | ||
pub struct EnumCodeType { | ||
id: String, | ||
} | ||
|
||
impl EnumCodeType { | ||
pub fn new(id: String) -> Self { | ||
Self { id } | ||
} | ||
} | ||
|
||
impl CodeType for EnumCodeType { | ||
fn type_label(&self, oracle: &dyn CodeOracle) -> String { | ||
oracle.class_name(&self.id) | ||
} | ||
|
||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String { | ||
format!("Enum{}", self.type_label(oracle)) | ||
} | ||
|
||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String { | ||
if let Literal::Enum(v, _) = literal { | ||
format!(".{}", oracle.enum_variant_name(v)) | ||
} else { | ||
unreachable!(); | ||
} | ||
} | ||
|
||
fn lower(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lower()", oracle.var_name(nm)) | ||
} | ||
|
||
fn write( | ||
&self, | ||
oracle: &dyn CodeOracle, | ||
nm: &dyn fmt::Display, | ||
target: &dyn fmt::Display, | ||
) -> String { | ||
format!("{}.write(into: {})", oracle.var_name(nm), target) | ||
} | ||
|
||
fn lift(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lift({})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn read(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.read(from: {})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> { | ||
Some(format!( | ||
"// Helper code for {} enum is found in EnumTemplate.swift", | ||
self.type_label(oracle) | ||
)) | ||
} | ||
} | ||
|
||
#[derive(Template)] | ||
#[template(syntax = "swift", escape = "none", path = "EnumTemplate.swift")] | ||
pub struct SwiftEnum { | ||
inner: Enum, | ||
contains_object_references: bool, | ||
} | ||
|
||
impl SwiftEnum { | ||
pub fn new(inner: Enum, ci: &ComponentInterface) -> Self { | ||
Self { | ||
contains_object_references: ci.item_contains_object_references(&inner), | ||
inner, | ||
} | ||
} | ||
pub fn inner(&self) -> &Enum { | ||
&self.inner | ||
} | ||
pub fn contains_object_references(&self) -> bool { | ||
self.contains_object_references | ||
} | ||
} | ||
|
||
impl CodeDeclaration for SwiftEnum { | ||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> { | ||
Some(self.render().unwrap()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* 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 std::fmt; | ||
|
||
use crate::bindings::backend::{CodeDeclaration, CodeOracle, CodeType, Literal}; | ||
use crate::interface::{ComponentInterface, Error}; | ||
use askama::Template; | ||
|
||
use super::filters; | ||
pub struct ErrorCodeType { | ||
id: String, | ||
} | ||
|
||
impl ErrorCodeType { | ||
pub fn new(id: String) -> Self { | ||
Self { id } | ||
} | ||
} | ||
|
||
impl CodeType for ErrorCodeType { | ||
fn type_label(&self, oracle: &dyn CodeOracle) -> String { | ||
oracle.class_name(&self.id) | ||
} | ||
|
||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String { | ||
format!("Error{}", self.type_label(oracle)) | ||
} | ||
|
||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String { | ||
unreachable!(); | ||
} | ||
|
||
fn lower(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lower()", oracle.var_name(nm)) | ||
} | ||
|
||
fn write( | ||
&self, | ||
oracle: &dyn CodeOracle, | ||
nm: &dyn fmt::Display, | ||
target: &dyn fmt::Display, | ||
) -> String { | ||
format!("{}.write(into: {})", oracle.var_name(nm), target) | ||
} | ||
|
||
fn lift(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.lift({})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn read(&self, oracle: &dyn CodeOracle, nm: &dyn fmt::Display) -> String { | ||
format!("{}.read(from: {})", self.type_label(oracle), nm) | ||
} | ||
|
||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> { | ||
Some(format!( | ||
"// Helper code for {} error is found in ErrorTemplate.swift", | ||
self.type_label(oracle) | ||
)) | ||
} | ||
} | ||
|
||
#[derive(Template)] | ||
#[template(syntax = "swift", escape = "none", path = "ErrorTemplate.swift")] | ||
pub struct SwiftError { | ||
inner: Error, | ||
contains_object_references: bool, | ||
} | ||
|
||
impl SwiftError { | ||
pub fn new(inner: Error, ci: &ComponentInterface) -> Self { | ||
Self { | ||
contains_object_references: ci.item_contains_object_references(&inner), | ||
inner, | ||
} | ||
} | ||
pub fn inner(&self) -> &Error { | ||
&self.inner | ||
} | ||
pub fn contains_object_references(&self) -> bool { | ||
self.contains_object_references | ||
} | ||
} | ||
|
||
impl CodeDeclaration for SwiftError { | ||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> { | ||
Some(self.render().unwrap()) | ||
} | ||
} |
Oops, something went wrong.