@@ -299,6 +299,7 @@ mod tests;
299
299
300
300
use crate :: cmp;
301
301
use crate :: fmt;
302
+ use crate :: fmt:: Debug ;
302
303
use crate :: mem:: take;
303
304
use crate :: ops:: { Deref , DerefMut } ;
304
305
use crate :: slice;
@@ -1786,38 +1787,14 @@ pub trait Write {
1786
1787
/// }
1787
1788
/// ```
1788
1789
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1789
- fn write_fmt ( & mut self , fmt : fmt:: Arguments < ' _ > ) -> Result < ( ) > {
1790
- // Create a shim which translates a Write to a fmt::Write and saves
1791
- // off I/O errors. instead of discarding them
1792
- struct Adapter < ' a , T : ?Sized + ' a > {
1793
- inner : & ' a mut T ,
1794
- error : Result < ( ) > ,
1795
- }
1796
-
1797
- impl < T : Write + ?Sized > fmt:: Write for Adapter < ' _ , T > {
1798
- fn write_str ( & mut self , s : & str ) -> fmt:: Result {
1799
- match self . inner . write_all ( s. as_bytes ( ) ) {
1800
- Ok ( ( ) ) => Ok ( ( ) ) ,
1801
- Err ( e) => {
1802
- self . error = Err ( e) ;
1803
- Err ( fmt:: Error )
1804
- }
1805
- }
1806
- }
1807
- }
1808
-
1809
- let mut output = Adapter { inner : self , error : Ok ( ( ) ) } ;
1810
- match fmt:: write ( & mut output, fmt) {
1811
- Ok ( ( ) ) => Ok ( ( ) ) ,
1812
- Err ( ..) => {
1813
- // check if the error came from the underlying `Write` or not
1814
- if output. error . is_err ( ) {
1815
- output. error
1816
- } else {
1817
- Err ( error:: const_io_error!( ErrorKind :: Uncategorized , "formatter error" ) )
1818
- }
1819
- }
1820
- }
1790
+ fn write_fmt ( mut self : & mut Self , fmt : fmt:: Arguments < ' _ > ) -> Result < ( ) > {
1791
+ let mut output = ( & mut self ) . fmt_adapter ( ) ;
1792
+ fmt:: write ( & mut output, fmt) . map_err ( |_| {
1793
+ output
1794
+ . mut_err ( )
1795
+ . take ( )
1796
+ . unwrap_or ( const_io_error ! ( ErrorKind :: Uncategorized , "formatter error" ) )
1797
+ } )
1821
1798
}
1822
1799
1823
1800
/// Creates a "by reference" adapter for this instance of `Write`.
@@ -1848,6 +1825,78 @@ pub trait Write {
1848
1825
{
1849
1826
self
1850
1827
}
1828
+
1829
+ /// Convert an [`io::Write`](Write) to a [`FmtWriteAdapter`].
1830
+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1831
+ fn fmt_adapter ( & mut self ) -> FmtWriteAdapter < ' _ , Self >
1832
+ where
1833
+ Self : Sized ,
1834
+ {
1835
+ FmtWriteAdapter { inner : self , error : None }
1836
+ }
1837
+ }
1838
+
1839
+ /// Adapter that enables writing through a [`fmt::Write`] to an underlying [`io::Write`](Write).
1840
+ ///
1841
+ /// # Examples
1842
+ ///
1843
+ /// ```rust
1844
+ /// #![feature(impl_fmt_write_for_io_write)]
1845
+ /// # use std::{fmt, io};
1846
+ /// # use std::io::Write;
1847
+ ///
1848
+ /// let mut output1 = String::new();
1849
+ /// let mut output2 = io::stdout();
1850
+ ///
1851
+ /// my_common_writer(&mut output1).unwrap();
1852
+ /// my_common_writer(&mut output2.fmt_adapter()).unwrap();
1853
+ ///
1854
+ /// fn my_common_writer(output: &mut impl fmt::Write) -> fmt::Result {
1855
+ /// writeln!(output, "Hello World!")
1856
+ /// }
1857
+ /// ```
1858
+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1859
+ pub struct FmtWriteAdapter < ' a , W : Write + ?Sized > {
1860
+ inner : & ' a mut W ,
1861
+ error : Option < Error > ,
1862
+ }
1863
+
1864
+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1865
+ impl < W : Write + ?Sized > FmtWriteAdapter < ' _ , W > {
1866
+ /// Returns a reference to the last error that occurred in this adapter.
1867
+ pub fn err ( & self ) -> & Option < Error > {
1868
+ & self . error
1869
+ }
1870
+
1871
+ /// Returns a mutable reference to the last error that occurred in this adapter.
1872
+ pub fn mut_err ( & mut self ) -> & mut Option < Error > {
1873
+ & mut self . error
1874
+ }
1875
+ }
1876
+
1877
+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1878
+ impl < W : Write + ?Sized > fmt:: Write for FmtWriteAdapter < ' _ , W > {
1879
+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
1880
+ match self . inner . write_all ( s. as_bytes ( ) ) {
1881
+ Ok ( ( ) ) => {
1882
+ self . error = None ;
1883
+ Ok ( ( ) )
1884
+ }
1885
+ Err ( e) => {
1886
+ self . error = Some ( e) ;
1887
+ Err ( fmt:: Error )
1888
+ }
1889
+ }
1890
+ }
1891
+ }
1892
+
1893
+ #[ unstable( feature = "impl_fmt_write_for_io_write" , issue = "77733" ) ]
1894
+ impl < W : Write + ?Sized > Debug for FmtWriteAdapter < ' _ , W > {
1895
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1896
+ let mut builder = f. debug_struct ( "FmtWriteAdapter" ) ;
1897
+ builder. field ( "error" , & self . error ) ;
1898
+ builder. finish ( )
1899
+ }
1851
1900
}
1852
1901
1853
1902
/// The `Seek` trait provides a cursor which can be moved within a stream of
0 commit comments