Skip to main content

fmt2/
write_to.rs

1use crate::{str::FmtStaticStrImpl, write::Write};
2
3pub trait WriteTo {
4    const ENDS_IN_NEWLINE: bool = false;
5    const MIN_SIZE: usize = 0;
6
7    fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
8    where
9        W: Write + ?Sized;
10
11    #[inline]
12    fn len_hint(&self) -> usize {
13        0
14    }
15}
16
17impl WriteTo for str {
18    fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
19    where
20        W: Write + ?Sized,
21    {
22        w.write_str(self)
23    }
24
25    fn len_hint(&self) -> usize {
26        self.len()
27    }
28}
29
30impl<T> WriteTo for Debug<[T]>
31where
32    T: FmtDebug,
33{
34    crate::fmt! { [s] => "[" @..join(s.0 => ", " => |e| {e;?}) "]" }
35}
36
37pub trait FmtAdvanced {
38    type Target: WriteTo + ?Sized;
39    fn fmt_advanced(&self) -> &Self::Target;
40}
41
42impl<T> FmtAdvanced for T
43where
44    T: WriteTo + ?Sized,
45{
46    type Target = Self;
47    #[inline]
48    fn fmt_advanced(&self) -> &Self::Target {
49        self
50    }
51}
52
53pub trait Fmt {
54    fn fmt(&self) -> &(impl WriteTo + ?Sized);
55}
56
57impl<T> Fmt for T
58where
59    T: FmtAdvanced + ?Sized,
60{
61    #[inline]
62    fn fmt(&self) -> &(impl WriteTo + ?Sized) {
63        self.fmt_advanced()
64    }
65}
66
67// impl<I, T> WriteTo for I
68// where
69//     I: Iterator<Item = &T> + ?Sized,
70//     T: WriteTo + ?Sized,
71// {
72//     const ENDS_IN_NEWLINE: bool = T::ENDS_IN_NEWLINE;
73//     fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
74//     where
75//         W: Write + ?Sized,
76//     {
77//         for v in self {
78//             w.write(v)
79//         }
80//         Ok(())
81//     }
82// }
83
84#[macro_export]
85macro_rules! declare_fmt_wrapper_struct {
86    { $Struct:ident $(<$(const $CONST:ident : $ConstType:ty),*>)? $Trait:ident $fn:ident $(, $($($rest:tt)+)?)? } => {
87        pub struct $Struct<T $($(, const $CONST: $ConstType)*)?>(T)
88        where
89            T: ?Sized,
90            Self: $crate::write_to::WriteTo;
91
92        pub trait $Trait $(<$(const $CONST: $ConstType),*>)? {
93            fn $fn(&self) -> &(impl $crate::write_to::WriteTo + ?Sized);
94        }
95
96        impl<T $($(, const $CONST: $ConstType)*)?> $Trait $(<$({ $CONST }),*>)? for T
97        where
98            T: ?Sized,
99            $Struct<T $($(, { $CONST })*)?>: $crate::write_to::WriteTo,
100        {
101            #[inline]
102            fn $fn(&self) -> &(impl $crate::write_to::WriteTo + ?Sized) {
103                unsafe { &*(self as *const Self as *const $Struct<Self $($(, { $CONST })*)?>) }
104            }
105        }
106
107        $($($crate::declare_fmt_wrapper_struct! { $($rest)+ })?)?
108    };
109}
110
111macro_rules! declare_std_write_to_wrapper_struct_internal {
112    { $($Struct:ident $(<$(const $CONST:ident : $ConstType:ty),* $(,)?>)? $Trait:ident $fn:ident => $StdTrait:ident $write_fn:ident),* $(,)? } => {
113        $(
114            $crate::declare_fmt_wrapper_struct! { $Struct $(<$(const $CONST : $ConstType),*>)? $Trait $fn }
115
116            impl<T $($(, const $CONST : $ConstType)*)?> $crate::write_to::WriteTo for $Struct<T $($(, { $CONST })*)?>
117            where
118                T: ::core::fmt::$StdTrait + ?Sized,
119            {
120                #[inline]
121                fn write_to<W>(&self, w: &mut W) -> ::core::result::Result<(), W::Error>
122                where
123                    W: $crate::write::Write + ?Sized,
124                {
125                    $crate::write::Write::$write_fn::<T $($(, { $CONST })*)?>(w, &self.0)
126                }
127            }
128        )*
129    };
130}
131
132macro_rules! impl_fmt_trait_internal {
133    { $StdTrait:ident $std_fn:ident => $Trait:ident $fn:ident => $($ty:ty)*} => {
134        $(
135            impl $Trait for $ty {
136                #[inline]
137                fn $fn(&self) -> &(impl $crate::write_to::WriteTo + ?Sized) {
138                    $StdTrait::$std_fn(self)
139                }
140            }
141        )*
142    };
143}
144
145declare_fmt_wrapper_struct! {
146    Debug   FmtDebug    fmt_debug,
147    Binary  FmtBinary   fmt_binary,
148    Octal   FmtOctal    fmt_octal,
149    Hex     FmtHex      fmt_hex,
150    Precision<const PRECISION: u8> FmtPrecision fmt_precision,
151    Iterator FmtIterator fmt_iterator,
152}
153
154declare_std_write_to_wrapper_struct_internal! {
155    StdDisplay  FmtStdDisplay   fmt_std_display => Display  write_std_display,
156    StdDebug    FmtStdDebug     fmt_std_debug   => Debug    write_std_debug,
157    StdBinary   FmtStdBinary    fmt_std_binary  => Binary   write_std_binary,
158    StdOctal    FmtStdOctal     fmt_std_octal   => Octal    write_std_octal,
159    StdHex      FmtStdHex       fmt_std_hex     => UpperHex write_std_upper_hex,
160}
161#[cfg(feature = "fmt_internals")]
162declare_std_write_to_wrapper_struct_internal! {
163    StdPrecision<const PRECISION: u8>   FmtStdPrecision fmt_std_precision   => Display write_std_precision,
164}
165
166impl_fmt_trait_internal! { FmtStdDisplay    fmt_std_display => Fmt          fmt         => usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
167impl_fmt_trait_internal! { FmtStdDebug      fmt_std_debug   => FmtDebug     fmt_debug   => usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
168impl_fmt_trait_internal! { FmtStdBinary     fmt_std_binary  => FmtBinary    fmt_binary  => usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
169impl_fmt_trait_internal! { FmtStdOctal      fmt_std_octal   => FmtOctal     fmt_octal   => usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
170impl_fmt_trait_internal! { FmtStdHex        fmt_std_hex     => FmtHex       fmt_hex     => usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
171
172//
173// impl<'t, I, T> WriteTo for Iterator<I>
174// where
175//     I: core::iter::Iterator<Item = &'t T> + Clone,
176//     T: WriteTo + ?Sized + 't,
177// {
178//     const ENDS_IN_NEWLINE: bool = T::ENDS_IN_NEWLINE;
179//
180//     fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
181//     where
182//         W: Write + ?Sized,
183//     {
184//         for t in self.0.clone() {
185//             t.write_to(w)?;
186//         }
187//         Ok(())
188//     }
189// }
190
191impl<'t, I, T> WriteTo for Iterator<I>
192where
193    I: core::iter::Iterator<Item = &'t T> + Clone,
194    T: WriteTo + ?Sized + 't,
195{
196    const ENDS_IN_NEWLINE: bool = T::ENDS_IN_NEWLINE;
197
198    #[inline]
199    fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
200    where
201        W: Write + ?Sized,
202    {
203        for t in self.0.clone() {
204            t.write_to(w)?;
205        }
206        Ok(())
207    }
208
209    #[inline]
210    fn len_hint(&self) -> usize {
211        self.0.size_hint().0 * T::MIN_SIZE
212    }
213}
214
215impl WriteTo for core::fmt::Arguments<'_> {
216    fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
217    where
218        W: Write + ?Sized,
219    {
220        w.write_std_args_ref(self)
221    }
222}
223
224impl WriteTo for Debug<str> {
225    fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
226    where
227        W: Write + ?Sized,
228    {
229        w.write_str(&self.0)
230    }
231}
232
233impl FmtStaticStrImpl for bool {
234    #[inline]
235    fn fmt_static_str_impl(&self) -> &'static str {
236        if *self {
237            "true"
238        } else {
239            "false"
240        }
241    }
242}
243
244impl FmtAdvanced for bool {
245    type Target = str;
246    #[inline]
247    fn fmt_advanced(&self) -> &Self::Target {
248        self.fmt_static_str_impl()
249    }
250}
251
252impl FmtPrecision<5> for bool {
253    fn fmt_precision(&self) -> &(impl crate::write_to::WriteTo + ?Sized) {
254        if *self {
255            "true "
256        } else {
257            "false"
258        }
259    }
260}
261
262// impl FmtDebug for bool {
263//     type Target = Self;
264//     fn fmt_debug(&self) -> &Self::Target {
265//         self
266//     }
267// }
268
269// pub trait WriteToFor<W>
270// where
271//     W: crate::write::Write + ?Sized,
272// {
273//     fn write_to_for(&self, w: &mut W) -> Result<(), W::Error>;
274// }
275//
276// impl<F, W> WriteToFor<W> for F
277// where
278//     F: Fn(&mut W) -> Result<(), W::Error>,
279//     W: crate::write::Write,
280// {
281//     fn write_to_for(&self, w: &mut W) -> Result<(), W::Error> {
282//         self(w)
283//     }
284// }
285
286#[cfg(feature = "std")]
287pub trait ToString {
288    fn to_string(&self) -> ::std::string::String;
289}
290
291#[cfg(feature = "std")]
292impl<T> ToString for T
293where
294    T: Fmt + ?Sized,
295{
296    fn to_string(&self) -> String {
297        let wt = self.fmt();
298        let mut s = String::with_capacity(wt.len_hint());
299        let Ok(()) = s.write(wt);
300        s
301    }
302}
303
304#[derive(Clone, Copy)]
305pub struct WithFmtAdvanced<'a, T, U = str>
306where
307    U: WriteTo + ?Sized,
308{
309    pub value: T,
310    pub fmt: &'a U,
311}
312
313impl<'a, T, U> WithFmtAdvanced<'a, T, U>
314where
315    U: WriteTo + ?Sized,
316{
317    pub const fn new(value: T, str: &'a U) -> Self {
318        Self { value, fmt: str }
319    }
320
321    pub fn map_value<V>(self, f: impl FnOnce(T) -> V) -> WithFmtAdvanced<'a, V, U> {
322        WithFmtAdvanced {
323            value: f(self.value),
324            fmt: self.fmt,
325        }
326    }
327
328    pub fn replace_value<V>(self, value: V) -> WithFmtAdvanced<'a, V, U> {
329        WithFmtAdvanced {
330            value,
331            fmt: self.fmt,
332        }
333    }
334}
335
336impl<T, U> FmtAdvanced for WithFmtAdvanced<'_, T, U>
337where
338    U: WriteTo + ?Sized,
339{
340    type Target = U;
341    fn fmt_advanced(&self) -> &Self::Target {
342        self.fmt.fmt_advanced()
343    }
344}
345
346impl<T0, T1, U> AsRef<T1> for WithFmtAdvanced<'_, T0, U>
347where
348    T0: AsRef<T1>,
349    T1: ?Sized,
350    U: WriteTo + ?Sized,
351{
352    #[inline]
353    fn as_ref(&self) -> &T1 {
354        self.value.as_ref()
355    }
356}
357
358impl<T, U> core::ops::Deref for WithFmtAdvanced<'_, T, U>
359where
360    U: WriteTo + ?Sized,
361{
362    type Target = Self;
363
364    fn deref(&self) -> &Self::Target {
365        self
366    }
367}
368
369#[macro_export]
370macro_rules! impl_write_to_for_std_display {
371	{ $($ty:ident $write_to_fn:ident),* $(,)? } => {
372		$(
373			impl $crate::write_to::WriteTo for $name {
374				#[inline]
375				fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
376					where
377						W: $crate::write::Write + ?Sized {
378					$crate::write::Write::write_std_display(w, self)
379				}
380			}
381		)*
382	};
383}
384
385#[macro_export]
386macro_rules! impl_std_display_for_write_to {
387	{ $($name:ty),* $(,)? } => {
388		$(
389			impl ::core::fmt::Display for $name {
390				#[inline]
391				fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
392					$crate::write::Write::write(f, self)
393				}
394			}
395		)*
396	};
397}
398
399#[allow(
400    clippy::allow_attributes,
401    clippy::unwrap_used,
402    clippy::expect_used,
403    clippy::panic,
404    clippy::missing_const_for_fn,
405    unused_variables,
406    unused_imports
407)]
408#[cfg(test)]
409mod tests {
410    // use core::borrow::Borrow;
411
412    // use crate::{str::FmtStaticStr, write_to::WriteTo};
413
414    // use super::{FmtAdvanced, ToString};
415
416    // #[test]
417    // fn borrow() {
418    //     let k = {
419    //         let s = "123";
420    //         // let s = String::new();
421    //         s.fmt_advanced()
422    //     };
423    //     ToString::to_string(k);
424    //     let k = {
425    //         let s = true;
426    //         s.fmt_static_str()
427    //     };
428    //     ToString::to_string(k);
429    // }
430
431    // #[test]
432    //     fn write() {
433    //         use crate::{
434    //             write::{Flush, Write, WriteInfallible},
435    //             write_to::WriteTo,
436    //         };
437    //
438    //         struct Test(bool);
439    //
440    //         impl WriteTo for Test {
441    //             fn write_to<W>(&self, w: &mut W) -> Result<(), W::Error>
442    //             where
443    //                 W: Write + ?Sized,
444    //             {
445    //                 w.write_str(self.0.fmt_advanced())
446    //             }
447    //         }
448    //
449    //         let mut s = String::new();
450    //         let Ok(()) = s.write(&Test(true));
451    //         assert_eq!(s, "true");
452    //
453    //         let mut s = String::new();
454    //         let Ok(()) = s.write(&Test(false));
455    //         assert_eq!(s, "false");
456    //
457    //         let mut s = String::new();
458    //         let Ok(()) = Test(true).write_to(&mut s);
459    //         assert_eq!(s, "true");
460    //
461    //         let mut s = String::new();
462    //         let Ok(()) = Test(false).write_to(&mut s);
463    //         assert_eq!(s, "false");
464    //
465    //         let mut s = String::new();
466    //         s.write_str_infallible("123456");
467    //         assert_eq!(s, "123456");
468    //
469    //         let mut s = String::new();
470    //         WriteInfallible::write_str_infallible(&mut s, "123abc");
471    //         assert_eq!(s, "123abc");
472    //
473    //         let mut s = String::new();
474    //         let Ok(()) = "123abc".write_to(&mut s);
475    //         assert_eq!(s, "123abc");
476    //     }
477}