use core::{
cell::Cell,
fmt::{Debug, Display},
};
use crate::{Literator, block::*, decorate::*, fmt::*, join::*};
pub struct Literate<I> {
iter: Cell<Option<I>>,
}
impl<I: Sized> Literate<I> {
pub const fn new(iter: I) -> Self {
Literate {
iter: Cell::new(Some(iter)),
}
}
pub fn into_inner(self) -> Option<I> {
self.iter.take()
}
pub fn map_iterator<F, O>(self, f: F) -> Literate<O>
where
F: FnOnce(I) -> O,
{
if let Some(iter) = self.iter.take() {
Literate::new(f(iter))
} else {
Literate {
iter: Cell::new(None),
}
}
}
fn map_literator<F, O>(self, f: F) -> Literate<O>
where
F: FnOnce(I) -> Literate<O>,
{
if let Some(iter) = self.iter.take() {
f(iter)
} else {
Literate {
iter: Cell::new(None),
}
}
}
}
impl<I: Clone> Clone for Literate<I> {
fn clone(&self) -> Self {
if let Some(value) = self.iter.take() {
let cloned = value.clone();
self.iter.set(Some(value)); Literate::new(cloned)
} else {
Literate {
iter: Cell::new(None),
}
}
}
}
impl<I> Display for Literate<I>
where
I: Iterator<Item: Display>,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let Some(mut iter) = self.iter.take() else {
return Ok(());
};
while let Some(item) = iter.next() {
item.fmt(f)?;
}
Ok(())
}
}
impl<I> Debug for Literate<I>
where
I: Iterator<Item: Debug>,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let Some(mut iter) = self.iter.take() else {
return Ok(());
};
while let Some(item) = iter.next() {
item.fmt(f)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::format;
struct Foo;
impl Display for Foo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("display")
}
}
impl Debug for Foo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("debug")
}
}
#[test]
fn forward_display_debug() {
assert_eq!(
format!("{}", Literate::new([Foo, Foo].iter())),
"displaydisplay"
);
assert_eq!(
format!("{:?}", Literate::new([Foo, Foo].iter())),
"debugdebug"
);
}
}
impl<I> Literator for Literate<I>
where
I: Iterator + Sized,
{
type Item = I::Item;
type Iter = I;
fn join<D>(self, delim: D) -> Join<Self::Iter, D>
where
Self: Sized,
D: Display,
{
Join::new_cell(self.iter.take(), delim)
}
fn concat(self) -> Self
where
Self: Sized,
{
self
}
fn conjunctive_join_custom<Delim, LastDelim>(
self,
delim: Delim,
last_delim: LastDelim,
) -> ConjunctiveJoin<Self::Iter, Delim, LastDelim>
where
Self: Sized,
Delim: Display,
LastDelim: Display,
{
ConjunctiveJoin::new_cell(self.iter.take(), delim, last_delim)
}
fn oxford_join_custom<Delim, ExactlyTwo, Final>(
self,
first_n: Delim,
exactly_two_conjunction: ExactlyTwo,
final_delim_conjunction: Final,
) -> OxfordJoin<Self::Iter, Delim, ExactlyTwo, Final>
where
Self: Sized,
Delim: Display,
ExactlyTwo: Display,
Final: Display,
{
OxfordJoin::new_cell(
self.iter.take(),
first_n,
exactly_two_conjunction,
final_delim_conjunction,
)
}
fn format_each_with<F>(
self,
with: F,
) -> Literate<impl Iterator<Item = FormatWith<Self::Item, F>>>
where
Self: Sized,
F: Fn(&Self::Item, &mut core::fmt::Formatter) -> core::fmt::Result + Clone,
{
self.map_literator(|i| i.format_each_with(with))
}
fn capitalize_first(self) -> Literate<impl Iterator<Item: Display>>
where
Self: Sized,
Self::Item: Display,
{
self.map_literator(|i| i.capitalize_first())
}
fn prefix_each_with<F>(
self,
with: F,
) -> Literate<impl Iterator<Item = PrefixWith<Self::Item, F>>>
where
F: Fn(&Self::Item, &mut core::fmt::Formatter) -> core::fmt::Result + Clone,
Self: Sized,
{
self.map_literator(|i| i.prefix_each_with(with))
}
fn suffix_each_with<F>(
self,
with: F,
) -> Literate<impl Iterator<Item = SuffixWith<Self::Item, F>>>
where
F: Fn(&Self::Item, &mut core::fmt::Formatter) -> core::fmt::Result + Clone,
Self: Sized,
{
self.map_literator(|i| i.suffix_each_with(with))
}
fn prefix_each<P>(self, prefix: P) -> Literate<impl Iterator<Item = Prefix<Self::Item, P>>>
where
P: Display + Clone,
Self: Sized,
{
self.map_literator(|i| i.prefix_each(prefix))
}
fn suffix_each<S>(self, suffix: S) -> Literate<impl Iterator<Item = Suffix<Self::Item, S>>>
where
S: Display + Clone,
Self: Sized,
{
self.map_literator(|i| i.suffix_each(suffix))
}
fn surround_each<P, S>(
self,
prefix: P,
suffix: S,
) -> Literate<impl Iterator<Item = Surround<Self::Item, P, S>>>
where
P: Display + Clone,
S: Display + Clone,
Self: Sized,
{
self.map_literator(|i| i.surround_each(prefix, suffix))
}
fn indent_each_custom<P, S>(
self,
level: usize,
indentation: P,
newline: S,
) -> Literate<impl Iterator<Item = Surround<Self::Item, Repeat<P>, S>>>
where
P: Display + Clone,
S: Display + Clone,
Self: Sized,
{
self.map_literator(|i| i.indent_each_custom(level, indentation, newline))
}
fn indented_block_custom<Open, Close, Indentation, Newline>(
self,
open: Open,
close: Close,
inner_level: usize,
indentation: Indentation,
newline: Newline,
) -> IndentedBlock<Self::Iter, Open, Close, Indentation, Newline>
where
Self: Sized,
Open: Display,
Close: Display,
Indentation: Display,
Newline: Display,
{
IndentedBlock::new_cell(
self.iter.take(),
open,
close,
indentation,
newline,
inner_level,
)
}
fn inline_block<P, D, S>(self, open: P, delim: D, close: S) -> InlineBlock<Self::Iter, P, D, S>
where
Self: Sized,
P: Display,
D: Display,
S: Display,
{
InlineBlock::new_cell(self.iter.take(), open, delim, close)
}
}