1 unstable release
0.1.0 | Aug 9, 2023 |
---|
#2223 in Rust patterns
55KB
702 lines
gep
gep
, a better pointer arithmetic library.
The name gep
comes from LLVM's getelementptr
instruction, the infamous
pointer arithmetic operation.
This library provides two new pointer types, [Ptr
] and NonNull
, which
have very similar APIs; they correspond to *mut T
and
core::ptr::NonNull
, respectively.
It also provides Rusty versions of memcpy
, memmove
, and memset
.
Offsets
The premiere operation provided by this library is [Ptr::at()
], which is
a generalized pointer arithmetic operation. For example, it will accept
any integer as input, not just isize
(although, like [<*mut T>::offset
],
the offset value must be valid to convert to isize
).
let mut ints = [0i32; 6];
let p = Ptr::from(&mut ints).element();
unsafe {
// Pointer to the 4th element.
let q = p.at(4);
q.write(42);
// Many operations have an `*_at` variant that internally calls .at().
q.write_at(-1, 55);
}
assert_eq!(ints, [0, 0, 0, 55, 42, 0]);
By default, at()
works on multiples of elements. To do a direct byte
offset instead, you can use the offset::ByteOffset
type instead.
use gep::offset::ByteOffset;
let mut ints = [0i32; 6];
let p = Ptr::from(&mut ints).element();
unsafe {
p.write_at(ByteOffset(4), 4242);
}
assert_eq!(ints[1], 4242);
It's also possible to use "field offsets" (via the offset::Field
type)
for accessing the fields of a struct directly, without creating intermediate
references to potentially invalid data.
use gep::offset::Field;
struct Foo {
a: i32,
b: [i32; 3],
}
let foo = Foo { a: 0, b: [1, 2, 3] };
let p = Ptr::from(&foo);
let value = unsafe {
p.read_at(gep::field!(Foo.b[1]))
};
assert_eq!(value, 2);
License: Apache-2.0