#[derive(Facet)]structTestStruct{number:i32,text:String,}#[test]fnpeek_struct(){// Create test struct instancelettest_struct=TestStruct{number:42,text:"hello".to_string(),};letpeek_value=Peek::new(&test_struct);// Convert to struct and check we can convert to PeekStructletpeek_struct=peek_value.into_struct().expect("Should be convertible to struct");// Test field access by nameletnumber_field=peek_struct.field_by_name("number").expect("Should have a number field");lettext_field=peek_struct.field_by_name("text").expect("Should have a text field");// Test field valuesletnumber_value=number_field.get::<i32>().unwrap();assert_eq!(*number_value,42);lettext_value=text_field.get::<String>().unwrap();assert_eq!(text_value,"hello");}
pubunsafetraitFacet<'facet>:'facet{/// The shape of this type////// Shape embeds all other constants of this trait.constSHAPE:&'staticShape;/// Function pointers to perform various operations: print the full type/// name (with generic type parameters), use the Display implementation,/// the Debug implementation, build a default value, clone, etc.////// If [`Self::SHAPE`] has `ShapeLayout::Unsized`, then the parent pointer needs to be passed.////// There are more specific vtables in variants of [`Def`]constVTABLE:&'staticValueVTable;}
#[cfg(feature = "alloc")]unsafeimplFacet<'_>foralloc::string::String{constVTABLE:&'staticValueVTable=&const{letmutvtable=value_vtable!(alloc::string::String,|f,_opts|write!(f,"{}",Self::SHAPE.type_identifier));letvtable_sized=vtable.sized_mut().unwrap();// 如何解析String类型vtable_sized.parse=||{Some(|s,target|{// For String, parsing from a string is just copying the stringOk(unsafe{target.put(s.to_string())})})};vtable};constSHAPE:&'staticShape=&const{Shape::builder_for_sized::<Self>().def(Def::Scalar).type_identifier("String").ty(Type::User(UserType::Opaque)).build()};}
//////////////////////////////////////////////////////////////////////////////////////// Default (in place, because we can't have sized) 🏠🔄///////////////////////////////////////////////////////////////////////////////////////// Specialization proxy for [`core::default::Default`]pubtraitSpezDefaultInPlaceYes{/// Creates a default value for the inner type in place.////// This method is called when the wrapped type implements `Default`./// It writes the default value into the provided uninitialized memory.////// # Safety////// This function operates on uninitialized memory and requires that `target`/// has sufficient space allocated for type `T`.unsafefnspez_default_in_place<'mem>(&self,target:PtrUninit<'mem>)->PtrMut<'mem>;}impl<T:Default>SpezDefaultInPlaceYesfor&SpezEmpty<T>{unsafefnspez_default_in_place<'mem>(&self,target:PtrUninit<'mem>)->PtrMut<'mem>{unsafe{target.put(<TasDefault>::default())}}}/// Specialization proxy for [`core::default::Default`]pubtraitSpezDefaultInPlaceNo{/// Fallback implementation when the type doesn't implement `Default`.////// This method is used as a fallback and is designed to be unreachable in practice./// It's only selected when the wrapped type doesn't implement `Default`.////// # Safety////// This function is marked unsafe as it deals with uninitialized memory,/// but it should never be reachable in practice.unsafefnspez_default_in_place<'mem>(&self,_target:PtrUninit<'mem>)->PtrMut<'mem>;}impl<T>SpezDefaultInPlaceNoforSpezEmpty<T>{unsafefnspez_default_in_place<'mem>(&self,_target:PtrUninit<'mem>)->PtrMut<'mem>{unreachable!()}}
/// Function to format a value for display////// If both [`DisplayFn`] and [`ParseFn`] are set, we should be able to round-trip the value.////// # Safety////// The `value` parameter must point to aligned, initialized memory of the correct type.pubtypeDisplayFn=for<'mem>unsafefn(value:PtrConst<'mem>,f:&mutcore::fmt::Formatter)->core::fmt::Result;/// Function to format a value for display////// If both [`DisplayFn`] and [`ParseFn`] are set, we should be able to round-trip the value.pubtypeDisplayFnTyped<T>=fn(value:&T,f:&mutcore::fmt::Formatter)->core::fmt::Result;****
implShape{/// Returns a builder for a shape for some type `T`.pubconstfnbuilder_for_sized<'a,T:Facet<'a>>()->ShapeBuilder{ShapeBuilder::new(T::VTABLE).layout(Layout::new::<T>()).id(ConstTypeId::of::<T>())}// ....}
usecore::alloc::Layout;/// Schema for reflection of a type#[derive(Clone, Copy)]#[repr(C)]pubstructShape{/// Unique type identifier, provided by the compiler.pubid:ConstTypeId,/// Size, alignment — enough to allocate a value of this type/// (but not initialize it.)publayout:ShapeLayout,/// Function pointers to perform various operations: print the full type/// name (with generic type parameters), use the Display implementation,/// the Debug implementation, build a default value, clone, etc.////// If the shape has `ShapeLayout::Unsized`, then the parent pointer needs to be passed.////// There are more specific vtables in variants of [`Def`]pubvtable:&'staticValueVTable,// ...}/// Layout of the shape#[derive(Clone, Copy, Debug, Hash)]pubenumShapeLayout{/// `Sized` typeSized(Layout),/// `!Sized` typeUnsized,}
// facet/facet-core/src/types/mod.rsimplShape{/// Heap-allocate a value of this shape#[cfg(feature = "alloc")]#[inline]pubfnallocate(&self)->Result<crate::ptr::PtrUninit<'static>,UnsizedError>{letlayout=self.layout.sized_layout()?;Ok(crate::ptr::PtrUninit::new(iflayout.size()==0{core::ptr::without_provenance_mut(layout.align())}else{// SAFETY: We have checked that layout's size is non-zerounsafe{alloc::alloc::alloc(layout)}}))}/// Deallocate a heap-allocated value of this shape#[cfg(feature = "alloc")]#[inline]pubunsafefndeallocate_mut(&self,ptr:PtrMut)->Result<(),UnsizedError>{usealloc::alloc::dealloc;letlayout=self.layout.sized_layout()?;iflayout.size()==0{// Nothing to deallocatereturnOk(());}// SAFETY: The user guarantees ptr is valid and from allocate, we checked size isn't 0unsafe{dealloc(ptr.as_mut_byte_ptr(),layout)}Ok(())}// ...}
impl<'facet>Partial<'facet>{/// Allocates a new Partial instance with the given shapepubfnalloc_shape(shape:&'staticShape)->Result<Self,ReflectError>{crate::trace!("alloc_shape({:?}), with layout {:?}",shape,shape.layout.sized_layout());letdata=shape.allocate().map_err(|_|ReflectError::Unsized{shape,operation:"alloc_shape",})?;// ....}/// Allocates a new TypedPartial instance with the given shape and typepubfnalloc<T>()->Result<TypedPartial<'facet,T>,ReflectError>whereT:Facet<'facet>,{Ok(TypedPartial{inner:Self::alloc_shape(T::SHAPE)?,phantom:PhantomData,})}}
pubstructPartial<'facet>{/// stack of frames to keep track of deeply nested initializationframes:Vec<Frame>,// ...}structFrame{/// Address of the value being initializeddata:PtrUninit<'static>,/// Shape of the value being initializedshape:&'staticShape,/// Tracks initialized fieldstracker:Tracker,/// Whether this frame owns the allocation or is just a field pointerownership:FrameOwnership,}
// /home/ken/tmp/facet/facet-reflect/src/partial/mod.rs/// Selects a field of a struct with a given namepubfnbegin_field(&mutself,field_name:&str)->Result<&mutSelf,ReflectError>{letframe=self.frames.last_mut().unwrap();matchframe.shape.ty{Type::User(user_type)=>matchuser_type{UserType::Struct(struct_type)=>{letidx=struct_type.fields.iter().position(|f|f.name==field_name);letidx=matchidx{Some(idx)=>idx,None=>{returnErr(ReflectError::OperationFailed{shape:frame.shape,operation:"field not found",});}};self.begin_nth_field(idx)}},}}
/// Selects the nth field of a struct by indexpubfnbegin_nth_field(&mutself,idx:usize)->Result<&mutSelf,ReflectError>{letframe=self.frames.last_mut().unwrap();matchframe.shape.ty{Type::User(user_type)=>matchuser_type{UserType::Struct(struct_type)=>{ifidx>=struct_type.fields.len(){returnErr(ReflectError::OperationFailed{shape:frame.shape,operation:"field index out of bounds",});}letfield=&struct_type.fields[idx];match&mutframe.tracker{Tracker::Uninit=>{frame.tracker=Tracker::Struct{iset:ISet::new(struct_type.fields.len()),current_child:Some(idx),}},Tracker::Struct{iset,current_child,}=>{// Check if this field was already initializedifiset.get(idx){// Drop the existing value before re-initializing// 获取name字段的指针,drop已经初始化的数据,进行重新初始化letfield_ptr=unsafe{frame.data.field_init_at(field.offset)};ifletSome(drop_fn)=field.shape.vtable.sized().and_then(|v|(v.drop_in_place)()){unsafe{drop_fn(field_ptr)};}// Unset the bit so we can re-initializeiset.unset(idx);}*current_child=Some(idx);}_=>unreachable!(),}// Push a new frame for this field onto the frames stack.letfield_ptr=unsafe{frame.data.field_uninit_at(field.offset)};letfield_shape=field.shape;// 修改最后一帧,也就是last_frame为当前操作的Struct的name fieldself.frames.push(Frame::new(field_ptr,field_shape,FrameOwnership::Field));Ok(self)}},}}
/// Sets a value wholesale into the current framepubfnset<U>(&mutself,value:U)->Result<&mutSelf,ReflectError>whereU:Facet<'facet>,{self.require_active()?;// For conversion frames, store the value in the conversion frame itself// The conversion will happen during end()letptr_const=PtrConst::new(&rawconstvalue);unsafe{// Safety: We are calling set_shape with a valid shape and a valid pointerself.set_shape(ptr_const,U::SHAPE)?};// Prevent the value from being dropped since we've copied itcore::mem::forget(value);Ok(self)}
/// Sets a value into the current frame by shape, for shape-based operations#[inline]pubunsafefnset_shape(&mutself,src_value:PtrConst<'_>,src_shape:&'staticShape,)->Result<&mutSelf,ReflectError>{letfr=self.frames.last_mut().unwrap();unsafe{fr.data.copy_from(src_value,fr.shape).unwrap();}fr.tracker=Tracker::Init;Ok(self)}