summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi/src
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-02-04 16:51:27 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-02-05 11:42:51 +0100
commit8d662becb65d3da9439a7fe1445ed6335d5637bf (patch)
treead5db8d1a86c8d56be891b2bbd532ae48d023d64 /openpgp-ffi/src
parent37831e50a7b0a88da65061f7baf6685effe81c3d (diff)
openpgp-ffi: Specialize armor writers.
Diffstat (limited to 'openpgp-ffi/src')
-rw-r--r--openpgp-ffi/src/armor.rs5
-rw-r--r--openpgp-ffi/src/io.rs48
2 files changed, 40 insertions, 13 deletions
diff --git a/openpgp-ffi/src/armor.rs b/openpgp-ffi/src/armor.rs
index f0da2905..c4f428e4 100644
--- a/openpgp-ffi/src/armor.rs
+++ b/openpgp-ffi/src/armor.rs
@@ -7,13 +7,12 @@
use std::mem::size_of;
use std::ptr;
use std::slice;
-use std::io;
use libc::{self, c_char, c_int, size_t};
extern crate sequoia_openpgp;
use self::sequoia_openpgp::armor;
-use super::io::{Reader, ReaderKind};
+use super::io::{Reader, ReaderKind, WriterKind};
use crate::Maybe;
use crate::MoveIntoRaw;
use crate::MoveResultIntoRaw;
@@ -386,7 +385,7 @@ pub extern "C" fn pgp_armor_writer_new
header_.iter().map(|h| (h.0.as_ref(), h.1.as_ref())).collect();
armor::Writer::new(inner, kind, &header)
- .map(|w| -> Box<dyn io::Write> { Box::new(w) })
+ .map(|w| WriterKind::Armored(w))
.map_err(|e| ::failure::Error::from(e))
.move_into_raw(errp)
}
diff --git a/openpgp-ffi/src/io.rs b/openpgp-ffi/src/io.rs
index afa3a74e..c9e96557 100644
--- a/openpgp-ffi/src/io.rs
+++ b/openpgp-ffi/src/io.rs
@@ -174,7 +174,35 @@ pub extern "C" fn pgp_reader_discard(errp: Option<&mut *mut crate::error::Error>
/// Wraps a generic writer.
#[crate::ffi_wrapper_type(prefix = "pgp_")]
-pub struct Writer(Box<dyn io::Write>);
+pub struct Writer(WriterKind);
+
+/// Specializes writers.
+///
+/// In some cases, we want to call functions on concrete types. To
+/// avoid nasty hacks, we have specialized variants for that.
+pub(crate) enum WriterKind {
+ Generic(Box<dyn io::Write>),
+ Armored(openpgp::armor::Writer<&'static mut WriterKind>),
+}
+
+impl Write for WriterKind {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ use self::WriterKind::*;
+ match self {
+ Generic(w) => w.write(buf),
+ Armored(w) => w.write(buf),
+ }
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ use self::WriterKind::*;
+ match self {
+ Generic(ref mut w) => w.flush(),
+ Armored(ref mut w) => w.flush(),
+ }
+ }
+}
+
/// Opens a file returning a writer.
///
@@ -186,7 +214,7 @@ fn pgp_writer_from_file(errp: Option<&mut *mut crate::error::Error>,
-> Maybe<Writer> {
let filename = ffi_param_cstr!(filename).to_string_lossy().into_owned();
File::create(Path::new(&filename))
- .map(|w| -> Box<dyn io::Write> { Box::new(w) })
+ .map(|w| WriterKind::Generic(Box::new(w)))
.map_err(|e| ::failure::Error::from(e))
.move_into_raw(errp)
}
@@ -195,8 +223,9 @@ fn pgp_writer_from_file(errp: Option<&mut *mut crate::error::Error>,
#[cfg(unix)]
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_writer_from_fd(fd: c_int) -> *mut Writer {
- let w: Box<dyn io::Write> = Box::new(unsafe { File::from_raw_fd(fd) });
- w.move_into_raw()
+ WriterKind::Generic(Box::new(unsafe {
+ File::from_raw_fd(fd)
+ })).move_into_raw()
}
/// Creates a writer from a buffer.
@@ -206,8 +235,7 @@ fn pgp_writer_from_bytes(buf: *mut u8, len: size_t) -> *mut Writer {
let buf = unsafe {
slice::from_raw_parts_mut(buf, len as usize)
};
- let w: Box<dyn io::Write> = Box::new(Cursor::new(buf));
- w.move_into_raw()
+ WriterKind::Generic(Box::new(Cursor::new(buf))).move_into_raw()
}
/// Creates an allocating writer.
@@ -224,10 +252,10 @@ fn pgp_writer_alloc(buf: *mut *mut c_void, len: *mut size_t)
let buf = ffi_param_ref_mut!(buf);
let len = ffi_param_ref_mut!(len);
- let w: Box<dyn io::Write> = Box::new(WriterAlloc {
+ let w = WriterKind::Generic(Box::new(WriterAlloc {
buf: buf,
len: len,
- });
+ }));
w.move_into_raw()
}
@@ -274,9 +302,9 @@ type WriterCallbackFn = fn(*mut c_void, *const c_void, size_t) -> ssize_t;
fn pgp_writer_from_callback(cb: WriterCallbackFn,
cookie: *mut c_void)
-> *mut Writer {
- let w: Box<dyn io::Write> = Box::new(WriterCallback {
+ let w = WriterKind::Generic(Box::new(WriterCallback {
cb, cookie,
- });
+ }));
w.move_into_raw()
}