[−][src]Trait structural::field::IntoVariantField
Provides shared and by-value access to an enum variant field.
The V
and F
type parameters are expected to be TStr.
Every instance of "the F
field"/"the V
variant" in the docs mean
"in the field/variant named by the F
/V
type parameter"
Safety
IsVariant<V>
and IntoVariantField<V, F>
must agree on what variant
the enum currently is.
If IsVariant
returns true for a particular V
variant,
then into_vfield_
,and move_out_vfield_
must return Some(_)
.
If overriden, the *_unchecked
methods must diverge
(abort, panic, or call the equivalent of std::hint::unreachable_unchecked
)
if the enum is not currently the V
variant,
and return the same field as the checked equivalents if the enum
is currently the V
variant.
Implementing move_out_vfield_
The way this method is expected to be implemented like this:
-
Match on the enum,if it's the expected variant continue the steps, otherwise return
None
. -
Move out the field using
std::ptr::read
or equivalent. -
Mark the field in the
moved_fields
parameter as being moved out using theset_moved_out
method, with aFieldBit
argument unique to this field in the variant (fields from different variants can use the sameFieldBit
as fields in other variants).
Every implementation of IntoVariantField::move_out_vfield_
must return field(s) that no other implementation of
IntoVariantField
or IntoField
for this type return.
The DropFields::drop_fields
implementation for this type must then
call is_moved_out
on its MovedOutFields
parameter
to decide whether to drop the field,
passing the same FieldBit
argument as in the move_out_vfield_
implementation.
If is_moved_out
returns false, then the field must be dropped.
Example
use structural::field::IntoVariantField; use structural::for_examples::{Bomb,WithBoom}; use structural::{StructuralExt,TS,fp}; fn example<T>(mut this: T) where T: IntoVariantField<TS!(Boom),TS!(a),Ty= &'static str>+ IntoVariantField<TS!(Boom),TS!(b),Ty= &'static [u16]>, { assert_eq!( this.is_variant(fp!(Boom)), true ); assert_eq!( this.field_(fp!(::Boom.a)), Some(&"Because.") ); assert_eq!( this.cloned_fields(fp!(::Boom=>a,b)), Some(( "Because.", &[13,21][..] )) ); assert_eq!( this.fields(fp!(::Boom=>a,b)), Some(( &"Because.", &&[13,21][..] )) ); assert_eq!( this.into_field(fp!(::Boom.a)), Some("Because.") ); } example(WithBoom::Boom{ a:"Because.", b:&[13,21] }); example(Bomb::Boom{ a:"Because.", b:&[13,21] });
Example: Manual implementation
While this trait is better derived, it can be implemented manually.
Note that the derive macro also declares trait aliases for the traits implemented here.
use structural::{ field::ownership::{FieldBit, DropFields, MovedOutFields, RunDrop}, FieldType, GetVariantField, IntoVariantField, FP, TS, StructuralExt,fp,structural_alias, }; use structural::enums::{IsVariant, VariantCount}; // The `FooBounds` trait is defined below. fn using_enum(bar: impl FooBounds, baz: impl FooBounds){ assert_eq!( bar.fields(fp!(::Bar=>0,1)), Some((&34, &51)) ); assert_eq!( bar.into_fields(fp!(::Bar=>0,1)), Some((34, 51)) ); assert_eq!( bar.is_variant(fp!(Bar)), true ); assert_eq!( bar.is_variant(fp!(Baz)), false ); assert_eq!( baz.fields(fp!(::Bar=>0,1)), None ); assert_eq!( baz.into_fields(fp!(::Bar=>0,1)), None ); assert_eq!( baz.is_variant(fp!(Bar)), false ); assert_eq!( baz.is_variant(fp!(Baz)), true ); } using_enum(Foo::Bar(34,51), Foo::Baz); #[derive(Copy,Clone)] enum Foo{ Bar(u32,u64), Baz, } const BAR_0_INDEX: FieldBit = FieldBit::new(0); const BAR_1_INDEX: FieldBit = FieldBit::new(1); unsafe impl VariantCount for Foo{ type Count=TS!(2); } unsafe impl IsVariant<TS!(Bar)> for Foo { fn is_variant_(&self,_:TS!(Bar))->bool{ match self { Foo::Bar{..}=>true, _=>false, } } } impl FieldType<FP!(::Bar.0)> for Foo{ type Ty=u32; } unsafe impl GetVariantField<TS!(Bar),TS!(0)> for Foo{ fn get_vfield_(&self, _:TS!(Bar), _:TS!(0)) -> Option<&u32>{ match self { Foo::Bar(ret,_)=>Some(ret), _=>None, } } } unsafe impl IntoVariantField<TS!(Bar),TS!(0)> for Foo{ fn into_vfield_(self, _:TS!(Bar), _:TS!(0)) -> Option<u32>{ match self { Foo::Bar(ret,_)=>Some(ret), _=>None, } } unsafe fn move_out_vfield_( &mut self, _: TS!(Bar), _: TS!(0), moved_fields: &mut MovedOutFields, ) -> Option<u32> { match self { Foo::Bar(ret,_)=>{ moved_fields.set_moved_out(BAR_0_INDEX); Some(std::ptr::read(ret)) }, _=>None, } } } impl FieldType<FP!(::Bar.1)> for Foo{ type Ty=u64; } unsafe impl GetVariantField<TS!(Bar),TS!(1)> for Foo{ fn get_vfield_(&self, _:TS!(Bar), _:TS!(1)) -> Option<&u64>{ match self { Foo::Bar(_,ret)=>Some(ret), _=>None, } } } unsafe impl IntoVariantField<TS!(Bar),TS!(1)> for Foo{ fn into_vfield_(self, _:TS!(Bar), _:TS!(1)) -> Option<u64>{ match self { Foo::Bar(_,ret)=>Some(ret), _=>None, } } unsafe fn move_out_vfield_( &mut self, _: TS!(Bar), _: TS!(1), moved_fields: &mut MovedOutFields, ) -> Option<u64> { match self { Foo::Bar(_,ret)=>{ moved_fields.set_moved_out(BAR_1_INDEX); Some(std::ptr::read(ret)) }, _=>None, } } } unsafe impl DropFields for Foo{ // This type does nothing before fields are moved. fn pre_move(&mut self){} unsafe fn drop_fields(&mut self, moved_fields: MovedOutFields){ match self { Foo::Bar(field0, field1)=>{ // RunDrop here ensures that the destructors for all fields are ran // even if any of them panics. let _a; if moved_fields.is_moved_out(BAR_0_INDEX){ _a = RunDrop::new(field0); } let _a; if moved_fields.is_moved_out(BAR_1_INDEX){ _a = RunDrop::new(field1); } } Foo::Baz=>{} } } } unsafe impl IsVariant<TS!(Baz)> for Foo { fn is_variant_(&self,_:TS!(Baz))->bool{ match self { Foo::Baz{..}=>true, _=>false, } } } structural_alias!{ trait FooBounds: Copy{ move Bar(u32,u64), move Baz, } }
Required methods
fn into_vfield_(self, variant_name: V, field_name: F) -> Option<Self::Ty>
Converts this into the F
field in the V
variant by value.
unsafe fn move_out_vfield_(
&mut self,
variant_name: V,
field_name: F,
moved_fields: &mut MovedOutFields
) -> Option<Self::Ty>
&mut self,
variant_name: V,
field_name: F,
moved_fields: &mut MovedOutFields
) -> Option<Self::Ty>
Moves out the F
field from the V
variant.
Safety
The same instance of MovedOutFields
must be passed to every call to
move_out_vfield_
on the same instance of this type,
as well as not mutating that MovedOutFields
instance outside of
methods of this trait for this type.
Each field must be moved with any method at most once on the same instance of this type.
Provided methods
unsafe fn into_vfield_unchecked_(
self,
variant_name: V,
field_name: F
) -> Self::Ty where
Self: Sized,
self,
variant_name: V,
field_name: F
) -> Self::Ty where
Self: Sized,
unsafe fn move_out_vfield_unchecked_(
&mut self,
variant_name: V,
field_name: F,
moved_fields: &mut MovedOutFields
) -> Self::Ty
&mut self,
variant_name: V,
field_name: F,
moved_fields: &mut MovedOutFields
) -> Self::Ty
Converts this into the F
field in the V
variant by value,
without checking that the enum is currently the V
variant.
This method exists so that Box<dyn Trait>
can be converted into a field by value.
Safety
The enum must be the V
variant.
The same instance of MovedOutFields
must be passed to every call to
move_out_vfield_unchecked_
on the same instance of this type,
as well as not mutating that MovedOutFields
instance outside of
methods of this trait for this type.
Each field must be moved with any method at most once on the same instance of this type.
Implementations on Foreign Types
impl<T> IntoVariantField<TStr<__TS<(__S, __o, __m, __e)>>, TStr<__TS<(__0,)>>> for Option<T> where
Self: DropFields,
[src]
Self: DropFields,
fn into_vfield_(
self,
_: TStr<__TS<(__S, __o, __m, __e)>>,
_: TStr<__TS<(__0,)>>
) -> Option<T>
[src]
self,
_: TStr<__TS<(__S, __o, __m, __e)>>,
_: TStr<__TS<(__0,)>>
) -> Option<T>
unsafe fn move_out_vfield_(
&mut self,
_: TStr<__TS<(__S, __o, __m, __e)>>,
_: TStr<__TS<(__0,)>>,
moved_fields: &mut MovedOutFields
) -> Option<T>
[src]
&mut self,
_: TStr<__TS<(__S, __o, __m, __e)>>,
_: TStr<__TS<(__0,)>>,
moved_fields: &mut MovedOutFields
) -> Option<T>
impl<T, E> IntoVariantField<TStr<__TS<(__O, __k)>>, TStr<__TS<(__0,)>>> for Result<T, E> where
Self: DropFields,
[src]
Self: DropFields,
fn into_vfield_(
self,
_: TStr<__TS<(__O, __k)>>,
_: TStr<__TS<(__0,)>>
) -> Option<T>
[src]
self,
_: TStr<__TS<(__O, __k)>>,
_: TStr<__TS<(__0,)>>
) -> Option<T>
unsafe fn move_out_vfield_(
&mut self,
_: TStr<__TS<(__O, __k)>>,
_: TStr<__TS<(__0,)>>,
moved_fields: &mut MovedOutFields
) -> Option<T>
[src]
&mut self,
_: TStr<__TS<(__O, __k)>>,
_: TStr<__TS<(__0,)>>,
moved_fields: &mut MovedOutFields
) -> Option<T>
impl<T, E> IntoVariantField<TStr<__TS<(__E, __r, __r)>>, TStr<__TS<(__0,)>>> for Result<T, E> where
Self: DropFields,
[src]
Self: DropFields,
fn into_vfield_(
self,
_: TStr<__TS<(__E, __r, __r)>>,
_: TStr<__TS<(__0,)>>
) -> Option<E>
[src]
self,
_: TStr<__TS<(__E, __r, __r)>>,
_: TStr<__TS<(__0,)>>
) -> Option<E>
unsafe fn move_out_vfield_(
&mut self,
_: TStr<__TS<(__E, __r, __r)>>,
_: TStr<__TS<(__0,)>>,
moved_fields: &mut MovedOutFields
) -> Option<E>
[src]
&mut self,
_: TStr<__TS<(__E, __r, __r)>>,
_: TStr<__TS<(__0,)>>,
moved_fields: &mut MovedOutFields
) -> Option<E>
impl<T: ?Sized, V, F, Ty> IntoVariantField<TStr<V>, F> for Box<T> where
T: IntoVariantField<TStr<V>, F, Ty = Ty>,
[src]
T: IntoVariantField<TStr<V>, F, Ty = Ty>,
fn into_vfield_(self, vname: TStr<V>, fname: F) -> Option<Ty>
[src]
unsafe fn move_out_vfield_(
&mut self,
vname: TStr<V>,
fname: F,
moved: &mut MovedOutFields
) -> Option<Ty>
[src]
&mut self,
vname: TStr<V>,
fname: F,
moved: &mut MovedOutFields
) -> Option<Ty>
Implementors
impl<T, V, F> IntoVariantField<TStr<V>, F> for FieldCloner<T> where
T: GetVariantField<TStr<V>, F>,
T::Ty: Clone,
[src]
T: GetVariantField<TStr<V>, F>,
T::Ty: Clone,
fn into_vfield_(self, variant_name: TStr<V>, field_name: F) -> Option<Self::Ty>
[src]
unsafe fn move_out_vfield_(
&mut self,
variant_name: TStr<V>,
field_name: F,
_: &mut MovedOutFields
) -> Option<Self::Ty>
[src]
&mut self,
variant_name: TStr<V>,
field_name: F,
_: &mut MovedOutFields
) -> Option<Self::Ty>
impl<T, __V, __F, __Ty> IntoVariantField<TStr<__V>, __F> for StrucWrapper<T> where
T: IntoVariantField<TStr<__V>, __F, Ty = __Ty>,
[src]
T: IntoVariantField<TStr<__V>, __F, Ty = __Ty>,
fn into_vfield_(self, vname: TStr<__V>, fname: __F) -> Option<__Ty>
[src]
unsafe fn move_out_vfield_(
&mut self,
vname: TStr<__V>,
fname: __F,
moved: &mut MovedOutFields
) -> Option<__Ty>
[src]
&mut self,
vname: TStr<__V>,
fname: __F,
moved: &mut MovedOutFields
) -> Option<__Ty>