Skip to content

Commit d59730c

Browse files
committed
feat: Implement RawStream for more types
1 parent 5066a91 commit d59730c

File tree

3 files changed

+145
-196
lines changed

3 files changed

+145
-196
lines changed

crates/anstream/src/stream.rs

Lines changed: 112 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -11,109 +11,78 @@ pub trait RawStream:
1111
{
1212
}
1313

14+
impl<T: RawStream + ?Sized> RawStream for &mut T {}
15+
impl<T: RawStream + ?Sized> RawStream for Box<T> {}
16+
17+
impl RawStream for dyn std::io::Write {}
18+
impl RawStream for dyn std::io::Write + Send {}
19+
impl RawStream for dyn std::io::Write + Send + Sync {}
20+
1421
impl RawStream for std::io::Stdout {}
1522

1623
impl RawStream for std::io::StdoutLock<'_> {}
1724

18-
impl RawStream for &'_ mut std::io::StdoutLock<'_> {}
19-
2025
impl RawStream for std::io::Stderr {}
2126

2227
impl RawStream for std::io::StderrLock<'_> {}
2328

24-
impl RawStream for &'_ mut std::io::StderrLock<'_> {}
25-
26-
impl RawStream for Box<dyn std::io::Write> {}
27-
28-
impl RawStream for &'_ mut Box<dyn std::io::Write> {}
29-
3029
impl RawStream for Vec<u8> {}
3130

32-
impl RawStream for &'_ mut Vec<u8> {}
33-
3431
impl RawStream for std::fs::File {}
3532

36-
impl RawStream for &'_ mut std::fs::File {}
37-
3833
#[allow(deprecated)]
3934
impl RawStream for crate::Buffer {}
4035

41-
#[allow(deprecated)]
42-
impl RawStream for &'_ mut crate::Buffer {}
43-
4436
/// Trait to determine if a descriptor/handle refers to a terminal/tty.
4537
pub trait IsTerminal: private::Sealed {
4638
/// Returns `true` if the descriptor/handle refers to a terminal/tty.
4739
fn is_terminal(&self) -> bool;
4840
}
4941

50-
impl IsTerminal for std::io::Stdout {
42+
impl<T: IsTerminal + ?Sized> IsTerminal for &T {
5143
#[inline]
5244
fn is_terminal(&self) -> bool {
53-
is_terminal_polyfill::IsTerminal::is_terminal(self)
45+
T::is_terminal(&**self)
5446
}
5547
}
56-
57-
impl IsTerminal for std::io::StdoutLock<'_> {
48+
impl<T: IsTerminal + ?Sized> IsTerminal for &mut T {
5849
#[inline]
5950
fn is_terminal(&self) -> bool {
60-
is_terminal_polyfill::IsTerminal::is_terminal(self)
51+
T::is_terminal(&**self)
6152
}
6253
}
63-
64-
impl IsTerminal for &'_ mut std::io::StdoutLock<'_> {
54+
impl<T: IsTerminal + ?Sized> IsTerminal for Box<T> {
6555
#[inline]
6656
fn is_terminal(&self) -> bool {
67-
(**self).is_terminal()
57+
T::is_terminal(&**self)
6858
}
6959
}
7060

71-
impl IsTerminal for std::io::Stderr {
61+
impl IsTerminal for std::io::Stdout {
7262
#[inline]
7363
fn is_terminal(&self) -> bool {
7464
is_terminal_polyfill::IsTerminal::is_terminal(self)
7565
}
7666
}
7767

78-
impl IsTerminal for std::io::StderrLock<'_> {
68+
impl IsTerminal for std::io::StdoutLock<'_> {
7969
#[inline]
8070
fn is_terminal(&self) -> bool {
8171
is_terminal_polyfill::IsTerminal::is_terminal(self)
8272
}
8373
}
8474

85-
impl IsTerminal for &'_ mut std::io::StderrLock<'_> {
86-
#[inline]
87-
fn is_terminal(&self) -> bool {
88-
(**self).is_terminal()
89-
}
90-
}
91-
92-
impl IsTerminal for Box<dyn std::io::Write> {
93-
#[inline]
94-
fn is_terminal(&self) -> bool {
95-
false
96-
}
97-
}
98-
99-
impl IsTerminal for &'_ mut Box<dyn std::io::Write> {
100-
#[inline]
101-
fn is_terminal(&self) -> bool {
102-
false
103-
}
104-
}
105-
106-
impl IsTerminal for Vec<u8> {
75+
impl IsTerminal for std::io::Stderr {
10776
#[inline]
10877
fn is_terminal(&self) -> bool {
109-
false
78+
is_terminal_polyfill::IsTerminal::is_terminal(self)
11079
}
11180
}
11281

113-
impl IsTerminal for &'_ mut Vec<u8> {
82+
impl IsTerminal for std::io::StderrLock<'_> {
11483
#[inline]
11584
fn is_terminal(&self) -> bool {
116-
false
85+
is_terminal_polyfill::IsTerminal::is_terminal(self)
11786
}
11887
}
11988

@@ -124,28 +93,28 @@ impl IsTerminal for std::fs::File {
12493
}
12594
}
12695

