Use swift-rs

This commit is contained in:
Brendan Allan 2021-10-20 14:54:17 +08:00
parent 4aaef94a5b
commit b29135843e
8 changed files with 42 additions and 202 deletions

12
src-tauri/Cargo.lock generated
View file

@ -33,6 +33,7 @@ dependencies = [
"snafu",
"sqlx",
"strum 0.21.0",
"swift-rs",
"tauri",
"tauri-build",
"walkdir",
@ -4057,6 +4058,17 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "swift-rs"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e56047444883f07ced9a621d23c8af8c7a3bbdafc16e02e00f4799943002e20"
dependencies = [
"base64",
"serde",
"serde_json",
]
[[package]]
name = "syn"
version = "0.11.11"

View file

@ -11,8 +11,7 @@ build = "src/build.rs"
[build-dependencies]
tauri-build = { version = "1.0.0-beta.3" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
swift-rs = "0.1.0"
[dependencies]
tauri = { version = "1.0.0-beta.5", features = ["api-all", "menu"] }
@ -45,6 +44,7 @@ log = "0.4.14"
objc = "0.2.7"
cocoa = "0.24.0"
objc-foundation = "0.1.1"
swift-rs = "0.1.0"
[features]
default = [ "custom-protocol" ]

View file

@ -1,82 +1,8 @@
use serde::Deserialize;
use serde_json;
use std::env;
use std::process::Command;
const MACOS_TARGET_VERSION: &str = "11";
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct SwiftTargetInfo {
triple: String,
unversioned_triple: String,
module_triple: String,
swift_runtime_compatibility_version: String,
#[serde(rename = "librariesRequireRPath")]
libraries_require_rpath: bool,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct SwiftPaths {
runtime_library_paths: Vec<String>,
runtime_library_import_paths: Vec<String>,
runtime_resource_path: String,
}
#[derive(Debug, Deserialize)]
struct SwiftTarget {
target: SwiftTargetInfo,
paths: SwiftPaths,
}
/// Builds mac_ddc library Swift project, sets the library search options right so we link
/// against Swift run-time correctly.
fn build_swift_natives() {
let profile = env::var("PROFILE").unwrap();
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let target = format!("{}-apple-macosx{}", arch, MACOS_TARGET_VERSION);
let swift_target_info_str = Command::new("swift")
.args(&["-target", &target, "-print-target-info"])
.output()
.unwrap()
.stdout;
let swift_target_info: SwiftTarget = serde_json::from_slice(&swift_target_info_str).unwrap();
if swift_target_info.target.libraries_require_rpath {
panic!("Libraries require RPath! Change minimum MacOS value to fix.")
}
if !Command::new("swift")
.args(&["build", "-c", &profile])
.current_dir("./swift-lib")
.status()
.unwrap()
.success()
{
panic!("Swift natives compilation failed")
}
swift_target_info
.paths
.runtime_library_paths
.iter()
.for_each(|path| {
println!("cargo:rustc-link-search=native={}", path);
});
println!(
"cargo:rustc-link-search=native=./swift-lib/.build/{}/{}",
swift_target_info.target.unversioned_triple, profile
);
println!("cargo:rustc-link-lib=static=swift-lib");
println!("cargo:rerun-if-changed=swift-lib/src/*.swift");
println!(
"cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET={}",
MACOS_TARGET_VERSION
);
}
use swift_rs::build_utils::{link_swift, link_swift_package};
fn main() {
build_swift_natives();
link_swift();
link_swift_package("swift-lib", "./swift-lib/");
tauri_build::build();
}

View file

@ -35,8 +35,7 @@ pub async fn scan_dir(path: String) -> Result<(), String> {
}
#[tauri::command(async)]
pub async fn get_file_thumb(path: &str) -> Result<String, String> {
let path = &path.to_string();
let thumbnail_b46 = get_file_thumbnail_base64(path.into()).to_string();
let thumbnail_b46 = get_file_thumbnail_base64(path).to_string();
Ok(thumbnail_b46)
}

View file

@ -1,59 +1,10 @@
#[derive(Debug)]
#[repr(C)]
struct SRArray<T> {
_nsobject_offset: u8,
data: *mut T,
length: usize,
}
impl<T> SRArray<T> {
fn into_slice(&self) -> &'static [T] {
unsafe { std::slice::from_raw_parts(self.data, self.length) }
}
}
#[derive(Debug)]
#[repr(C)]
struct SRData {
_nsobject_offset: u8,
data: *mut SRArray<u8>,
}
impl SRData {
pub fn into_slice(&self) -> &'static [u8] {
unsafe { (*self.data).into_slice() }
}
pub fn data(&self) -> &SRArray<u8> {
unsafe { &*(self.data) }
}
}
#[derive(Debug)]
#[repr(C)]
pub struct SRString(SRData);
impl SRString {
pub fn to_string(&self) -> String {
unsafe { std::str::from_utf8_unchecked(self.0.into_slice()) }.into()
}
}
impl From<&String> for &SRString {
fn from(string: &String) -> &'static SRString {
unsafe { allocate_string(string.as_ptr(), string.len()) }
}
}
use swift_rs::types::SRString;
extern "C" {
fn return_data() -> &'static SRData;
fn return_string() -> &'static SRString;
fn echo_string(string: &SRString);
fn allocate_string(data: *const u8, size: usize) -> &'static SRString;
#[link_name = "get_file_thumbnail_base64"]
fn get_file_thumbnail_base64_(path: &SRString) -> &'static SRString;
}
pub fn get_file_thumbnail_base64(path: &SRString) -> &'static SRString {
unsafe { get_file_thumbnail_base64_(path) }
pub fn get_file_thumbnail_base64(path: &str) -> &'static SRString {
unsafe { get_file_thumbnail_base64_(path.into()) }
}

