How to insert into a hash map a key value pair if and only if the key is not already in the map?

I have this method:

    pub fn AddCab(&mut self,name: String,color: String) -> &Cab {               
        match self.cabs.get(&name) {                                            
            None => {                                                           
                self.cabs.insert(name,Cab::new(name.clone(),color));            
                &self.cabs[&name]                                               
            },                                                                  
            Some(c) => c,                                                       
        }                                                                       
    }                                                                           

And I am getting this error:

error[E0502]: cannot borrow `self.cabs` as mutable because it is also borrowed a
s immutable
   --> src/lib.rs:699:17
    |
696 |       pub fn AddCab(&mut self,name: String,color: String) -> &Cab {
    |                     - let's call the lifetime of this reference `'1`
697 |           match self.cabs.get(&name) {
    |           -     --------- immutable borrow occurs here
    |  _________|
    | |
698 | |             None => {
699 | |                 self.cabs.insert(name,Cab::new(name.clone(),color));
    | |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ muta
ble borrow occurs here
700 | |                 &self.cabs[&name]
701 | |             },
702 | |             Some(c) => c,
703 | |         }
    | |_________- returning this value requires that `self.cabs` is borrowed for
 `'1`

The cabs field is declared as: cabs: CabNameMap.

Is there a way around this?

Yes, use the entry function instead of get/insert.

I don't want to modify the entry, only insert if it is not there. I am not sure if the entry method is the right thing.

Would this work for you? This is simply a snippet from the docs for HashMap

// update a key, guarding against the key possibly not being set
let stat = player_stats.entry("attack").or_insert(100);

Otherwise, a code we can run (sort of) in the playground may be useful.

Wouldn't if clause be easier?

pub fn AddCab(&mut self,name: String,color: String) -> &Cab {               
        if self.cabs.contains_key(&name) {
                self.cabs.insert(name,Cab::new(name.clone(),color));            
                
         }
         &self.cabs[&name]                                               
    }        

...although, now I prefer not to write such wrapping code, it just makes it unclear what is happening. I'd put this if into caller code, unless this repeats very often.

You use the or_insert method. Entry in std::collections::hash_map - Rust

This should do what you need:

pub fn AddCab(&mut self, name: String, color: String) -> &Cab {
    self.cabs.entry(name).or_insert(Cab::new(name, color))
}

The entry API is made for exactly this, avoiding the borrow issue.

What a coincidence, I'm writing examples for AI training, and this is one of the cases.