print_bytes/
writer.rs

1#![cfg_attr(windows, allow(private_interfaces))]
2
3use std::io::BufWriter;
4use std::io::LineWriter;
5#[cfg(any(doc, not(feature = "specialization")))]
6use std::io::Stderr;
7#[cfg(any(doc, not(feature = "specialization")))]
8use std::io::StderrLock;
9#[cfg(any(doc, not(feature = "specialization")))]
10use std::io::Stdout;
11#[cfg(any(doc, not(feature = "specialization")))]
12use std::io::StdoutLock;
13use std::io::Write;
14#[cfg(all(feature = "specialization", windows))]
15use std::os::windows::io::AsHandle;
16
17#[cfg(windows)]
18use super::console::Console;
19
20#[cfg(windows)]
21pub(super) trait ToConsole {
22    fn to_console(&self) -> Option<Console<'_>>;
23}
24
25#[cfg(all(feature = "specialization", windows))]
26impl<T> ToConsole for T
27where
28    T: ?Sized,
29{
30    default fn to_console(&self) -> Option<Console<'_>> {
31        None
32    }
33}
34
35#[cfg(all(feature = "specialization", windows))]
36impl<T> ToConsole for T
37where
38    T: AsHandle + ?Sized + Write,
39{
40    fn to_console(&self) -> Option<Console<'_>> {
41        Console::from_handle(self)
42    }
43}
44
45/// A bound for [`write_lossy`] that allows it to be used for some types
46/// without specialization.
47///
48/// When the "specialization" feature is enabled, this trait is implemented for
49/// all types.
50///
51/// [`write_lossy`]: super::write_lossy
52pub trait WriteLossy {
53    #[cfg(windows)]
54    #[doc(hidden)]
55    fn __to_console(&self) -> Option<Console<'_>>;
56}
57
58#[cfg(feature = "specialization")]
59#[cfg_attr(print_bytes_docs_rs, doc(cfg(feature = "specialization")))]
60impl<T> WriteLossy for T
61where
62    T: ?Sized,
63{
64    #[cfg(windows)]
65    default fn __to_console(&self) -> Option<Console<'_>> {
66        self.to_console()
67    }
68}
69
70macro_rules! r#impl {
71    ( $generic:ident , $type:ty ) => {
72        impl<$generic> WriteLossy for $type
73        where
74            $generic: ?Sized + WriteLossy,
75        {
76            #[cfg(windows)]
77            fn __to_console(&self) -> Option<Console<'_>> {
78                (**self).__to_console()
79            }
80        }
81    };
82}
83r#impl!(T, &mut T);
84r#impl!(T, Box<T>);
85
86macro_rules! r#impl {
87    ( $generic:ident , $type:ty ) => {
88        impl<$generic> WriteLossy for $type
89        where
90            $generic: Write + WriteLossy,
91        {
92            #[cfg(windows)]
93            fn __to_console(&self) -> Option<Console<'_>> {
94                self.get_ref().__to_console()
95            }
96        }
97    };
98}
99r#impl!(T, BufWriter<T>);
100r#impl!(T, LineWriter<T>);
101
102macro_rules! impl_to_console {
103    ( $(#[ $attr:meta ])* $type:ty , $to_console_fn:expr , ) => {
104        #[cfg(any(doc, not(feature = "specialization")))]
105        impl $crate::WriteLossy for $type {
106            #[cfg(windows)]
107            fn __to_console(&self) -> Option<Console<'_>> {
108                $crate::writer::ToConsole::to_console(self)
109            }
110        }
111
112        #[cfg(windows)]
113        $(#[$attr])*
114        impl $crate::writer::ToConsole for $type {
115            fn to_console<'a>(&'a self) -> Option<Console<'a>> {
116                let to_console_fn: fn(&'a Self) -> _ = $to_console_fn;
117                to_console_fn(self)
118            }
119        }
120    };
121}
122
123macro_rules! r#impl {
124    ( $($type:ty),+ ) => {
125    $(
126        impl_to_console! {
127            #[cfg(not(feature = "specialization"))]
128            $type, Console::from_handle,
129        }
130    )+
131    };
132}
133r#impl!(Stderr, StderrLock<'_>, Stdout, StdoutLock<'_>);
134
135impl_to_console! {
136    #[cfg(not(feature = "specialization"))]
137    Vec<u8>, |_| None,
138}