use std::num::NonZeroU16;
use crate::cells::TAB_WIDTH;
use crate::line::Line;
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct Measurement {
minimum: u16,
maximum: u16,
}
impl Measurement {
#[must_use]
pub fn new(minimum: u16, maximum: u16) -> Self {
Self {
minimum,
maximum: maximum.max(minimum),
}
}
#[must_use]
pub fn exact(width: u16) -> Self {
Self::new(width, width)
}
#[must_use]
pub fn minimum(self) -> u16 {
self.minimum
}
#[must_use]
pub fn maximum(self) -> u16 {
self.maximum
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum BoxChars {
#[default]
Unicode,
Ascii,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Context {
width: u16,
unbounded: bool,
tab_width: NonZeroU16,
box_chars: BoxChars,
}
impl Context {
#[must_use]
pub fn new(width: u16) -> Self {
Self {
width,
unbounded: false,
tab_width: TAB_WIDTH,
box_chars: BoxChars::default(),
}
}
#[must_use]
pub fn unbounded() -> Self {
Self {
unbounded: true,
..Self::new(u16::MAX)
}
}
#[must_use]
pub fn at_width(&self, width: u16) -> Self {
Self {
width,
..self.clone()
}
}
#[must_use]
pub fn at_tab_width(&self, tab_width: NonZeroU16) -> Self {
Self {
tab_width,
..self.clone()
}
}
#[must_use]
pub fn using_box_chars(&self, box_chars: BoxChars) -> Self {
Self {
box_chars,
..self.clone()
}
}
#[must_use]
pub fn width(&self) -> u16 {
self.width
}
#[must_use]
pub fn is_unbounded(&self) -> bool {
self.unbounded
}
#[must_use]
pub fn tab_width(&self) -> NonZeroU16 {
self.tab_width
}
#[must_use]
pub fn box_chars(&self) -> BoxChars {
self.box_chars
}
}
pub trait Renderable {
fn measure(&self, context: &Context) -> Measurement;
fn render(&self, context: &Context) -> Vec<Line>;
}
impl<T: Renderable + ?Sized> Renderable for &T {
fn measure(&self, context: &Context) -> Measurement {
(**self).measure(context)
}
fn render(&self, context: &Context) -> Vec<Line> {
(**self).render(context)
}
}
impl<T: Renderable + ?Sized> Renderable for Box<T> {
fn measure(&self, context: &Context) -> Measurement {
(**self).measure(context)
}
fn render(&self, context: &Context) -> Vec<Line> {
(**self).render(context)
}
}