rune/modules/
capture_io.rsuse core::mem::take;
use ::rust_alloc::sync::Arc;
use parking_lot::Mutex;
use crate as rune;
use crate::alloc::fmt::TryWrite;
use crate::alloc::string::FromUtf8Error;
use crate::alloc::{String, Vec};
use crate::runtime::{InstAddress, Memory, Output, VmError, VmResult};
use crate::{ContextError, Module, Value};
#[rune::module(::std::io)]
pub fn module(io: &CaptureIo) -> Result<Module, ContextError> {
let mut module = Module::from_meta(self::module_meta)?;
let o = io.clone();
module
.function("print", move |m: &str| {
match write!(o.inner.lock(), "{}", m) {
Ok(()) => VmResult::Ok(()),
Err(error) => VmResult::panic(error),
}
})
.build()?;
let o = io.clone();
module
.function("println", move |m: &str| {
match writeln!(o.inner.lock(), "{}", m) {
Ok(()) => VmResult::Ok(()),
Err(error) => VmResult::panic(error),
}
})
.build()?;
let o = io.clone();
module
.raw_function("dbg", move |stack, addr, args, output| {
let mut o = o.inner.lock();
dbg_impl(&mut o, stack, addr, args, output)
})
.build()?;
Ok(module)
}
#[derive(Default, Clone)]
pub struct CaptureIo {
inner: Arc<Mutex<Vec<u8>>>,
}
impl CaptureIo {
pub fn new() -> Self {
Self::default()
}
pub fn is_empty(&self) -> bool {
self.inner.lock().is_empty()
}
pub fn drain(&self) -> Vec<u8> {
let mut o = self.inner.lock();
take(&mut *o)
}
cfg_std! {
pub fn drain_into<O>(&self, mut out: O) -> std::io::Result<()>
where
O: std::io::Write,
{
let mut o = self.inner.lock();
out.write_all(o.as_slice())?;
o.clear();
Ok(())
}
}
pub fn drain_utf8(&self) -> Result<String, FromUtf8Error> {
String::from_utf8(self.drain())
}
}
fn dbg_impl(
o: &mut Vec<u8>,
stack: &mut dyn Memory,
addr: InstAddress,
args: usize,
out: Output,
) -> VmResult<()> {
for value in vm_try!(stack.slice_at(addr, args)) {
vm_try!(writeln!(o, "{:?}", value).map_err(VmError::panic));
}
vm_try!(out.store(stack, Value::unit));
VmResult::Ok(())
}