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#[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
172impl<'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#[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 }