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//!
19//! mod foo_sys {
20//! pub enum FOO {}
21//!
22//! extern {
23//! pub fn FOO_free(foo: *mut FOO);
24//! }
25//! }
26//!
27//! // The borrowed type is a newtype wrapper around an `Opaque` value.
28//! //
29//! // `FooRef` values never exist; we instead create references to `FooRef`s
30//! // from raw C pointers.
31//! pub struct FooRef(Opaque);
32//!
33//! impl ForeignTypeRef for FooRef {
34//! type CType = foo_sys::FOO;
35//! }
36//!
37//! // The owned type is simply a newtype wrapper around the raw C type.
38//! //
39//! // It dereferences to `FooRef`, so methods that do not require ownership
40//! // should be defined there.
41//! pub struct Foo(*mut foo_sys::FOO);
42//!
43//! impl Drop for Foo {
44//! fn drop(&mut self) {
45//! unsafe { foo_sys::FOO_free(self.0) }
46//! }
47//! }
48//!
49//! impl ForeignType for Foo {
50//! type CType = foo_sys::FOO;
51//! type Ref = FooRef;
52//!
53//! unsafe fn from_ptr(ptr: *mut foo_sys::FOO) -> Foo {
54//! Foo(ptr)
55//! }
56//!
57//! fn as_ptr(&self) -> *mut foo_sys::FOO {
58//! self.0
59//! }
60//! }
61//!
62//! impl Deref for Foo {
63//! type Target = FooRef;
64//!
65//! fn deref(&self) -> &FooRef {
66//! unsafe { FooRef::from_ptr(self.0) }
67//! }
68//! }
69//!
70//! impl DerefMut for Foo {
71//! fn deref_mut(&mut self) -> &mut FooRef {
72//! unsafe { FooRef::from_ptr_mut(self.0) }
73//! }
74//! }
75//! ```
76//!
77//! The `foreign_type!` macro can generate this boilerplate for you:
78//!
79//! ```
80//! #[macro_use]
81//! extern crate foreign_types;
82//!
83//! mod foo_sys {
84//! pub enum FOO {}
85//!
86//! extern {
87//! pub fn FOO_free(foo: *mut FOO);
88//! pub fn FOO_duplicate(foo: *mut FOO) -> *mut FOO; // Optional
89//! }
90//! }
91//!
92//! foreign_type! {
93//! type CType = foo_sys::FOO;
94//! fn drop = foo_sys::FOO_free;
95//! fn clone = foo_sys::FOO_duplicate; // Optional
96//! /// A Foo.
97//! pub struct Foo;
98//! /// A borrowed Foo.
99//! pub struct FooRef;
100//! }
101//!
102//! # fn main() {}
103//! ```
104//!
105//! If `fn clone` is specified, then it must take `CType` as an argument and return a copy of it as `CType`.
106//! It will be used to implement `ToOwned` and `Clone`.
107//!
108//! `#[derive(…)] is permitted before the lines with `pub struct`.
109//! `#[doc(hidden)]` before the `type CType` line will hide the `foreign_type!` implementations from documentation.
110//!
111//! Say we then have a separate type in our C API that contains a `FOO`:
112//!
113//! ```
114//! mod foo_sys {
115//! pub enum FOO {}
116//! pub enum BAR {}
117//!
118//! extern {
119//! pub fn FOO_free(foo: *mut FOO);
120//! pub fn BAR_free(bar: *mut BAR);
121//! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO;
122//! }
123//! }
124//! ```
125//!
126//! The documentation for the C library states that `BAR_get_foo` returns a reference into the `BAR`
127//! passed to it, which translates into a reference in Rust. It also says that we're allowed to
128//! modify the `FOO`, so we'll define a pair of accessor methods, one immutable and one mutable:
129//!
130//! ```
131//! #[macro_use]
132//! extern crate foreign_types;
133//!
134//! use foreign_types::ForeignTypeRef;
135//!
136//! mod foo_sys {
137//! pub enum FOO {}
138//! pub enum BAR {}
139//!
140//! extern {
141//! pub fn FOO_free(foo: *mut FOO);
142//! pub fn BAR_free(bar: *mut BAR);
143//! pub fn BAR_get_foo(bar: *mut BAR) -> *mut FOO;
144//! }
145//! }
146//!
147//! foreign_type! {
148//! #[doc(hidden)]
149//! type CType = foo_sys::FOO;
150//! fn drop = foo_sys::FOO_free;
151//! /// A Foo.
152//! pub struct Foo;
153//! /// A borrowed Foo.
154//! pub struct FooRef;
155//! }
156//!
157//! foreign_type! {
158//! type CType = foo_sys::BAR;
159//! fn drop = foo_sys::BAR_free;
160//! /// A Foo.
161//! pub struct Bar;
162//! /// A borrowed Bar.
163//! pub struct BarRef;
164//! }
165//!
166//! impl BarRef {
167//! fn foo(&self) -> &FooRef {
168//! unsafe { FooRef::from_ptr(foo_sys::BAR_get_foo(self.as_ptr())) }
169//! }
170//!
171//! fn foo_mut(&mut self) -> &mut FooRef {
172//! unsafe { FooRef::from_ptr_mut(foo_sys::BAR_get_foo(self.as_ptr())) }
173//! }
174//! }
175//!
176//! # fn main() {}
177//! ```
178#![no_std]
179#![warn(missing_docs)]
180#![doc(html_root_url="https://docs.rs/foreign-types/0.3")]
181extern crate foreign_types_shared;
182
183#[doc(inline)]
184pub use foreign_types_shared::*;
185
186/// A macro to easily define wrappers for foreign types.
187///
188/// # Examples
189///
190/// ```
191/// #[macro_use]
192/// extern crate foreign_types;
193///
194/// # mod openssl_sys { pub type SSL = (); pub unsafe fn SSL_free(_: *mut SSL) {} pub unsafe fn SSL_dup(x: *mut SSL) -> *mut SSL {x} }
195/// foreign_type! {
196/// type CType = openssl_sys::SSL;
197/// fn drop = openssl_sys::SSL_free;
198/// fn clone = openssl_sys::SSL_dup;
199/// /// Documentation for the owned type.
200/// pub struct Ssl;
201/// /// Documentation for the borrowed type.
202/// pub struct SslRef;
203/// }
204///
205/// # fn main() {}
206/// ```
207#[macro_export]
208macro_rules! foreign_type {
209 (
210 $(#[$impl_attr:meta])*
211 type CType = $ctype:ty;
212 fn drop = $drop:expr;
213 $(fn clone = $clone:expr;)*
214 $(#[$owned_attr:meta])*
215 pub struct $owned:ident;
216 $(#[$borrowed_attr:meta])*
217 pub struct $borrowed:ident;
218 ) => {
219 $(#[$owned_attr])*
220 pub struct $owned(*mut $ctype);
221
222 $(#[$impl_attr])*
223 impl $crate::ForeignType for $owned {
224 type CType = $ctype;
225 type Ref = $borrowed;
226
227 #[inline]
228 unsafe fn from_ptr(ptr: *mut $ctype) -> $owned {
229 $owned(ptr)
230 }
231
232 #[inline]
233 fn as_ptr(&self) -> *mut $ctype {
234 self.0
235 }
236 }
237
238 impl Drop for $owned {
239 #[inline]
240 fn drop(&mut self) {
241 unsafe { $drop(self.0) }
242 }
243 }
244
245 $(
246 impl Clone for $owned {
247 #[inline]
248 fn clone(&self) -> $owned {
249 unsafe {
250 let handle: *mut $ctype = $clone(self.0);
251 $crate::ForeignType::from_ptr(handle)
252 }
253 }
254 }
255
256 impl ::std::borrow::ToOwned for $borrowed {
257 type Owned = $owned;
258 #[inline]
259 fn to_owned(&self) -> $owned {
260 unsafe {
261 let handle: *mut $ctype = $clone($crate::ForeignTypeRef::as_ptr(self));
262 $crate::ForeignType::from_ptr(handle)
263 }
264 }
265 }
266 )*
267
268 impl ::std::ops::Deref for $owned {
269 type Target = $borrowed;
270
271 #[inline]
272 fn deref(&self) -> &$borrowed {
273 unsafe { $crate::ForeignTypeRef::from_ptr(self.0) }
274 }
275 }
276
277 impl ::std::ops::DerefMut for $owned {
278 #[inline]
279 fn deref_mut(&mut self) -> &mut $borrowed {
280 unsafe { $crate::ForeignTypeRef::from_ptr_mut(self.0) }
281 }
282 }
283
284 impl ::std::borrow::Borrow<$borrowed> for $owned {
285 #[inline]
286 fn borrow(&self) -> &$borrowed {
287 &**self
288 }
289 }
290
291 impl ::std::convert::AsRef<$borrowed> for $owned {
292 #[inline]
293 fn as_ref(&self) -> &$borrowed {
294 &**self
295 }
296 }
297
298 $(#[$borrowed_attr])*
299 pub struct $borrowed($crate::Opaque);
300
301 $(#[$impl_attr])*
302 impl $crate::ForeignTypeRef for $borrowed {
303 type CType = $ctype;
304 }
305 }
306}
307