How to read exact value from hashmap and not the reference to the value

I am using hashmap under the following struct

#[derive(Default)]
pub struct CasbinGRPC {
    enforcer_map: HashMap<i32, Enforcer>,
    adapter_map: HashMap<i32, Box<dyn Adapter>>,
}

I want to use it under the following function:

pub fn get_enforcer(&self, handle: i32) -> Result<&Enforcer, &str> {
        self.enforcer_map.get(&handle).ok_or("No enforcer found")
    }

Here, self refers to the above struct. get() returns reference to the Enforcer value &Enforcer, but I need Enforcer as value. I am not sure how can I do it? Using get_mut() I get following error:

22 |     pub fn get_enforcer(&self, handle: i32) -> Result<&mut Enforcer, &str> {
   |                         ----- help: consider changing this to be a mutable reference: `&mut self`
23 |         self.enforcer_map.get_mut(&handle).ok_or("No enforcer found")
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable

I can't use &mut self in above function, since its restricted by some other functions definition defined by .proto file extracted using tonic_build.

So the only thing I could do is to find a way so that hashmap can return dereferenced value Enforcer without needing to have &mut self. Also, I have tried using remove() but that doesn't makes sense since we need to remove the value from the hashmap and that too requires to have &mut self in function definition.

NOTE:
Enforcer is defined here: casbin-rs/enforcer.rs at master · casbin/casbin-rs · GitHub

Getting the value without a reference means you have either copied or moved the value out of the collection. For the first, map.get(key)?.clone(), for the second map.remove(key)

2 Likes

Thank you for the suggestion, but I believe that wont work in this case since the output of self.enforcer_map.get(&handle).unwrap().to_owned() is &Enforcer, where to_owned() generally creates clone, even using clone won't make any difference.

I am getting following output, this doesn't change even on using .clone()

I don't see an implementation of Clone on Enforcer (and it doesn't really make sense), so the only thing that will be cloning is the reference itself.

Really your problem here is that you do actually need a mutable ref, there's not really a way around it. RefCell is probably your best option here, though it's a bit ugly.

1 Like

Tonic makes your methods take &self so that they can be called in parallel. You should use a mutex around muable data in the struct. See this for more.

1 Like

Thank you, surely will take it