rust: Enable C++ streams to be passed into Rust code
This commit is contained in:
parent
22d97339b2
commit
e6dd9550e1
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2020 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#ifndef ZCASH_RUST_INCLUDE_RUST_STREAMS_H
|
||||
#define ZCASH_RUST_INCLUDE_RUST_STREAMS_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef long (*read_callback_t)(void* context, unsigned char* pch, size_t nSize);
|
||||
typedef long (*write_callback_t)(void* context, const unsigned char* pch, size_t nSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ZCASH_RUST_INCLUDE_RUST_STREAMS_H
|
|
@ -66,6 +66,7 @@ use zcash_history::{Entry as MMREntry, NodeData as MMRNodeData, Tree as MMRTree}
|
|||
mod blake2b;
|
||||
mod ed25519;
|
||||
mod metrics_ffi;
|
||||
mod streams_ffi;
|
||||
mod tracing_ffi;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
use std::io;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use libc::{c_long, c_void, size_t};
|
||||
|
||||
pub type StreamObj = NonNull<c_void>;
|
||||
pub type ReadCb =
|
||||
unsafe extern "C" fn(obj: Option<StreamObj>, pch: *mut u8, size: size_t) -> c_long;
|
||||
pub type WriteCb =
|
||||
unsafe extern "C" fn(obj: Option<StreamObj>, pch: *const u8, size: size_t) -> c_long;
|
||||
|
||||
pub struct CppStreamReader {
|
||||
inner: Option<StreamObj>,
|
||||
cb: ReadCb,
|
||||
}
|
||||
|
||||
impl CppStreamReader {
|
||||
pub fn from_raw_parts(inner: Option<StreamObj>, cb: ReadCb) -> Self {
|
||||
CppStreamReader { inner, cb }
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for CppStreamReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
match unsafe { (self.cb)(self.inner, buf.as_mut_ptr(), buf.len()) } {
|
||||
-1 => Err(io::Error::new(io::ErrorKind::Other, "C++ stream error")),
|
||||
n => Ok(n as usize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CppStreamWriter {
|
||||
inner: Option<StreamObj>,
|
||||
cb: WriteCb,
|
||||
}
|
||||
|
||||
impl CppStreamWriter {
|
||||
pub fn from_raw_parts(inner: Option<StreamObj>, cb: WriteCb) -> Self {
|
||||
CppStreamWriter { inner, cb }
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for CppStreamWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match unsafe { (self.cb)(self.inner, buf.as_ptr(), buf.len()) } {
|
||||
-1 => Err(io::Error::new(io::ErrorKind::Other, "C++ stream error")),
|
||||
n => Ok(n as usize),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -22,6 +22,51 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Wrapper around C++ stream objects, enabling them to be passed into Rust code.
|
||||
*/
|
||||
template<typename Stream>
|
||||
class RustStream {
|
||||
Stream* stream;
|
||||
|
||||
public:
|
||||
RustStream(Stream& stream_) : stream(&stream_) {}
|
||||
|
||||
static long read_callback(void* context, unsigned char* pch, size_t nSize)
|
||||
{
|
||||
return reinterpret_cast<RustStream*>(context)->read(
|
||||
reinterpret_cast<char*>(pch), nSize);
|
||||
}
|
||||
|
||||
static long write_callback(void* context, const unsigned char* pch, size_t nSize)
|
||||
{
|
||||
return reinterpret_cast<RustStream*>(context)->write(
|
||||
reinterpret_cast<const char*>(pch), nSize);
|
||||
}
|
||||
|
||||
long read(char* pch, size_t nSize)
|
||||
{
|
||||
try {
|
||||
stream->read(pch, nSize);
|
||||
return nSize;
|
||||
} catch (std::ios_base::failure e) {
|
||||
// TODO: log
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long write(const char* pch, size_t nSize)
|
||||
{
|
||||
try {
|
||||
stream->write(pch, nSize);
|
||||
return nSize;
|
||||
} catch (std::ios_base::failure e) {
|
||||
// TODO: log
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Stream>
|
||||
class OverrideStream
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue