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/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)](#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}