artichoke_backend/
warn.rs

1use std::fmt::Write;
2
3use spinoso_exception::IOError;
4
5use crate::Artichoke;
6use crate::core::{ModuleRegistry, TryConvertMut, Value as _, Warn};
7use crate::def::NotDefinedError;
8use crate::error::Error;
9use crate::extn::core::warning::Warning;
10use crate::ffi::InterpreterExtractError;
11use crate::fmt::WriteError;
12use crate::state::output::Output;
13
14impl Warn for Artichoke {
15    type Error = Error;
16
17    fn warn(&mut self, message: &[u8]) -> Result<(), Self::Error> {
18        let state = self.state.as_deref_mut().ok_or_else(InterpreterExtractError::new)?;
19
20        // FIXME: Avoid direct printing to stderr here.
21        //
22        // Ruby warnings should be exclusively handled by `Warning.warn` in Ruby code to avoid
23        // duplicate messages.
24        //
25        // See issue: https://github.com/artichoke/artichoke/issues/2844
26        if let Err(err) = state.output.write_stderr(b"rb warning: ") {
27            let mut message = String::from("Failed to write warning to $stderr: ");
28            write!(&mut message, "{err}").map_err(WriteError::from)?;
29            return Err(IOError::from(message).into());
30        }
31        if let Err(err) = state.output.write_stderr(message) {
32            let mut message = String::from("Failed to write warning to $stderr: ");
33            write!(&mut message, "{err}").map_err(WriteError::from)?;
34            return Err(IOError::from(message).into());
35        }
36        if let Err(err) = state.output.write_stderr(b"\n") {
37            let mut message = String::from("Failed to write warning to $stderr: ");
38            write!(&mut message, "{err}").map_err(WriteError::from)?;
39            return Err(IOError::from(message).into());
40        }
41
42        let warning = self
43            .module_of::<Warning>()?
44            .ok_or_else(|| NotDefinedError::module("Warning"))?;
45        let message = self.try_convert_mut(message)?;
46        warning.funcall(self, "warn", &[message], None)?;
47        Ok(())
48    }
49}