I have some structs with static methods e.g. execute
and translate
. In one part of my code I need to map a code to one of these structs and call execute
and in another I need to map the same type of code to the translate
method of a struct. I thought that a good solution could be a trait and some form of compile time reflection with macros but this appears to not be possible. Another approach I've considered is some sort of Box<dyn trait>
approach with the trait requiring a get_code
method, maintaining one list or some sort of dictionary however this seems like it might incur some performance penalties over the two match statements I currently have hard-coded, would be difficult to pass around and would still require updating a list. What's the best way to implement this, preferably keeping all the changing code within the struct definition?
Can you show some example code?
Currently the struct might look like:
pub struct CopyInstruction {
address: usize,
}
pub const COPY_INSTRUCTION_CODE: InstructionCodeType = 3;
impl CopyInstruction {
pub fn get_debug(args) {
}
pub fn execute(args) {
}
}
And then the two usages are both similar to
macro_rules! translate {
($instruction: ident, $data: expr, $i: expr) => {
$instruction::get_debug(&$data, &mut $i)
};
}
let output = match InstructionCodeType::from_le_bytes(code.try_into().unwrap()) {
STACK_CREATE_INSTRUCTION_CODE => translate!(StackCreateInstruction, data, i),
STACK_UP_INSTRUCTION_CODE => translate!(StackUpInstruction, data, i),
HEAP_ALLOC_INSTRUCTION_CODE => translate!(HeapAllocInstruction, data, i),
COPY_INSTRUCTION_CODE => translate!(CopyInstruction, data, i),
STACK_DOWN_INSTRUCTION_CODE => translate!(StackDownInstruction, data, i),
code => panic!("Debug not implemented for code {}", code),
};
with both calling different static methods on the struct (replacing the contents of the translate macro)
I do not understand the problem. The example you provided doesn't help much. Are you trying to share data throughout your program and finding it difficult to achieve that?
I think I got your point. Do you want this?
let output = {
let get_debug = match InstructionCodeType::from_le_bytes(code.try_into().unwrap()) {
STACK_CREATE_INSTRUCTION_CODE => StackCreateInstruction::get_debug,
STACK_UP_INSTRUCTION_CODE => StackUpInstruction::get_debug,
HEAP_ALLOC_INSTRUCTION_CODE => HeapAllocInstruction::get_debug,
COPY_INSTRUCTION_CODE => CopyInstruction::get_debug,
STACK_DOWN_INSTRUCTION_CODE => StackDownInstruction::get_debug,
code => panic!("Debug not implemented for code {}", code),
};
get_debug(&data, &mut i);
};
Although this workaround is 100% sound, I would suggest you to put those get_debug
s into a trait, then make a function take a generic type implements that trait. It may more elegant and 'rusty'. I cannot do it for you, because I didn't know what exact type args
is.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.