@@ -253,6 +253,7 @@ mod tests;
253
253
254
254
use crate :: cmp;
255
255
use crate :: fmt;
256
+ use crate :: fmt:: Debug ;
256
257
use crate :: mem:: take;
257
258
use crate :: ops:: { Deref , DerefMut } ;
258
259
use crate :: slice;
@@ -1688,38 +1689,14 @@ pub trait Write {
1688
1689
/// }
1689
1690
/// ```
1690
1691
#[ 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
+ } )
1723
1700
}
1724
1701
1725
1702
/// Creates a "by reference" adapter for this instance of `Write`.
@@ -1750,6 +1727,78 @@ pub trait Write {
1750
1727
{
1751
1728
self
1752
1729
}
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
+ }
1753
1802
}
1754
1803
1755
1804
/// The `Seek` trait provides a cursor which can be moved within a stream of
0 commit comments