Skip to content

Commit 23388b8

Browse files
committed
hashbrown support
1 parent 8c9d915 commit 23388b8

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

Cargo.lock

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

redis/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ log = { version = "0.4", optional = true }
9090
# Optional uuid support
9191
uuid = { version = "1.10.0", optional = true }
9292

93+
# Optional hashbrown support
94+
hashbrown = { version = "0.14", optional = true }
95+
9396
[features]
9497
default = ["acl", "streams", "geospatial", "script", "keep-alive"]
9598
acl = []
@@ -119,6 +122,7 @@ bigdecimal = ["dep:bigdecimal"]
119122
num-bigint = []
120123
uuid = ["dep:uuid"]
121124
disable-client-setinfo = []
125+
hashbrown = ["dep:hashbrown"]
122126

123127
# Deprecated features
124128
tls = ["tls-native-tls"] # use "tls-native-tls" instead

redis/src/types.rs

+88
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,22 @@ impl<T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default> ToRedisArgs
15361536
}
15371537
}
15381538

1539+
#[cfg(feature = "hashbrown")]
1540+
impl<T: ToRedisArgs + Hash + Eq, S: BuildHasher + Default> ToRedisArgs
1541+
for hashbrown::HashSet<T, S>
1542+
{
1543+
fn write_redis_args<W>(&self, out: &mut W)
1544+
where
1545+
W: ?Sized + RedisWrite,
1546+
{
1547+
ToRedisArgs::make_arg_iter_ref(self.iter(), out)
1548+
}
1549+
1550+
fn num_of_args(&self) -> usize {
1551+
self.len()
1552+
}
1553+
}
1554+
15391555
/// @note: Redis cannot store empty sets so the application has to
15401556
/// check whether the set is empty and if so, not attempt to use that
15411557
/// result
@@ -1612,6 +1628,25 @@ impl<T: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs> ToRedisArgs
16121628
}
16131629
}
16141630

1631+
#[cfg(feature = "hashbrown")]
1632+
impl<T: ToRedisArgs + Hash + Eq + Ord, V: ToRedisArgs> ToRedisArgs for hashbrown::HashMap<T, V> {
1633+
fn write_redis_args<W>(&self, out: &mut W)
1634+
where
1635+
W: ?Sized + RedisWrite,
1636+
{
1637+
for (key, value) in self {
1638+
assert!(key.num_of_args() <= 1 && value.num_of_args() <= 1);
1639+
1640+
key.write_redis_args(out);
1641+
value.write_redis_args(out);
1642+
}
1643+
}
1644+
1645+
fn num_of_args(&self) -> usize {
1646+
self.len()
1647+
}
1648+
}
1649+
16151650
macro_rules! to_redis_args_for_tuple {
16161651
() => ();
16171652
($($name:ident,)+) => (
@@ -2105,6 +2140,36 @@ impl<K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default>
21052140
}
21062141
}
21072142

2143+
#[cfg(feature = "hashbrown")]
2144+
impl<K: FromRedisValue + Eq + Hash, V: FromRedisValue, S: BuildHasher + Default> FromRedisValue
2145+
for hashbrown::HashMap<K, V, S>
2146+
{
2147+
fn from_redis_value(v: &Value) -> RedisResult<hashbrown::HashMap<K, V, S>> {
2148+
let v = get_inner_value(v);
2149+
match *v {
2150+
Value::Nil => Ok(Default::default()),
2151+
_ => v
2152+
.as_map_iter()
2153+
.ok_or_else(|| {
2154+
invalid_type_error_inner!(v, "Response type not hashmap compatible")
2155+
})?
2156+
.map(|(k, v)| Ok((from_redis_value(k)?, from_redis_value(v)?)))
2157+
.collect(),
2158+
}
2159+
}
2160+
fn from_owned_redis_value(v: Value) -> RedisResult<hashbrown::HashMap<K, V, S>> {
2161+
let v = get_owned_inner_value(v);
2162+
match v {
2163+
Value::Nil => Ok(Default::default()),
2164+
_ => v
2165+
.into_map_iter()
2166+
.map_err(|v| invalid_type_error_inner!(v, "Response type not hashmap compatible"))?
2167+
.map(|(k, v)| Ok((from_owned_redis_value(k)?, from_owned_redis_value(v)?)))
2168+
.collect(),
2169+
}
2170+
}
2171+
}
2172+
21082173
#[cfg(feature = "ahash")]
21092174
impl<K: FromRedisValue + Eq + Hash, V: FromRedisValue> FromRedisValue for ahash::AHashMap<K, V> {
21102175
fn from_redis_value(v: &Value) -> RedisResult<ahash::AHashMap<K, V>> {
@@ -2175,6 +2240,29 @@ impl<T: FromRedisValue + Eq + Hash, S: BuildHasher + Default> FromRedisValue
21752240
}
21762241
}
21772242

2243+
#[cfg(feature = "hashbrown")]
2244+
impl<T: FromRedisValue + Eq + Hash, S: BuildHasher + Default> FromRedisValue
2245+
for hashbrown::HashSet<T, S>
2246+
{
2247+
fn from_redis_value(v: &Value) -> RedisResult<hashbrown::HashSet<T, S>> {
2248+
let v = get_inner_value(v);
2249+
let items = v
2250+
.as_sequence()
2251+
.ok_or_else(|| invalid_type_error_inner!(v, "Response type not hashset compatible"))?;
2252+
items.iter().map(|item| from_redis_value(item)).collect()
2253+
}
2254+
fn from_owned_redis_value(v: Value) -> RedisResult<hashbrown::HashSet<T, S>> {
2255+
let v = get_owned_inner_value(v);
2256+
let items = v
2257+
.into_sequence()
2258+
.map_err(|v| invalid_type_error_inner!(v, "Response type not hashset compatible"))?;
2259+
items
2260+
.into_iter()
2261+
.map(|item| from_owned_redis_value(item))
2262+
.collect()
2263+
}
2264+
}
2265+
21782266
#[cfg(feature = "ahash")]
21792267
impl<T: FromRedisValue + Eq + Hash> FromRedisValue for ahash::AHashSet<T> {
21802268
fn from_redis_value(v: &Value) -> RedisResult<ahash::AHashSet<T>> {

0 commit comments

Comments
 (0)