1#[cfg(feature = "thread")]
4use crate::thread::{ReentrantMutex, ReentrantMutexGuard};
5use core::fmt::{self, Arguments};
6#[cfg(not(feature = "thread"))]
7use core::marker::PhantomData;
8
9pub type Error = rustix::io::Errno;
10
11pub type Result<T> = core::result::Result<T, Error>;
12
13pub trait Read {
14 fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
15
16 fn is_read_vectored(&self) -> bool {
17 false
18 }
19}
20
21pub trait Write {
22 fn write(&mut self, buf: &[u8]) -> Result<usize>;
23
24 fn is_write_vectored(&self) -> bool {
25 false
26 }
27
28 fn flush(&mut self) -> Result<()>;
29
30 fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
31 while !buf.is_empty() {
32 match self.write(buf) {
33 Ok(n) => buf = &buf[n..],
34 Err(Error::INTR) => {}
35 Err(err) => return Err(err),
36 }
37 }
38 Ok(())
39 }
40
41 fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()> {
42 struct Adapter<'a, T: ?Sized + 'a> {
45 inner: &'a mut T,
46 error: Result<()>,
47 }
48
49 impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
50 fn write_str(&mut self, s: &str) -> fmt::Result {
51 match self.inner.write_all(s.as_bytes()) {
52 Ok(()) => Ok(()),
53 Err(e) => {
54 self.error = Err(e);
55 Err(fmt::Error)
56 }
57 }
58 }
59 }
60
61 let mut output = Adapter {
62 inner: self,
63 error: Ok(()),
64 };
65 match fmt::write(&mut output, fmt) {
66 Ok(()) => Ok(()),
67 Err(..) => {
68 if output.error.is_err() {
70 output.error
71 } else {
72 Err(Error::IO)
73 }
74 }
75 }
76 }
77}
78
79pub struct StdoutLock<'a> {
80 #[cfg(feature = "thread")]
81 _lock: ReentrantMutexGuard<'a, ()>,
82
83 #[cfg(not(feature = "thread"))]
84 _phantom: PhantomData<&'a ()>,
85}
86
87#[cfg(feature = "thread")]
88static STDOUT_LOCK: ReentrantMutex<()> = ReentrantMutex::new(());
89
90pub struct Stdout(());
91
92pub fn stdout() -> Stdout {
93 Stdout(())
94}
95
96impl Stdout {
97 pub fn lock(&self) -> StdoutLock<'static> {
98 StdoutLock {
99 #[cfg(feature = "thread")]
100 _lock: STDOUT_LOCK.lock(),
101
102 #[cfg(not(feature = "thread"))]
103 _phantom: PhantomData,
104 }
105 }
106}
107
108impl Write for Stdout {
109 #[cfg_attr(feature = "std", allow(unused_unsafe))]
110 fn write(&mut self, buf: &[u8]) -> Result<usize> {
111 rustix::io::write(unsafe { rustix::stdio::stdout() }, buf)
112 }
113
114 fn flush(&mut self) -> Result<()> {
115 Ok(())
116 }
117}
118
119impl<'a> Write for StdoutLock<'a> {
120 fn write(&mut self, buf: &[u8]) -> Result<usize> {
121 Stdout(()).write(buf)
122 }
123
124 fn flush(&mut self) -> Result<()> {
125 Stdout(()).flush()
126 }
127}
128
129impl core::fmt::Write for Stdout {
130 fn write_str(&mut self, s: &str) -> core::fmt::Result {
131 match self.write_all(s.as_bytes()) {
132 Ok(_) => Ok(()),
133 Err(err) => panic!("failed printing to stdout: {:?}", err),
134 }
135 }
136}
137
138impl<'a> core::fmt::Write for StdoutLock<'a> {
139 fn write_str(&mut self, s: &str) -> core::fmt::Result {
140 Stdout(()).write_str(s)
141 }
142}
143
144pub struct StderrLock<'a> {
145 #[cfg(feature = "thread")]
146 _lock: ReentrantMutexGuard<'a, ()>,
147
148 #[cfg(not(feature = "thread"))]
149 _phantom: PhantomData<&'a ()>,
150}
151
152#[cfg(feature = "thread")]
153static STDERR_LOCK: ReentrantMutex<()> = ReentrantMutex::new(());
154
155pub struct Stderr(());
156
157pub fn stderr() -> Stderr {
158 Stderr(())
159}
160
161impl Stderr {
162 pub fn lock(&self) -> StderrLock<'static> {
163 StderrLock {
164 #[cfg(feature = "thread")]
165 _lock: STDERR_LOCK.lock(),
166
167 #[cfg(not(feature = "thread"))]
168 _phantom: PhantomData,
169 }
170 }
171}
172
173impl Write for Stderr {
174 #[cfg_attr(feature = "std", allow(unused_unsafe))]
175 fn write(&mut self, buf: &[u8]) -> Result<usize> {
176 rustix::io::write(unsafe { rustix::stdio::stderr() }, buf)
177 }
178
179 fn flush(&mut self) -> Result<()> {
180 Ok(())
181 }
182}
183
184impl<'a> Write for StderrLock<'a> {
185 fn write(&mut self, buf: &[u8]) -> Result<usize> {
186 Stderr(()).write(buf)
187 }
188
189 fn flush(&mut self) -> Result<()> {
190 Stderr(()).flush()
191 }
192}
193
194impl core::fmt::Write for Stderr {
195 fn write_str(&mut self, s: &str) -> core::fmt::Result {
196 match self.write_all(s.as_bytes()) {
197 Ok(_) => Ok(()),
198 Err(err) => panic!("failed printing to stderr: {:?}", err),
199 }
200 }
201}
202
203impl<'a> core::fmt::Write for StderrLock<'a> {
204 fn write_str(&mut self, s: &str) -> core::fmt::Result {
205 Stderr(()).write_str(s)
206 }
207}
208
209pub trait Seek {
210 fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
211
212 fn rewind(&mut self) -> Result<()> {
213 self.seek(SeekFrom::Start(0))?;
214 Ok(())
215 }
216
217 fn stream_position(&mut self) -> Result<u64> {
218 self.seek(SeekFrom::Current(0))
219 }
220}
221
222#[derive(Copy, Clone, Eq, PartialEq, Debug)]
223pub enum SeekFrom {
224 Start(u64),
225 End(i64),
226 Current(i64),
227}