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 structs of different length will share their data with the Vec<u8>. In this example, the memory layout of my structs 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?