summaryrefslogtreecommitdiffstats
path: root/ffi/src/lib.rs
blob: 745ca6c8e8712eeae767f8ff7f64ba54472d39ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! Provides a Foreign Function Interface.
//!
//! We provide a set of functions that use C types and the C calling
//! convention.  This interfaces allows you to use Sequoia safely from
//! any other language.
//!
//! # Guarantees
//!
//! Provided that the caller obeys her side of the contract, this
//! library...
//!
//!  - will not make an invalid memory access,
//!  - will not `abort(2)`,
//!  - XXX
//!
//! # Types
//!
//! Sequoia objects are opaque objects.  They are created in
//! constructors, and must be freed when no longer needed.
//!
//! Pointers handed to Sequoia must not be `NULL`, unless explicitly
//! stated.  See [references].
//!
//! [references]: #references
//!
//! Enumeration-like values must be in the valid range.
//!
//! Strings must be UTF-8 encoded and zero-terminated.  Malformed
//! characters will be substituted, and the result is likely not what
//! you expect.
//!
//! # Ownership
//!
//! When ownership of a `T` is transferred across the FFI boundary, a
//! `*mut T` is used.
//!
//! To transfer ownership from Rust to C, we box the Rust object, and
//! use [`Box::into_raw(..)`].  From this moment on, ownership must be
//! managed by the C application.
//!
//! [`Box::into_raw(..)`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.into_raw
//!
//! To transfer ownership from C to Rust, we re-create the box using
//! [`Box::from_raw(..)`].
//!
//! [`Box::from_raw(..)`]: https://doc.rust-lang.org/std/boxed/struct.Box.html#method.from_raw
//!
//! In this crate we use a series of macros to transfer ownership from
//! Rust to C.  `fry_box` matches on `Result<T>`, handling errors by
//! terminating the current function, returning the error using the
//! context.  `maybe_box_raw` matches on `Option<T>`, turning `None`
//! into `NULL`.  Finally, `box_raw` is merely a shortcut for
//! `Box::into_raw(Box::new(..))`.
//!
//! # References
//!
//! When references are transferred across the FFI boundary, we use
//! `*const T`, or `*mut T`.  If the parameter is optional, a
//! `Option<&T>` or `Option<&mut T>` is used.
//!
//! Application code must adhere to Rust's reference rules:
//!
//!  - Either one mutable reference or any number of immutable ones.
//!  - All references are non-`NULL`.
//!  - All references are valid.
//!
//! In this crate we enforce the second rule by asserting that all
//! pointers handed in are non-`NULL`.  If a parameter of an FFI
//! function uses `Option<&T>` or `Option<&mut T>`, it may be called
//! with `NULL`.  A notable example are the destructors (`sq_*_free`).
//!
//! # Lifetimes
//!
//! If you derive a complex object from another complex object, you
//! must assume that the original object is borrowed by the resulting
//! object unless explicitly stated otherwise.  For example, objects
//! created using a context must not outlive that context.  Similarly,
//! iterators must not outlive the object they are created from.
//!
//! Failing to adhere to lifetime restrictions results in undefined
//! behavior.
//!
//! # Error handling
//!
//! Sequoia will panic if you provide bad arguments, e.g. hand a
//! `NULL` pointer to a function that does not explicitly allow this.
//!
//! Failing functions return `NULL`.  Functions that require a
//! `Context` return complex errors.  Complex errors are stored in the
//! `Context`, and can be retrieved using `sq_last_strerror`.
//!
//! # Examples
//!
//! ```c
//! #include <sequoia.h>
//! #include <error.h>
//!
//! pgp_error_t err;
//! pgp_cert_t cert;
//!
//! cert = pgp_cert_from_file (&err, "../openpgp/tests/data/keys/testy.pgp");
//! if (cert == NULL)
//!   error (1, 0, "pgp_cert_from_bytes: %s", pgp_error_to_string (err));
//!
//! pgp_cert_free (cert);
//! ```

#![warn(missing_docs)]

use sequoia_ffi_macros;
use sequoia_ffi_macros::{
    ffi_wrapper_type,
};

#[macro_use]
pub mod openpgp {
    //! Bindings for the low-level openpgp crate.
    include!("../../openpgp-ffi/src/common.rs");
}

pub(crate) use crate::openpgp::{
    io,
    build_hasher,
    strndup,
    MoveFromRaw,
    RefRaw,
    RefMutRaw,
    MoveIntoRaw,
    MoveResultIntoRaw,
    Maybe,
    maybe_time,
    to_time_t,
};

/* Error handling with implicit context.  */

/// Emits local macros for error handling that use the given context
/// to store complex errors.
macro_rules! ffi_make_fry_from_ctx {
    ($ctx:ident) => {
        ffi_make_fry_from_errp!(Some($ctx.errp()))
    }
}

pub mod core;
pub mod error;
pub mod net;
pub mod store;