summaryrefslogtreecommitdiffstats
path: root/ffi/src
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-01-17 11:11:27 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-01-17 16:48:28 +0100
commit3f58832474a4b270e136544016a401ef773ac065 (patch)
treec617160250c3040ca964c1b72ab5957cd872b82f /ffi/src
parent38b4108cc1eac851ac17932c5c33623dd535bebb (diff)
openpgp-ffi: New crate.
- This creates a new crate, 'sequoia-openpgp-ffi', and moves a handful of functions from 'sequoia-ffi' to it. - The 'sequoia-ffi' crate is a superset of the 'sequoia-openpgp-ffi' crate. This is accomplished by some include! magic. - My first attempt involved having 'sequoia-ffi' depend on 'sequoia-openpgp-ffi', so that the former just re-exports the symbols. However, that turned out to be unreliable, and might be not what we want, because it could also duplicate parts of Rust's standard library. - Fixes #144.
Diffstat (limited to 'ffi/src')
-rw-r--r--ffi/src/core.rs175
-rw-r--r--ffi/src/error.rs118
-rw-r--r--ffi/src/lib.rs242
-rw-r--r--ffi/src/openpgp/armor.rs347
-rw-r--r--ffi/src/openpgp/crypto.rs54
-rw-r--r--ffi/src/openpgp/fingerprint.rs110
-rw-r--r--ffi/src/openpgp/keyid.rs99
-rw-r--r--ffi/src/openpgp/mod.rs1637
-rw-r--r--ffi/src/openpgp/packet_pile.rs93
-rw-r--r--ffi/src/openpgp/tpk.rs698
-rw-r--r--ffi/src/openpgp/tsk.rs76
11 files changed, 16 insertions, 3633 deletions
diff --git a/ffi/src/core.rs b/ffi/src/core.rs
index 915dcffc..f644dc4b 100644
--- a/ffi/src/core.rs
+++ b/ffi/src/core.rs
@@ -39,15 +39,8 @@
//! ```
use failure;
-use std::fs::File;
-use std::io::{self, Read, Write, Cursor};
-use std::path::Path;
use std::ptr;
-use std::slice;
-use libc::{uint8_t, c_void, c_char, c_int, size_t, ssize_t, realloc};
-
-#[cfg(unix)]
-use std::os::unix::io::FromRawFd;
+use libc::{uint8_t, c_char, c_int};
use sequoia_core as core;
use sequoia_core::Config;
@@ -225,169 +218,3 @@ pub extern "system" fn sq_config_ephemeral(cfg: *mut Config) {
let cfg = ffi_param_ref_mut!(cfg);
cfg.set_ephemeral();
}
-
-/* Reader and writer. */
-
-/// Opens a file returning a reader.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_reader_from_file(errp: Option<&mut *mut failure::Error>,
- filename: *const c_char)
- -> *mut Box<Read> {
- ffi_make_fry_from_errp!(errp);
- let filename = ffi_param_cstr!(filename).to_string_lossy().into_owned();
- ffi_try_box!(File::open(Path::new(&filename))
- .map(|r| Box::new(r))
- .map_err(|e| e.into()))
-}
-
-/// Opens a file descriptor returning a reader.
-#[cfg(unix)]
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_reader_from_fd(fd: c_int)
- -> *mut Box<Read> {
- box_raw!(Box::new(unsafe { File::from_raw_fd(fd) }))
-}
-
-/// Creates a reader from a buffer.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_reader_from_bytes(buf: *const uint8_t,
- len: size_t)
- -> *mut Box<Read> {
- assert!(!buf.is_null());
- let buf = unsafe {
- slice::from_raw_parts(buf, len as usize)
- };
- box_raw!(Box::new(Cursor::new(buf)))
-}
-
-/// Frees a reader.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_reader_free(reader: Option<&mut Box<Read>>) {
- ffi_free!(reader)
-}
-
-/// Reads up to `len` bytes into `buf`.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_reader_read(errp: Option<&mut *mut failure::Error>,
- reader: *mut Box<Read>,
- buf: *mut uint8_t, len: size_t)
- -> ssize_t {
- ffi_make_fry_from_errp!(errp);
- let reader = ffi_param_ref_mut!(reader);
- assert!(!buf.is_null());
- let buf = unsafe {
- slice::from_raw_parts_mut(buf, len as usize)
- };
- ffi_try_or!(reader.read(buf).map_err(|e| e.into()), -1) as ssize_t
-}
-
-
-/// Opens a file returning a writer.
-///
-/// The file will be created if it does not exist, or be truncated
-/// otherwise. If you need more control, use `sq_writer_from_fd`.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_writer_from_file(errp: Option<&mut *mut failure::Error>,
- filename: *const c_char)
- -> *mut Box<Write> {
- ffi_make_fry_from_errp!(errp);
- let filename = ffi_param_cstr!(filename).to_string_lossy().into_owned();
- ffi_try_box!(File::create(Path::new(&filename))
- .map(|r| Box::new(r))
- .map_err(|e| e.into()))
-}
-
-/// Opens a file descriptor returning a writer.
-#[cfg(unix)]
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_writer_from_fd(fd: c_int)
- -> *mut Box<Write> {
- box_raw!(Box::new(unsafe { File::from_raw_fd(fd) }))
-}
-
-/// Creates a writer from a buffer.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_writer_from_bytes(buf: *mut uint8_t,
- len: size_t)
- -> *mut Box<Write> {
- assert!(!buf.is_null());
- let buf = unsafe {
- slice::from_raw_parts_mut(buf, len as usize)
- };
- box_raw!(Box::new(Cursor::new(buf)))
-}
-
-/// Creates an allocating writer.
-///
-/// This writer allocates memory using `malloc`, and stores the
-/// pointer to the memory and the number of bytes written to the given
-/// locations `buf`, and `len`. Both must either be set to zero, or
-/// reference a chunk of memory allocated using libc's heap allocator.
-/// The caller is responsible to `free` it once the writer has been
-/// destroyed.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_writer_alloc(buf: *mut *mut c_void,
- len: *mut size_t)
- -> *mut Box<Write> {
- let buf = ffi_param_ref_mut!(buf);
- let len = ffi_param_ref_mut!(len);
-
- box_raw!(Box::new(WriterAlloc {
- buf: buf,
- len: len,
- }))
-}
-
-struct WriterAlloc {
- buf: &'static mut *mut c_void,
- len: &'static mut size_t,
-}
-
-impl Write for WriterAlloc {
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let old_len = *self.len;
- let new_len = old_len + buf.len();
-
- let new = unsafe {
- realloc(*self.buf, new_len)
- };
- if new.is_null() {
- return Err(io::Error::new(io::ErrorKind::Other, "out of memory"));
- }
-
- *self.buf = new;
- *self.len = new_len;
-
- let sl = unsafe {
- slice::from_raw_parts_mut(new as *mut u8, new_len)
- };
- &mut sl[old_len..].copy_from_slice(buf);
- Ok(buf.len())
- }
-
- fn flush(&mut self) -> io::Result<()> {
- // Do nothing.
- Ok(())
- }
-}
-
-/// Frees a writer.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_writer_free(writer: Option<&mut Box<Write>>) {
- ffi_free!(writer)
-}
-
-/// Writes up to `len` bytes of `buf` into `writer`.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_writer_write(errp: Option<&mut *mut failure::Error>,
- writer: *mut Box<Write>,
- buf: *const uint8_t, len: size_t)
- -> ssize_t {
- ffi_make_fry_from_errp!(errp);
- let writer = ffi_param_ref_mut!(writer);
- assert!(!buf.is_null());
- let buf = unsafe {
- slice::from_raw_parts(buf, len as usize)
- };
- ffi_try_or!(writer.write(buf).map_err(|e| e.into()), -1) as ssize_t
-}
diff --git a/ffi/src/error.rs b/ffi/src/error.rs
index 369cbb25..d9fb2c21 100644
--- a/ffi/src/error.rs
+++ b/ffi/src/error.rs
@@ -2,125 +2,17 @@
use failure;
use std::io;
-use libc::c_char;
extern crate sequoia_openpgp as openpgp;
use sequoia_core as core;
+pub use openpgp::error::Status;
-/// Frees an error.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_error_free(error: Option<&mut failure::Error>) {
- ffi_free!(error)
+trait FromSequoiaError<'a> {
+ fn from_sequoia_error(&'a failure::Error) -> Status;
}
-/// Returns the error message.
-///
-/// The returned value must be freed with `free(3)`.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_error_string(error: *const failure::Error)
- -> *mut c_char {
- let error = ffi_param_ref!(error);
- ffi_return_string!(&format!("{}", error))
-}
-
-/// Returns the error status code.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_error_status(error: *const failure::Error)
- -> Status {
- let error = ffi_param_ref!(error);
- error.into()
-}
-
-/// XXX: Reorder and name-space before release.
-#[derive(PartialEq, Debug)]
-#[repr(C)]
-pub enum Status {
- /// The operation was successful.
- Success = 0,
-
- /// An unknown error occurred.
- UnknownError = -1,
-
- /// The network policy was violated by the given action.
- NetworkPolicyViolation = -2,
-
- /// An IO error occurred.
- IoError = -3,
-
- /// A given argument is invalid.
- InvalidArgument = -15,
-
- /// The requested operation is invalid.
- InvalidOperation = -4,
-
- /// The packet is malformed.
- MalformedPacket = -5,
-
- /// Unsupported hash algorithm.
- UnsupportedHashAlgorithm = -9,
-
- /// Unsupported public key algorithm.
- UnsupportedPublicKeyAlgorithm = -18,
-
- /// Unsupported elliptic curve.
- UnsupportedEllipticCurve = -21,
-
- /// Unsupported symmetric algorithm.
- UnsupportedSymmetricAlgorithm = -10,
-
- /// Unsupported AEAD algorithm.
- UnsupportedAEADAlgorithm = -26,
-
- /// Unsupport signature type.
- UnsupportedSignatureType = -20,
-
- /// Invalid password.
- InvalidPassword = -11,
-
- /// Invalid session key.
- InvalidSessionKey = -12,
-
- /// Missing session key.
- MissingSessionKey = -27,
-
- /// Malformed TPK.
- MalformedTPK = -13,
-
- // XXX: -14 was UserIDNotFound.
-
- // XXX: Skipping InvalidArgument = -15.
-
- /// Malformed MPI.
- MalformedMPI = -16,
-
- // XXX: Skipping UnknownPublicKeyAlgorithm = -17.
- // XXX: Skipping UnsupportedPublicKeyAlgorithm = -18
-
- /// Bad signature.
- BadSignature = -19,
-
- /// Message has been manipulated.
- ManipulatedMessage = -25,
-
- // XXX: Skipping UnsupportedSignatureType = -20
- // XXX: Skipping UnsupportedEllipticCurve = -21
-
- /// Malformed message.
- MalformedMessage = -22,
-
- /// Index out of range.
- IndexOutOfRange = -23,
-
- /// TPK not supported.
- UnsupportedTPK = -24,
-
- // XXX: Skipping ManipulatedMessage = -25
- // XXX: Skipping UnsupportedAEADAlgorithm = -26
- // XXX: Skipping MissingSessionKey = -27
-}
-
-impl<'a> From<&'a failure::Error> for Status {
- fn from(e: &'a failure::Error) -> Self {
+impl<'a> FromSequoiaError<'a> for Status {
+ fn from_sequoia_error(e: &'a failure::Error) -> Self {
if let Some(e) = e.downcast_ref::<core::Error>() {
return match e {
&core::Error::NetworkPolicyViolation(_) =>
diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs
index 2f5f3bbe..60742680 100644
--- a/ffi/src/lib.rs
+++ b/ffi/src/lib.rs
@@ -119,136 +119,16 @@ extern crate sequoia_core;
extern crate sequoia_net;
extern crate sequoia_store;
-use std::collections::hash_map::{DefaultHasher, RandomState};
-use std::hash::BuildHasher;
-
-/* Canonical free(). */
-
-/// Transfers ownership from C to Rust, then frees the object.
-///
-/// NOP if called with NULL.
-macro_rules! ffi_free {
- ($name:ident) => {{
- if let Some(ptr) = $name {
- unsafe {
- drop(Box::from_raw(ptr))
- }
- }
- }};
-}
-
-/* Parameter handling. */
-
-/// Transfers ownership from C to Rust.
-///
-/// # Panics
-///
-/// Panics if called with NULL.
-macro_rules! ffi_param_move {
- ($name:expr) => {{
- if $name.is_null() {
- panic!("Parameter {} is NULL", stringify!($name));
- }
- unsafe {
- Box::from_raw($name)
- }
- }};
-}
-
-/// Transfers a reference from C to Rust.
-///
-/// # Panics
-///
-/// Panics if called with NULL.
-macro_rules! ffi_param_ref {
- ($name:ident) => {{
- if $name.is_null() {
- panic!("Parameter {} is NULL", stringify!($name));
- }
- unsafe {
- &*$name
- }
- }};
-}
-
-/// Transfers a mutable reference from C to Rust.
-///
-/// # Panics
-///
-/// Panics if called with NULL.
-macro_rules! ffi_param_ref_mut {
- ($name:ident) => {{
- if $name.is_null() {
- panic!("Parameter {} is NULL", stringify!($name));
- }
- unsafe {
- &mut *$name
- }
- }};
-}
-
-/// Transfers a reference to a string from C to Rust.
-///
-/// # Panics
-///
-/// Panics if called with NULL.
-macro_rules! ffi_param_cstr {
- ($name:expr) => {{
- if $name.is_null() {
- panic!("Parameter {} is NULL", stringify!($name));
- }
- unsafe {
- ::std::ffi::CStr::from_ptr($name)
- }
- }};
-}
-
-/* Return value handling. */
-
-/// Duplicates a string similar to strndup(3).
-fn strndup(src: &[u8]) -> Option<*mut libc::c_char> {
- if src.contains(&0) {
- return None;
- }
-
- let l = src.len() + 1;
- let s = unsafe {
- ::std::slice::from_raw_parts_mut(libc::malloc(l) as *mut u8, l)
- };
- &mut s[..l - 1].copy_from_slice(src);
- s[l - 1] = 0;
-
- Some(s.as_mut_ptr() as *mut libc::c_char)
-}
-
-/// Transfers a string from Rust to C, allocating it using malloc.
-///
-/// # Panics
-///
-/// Panics if the given string contains a 0.
-macro_rules! ffi_return_string {
- ($name:expr) => {{
- let string = $name;
- let bytes: &[u8] = string.as_ref();
- ::strndup(bytes).expect(
- &format!("Returned string {} contains a 0 byte.", stringify!($name))
- )
- }};
+#[macro_use]
+pub mod openpgp {
+ //! Bindings for the low-level openpgp crate.
+ include!("../../openpgp-ffi/src/common.rs");
}
-/// Transfers a string from Rust to C, allocating it using malloc.
-///
-/// # Panics
-///
-/// Does *NOT* panic if the given string contains a 0, but returns
-/// `NULL`.
-macro_rules! ffi_return_maybe_string {
- ($name:expr) => {{
- let string = $name;
- let bytes: &[u8] = string.as_ref();
- ::strndup(bytes).unwrap_or(::std::ptr::null_mut())
- }};
-}
+pub(crate) use openpgp::{
+ build_hasher,
+ strndup,
+};
/* Error handling with implicit context. */
@@ -260,110 +140,8 @@ macro_rules! ffi_make_fry_from_ctx {
}
}
-/* Error handling with implicit error return argument. */
-
-/// Emits local macros for error handling that use the given context
-/// to store complex errors.
-macro_rules! ffi_make_fry_from_errp {
- ($errp:expr) => {
- /// Like try! for ffi glue.
- ///
- /// Evaluates the given expression. On success, evaluate to
- /// `Status.Success`. On failure, stashes the error in the
- /// context and evaluates to the appropriate Status code.
- #[allow(unused_macros)]
- macro_rules! ffi_try_status {
- ($expr:expr) => {
- match $expr {
- Ok(_) => Status::Success,
- Err(e) => {
- let status = Status::from(&e);
- if let Some(errp) = $errp {
- *errp = box_raw!(e);
- }
- status
- },
- }
- };
- }
-
- /// Like try! for ffi glue.
- ///
- /// Unwraps the given expression. On failure, stashes the
- /// error in the context and returns $or.
- #[allow(unused_macros)]
- macro_rules! ffi_try_or {
- ($expr:expr, $or:expr) => {
- match $expr {
- Ok(v) => v,
- Err(e) => {
- if let Some(errp) = $errp {
- *errp = box_raw!(e);
- }
- return $or;
- },
- }
- };
- }
-
- /// Like try! for ffi glue.
- ///
- /// Unwraps the given expression. On failure, stashes the
- /// error in the context and returns NULL.
- #[allow(unused_macros)]
- macro_rules! ffi_try {
- ($expr:expr) => {
- ffi_try_or!($expr, ::std::ptr::null_mut())
- };
- }
-
- /// Like try! for ffi glue, then box into raw pointer.
- ///
- /// This is used to transfer ownership from Rust to C.
- ///
- /// Unwraps the given expression. On success, it boxes the
- /// value and turns it into a raw pointer. On failure,
- /// stashes the error in the context and returns NULL.
- #[allow(unused_macros)]
- macro_rules! ffi_try_box {
- ($expr:expr) => {
- Box::into_raw(Box::new(ffi_try!($expr)))
- }
- }
- }
-}
-
-/// Box, then turn into raw pointer.
-///
-/// This is used to transfer ownership from Rust to C.
-macro_rules! box_raw {
- ($expr:expr) => {
- Box::into_raw(Box::new($expr))
- }
-}
-
-/// Box an Option<T>, then turn into raw pointer.
-///
-/// This is used to transfer ownership from Rust to C.
-macro_rules! maybe_box_raw {
- ($expr:expr) => {
- $expr.map(|x| box_raw!(x)).unwrap_or(ptr::null_mut())
- }
-}
-
-/// Builds hashers for computing hashes.
-///
-/// This is used to derive Hasher instances for computing hashes of
-/// objects so that they can be used in hash tables by foreign code.
-pub(crate) fn build_hasher() -> DefaultHasher {
- lazy_static! {
- static ref RANDOM_STATE: RandomState = RandomState::new();
- }
- RANDOM_STATE.build_hasher()
-}
-
-pub mod error;
pub mod core;
-pub mod openpgp;
+pub mod error;
pub mod net;
pub mod store;
+
diff --git a/ffi/src/openpgp/armor.rs b/ffi/src/openpgp/armor.rs
deleted file mode 100644
index 1a42c369..00000000
--- a/ffi/src/openpgp/armor.rs
+++ /dev/null
@@ -1,347 +0,0 @@
-//! ASCII Armor.
-//!
-//! Wraps [`sequoia-openpgp::armor`].
-//!
-//! [`sequoia-openpgp::armor`]: ../../../sequoia_openpgp/armor/index.html
-
-use std::mem::size_of;
-use std::ptr;
-use std::slice;
-use std::io::{Read, Write};
-use libc::{self, uint8_t, c_char, c_int, size_t};
-
-extern crate sequoia_openpgp;
-use self::sequoia_openpgp::armor;
-
-/// Represents a (key, value) pair in an armor header.
-#[repr(C)]
-pub struct ArmorHeader {
- key: *const c_char,
- value: *const c_char,
-}
-
-fn int_to_kind(kind: c_int) -> Option<armor::Kind> {
- match kind {
- 0 => None,
- 1 => Some(armor::Kind::Message),
- 2 => Some(armor::Kind::PublicKey),
- 3 => Some(armor::Kind::SecretKey),
- 4 => Some(armor::Kind::Signature),
- 5 => Some(armor::Kind::File),
- _ => panic!("Bad kind: {}", kind),
- }
-}
-
-fn kind_to_int(kind: Option<armor::Kind>) -> c_int {
- match kind {
- None => 0,
- Some(armor::Kind::Message) => 1,
- Some(armor::Kind::PublicKey) => 2,
- Some(armor::Kind::SecretKey) => 3,
- Some(armor::Kind::Signature) => 4,
- Some(armor::Kind::File) => 5,
- }
-}
-
-/// Constructs a new filter for the given type of data.
-///
-/// A filter that strips ASCII Armor from a stream of data.
-///
-/// # Example
-///
-/// ```c
-/// #define _GNU_SOURCE
-/// #include <assert.h>
-/// #include <error.h>
-/// #include <stdio.h>
-/// #include <stdlib.h>
-/// #include <string.h>
-///
-/// #include <sequoia.h>
-///
-/// const char *armored =
-/// "-----BEGIN PGP ARMORED FILE-----\n"
-/// "Key0: Value0\n"
-/// "Key1: Value1\n"
-/// "\n"
-/// "SGVsbG8gd29ybGQh\n"
-/// "=s4Gu\n"
-/// "-----END PGP ARMORED FILE-----\n";
-///
-/// int
-/// main (int argc, char **argv)
-/// {
-/// sq_error_t err;
-/// sq_reader_t bytes;
-/// sq_reader_t armor;
-/// sq_armor_kind_t kind;
-/// char message[12];
-/// sq_armor_header_t *header;
-/// size_t header_len;
-///
-/// bytes = sq_reader_from_bytes ((uint8_t *) armored, strlen (armored));
-/// armor = sq_armor_reader_new (bytes, SQ_ARMOR_KIND_ANY);
-///
-/// header = sq_armor_reader_headers (&err, armor, &header_len);
-/// if (header == NULL)
-/// error (1, 0, "Getting headers failed: %s", sq_error_string (err));
-///
-/// assert (header_len == 2);
-/// assert (strcmp (header[0].key, "Key0") == 0
-/// && strcmp (header[0].value, "Value0") == 0);
-/// assert (strcmp (header[1].key, "Key1") == 0
-/// && strcmp (header[1].value, "Value1") == 0);
-/// for (size_t i = 0; i < header_len; i++)
-/// {
-/// free (header[i].key);
-/// free (header[i].value);
-/// }
-/// free (header);
-///
-/// kind = sq_armor_reader_kind (armor);
-/// assert (kind == SQ_ARMOR_KIND_FILE);
-///
-/// if (sq_reader_read (&err, armor, (uint8_t *) message, 12) < 0)
-/// error (1, 0, "Reading failed: %s", sq_error_string (err));
-///
-/// assert (memcmp (message, "Hello world!", 12) == 0);
-///
-/// sq_reader_free (armor);
-/// sq_reader_free (bytes);
-/// return 0;
-/// }
-/// ```
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_armor_reader_new(inner: *mut Box<Read>,
- kind: c_int)
- -> *mut Box<Read> {
- let inner = ffi_param_ref_mut!(inner);
- let kind = int_to_kind(kind);
-
- box_raw!(Box::new(armor::Reader::new(inner, kind)))
-}
-
-/// Creates a `Reader` from a file.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_armor_reader_from_file(errp: Option<&mut *mut failure::Error>,
- filename: *const c_char,
- kind: c_int)
- -> *mut Box<Read> {
- ffi_make_fry_from_errp!(errp);
- let filename = ffi_param_cstr!(filename).to_string_lossy().into_owned();
- let kind = int_to_kind(kind);
-
- ffi_try_box!(armor::Reader::from_file(&filename, kind)
- .map(|r| Box::new(r))
- .map_err(|e| e.into()))
-}
-
-/// Creates a `Reader` from a buffer.
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_armor_reader_from_bytes(b: *const uint8_t, len: size_t,
- kind: c_int)
- -> *mut Box<Read> {
- assert!(!b.is_null());
- let buf = unsafe {
- slice::from_raw_parts(b, len as usize)
- };
- let kind = int_to_kind(kind);
-
- box_raw!(Box::new(armor::Reader::from_bytes(buf, kind)))
-}
-
-/// Returns the kind of data this reader is for.
-///
-/// Useful if the kind of data is not known in advance. If the header
-/// has not been encountered yet (try reading some data first!), this
-/// function returns SQ_ARMOR_KIND_ANY.
-///
-/// # Example
-///
-/// See [this] example.
-///
-/// [this]: fn.sq_armor_reader_new.html
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_armor_reader_kind(reader: *mut Box<Read>)
- -> c_int {
- // We need to downcast `reader`. To do that, we need to do a
- // little dance. We will momentarily take ownership of `reader`,
- // wrapping it in a Box again. Then, at the end of the function,
- // we will leak it again.
- let reader = ffi_param_move!(reader as *mut Box<armor::Reader>);
- let kind = kind_to_int(reader.kind());
- Box::into_raw(reader);
- kind
-}
-
-/// Returns the armored headers.
-///
-/// The tuples contain a key and a value.
-///
-/// Note: if a key occurs multiple times, then there are multiple
-/// entries in the vector with the same key; values with the same
-/// key are *not* combined.
-///
-/// The returned array and the strings in the headers have been
-/// allocated with `malloc`, and the caller is responsible for freeing
-/// both the array and the strings.
-///
-/// # Example
-///
-/// See [this] example.
-///
-/// [this]: fn.sq_armor_reader_new.html
-#[::ffi_catch_abort] #[no_mangle]
-pub extern "system" fn sq_armor_reader_headers(errp: Option<&mut *mut failure::Error>,
- reader: *mut Box<Read>,
- len: *mut size_t)
- -> *mut ArmorHeader {
- ffi_make_fry_from_errp!(errp);
- let len = ffi_param_ref_mut!(len);
-
- // We need to downcast `reade