127-
impl IsTerminal for &'_ mut std::fs::File {
128-
#[inline]
129-
fn is_terminal(&self) -> bool {
130-
(**self).is_terminal()
131-
}
132-
}
133-
134-
#[allow(deprecated)]
135-
impl IsTerminal for crate::Buffer {
136-
#[inline]
137-
fn is_terminal(&self) -> bool {
138-
false
139-
}
96+
macro_rules! impl_default_is_terminal {
97+
($( $(#[$attr:meta])* $t:ty),* $(,)?) => {
98+
$(
99+
$(#[$attr])*
100+
impl IsTerminal for $t {
101+
#[inline]
102+
fn is_terminal(&self) -> bool {
103+
false
104+
}
105+
}
106+
)*
107+
};
140108
}
141109

142-
#[allow(deprecated)]
143-
impl IsTerminal for &'_ mut crate::Buffer {
144-
#[inline]
145-
fn is_terminal(&self) -> bool {
146-
(**self).is_terminal()
147-
}
148-
}
110+
impl_default_is_terminal!(
111+
dyn std::io::Write,
112+
dyn std::io::Write + Send,
113+
dyn std::io::Write + Send + Sync,
114+
Vec<u8>,
115+
#[allow(deprecated)]
116+
crate::Buffer,
117+
);
149118

150119
/// Lock a stream
151120
pub trait AsLockedWrite: private::Sealed {
@@ -158,109 +127,124 @@ pub trait AsLockedWrite: private::Sealed {
158127
fn as_locked_write(&mut self) -> Self::Write<'_>;
159128
}
160129

161-
impl AsLockedWrite for std::io::Stdout {
162-
type Write<'w> = std::io::StdoutLock<'w>;
130+
impl<T: AsLockedWrite + ?Sized> AsLockedWrite for &mut T {
131+
type Write<'w>
132+
= <T as AsLockedWrite>::Write<'w>
133+
where
134+
Self: 'w;
163135

164136
#[inline]
165137
fn as_locked_write(&mut self) -> Self::Write<'_> {
166-
self.lock()
138+
T::as_locked_write(&mut **self)
167139
}
168140
}
169-
170-
impl AsLockedWrite for std::io::StdoutLock<'static> {
171-
type Write<'w> = &'w mut Self;
141+
impl<T: AsLockedWrite + ?Sized> AsLockedWrite for Box<T> {
142+
type Write<'w>
143+
= <T as AsLockedWrite>::Write<'w>
144+
where
145+
Self: 'w;
172146

173147
#[inline]
174148
fn as_locked_write(&mut self) -> Self::Write<'_> {
175-
self
149+
T::as_locked_write(&mut **self)
176150
}
177151
}
178152

179-
impl AsLockedWrite for std::io::Stderr {
180-
type Write<'w> = std::io::StderrLock<'w>;
153+
impl AsLockedWrite for std::io::Stdout {
154+
type Write<'w> = std::io::StdoutLock<'w>;
181155

182156
#[inline]
183157
fn as_locked_write(&mut self) -> Self::Write<'_> {
184158
self.lock()
185159
}
186160
}
187161

188-
impl AsLockedWrite for std::io::StderrLock<'static> {
189-
type Write<'w> = &'w mut Self;
190-
191-
#[inline]
192-
fn as_locked_write(&mut self) -> Self::Write<'_> {
193-
self
194-
}
195-
}
196-
197-
impl AsLockedWrite for Box<dyn std::io::Write> {
198-
type Write<'w> = &'w mut Self;
199-
200-
#[inline]
201-
fn as_locked_write(&mut self) -> Self::Write<'_> {
202-
self
203-
}
204-
}
205-
206-
impl AsLockedWrite for Vec<u8> {
207-
type Write<'w> = &'w mut Self;
162+
impl AsLockedWrite for std::io::Stderr {
163+
type Write<'w> = std::io::StderrLock<'w>;
208164

209165
#[inline]
210166
fn as_locked_write(&mut self) -> Self::Write<'_> {
211-
self
167+
self.lock()
212168
}
213169
}
214170

