Crates.io | fruity__bbqsrc |
lib.rs | fruity__bbqsrc |
version | 0.2.0 |
source | src |
created_at | 2021-06-20 22:12:21.393096 |
updated_at | 2021-06-20 22:12:21.393096 |
description | Rusty bindings for Apple libraries |
homepage | https://github.com/nvzqz/fruity |
repository | https://github.com/nvzqz/fruity |
max_upload_size | |
id | 412592 |
size | 506,681 |
Rusty bindings for Apple libraries, brought to you by @NikolaiVazquez.
If this project is useful to you, consider sponsoring me or donating directly!
Doing so enables me to create high-quality open source software like this. ❤️
This library is available on crates.io and can be used in your project
by adding the following to your project's Cargo.toml
:
[dependencies.fruity]
version = "0.2.0"
Each module for a library or framework has its own feature flag with the same name.
For example, this is how you enable the
foundation
module:
[dependencies.fruity]
version = "0.2.0"
features = ["foundation"]
This feature transitively enables the
objc
feature/module.
Fruity makes interfacing with these C and Objective-C APIs feel natural in Rust.
Automatic Reference Counting.
Fruity takes advantage of Rust's ownership model to handle object reference counting for you.
NSObject
is a smart pointer that calls
retain
on Clone
and
release
on Drop
. This is
exactly how Rust's
Arc<T>
works.
Option<NSObject>
.
In Objective-C, all objects are nullable unless marked with _Nonnull
. This
often leads to either very defensive checks or careless ignoring of null
objects.
Fruity reverses that and instead makes all objects (such as
NSObject
)
non-null by default. An object can be made nullable by wrapping it with
Option<T>
.
To make FFI safe and easy, the following Objective-C and Rust types are ABI-compatible:
NSObject * _Nonnull
and NSObject
NSObject * _Nullable
and Option<NSObject>
This is because
NSObject
is a
#[repr(transparent)]
wrapper around a
NonNull<T>
pointer.
Result<T, NSError>
.
In Objective-C, methods take a pointer to where an
NSError
is placed upon failure. This makes it easy to avoid error handling and assume
the happy path, which can lead to bugs when errors occur.
Fruity instead returns a
Result
, which
is the canonical way to handle errors in Rust. This ensures that errors must
be acknowledged in some way.
Natural inheritance.
Most of these types are classes that inherit from each other. Because true
inheritance is not possible in Rust, Fruity uses
Deref
to model Objective-C subclassing.
Builder Pattern.
Types like
DispatchQueue
have many configurable inputs to create an instance. Many of these inputs have
standard default values, so it is cumbersome to specify them all each time.
Swift solves this by having default parameters in
init
.
However, Rust does not have default function parameters.
Fruity instead solves this using the
builder pattern.
See
DispatchQueueBuilder
as an example. This reduces and simplifies code for creating dispatch queues.
Using Fruity to interface with Objective-C libraries should have as little runtime cost as writing the same code directly in Objective-C.
This is true for the following:
Calling object methods.
Method dispatch is always direct and does not need the error checking overhead
of other wrappers that use the
objc::msg_send!
macro. This also reduces the size of your program by not emitting panics that
would otherwise never get called.
This library is carefully written to ensure that calls to
objc_msgSend
are always done with the correct object type, method selector, and arguments.
Getting a static class.
Getters like NSString::class
retrieve the class directly through its symbol.
This is instantaneous, especially when compared to calling into the
Objective-C runtime via
objc_getClass
.
Creating an NSString
from a Rust string literal.
The nsstring!
macro creates an NSString
literal (i.e. @"string"
) at compile time. There
is no runtime dispatch/allocation/initialization cost.
Some parts of this library still aren't zero cost. Your help would be much appreciated here!
These are:
selector!
macro. See
issue #2
for details.This project is released under either the MIT License or Apache License (Version 2.0), at your choosing.