summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi/src
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-01-29 22:57:39 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-01-29 23:48:15 +0100
commit81e1b39d2ea9ffa07f11aed3f230a7f26792058f (patch)
tree509b61e4b3e0535e82d4277e809e3023ec8cf839 /openpgp-ffi/src
parente5ee74691f21f46bdc30556a6b67ecf5f9532ece (diff)
openpgp-ffi: Add a general writer interface.
Diffstat (limited to 'openpgp-ffi/src')
-rw-r--r--openpgp-ffi/src/io.rs42
1 files changed, 42 insertions, 0 deletions
diff --git a/openpgp-ffi/src/io.rs b/openpgp-ffi/src/io.rs
index f0314e19..e3488e07 100644
--- a/openpgp-ffi/src/io.rs
+++ b/openpgp-ffi/src/io.rs
@@ -228,6 +228,48 @@ impl Write for WriterAlloc {
}
}
+/// The callback type for the generic callback-based writer interface.
+type WriterCallbackFn = fn(*mut c_void, *const c_void, size_t) -> ssize_t;
+
+/// Creates an writer from a callback and cookie.
+///
+/// This writer calls the given callback to write data.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_writer_from_callback(cb: WriterCallbackFn,
+ cookie: *mut c_void)
+ -> *mut Writer {
+ let w: Box<dyn io::Write> = Box::new(WriterCallback {
+ cb, cookie,
+ });
+ w.move_into_raw()
+}
+
+/// A generic callback-based writer implementation.
+struct WriterCallback {
+ cb: WriterCallbackFn,
+ cookie: *mut c_void,
+}
+
+impl Write for WriterCallback {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ let r =
+ (self.cb)(self.cookie, buf.as_ptr() as *const c_void, buf.len());
+ if r < 0 {
+ use std::io as stdio;
+ Err(stdio::Error::new(stdio::ErrorKind::Other,
+ "Unknown error in write callback"))
+ } else {
+ Ok(r as usize)
+ }
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ // Do nothing.
+ // XXX: Should we add a callback for that?
+ Ok(())
+ }
+}
+
/// Writes up to `len` bytes of `buf` into `writer`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_writer_write(errp: Option<&mut *mut crate::error::Error>,