@@ -253,6 +253,7 @@ mod tests;
253253
254254use crate :: cmp;
255255use crate :: fmt;
256+ use crate :: fmt:: Debug ;
256257use crate :: mem:: take;
257258use crate :: ops:: { Deref , DerefMut } ;
258259use crate :: slice;
@@ -1688,38 +1689,14 @@ pub trait Write {
16881689 /// }
16891690 /// ```
16901691 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1691- fn write_fmt ( & mut self , fmt : fmt:: Arguments < ' _ > ) -> Result < ( ) > {
1692- // Create a shim which translates a Write to a fmt::Write and saves
1693- // off I/O errors. instead of discarding them
1694- struct Adapter < ' a , T : ?Sized + ' a > {
1695- inner : & ' a mut T ,
1696- error : Result < ( ) > ,
1697- }
1698-
1699- impl < T : Write + ?Sized > fmt:: Write for Adapter < ' _ , T > {
1700- fn write_str ( & mut self , s : & str ) -> fmt:: Result {
1701- match self . inner . write_all ( s. as_bytes ( ) ) {
1702- Ok ( ( ) ) => Ok ( ( ) ) ,
1703- Err ( e) => {
1704- self . error = Err ( e) ;
1705- Err ( fmt:: Error )
1706- }
1707- }
1708- }
1709- }
1710-
1711- let mut output = Adapter { inner : self , error : Ok ( ( ) ) } ;
1712- match fmt:: write ( & mut output, fmt) {
1713- Ok ( ( ) ) => Ok ( ( ) ) ,
1714- Err ( ..) => {
1715- // check if the error came from the underlying `Write` or not
1716- if output. error . is_err ( ) {
1717- output. error
1718- } else {
1719- Err ( error:: const_io_error!( ErrorKind :: Uncategorized , "formatter error" ) )
1720- }
1721- }
1722- }
1692+ fn write_fmt ( mut self : & mut Self , fmt : fmt:: Arguments < ' _ > ) -> Result < ( ) > {
1693+ let mut output = ( & mut self ) . fmt_adapter ( ) ;
1694+ fmt:: write ( & mut output, fmt) . map_err ( |_| {
1695+ output
1696+ . mut_err ( )
1697+ . take ( )
1698+ . unwrap_or ( const_io_error ! ( ErrorKind :: Uncategorized , "formatter error" ) )
1699+ } )
17231700 }
17241701
17251702 /// Creates a "by reference" adapter for this instance of `Write`.
@@ -1750,6 +1727,78 @@ pub trait Write {
17501727 {
17511728 self
17521729 }
1730+
1731+ /// Convert an [`io::Write`](Write) to a [`FmtWriteAdapter`].
1732+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1733+ fn fmt_adapter ( & mut self ) -> FmtWriteAdapter < ' _ , Self >
1734+ where
1735+ Self : Sized ,
1736+ {
1737+ FmtWriteAdapter { inner : self , error : None }
1738+ }
1739+ }
1740+
1741+ /// Adapter that enables writing through a [`fmt::Write`] to an underlying [`io::Write`](Write).
1742+ ///
1743+ /// # Examples
1744+ ///
1745+ /// ```rust
1746+ /// #![feature(impl_fmt_write_for_io_write)]
1747+ /// # use std::{fmt, io};
1748+ /// # use std::io::Write;
1749+ ///
1750+ /// let mut output1 = String::new();
1751+ /// let mut output2 = io::stdout();
1752+ ///
1753+ /// my_common_writer(&mut output1).unwrap();
1754+ /// my_common_writer(&mut output2.fmt_adapter()).unwrap();
1755+ ///
1756+ /// fn my_common_writer(output: &mut impl fmt::Write) -> fmt::Result {
1757+ /// writeln!(output, "Hello World!")
1758+ /// }
1759+ /// ```
1760+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1761+ pub struct FmtWriteAdapter < ' a , W : Write + ?Sized > {
1762+ inner : & ' a mut W ,
1763+ error : Option < Error > ,
1764+ }
1765+
1766+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1767+ impl < W : Write + ?Sized > FmtWriteAdapter < ' _ , W > {
1768+ /// Returns a reference to the last error that occurred in this adapter.
1769+ pub fn err ( & self ) -> & Option < Error > {
1770+ & self . error
1771+ }
1772+
1773+ /// Returns a mutable reference to the last error that occurred in this adapter.
1774+ pub fn mut_err ( & mut self ) -> & mut Option < Error > {
1775+ & mut self . error
1776+ }
1777+ }
1778+
1779+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1780+ impl < W : Write + ?Sized > fmt:: Write for FmtWriteAdapter < ' _ , W > {
1781+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
1782+ match self . inner . write_all ( s. as_bytes ( ) ) {
1783+ Ok ( ( ) ) => {
1784+ self . error = None ;
1785+ Ok ( ( ) )
1786+ }
1787+ Err ( e) => {
1788+ self . error = Some ( e) ;
1789+ Err ( fmt:: Error )
1790+ }
1791+ }
1792+ }
1793+ }
1794+
1795+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1796+ impl < W : Write + ?Sized > Debug for FmtWriteAdapter < ' _ , W > {
1797+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1798+ let mut builder = f. debug_struct ( "FmtWriteAdapter" ) ;
1799+ builder. field ( "error" , & self . error ) ;
1800+ builder. finish ( )
1801+ }
17531802}
17541803
17551804/// The `Seek` trait provides a cursor which can be moved within a stream of
0 commit comments