use alloc::string::{String, ToString};
use crate::{
format_rust_code::FormatAsRustCode,
props::{
basic::pixel::{CssPixelValueParseError, CssPixelValueParseErrorOwned, PixelValue},
formatter::PrintAsCssValue,
macros::PixelValueTaker,
},
};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum LayoutTableLayout {
Auto,
Fixed,
}
impl Default for LayoutTableLayout {
fn default() -> Self {
Self::Auto
}
}
impl PrintAsCssValue for LayoutTableLayout {
fn print_as_css_value(&self) -> String {
match self {
LayoutTableLayout::Auto => "auto".to_string(),
LayoutTableLayout::Fixed => "fixed".to_string(),
}
}
}
impl FormatAsRustCode for LayoutTableLayout {
fn format_as_rust_code(&self, _tabs: usize) -> String {
match self {
LayoutTableLayout::Auto => "LayoutTableLayout::Auto".to_string(),
LayoutTableLayout::Fixed => "LayoutTableLayout::Fixed".to_string(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum StyleBorderCollapse {
Separate,
Collapse,
}
impl Default for StyleBorderCollapse {
fn default() -> Self {
Self::Separate
}
}
impl PrintAsCssValue for StyleBorderCollapse {
fn print_as_css_value(&self) -> String {
match self {
StyleBorderCollapse::Separate => "separate".to_string(),
StyleBorderCollapse::Collapse => "collapse".to_string(),
}
}
}
impl FormatAsRustCode for StyleBorderCollapse {
fn format_as_rust_code(&self, _tabs: usize) -> String {
match self {
StyleBorderCollapse::Separate => "StyleBorderCollapse::Separate".to_string(),
StyleBorderCollapse::Collapse => "StyleBorderCollapse::Collapse".to_string(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct LayoutBorderSpacing {
pub horizontal: PixelValue,
pub vertical: PixelValue,
}
impl Default for LayoutBorderSpacing {
fn default() -> Self {
Self {
horizontal: PixelValue::const_px(0),
vertical: PixelValue::const_px(0),
}
}
}
impl LayoutBorderSpacing {
pub const fn new(spacing: PixelValue) -> Self {
Self {
horizontal: spacing,
vertical: spacing,
}
}
pub const fn new_separate(horizontal: PixelValue, vertical: PixelValue) -> Self {
Self {
horizontal,
vertical,
}
}
pub const fn zero() -> Self {
Self {
horizontal: PixelValue::const_px(0),
vertical: PixelValue::const_px(0),
}
}
}
impl PrintAsCssValue for LayoutBorderSpacing {
fn print_as_css_value(&self) -> String {
if self.horizontal == self.vertical {
self.horizontal.to_string()
} else {
format!("{} {}", self.horizontal, self.vertical)
}
}
}
impl FormatAsRustCode for LayoutBorderSpacing {
fn format_as_rust_code(&self, _tabs: usize) -> String {
use crate::format_rust_code::format_pixel_value;
format!(
"LayoutBorderSpacing {{ horizontal: {}, vertical: {} }}",
format_pixel_value(&self.horizontal),
format_pixel_value(&self.vertical)
)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum StyleCaptionSide {
Top,
Bottom,
}
impl Default for StyleCaptionSide {
fn default() -> Self {
Self::Top
}
}
impl PrintAsCssValue for StyleCaptionSide {
fn print_as_css_value(&self) -> String {
match self {
StyleCaptionSide::Top => "top".to_string(),
StyleCaptionSide::Bottom => "bottom".to_string(),
}
}
}
impl FormatAsRustCode for StyleCaptionSide {
fn format_as_rust_code(&self, _tabs: usize) -> String {
match self {
StyleCaptionSide::Top => "StyleCaptionSide::Top".to_string(),
StyleCaptionSide::Bottom => "StyleCaptionSide::Bottom".to_string(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum StyleEmptyCells {
Show,
Hide,
}
impl Default for StyleEmptyCells {
fn default() -> Self {
Self::Show
}
}
impl PrintAsCssValue for StyleEmptyCells {
fn print_as_css_value(&self) -> String {
match self {
StyleEmptyCells::Show => "show".to_string(),
StyleEmptyCells::Hide => "hide".to_string(),
}
}
}
impl FormatAsRustCode for StyleEmptyCells {
fn format_as_rust_code(&self, _tabs: usize) -> String {
match self {
StyleEmptyCells::Show => "StyleEmptyCells::Show".to_string(),
StyleEmptyCells::Hide => "StyleEmptyCells::Hide".to_string(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum LayoutTableLayoutParseError<'a> {
InvalidKeyword(&'a str),
}
pub fn parse_table_layout<'a>(
input: &'a str,
) -> Result<LayoutTableLayout, LayoutTableLayoutParseError<'a>> {
match input.trim() {
"auto" => Ok(LayoutTableLayout::Auto),
"fixed" => Ok(LayoutTableLayout::Fixed),
other => Err(LayoutTableLayoutParseError::InvalidKeyword(other)),
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum StyleBorderCollapseParseError<'a> {
InvalidKeyword(&'a str),
}
pub fn parse_border_collapse<'a>(
input: &'a str,
) -> Result<StyleBorderCollapse, StyleBorderCollapseParseError<'a>> {
match input.trim() {
"separate" => Ok(StyleBorderCollapse::Separate),
"collapse" => Ok(StyleBorderCollapse::Collapse),
other => Err(StyleBorderCollapseParseError::InvalidKeyword(other)),
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum LayoutBorderSpacingParseError<'a> {
PixelValue(CssPixelValueParseError<'a>),
InvalidFormat,
}
pub fn parse_border_spacing<'a>(
input: &'a str,
) -> Result<LayoutBorderSpacing, LayoutBorderSpacingParseError<'a>> {
use crate::props::basic::parse_pixel_value;
let parts: Vec<&str> = input.trim().split_whitespace().collect();
match parts.len() {
1 => {
let value =
parse_pixel_value(parts[0]).map_err(LayoutBorderSpacingParseError::PixelValue)?;
Ok(LayoutBorderSpacing::new(value))
}
2 => {
let horizontal =
parse_pixel_value(parts[0]).map_err(LayoutBorderSpacingParseError::PixelValue)?;
let vertical =
parse_pixel_value(parts[1]).map_err(LayoutBorderSpacingParseError::PixelValue)?;
Ok(LayoutBorderSpacing::new_separate(horizontal, vertical))
}
_ => Err(LayoutBorderSpacingParseError::InvalidFormat),
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum StyleCaptionSideParseError<'a> {
InvalidKeyword(&'a str),
}
pub fn parse_caption_side<'a>(
input: &'a str,
) -> Result<StyleCaptionSide, StyleCaptionSideParseError<'a>> {
match input.trim() {
"top" => Ok(StyleCaptionSide::Top),
"bottom" => Ok(StyleCaptionSide::Bottom),
other => Err(StyleCaptionSideParseError::InvalidKeyword(other)),
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum StyleEmptyCellsParseError<'a> {
InvalidKeyword(&'a str),
}
pub fn parse_empty_cells<'a>(
input: &'a str,
) -> Result<StyleEmptyCells, StyleEmptyCellsParseError<'a>> {
match input.trim() {
"show" => Ok(StyleEmptyCells::Show),
"hide" => Ok(StyleEmptyCells::Hide),
other => Err(StyleEmptyCellsParseError::InvalidKeyword(other)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_table_layout() {
assert_eq!(parse_table_layout("auto").unwrap(), LayoutTableLayout::Auto);
assert_eq!(
parse_table_layout("fixed").unwrap(),
LayoutTableLayout::Fixed
);
assert!(parse_table_layout("invalid").is_err());
}
#[test]
fn test_parse_border_collapse() {
assert_eq!(
parse_border_collapse("separate").unwrap(),
StyleBorderCollapse::Separate
);
assert_eq!(
parse_border_collapse("collapse").unwrap(),
StyleBorderCollapse::Collapse
);
assert!(parse_border_collapse("invalid").is_err());
}
#[test]
fn test_parse_border_spacing() {
let spacing1 = parse_border_spacing("5px").unwrap();
assert_eq!(spacing1.horizontal, PixelValue::const_px(5));
assert_eq!(spacing1.vertical, PixelValue::const_px(5));
let spacing2 = parse_border_spacing("5px 10px").unwrap();
assert_eq!(spacing2.horizontal, PixelValue::const_px(5));
assert_eq!(spacing2.vertical, PixelValue::const_px(10));
}
#[test]
fn test_parse_caption_side() {
assert_eq!(parse_caption_side("top").unwrap(), StyleCaptionSide::Top);
assert_eq!(
parse_caption_side("bottom").unwrap(),
StyleCaptionSide::Bottom
);
assert!(parse_caption_side("invalid").is_err());
}
#[test]
fn test_parse_empty_cells() {
assert_eq!(parse_empty_cells("show").unwrap(), StyleEmptyCells::Show);
assert_eq!(parse_empty_cells("hide").unwrap(), StyleEmptyCells::Hide);
assert!(parse_empty_cells("invalid").is_err());
}
}