use core::{
cell::Cell,
fmt::{self, Display, Formatter},
};
use crate::Literator;
pub struct Join<I, D> {
iter: Cell<Option<I>>,
delim: D,
}
impl<I: Copy, D: Clone> Clone for Join<I, D> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
delim: self.delim.clone(),
}
}
}
impl<D, I> Join<I, D>
where
D: Display,
I: Literator,
{
pub(super) fn new(iter: I, delim: D) -> Self {
Join {
iter: Cell::new(Some(iter)),
delim,
}
}
pub(crate) fn do_fmt<F>(&self, f: &mut Formatter, fmt_item: F) -> fmt::Result
where
F: Fn(&I::Item, &mut Formatter) -> fmt::Result,
{
let Some(mut iter) = self.iter.take() else {
return Ok(());
};
if let Some(first) = iter.next() {
fmt_item(&first, f)?;
for item in iter {
write!(f, "{}", self.delim)?;
fmt_item(&item, f)?;
}
}
Ok(())
}
}
pub struct ConjunctiveJoin<I, D = &'static str, L = &'static str> {
iter: Cell<Option<I>>,
delim: D,
last: L,
}
impl<I, D, L> Clone for ConjunctiveJoin<I, D, L>
where
I: Copy,
D: Clone,
L: Clone,
{
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
delim: self.delim.clone(),
last: self.last.clone(),
}
}
}
impl<I, D, L> ConjunctiveJoin<I, D, L>
where
I: Literator,
D: Display,
L: Display,
{
pub(super) fn new(iter: I, delim: D, last: L) -> Self {
Self {
iter: Cell::new(Some(iter)),
delim,
last,
}
}
pub(crate) fn do_fmt<F>(&self, f: &mut Formatter, fmt_item: F) -> fmt::Result
where
F: Fn(&I::Item, &mut Formatter) -> fmt::Result,
{
let Self { iter, delim, last } = self;
let Some(mut iter) = iter.take() else {
return Ok(());
};
let Some(first) = iter.next() else {
return Ok(());
};
fmt_item(&first, f)?;
let Some(mut current) = iter.next() else {
return Ok(());
};
while let Some(lookahead) = iter.next() {
write!(f, "{delim}")?;
fmt_item(¤t, f)?;
current = lookahead;
}
write!(f, "{last}")?;
fmt_item(¤t, f)
}
}
pub struct OxfordJoin<
I,
Delim = &'static str,
ExactlyTwo = &'static str,
FinalDelimConjunction = &'static str,
> {
iter: Cell<Option<I>>,
sep: Delim,
two_sep: ExactlyTwo,
last_sep: FinalDelimConjunction,
}
impl<I, D1, D2, D3> Clone for OxfordJoin<I, D1, D2, D3>
where
I: Copy,
D1: Clone,
D2: Clone,
D3: Clone,
{
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
sep: self.sep.clone(),
two_sep: self.two_sep.clone(),
last_sep: self.last_sep.clone(),
}
}
}
impl<I, D1, D2, D3> OxfordJoin<I, D1, D2, D3>
where
I: Literator,
D1: Display,
D2: Display,
D3: Display,
{
pub(super) fn new(iter: I, sep: D1, two_sep: D2, last_sep: D3) -> Self {
Self {
iter: Cell::new(Some(iter)),
sep,
two_sep,
last_sep,
}
}
pub(crate) fn do_fmt<F>(&self, f: &mut Formatter, fmt_item: F) -> fmt::Result
where
F: Fn(&I::Item, &mut Formatter) -> fmt::Result,
{
let Self {
iter,
sep,
two_sep,
last_sep,
} = self;
let Some(mut iter) = iter.take() else {
return Ok(());
};
let Some(first) = iter.next() else {
return Ok(());
};
fmt_item(&first, f)?;
let Some(second) = iter.next() else {
return Ok(());
};
let mut lookahead = iter.next();
if lookahead.is_none() {
write!(f, "{two_sep}")?;
return fmt_item(&second, f);
}
let mut next = second;
while let Some(next_next) = lookahead {
write!(f, "{sep}")?;
fmt_item(&next, f)?;
next = next_next;
lookahead = iter.next();
}
write!(f, "{last_sep}")?;
fmt_item(&next, f)
}
}