1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! Property setters without runtime type-checking
//! *Warning*: Be careful when using: functions allow you to change properties
//! without checking - which can lead to untracked errors during execution.
use yoga::FlexStyle;

use types::{
    get_reflect_property_type,
    pair_to_flex,
    PropertyError,
    SharedUnit,
    Appearance,
    Properties,
};

macro_rules! default_setter {
    ($properties:ident, $field:ident, $key:ident, $value:ident) => {
        if $properties.$field.0.contains_key(&$key) {
            let item = $properties.$field.0.get_mut(&$key).unwrap();
            *item = $value;
        } else {
            $properties.$field.0.insert($key, $value);
        }
    };
}

/// Set basic appearance property without check
pub fn set_appearance_without_check(properties: &mut Properties, key: String, value: Appearance) {
    default_setter!(properties, appearance, key, value);
}

/// Set basic layout property without check
pub fn set_layout_without_check(properties: &mut Properties, key: String, value: FlexStyle) {
    default_setter!(properties, layout, key, value);
}

/// Set shared layout property without check (expression or exact unit)
pub fn set_layout_unit_without_check(
    properties: &mut Properties,
    key: String,
    value: SharedUnit,
) -> Result<(), PropertyError> {
    match value {
        SharedUnit::StyleUnit(unit) => {
            properties.expressions.0.remove(&key).is_some();

            pair_to_flex(key.clone(), unit).and_then(|unit| {
                if let Some(item) = properties.layout.0.get_mut(&key) {
                    *item = unit;
                    return Ok(());
                }

                properties.layout.0.insert(key, unit).is_some();
                Ok(())
            })
        }

        SharedUnit::CalcExpr(expression) => {
            properties.layout.0.remove(&key).is_some();

            let expression = if !expression.get_compiled().is_some() {
                expression.compile().map_err(|error| PropertyError::InvalidExpression {
                    key: key.clone(),
                    error,
                })?
            } else {
                expression
            };

            properties.expressions.0.insert(key, expression).is_some();
            Ok(())
        }
    }
}

/// Create expected type error by property key
pub fn expected_type_error(property: String) -> PropertyError {
    PropertyError::InvalidType {
        expected: get_reflect_property_type(property.as_str()).to_string(),
        property: property,
    }
}