pub struct Joiner<I, S>
where
I: std::iter::Iterator,
S: std::fmt::Display,
{
iter: I,
sep: S,
}
impl<I, S> Joiner<I, S>
where
I: std::iter::Iterator,
S: std::fmt::Display,
{
#[inline]
pub fn new(iter: I, sep: S) -> Self {
Self { iter, sep }
}
#[inline]
pub fn into_string(self) -> String
where I::Item: std::fmt::Display {
let mut buffer = String::new();
let _ = self.write_fmt(&mut buffer);
buffer
}
pub fn write_fmt<W: std::fmt::Write>(mut self, mut writer: W) -> std::fmt::Result
where I::Item: std::fmt::Display {
if let Some(first) = self.iter.next() {
write!(writer, "{}", first)?;
for item in self.iter {
write!(writer, "{}{}", self.sep, item)?;
}
}
Ok(())
}
pub fn write_io<W: std::io::Write>(mut self, mut writer: W) -> std::io::Result<()>
where I::Item: std::fmt::Display {
if let Some(first) = self.iter.next() {
write!(writer, "{}", first)?;
for item in self.iter {
write!(writer, "{}{}", self.sep, item)?;
}
}
Ok(())
}
}
impl<I, S> From<Joiner<I, S>> for String
where
I: std::iter::Iterator,
S: std::fmt::Display,
I::Item: std::fmt::Display,
{
#[inline]
fn from(value: Joiner<I, S>) -> Self {
value.into_string()
}
}
impl<I, S> Clone for Joiner<I, S>
where
I: std::iter::Iterator,
S: std::fmt::Display,
I::Item: std::fmt::Display,
I: Clone,
S: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
sep: self.sep.clone(),
}
}
}
impl<I, S> std::fmt::Display for Joiner<I, S>
where
I: std::iter::Iterator,
S: std::fmt::Display,
I::Item: std::fmt::Display,
I: Clone,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut iter = self.iter.clone();
if let Some(first) = iter.next() {
first.fmt(f)?;
for item in iter {
self.sep.fmt(f)?;
item.fmt(f)?;
}
}
Ok(())
}
}
impl<I, S> std::fmt::Debug for Joiner<I, S>
where
I: std::iter::Iterator,
S: std::fmt::Display,
I::Item: std::fmt::Debug,
I: Clone,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut iter = self.iter.clone();
if let Some(first) = iter.next() {
first.fmt(f)?;
for item in iter {
self.sep.fmt(f)?;
item.fmt(f)?;
}
}
Ok(())
}
}
pub trait Join<I: std::iter::Iterator>: std::iter::IntoIterator<IntoIter = I> {
#[inline]
fn join<S>(self, sep: S) -> Joiner<I, S>
where
Self: Sized,
S: std::fmt::Display,
{
Joiner {
iter: self.into_iter(),
sep,
}
}
#[inline]
fn join_str<S>(self, sep: S) -> Joiner<DisplayIter<I>, DisplayWrapper<S>>
where
Self: Sized,
S: AsRef<str>,
I::Item: AsRef<str>,
{
Joiner {
iter: DisplayIter {
iter: self.into_iter(),
},
sep: DisplayWrapper(sep),
}
}
}
impl<T> Join<T::IntoIter> for T where T: std::iter::IntoIterator {}
#[repr(transparent)]
#[derive(Debug)]
pub struct DisplayWrapper<T: AsRef<str>>(T);
impl<T: AsRef<str>> DisplayWrapper<T> {
#[inline]
pub fn new(value: T) -> Self {
Self(value)
}
}
impl<T> std::fmt::Display for DisplayWrapper<T>
where
T: AsRef<str>,
{
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.as_ref().fmt(f)
}
}
impl<T> Clone for DisplayWrapper<T>
where
T: AsRef<str>,
T: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T> AsRef<str> for DisplayWrapper<T>
where
T: AsRef<str>,
{
#[inline]
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
#[derive(Debug)]
pub struct DisplayIter<I>
where
I: std::iter::Iterator,
{
iter: I,
}
impl<I> DisplayIter<I>
where
I: std::iter::Iterator,
{
#[inline]
pub fn new(elements: impl Join<I>) -> Self {
Self {
iter: elements.into_iter(),
}
}
}
impl<I> std::iter::Iterator for DisplayIter<I>
where
I: std::iter::Iterator,
I::Item: AsRef<str>,
{
type Item = DisplayWrapper<I::Item>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let Some(item) = self.iter.next() {
return Some(DisplayWrapper(item));
}
None
}
#[inline]
fn last(self) -> Option<Self::Item>
where
Self: Sized,
{
if let Some(item) = self.iter.last() {
return Some(DisplayWrapper(item));
}
None
}
#[inline]
fn count(self) -> usize
where
Self: Sized,
{
self.iter.count()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n).map(DisplayWrapper)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline]
#[cfg(target_feature = "iter_advance_by")]
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
self.iter.advance_by(n)
}
#[inline]
#[cfg(target_feature = "trusted_random_access")]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
{
DisplayWrapper(self.iter.__iterator_get_unchecked(idx))
}
}
impl<I> std::iter::ExactSizeIterator for DisplayIter<I>
where
I: std::iter::ExactSizeIterator,
I::Item: AsRef<str>,
{
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
#[inline]
#[cfg(target_feature = "exact_size_is_empty")]
fn is_empty(&self) -> bool {
self.iter.is_empty()
}
}
impl<I> std::iter::DoubleEndedIterator for DisplayIter<I>
where
I: std::iter::DoubleEndedIterator,
I::Item: AsRef<str>,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if let Some(item) = self.iter.next_back() {
return Some(DisplayWrapper(item));
}
None
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
if let Some(item) = self.iter.nth_back(n) {
return Some(DisplayWrapper(item));
}
None
}
#[inline]
#[cfg(target_feature = "iter_advance_by")]
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
self.iter.advance_back_by(n)
}
}
impl<I> Clone for DisplayIter<I>
where
I: std::iter::Iterator,
I: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
}
}
}
#[inline]
pub fn join<I, S>(elements: impl Join<I>, sep: S) -> Joiner<I, S>
where
I: std::iter::Iterator,
S: std::fmt::Display,
{
elements.join(sep)
}
#[inline]
pub fn join_str<I, S>(
elements: impl Join<I>,
sep: S,
) -> Joiner<impl std::iter::Iterator<Item = impl std::fmt::Display>, impl std::fmt::Display>
where
I: std::iter::Iterator,
I::Item: AsRef<str>,
S: AsRef<str>,
{
DisplayIter::new(elements).join(DisplayWrapper(sep))
}