#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct Border<T> {
pub top: Option<T>,
pub bottom: Option<T>,
pub left: Option<T>,
pub right: Option<T>,
pub left_top_corner: Option<T>,
pub left_bottom_corner: Option<T>,
pub right_top_corner: Option<T>,
pub right_bottom_corner: Option<T>,
}
impl<T> Border<T> {
#[allow(clippy::too_many_arguments)]
pub const fn new(
top: Option<T>,
bottom: Option<T>,
left: Option<T>,
right: Option<T>,
left_top_corner: Option<T>,
left_bottom_corner: Option<T>,
right_top_corner: Option<T>,
right_bottom_corner: Option<T>,
) -> Self {
Self {
top,
bottom,
left,
right,
left_top_corner,
left_bottom_corner,
right_top_corner,
right_bottom_corner,
}
}
#[allow(clippy::too_many_arguments)]
pub const fn full(
top: T,
bottom: T,
left: T,
right: T,
top_left: T,
top_right: T,
bottom_left: T,
bottom_right: T,
) -> Self {
Self::new(
Some(top),
Some(bottom),
Some(left),
Some(right),
Some(top_left),
Some(bottom_left),
Some(top_right),
Some(bottom_right),
)
}
pub const fn empty() -> Self {
Self::new(None, None, None, None, None, None, None, None)
}
pub const fn is_empty(&self) -> bool {
self.top.is_none()
&& self.left_top_corner.is_none()
&& self.right_top_corner.is_none()
&& self.bottom.is_none()
&& self.left_bottom_corner.is_none()
&& self.left_top_corner.is_none()
&& self.left.is_none()
&& self.right.is_none()
}
pub fn is_same(&self) -> bool
where
T: PartialEq,
{
self.top == self.bottom
&& self.top == self.left
&& self.top == self.right
&& self.top == self.left_top_corner
&& self.top == self.right_top_corner
&& self.top == self.left_bottom_corner
&& self.top == self.right_bottom_corner
}
pub const fn has_top(&self) -> bool {
self.top.is_some() || self.left_top_corner.is_some() || self.right_top_corner.is_some()
}
pub const fn has_bottom(&self) -> bool {
self.bottom.is_some()
|| self.left_bottom_corner.is_some()
|| self.right_bottom_corner.is_some()
}
pub const fn has_left(&self) -> bool {
self.left.is_some() || self.left_top_corner.is_some() || self.left_bottom_corner.is_some()
}
pub const fn has_right(&self) -> bool {
self.right.is_some()
|| self.right_top_corner.is_some()
|| self.right_bottom_corner.is_some()
}
pub fn map<F, T1>(self, f: F) -> Border<T1>
where
F: Fn(T) -> T1,
{
Border {
top: self.top.map(&f),
bottom: self.bottom.map(&f),
left: self.left.map(&f),
right: self.right.map(&f),
left_top_corner: self.left_top_corner.map(&f),
left_bottom_corner: self.left_bottom_corner.map(&f),
right_top_corner: self.right_top_corner.map(&f),
right_bottom_corner: self.right_bottom_corner.map(&f),
}
}
}
impl<T: Copy> Border<T> {
pub const fn filled(c: T) -> Self {
Self::full(c, c, c, c, c, c, c, c)
}
}
impl<T: Copy> Border<&T> {
pub fn copied(&self) -> Border<T> {
Border {
top: self.top.copied(),
bottom: self.bottom.copied(),
left: self.left.copied(),
right: self.right.copied(),
left_bottom_corner: self.left_bottom_corner.copied(),
left_top_corner: self.left_top_corner.copied(),
right_bottom_corner: self.right_bottom_corner.copied(),
right_top_corner: self.right_top_corner.copied(),
}
}
}
impl<T: Clone> Border<&T> {
pub fn cloned(&self) -> Border<T> {
Border {
top: self.top.cloned(),
bottom: self.bottom.cloned(),
left: self.left.cloned(),
right: self.right.cloned(),
left_bottom_corner: self.left_bottom_corner.cloned(),
left_top_corner: self.left_top_corner.cloned(),
right_bottom_corner: self.right_bottom_corner.cloned(),
right_top_corner: self.right_top_corner.cloned(),
}
}
}
impl<T> Border<T> {
pub fn convert<B>(self) -> Border<B>
where
B: From<T>,
{
macro_rules! conv_opt {
($opt:expr) => {
match $opt {
Some(opt) => Some(B::from(opt)),
None => None,
}
};
}
Border {
top: conv_opt!(self.top),
bottom: conv_opt!(self.bottom),
left: conv_opt!(self.left),
right: conv_opt!(self.right),
left_bottom_corner: conv_opt!(self.left_bottom_corner),
left_top_corner: conv_opt!(self.left_top_corner),
right_bottom_corner: conv_opt!(self.right_bottom_corner),
right_top_corner: conv_opt!(self.right_top_corner),
}
}
}