View file

@ -0,0 +1,16 @@
{
"object": {
"pins": [
{
"package": "SwiftRs",
"repositoryURL": "https://github.com/Brendonovich/swift-rs",
"state": {
"branch": "master",
"revision": "1827da87300a581b5cd828dd5c9bd5dcd26243b6",
"version": null
}
}
]
},
"version": 1
}

View file

@ -18,13 +18,14 @@ let package = Package(
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(name: "SwiftRs", url: "https://github.com/Brendonovich/swift-rs", branch: "master")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "swift-lib",
dependencies: [],
dependencies: [.product(name: "SwiftRs", package: "SwiftRs")],
path: "src")
]
)

View file

@ -1,70 +1,6 @@
import Foundation
import AppKit
// Size: 24 bytes
public class SRArray<T>: NSObject {
var pointer: UnsafePointer<T>
var length: Int
init(_ data: [T]) {
let mut_data = UnsafeMutablePointer<T>.allocate(capacity: data.count)
mut_data.initialize(from: data, count: data.count)
self.pointer = UnsafePointer(mut_data)
self.length = data.count
}
}
// Size: 16 bytes
public class SRData: NSObject {
var data: SRArray<UInt8>
init(_ data: [UInt8]) {
self.data = SRArray(data)
}
func to_data() -> Data {
return Data(bytes: self.data.pointer, count: self.data.length)
}
}
// Size: 16 bytes
public class SRString: SRData {
init(_ string: String) {
super.init(Array(string.utf8))
}
func to_string() -> String {
return String(bytes: self.to_data(), encoding: .utf8)!
}
}
@_cdecl("return_data")
public func returnData() -> SRData {
return SRData([1,2,3])
}
@_cdecl("return_string")
public func returnString() -> SRString {
return SRString("123456")
}
@_cdecl("echo_string")
public func echoString(string: SRString) {
print(string.to_string())
}
// SRstring pointer is passed to rust correctly
// data pointer is passed to rust correctly
// guessing that the type of SRArray isn't the same
@_cdecl("allocate_string")
public func allocate_string(data: UnsafePointer<UInt8>, size: Int) -> SRString {
let buffer = UnsafeBufferPointer(start: data, count: size)
let string = String(bytes: buffer, encoding: .utf8)!;
let SRstring = SRString(string);
return SRstring
}
import SwiftRs
@_cdecl("get_file_thumbnail_base64")
public func getFileThumbnailBase64(path: SRString) -> SRString {
@ -74,5 +10,4 @@ public func getFileThumbnailBase64(path: SRString) -> SRString {
let bitmap = NSBitmapImageRep(data: image.tiffRepresentation!)!.representation(using: .png, properties: [:])!
return SRString(bitmap.base64EncodedString())
}
}