foreign_types/lib.rs
1//! A framework for Rust wrappers over C APIs.
2//!
3//! Ownership is as important in C as it is in Rust, but the semantics are often implicit. In
4//! particular, pointer-to-value is commonly used to pass C values both when transferring ownership
5//! or a borrow.
6//!
7//! This crate provides a framework to define a Rust wrapper over these kinds of raw C APIs in a way
8//! that allows ownership semantics to be expressed in an ergonomic manner. The framework takes a
9//! dual-type approach similar to APIs in the standard library such as `PathBuf`/`Path` or `String`/
10//! `str`. One type represents an owned value and references to the other represent borrowed
11//! values.
12//!
13//! # Examples
14//!
15//! ```
16//! use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
17//! use std::ops::{Deref, DerefMut};
18//! use std::ptr::NonNull;
19//!
20//! mod foo_sys {
21//! pub enum FOO {}
22//!
23//! extern {
24//! pub fn FOO_free(foo: *mut FOO);
25//! }
26//! }
27//!
28//! // The borrowed type is a newtype wrapper around an `Opaque` value.
29//! //
30//! // `FooRef` values never exist; we instead create references to `FooRef`s
31//! // from raw C pointers.
32//! pub struct FooRef(Opaque);
33//!
34//! unsafe impl ForeignTypeRef for FooRef {
35//! type CType = foo_sys::FOO;
36//! }
37//!
38//! // The owned type is simply a newtype wrapper around the raw C type.
39//! //
40//! // It dereferences to `FooRef`, so methods that do not require ownership
41//! // should be defined there.
42//! pub struct Foo(NonNull<foo_sys::FOO>);
43//!
44//! unsafe impl Sync for FooRef {}
45//! unsafe impl Send for FooRef {}
46//!
47//! unsafe impl Sync for Foo {}
48//! unsafe impl Send for Foo {}
49//!
50//! impl Drop for Foo {
51//! fn drop(&mut self) {
52//! unsafe { foo_sys::FOO_free(self.as_ptr()) }
53//! }
54//! }
55//!
56//! unsafe impl ForeignType for Foo {
57//! type CType = foo_sys::FOO;
58//! type Ref = FooRef;
59//!
60//! unsafe fn from_ptr(ptr: *mut foo_sys::FOO) -> Foo {
61//! Foo(NonNull::new_unchecked(ptr))
62//! }
63//!
64//! fn as_ptr(&self) -> *mut foo_sys::FOO {
65//! self.0.as_ptr()
66//! }
67//!
68//! fn into_ptr(self) -> *mut foo_sys::FOO {
69//! let inner = self.as_ptr();
70//! ::core::mem::forget(self);
71//! inner
72//! }
73//! }
74//!
75//! impl Deref for Foo {
76//! type Target = FooRef;
77//!
78//! fn deref(&self) -> &FooRef {
79//! unsafe { FooRef::from_ptr(self.as_ptr()) }
80//! }
81//! }
82//!
83//! impl DerefMut for Foo {
84//! fn deref_mut(&mut self) -> &mut FooRef {
85//! unsafe { FooRef::from_ptr_mut(self.as_ptr()) }
86//! }
87//! }
88//!
89//! // add in Borrow, BorrowMut, AsRef, AsRefMut, Clone, ToOwned...
90//! ```
91//!
92//! The `foreign_type!` macro can generate this boilerplate for you:
93//!
94//! ```
95//! use foreign_types::foreign_type;
96//!
97//! mod foo_sys {
98//! pub enum FOO {}
99//!
100//! extern {
101//! pub fn FOO_free(foo: *mut FOO);
102//! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // optional
103//! }
104//! }
105//!
106//! foreign_type! {
107//! /// A Foo.
108//! pub unsafe type Foo
109//! : Sync + Send // optional
110//! {
111//! type CType = foo_sys::FOO;
112//! fn drop = foo_sys::FOO_free;
113//! fn clone = foo_sys::FOO_duplicate; // optional
114//! }
115//!
116//! /// A Foo with generic parameters.
117//! pub unsafe type GenericFoo<T> {
118//! type CType = foo_sys::FOO;
119//! // This type is added as a `PhantomData` field to handle variance
120//! // of the parameters. However, it has no impact on trait impls:
121//! // `GenericFoo<T>` is always `Clone`, even if `T` is not.
122//! type PhantomData = T;
123//! fn drop = foo_sys::FOO_free;
124//! fn clone = foo_sys::FOO_duplicate;
125//! }
126//! }
127//!
128//! # fn main() {}
129//! ```
130//!
131//! If `fn clone` is specified, then it must take `CType` as an argument and return a copy of it as `CType`.
132//! It will be used to implement `Clone`, and if the `std` Cargo feature is enabled, `ToOwned`.
133//!
134//! Say we then have a separate type in our C API that contains a `FOO`:
135//!
136//! ```
137//! mod foo_sys {
138//! pub enum FOO {}
139//! pub enum BAR {}
140//!
141//! extern {
142//! pub fn FOO_free(foo: *mut FOO);
143//! pub fn BAR_free(bar: *mut BAR);
144//! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO;
145//! }
146//! }
147//! ```
148//!
149//! The documentation for the C library states that `BAR_get_foo` returns a reference into the `BAR`
150//! passed to it, which translates into a reference in Rust. It also says that we're allowed to
151//! modify the `FOO`, so we'll define a pair of accessor methods, one immutable and one mutable:
152//!
153//! ```
154//! use foreign_types::{ForeignTypeRef, foreign_type};
155//!
156//! mod foo_sys {
157//! pub enum FOO {}
158//! pub enum BAR {}
159//!
160//! extern {
161//! pub fn FOO_free(foo: *mut FOO);
162//! pub fn BAR_free(bar: *mut BAR);
163//! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO;
164//! }
165//! }
166//!
167//! foreign_type! {
168//! /// A Foo.
169//! pub unsafe type Foo: Sync + Send {
170//! type CType = foo_sys::FOO;
171//! fn drop = foo_sys::FOO_free;
172//! }
173//!
174//! /// A Bar.
175//! pub unsafe type Bar: Sync + Send {
176//! type CType = foo_sys::BAR;
177//! fn drop = foo_sys::BAR_free;
178//! }
179//! }
180//!
181//! impl BarRef {
182//! fn foo(&self) -> &FooRef {
183//! unsafe { FooRef::from_ptr(foo_sys::BAR_get_foo(self.as_ptr())) }
184//! }
185//!
186//! fn foo_mut(&mut self) -> &mut FooRef {
187//! unsafe { FooRef::from_ptr_mut(foo_sys::BAR_get_foo(self.as_ptr())) }
188//! }
189//! }
190//!
191//! # fn main() {}
192//! ```
193#![no_std]
194#![warn(missing_docs)]
195#![doc(html_root_url = "https://docs.rs/foreign-types/0.5")]
196
197#[cfg(feature = "std")]
198extern crate std;
199
200#[doc(hidden)]
201pub use foreign_types_macros::foreign_type_impl;
202#[doc(inline)]
203pub use foreign_types_shared::{ForeignType, ForeignTypeRef, Opaque};
204
205#[doc(hidden)]
206pub mod export {
207 pub use core::borrow::{Borrow, BorrowMut};
208 pub use core::clone::Clone;
209 pub use core::convert::{AsMut, AsRef};
210 pub use core::marker::{PhantomData, Send, Sync};
211 pub use core::ops::{Deref, DerefMut, Drop};
212 pub use core::ptr::NonNull;
213
214 #[cfg(feature = "std")]
215 pub use std::borrow::ToOwned;
216}
217
218/// A macro to easily define wrappers for foreign types.
219///
220/// # Examples
221///
222/// ```
223/// use foreign_types::foreign_type;
224///
225/// # mod openssl_sys { pub type SSL = (); pub unsafe fn SSL_free(_: *mut SSL) {} pub unsafe fn SSL_dup(x: *mut SSL) -> *mut SSL {x} }
226/// # mod foo_sys { pub type THING = (); pub unsafe fn THING_free(_: *mut THING) {} }
227/// foreign_type! {
228/// /// Documentation for the owned type.
229/// pub unsafe type Ssl: Sync + Send {
230/// type CType = openssl_sys::SSL;
231/// fn drop = openssl_sys::SSL_free;
232/// fn clone = openssl_sys::SSL_dup;
233/// }
234///
235/// /// This type immutably borrows other data and has a limited lifetime!
236/// pub unsafe type Thing<'a>: Send {
237/// type CType = foo_sys::THING;
238/// type PhantomData = &'a ();
239/// fn drop = foo_sys::THING_free;
240/// }
241/// }
242///
243/// # fn main() {}
244/// ```
245#[macro_export(local_inner_macros)]
246macro_rules! foreign_type {
247 ($($t:tt)*) => {
248 $crate::foreign_type_impl!($crate $($t)*);
249 };
250}