use std::sync::Arc;
use crate::{SafeRawTerminal, SendRawTerminal, StdMutex};
pub type LockedOutputDevice<'a> = &'a mut dyn std::io::Write;
#[macro_export]
macro_rules! lock_output_device_as_mut {
($device:expr) => {
&mut *$device.lock()
};
}
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct OutputDevice {
pub resource: SafeRawTerminal,
pub is_mock: bool,
}
impl Default for OutputDevice {
fn default() -> Self { Self::new_stdout() }
}
impl OutputDevice {
#[must_use]
pub fn new_stdout() -> Self {
Self {
resource: Arc::new(StdMutex::new(std::io::stdout())),
is_mock: false,
}
}
#[must_use]
pub fn new_stderr() -> Self {
Self {
resource: Arc::new(StdMutex::new(std::io::stderr())),
is_mock: false,
}
}
}
impl OutputDevice {
pub fn lock(&self) -> std::sync::MutexGuard<'_, SendRawTerminal> {
self.resource.lock().unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stdout_output_device() {
let output_device = OutputDevice::new_stdout();
let mut_ref: LockedOutputDevice<'_> = lock_output_device_as_mut!(output_device);
mut_ref.write_all(b"Hello, world!\n").ok();
assert!(!output_device.is_mock);
}
#[test]
fn test_stdout_output_device_is_not_mock() {
let device = OutputDevice::new_stdout();
assert!(!device.is_mock);
}
}