-
Notifications
You must be signed in to change notification settings - Fork 289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experiment with Equivalent that takes self by value #391
Conversation
cf58a74
to
6c9cc5d
Compare
Is it possible not to do this? That is, extracting the The point is that I am now developing common traits in order to abstract from different types of containers (see the code below). If you start accepting a key by value rather than by reference, then the trait cannot be implemented for use std::collections::{self, hash_map};
pub trait Equivalent<K: ?Sized>: hashbrown::Equivalent<K> + indexmap::Equivalent<K> {
fn equivalent(&self, key: &K) -> bool;
}
impl<Q: ?Sized, K: ?Sized> Equivalent<K> for Q
where
Q: Eq,
K: Borrow<Q>,
{
#[inline]
fn equivalent(&self, key: &K) -> bool {
*self == *key.borrow()
}
}
pub trait AnyContainerRef<E: ?Sized> {
type Key;
type Value;
type Keys<'a>: Iterator<Item = &'a Self::Key>
where
Self: 'a,
Self::Key: 'a;
type Values<'a>: Iterator<Item = &'a Self::Value>
where
Self: 'a,
Self::Value: 'a;
fn cont_len(&self) -> usize;
fn is_cont_empty(&self) -> bool;
fn contains_eq(&self, key: &E) -> bool;
fn get_value(&self, key: &E) -> Option<&Self::Value>;
fn get_converted<'a, 'b, FV>(&'a self, key: &E) -> Option<FV>
where
FV: From<&'b Self::Value>,
Self::Value: 'b,
'a: 'b,
{
if let Some(value) = self.get_value(key) {
return Some(value.into());
}
None
}
fn cont_keys(&self) -> Self::Keys<'_>;
fn cont_values(&self) -> Self::Values<'_>;
}
impl<K, V, Q, S> AnyContainerRef<Q> for collections::HashMap<K, V, S>
where
K: Hash + Eq + Borrow<Q>,
Q: ?Sized + Hash + Eq,
S: BuildHasher,
{
type Key = K;
type Value = V;
type Keys<'a> = hash_map::Keys<'a, K, V> where Self: 'a, K: 'a, V: 'a;
type Values<'a> = hash_map::Values<'a, K, V> where Self: 'a, K: 'a, V: 'a;
#[inline]
fn cont_len(&self) -> usize {
self.len()
}
#[inline]
fn is_cont_empty(&self) -> bool {
self.is_empty()
}
#[inline]
fn contains_eq(&self, eq: &Q) -> bool {
self.contains_key(eq)
}
#[inline]
fn get_value(&self, key: &Q) -> Option<&Self::Value> {
self.get(key)
}
#[inline]
fn cont_keys(&self) -> Self::Keys<'_> {
self.keys()
}
#[inline]
fn cont_values(&self) -> Self::Values<'_> {
self.values()
}
}
impl<K, V, Q, S> AnyContainerRef<Q> for hashbrown::HashMap<K, V, S>
where
K: Hash + Eq,
Q: ?Sized + Hash + Equivalent<K>,
S: BuildHasher,
{
type Key = K;
type Value = V;
type Keys<'a> = hashbrown::hash_map::Keys<'a, K, V> where Self: 'a, K: 'a, V: 'a;
type Values<'a> = hashbrown::hash_map::Values<'a, K, V> where Self: 'a, K: 'a, V: 'a;
#[inline]
fn cont_len(&self) -> usize {
self.len()
}
#[inline]
fn is_cont_empty(&self) -> bool {
self.is_empty()
}
#[inline]
fn contains_eq(&self, eq: &Q) -> bool {
self.contains_key(eq)
}
#[inline]
fn get_value(&self, key: &Q) -> Option<&Self::Value> {
self.get(key)
}
#[inline]
fn cont_keys(&self) -> Self::Keys<'_> {
self.keys()
}
#[inline]
fn cont_values(&self) -> Self::Values<'_> {
self.values()
}
}
impl<K, V, Q, S> AnyContainerRef<Q> for indexmap::IndexMap<K, V, S>
where
K: Hash + Eq,
Q: ?Sized + Hash + Equivalent<K>,
S: BuildHasher,
{
type Key = K;
type Value = V;
type Keys<'a> = indexmap::map::Keys<'a, K, V> where Self: 'a, K: 'a, V: 'a;
type Values<'a> = indexmap::map::Values<'a, K, V> where Self: 'a, K: 'a, V: 'a;
#[inline]
fn cont_len(&self) -> usize {
self.len()
}
#[inline]
fn is_cont_empty(&self) -> bool {
self.is_empty()
}
#[inline]
fn contains_eq(&self, eq: &Q) -> bool {
self.contains_key(eq)
}
#[inline]
fn get_value(&self, key: &Q) -> Option<&Self::Value> {
self.get(key)
}
#[inline]
fn cont_keys(&self) -> Self::Keys<'_> {
self.keys()
}
#[inline]
fn cont_values(&self) -> Self::Values<'_> {
self.values()
}
} |
I think there's no problem for your case, but let's keep that discussion in indexmap-rs/indexmap#253. |
☔ The latest upstream changes (presumably #425) made this pull request unmergeable. Please resolve the merge conflicts. |
We're talking about sharing the
Equivalent
trait withindexmap
, and I'm trying changes:indexmap-rs/indexmap#253 (comment)
While this changes a lot of API signatures, note that I didn't have to change any test code, except the one implementing
Equivalent
manually of course.