Trait repr_offset::ext::ROExtAcc

source ·
pub unsafe trait ROExtAcc: Sized {
    // Required methods
    fn f_get<F>(&self, offset: FieldOffset<Self, F, Aligned>) -> &F;
    fn f_get_mut<F>(&mut self, offset: FieldOffset<Self, F, Aligned>) -> &mut F;
    fn f_get_ptr<F, A>(&self, offset: FieldOffset<Self, F, A>) -> *const F;
    fn f_get_mut_ptr<F, A>(&mut self, offset: FieldOffset<Self, F, A>) -> *mut F;
}
Expand description

Extension trait for (mutable) references to access fields generically, where the field is determined by a FieldOffset parameter.

Safety

This trait must not to be implemented outside the repr_offset crate.

Examples

Unaligned field pointers

Getting raw pointers to all fields in a packed struct.

use repr_offset::{
    for_examples::ReprPacked,
    ROExtAcc,
    off,
};

type This = ReprPacked<u8, Option<usize>, &'static [u16], &'static str>;

let value: This = ReprPacked {
    a: 3,
    b: Some(5),
    c: &[0, 1, 2],
    d: "hello",
};

unsafe {
    let (a_ptr, b_ptr, c_ptr, d_ptr) = get_field_ptrs(&value);
    assert_eq!(a_ptr.read_unaligned(), 3);
    assert_eq!(b_ptr.read_unaligned(), Some(5));
    assert_eq!(c_ptr.read_unaligned(), &[0, 1, 2]);
    assert_eq!(d_ptr.read_unaligned(), "hello");
}

// Note: the mutable version of this function couldn't use `f_get_mut_ptr`,
//       it must use `ROExtRawMutAcc::f_raw_get_mut`
fn get_field_ptrs(
    this: &This,
) -> (*const u8, *const Option<usize>, *const &'static [u16], *const &'static str) {
    (
        this.f_get_ptr(off!(a)),
        this.f_get_ptr(off!(b)),
        this.f_get_ptr(off!(c)),
        this.f_get_ptr(off!(d)),
    )
}

Required Methods§

source

fn f_get<F>(&self, offset: FieldOffset<Self, F, Aligned>) -> &F

Gets a reference to a field, determined by offset.

Example
use repr_offset::{
    for_examples::ReprC,
    ROExtAcc, off,
};

let value = ReprC {
    a: 3,
    b: "foo",
    c: ReprC {
        a: 5,
        b: "bar",
        c: 8,
        d: 13,
    },
    d: false,
};

assert_eq!(value.f_get(off!(a)), &3);
assert_eq!(value.f_get(off!(c.a)), &5);
assert_eq!(value.f_get(off!(c.b)), &"bar");

source

fn f_get_mut<F>(&mut self, offset: FieldOffset<Self, F, Aligned>) -> &mut F

Gets a muatble reference to a field, determined by offset.

Example
use repr_offset::{
    for_examples::{ReprAlign4, ReprC},
    ROExtAcc, off,
};

use std::cmp::Ordering;

let mut value = ReprC {
    a: 3,
    b: Some(5),
    c: Ordering::Less,
    d: ReprAlign4 {
        a: 8,
        b: "bar",
        c: 13,
        d: 21,
    },
};

let foo = value.f_get_mut(off!(a));
assert_eq!(foo, &mut 3);
*foo += 100;
assert_eq!(value.a, 103);

let bar = value.f_get_mut(off!(d.a));
assert_eq!(bar, &mut 8);

let baz = value.f_get_mut(off!(d.d));
assert_eq!(baz, &mut 21);
*baz += 300;
assert_eq!(value.d.d, 321);
source

fn f_get_ptr<F, A>(&self, offset: FieldOffset<Self, F, A>) -> *const F

Gets a const pointer to a field, the field is determined by offset.

Example
use repr_offset::{
    for_examples::ReprC,
    ROExtAcc, off,
};

let value = ReprC {
    a: 3,
    b: "foo",
    c: ReprC {
        a: 5,
        b: "bar",
        c: 8,
        d: 13,
    },
    d: false,
};

unsafe {
    assert_eq!(value.f_get_ptr(off!(a)).read(), 3);
    assert_eq!(value.f_get_ptr(off!(c.a)).read(), 5);
    assert_eq!(value.f_get_ptr(off!(c.b)).read(), "bar");
}
source

fn f_get_mut_ptr<F, A>(&mut self, offset: FieldOffset<Self, F, A>) -> *mut F

Gets a mutable pointer to a field, determined by offset.

Example
use repr_offset::{
    for_examples::{ReprC, ReprPacked},
    utils::moved,
    ROExtAcc, off,
};

use std::cmp::Ordering;

let mut value = ReprPacked {
    a: 3,
    b: Some(5),
    c: Ordering::Less,
    d: ReprC {
        a: 8,
        b: "bar",
        c: 13,
        d: 21,
    },
};

unsafe {
    let foo = value.f_get_mut_ptr(off!(a));
    let old_a = foo.read_unaligned();
    assert_eq!(old_a, 3);
    foo.write_unaligned(old_a + 100);
    // the `moved` function prevents the creation of a reference to the packed field.
    assert_eq!(moved(value.a), 103);
     
    let baz = value.f_get_mut_ptr(off!(d.d));
    let old_dd = baz.read_unaligned();
    assert_eq!(old_dd, 21);
    baz.write_unaligned(old_dd + 300);
    // the `moved` function prevents the creation of a reference to the packed field.
    assert_eq!(moved(value.d.d), 321);
}

Implementors§

source§

impl<S> ROExtAcc for S