I have a Vec<u8>
named vec
and a variable named x
of type &dyn Trait
. I want the data pointer of x
to point to a position in vec
.
#[derive(Debug)]
struct Point {
x: u8,
y: u8,
}
fn main() {
let vec: Vec<u8> = vec![35, 1, 51, 10];
let x: &dyn Debug;
// create a &dyn Debug with its data pointer
// pointing to vec[2] while the vtable points
// to Point's implementation of Debug
println!("{:?}", x); // expected output: "Point { x: 51, y: 10 }"
}
I'm trying to develop a virtual machine like the JVM. Every struct (Point
, Line
) that implements the desired trait (Display
or Debug
) will actually be an instruction (Add
, Mov
, ...) which will implement the trait Instruction
, this trait contains the code of the instruction itself.
Here's another example that is closer to what I want to do:
use std::fmt::{self, Display};
struct Point {
pub x: u8,
pub y: u8,
}
impl Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
struct Line {
pub start: Point,
pub end: Point,
}
impl Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.start, self.end)
}
}
struct Data {
vec: Vec<u8>,
index: usize,
}
impl Data {
fn new(vec: Vec<u8>) -> Self {
Self { vec, index: 0 }
}
fn next(&mut self) -> Option<&dyn Display> {
let obj;
self.index += 1;
match self.vec[self.index] {
0 => {
obj = Some(/* &Point { ... } with address equal to &(self.vec[self.index])*/);
self.index += std::mem::size_of::<Point>();
}
1 => {
obj = Some(/* &Line { ... } with address equal to &(self.vec[self.index])*/);
self.index += std::mem::size_of::<Line>();
}
_ => {
obj = None;
}
}
obj
}
}
fn main() {
let raw_vec: Vec<u8> = vec![0, 24, 53, 1, 65, 103, 68, 10, 2];
let data = Data::new(raw_vec);
assert!(format!("{}", data.next().unwrap()) == "(24, 53)".to_string());
assert!(format!("{}", data.next().unwrap()) == "((65, 103), (68, 10))".to_string());
}
Multiple struct
s of different length will share their data with the Vec<u8>
. In this example, the memory layout of my struct
s may not match what I suppose they are, but this does not matter because their layout does not need to be known at compile time, but only at runtime. think of the Vec<u8>
as the bytes read from a file by the program while the file itself was created by this same program.
How would I do that, even if it's unsafe or undefined behavior and without using smart pointers/heap allocation?