Possibility of a VacantEntry to return an OccupiedEntry on insertion

I am working on some code that looks like this:

fn my_operation() -> Result<()> {
    let mut map = BTreeMap::new();
    let object = serde_json::from_str(/*some str*/)?;
    for (key, value) in object {
        let &mut entry = map.entry(key);
        process_value(value, &mut entry);
}

fn process_value(value: Value, entry: &mut Entry<String, Vec<usize>>) {
    match value {
        Value::String(s) => {
           // conditionally insert into the map, nothing may be added, so no entry is created in this case
           if s.len() > 10 {
               entry.or_default().push(s.len());
            }
        }
       Value::Array(a) => a.into_iter().for_each(|item| process_value(item, entry),
       _ => todo!()
}

The issue is that insert on VacantEntry consumes self so I am not able to reuse the entry once I have inserted in it once.

I have considered passing the key and the map to the process_value function. This would means performing a lookup every time, and cloning the key every time I need to insert. I also tought about passing a Either<Entry<String, Vec<usize>>, &mut Vec<usize>> but that's rather ugly.

I am wondering if it would be possible for the Entry::insert_* method to mutate in place the Entry and turn a VavantEntry into a OccupiedEntry, and thus only mutably borrowing self, or for VacantEntry to expose a method that returns an OccupiedEntry upon insert?

Looks like there’s an unstable/nightly-only method Entry::insert that does this. Some more discussion in the corresponding issue #65225.

1 Like

Thanks @steffahn ! Indeed I didn't see that it was implemented on HashMap, thanks for the link to the tracking issue

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.