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