Skip to content

Commit

Permalink
Merge pull request #13 from madsmtm/documentation
Browse files Browse the repository at this point in the history
Improve documentation
  • Loading branch information
madsmtm committed Sep 1, 2021
2 parents e846ef2 + fa2f1f9 commit 66c7ddf
Show file tree
Hide file tree
Showing 40 changed files with 521 additions and 278 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"objc_encode",
"objc_exception",
"objc_foundation",
"objc_foundation_derive",
"objc_id",
]
exclude = ["objc/tests-ios"]
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Objective-C in Rust

[![License](https://badgen.net/badge/license/MIT/blue)](../LICENSE.txt)
[![CI Status](https://github.com/madsmtm/objc/workflows/CI/badge.svg)](https://github.com/madsmtm/objc/actions)
19 changes: 11 additions & 8 deletions objc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
[package]
name = "objc"
version = "0.2.7"
authors = ["Steven Sheldon"]
version = "0.2.7" # Remember to update html_root_url in lib.rs
authors = ["Steven Sheldon", "Mads Marquart <[email protected]>"]
edition = "2018"

description = "Objective-C Runtime bindings and wrapper for Rust."
keywords = ["objective-c", "osx", "ios", "cocoa", "uikit"]
description = "Objective-C runtime bindings and interface."
keywords = ["objective-c", "macos", "ios", "objc_msgSend"]
categories = [
"api-bindings",
"development-tools::ffi",
"os::macos-apis",
]
readme = "README.md"
repository = "http://github.com/SSheldon/rust-objc"
documentation = "http://ssheldon.github.io/rust-objc/objc/"
repository = "https://github.com/madsmtm/objc"
documentation = "https://docs.rs/objc/"
license = "MIT"

exclude = [
".gitignore",
".travis.yml",
"doc.sh",
"tests-ios/**",
]
Expand Down
38 changes: 27 additions & 11 deletions objc/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
Objective-C Runtime bindings and wrapper for Rust.
# `objc`

[![Latest version](https://badgen.net/crates/v/objc)](https://crates.io/crates/objc)
[![License](https://badgen.net/badge/license/MIT/blue)](../LICENSE.txt)
[![Documentation](https://docs.rs/objc/badge.svg)](https://docs.rs/objc/)
[![CI Status](https://github.com/madsmtm/objc/workflows/CI/badge.svg)](https://github.com/madsmtm/objc/actions)

* Documentation: http://ssheldon.github.io/rust-objc/objc/
* Crate: https://crates.io/crates/objc
Objective-C Runtime bindings and wrapper for Rust.

## Messaging objects

Objective-C objects can be messaged using the `msg_send!` macro:

``` rust
```rust , no_run
use objc::{class, msg_send};
use objc::runtime::{BOOL, Object};

let cls = class!(NSObject);
let obj: *mut Object = msg_send![cls, new];
let hash: usize = msg_send![obj, hash];
let is_kind: BOOL = msg_send![obj, isKindOfClass:cls];
// Even void methods must have their return type annotated
let _: () = msg_send![obj, release];
unsafe {
let obj: *mut Object = msg_send![cls, new];
let hash: usize = msg_send![obj, hash];
let is_kind: BOOL = msg_send![obj, isKindOfClass:cls];
// Even void methods must have their return type annotated
let _: () = msg_send![obj, release];
}
```

## Reference counting
Expand All @@ -24,7 +33,10 @@ A `StrongPtr` retains an object and releases the object when dropped.
A `WeakPtr` will not retain the object, but can be upgraded to a `StrongPtr`
and safely fails if the object has been deallocated.

``` rust
```rust , no_run
use objc::{class, msg_send};
use objc::rc::{autoreleasepool, StrongPtr};

// StrongPtr will release the object when dropped
let obj = unsafe {
StrongPtr::new(msg_send![class!(NSObject), new])
Expand Down Expand Up @@ -52,7 +64,11 @@ methods can then be added before the class is ultimately registered.
The following example demonstrates declaring a class named `MyNumber` that has
one ivar, a `u32` named `_number` and a `number` method that returns it:

``` rust
```rust , no_run
use objc::{class, sel};
use objc::declare::ClassDecl;
use objc::runtime::{Object, Sel};

let superclass = class!(NSObject);
let mut decl = ClassDecl::new("MyNumber", superclass).unwrap();

Expand Down
2 changes: 1 addition & 1 deletion examples/objc.rs → objc/examples/introspection.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use objc::rc::StrongPtr;
use objc::runtime::{Class, Object};
use objc::{class, msg_send, Encode};
use objc::{class, msg_send, sel, Encode};

fn main() {
// Get a class
Expand Down
8 changes: 4 additions & 4 deletions objc/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use core::sync::atomic::{AtomicPtr, Ordering};

use crate::runtime::{self, Class, Sel};

/// Allows storing a `Sel` in a static and lazily loading it.
/// Allows storing a [`Sel`] in a static and lazily loading it.
#[doc(hidden)]
pub struct CachedSel {
ptr: AtomicPtr<c_void>,
}

impl CachedSel {
/// Constructs a new `CachedSel`.
/// Constructs a new [`CachedSel`].
pub const fn new() -> CachedSel {
CachedSel {
ptr: AtomicPtr::new(ptr::null_mut()),
Expand All @@ -35,14 +35,14 @@ impl CachedSel {
}
}

/// Allows storing a `Class` reference in a static and lazily loading it.
/// Allows storing a [`Class`] reference in a static and lazily loading it.
#[doc(hidden)]
pub struct CachedClass {
ptr: AtomicPtr<Class>,
}

impl CachedClass {
/// Constructs a new `CachedClass`.
/// Constructs a new [`CachedClass`].
pub const fn new() -> CachedClass {
CachedClass {
ptr: AtomicPtr::new(ptr::null_mut()),
Expand Down
71 changes: 40 additions & 31 deletions objc/src/declare.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
Functionality for declaring Objective-C classes.
Classes can be declared using the `ClassDecl` struct. Instance variables and
Classes can be declared using the [`ClassDecl`] struct. Instance variables and
methods can then be added before the class is ultimately registered.
# Example
Expand All @@ -13,7 +13,6 @@ one ivar, a `u32` named `_number` and a `number` method that returns it:
# use objc::{class, sel};
# use objc::declare::ClassDecl;
# use objc::runtime::{Class, Object, Sel};
# fn main() {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new("MyNumber", superclass).unwrap();
Expand All @@ -30,7 +29,6 @@ unsafe {
}
decl.register();
# }
```
*/

Expand All @@ -52,7 +50,7 @@ pub trait MethodImplementation {
/// The argument types of the method.
type Args: EncodeArguments;

/// Returns self as an `Imp` of a method.
/// Returns self as an [`Imp`] of a method.
fn imp(self) -> Imp;
}

Expand Down Expand Up @@ -129,20 +127,21 @@ impl ClassDecl {
}
}

/// Constructs a `ClassDecl` with the given name and superclass.
/// Returns `None` if the class couldn't be allocated.
/// Constructs a [`ClassDecl`] with the given name and superclass.
///
/// Returns [`None`] if the class couldn't be allocated.
pub fn new(name: &str, superclass: &Class) -> Option<ClassDecl> {
ClassDecl::with_superclass(name, Some(superclass))
}

/**
Constructs a `ClassDecl` declaring a new root class with the given name.
Returns `None` if the class couldn't be allocated.
Constructs a [`ClassDecl`] declaring a new root class with the given name.
Returns [`None`] if the class couldn't be allocated.
An implementation for `+initialize` must also be given; the runtime calls
this method for all classes, so it must be defined on root classes.
Note that implementing a root class is not a simple endeavor.
Note that implementing a root class is not a simple endeavor!
For example, your class probably cannot be passed to Cocoa code unless
the entire `NSObject` protocol is implemented.
Functionality it expects, like implementations of `-retain` and `-release`
Expand All @@ -158,9 +157,12 @@ impl ClassDecl {
decl
}

/// Adds a method with the given name and implementation to self.
/// Panics if the method wasn't sucessfully added
/// or if the selector and function take different numbers of arguments.
/// Adds a method with the given name and implementation.
///
/// # Panics
///
/// Panics if the method wasn't sucessfully added or if the selector and
/// function take different numbers of arguments.
///
/// # Safety
///
Expand All @@ -184,9 +186,12 @@ impl ClassDecl {
assert!(success != NO, "Failed to add method {:?}", sel);
}

/// Adds a class method with the given name and implementation to self.
/// Panics if the method wasn't sucessfully added
/// or if the selector and function take different numbers of arguments.
/// Adds a class method with the given name and implementation.
///
/// # Panics
///
/// Panics if the method wasn't sucessfully added or if the selector and
/// function take different numbers of arguments.
///
/// # Safety
///
Expand All @@ -211,12 +216,12 @@ impl ClassDecl {
assert!(success != NO, "Failed to add class method {:?}", sel);
}

/// Adds an ivar with type `T` and the provided name to self.
/// Panics if the ivar wasn't successfully added.
pub fn add_ivar<T>(&mut self, name: &str)
where
T: Encode,
{
/// Adds an ivar with type `T` and the provided name.
///
/// # Panics
///
/// If the ivar wasn't successfully added.
pub fn add_ivar<T: Encode>(&mut self, name: &str) {
let c_name = CString::new(name).unwrap();
let encoding = CString::new(T::ENCODING.to_string()).unwrap();
let size = mem::size_of::<T>();
Expand All @@ -227,15 +232,18 @@ impl ClassDecl {
assert!(success != NO, "Failed to add ivar {}", name);
}

/// Adds a protocol to self. Panics if the protocol wasn't successfully
/// added
/// Adds the given protocol to self.
///
/// # Panics
///
/// If the protocol wasn't successfully added.
pub fn add_protocol(&mut self, proto: &Protocol) {
let success = unsafe { runtime::class_addProtocol(self.cls, proto) };
assert!(success != NO, "Failed to add protocol {:?}", proto);
}

/// Registers self, consuming it and returning a reference to the
/// newly registered `Class`.
/// Registers the [`ClassDecl`], consuming it, and returns a reference to
/// the newly registered [`Class`].
pub fn register(self) -> &'static Class {
unsafe {
let cls = self.cls;
Expand All @@ -262,8 +270,9 @@ pub struct ProtocolDecl {
}

impl ProtocolDecl {
/// Constructs a `ProtocolDecl` with the given name. Returns `None` if the
/// protocol couldn't be allocated.
/// Constructs a [`ProtocolDecl`] with the given name.
///
/// Returns [`None`] if the protocol couldn't be allocated.
pub fn new(name: &str) -> Option<ProtocolDecl> {
let c_name = CString::new(name).unwrap();
let proto = unsafe { runtime::objc_allocateProtocol(c_name.as_ptr()) };
Expand Down Expand Up @@ -303,7 +312,7 @@ impl ProtocolDecl {
}
}

/// Adds an instance method declaration with a given description to self.
/// Adds an instance method declaration with a given description.
pub fn add_method_description<Args, Ret>(&mut self, sel: Sel, is_required: bool)
where
Args: EncodeArguments,
Expand All @@ -312,7 +321,7 @@ impl ProtocolDecl {
self.add_method_description_common::<Args, Ret>(sel, is_required, true)
}

/// Adds a class method declaration with a given description to self.
/// Adds a class method declaration with a given description.
pub fn add_class_method_description<Args, Ret>(&mut self, sel: Sel, is_required: bool)
where
Args: EncodeArguments,
Expand All @@ -328,8 +337,8 @@ impl ProtocolDecl {
}
}

/// Registers self, consuming it and returning a reference to the
/// newly registered `Protocol`.
/// Registers the [`ProtocolDecl`], consuming it and returning a reference
/// to the newly registered [`Protocol`].
pub fn register(self) -> &'static Protocol {
unsafe {
runtime::objc_registerProtocol(self.proto);
Expand Down
2 changes: 1 addition & 1 deletion objc/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ unsafe impl<'a> Encode for &'a mut Class {
}

/// Types that represent a group of arguments, where each has an Objective-C
/// type encoding.
/// type-encoding.
pub trait EncodeArguments {
/// The type as which the encodings for Self will be returned.
const ENCODINGS: &'static [Encoding<'static>];
Expand Down
15 changes: 7 additions & 8 deletions objc/src/exception.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use objc_exception;

use crate::rc::StrongPtr;
use crate::runtime::Object;

Expand All @@ -14,11 +12,12 @@ use crate::runtime::Object;
///
/// # Safety
///
/// This encourages unwinding through the closure from Objective-C, which is
/// not safe.
pub unsafe fn catch_exception<F, R>(closure: F) -> Result<R, StrongPtr>
where
F: FnOnce() -> R,
{
/// The given closure must not panic.
///
/// Additionally, this unwinds through the closure from Objective-C, which is
/// undefined behaviour until `C-unwind` is stabilized, see [RFC-2945].
///
/// [RFC-2945]: https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html
pub unsafe fn catch_exception<R>(closure: impl FnOnce() -> R) -> Result<R, StrongPtr> {
objc_exception::r#try(closure).map_err(|exception| StrongPtr::new(exception as *mut Object))
}
12 changes: 10 additions & 2 deletions objc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ Objective-C objects can be messaged using the [`msg_send!`](macro.msg_send!.html
``` no_run
# use objc::{class, msg_send};
# use objc::runtime::{BOOL, Class, Object};
# fn main() {
# unsafe {
let cls = class!(NSObject);
let obj: *mut Object = msg_send![cls, new];
Expand All @@ -17,7 +16,6 @@ let is_kind: BOOL = msg_send![obj, isKindOfClass:cls];
// Even void methods must have their return type annotated
let _: () = msg_send![obj, release];
# }
# }
```
# Reference counting
Expand Down Expand Up @@ -63,10 +61,20 @@ The bindings can be used on Linux or *BSD utilizing the
#![no_std]
#![warn(missing_docs)]
#![allow(clippy::missing_safety_doc)]
// Update in Cargo.toml as well.
#![doc(html_root_url = "https://docs.rs/objc/0.2.7")]

extern crate alloc;
extern crate std;

#[cfg(doctest)]
#[doc = include_str!("../README.md")]
extern "C" {}

#[cfg(doctest)]
#[doc = include_str!("../../README.md")]
extern "C" {}

pub use objc_encode::{Encode, Encoding};

pub use crate::encode::EncodeArguments;
Expand Down
Loading

0 comments on commit 66c7ddf

Please sign in to comment.