facet_reflect/partial/partial_api/
set.rs1use super::*;
2use facet_core::{Def, DynDateTimeKind, NumericType, PrimitiveType, Type};
3
4impl<'facet, const BORROW: bool> Partial<'facet, BORROW> {
8 pub fn set<U>(mut self, value: U) -> Result<Self, ReflectError>
14 where
15 U: Facet<'facet>,
16 {
17 struct DropVal<U> {
18 ptr: *mut U,
19 }
20 impl<U> Drop for DropVal<U> {
21 #[inline]
22 fn drop(&mut self) {
23 unsafe { core::ptr::drop_in_place(self.ptr) };
24 }
25 }
26
27 let mut value = ManuallyDrop::new(value);
28 let drop = DropVal {
29 ptr: (&mut value) as *mut ManuallyDrop<U> as *mut U,
30 };
31
32 let ptr_const = PtrConst::new(drop.ptr);
33 self = unsafe { self.set_shape(ptr_const, U::SHAPE)? };
35 core::mem::forget(drop);
36
37 Ok(self)
38 }
39
40 #[inline]
54 pub unsafe fn set_shape(
55 mut self,
56 src_value: PtrConst,
57 src_shape: &'static Shape,
58 ) -> Result<Self, ReflectError> {
59 let fr = self.frames_mut().last_mut().unwrap();
60 crate::trace!("set_shape({src_shape:?})");
61
62 if let Def::DynamicValue(dyn_def) = &fr.shape.def {
64 return unsafe { self.set_into_dynamic_value(src_value, src_shape, dyn_def) };
65 }
66
67 if !fr.shape.is_shape(src_shape) {
68 return Err(ReflectError::WrongShape {
69 expected: fr.shape,
70 actual: src_shape,
71 });
72 }
73
74 fr.deinit();
75
76 unsafe {
79 fr.data.copy_from(src_value, fr.shape).unwrap();
82 }
83
84 unsafe {
86 fr.mark_as_init();
87 }
88
89 Ok(self)
90 }
91
92 unsafe fn set_into_dynamic_value(
98 mut self,
99 src_value: PtrConst,
100 src_shape: &'static Shape,
101 dyn_def: &facet_core::DynamicValueDef,
102 ) -> Result<Self, ReflectError> {
103 let fr = self.frames_mut().last_mut().unwrap();
104 let vtable = dyn_def.vtable;
105
106 fr.deinit();
107
108 if fr.shape.is_shape(src_shape) {
110 unsafe {
111 fr.data.copy_from(src_value, fr.shape).unwrap();
112 fr.mark_as_init();
113 }
114 return Ok(self);
115 }
116
117 let size_bits = src_shape
119 .layout
120 .sized_layout()
121 .map(|l| l.size() * 8)
122 .unwrap_or(0);
123
124 match &src_shape.ty {
126 Type::Primitive(PrimitiveType::Boolean) => {
127 let val = unsafe { *(src_value.as_byte_ptr() as *const bool) };
128 unsafe { (vtable.set_bool)(fr.data, val) };
129 }
130 Type::Primitive(PrimitiveType::Numeric(NumericType::Float)) => {
131 if size_bits == 64 {
132 let val = unsafe { *(src_value.as_byte_ptr() as *const f64) };
133 let success = unsafe { (vtable.set_f64)(fr.data, val) };
134 if !success {
135 return Err(ReflectError::OperationFailed {
136 shape: src_shape,
137 operation: "f64 value (NaN/Infinity) not representable in dynamic value",
138 });
139 }
140 } else if size_bits == 32 {
141 let val = unsafe { *(src_value.as_byte_ptr() as *const f32) } as f64;
142 let success = unsafe { (vtable.set_f64)(fr.data, val) };
143 if !success {
144 return Err(ReflectError::OperationFailed {
145 shape: src_shape,
146 operation: "f32 value (NaN/Infinity) not representable in dynamic value",
147 });
148 }
149 } else {
150 return Err(ReflectError::OperationFailed {
151 shape: src_shape,
152 operation: "unsupported float size for dynamic value",
153 });
154 }
155 }
156 Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: true })) => {
157 let val: i64 = match size_bits {
158 8 => (unsafe { *(src_value.as_byte_ptr() as *const i8) }) as i64,
159 16 => (unsafe { *(src_value.as_byte_ptr() as *const i16) }) as i64,
160 32 => (unsafe { *(src_value.as_byte_ptr() as *const i32) }) as i64,
161 64 => unsafe { *(src_value.as_byte_ptr() as *const i64) },
162 _ => {
163 return Err(ReflectError::OperationFailed {
164 shape: src_shape,
165 operation: "unsupported signed integer size for dynamic value",
166 });
167 }
168 };
169 unsafe { (vtable.set_i64)(fr.data, val) };
170 }
171 Type::Primitive(PrimitiveType::Numeric(NumericType::Integer { signed: false })) => {
172 let val: u64 = match size_bits {
173 8 => (unsafe { *src_value.as_byte_ptr() }) as u64,
174 16 => (unsafe { *(src_value.as_byte_ptr() as *const u16) }) as u64,
175 32 => (unsafe { *(src_value.as_byte_ptr() as *const u32) }) as u64,
176 64 => unsafe { *(src_value.as_byte_ptr() as *const u64) },
177 _ => {
178 return Err(ReflectError::OperationFailed {
179 shape: src_shape,
180 operation: "unsupported unsigned integer size for dynamic value",
181 });
182 }
183 };
184 unsafe { (vtable.set_u64)(fr.data, val) };
185 }
186 Type::Primitive(PrimitiveType::Textual(_)) => {
187 if src_shape.type_identifier == "char" {
189 let c = unsafe { *(src_value.as_byte_ptr() as *const char) };
190 let mut buf = [0u8; 4];
191 let s = c.encode_utf8(&mut buf);
192 unsafe { (vtable.set_str)(fr.data, s) };
193 } else {
194 let s: &str = unsafe { *(src_value.as_byte_ptr() as *const &str) };
196 unsafe { (vtable.set_str)(fr.data, s) };
197 }
198 }
199 _ => {
200 if src_shape.type_identifier == "String" {
202 let s: &::alloc::string::String =
203 unsafe { &*(src_value.as_byte_ptr() as *const ::alloc::string::String) };
204 unsafe { (vtable.set_str)(fr.data, s.as_str()) };
205 unsafe {
207 src_shape
208 .call_drop_in_place(PtrMut::new(src_value.as_byte_ptr() as *mut u8));
209 }
210 } else {
211 return Err(ReflectError::OperationFailed {
212 shape: src_shape,
213 operation: "cannot convert this type to dynamic value",
214 });
215 }
216 }
217 }
218
219 let fr = self.frames_mut().last_mut().unwrap();
220 fr.tracker = Tracker::DynamicValue {
221 state: DynamicValueState::Scalar,
222 };
223 unsafe { fr.mark_as_init() };
224 Ok(self)
225 }
226
227 #[allow(clippy::too_many_arguments)]
232 pub fn set_datetime(
233 mut self,
234 year: i32,
235 month: u8,
236 day: u8,
237 hour: u8,
238 minute: u8,
239 second: u8,
240 nanos: u32,
241 kind: DynDateTimeKind,
242 ) -> Result<Self, ReflectError> {
243 let fr = self.frames_mut().last_mut().unwrap();
244
245 let dyn_def = match &fr.shape.def {
247 Def::DynamicValue(dv) => dv,
248 _ => {
249 return Err(ReflectError::OperationFailed {
250 shape: fr.shape,
251 operation: "set_datetime requires a DynamicValue target",
252 });
253 }
254 };
255
256 let vtable = dyn_def.vtable;
257
258 let Some(set_datetime_fn) = vtable.set_datetime else {
260 return Err(ReflectError::OperationFailed {
261 shape: fr.shape,
262 operation: "dynamic value type does not support datetime",
263 });
264 };
265
266 fr.deinit();
267
268 unsafe {
270 set_datetime_fn(fr.data, year, month, day, hour, minute, second, nanos, kind);
271 }
272
273 let fr = self.frames_mut().last_mut().unwrap();
274 fr.tracker = Tracker::DynamicValue {
275 state: DynamicValueState::Scalar,
276 };
277 unsafe { fr.mark_as_init() };
278 Ok(self)
279 }
280
281 pub unsafe fn set_from_function<F>(mut self, f: F) -> Result<Self, ReflectError>
291 where
292 F: FnOnce(PtrUninit) -> Result<(), ReflectError>,
293 {
294 let frame = self.frames_mut().last_mut().unwrap();
295
296 frame.deinit();
297 f(frame.data)?;
298
299 unsafe {
301 frame.mark_as_init();
302 }
303
304 Ok(self)
305 }
306
307 #[inline]
316 pub fn set_default(self) -> Result<Self, ReflectError> {
317 let frame = self.frames().last().unwrap();
318 let shape = frame.shape;
319
320 unsafe {
322 self.set_from_function(move |ptr| {
323 shape.call_default_in_place(ptr.assume_init()).ok_or(
324 ReflectError::OperationFailed {
325 shape,
326 operation: "type does not implement Default",
327 },
328 )?;
329 Ok(())
330 })
331 }
332 }
333
334 pub unsafe fn set_from_peek(self, peek: &Peek<'_, '_>) -> Result<Self, ReflectError> {
345 let src_ptr = peek.data();
347 let src_shape = peek.shape();
348
349 unsafe { self.set_shape(src_ptr, src_shape) }
351 }
352
353 pub fn parse_from_str(mut self, s: &str) -> Result<Self, ReflectError> {
357 let frame = self.frames_mut().last_mut().unwrap();
358 let shape = frame.shape;
359
360 frame.deinit();
362
363 let result = unsafe { shape.call_parse(s, frame.data.assume_init()) };
365
366 match result {
367 Some(Ok(())) => {
368 unsafe {
370 frame.mark_as_init();
371 }
372 Ok(self)
373 }
374 Some(Err(_pe)) => {
375 Err(ReflectError::OperationFailed {
377 shape,
378 operation: "Failed to parse string value",
379 })
380 }
381 None => Err(ReflectError::OperationFailed {
382 shape,
383 operation: "Type does not support parsing from string",
384 }),
385 }
386 }
387}