#[cfg(feature = "std")]
use std::io::{self, Write as _};
use crate as rune;
#[cfg(feature = "std")]
use crate::alloc::fmt::TryWrite;
use crate::compile;
use crate::macros::{quote, FormatArgs, MacroContext, TokenStream};
use crate::parse::Parser;
#[cfg(feature = "std")]
use crate::runtime::{Formatter, InstAddress, Memory, Output, Panic, VmResult};
use crate::{ContextError, Module};
#[rune::module(::std::io)]
pub fn module(
#[cfg_attr(not(feature = "std"), allow(unused))] stdio: bool,
) -> Result<Module, ContextError> {
let mut module = Module::from_meta(self::module_meta)?.with_unique("std::io");
module.item_mut().docs(docstring! {
})?;
#[cfg(feature = "std")]
module.ty::<io::Error>()?;
#[cfg(feature = "std")]
module.function_meta(io_error_display_fmt)?;
#[cfg(feature = "std")]
module.function_meta(io_error_debug_fmt)?;
#[cfg(feature = "std")]
if stdio {
module.function_meta(print_impl)?;
module.function_meta(println_impl)?;
module
.raw_function("dbg", dbg_impl)
.build()?
.docs(docstring! {
})?;
}
module.macro_meta(dbg_macro)?;
module.macro_meta(print_macro)?;
module.macro_meta(println_macro)?;
Ok(module)
}
#[rune::function(instance, protocol = DISPLAY_FMT)]
#[cfg(feature = "std")]
fn io_error_display_fmt(error: &io::Error, f: &mut Formatter) -> VmResult<()> {
vm_write!(f, "{error}")
}
#[rune::function(instance, protocol = DEBUG_FMT)]
#[cfg(feature = "std")]
fn io_error_debug_fmt(error: &io::Error, f: &mut Formatter) -> VmResult<()> {
vm_write!(f, "{error:?}")
}
#[cfg(feature = "std")]
fn dbg_impl(stack: &mut dyn Memory, addr: InstAddress, args: usize, out: Output) -> VmResult<()> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
for value in vm_try!(stack.slice_at(addr, args)) {
vm_try!(writeln!(stdout, "{:?}", value).map_err(Panic::custom));
}
vm_try!(out.store(stack, ()));
VmResult::Ok(())
}
#[rune::macro_(path = dbg)]
pub(crate) fn dbg_macro(
cx: &mut MacroContext<'_, '_, '_>,
stream: &TokenStream,
) -> compile::Result<TokenStream> {
Ok(quote!(::std::io::dbg(#stream)).into_token_stream(cx)?)
}
#[rune::macro_(path = print)]
pub(crate) fn print_macro(
cx: &mut MacroContext<'_, '_, '_>,
stream: &TokenStream,
) -> compile::Result<TokenStream> {
let mut p = Parser::from_token_stream(stream, cx.input_span());
let args = p.parse_all::<FormatArgs>()?;
let expanded = args.expand(cx)?;
Ok(quote!(::std::io::print(#expanded)).into_token_stream(cx)?)
}
#[rune::function(path = print)]
#[cfg(feature = "std")]
fn print_impl(m: &str) -> VmResult<()> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
if let Err(error) = write!(stdout, "{}", m) {
return VmResult::err(Panic::custom(error));
}
VmResult::Ok(())
}
#[rune::macro_(path = println)]
pub(crate) fn println_macro(
cx: &mut MacroContext<'_, '_, '_>,
stream: &TokenStream,
) -> compile::Result<TokenStream> {
let mut p = Parser::from_token_stream(stream, cx.input_span());
let args = p.parse_all::<FormatArgs>()?;
let expanded = args.expand(cx)?;
Ok(quote!(::std::io::println(#expanded)).into_token_stream(cx)?)
}
#[rune::function(path = println)]
#[cfg(feature = "std")]
fn println_impl(message: &str) -> VmResult<()> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
if let Err(error) = writeln!(stdout, "{}", message) {
return VmResult::err(Panic::custom(error));
}
VmResult::Ok(())
}