artichoke_backend/state/
output.rs1use std::fmt;
2use std::io::{self, Write};
3
4use bstr::BString;
5
6#[cfg(all(not(feature = "output-strategy-capture"), not(feature = "output-strategy-null")))]
7pub type Strategy = Process;
8#[cfg(all(feature = "output-strategy-capture", not(feature = "output-strategy-null")))]
9pub type Strategy = Captured;
10#[cfg(all(feature = "output-strategy-capture", feature = "output-strategy-null"))]
11pub type Strategy = Null;
12
13pub trait Output: Send + Sync + fmt::Debug {
14 fn write_stdout<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()>;
15
16 fn write_stderr<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()>;
17
18 fn print<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
19 self.write_stdout(bytes)?;
20 Ok(())
21 }
22
23 fn puts<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
24 self.write_stdout(bytes)?;
25 self.write_stdout(b"\n")?;
26 Ok(())
27 }
28}
29
30#[derive(Default, Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
31pub struct Process {
32 _private: (),
33}
34
35impl Process {
36 #[must_use]
38 pub const fn new() -> Self {
39 Self { _private: () }
40 }
41}
42
43impl Output for Process {
44 fn write_stdout<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
45 io::stdout().write_all(bytes.as_ref())
46 }
47
48 fn write_stderr<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
49 io::stderr().write_all(bytes.as_ref())
50 }
51}
52
53#[derive(Default, Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
54pub struct Captured {
55 stdout: BString,
56 stderr: BString,
57}
58
59impl Captured {
60 #[must_use]
62 pub const fn new() -> Self {
63 Self {
64 stdout: BString::new(vec![]),
65 stderr: BString::new(vec![]),
66 }
67 }
68
69 pub fn clear(&mut self) {
70 self.stdout.clear();
71 self.stderr.clear();
72 }
73
74 #[must_use]
75 pub fn stdout(&self) -> &[u8] {
76 self.stdout.as_slice()
77 }
78
79 #[must_use]
80 pub fn stderr(&self) -> &[u8] {
81 self.stderr.as_slice()
82 }
83}
84
85impl Output for Captured {
86 fn write_stdout<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
87 self.stdout.extend_from_slice(bytes.as_ref());
88 Ok(())
89 }
90
91 fn write_stderr<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
92 self.stderr.extend_from_slice(bytes.as_ref());
93 Ok(())
94 }
95}
96
97impl Output for &'_ mut Captured {
98 fn write_stdout<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
99 self.stdout.extend_from_slice(bytes.as_ref());
100 Ok(())
101 }
102
103 fn write_stderr<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
104 self.stderr.extend_from_slice(bytes.as_ref());
105 Ok(())
106 }
107}
108
109#[derive(Default, Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
110pub struct Null {
111 _private: (),
112}
113
114impl Null {
115 #[must_use]
117 pub const fn new() -> Self {
118 Self { _private: () }
119 }
120}
121
122impl Output for Null {
123 fn write_stdout<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
124 drop(bytes);
125 Ok(())
126 }
127
128 fn write_stderr<T: AsRef<[u8]>>(&mut self, bytes: T) -> io::Result<()> {
129 drop(bytes);
130 Ok(())
131 }
132}