Skip to main content

azul_css/props/layout/
text.rs

1//! CSS `text-justify` property.
2//!
3//! Defines [`LayoutTextJustify`] and its parser [`parse_layout_text_justify`],
4//! used by the CSS property parsing pipeline.
5
6use alloc::string::{String, ToString};
7use core::fmt;
8use crate::corety::AzString;
9
10use crate::{format_rust_code::FormatAsRustCode, props::formatter::PrintAsCssValue};
11
12/// CSS `text-justify` property value.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14#[repr(C)]
15#[derive(Default)]
16pub enum LayoutTextJustify {
17    #[default]
18    Auto,
19    None,
20    InterWord,
21    InterCharacter,
22    /// Legacy value; the parser maps `"distribute"` to `InterCharacter` per spec.
23    /// Retained for `#[repr(C)]` FFI backward compatibility.
24    Distribute,
25}
26
27
28impl PrintAsCssValue for LayoutTextJustify {
29    fn print_as_css_value(&self) -> String {
30        match self {
31            LayoutTextJustify::Auto => "auto",
32            LayoutTextJustify::None => "none",
33            LayoutTextJustify::InterWord => "inter-word",
34            LayoutTextJustify::InterCharacter => "inter-character",
35            LayoutTextJustify::Distribute => "distribute",
36        }
37        .to_string()
38    }
39}
40
41impl FormatAsRustCode for LayoutTextJustify {
42    fn format_as_rust_code(&self, _tabs: usize) -> String {
43        format!("LayoutTextJustify::{self:?}")
44    }
45}
46
47#[derive(Debug, Clone, PartialEq)]
48pub enum TextJustifyParseError<'a> {
49    InvalidValue(&'a str),
50}
51
52impl<'a> fmt::Display for TextJustifyParseError<'a> {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        match self {
55            TextJustifyParseError::InvalidValue(s) => {
56                write!(f, "Invalid text-justify value: '{}'.", s)
57            }
58        }
59    }
60}
61
62#[derive(Debug, Clone, PartialEq)]
63#[repr(C, u8)]
64pub enum TextJustifyParseErrorOwned {
65    InvalidValue(AzString),
66}
67
68impl<'a> TextJustifyParseError<'a> {
69    pub fn to_owned(&self) -> TextJustifyParseErrorOwned {
70        match self {
71            TextJustifyParseError::InvalidValue(s) => {
72                TextJustifyParseErrorOwned::InvalidValue((*s).to_string().into())
73            }
74        }
75    }
76}
77
78impl TextJustifyParseErrorOwned {
79    pub fn to_borrowed(&self) -> TextJustifyParseError<'_> {
80        match self {
81            TextJustifyParseErrorOwned::InvalidValue(s) => {
82                TextJustifyParseError::InvalidValue(s.as_str())
83            }
84        }
85    }
86}
87
88/// Parses a `text-justify` CSS value string into a [`LayoutTextJustify`].
89pub fn parse_layout_text_justify<'a>(
90    input: &'a str,
91) -> Result<LayoutTextJustify, TextJustifyParseError<'a>> {
92    match input.trim() {
93        "auto" => Ok(LayoutTextJustify::Auto),
94        "none" => Ok(LayoutTextJustify::None),
95        "inter-word" => Ok(LayoutTextJustify::InterWord),
96        "inter-character" => Ok(LayoutTextJustify::InterCharacter),
97        // +spec:text-alignment-spacing:4a88c2 - distribute computes to inter-character (legacy value alias)
98        // +spec:text-alignment-spacing:58c33f - distribute computes to inter-character per spec clarification
99        "distribute" => Ok(LayoutTextJustify::InterCharacter),
100        other => Err(TextJustifyParseError::InvalidValue(other)),
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107    #[test]
108    fn test_parse_layout_text_justify() {
109        assert_eq!(
110            parse_layout_text_justify("auto"),
111            Ok(LayoutTextJustify::Auto)
112        );
113        assert_eq!(
114            parse_layout_text_justify("none"),
115            Ok(LayoutTextJustify::None)
116        );
117        assert_eq!(
118            parse_layout_text_justify("inter-word"),
119            Ok(LayoutTextJustify::InterWord)
120        );
121        assert_eq!(
122            parse_layout_text_justify("inter-character"),
123            Ok(LayoutTextJustify::InterCharacter)
124        );
125        assert_eq!(
126            parse_layout_text_justify("distribute"),
127            Ok(LayoutTextJustify::InterCharacter)
128        );
129        assert!(parse_layout_text_justify("invalid").is_err());
130    }
131}