Skip to content

Commit

Permalink
Add wrapper FfiUrl (#195)
Browse files Browse the repository at this point in the history
* WIP

* wip

* not working

* Moving 4 positions before try_read

* tests

* Add Swift test

* bump version

* feedback updates

* remove useeless use

* Create from String and expose Url

* fix test
  • Loading branch information
matiasbzurovski authored Aug 7, 2024
1 parent b05189d commit e8cb924
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sargon"
version = "1.1.1"
version = "1.1.2"
edition = "2021"
build = "build.rs"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Foundation
import SargonUniFFI

#if DEBUG
import XCTestDynamicOverlay
#endif // DEBUG

extension FfiUrl {
public var url: URL {
ffiUrlGetUrl(ffiUrl: self)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Foundation

extension FfiUrl: @unchecked Sendable {}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import SargonUniFFI
extension AppPreferences: SargonModel {}

extension AppPreferences {
public func hasGateway(with url: URL) -> Bool {
public func hasGateway(with url: FfiUrl) -> Bool {
appPreferencesHasGatewayWithUrl(appPreferences: self, url: url)
}
}
12 changes: 12 additions & 0 deletions apple/Tests/TestCases/Prelude/FfiUrlTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Foundation
import Sargon
import SargonUniFFI
import XCTest

final class FfiUrlTests: TestCase {
func test_url() throws {
let url = URL(string: "https://radixdlt.com/")!
let sut = try FfiUrl(urlPath: url.absoluteString)
XCTAssertEqual(sut.url, url)
}
}
18 changes: 14 additions & 4 deletions apple/Tests/TestCases/Profile/AppPreferencesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,19 @@ final class AppPreferencesTests: Test<AppPreferences> {
XCTAssertEqual(SUT.default.transaction.defaultDepositGuarantee, 0.99)
}

func test_has_gateway() {
XCTAssertTrue(SUT.default.hasGateway(with: .init(string: "https://mainnet.radixdlt.com/")!))
XCTAssertTrue(SUT.default.hasGateway(with: .init(string: "https://mainnet.radixdlt.com")!))
XCTAssertFalse(SUT.default.hasGateway(with: .init(string: "https://radixdlt.com")!))
func test_has_gateway_valid() throws {
XCTAssertTrue(SUT.default.hasGateway(with: try .init(urlPath: "https://mainnet.radixdlt.com/")))
XCTAssertTrue(SUT.default.hasGateway(with: try .init(urlPath: "https://mainnet.radixdlt.com")))
XCTAssertFalse(SUT.default.hasGateway(with: try .init(urlPath: "https://radixdlt.com/")))
}

func test_has_gateway_invalid() {
let urlPath = "invalid input"
XCTAssertThrowsError(SUT.default.hasGateway(with: try .init(urlPath: urlPath))) { error in
guard let commonError = error as? SargonUniFFI.CommonError else {
return XCTFail("Expected CommonError")
}
XCTAssertEqual(commonError, .InvalidUrl(badValue: urlPath))
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod home_cards;
mod profile;
mod radix_connect;
mod system;
mod types;
mod wrapped_radix_engine_toolkit;

pub mod prelude {
Expand Down
7 changes: 4 additions & 3 deletions src/profile/v100/app_preferences/app_preferences_uniffi_fn.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::prelude::*;
use crate::types::*;

#[uniffi::export]
pub fn new_app_preferences_sample() -> AppPreferences {
Expand All @@ -18,9 +19,9 @@ pub fn new_app_preferences_default() -> AppPreferences {
#[uniffi::export]
pub fn app_preferences_has_gateway_with_url(
app_preferences: AppPreferences,
url: Url,
url: &FfiUrl,
) -> bool {
app_preferences.has_gateway_with_url(url)
app_preferences.has_gateway_with_url(url.url.clone())
}

#[cfg(test)]
Expand All @@ -46,7 +47,7 @@ mod tests {
fn test_app_preferences_has_gateway_with_url() {
assert!(app_preferences_has_gateway_with_url(
SUT::sample(),
Url::parse("https://mainnet.radixdlt.com").unwrap()
&FfiUrl::from_str("https://mainnet.radixdlt.com").unwrap()
));
}
}
66 changes: 66 additions & 0 deletions src/types/ffi_url.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::prelude::*;

/// A wrapper around `Url` that allows us to safely deal with Urls generated on hosts.
///
/// Context: We have defined a custom type conversion between Rust's `Url` and the hosts analogues.
/// However, a Url could be considered valid on host but not on Rust. For example, Swift allows to build a Url
/// from string `"invalid input"`, while Rust doesn't.
///
/// Therefore, if a given Rust function expects a `Url` as param and is sent one from host side which is invalid,
/// the code will panic. However, if we send the wrapper instead, we make sure the conversion is safely done on the
/// host side, dealing with the failing conversion properly rather than panicking.
#[derive(Debug, PartialEq, Eq, Hash, uniffi::Object, derive_more::Display)]
#[uniffi::export(Debug, Display, Eq, Hash)]
pub struct FfiUrl {
pub url: Url,
}

#[uniffi::export]
impl FfiUrl {
#[uniffi::constructor]
pub fn new(url_path: String) -> Result<Self> {
Self::from_str(&url_path)
}
}

#[uniffi::export]
pub fn ffi_url_get_url(ffi_url: &FfiUrl) -> Url {
ffi_url.url.clone()
}

impl FromStr for FfiUrl {
type Err = CommonError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let url = parse_url(s)?;
Ok(Self { url })
}
}

#[cfg(test)]
mod tests {
use super::*;

#[allow(clippy::upper_case_acronyms)]
type SUT = FfiUrl;

#[test]
fn test_new() {
let url_path = "https://radixdlt.com";
let result = SUT::new(url_path.to_string());
assert_eq!(result.unwrap().url, Url::parse(url_path).unwrap());
}

#[test]
fn test_from_str() {
let result = SUT::from_str("https://radixdlt.com");
assert!(result.is_ok());
}

#[test]
fn test_get_url() {
let url_path = "https://radixdlt.com";
let sut = SUT::new(url_path.to_string()).unwrap();
assert_eq!(ffi_url_get_url(&sut), Url::parse(url_path).unwrap());
}
}
3 changes: 3 additions & 0 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod ffi_url;

pub use ffi_url::*;

0 comments on commit e8cb924

Please sign in to comment.