diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-01-29 22:57:39 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-01-29 23:48:15 +0100 |
commit | 81e1b39d2ea9ffa07f11aed3f230a7f26792058f (patch) | |
tree | 509b61e4b3e0535e82d4277e809e3023ec8cf839 /openpgp-ffi/src | |
parent | e5ee74691f21f46bdc30556a6b67ecf5f9532ece (diff) |
openpgp-ffi: Add a general writer interface.
Diffstat (limited to 'openpgp-ffi/src')
-rw-r--r-- | openpgp-ffi/src/io.rs | 42 |
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>, |