fyrox_core/visitor/
pod.rs1use crate::visitor::{
24 error::VisitError,
25 field::{Field, FieldKind},
26 Visit, VisitResult, Visitor,
27};
28
29const POD_TYPES: &[&str] = &[
30 "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64",
31];
32
33fn type_id_to_str(type_id: u8) -> &'static str {
34 POD_TYPES
35 .get(type_id as usize)
36 .copied()
37 .unwrap_or("Invalid Type")
38}
39
40pub trait Pod: Copy {
43 fn type_id() -> u8;
48}
49
50impl Pod for u8 {
51 fn type_id() -> u8 {
52 0
53 }
54}
55
56impl Pod for i8 {
57 fn type_id() -> u8 {
58 1
59 }
60}
61
62impl Pod for u16 {
63 fn type_id() -> u8 {
64 2
65 }
66}
67
68impl Pod for i16 {
69 fn type_id() -> u8 {
70 3
71 }
72}
73
74impl Pod for u32 {
75 fn type_id() -> u8 {
76 4
77 }
78}
79
80impl Pod for i32 {
81 fn type_id() -> u8 {
82 5
83 }
84}
85
86impl Pod for u64 {
87 fn type_id() -> u8 {
88 6
89 }
90}
91
92impl Pod for i64 {
93 fn type_id() -> u8 {
94 7
95 }
96}
97
98impl Pod for f32 {
99 fn type_id() -> u8 {
100 8
101 }
102}
103
104impl Pod for f64 {
105 fn type_id() -> u8 {
106 9
107 }
108}
109
110pub struct PodVecView<'a, T: Pod> {
114 type_id: u8,
115 vec: &'a mut Vec<T>,
116}
117
118impl<'a, T: Pod> PodVecView<'a, T> {
119 pub fn from_pod_vec(vec: &'a mut Vec<T>) -> Self {
121 Self {
122 type_id: T::type_id(),
123 vec,
124 }
125 }
126}
127
128impl<T: Pod> Visit for PodVecView<'_, T> {
129 #[allow(clippy::uninit_vec)]
130 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
131 if visitor.reading {
132 if let Some(field) = visitor.find_field(name) {
133 match &field.kind {
134 FieldKind::PodArray {
135 type_id,
136 element_size,
137 bytes,
138 } => {
139 if *type_id == self.type_id {
140 let len = bytes.len() / *element_size as usize;
141 let mut data = Vec::<T>::with_capacity(len);
142 unsafe {
143 data.set_len(len);
144 std::ptr::copy_nonoverlapping(
145 bytes.as_ptr(),
146 data.as_mut_ptr() as *mut u8,
147 bytes.len(),
148 );
149 }
150 *self.vec = data;
151 Ok(())
152 } else {
153 Err(VisitError::TypeMismatch {
154 expected: type_id_to_str(self.type_id),
155 actual: type_id_to_str(*type_id),
156 })
157 }
158 }
159 _ => Err(VisitError::FieldTypeDoesNotMatch {
160 expected: stringify!(FieldKind::PodArray),
161 actual: format!("{:?}", field.kind),
162 }),
163 }
164 } else {
165 Err(VisitError::field_does_not_exist(name, visitor))
166 }
167 } else if visitor.find_field(name).is_some() {
168 Err(VisitError::FieldAlreadyExists(name.to_owned()))
169 } else {
170 let node = visitor.current_node();
171 node.fields.push(Field::new(
172 name,
173 FieldKind::PodArray {
174 type_id: T::type_id(),
175 element_size: std::mem::size_of::<T>() as u32,
176 bytes: unsafe {
177 let mut data = self.vec.clone();
178 let bytes = Vec::from_raw_parts(
179 data.as_mut_ptr() as *mut u8,
180 data.len() * std::mem::size_of::<T>(),
181 data.capacity() * std::mem::size_of::<T>(),
182 );
183 std::mem::forget(data);
184 bytes
185 },
186 },
187 ));
188 Ok(())
189 }
190 }
191}
192
193#[cfg(test)]
194mod test {
195 use crate::visitor::pod::PodVecView;
196
197 #[test]
198 fn pod_vec_view_from_pod_vec() {
199 let mut v = Vec::<u8>::new();
201 let mut v2 = v.clone();
202 let p = PodVecView::from_pod_vec(&mut v);
203 assert_eq!(p.type_id, 0_u8);
204 assert_eq!(p.vec, &mut v2);
205
206 let mut v = Vec::<i8>::new();
208 let p = PodVecView::from_pod_vec(&mut v);
209 assert_eq!(p.type_id, 1_u8);
210
211 let mut v = Vec::<u16>::new();
213 let p = PodVecView::from_pod_vec(&mut v);
214 assert_eq!(p.type_id, 2_u8);
215
216 let mut v = Vec::<i16>::new();
218 let p = PodVecView::from_pod_vec(&mut v);
219 assert_eq!(p.type_id, 3_u8);
220
221 let mut v = Vec::<u32>::new();
223 let p = PodVecView::from_pod_vec(&mut v);
224 assert_eq!(p.type_id, 4_u8);
225
226 let mut v = Vec::<i32>::new();
228 let p = PodVecView::from_pod_vec(&mut v);
229 assert_eq!(p.type_id, 5_u8);
230
231 let mut v = Vec::<u64>::new();
233 let p = PodVecView::from_pod_vec(&mut v);
234 assert_eq!(p.type_id, 6_u8);
235
236 let mut v = Vec::<i64>::new();
238 let p = PodVecView::from_pod_vec(&mut v);
239 assert_eq!(p.type_id, 7_u8);
240
241 let mut v = Vec::<f32>::new();
243 let p = PodVecView::from_pod_vec(&mut v);
244 assert_eq!(p.type_id, 8_u8);
245
246 let mut v = Vec::<f64>::new();
248 let p = PodVecView::from_pod_vec(&mut v);
249 assert_eq!(p.type_id, 9_u8);
250 }
251}