#buffer #memory #casting #bytes

pkbuffer

Buffer objects made for arbitrary casting and addressing!

6 releases (3 breaking)

0.4.2 Jan 6, 2023
0.4.1 Apr 23, 2022
0.4.0 Mar 29, 2022
0.3.0 Mar 26, 2022
0.1.0 Feb 18, 2022

#5 in #casting

Download history 11/week @ 2022-10-07 9/week @ 2022-10-14 12/week @ 2022-10-21 9/week @ 2022-10-28 17/week @ 2022-11-04 6/week @ 2022-11-11 15/week @ 2022-11-18 10/week @ 2022-11-25 6/week @ 2022-12-02 10/week @ 2022-12-09 5/week @ 2022-12-16 13/week @ 2022-12-23 6/week @ 2022-12-30 138/week @ 2023-01-06 142/week @ 2023-01-13 25/week @ 2023-01-20

313 downloads per month
Used in exe

GPL-3.0 license

77KB
1K SLoC

PKBuffer

PKBuffer is a simple but flexible buffer library that allows you to cast Rust objects onto a byte buffer. It was born of multiple memory parsing scenarios such as executable header parsing and game ROM memory mapping. Its name comes from the magic that is casting arbitrary structure definitions at byte buffers and the fact that I was reverse engineering the game EarthBound at the time.

You can read the documentation here, and see various use examples in the test file. The changelog can be found here.


lib.rs:

PKBuffer is a library built for arbitrary casting of data structures onto segments of memory! This includes sections of unowned memory, such as examining the headers of a currently running executable. It creates an interface for reading and writing data structures to an arbitrary buffer of bytes.

For example:

use pkbuffer::{Buffer, VecBuffer, Castable};

#[repr(packed)]
#[derive(Copy, Clone, Castable)]
struct Object {
   byte: u8,
   word: u16,
   dword: u32,
}

let mut buffer = VecBuffer::with_initial_size(std::mem::size_of::<Object>());
let object = buffer.get_mut_ref::<Object>(0).unwrap();
object.byte = 0x01;
object.word = 0x0302;
object.dword = 0x07060504;

assert_eq!(buffer, [1,2,3,4,5,6,7]);

Objects retrieved from Buffer objects must implement the Castable trait. This trait ensures that a series of attributes are applied to the object. For convenience, a derive macro is provided.

Buffer objects are derived from the Buffer trait. This trait implements much functionality of slice objects as well as data casting abilities of the derived Buffer objects.

Buffer objects comes in two forms: pointer form (PtrBuffer) and allocated form (VecBuffer). Each of these structures come in handy for different reasons. PtrBuffer is useful on unowned data such as arbitrary locations in memory, whereas VecBuffer's utility comes from being able to manipulate the underlying owned data.

VecBuffers are handy for creating a brand-new buffer of objects.

use pkbuffer::{Buffer, VecBuffer};

let mut buffer = VecBuffer::new();
buffer.append_ref::<u8>(&0x1);
buffer.append_ref::<u16>(&0x0302);
buffer.append_ref::<u32>(&0x07060504);
assert_eq!(buffer, [1,2,3,4,5,6,7]);

Dependencies

~315–780KB
~18K SLoC