use alloc::string::{String, ToString};
use crate::corety::AzString;
use crate::props::formatter::PrintAsCssValue;
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum LayoutDisplay {
None,
#[default]
Block,
Inline,
InlineBlock,
Flex,
InlineFlex,
Table,
InlineTable,
TableRowGroup,
TableHeaderGroup,
TableFooterGroup,
TableRow,
TableColumnGroup,
TableColumn,
TableCell,
TableCaption,
FlowRoot,
ListItem,
RunIn,
Marker,
Grid,
InlineGrid,
Contents,
}
impl LayoutDisplay {
#[must_use] pub const fn creates_block_context(&self) -> bool {
matches!(
self,
Self::Block
| Self::FlowRoot
| Self::Flex
| Self::Grid
| Self::Table
| Self::ListItem
)
}
#[must_use] pub const fn creates_flex_context(&self) -> bool {
matches!(self, Self::Flex | Self::InlineFlex)
}
#[must_use] pub const fn creates_table_context(&self) -> bool {
matches!(self, Self::Table | Self::InlineTable)
}
#[must_use] pub const fn is_layout_internal(&self) -> bool {
matches!(
self,
Self::TableRowGroup
| Self::TableHeaderGroup
| Self::TableFooterGroup
| Self::TableRow
| Self::TableColumnGroup
| Self::TableColumn
| Self::TableCell
| Self::TableCaption
)
}
#[must_use] pub const fn is_inline_level(&self) -> bool {
matches!(
self,
Self::Inline
| Self::InlineBlock
| Self::InlineFlex
| Self::InlineTable
| Self::InlineGrid
)
}
}
impl PrintAsCssValue for LayoutDisplay {
fn print_as_css_value(&self) -> String {
String::from(match self {
Self::None => "none",
Self::Block => "block",
Self::Inline => "inline",
Self::InlineBlock => "inline-block",
Self::Flex => "flex",
Self::InlineFlex => "inline-flex",
Self::Table => "table",
Self::InlineTable => "inline-table",
Self::TableRowGroup => "table-row-group",
Self::TableHeaderGroup => "table-header-group",
Self::TableFooterGroup => "table-footer-group",
Self::TableRow => "table-row",
Self::TableColumnGroup => "table-column-group",
Self::TableColumn => "table-column",
Self::TableCell => "table-cell",
Self::TableCaption => "table-caption",
Self::ListItem => "list-item",
Self::RunIn => "run-in",
Self::Marker => "marker",
Self::FlowRoot => "flow-root",
Self::Grid => "grid",
Self::InlineGrid => "inline-grid",
Self::Contents => "contents",
})
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum LayoutFloat {
Left,
Right,
#[default]
None,
}
impl PrintAsCssValue for LayoutFloat {
fn print_as_css_value(&self) -> String {
String::from(match self {
Self::Left => "left",
Self::Right => "right",
Self::None => "none",
})
}
}
#[cfg(feature = "parser")]
#[derive(Clone, PartialEq, Eq)]
pub enum LayoutDisplayParseError<'a> {
InvalidValue(&'a str),
}
#[cfg(feature = "parser")]
impl_debug_as_display!(LayoutDisplayParseError<'a>);
#[cfg(feature = "parser")]
impl_display! { LayoutDisplayParseError<'a>, {
InvalidValue(val) => format!("Invalid display value: \"{}\"", val),
}}
#[cfg(feature = "parser")]
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C, u8)]
pub enum LayoutDisplayParseErrorOwned {
InvalidValue(AzString),
}
#[cfg(feature = "parser")]
impl LayoutDisplayParseError<'_> {
#[must_use] pub fn to_contained(&self) -> LayoutDisplayParseErrorOwned {
match self {
Self::InvalidValue(s) => LayoutDisplayParseErrorOwned::InvalidValue((*s).to_string().into()),
}
}
}
#[cfg(feature = "parser")]
impl LayoutDisplayParseErrorOwned {
#[must_use] pub fn to_shared(&self) -> LayoutDisplayParseError<'_> {
match self {
Self::InvalidValue(s) => LayoutDisplayParseError::InvalidValue(s.as_str()),
}
}
}
#[cfg(feature = "parser")]
pub fn parse_layout_display(
input: &str,
) -> Result<LayoutDisplay, LayoutDisplayParseError<'_>> {
let input = input.trim();
match input {
"none" => Ok(LayoutDisplay::None),
"block" => Ok(LayoutDisplay::Block),
"inline" => Ok(LayoutDisplay::Inline),
"inline-block" => Ok(LayoutDisplay::InlineBlock),
"flex" => Ok(LayoutDisplay::Flex),
"inline-flex" => Ok(LayoutDisplay::InlineFlex),
"table" => Ok(LayoutDisplay::Table),
"inline-table" => Ok(LayoutDisplay::InlineTable),
"table-row-group" => Ok(LayoutDisplay::TableRowGroup),
"table-header-group" => Ok(LayoutDisplay::TableHeaderGroup),
"table-footer-group" => Ok(LayoutDisplay::TableFooterGroup),
"table-row" => Ok(LayoutDisplay::TableRow),
"table-column-group" => Ok(LayoutDisplay::TableColumnGroup),
"table-column" => Ok(LayoutDisplay::TableColumn),
"table-cell" => Ok(LayoutDisplay::TableCell),
"table-caption" => Ok(LayoutDisplay::TableCaption),
"list-item" => Ok(LayoutDisplay::ListItem),
"run-in" => Ok(LayoutDisplay::RunIn),
"marker" => Ok(LayoutDisplay::Marker),
"grid" => Ok(LayoutDisplay::Grid),
"inline-grid" => Ok(LayoutDisplay::InlineGrid),
"flow-root" => Ok(LayoutDisplay::FlowRoot),
"contents" => Ok(LayoutDisplay::Contents),
_ => Err(LayoutDisplayParseError::InvalidValue(input)),
}
}
#[cfg(feature = "parser")]
#[derive(Clone, PartialEq, Eq)]
pub enum LayoutFloatParseError<'a> {
InvalidValue(&'a str),
}
#[cfg(feature = "parser")]
impl_debug_as_display!(LayoutFloatParseError<'a>);
#[cfg(feature = "parser")]
impl_display! { LayoutFloatParseError<'a>, {
InvalidValue(val) => format!("Invalid float value: \"{}\"", val),
}}
#[cfg(feature = "parser")]
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C, u8)]
pub enum LayoutFloatParseErrorOwned {
InvalidValue(AzString),
}
#[cfg(feature = "parser")]
impl LayoutFloatParseError<'_> {
#[must_use] pub fn to_contained(&self) -> LayoutFloatParseErrorOwned {
match self {
Self::InvalidValue(s) => LayoutFloatParseErrorOwned::InvalidValue((*s).to_string().into()),
}
}
}
#[cfg(feature = "parser")]
impl LayoutFloatParseErrorOwned {
#[must_use] pub fn to_shared(&self) -> LayoutFloatParseError<'_> {
match self {
Self::InvalidValue(s) => LayoutFloatParseError::InvalidValue(s.as_str()),
}
}
}
#[cfg(feature = "parser")]
pub fn parse_layout_float(input: &str) -> Result<LayoutFloat, LayoutFloatParseError<'_>> {
let input = input.trim();
match input {
"left" => Ok(LayoutFloat::Left),
"right" => Ok(LayoutFloat::Right),
"none" => Ok(LayoutFloat::None),
_ => Err(LayoutFloatParseError::InvalidValue(input)),
}
}
#[cfg(all(test, feature = "parser"))]
mod tests {
use super::*;
#[test]
#[allow(clippy::cognitive_complexity)] fn test_parse_layout_display() {
assert_eq!(parse_layout_display("block").unwrap(), LayoutDisplay::Block);
assert_eq!(
parse_layout_display("inline").unwrap(),
LayoutDisplay::Inline
);
assert_eq!(
parse_layout_display("inline-block").unwrap(),
LayoutDisplay::InlineBlock
);
assert_eq!(parse_layout_display("flex").unwrap(), LayoutDisplay::Flex);
assert_eq!(
parse_layout_display("inline-flex").unwrap(),
LayoutDisplay::InlineFlex
);
assert_eq!(parse_layout_display("grid").unwrap(), LayoutDisplay::Grid);
assert_eq!(
parse_layout_display("inline-grid").unwrap(),
LayoutDisplay::InlineGrid
);
assert_eq!(parse_layout_display("none").unwrap(), LayoutDisplay::None);
assert_eq!(
parse_layout_display("flow-root").unwrap(),
LayoutDisplay::FlowRoot
);
assert_eq!(
parse_layout_display("list-item").unwrap(),
LayoutDisplay::ListItem
);
assert!(parse_layout_display("inherit").is_err());
assert!(parse_layout_display("initial").is_err());
assert_eq!(parse_layout_display("table").unwrap(), LayoutDisplay::Table);
assert_eq!(
parse_layout_display("inline-table").unwrap(),
LayoutDisplay::InlineTable
);
assert_eq!(
parse_layout_display("table-row").unwrap(),
LayoutDisplay::TableRow
);
assert_eq!(
parse_layout_display("table-cell").unwrap(),
LayoutDisplay::TableCell
);
assert_eq!(
parse_layout_display("table-caption").unwrap(),
LayoutDisplay::TableCaption
);
assert_eq!(
parse_layout_display("table-column-group").unwrap(),
LayoutDisplay::TableColumnGroup
);
assert_eq!(
parse_layout_display("table-header-group").unwrap(),
LayoutDisplay::TableHeaderGroup
);
assert_eq!(
parse_layout_display("table-footer-group").unwrap(),
LayoutDisplay::TableFooterGroup
);
assert_eq!(
parse_layout_display("table-row-group").unwrap(),
LayoutDisplay::TableRowGroup
);
assert_eq!(
parse_layout_display(" inline-flex ").unwrap(),
LayoutDisplay::InlineFlex
);
assert!(parse_layout_display("invalid-value").is_err());
assert!(parse_layout_display("").is_err());
assert!(parse_layout_display("display").is_err());
}
#[test]
fn test_parse_layout_float() {
assert_eq!(parse_layout_float("left").unwrap(), LayoutFloat::Left);
assert_eq!(parse_layout_float("right").unwrap(), LayoutFloat::Right);
assert_eq!(parse_layout_float("none").unwrap(), LayoutFloat::None);
assert_eq!(parse_layout_float(" right ").unwrap(), LayoutFloat::Right);
assert!(parse_layout_float("center").is_err());
assert!(parse_layout_float("").is_err());
assert!(parse_layout_float("float-left").is_err());
}
}