perf(borders): allow border!() in const (#977)

This allows more compiler optimizations when the macro is used.
This commit is contained in:
EdJoPaTo 2024-03-04 06:17:28 +01:00 committed by GitHub
parent c12bcfefa2
commit e02f4768ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 72 additions and 41 deletions

View file

@ -51,39 +51,52 @@ impl Debug for Borders {
} }
} }
/// Macro that constructs and returns a [`Borders`] object from TOP, BOTTOM, LEFT, RIGHT, NONE, and /// Macro that constructs and returns a combination of the [`Borders`] object from TOP, BOTTOM, LEFT
/// ALL. Internally it creates an empty `Borders` object and then inserts each bit flag specified /// and RIGHT.
/// into it using `Borders::insert()`. ///
/// When used with NONE you should consider omitting this completely. For ALL you should consider
/// [`Block::bordered()`](crate::widgets::Block::bordered) instead.
/// ///
/// ## Examples /// ## Examples
/// ///
///``` /// ```
/// use ratatui::{border, prelude::*, widgets::*}; /// # use ratatui::{border, prelude::*, widgets::*};
/// /// Block::new()
/// Block::default() /// .title("Construct Borders and use them in place")
/// //Construct a `Borders` object and use it in place
/// .borders(border!(TOP, BOTTOM)); /// .borders(border!(TOP, BOTTOM));
/// ```
/// ///
/// //`border!` can be called with any order of individual sides /// `border!` can be called with any number of individual sides:
/// let bottom_first = border!(BOTTOM, LEFT, TOP); ///
/// //with the ALL keyword which works as expected /// ```
/// let all = border!(ALL); /// # use ratatui::{border, prelude::*, widgets::*};
/// //or with nothing to return a `Borders::NONE' bitflag. /// let right_open = border!(TOP, LEFT, BOTTOM);
/// let none = border!(NONE); /// assert_eq!(right_open, Borders::TOP | Borders::LEFT | Borders::BOTTOM);
/// ```
///
/// Single borders work but using `Borders::` directly would be simpler.
///
/// ```
/// # use ratatui::{border, prelude::*, widgets::*};
/// assert_eq!(border!(TOP), Borders::TOP);
/// assert_eq!(border!(ALL), Borders::ALL);
/// assert_eq!(border!(), Borders::NONE);
/// ``` /// ```
#[cfg(feature = "macros")] #[cfg(feature = "macros")]
#[macro_export] #[macro_export]
macro_rules! border { macro_rules! border {
( $($b:tt), +) => {{ () => {
let mut border = Borders::empty();
$(
border.insert(Borders::$b);
)*
border
}};
() =>{
Borders::NONE Borders::NONE
} };
($b:ident) => {
Borders::$b
};
($first:ident,$($other:ident),*) => {
Borders::$first
$(
.union(Borders::$other)
)*
};
} }
#[cfg(test)] #[cfg(test)]
@ -107,3 +120,40 @@ mod tests {
); );
} }
} }
#[cfg(all(test, feature = "macros"))]
mod macro_tests {
use super::*;
#[test]
fn can_be_const() {
const NOTHING: Borders = border!();
const JUST_TOP: Borders = border!(TOP);
const TOP_BOTTOM: Borders = border!(TOP, BOTTOM);
const RIGHT_OPEN: Borders = border!(TOP, LEFT, BOTTOM);
assert_eq!(NOTHING, Borders::NONE);
assert_eq!(JUST_TOP, Borders::TOP);
assert_eq!(TOP_BOTTOM, Borders::TOP | Borders::BOTTOM);
assert_eq!(RIGHT_OPEN, Borders::TOP | Borders::LEFT | Borders::BOTTOM);
}
#[test]
fn border_empty() {
let empty = Borders::NONE;
assert_eq!(empty, border!());
}
#[test]
fn border_all() {
let all = Borders::ALL;
assert_eq!(all, border!(ALL));
assert_eq!(all, border!(TOP, BOTTOM, LEFT, RIGHT));
}
#[test]
fn border_left_right() {
let left_right = Borders::from_bits(Borders::LEFT.bits() | Borders::RIGHT.bits());
assert_eq!(left_right, Some(border!(RIGHT, LEFT)));
}
}

View file

@ -1,19 +0,0 @@
#![cfg(feature = "macros")]
use ratatui::{border, widgets::Borders};
#[test]
fn border_empty_test() {
let empty = Borders::NONE;
assert_eq!(empty, border!());
}
#[test]
fn border_all_test() {
let all = Borders::ALL;
assert_eq!(all, border!(ALL));
assert_eq!(all, border!(TOP, BOTTOM, LEFT, RIGHT));
}
#[test]
fn border_left_right_test() {
let left_right = Borders::from_bits(Borders::LEFT.bits() | Borders::RIGHT.bits());
assert_eq!(left_right, Some(border!(RIGHT, LEFT)));
}