iter_debug/lib.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2#![no_std]
3#![no_implicit_prelude]
4//! [](https://github.com/1e1001/iter-debug)
5//! [](https://crates.io/crates/iter-debug)
6//! [](https://docs.rs/iter-debug)
7//! [](#License)
8//!
9//! Allows debugging iterators without collecting them to a
10//! [`Vec`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html) first, such as for `no_std` environments.
11//! ```
12//! # use iter_debug::DebugIterator;
13//! println!("{:?}", [1, 2, 3, 4].map(|v| v * 2).debug());
14//! // => [2, 4, 6, 8]
15//! ```
16extern crate core;
17
18use core::cell::Cell;
19use core::fmt::{Debug, Error, Formatter, Result};
20use core::iter::IntoIterator;
21use core::marker::Sized;
22use core::option::Option;
23
24#[cfg(test)]
25mod tests;
26
27/// The whole point, see the [crate docs](`crate`).
28///
29/// Note that the iterator can only be debugged once, aim to debug your iterator
30/// as late as possible, usually directly in the print / format statement.
31pub struct IterDebug<T>(Cell<Option<T>>);
32
33impl<T> IterDebug<T> {
34 /// Construct a new instance directly, instead of using the
35 /// [`debug`](DebugIterator::debug) method.
36 #[inline]
37 pub fn new(item: T) -> Self {
38 Self(Cell::new(Option::Some(item)))
39 }
40 /// Attempt to extract the inner iterator, returning [`None`](Option::None)
41 /// if it has already been removed or debug printed.
42 #[inline]
43 pub fn try_into_inner(&self) -> Option<T> {
44 self.0.take()
45 }
46}
47
48impl<T> Debug for IterDebug<T>
49where
50 T: IntoIterator,
51 T::Item: Debug,
52{
53 #[inline]
54 fn fmt(&self, formatter: &mut Formatter) -> Result {
55 self.0
56 .take()
57 .ok_or(Error)
58 .and_then(|value| formatter.debug_list().entries(value).finish())
59 }
60}
61
62/// Helper trait that lets you `.debug()` an iterator, like the other
63/// combinators.
64///
65/// Automatically implemented for all [`IntoIterator`] where the item
66/// is [`Debug`].
67pub trait DebugIterator {
68 /// Convert this iterator into an [`IterDebug`] for printing
69 #[inline]
70 fn debug(self) -> IterDebug<Self>
71 where
72 Self: Sized,
73 {
74 IterDebug::new(self)
75 }
76}
77impl<T> DebugIterator for T
78where
79 T: IntoIterator,
80 T::Item: Debug,
81{
82}