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::{codegen::format::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            Self::Auto => "auto",
32            Self::None => "none",
33            Self::InterWord => "inter-word",
34            Self::InterCharacter => "inter-character",
35            Self::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, Eq)]
48pub enum TextJustifyParseError<'a> {
49    InvalidValue(&'a str),
50}
51
52impl fmt::Display for TextJustifyParseError<'_> {
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, Eq)]
63#[repr(C, u8)]
64pub enum TextJustifyParseErrorOwned {
65    InvalidValue(AzString),
66}
67
68impl TextJustifyParseError<'_> {
69    #[must_use] 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    #[must_use] pub fn to_borrowed(&self) -> TextJustifyParseError<'_> {
80        match self {
81            Self::InvalidValue(s) => {
82                TextJustifyParseError::InvalidValue(s.as_str())
83            }
84        }
85    }
86}
87
88/// Parses a `text-justify` CSS value string into a [`LayoutTextJustify`].
89/// # Errors
90///
91/// Returns an error if `input` is not a valid CSS `text-justify` value.
92pub fn parse_layout_text_justify(
93    input: &str,
94) -> Result<LayoutTextJustify, TextJustifyParseError<'_>> {
95    match input.trim() {
96        "auto" => Ok(LayoutTextJustify::Auto),
97        "none" => Ok(LayoutTextJustify::None),
98        "inter-word" => Ok(LayoutTextJustify::InterWord),
99        // "distribute" is a legacy alias that computes to inter-character:
100        // +spec:text-alignment-spacing:4a88c2  +spec:text-alignment-spacing:58c33f
101        "inter-character" | "distribute" => Ok(LayoutTextJustify::InterCharacter),
102        other => Err(TextJustifyParseError::InvalidValue(other)),
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109    #[test]
110    fn test_parse_layout_text_justify() {
111        assert_eq!(
112            parse_layout_text_justify("auto"),
113            Ok(LayoutTextJustify::Auto)
114        );
115        assert_eq!(
116            parse_layout_text_justify("none"),
117            Ok(LayoutTextJustify::None)
118        );
119        assert_eq!(
120            parse_layout_text_justify("inter-word"),
121            Ok(LayoutTextJustify::InterWord)
122        );
123        assert_eq!(
124            parse_layout_text_justify("inter-character"),
125            Ok(LayoutTextJustify::InterCharacter)
126        );
127        assert_eq!(
128            parse_layout_text_justify("distribute"),
129            Ok(LayoutTextJustify::InterCharacter)
130        );
131        assert!(parse_layout_text_justify("invalid").is_err());
132    }
133}