afia_component/dom/
element.rs1use std::slice;
4use std::sync::Arc;
5
6use crate::dom::node::AsDomNode;
7use crate::dom::node_list::NodeList;
8use crate::ComponentImports;
9
10mod child;
11
12#[derive(Clone)]
14pub struct DomElement {
15 inner: Arc<DomElementInner>,
16}
17struct DomElementInner {
18 element: i64,
19 component_imports: ComponentImports,
20}
21impl DomElement {
22 pub fn maybe_new(handle: i64, component_imports: ComponentImports) -> Option<Self> {
25 if handle == 0 {
26 return None;
27 }
28
29 Some(Self {
30 inner: Arc::new(DomElementInner {
31 element: handle,
32 component_imports,
33 }),
34 })
35 }
36
37 pub fn temporary_way_to_get_i64(&self) -> i64 {
39 self.to_i64()
40 }
41
42 pub(crate) fn component_imports(&self) -> &ComponentImports {
43 &self.inner.component_imports
44 }
45
46 pub(crate) fn component_imports_ptr(&self) -> *const std::ffi::c_void {
47 self.inner.component_imports.component_imports_ptr
48 }
49
50 pub(crate) fn to_i64(&self) -> i64 {
51 self.inner.element
52 }
53
54 pub fn do_not_use_this_for_new_stuff_temporary_public_way_to_create_using_existing_i64_handle(
59 &self,
60 element_handle: i64,
61 ) -> Option<Self> {
62 Self::maybe_new(element_handle, self.inner.component_imports.clone())
63 }
64
65 pub fn set_text_content(&self, text: &str) {
67 unsafe {
68 afia_component_sys::dom_element_set_text_content(
69 self.inner.component_imports.pointer(),
70 self.inner.element,
71 text.as_ptr(),
72 text.len(),
73 )
74 }
75 }
76
77 pub fn previous_element_sibling(&self) -> Option<DomElement> {
82 let sibling = unsafe {
83 afia_component_sys::dom_element_previous_element_sibling(
84 self.imports_ptr(),
85 self.handle(),
86 )
87 };
88
89 DomElement::maybe_new(sibling, self.inner.component_imports.clone())
90 }
91
92 pub fn next_element_sibling(&self) -> Option<DomElement> {
97 let sibling = unsafe {
98 afia_component_sys::dom_element_next_element_sibling(self.imports_ptr(), self.handle())
99 };
100
101 DomElement::maybe_new(sibling, self.inner.component_imports.clone())
102 }
103
104 pub fn tag_name(&self) -> String {
109 let mut buf = [0; 20];
111
112 let tag_len = unsafe {
113 afia_component_sys::element_tag_name(
114 self.imports_ptr(),
115 self.handle(),
116 buf.as_mut_ptr(),
117 buf.len(),
118 )
119 };
120 assert!(buf.len() as i32 >= tag_len);
122
123 let tag_slice = unsafe { slice::from_raw_parts(buf.as_ptr(), tag_len as usize) };
124 let tag = str::from_utf8(tag_slice).unwrap();
125 tag.to_string()
126 }
127
128 pub fn click(&self) {
133 unsafe { afia_component_sys::element_click(self.imports_ptr(), self.handle()) }
134 }
135
136 pub fn child_nodes(&self) -> NodeList {
141 let child_nodes =
142 unsafe { afia_component_sys::element_child_nodes(self.imports_ptr(), self.handle()) };
143 NodeList::new(child_nodes, self.component_imports().clone())
144 }
145
146 pub fn get_attribute(&self, key: &str) -> Option<String> {
151 let mut out = [0; 255];
152 let result = unsafe {
153 afia_component_sys::element_get_attribute(
154 self.imports_ptr(),
155 self.handle(),
156 key.as_ptr(),
157 key.len(),
158 out.as_mut_ptr(),
159 out.len(),
160 )
161 };
162 match result {
163 ..-1 => {
164 todo!("error handling")
165 }
166 -1 => None,
167 0 => None,
168 1.. => {
169 let result = result as usize;
170 if out.len() < result {
171 todo!("handle scenario where buffer was smaller than the value")
172 };
173 let value = str::from_utf8(&out[0..result]).unwrap();
174 Some(value.to_string())
175 }
176 }
177 }
178
179 pub fn inner_text(&self) -> String {
184 let mut out = [0u8; 1000];
185 let result = unsafe {
186 afia_component_sys::element_inner_text(
187 self.imports_ptr(),
188 self.handle(),
189 out.as_mut_ptr(),
190 out.len(),
191 )
192 };
193 match result {
194 ..=-1 => {
195 todo!("error handling")
196 }
197 0.. => {
198 let result = result as usize;
199 if out.len() < result {
200 todo!("handle scenario where buffer was smaller than the value")
201 };
202 let value = str::from_utf8(&out[0..result]).unwrap();
203 value.to_string()
204 }
205 }
206 }
207}
208impl Drop for DomElementInner {
209 fn drop(&mut self) {
210 }
212}
213
214impl ComponentImports {
215 pub fn create_element(&self, tag: &str) -> Option<DomElement> {
217 let element = unsafe {
218 afia_component_sys::create_element(self.component_imports_ptr, tag.as_ptr(), tag.len())
219 };
220
221 DomElement::maybe_new(element, self.clone())
222 }
223}