pub unsafe trait GetVariantFieldMut<V, F>: GetVariantField<V, F> {
// Required methods
fn get_vfield_mut_(&mut self, variant: V, field: F) -> Option<&mut Self::Ty>;
unsafe fn get_vfield_raw_mut_(
ptr: *mut (),
variant: V,
field: F,
) -> Option<NonNull<Self::Ty>>
where Self: Sized;
fn get_vfield_raw_mut_fn(&self) -> GetVFieldRawMutFn<V, F, Self::Ty>;
fn get_vfield_raw_mut_unchecked_fn(&self) -> GetFieldRawMutFn<F, Self::Ty>;
// Provided methods
unsafe fn get_vfield_mut_unchecked(
&mut self,
variant: V,
field: F,
) -> &mut Self::Ty { ... }
unsafe fn get_vfield_raw_mut_unchecked(
ptr: *mut (),
field: F,
) -> *mut Self::Ty
where Self: Sized,
V: ConstDefault { ... }
}
Expand description
Provides shared and mutable 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
Implementors ought not mutate fields inside their accessor trait impls, or the accessor trait impls of other fields.
The safety requirements for
GetFielfMut::get_field_raw_mut
also apply to
GetVariantFieldMut::get_vfield_raw_mut_
.
IsVariant<V>
and GetVariantFieldMut<V, F>
must agree on what variant the enum currently is.
If IsVariant
returns true for a particular V
variant,
then get_vfield_mut_
and get_vfield_raw_mut_
must return Some(_)
for the same variant.
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.
§Example: Use as bound.
use structural::field::GetVariantFieldMut;
use structural::for_examples::{Bomb,WithBoom};
use structural::{StructuralExt,TS,fp};
fn example<T>(this: &mut T)
where
T: GetVariantFieldMut<TS!(Boom),TS!(a),Ty= &'static str>+
GetVariantFieldMut<TS!(Boom),TS!(b),Ty= &'static [u16]>,
{
assert_eq!( this.field_(fp!(::Boom.a)), Some(&"why?") );
assert_eq!( this.field_mut(fp!(::Boom.a)), Some(&mut "why?") );
// You can use `fp!(::Foo=>bar,baz)` to access multiple fields inside
// an enum variant.
assert_eq!( this.fields(fp!(::Boom=>a,b)), Some(( &"why?", &&[0,1,2][..] )) );
assert_eq!( this.cloned_fields(fp!(::Boom=>a,b)), Some(( "why?", &[0,1,2][..] )) );
assert_eq!(
this.fields_mut(fp!(::Boom=>a,b)),
Some(( &mut "why?", &mut &[0,1,2][..] )),
);
assert_eq!( this.is_variant(fp!(Boom)), true );
}
example(&mut WithBoom::Boom{ a:"why?", b:&[0,1,2] });
example(&mut Bomb::Boom{ a:"why?", b:&[0,1,2] });
§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::{
FieldType, GetVariantField, GetVariantFieldMut, FP, TS,
StructuralExt,fp,structural_alias,
};
use structural::enums::{IsVariant, VariantCount};
// The `FooBounds` trait is defined below.
fn using_enum(bar: &mut dyn FooBounds, baz: &mut dyn FooBounds){
assert_eq!( bar.fields(fp!(::Bar=>0,1)), Some((&34, &51)) );
assert_eq!( bar.fields_mut(fp!(::Bar=>0,1)), Some((&mut 34, &mut 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.fields_mut(fp!(::Bar=>0,1)), None );
assert_eq!( baz.is_variant(fp!(Bar)), false );
assert_eq!( baz.is_variant(fp!(Baz)), true );
}
using_enum(&mut Foo::Bar(34,51), &mut Foo::Baz);
enum Foo{
Bar(u32,u64),
Baz,
}
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 GetVariantFieldMut<TS!(Bar),TS!(0)> for Foo {
fn get_vfield_mut_(&mut self, _:TS!(Bar), _:TS!(0))->Option<&mut u32>{
match self {
Foo::Bar(ret,_)=>Some(ret),
_=>None
}
}
unsafe fn get_vfield_raw_mut_(
this:*mut (),
_:TS!(Bar),
_:TS!(0),
)->Option<std::ptr::NonNull<u32>> {
structural::z_raw_borrow_enum_field!(this as *mut Self, Foo::Bar.0 : u32)
}
structural::z_unsafe_impl_get_vfield_raw_mut_fn!{
Self= Self,
variant_tstr= TS!(Bar),
field_tstr= TS!(0),
field_type= u32,
}
}
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 GetVariantFieldMut<TS!(Bar),TS!(1)> for Foo {
fn get_vfield_mut_(&mut self, _:TS!(Bar), _:TS!(1))->Option<&mut u64>{
match self {
Foo::Bar(_,ret)=>Some(ret),
_=>None
}
}
unsafe fn get_vfield_raw_mut_(
this:*mut (),
_:TS!(Bar),
_:TS!(1),
)->Option<std::ptr::NonNull<u64>> {
structural::z_raw_borrow_enum_field!(this as *mut Self, Foo::Bar.1 : u64)
}
structural::z_unsafe_impl_get_vfield_raw_mut_fn!{
Self= Self,
variant_tstr= TS!(Bar),
field_tstr= TS!(1),
field_type= u64,
}
}
unsafe impl IsVariant<TS!(Baz)> for Foo {
fn is_variant_(&self,_:TS!(Baz))->bool{
match self {
Foo::Baz{..}=>true,
_=>false,
}
}
}
structural_alias!{
trait FooBounds{
mut Bar(u32,u64),
mut Baz,
}
}
Required Methods§
Sourcefn get_vfield_mut_(&mut self, variant: V, field: F) -> Option<&mut Self::Ty>
fn get_vfield_mut_(&mut self, variant: V, field: F) -> Option<&mut Self::Ty>
Accesses the F
field in the V
variant by mutable reference.
Sourceunsafe fn get_vfield_raw_mut_(
ptr: *mut (),
variant: V,
field: F,
) -> Option<NonNull<Self::Ty>>where
Self: Sized,
unsafe fn get_vfield_raw_mut_(
ptr: *mut (),
variant: V,
field: F,
) -> Option<NonNull<Self::Ty>>where
Self: Sized,
Accesses the F
field in the V
variant by raw pointer.
§Safety
You must pass a pointer casted from *mut Self
to *mut ()
,
pointing to a fully initialized instance of the type.
This function returns a NonNull
purely as an optimization detail,
functions that return raw pointers (*mut _
) are also
expected to return pointers to valid fields.
Sourcefn get_vfield_raw_mut_fn(&self) -> GetVFieldRawMutFn<V, F, Self::Ty>
fn get_vfield_raw_mut_fn(&self) -> GetVFieldRawMutFn<V, F, Self::Ty>
Gets a function pointer to the get_vfield_raw_mut_
method.
This exists so that the method can be called in dyn Trait
s
Sourcefn get_vfield_raw_mut_unchecked_fn(&self) -> GetFieldRawMutFn<F, Self::Ty>
fn get_vfield_raw_mut_unchecked_fn(&self) -> GetFieldRawMutFn<F, Self::Ty>
Gets a function pointer to the get_vfield_raw_mut_unchecked
method.
This exists so that the method can be called in dyn Trait
s
Provided Methods§
Sourceunsafe fn get_vfield_mut_unchecked(
&mut self,
variant: V,
field: F,
) -> &mut Self::Ty
unsafe fn get_vfield_mut_unchecked( &mut self, variant: V, field: F, ) -> &mut Self::Ty
Accesses the F
field in the V
variant by mutable reference,
without checking that the enum is currently the V
variant.
§Safety
The enum must be the V
variant.
Sourceunsafe fn get_vfield_raw_mut_unchecked(ptr: *mut (), field: F) -> *mut Self::Tywhere
Self: Sized,
V: ConstDefault,
unsafe fn get_vfield_raw_mut_unchecked(ptr: *mut (), field: F) -> *mut Self::Tywhere
Self: Sized,
V: ConstDefault,
Accesses the F
field in the V
variant by raw pointer,
without checking that the enum is currently the V
variant.
§Safety
You must pass a pointer casted from *mut Self
to *mut ()
,
pointing to a fully initialized instance of the type.
The enum must also be the V
variant (type parameter of this trait).