How to call struct method as function pointer in loop

⚓ Rust    📅 2026-04-20    👤 surdeus    👁️ 3      

surdeus

I write a parser to analyze the text. I want to store the methods into a HashMap, like the table-driven approach in C languange, to reduce the match-select code. then I can call the method by accessing the HashMap using the state as key. But there are a few tricky problems.
My intention is to use a concise method to replace numerous branches(match-select, if-else and so on).
NOTE: It needs to support the lifetime if feasible.

The sample code as following:

use std::collections::HashMap;

//It needs to set lifetime to match the Parser<'a>
type HandlerPtr<'a> = fn(&'a mut Parser<'a>)->i32;

//It need lifetime to support the buffer reference
pub struct Parser<'a> {
    //It MUST be the reference here
    buffer: &'a [u8],
    state: i32,
    handlers: HashMap<i32, HandlerPtr<'a>>,
}

impl<'a> Parser<'a> {
    pub fn new(buf: &'a [u8]) -> Self {
        Self{
            buffer: buf,
            state: -1,
            handlers: HashMap::new(),
        }
    }

    pub fn init(&mut self) {
        self.handlers.insert(-1, Parser::handle_none);
        self.handlers.insert(0, Parser::handle_one);

    }

    pub fn test(&'a mut self) {
        let mut state = -1_i32;
        //Compiling error when accessing the HashMap more than once
        for _i in 0..3{
            let myfn = self.handlers.get(&state).unwrap();
            state = myfn(self);
            println!("---test: {}", state);
        }
    }

    pub fn handle_none(&'a mut self) -> i32 {
        let ch = self.buffer[0];
        println!("[handle_none] {:?}", ch);
        //change state

        self.state = 0;
        self.state
    }

    pub fn handle_one(&mut self) -> i32 {
        let ch = self.buffer[1];
        println!("[handle_one] {:?}", ch);

        self.state = -1;
        self.state
    }
}

fn main() {
    let buf = [0_u8;16];
    let mut p = Parser::new(&buf);
    p.init();
    p.test();
}

The compiler report the error as:

let myfn = self.handlers.get(&state).unwrap();
   |                        ------------------------- argument requires that `*self` is borrowed for `'a`
   |             state = myfn(self);
   |                          ^^^^ `*self` was mutably borrowed here in the previous iteration of the loop

There are more then once mutable borrowed if I want to access the method function pointer. I try the version without lifetime, it works. But it seems unsolvable in the lifetime version.
Does anyone know how to fix the issues? Or can give other alternative solutions?
Thank you!

2 posts - 2 participants

Read full topic

🏷️ Rust_feed