debug3/
std_impls.rs

1use std::{
2    alloc::Layout,
3    collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
4    num::IntErrorKind,
5    ops::Deref,
6    path::{Path, PathBuf},
7    rc::Rc,
8    sync::{Arc, Mutex, TryLockError},
9};
10
11use crate::{Debug, Formatter};
12
13macro_rules! std_debug {
14    ($($t:ty),+ ,) => {
15        $(
16            impl Debug for $t {
17                fn fmt(&self, f: &mut Formatter) {
18                    f.write_debug(self)
19                }
20            }
21        )+
22    };
23}
24
25std_debug! {
26    bool,
27    char,
28    f32,
29    f64,
30    isize,
31    i8,
32    i16,
33    i32,
34    i64,
35    i128,
36    usize,
37    u8,
38    u16,
39    u32,
40    u64,
41    u128,
42    String,
43    str,
44    (),
45    Path,
46    PathBuf,
47    std::num::NonZeroI8,
48    std::num::NonZeroI16,
49    std::num::NonZeroI32,
50    std::num::NonZeroI64,
51    std::num::NonZeroI128,
52    std::num::NonZeroIsize,
53    std::num::NonZeroU8,
54    std::num::NonZeroU16,
55    std::num::NonZeroU32,
56    std::num::NonZeroU64,
57    std::num::NonZeroU128,
58    std::num::NonZeroUsize,
59}
60
61macro_rules! peel {
62    ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })
63}
64
65macro_rules! tuple {
66    () => ();
67    ( $($name:ident,)+ ) => (
68        impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized {
69            #[allow(non_snake_case, unused_assignments)]
70            fn fmt(&self, f: &mut Formatter) {
71                let mut builder = f.debug_tuple("");
72                let ($(ref $name,)+) = *self;
73                $(
74                    builder.field(&$name);
75                )+
76
77                builder.finish()
78            }
79        }
80        peel! { $($name,)+ }
81    )
82}
83
84macro_rules! last_type {
85    ($a:ident,) => { $a };
86    ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
87}
88
89tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
90
91macro_rules! fmt_refs {
92    ($($tr:ident),*) => {
93        $(
94        impl<T: ?Sized + $tr> $tr for &T {
95            fn fmt(&self, f: &mut Formatter) { $tr::fmt(&**self, f) }
96        }
97        impl<T: ?Sized + $tr> $tr for &mut T {
98            fn fmt(&self, f: &mut Formatter) { $tr::fmt(&**self, f) }
99        }
100        )*
101    }
102}
103
104fmt_refs! { Debug /*, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp */ }
105
106impl<T: ?Sized + Debug> Debug for Box<T> {
107    fn fmt(&self, f: &mut Formatter) {
108        Debug::fmt(&**self, f)
109    }
110}
111
112impl<T: Debug, const N: usize> Debug for [T; N] {
113    fn fmt(&self, f: &mut Formatter) {
114        Debug::fmt(&self[..], f)
115    }
116}
117
118impl<T: ?Sized + Debug> Debug for Arc<T> {
119    fn fmt(&self, f: &mut Formatter) {
120        Debug::fmt(&**self, f)
121    }
122}
123
124impl<T: ?Sized + Debug> Debug for Rc<T> {
125    fn fmt(&self, f: &mut Formatter) {
126        Debug::fmt(&**self, f)
127    }
128}
129
130impl<T: ?Sized> Debug for *const T {
131    fn fmt(&self, f: &mut Formatter) {
132        f.write_debug(self)
133    }
134}
135
136impl<T: ?Sized> Debug for *mut T {
137    fn fmt(&self, f: &mut Formatter) {
138        Debug::fmt(&(self as *const _), f)
139    }
140}
141
142macro_rules! list_like {
143    ($($t:ty),+) => {
144        $(
145            impl<T: Debug> Debug for $t {
146                fn fmt(&self, f: &mut Formatter) {
147                    f.debug_list().entries(self.iter()).finish()
148                }
149            }
150        )+
151    };
152}
153
154list_like! {
155    [T], Vec<T>, VecDeque<T>, LinkedList<T>, BinaryHeap<T>
156}
157
158impl<K, V, S> Debug for HashMap<K, V, S>
159where
160    K: Debug,
161    V: Debug,
162{
163    fn fmt(&self, f: &mut Formatter) {
164        f.debug_map().entries(self.iter()).finish()
165    }
166}
167impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
168    fn fmt(&self, f: &mut Formatter) {
169        f.debug_map().entries(self.iter()).finish()
170    }
171}
172impl<T, S> Debug for HashSet<T, S>
173where
174    T: Debug,
175{
176    fn fmt(&self, f: &mut Formatter) {
177        f.debug_set().entries(self.iter()).finish()
178    }
179}
180impl<T> Debug for BTreeSet<T>
181where
182    T: Debug,
183{
184    fn fmt(&self, f: &mut Formatter) {
185        f.debug_set().entries(self.iter()).finish()
186    }
187}
188impl<T: Debug> Debug for Option<T> {
189    fn fmt(&self, f: &mut Formatter) {
190        match self {
191            Some(v) => f.debug_tuple("Some").field(v).finish(),
192            None => f.debug_tuple("None").finish(),
193        }
194    }
195}
196
197impl<T: ?Sized> Debug for std::marker::PhantomData<T> {
198    fn fmt(&self, f: &mut Formatter) {
199        f.debug_struct("PhantomData").finish()
200    }
201}
202
203impl<T: Copy + Debug> Debug for std::cell::Cell<T> {
204    fn fmt(&self, f: &mut Formatter) {
205        f.debug_struct("Cell").field("value", &self.get()).finish()
206    }
207}
208
209impl<T: ?Sized + Debug> Debug for std::cell::RefCell<T> {
210    fn fmt(&self, f: &mut Formatter) {
211        match self.try_borrow() {
212            Ok(borrow) => f.debug_struct("RefCell").field("value", &borrow).finish(),
213            Err(_) => {
214                // The RefCell is mutably borrowed so we can't look at its value
215                // here. Show a placeholder instead.
216                struct BorrowedPlaceholder;
217
218                impl Debug for BorrowedPlaceholder {
219                    fn fmt(&self, f: &mut Formatter) {
220                        f.write_display("<borrowed>")
221                    }
222                }
223
224                f.debug_struct("RefCell")
225                    .field("value", &BorrowedPlaceholder)
226                    .finish()
227            }
228        }
229    }
230}
231
232impl<T: ?Sized + Debug> Debug for std::cell::Ref<'_, T> {
233    fn fmt(&self, f: &mut Formatter) {
234        Debug::fmt(&**self, f)
235    }
236}
237
238impl<T: ?Sized + Debug> Debug for std::cell::RefMut<'_, T> {
239    fn fmt(&self, f: &mut Formatter) {
240        Debug::fmt(self.deref(), f)
241    }
242}
243
244impl<T: ?Sized> Debug for std::cell::UnsafeCell<T> {
245    fn fmt(&self, f: &mut Formatter) {
246        f.debug_struct("UnsafeCell").finish_non_exhaustive()
247    }
248}
249
250impl Debug for std::fmt::Arguments<'_> {
251    fn fmt(&self, f: &mut Formatter) {
252        f.write_debug(self)
253    }
254}
255
256impl<T: ?Sized + Debug> Debug for Mutex<T> {
257    fn fmt(&self, f: &mut Formatter) {
258        let mut d = f.debug_struct("Mutex");
259        match self.try_lock() {
260            Ok(guard) => {
261                d.field("data", &&*guard);
262            }
263            Err(TryLockError::Poisoned(err)) => {
264                d.field("data", &&**err.get_ref());
265            }
266            Err(TryLockError::WouldBlock) => {
267                struct LockedPlaceholder;
268                impl Debug for LockedPlaceholder {
269                    fn fmt(&self, f: &mut Formatter) {
270                        f.write_debug(format_args!("<locked>"))
271                    }
272                }
273                d.field("data", &LockedPlaceholder);
274            }
275        }
276        d.field("poisoned", &self.is_poisoned());
277        d.finish_non_exhaustive()
278    }
279}
280
281impl Debug for Layout {
282    fn fmt(&self, f: &mut Formatter) {
283        f.debug_struct("Layout")
284            .field("size", &self.size())
285            .field("align", &self.align())
286            .finish()
287    }
288}
289
290impl<B> Debug for std::borrow::Cow<'_, B>
291where
292    B: Debug + ToOwned + ?Sized,
293    <B as ToOwned>::Owned: Debug,
294{
295    fn fmt(&self, f: &mut Formatter) {
296        match *self {
297            Self::Borrowed(ref b) => Debug::fmt(b, f),
298            Self::Owned(ref o) => Debug::fmt(o, f),
299        }
300    }
301}
302
303impl Debug for std::num::ParseIntError {
304    fn fmt(&self, f: &mut Formatter) {
305        f.debug_struct("ParseIntError")
306            .field("kind", &self.kind())
307            .finish()
308    }
309}
310
311impl Debug for IntErrorKind {
312    fn fmt(&self, f: &mut Formatter) {
313        f.debug_tuple(match self {
314            Self::Empty => "Empty",
315            Self::InvalidDigit => "InvalidDigit",
316            Self::PosOverflow => "PosOverflow",
317            Self::NegOverflow => "NegOverflow",
318            Self::Zero => "Zero",
319            _ => "Unknown",
320        })
321        .finish()
322    }
323}
324
325impl Debug for std::time::Duration {
326    fn fmt(&self, f: &mut Formatter) {
327        f.debug_struct("Duration")
328            .field("secs", &self.as_secs())
329            .field("nanos", &self.subsec_nanos())
330            .finish()
331    }
332}
333
334impl Debug for Box<dyn std::error::Error + '_> {
335    fn fmt(&self, f: &mut Formatter) {
336        // TODO: Is this good
337        f.write_debug(&**self)
338    }
339}
340
341impl Debug for Box<dyn std::error::Error + Send + Sync + '_> {
342    fn fmt(&self, f: &mut Formatter) {
343        // TODO: Is this good
344        f.write_debug(&**self)
345    }
346}
347
348impl Debug for std::io::Error {
349    fn fmt(&self, f: &mut Formatter) {
350        Debug::fmt(&self.kind(), f) // TODO: This isn't ideal
351    }
352}
353impl Debug for std::io::ErrorKind {
354    fn fmt(&self, f: &mut Formatter) {
355        // Quite alot of these are nighty only
356        let kind = match self {
357            Self::NotFound => "NotFound",
358            Self::PermissionDenied => "PermissionDenied",
359            Self::ConnectionRefused => "ConnectionRefused",
360            Self::ConnectionReset => "ConnectionReset",
361            // Self::HostUnreachable => "HostUnreachable",
362            // Self::NetworkUnreachable => "NetworkUnreachable",
363            Self::ConnectionAborted => "ConnectionAborted",
364            Self::NotConnected => "NotConnected",
365            Self::AddrInUse => "AddrInUse",
366            Self::AddrNotAvailable => "AddrNotAvailable",
367            // Self::NetworkDown => "NetworkDown",
368            Self::BrokenPipe => "BrokenPipe",
369            Self::AlreadyExists => "AlreadyExists",
370            Self::WouldBlock => "WouldBlock",
371            // Self::NotADirectory => "NotADirectory",
372            // Self::IsADirectory => "IsADirectory",
373            // Self::DirectoryNotEmpty => "DirectoryNotEmpty",
374            // Self::ReadOnlyFilesystem => "ReadOnlyFilesystem",
375            // Self::FilesystemLoop => "FilesystemLoop",
376            // Self::StaleNetworkFileHandle => "StaleNetworkFileHandle",
377            Self::InvalidInput => "InvalidInput",
378            Self::InvalidData => "InvalidData",
379            Self::TimedOut => "TimedOut",
380            Self::WriteZero => "WriteZero",
381            // Self::StorageFull => "StorageFull",
382            // Self::NotSeekable => "NotSeekable",
383            // Self::FilesystemQuotaExceeded => "FilesystemQuotaExceeded",
384            // Self::FileTooLarge => "FileTooLarge",
385            // Self::ResourceBusy => "ResourceBusy",
386            // Self::ExecutableFileBusy => "ExecutableFileBusy",
387            // Self::Deadlock => "Deadlock",
388            // Self::CrossesDevices => "CrossesDevices",
389            // Self::TooManyLinks => "TooManyLinks",
390            // Self::InvalidFilename => "InvalidFilename",
391            // Self::ArgumentListTooLong => "ArgumentListTooLong",
392            Self::Interrupted => "Interrupted",
393            Self::Unsupported => "Unsupported",
394            Self::UnexpectedEof => "UnexpectedEof",
395            Self::OutOfMemory => "OutOfMemory",
396            Self::Other => "Other",
397            // Self::Uncategorized => "Uncategorized",
398            _ => "???",
399        };
400        f.write_display(kind)
401    }
402}
403
404impl Debug for std::num::ParseFloatError {
405    fn fmt(&self, f: &mut Formatter) {
406        f.debug_struct("ParseFloatError").finish() // TODO: This has a kind, but
407                                                   // it's secret.
408    }
409}
410
411impl<T: Debug> Debug for std::ops::Range<T> {
412    fn fmt(&self, f: &mut Formatter) {
413        Debug::fmt(&self.start, f);
414        f.word("..");
415        Debug::fmt(&self.end, f);
416    }
417}
418impl<T: Debug> Debug for std::ops::RangeFrom<T> {
419    fn fmt(&self, f: &mut Formatter) {
420        Debug::fmt(&self.start, f);
421        f.word("..");
422    }
423}
424impl Debug for std::ops::RangeFull {
425    fn fmt(&self, f: &mut Formatter) {
426        f.word("..")
427    }
428}
429impl<T: Debug> Debug for std::ops::RangeInclusive<T> {
430    fn fmt(&self, f: &mut Formatter) {
431        Debug::fmt(&self.start(), f);
432        f.word("..=");
433        Debug::fmt(&self.end(), f);
434    }
435}
436impl<T: Debug> Debug for std::ops::RangeTo<T> {
437    fn fmt(&self, f: &mut Formatter) {
438        f.word("..");
439        Debug::fmt(&self.end, f);
440    }
441}
442impl<T: Debug> Debug for std::ops::RangeToInclusive<T> {
443    fn fmt(&self, f: &mut Formatter) {
444        f.word("..=");
445        Debug::fmt(&self.end, f);
446    }
447}
448
449// TODO: Tests