lewp_css/domain/expressions/
var_expression.rs1use {
5 super::Expression,
6 crate::{
7 domain::units::{conversions::*, Unit},
8 parsers::ParserContext,
9 CustomParseError,
10 },
11 cssparser::{serialize_identifier, ParseError, Parser, ToCss},
12 std::fmt,
13};
14
15#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
16pub struct VarExpression {
17 pub custom_property_lower_case_name_without_double_dash: String,
18
19 pub default_value_css: Option<String>,
20
21 pub is_not_in_page_rule: bool,
22}
23
24impl ToCss for VarExpression {
25 fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
26 dest.write_str("--")?;
27 serialize_identifier(
28 &self.custom_property_lower_case_name_without_double_dash,
29 dest,
30 )?;
31
32 if let Some(ref default_value) = self.default_value_css {
33 dest.write_char(',')?;
34 dest.write_str(default_value)?;
35 }
36
37 Ok(())
38 }
39}
40
41impl<U: Unit> Expression<U> for VarExpression {
42 #[inline(always)]
45 fn evaluate<
46 Conversion: FontRelativeLengthConversion<U::Number>
47 + ViewportPercentageLengthConversion<U::Number>
48 + PercentageConversion<U::Number>
49 + AttributeConversion<U>
50 + CssVariableConversion,
51 >(
52 &self,
53 conversion: &Conversion,
54 ) -> Option<U::Number> {
55 match conversion.cssVariableValue(
56 &self.custom_property_lower_case_name_without_double_dash,
57 ) {
58 Some(value_css) => U::from_raw_css_for_var_expression_evaluation(
59 value_css,
60 self.is_not_in_page_rule,
61 )
62 .map(|unit| unit.to_CssNumber()),
63 None => {
64 if let Some(ref value_css) = self.default_value_css {
65 U::from_raw_css_for_var_expression_evaluation(
66 value_css,
67 self.is_not_in_page_rule,
68 )
69 .map(|unit| unit.to_CssNumber())
70 } else {
71 None
72 }
73 }
74 }
75 }
76}
77
78impl VarExpression {
79 #[inline(always)]
80 pub(crate) fn parse<'i, 't>(
81 context: &ParserContext,
82 input: &mut Parser<'i, 't>,
83 ) -> Result<Self, ParseError<'i, CustomParseError<'i>>> {
84 input.parse_nested_block(|input| {
85 let custom_property_lower_case_name_without_double_dash = {
86 let identifier = input.expect_ident()?;
87 if !identifier.starts_with("--") {
88 return Err(ParseError::from(
89 CustomParseError::CssVariablesInVarExpressionsMustStartWithTwoDashes(
90 identifier.clone(),
91 ),
92 ));
93 }
94 let mut custom_property_lower_case_name_without_double_dash =
95 (&identifier[2..]).to_owned();
96 custom_property_lower_case_name_without_double_dash.make_ascii_lowercase();
97 custom_property_lower_case_name_without_double_dash
98 };
99
100 let startPosition = input.position();
101
102 let result = input.r#try(|input| {
103 input.expect_comma()?;
104 input.skip_whitespace();
105
106 if input.is_exhausted() {
107 Ok(None)
108 } else {
109 let result: Result<_, ParseError<CustomParseError>> =
110 input.parse_entirely(|input| {
111 Ok(Some(input.slice_from(startPosition).to_owned()))
112 });
113 result
114 }
115 });
116
117 let default_value_css = if let Ok(Some(default_value_css)) = result {
118 if default_value_css.is_empty() {
119 None
120 } else {
121 Some(default_value_css)
122 }
123 } else {
124 None
125 };
126
127 Ok(Self {
128 custom_property_lower_case_name_without_double_dash,
129 default_value_css,
130 is_not_in_page_rule: context.isNotInPageRule(),
131 })
132 })
133 }
134}