billyrieger/bimap-rs

Generalize query interfaces

Closed this issue · 3 comments

It should be possible to generalize some of the interfaces for querying the BiMap to match the APIs in the standard library. (BTreeMap::get, HashMap::get.)

I've implemented this for my own copy of BiBTreeMap, so I'm fairly confident it works as expected.

    pub fn get_by_left<Q>(&self, left: &Q) -> Option<&R> 
        where
            Rc<L>: Borrow<Q>,
            Q: Ord + ?Sized, 

I'm not familiar enough with the code to know if it would be an obvious improvement or not, but I'd be happy to submit a PR if it's desirable and I find a good time to write it up.

I agree that using the Borrow trait would be desirable. Unfortunately, the method signature you suggested leaks implementation details, namely the use of Rc to share keys and values between the interior maps. That's a deal-breaker for me because eventually I'd like to get rid of Rc usage entirely and use raw pointers instead, something like this:

struct BiHashMap<L, R> {
    left_map: HashMap<Box<L>, *const R>,
    right_map: HashMap<Box<R>, *const L>,
}

I think such an implementation would be safe, but I'm not completely sure. Regardless, such a change would mean changing the function's type signature, any similar changes in the future would be propagated through the public API. If there's a way to accomplish this without leaking implementation details, I'd be all for it.

Out of curiosity, how did you get that to work at all? I attempted essentially the same thing a while ago but ran into a roadblock.

I think you're right. I don't actually have the Rc<L>: Borrow<Q> version working in the way I thought I had, due to the same roadblock you mentioned. Bummer... Thanks for taking a look at it anyway.

I think I may have found a way to get this to work, although it requires some unsafe usage. playground link