215-
impl AsLockedWrite for std::fs::File {
216-
type Write<'w> = &'w mut Self;
171+
macro_rules! impl_default_locked_write {
172+
($( $(#[$attr:meta])* $t:ty),* $(,)?) => {
173+
$(
174+
$(#[$attr])*
175+
impl AsLockedWrite for $t {
176+
type Write<'w> = &'w mut Self where Self: 'w;
217177

218-
#[inline]
219-
fn as_locked_write(&mut self) -> Self::Write<'_> {
220-
self
221-
}
178+
#[inline]
179+
fn as_locked_write(&mut self) -> Self::Write<'_> {
180+
self
181+
}
182+
}
183+
)*
184+
};
222185
}
223186

224-
#[allow(deprecated)]
225-
impl AsLockedWrite for crate::Buffer {
226-
type Write<'w> = &'w mut Self;
227-
228-
#[inline]
229-
fn as_locked_write(&mut self) -> Self::Write<'_> {
230-
self
231-
}
232-
}
187+
impl_default_locked_write!(
188+
dyn std::io::Write,
189+
dyn std::io::Write + Send,
190+
dyn std::io::Write + Send + Sync,
191+
std::io::StdoutLock<'_>,
192+
std::io::StderrLock<'_>,
193+
Vec<u8>,
194+
std::fs::File,
195+
#[allow(deprecated)]
196+
crate::Buffer,
197+
);
233198

234199
mod private {
235200
pub trait Sealed {}
236201

202+
impl<T: Sealed + ?Sized> Sealed for &T {}
203+
impl<T: Sealed + ?Sized> Sealed for &mut T {}
204+
impl<T: Sealed + ?Sized> Sealed for Box<T> {}
205+
206+
impl Sealed for dyn std::io::Write {}
207+
impl Sealed for dyn std::io::Write + Send {}
208+
impl Sealed for dyn std::io::Write + Send + Sync {}
209+
237210
impl Sealed for std::io::Stdout {}
238211

239212
impl Sealed for std::io::StdoutLock<'_> {}
240213

241-
impl Sealed for &'_ mut std::io::StdoutLock<'_> {}
242-
243214
impl Sealed for std::io::Stderr {}
244215

245216
impl Sealed for std::io::StderrLock<'_> {}
246217

247-
impl Sealed for &'_ mut std::io::StderrLock<'_> {}
218+
impl Sealed for Vec<u8> {}
248219

249-
impl Sealed for Box<dyn std::io::Write> {}
220+
impl Sealed for std::fs::File {}
250221

251-
impl Sealed for &'_ mut Box<dyn std::io::Write> {}
222+
#[allow(deprecated)]
223+
impl Sealed for crate::Buffer {}
224+
}
252225

253-
impl Sealed for Vec<u8> {}
226+
#[cfg(test)]
227+
mod tests {
228+
use super::*;
254229

255-
impl Sealed for &'_ mut Vec<u8> {}
230+
fn assert_raw_stream<T: RawStream>() {}
256231

257-
impl Sealed for std::fs::File {}
232+
#[test]
233+
fn raw_streams() {
234+
assert_raw_stream::<Box<dyn std::io::Write>>();
235+
assert_raw_stream::<Box<dyn std::io::Write + 'static>>();
236+
assert_raw_stream::<Box<dyn std::io::Write + Send>>();
237+
assert_raw_stream::<Box<dyn std::io::Write + Send + Sync>>();
258238

259-
impl Sealed for &'_ mut std::fs::File {}
239+
assert_raw_stream::<&mut (dyn std::io::Write)>();
240+
assert_raw_stream::<&mut (dyn std::io::Write + 'static)>();
241+
assert_raw_stream::<&mut (dyn std::io::Write + Send)>();
242+
assert_raw_stream::<&mut (dyn std::io::Write + Send + Sync)>();
260243

261-
#[allow(deprecated)]
262-
impl Sealed for crate::Buffer {}
244+
assert_raw_stream::<Vec<u8>>();
245+
assert_raw_stream::<&mut Vec<u8>>();
263246

264-
#[allow(deprecated)]
265-
impl Sealed for &'_ mut crate::Buffer {}
247+
assert_raw_stream::<std::fs::File>();
248+
assert_raw_stream::<&mut std::fs::File>();
249+
}
266250
}

crates/anstyle-wincon/src/ansi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Low-level ANSI-styling
22
33
/// Write ANSI colored text to the stream
4-
pub fn write_colored<S: std::io::Write>(
4+
pub fn write_colored<S: std::io::Write + ?Sized>(
55
stream: &mut S,
66
fg: Option<anstyle::AnsiColor>,
77
bg: Option<anstyle::AnsiColor>,

0 commit comments

Comments
 (0)