Skip to content

Improve documentation #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "objc-encode"
version = "1.1.0"
version = "1.1.0" # Remember to update html_root_url in lib.rs
authors = ["Steven Sheldon"]
edition = "2018"

Expand All @@ -9,7 +9,7 @@ keywords = ["objective-c", "osx", "ios", "cocoa", "uikit"]
categories = ["development-tools::ffi", "no-std"]
readme = "README.md"
repository = "http://github.com/SSheldon/rust-objc-encode"
documentation = "http://ssheldon.github.io/rust-objc/objc_encode/"
documentation = "https://docs.rs/objc-encode/"
license = "MIT"

exclude = [
Expand Down
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
# ``objc-encode``

[![Crates.io](https://img.shields.io/crates/v/objc-encode.svg)](https://crates.io/crates/objc-encode)
[![Docs.rs](https://docs.rs/objc-encode/badge.svg)](https://docs.rs/objc-encode/)

Objective-C type encoding creation and parsing in Rust.

The Objective-C compiler encodes types as strings for usage in the runtime.
This crate aims to provide a strongly-typed (rather than stringly-typed) way
to create and describe these type encodings without memory allocation in Rust.

# Implementing Encode

## Implementing Encode

This crate declares an `Encode` trait that can be implemented for types that
the Objective-C compiler can encode. Implementing this trait looks like:

``` rust
```rust
unsafe impl Encode for CGPoint {
const ENCODING: Encoding<'static> =
Encoding::Struct("CGPoint", &[CGFloat::ENCODING, CGFLOAT::ENCODING]);
Expand All @@ -19,20 +25,20 @@ unsafe impl Encode for CGPoint {
For an example of how this works with more complex types, like structs
containing structs, see the `core_graphics` example.

# Comparing with encoding strings
## Comparing with encoding strings

An `Encoding` can be compared with an encoding string from the Objective-C
runtime:

``` rust
```rust
assert!(&i32::ENCODING == "i");
```

# Generating encoding strings
## Generating encoding strings

Every `Encoding` implements `Display` as its string representation.
This can be generated conveniently through the `to_string` method:

``` rust
```rust
assert_eq!(i32::ENCODING.to_string(), "i");
```
34 changes: 34 additions & 0 deletions examples/ns_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use objc_encode::{Encode, Encoding};

/// We don't know the size of NSString, so we can only hold pointers to it.
///
/// TODO: Use [`extern type`][rfc-1861] when that gets stabilized.
///
/// [rfc-1861]: https://rust-lang.github.io/rfcs/1861-extern-types.html
#[repr(C)]
struct NSString {
_priv: [u8; 0],
}

/// Implement `Encode` for references.
///
/// This also implements for `*mut NSString` and `Option<&mut NSString>`.
unsafe impl<'a> Encode for &'a NSString {
const ENCODING: Encoding<'static> = Encoding::Object;
}

/// Implement `Encode` for mutable references.
///
/// This also implements for `*mut NSString` and `Option<&mut NSString>`.
unsafe impl<'a> Encode for &'a mut NSString {
const ENCODING: Encoding<'static> = Encoding::Object;
}

fn main() {
println!("{}", <*const NSString>::ENCODING);
println!("{}", <*mut NSString>::ENCODING);
println!("{}", <&NSString>::ENCODING);
println!("{}", <&mut NSString>::ENCODING);
println!("{}", Option::<&NSString>::ENCODING);
println!("{}", Option::<&mut NSString>::ENCODING);
}
30 changes: 22 additions & 8 deletions src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ use crate::Encoding;

/// Types that have an Objective-C type encoding.
///
/// Unsafe because Objective-C will make assumptions about the type (like its
/// size and alignment) from its encoding, so the implementer must verify that
/// the encoding is accurate.
/// # Safety
///
/// Objective-C will make assumptions about the type (like its size and
/// alignment) from its encoding, so the implementer must verify that the
/// encoding is accurate.
pub unsafe trait Encode {
/// Returns the Objective-C type encoding for Self.
/// The Objective-C type encoding for `Self`.
const ENCODING: Encoding<'static>;
}

Expand Down Expand Up @@ -86,18 +88,30 @@ External crates cannot implement Encode for pointers or Optionals, but they
As a workaround, we provide implementations for these types that return the
same encoding as references.
*/
unsafe impl<T> Encode for *const T where for<'b> &'b T: Encode {
unsafe impl<T> Encode for *const T
where
for<'b> &'b T: Encode,
{
const ENCODING: Encoding<'static> = <&T>::ENCODING;
}

unsafe impl<T> Encode for *mut T where for<'b> &'b mut T: Encode {
unsafe impl<T> Encode for *mut T
where
for<'b> &'b mut T: Encode,
{
const ENCODING: Encoding<'static> = <&mut T>::ENCODING;
}

unsafe impl<'a, T> Encode for Option<&'a T> where for<'b> &'b T: Encode {
unsafe impl<'a, T> Encode for Option<&'a T>
where
for<'b> &'b T: Encode,
{
const ENCODING: Encoding<'static> = <&T>::ENCODING;
}

unsafe impl<'a, T> Encode for Option<&'a mut T> where for<'b> &'b mut T: Encode {
unsafe impl<'a, T> Encode for Option<&'a mut T>
where
for<'b> &'b mut T: Encode,
{
const ENCODING: Encoding<'static> = <&mut T>::ENCODING;
}
75 changes: 55 additions & 20 deletions src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,92 @@ use crate::parse;
/// <https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html>
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Encoding<'a> {
/// A C `char`. Corresponds to the `c` code.
Char,
/// A C `short`. Corresponds to the `s` code.
Short,
/// A C `int`. Corresponds to the `i` code.
Int,
/// A C `long`. Corresponds to the `l` code.
Long,
/// A C `long long`. Corresponds to the `q` code.
LongLong,
/// A C `unsigned char`. Corresponds to the `C` code.
UChar,
/// A C `unsigned short`. Corresponds to the `S` code.
UShort,
/// A C `unsigned int`. Corresponds to the `I` code.
UInt,
/// A C `unsigned long`. Corresponds to the `L` code.
ULong,
/// A C `unsigned long long`. Corresponds to the `Q` code.
ULongLong,
/// A C `float`. Corresponds to the `f` code.
Float,
/// A C `double`. Corresponds to the `d` code.
Double,
/// A C++ `bool` / C99 `_Bool`. Corresponds to the `B` code.
Bool,
/// A C `void`. Corresponds to the `v` code.
Void,
/// A C `char *`. Corresponds to the `*` code.
String,
/// An Objective-C object (`id`). Corresponds to the `@` code.
Object,
/// An Objective-C block. Corresponds to the `@?` code.
Block,
/// An Objective-C class (`Class`). Corresponds to the `#` code.
Class,
/// An Objective-C selector (`SEL`). Corresponds to the `:` code.
Sel,
/// An unknown type. Corresponds to the `?` code.
Unknown,
/// A bitfield with the given number of bits.
///
/// Corresponds to the `b`num code.
BitField(u32),
/// A pointer to the given type.
///
/// Corresponds to the `^`type code.
Pointer(&'a Encoding<'a>),
/// An array with the given length and type.
///
/// Corresponds to the `[len type]` code.
Array(u32, &'a Encoding<'a>),
/// A struct with the given name and fields.
///
/// Corresponds to the `{name=fields...}` code.
Struct(&'a str, &'a [Encoding<'a>]),
/// A union with the given name and fields.
///
/// Corresponds to the `(name=fields...)` code.
Union(&'a str, &'a [Encoding<'a>]),
}

impl fmt::Display for Encoding<'_> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use Encoding::*;
let code = match *self {
Char => "c",
Short => "s",
Int => "i",
Long => "l",
LongLong => "q",
UChar => "C",
UShort => "S",
UInt => "I",
ULong => "L",
Char => "c",
Short => "s",
Int => "i",
Long => "l",
LongLong => "q",
UChar => "C",
UShort => "S",
UInt => "I",
ULong => "L",
ULongLong => "Q",
Float => "f",
Double => "d",
Bool => "B",
Void => "v",
String => "*",
Object => "@",
Block => "@?",
Class => "#",
Sel => ":",
Unknown => "?",
Float => "f",
Double => "d",
Bool => "B",
Void => "v",
String => "*",
Object => "@",
Block => "@?",
Class => "#",
Sel => ":",
Unknown => "?",
BitField(b) => {
return write!(formatter, "b{}", b);
}
Expand Down Expand Up @@ -101,8 +136,8 @@ impl PartialEq<Encoding<'_>> for str {

#[cfg(test)]
mod tests {
use std::string::ToString;
use super::Encoding;
use alloc::string::ToString;

#[test]
fn test_array_display() {
Expand Down
22 changes: 13 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ to create and describe these type encodings without memory allocation in Rust.

# Implementing Encode

This crate declares an `Encode` trait that can be implemented for types that
This crate declares an [`Encode`] trait that can be implemented for types that
the Objective-C compiler can encode. Implementing this trait looks like:

``` ignore
```ignore
unsafe impl Encode for CGPoint {
const ENCODING: Encoding<'static> =
Encoding::Struct("CGPoint", &[CGFloat::ENCODING, CGFLOAT::ENCODING]);
Expand All @@ -22,7 +22,7 @@ containing structs, see the `core_graphics` example.

# Comparing with encoding strings

An `Encoding` can be compared with an encoding string from the Objective-C
An [`Encoding`] can be compared with an encoding string from the Objective-C
runtime:

```
Expand All @@ -32,8 +32,9 @@ assert!(&i32::ENCODING == "i");

# Generating encoding strings

Every `Encoding` implements `Display` as its string representation.
This can be generated conveniently through the `to_string` method:
Every [`Encoding`] implements [`Display`][`core::fmt::Display`] as its string
representation. This can be generated conveniently through the
[`to_string`][`alloc::string::ToString::to_string`] method:

```
# use objc_encode::Encode;
Expand All @@ -42,13 +43,16 @@ assert_eq!(i32::ENCODING.to_string(), "i");
*/

#![no_std]
#![warn(missing_docs)]
// Update in Cargo.toml as well.
#![doc(html_root_url = "https://docs.rs/objc-encode/1.1.0")]

#[cfg(test)]
extern crate std;
#[cfg(any(test, doc))]
extern crate alloc;

mod encoding;
mod encode;
mod encoding;
mod parse;

pub use crate::encoding::Encoding;
pub use crate::encode::Encode;
pub use crate::encoding::Encoding;
Loading