facet_reflect/poke/
value.rs1use core::marker::PhantomData;
2
3use facet_core::{Def, Facet, PtrConst, PtrMut, Shape, Type, UserType};
4
5use crate::ReflectError;
6
7use super::{PokeList, PokeStruct};
8
9pub struct Poke<'mem, 'facet> {
47 pub(crate) data: PtrMut,
49
50 pub(crate) shape: &'static Shape,
52
53 #[allow(clippy::type_complexity)]
56 _marker: PhantomData<(&'mem mut (), fn(&'facet ()) -> &'facet ())>,
57}
58
59impl<'mem, 'facet> Poke<'mem, 'facet> {
60 pub fn new<T: Facet<'facet>>(t: &'mem mut T) -> Self {
65 Self {
66 data: PtrMut::new(t as *mut T as *mut u8),
67 shape: T::SHAPE,
68 _marker: PhantomData,
69 }
70 }
71
72 pub unsafe fn from_raw_parts(data: PtrMut, shape: &'static Shape) -> Self {
79 Self {
80 data,
81 shape,
82 _marker: PhantomData,
83 }
84 }
85
86 #[inline(always)]
88 pub const fn shape(&self) -> &'static Shape {
89 self.shape
90 }
91
92 #[inline(always)]
94 pub const fn data(&self) -> PtrConst {
95 self.data.as_const()
96 }
97
98 #[inline(always)]
100 pub const fn data_mut(&mut self) -> PtrMut {
101 self.data
102 }
103
104 #[inline]
106 pub const fn is_struct(&self) -> bool {
107 matches!(self.shape.ty, Type::User(UserType::Struct(_)))
108 }
109
110 #[inline]
112 pub const fn is_enum(&self) -> bool {
113 matches!(self.shape.ty, Type::User(UserType::Enum(_)))
114 }
115
116 #[inline]
118 pub const fn is_scalar(&self) -> bool {
119 matches!(self.shape.def, Def::Scalar)
120 }
121
122 pub const fn into_struct(self) -> Result<PokeStruct<'mem, 'facet>, ReflectError> {
124 match self.shape.ty {
125 Type::User(UserType::Struct(struct_type)) => Ok(PokeStruct {
126 value: self,
127 ty: struct_type,
128 }),
129 _ => Err(ReflectError::WasNotA {
130 expected: "struct",
131 actual: self.shape,
132 }),
133 }
134 }
135
136 pub const fn into_enum(self) -> Result<super::PokeEnum<'mem, 'facet>, ReflectError> {
138 match self.shape.ty {
139 Type::User(UserType::Enum(enum_type)) => Ok(super::PokeEnum {
140 value: self,
141 ty: enum_type,
142 }),
143 _ => Err(ReflectError::WasNotA {
144 expected: "enum",
145 actual: self.shape,
146 }),
147 }
148 }
149
150 #[inline]
152 pub const fn into_list(self) -> Result<PokeList<'mem, 'facet>, ReflectError> {
153 if let Def::List(def) = self.shape.def {
154 return Ok(unsafe { PokeList::new(self, def) });
158 }
159
160 Err(ReflectError::WasNotA {
161 expected: "list",
162 actual: self.shape,
163 })
164 }
165
166 pub fn get<T: Facet<'facet>>(&self) -> Result<&T, ReflectError> {
170 if self.shape != T::SHAPE {
171 return Err(ReflectError::WrongShape {
172 expected: self.shape,
173 actual: T::SHAPE,
174 });
175 }
176 Ok(unsafe { self.data.as_const().get::<T>() })
177 }
178
179 pub fn get_mut<T: Facet<'facet>>(&mut self) -> Result<&mut T, ReflectError> {
183 if self.shape != T::SHAPE {
184 return Err(ReflectError::WrongShape {
185 expected: self.shape,
186 actual: T::SHAPE,
187 });
188 }
189 Ok(unsafe { self.data.as_mut::<T>() })
190 }
191
192 pub fn set<T: Facet<'facet>>(&mut self, value: T) -> Result<(), ReflectError> {
196 if self.shape != T::SHAPE {
197 return Err(ReflectError::WrongShape {
198 expected: self.shape,
199 actual: T::SHAPE,
200 });
201 }
202 unsafe {
203 self.shape.call_drop_in_place(self.data);
205 core::ptr::write(self.data.as_mut_byte_ptr() as *mut T, value);
206 }
207 Ok(())
208 }
209
210 #[inline]
212 pub fn as_peek(&self) -> crate::Peek<'_, 'facet> {
213 unsafe { crate::Peek::unchecked_new(self.data.as_const(), self.shape) }
214 }
215}
216
217impl core::fmt::Debug for Poke<'_, '_> {
218 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
219 write!(f, "Poke<{}>", self.shape)
220 }
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226
227 #[test]
228 fn poke_primitive_get_set() {
229 let mut x: i32 = 42;
230 let mut poke = Poke::new(&mut x);
231
232 assert_eq!(*poke.get::<i32>().unwrap(), 42);
233
234 poke.set(100i32).unwrap();
235 assert_eq!(x, 100);
236 }
237
238 #[test]
239 fn poke_primitive_get_mut() {
240 let mut x: i32 = 42;
241 let mut poke = Poke::new(&mut x);
242
243 *poke.get_mut::<i32>().unwrap() = 99;
244 assert_eq!(x, 99);
245 }
246
247 #[test]
248 fn poke_wrong_type_fails() {
249 let mut x: i32 = 42;
250 let poke = Poke::new(&mut x);
251
252 let result = poke.get::<u32>();
253 assert!(matches!(result, Err(ReflectError::WrongShape { .. })));
254 }
255
256 #[test]
257 fn poke_set_wrong_type_fails() {
258 let mut x: i32 = 42;
259 let mut poke = Poke::new(&mut x);
260
261 let result = poke.set(42u32);
262 assert!(matches!(result, Err(ReflectError::WrongShape { .. })));
263 }
264
265 #[test]
266 fn poke_string_drop_and_replace() {
267 let mut s = String::from("hello");
269 let mut poke = Poke::new(&mut s);
270
271 poke.set(String::from("world")).unwrap();
272 assert_eq!(s, "world");
273 }
274}