#![cfg(feature = "std")]
use crate::{Alignment, PaddedValue, PanicOnExcess, Width};
use derive_builder::Builder;
use fmt_iter::FmtIter;
use std::{cmp::max, collections::LinkedList, fmt::Display};
#[derive(Debug, Clone, Copy, Builder)]
pub struct PaddedColumn<ValueIter, PadBlock = char, Pad = Alignment>
where
ValueIter: Iterator,
ValueIter::Item: Width,
PadBlock: Display + Copy,
Pad: crate::Pad<ValueIter::Item, PadBlock> + Copy,
{
pub values: ValueIter,
pub pad_block: PadBlock,
pub pad: Pad,
}
impl<ValueIter, PadBlock, Pad> IntoIterator for PaddedColumn<ValueIter, PadBlock, Pad>
where
ValueIter: Iterator,
ValueIter::Item: Width,
PadBlock: Display + Copy,
Pad: crate::Pad<ValueIter::Item, PadBlock> + Copy,
{
type Item = PaddedValue<ValueIter::Item, PadBlock, PanicOnExcess, Pad>;
type IntoIter = PaddedColumnIter<ValueIter::Item, PadBlock, Pad>;
fn into_iter(self) -> Self::IntoIter {
let PaddedColumn {
values,
pad_block,
pad,
} = self;
let mut iter = PaddedColumnIter::new(pad_block, pad);
iter.extend(values);
iter
}
}
#[derive(Debug, Clone)]
pub struct PaddedColumnIter<Value, PadBlock = char, Pad = Alignment>
where
Value: Width,
PadBlock: Display + Copy,
Pad: crate::Pad<Value, PadBlock> + Copy,
{
value_list: LinkedList<Value>,
pad_block: PadBlock,
pad: Pad,
total_width: usize,
}
impl<Value, PadBlock, Pad> PaddedColumnIter<Value, PadBlock, Pad>
where
Value: Width,
PadBlock: Display + Copy,
Pad: crate::Pad<Value, PadBlock> + Copy,
{
pub fn new(pad_block: PadBlock, pad: Pad) -> Self {
PaddedColumnIter {
value_list: LinkedList::new(),
total_width: 0,
pad_block,
pad,
}
}
pub fn push_back(&mut self, value: Value) {
self.total_width = max(self.total_width, value.width());
self.value_list.push_back(value);
}
pub fn pad_block(&self) -> PadBlock {
self.pad_block
}
pub fn pad(&self) -> Pad {
self.pad
}
pub fn total_width(&self) -> usize {
self.total_width
}
}
impl<Value, PadBlock, Pad> Iterator for PaddedColumnIter<Value, PadBlock, Pad>
where
Value: Width,
PadBlock: Display + Copy,
Pad: crate::Pad<Value, PadBlock> + Copy,
{
type Item = PaddedValue<Value, PadBlock, PanicOnExcess, Pad>;
fn next(&mut self) -> Option<Self::Item> {
let PaddedColumnIter {
value_list,
pad_block,
pad,
total_width,
} = self;
value_list.pop_front().map(|value| PaddedValue {
value,
pad_block: *pad_block,
pad: *pad,
total_width: *total_width,
handle_excess: PanicOnExcess,
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl<Value, PadBlock, Pad> ExactSizeIterator for PaddedColumnIter<Value, PadBlock, Pad>
where
Value: Width,
PadBlock: Display + Copy,
Pad: crate::Pad<Value, PadBlock> + Copy,
{
fn len(&self) -> usize {
self.value_list.len()
}
}
impl<Value, PadBlock, Pad> Extend<Value> for PaddedColumnIter<Value, PadBlock, Pad>
where
Value: Width,
PadBlock: Display + Copy,
Pad: crate::Pad<Value, PadBlock> + Copy,
{
fn extend<Values: IntoIterator<Item = Value>>(&mut self, values: Values) {
for value in values {
self.push_back(value);
}
}
}
impl<Value, PadBlock, Pad> Width for FmtIter<PaddedColumnIter<Value, PadBlock, Pad>>
where
Value: Width + Clone,
PadBlock: Display + Copy,
Pad: crate::Pad<Value, PadBlock> + Copy,
{
fn width(&self) -> usize {
self.total_width() * self.len()
}
}