use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct BoxChars {
pub top_left: char,
pub top_right: char,
pub bottom_left: char,
pub bottom_right: char,
pub horizontal: char,
pub vertical: char,
pub vertical_right: char,
pub vertical_left: char,
pub horizontal_down: char,
pub horizontal_up: char,
pub cross: char,
}
impl BoxChars {
pub const ASCII: Self = Self {
top_left: '+',
top_right: '+',
bottom_left: '+',
bottom_right: '+',
horizontal: '-',
vertical: '|',
vertical_right: '+',
vertical_left: '+',
horizontal_down: '+',
horizontal_up: '+',
cross: '+',
};
pub const SQUARE: Self = Self {
top_left: '┌',
top_right: '┐',
bottom_left: '└',
bottom_right: '┘',
horizontal: '─',
vertical: '│',
vertical_right: '├',
vertical_left: '┤',
horizontal_down: '┬',
horizontal_up: '┴',
cross: '┼',
};
pub const ROUNDED: Self = Self {
top_left: '╭',
top_right: '╮',
bottom_left: '╰',
bottom_right: '╯',
horizontal: '─',
vertical: '│',
vertical_right: '├',
vertical_left: '┤',
horizontal_down: '┬',
horizontal_up: '┴',
cross: '┼',
};
pub const HEAVY: Self = Self {
top_left: '┏',
top_right: '┓',
bottom_left: '┗',
bottom_right: '┛',
horizontal: '━',
vertical: '┃',
vertical_right: '┣',
vertical_left: '┫',
horizontal_down: '┳',
horizontal_up: '┻',
cross: '╋',
};
pub const DOUBLE: Self = Self {
top_left: '╔',
top_right: '╗',
bottom_left: '╚',
bottom_right: '╝',
horizontal: '═',
vertical: '║',
vertical_right: '╠',
vertical_left: '╣',
horizontal_down: '╦',
horizontal_up: '╩',
cross: '╬',
};
pub const MINIMAL: Self = Self {
top_left: ' ',
top_right: ' ',
bottom_left: ' ',
bottom_right: ' ',
horizontal: '─',
vertical: ' ',
vertical_right: ' ',
vertical_left: ' ',
horizontal_down: '─',
horizontal_up: '─',
cross: '─',
};
pub const NONE: Self = Self {
top_left: ' ',
top_right: ' ',
bottom_left: ' ',
bottom_right: ' ',
horizontal: ' ',
vertical: ' ',
vertical_right: ' ',
vertical_left: ' ',
horizontal_down: ' ',
horizontal_up: ' ',
cross: ' ',
};
pub const SIMPLE: Self = Self {
top_left: '┌',
top_right: '┐',
bottom_left: '└',
bottom_right: '┘',
horizontal: '─',
vertical: '│',
vertical_right: '│',
vertical_left: '│',
horizontal_down: '─',
horizontal_up: '─',
cross: '─',
};
#[inline]
#[must_use]
pub const fn custom(
top_left: char,
top_right: char,
bottom_left: char,
bottom_right: char,
horizontal: char,
vertical: char,
) -> Self {
Self {
top_left,
top_right,
bottom_left,
bottom_right,
horizontal,
vertical,
vertical_right: vertical,
vertical_left: vertical,
horizontal_down: horizontal,
horizontal_up: horizontal,
cross: horizontal,
}
}
#[must_use]
pub fn top_border(&self, width: usize) -> String {
let inner_width = width.saturating_sub(2);
format!(
"{}{}{}",
self.top_left,
self.horizontal.to_string().repeat(inner_width),
self.top_right
)
}
#[must_use]
pub fn bottom_border(&self, width: usize) -> String {
let inner_width = width.saturating_sub(2);
format!(
"{}{}{}",
self.bottom_left,
self.horizontal.to_string().repeat(inner_width),
self.bottom_right
)
}
#[must_use]
pub fn row_divider(&self, width: usize) -> String {
let inner_width = width.saturating_sub(2);
format!(
"{}{}{}",
self.vertical_right,
self.horizontal.to_string().repeat(inner_width),
self.vertical_left
)
}
}
impl Default for BoxChars {
#[inline]
fn default() -> Self {
Self::ROUNDED
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ascii_box() {
let b = BoxChars::ASCII;
assert_eq!(b.top_left, '+');
assert_eq!(b.horizontal, '-');
assert_eq!(b.vertical, '|');
}
#[test]
fn test_rounded_box() {
let b = BoxChars::ROUNDED;
assert_eq!(b.top_left, '╭');
assert_eq!(b.top_right, '╮');
}
#[test]
fn test_top_border() {
let b = BoxChars::ASCII;
let border = b.top_border(10);
assert_eq!(border, "+--------+");
}
#[test]
fn test_bottom_border() {
let b = BoxChars::ASCII;
let border = b.bottom_border(10);
assert_eq!(border, "+--------+");
}
#[test]
fn test_row_divider() {
let b = BoxChars::SQUARE;
let divider = b.row_divider(10);
assert_eq!(divider, "├────────┤");
}
#[test]
fn test_default() {
let b = BoxChars::default();
assert_eq!(b.top_left, '╭');
}
#[test]
fn test_custom() {
let b = BoxChars::custom('*', '*', '*', '*', '=', '!');
assert_eq!(b.top_left, '*');
assert_eq!(b.horizontal, '=');
assert_eq!(b.vertical, '!');
}
}