1use crate::utf8_output::Utf8Output;
2use crate::WriteStr;
3#[cfg(windows)]
4use io_extras::os::windows::{
5 AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, RawHandleOrSocket,
6};
7#[cfg(feature = "layered-io")]
8use layered_io::{Bufferable, WriteLayered};
9use std::io::{self, Write};
10use std::{fmt, str};
11#[cfg(feature = "terminal-io")]
12use terminal_io::{Terminal, TerminalColorSupport, WriteTerminal};
13#[cfg(not(windows))]
14use {
15 io_extras::os::rustix::{AsRawFd, RawFd},
16 std::os::fd::{AsFd, BorrowedFd},
17};
18
19pub struct Utf8Writer<Inner: Write> {
28 pub(crate) inner: Inner,
30
31 pub(crate) output: Utf8Output,
33}
34
35impl<Inner: Write> Utf8Writer<Inner> {
36 #[inline]
38 pub fn new(inner: Inner) -> Self {
39 Self {
40 inner,
41 output: Utf8Output::new(),
42 }
43 }
44
45 #[inline]
47 pub fn into_inner(mut self) -> io::Result<Inner> {
48 self.flush()?;
49 Utf8Output::into_inner(self)
50 }
51}
52
53#[cfg(feature = "layered-io")]
54impl<Inner: WriteLayered> Utf8Writer<Inner> {
55 #[inline]
58 pub fn close_into_inner(self) -> io::Result<Inner> {
59 Utf8Output::into_inner(self)
60 }
61
62 #[inline]
65 pub fn abandon_into_inner(self) -> Inner {
66 Utf8Output::abandon_into_inner(self)
67 }
68}
69
70#[cfg(feature = "terminal-io")]
71impl<Inner: Write + WriteTerminal> Terminal for Utf8Writer<Inner> {}
72
73#[cfg(feature = "terminal-io")]
74impl<Inner: Write + WriteTerminal> WriteTerminal for Utf8Writer<Inner> {
75 #[inline]
76 fn color_support(&self) -> TerminalColorSupport {
77 self.inner.color_support()
78 }
79
80 #[inline]
81 fn color_preference(&self) -> bool {
82 self.inner.color_preference()
83 }
84
85 #[inline]
86 fn is_output_terminal(&self) -> bool {
87 self.inner.is_output_terminal()
88 }
89}
90
91#[cfg(feature = "layered-io")]
92impl<Inner: WriteLayered> WriteLayered for Utf8Writer<Inner> {
93 #[inline]
94 fn close(&mut self) -> io::Result<()> {
95 Utf8Output::close(self)
96 }
97}
98
99impl<Inner: Write> WriteStr for Utf8Writer<Inner> {
100 #[inline]
101 fn write_str(&mut self, s: &str) -> io::Result<()> {
102 Utf8Output::write_str(self, s)
103 }
104}
105
106#[cfg(feature = "layered-io")]
107impl<Inner: WriteLayered> Bufferable for Utf8Writer<Inner> {
108 #[inline]
109 fn abandon(&mut self) {
110 Utf8Output::abandon(self)
111 }
112
113 #[inline]
114 fn suggested_buffer_size(&self) -> usize {
115 Utf8Output::suggested_buffer_size(self)
116 }
117}
118
119impl<Inner: Write> Write for Utf8Writer<Inner> {
120 #[inline]
121 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
122 Utf8Output::write(self, buf)
123 }
124
125 #[inline]
126 fn flush(&mut self) -> io::Result<()> {
127 Utf8Output::flush(self)
128 }
129}
130
131#[cfg(not(windows))]
132impl<Inner: Write + AsRawFd> AsRawFd for Utf8Writer<Inner> {
133 #[inline]
134 fn as_raw_fd(&self) -> RawFd {
135 self.inner.as_raw_fd()
136 }
137}
138
139#[cfg(not(windows))]
140impl<Inner: Write + AsFd> AsFd for Utf8Writer<Inner> {
141 #[inline]
142 fn as_fd(&self) -> BorrowedFd<'_> {
143 self.inner.as_fd()
144 }
145}
146
147#[cfg(windows)]
148impl<Inner: Write + AsRawHandleOrSocket> AsRawHandleOrSocket for Utf8Writer<Inner> {
149 #[inline]
150 fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
151 self.inner.as_raw_handle_or_socket()
152 }
153}
154
155#[cfg(windows)]
156impl<Inner: Write + AsHandleOrSocket> AsHandleOrSocket for Utf8Writer<Inner> {
157 #[inline]
158 fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
159 self.inner.as_handle_or_socket()
160 }
161}
162
163impl<Inner: Write + fmt::Debug> fmt::Debug for Utf8Writer<Inner> {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 let mut b = f.debug_struct("Utf8Writer");
166 b.field("inner", &self.inner);
167 b.finish()
168 }
169}