use crate::cell::*;
use crate::Cells;
pub struct CellsFormatter<'a, 'b, T: ?Sized> {
w: &'a mut dyn CellsWrite,
d: Option<&'b T>,
stretch: bool,
}
impl<'a, 'b, T: ?Sized> CellsFormatter<'a, 'b, T> {
pub(crate) fn new(w: &'a mut dyn CellsWrite, d: Option<&'b T>) -> Self {
Self {
w,
d,
stretch: false,
}
}
pub fn column_with(
&mut self,
header: impl RawCell,
f: impl FnOnce(&mut CellsFormatter<'_, 'b, T>),
) {
self.w.column_start(&header);
f(self);
self.w.column_end(&header);
}
pub fn content<U: Cells>(&mut self, f: impl FnOnce(&'b T) -> U) {
self.map_with(f, U::fmt)
}
pub(crate) fn content_cell<U: RawCell>(&mut self, f: impl FnOnce(&'b T) -> U) {
self.w.content(
self.d.map(f).as_ref().map(|x| x as &dyn RawCell),
self.stretch,
);
}
pub fn column<U: Cells>(&mut self, header: impl RawCell, f: impl FnOnce(&'b T) -> U) {
self.column_with(header, |cf| cf.content(f));
}
pub fn map<U: ?Sized>(&mut self, m: impl FnOnce(&T) -> &U) -> CellsFormatter<'_, 'b, U> {
CellsFormatter {
w: self.w,
d: self.d.map(m),
stretch: self.stretch,
}
}
pub fn map_with<U>(
&mut self,
m: impl FnOnce(&'b T) -> U,
f: impl FnOnce(&mut CellsFormatter<U>),
) {
f(&mut CellsFormatter {
w: self.w,
d: self.d.map(m).as_ref(),
stretch: self.stretch,
});
}
pub fn filter(&mut self, f: impl FnOnce(&T) -> bool) -> CellsFormatter<T> {
CellsFormatter {
w: self.w,
d: self.d.filter(|data| f(data)),
stretch: self.stretch,
}
}
pub fn filter_map<U>(&mut self, f: impl FnOnce(&T) -> Option<&U>) -> CellsFormatter<'_, 'b, U> {
CellsFormatter {
w: self.w,
d: self.d.and_then(f),
stretch: self.stretch,
}
}
pub fn filter_map_with<U>(
&mut self,
f: impl FnOnce(&'b T) -> Option<U>,
some: impl FnOnce(&mut CellsFormatter<U>),
) {
some(&mut CellsFormatter {
w: self.w,
d: self.d.and_then(f).as_ref(),
stretch: self.stretch,
});
}
pub fn try_map_with<O, E: RawCell>(
&mut self,
f: impl FnOnce(&'b T) -> std::result::Result<O, E>,
ok: impl FnOnce(&mut CellsFormatter<O>),
) {
let d = self.d.map(f);
if let Some(Err(e)) = &d {
self.w.content_start(e);
}
ok(&mut CellsFormatter {
w: self.w,
d: d.as_ref().and_then(|x| x.as_ref().ok()),
stretch: self.stretch,
});
if let Some(Err(e)) = &d {
self.w.content_end(e);
}
}
pub fn stretch(&mut self) -> CellsFormatter<'_, 'b, T> {
CellsFormatter {
w: self.w,
d: self.d,
stretch: true,
}
}
pub fn with(&mut self, f: impl Fn(&mut Self)) {
f(self);
}
}
impl<'a, 'b, T: ?Sized> CellsFormatter<'a, 'b, &T> {
pub fn unref(&mut self) -> CellsFormatter<T> {
CellsFormatter {
w: self.w,
d: self.d.map(|x| &**x),
stretch: self.stretch,
}
}
}
impl<'a, 'b, T: ?Sized> CellsFormatter<'a, 'b, &mut T> {
pub fn unref(&mut self) -> CellsFormatter<T> {
CellsFormatter {
w: self.w,
d: self.d.map(|x| &**x),
stretch: self.stretch,
}
}
}
pub(crate) trait CellsWrite {
fn content(&mut self, cell: Option<&dyn RawCell>, stretch: bool);
fn content_start(&mut self, cell: &dyn RawCell);
fn content_end(&mut self, cell: &dyn RawCell);
fn column_start(&mut self, header: &dyn RawCell);
fn column_end(&mut self, header: &dyn RawCell);
}