iter_debug/
lib.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2#![no_std]
3#![no_implicit_prelude]
4//! [![Repository](https://img.shields.io/badge/repository-GitHub-brightgreen.svg)](https://github.com/1e1001/rsutil/tree/main/iter-debug)
5//! [![Crates.io](https://img.shields.io/crates/v/iter-debug)](https://crates.io/crates/iter-debug)
6//! [![docs.rs](https://img.shields.io/docsrs/iter-debug)](https://docs.rs/iter-debug)
7//! [![MIT OR Apache-2.0](https://img.shields.io/crates/l/iter-debug)](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}