Skip to main content

afia_component/
node_property.rs

1//! Types related to getting and setting a property on a DOM node.
2
3use crate::dom::element::DomElement;
4
5/// An error when attempting to retrieve a property from a DOM node.
6#[derive(Debug)]
7pub enum DomNodeGetPropertyStringError {
8    /// The key was too long.
9    KeyTooLong,
10    /// The key's bytes were not valid UTF-8.
11    KeyNotUtf8,
12    /// The property exists, but the value is not a string.
13    ValueNotString,
14    /// The out buffer was smaller than the length of the input element's value.
15    OutBufferBelowMinimumSize,
16    /// The out buffer was smaller than the length of the local storage item's value.
17    #[allow(missing_docs)]
18    OutBufferSmallerThanValue { value_len: usize },
19    #[allow(missing_docs)]
20    Other { error_code: i32 },
21}
22
23/// An error when attempting to retrieve a boolean property from a DOM node.
24#[derive(Debug)]
25pub enum DomNodeGetPropertyBoolError {
26    /// The key was too long.
27    KeyTooLong,
28    /// The key's bytes were not valid UTF-8.
29    KeyNotUtf8,
30    /// The property exists, but the value is not a boolean.
31    ValueNotBool,
32    #[allow(missing_docs)]
33    Other { error_code: i32 },
34}
35
36impl DomElement {
37    /// Get DOM node's property.
38    /// The property is expected to have a string value, otherwise an error is returned.
39    pub fn get_property_string<'out>(
40        &self,
41        key: &str,
42        out_buffer: &'out mut [u8],
43    ) -> Result<&'out str, DomNodeGetPropertyStringError> {
44        let returned = unsafe {
45            afia_component_sys::dom_node_get_property_string(
46                self.component_imports_ptr(),
47                self.to_i64(),
48                key.as_ptr(),
49                key.len(),
50                out_buffer.as_mut_ptr(),
51                out_buffer.len(),
52            )
53        };
54
55        match returned {
56            length if length >= 0 => {
57                let length = length as usize;
58
59                // SAFETY: here we are trusting that the Afia host worked as expected and wrote a
60                // utf8 string to the buffer.
61                let string = unsafe { std::str::from_utf8_unchecked(&out_buffer[0..length]) };
62
63                Ok(string)
64            }
65            -1 => Err(DomNodeGetPropertyStringError::KeyTooLong),
66            -2 => Err(DomNodeGetPropertyStringError::KeyNotUtf8),
67            -3 => Err(DomNodeGetPropertyStringError::ValueNotString),
68            -4 => Err(DomNodeGetPropertyStringError::OutBufferBelowMinimumSize),
69            -5 => {
70                let mut val_len = [0; 4];
71                val_len.copy_from_slice(&out_buffer[0..4]);
72                let val = i32::from_le_bytes(val_len);
73                Err(DomNodeGetPropertyStringError::OutBufferSmallerThanValue {
74                    value_len: val as usize,
75                })
76            }
77            unknown_error_code => Err(DomNodeGetPropertyStringError::Other {
78                error_code: unknown_error_code,
79            }),
80        }
81    }
82
83    /// Get DOM node's property.
84    /// The property is expected to have a bool value, otherwise an error is returned.
85    pub fn get_property_bool<'out>(&self, key: &str) -> Result<bool, DomNodeGetPropertyBoolError> {
86        let returned = unsafe {
87            afia_component_sys::dom_node_get_property_bool(
88                self.component_imports_ptr(),
89                self.to_i64(),
90                key.as_ptr(),
91                key.len(),
92            )
93        };
94
95        match returned {
96            0 => Ok(false),
97            1 => Ok(true),
98            -1 => Err(DomNodeGetPropertyBoolError::KeyTooLong),
99            -2 => Err(DomNodeGetPropertyBoolError::KeyNotUtf8),
100            -3 => Err(DomNodeGetPropertyBoolError::ValueNotBool),
101            unknown_error_code => Err(DomNodeGetPropertyBoolError::Other {
102                error_code: unknown_error_code,
103            }),
104        }
105    }
106
107    /// Set DOM node's property to a string value.
108    pub fn set_property_string(&self, key: &str, value: &str) {
109        unsafe {
110            afia_component_sys::dom_node_set_property_string(
111                self.component_imports_ptr(),
112                self.to_i64(),
113                key.as_ptr(),
114                key.len(),
115                value.as_ptr(),
116                value.len(),
117            )
118        }
119    }
120
121    /// Set DOM node's property to a boolean value.
122    pub fn set_property_bool(&self, key: &str, value: bool) {
123        let value: i32 = if value { 1 } else { 0 };
124        unsafe {
125            afia_component_sys::dom_node_set_property_bool(
126                self.component_imports_ptr(),
127                self.to_i64(),
128                key.as_ptr(),
129                key.len(),
130                value,
131            );
132        }
133    }
134}