From 7f9f60d9e7c70cb1e2dfc26bf3defd99046d8274 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 26 Jun 2024 00:30:41 +0100 Subject: [PATCH] Working on support of BTreeMap This commit adds reflection support for it, but it is not used yet. Taken from PR #700. --- protobuf/src/reflect/map/generated.rs | 57 ++++++++++++++++++-- protobuf/src/reflect/runtime_types.rs | 76 ++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 6 deletions(-) diff --git a/protobuf/src/reflect/map/generated.rs b/protobuf/src/reflect/map/generated.rs index 0a5f200e9..d1f01047e 100644 --- a/protobuf/src/reflect/map/generated.rs +++ b/protobuf/src/reflect/map/generated.rs @@ -1,4 +1,6 @@ +use std::collections::btree_map; use std::collections::hash_map; +use std::collections::BTreeMap; use std::collections::HashMap; use std::hash::Hash; @@ -19,7 +21,9 @@ where K::RuntimeType: RuntimeTypeMapKey, { fn reflect_iter<'a>(&'a self) -> ReflectMapIter<'a> { - ReflectMapIter::new(GeneratedMapIterImpl::<'a, K, V> { iter: self.iter() }) + ReflectMapIter::new(GeneratedMapIterImpl::<'a, K, V, hash_map::Iter<'a, K, V>> { + iter: self.iter(), + }) } fn len(&self) -> usize { @@ -53,12 +57,55 @@ where } } -struct GeneratedMapIterImpl<'a, K: Eq + Hash + 'static, V: 'static> { - iter: hash_map::Iter<'a, K, V>, +impl ReflectMap for BTreeMap +where + K: ProtobufValue + Ord, + V: ProtobufValue, + K::RuntimeType: RuntimeTypeMapKey, +{ + fn reflect_iter<'a>(&'a self) -> ReflectMapIter<'a> { + ReflectMapIter::new( + GeneratedMapIterImpl::<'a, K, V, btree_map::Iter<'a, K, V>> { iter: self.iter() }, + ) + } + + fn len(&self) -> usize { + BTreeMap::len(self) + } + + fn is_empty(&self) -> bool { + self.is_empty() + } + + fn get<'a>(&'a self, key: ReflectValueRef) -> Option> { + ::btree_map_get(self, key).map(V::RuntimeType::as_ref) + } + + fn insert(&mut self, key: ReflectValueBox, value: ReflectValueBox) { + let key: K = key.downcast().expect("wrong key type"); + let value: V = value.downcast().expect("wrong value type"); + self.insert(key, value); + } + + fn clear(&mut self) { + self.clear(); + } + + fn key_type(&self) -> RuntimeType { + K::RuntimeType::runtime_type_box() + } + + fn value_type(&self) -> RuntimeType { + V::RuntimeType::runtime_type_box() + } +} + +struct GeneratedMapIterImpl<'a, K: 'static, V: 'static, I: Iterator> { + iter: I, } -impl<'a, K: ProtobufValue + Eq + Hash, V: ProtobufValue> ReflectMapIterTrait<'a> - for GeneratedMapIterImpl<'a, K, V> +impl<'a, K: ProtobufValue, V: ProtobufValue, I: Iterator> + ReflectMapIterTrait<'a> for GeneratedMapIterImpl<'a, K, V, I> { fn next(&mut self) -> Option<(ReflectValueRef<'a>, ReflectValueRef<'a>)> { match self.iter.next() { diff --git a/protobuf/src/reflect/runtime_types.rs b/protobuf/src/reflect/runtime_types.rs index d10be194b..bb7302c3c 100644 --- a/protobuf/src/reflect/runtime_types.rs +++ b/protobuf/src/reflect/runtime_types.rs @@ -1,5 +1,6 @@ //! Implementations of `RuntimeType` for all types. +use std::collections::BTreeMap; use std::collections::HashMap; use std::fmt; use std::marker; @@ -123,6 +124,12 @@ pub trait RuntimeTypeMapKey: RuntimeTypeTrait { /// Query hash map with a given key. fn hash_map_get<'a, V>(map: &'a HashMap, key: ReflectValueRef) -> Option<&'a V>; + + /// Query btree map with a given key. + fn btree_map_get<'a, V>( + map: &'a BTreeMap, + key: ReflectValueRef, + ) -> Option<&'a V>; } /// Implementation for `f32` @@ -318,6 +325,16 @@ impl RuntimeTypeMapKey for RuntimeTypeI32 { _ => None, } } + + fn btree_map_get<'a, V>( + map: &'a BTreeMap, + key: ReflectValueRef, + ) -> Option<&'a V> { + match key { + ReflectValueRef::I32(i) => map.get(&i), + _ => None, + } + } } impl RuntimeTypeTrait for RuntimeTypeI64 { @@ -371,7 +388,20 @@ impl RuntimeTypeTrait for RuntimeTypeI64 { } } impl RuntimeTypeMapKey for RuntimeTypeI64 { - fn hash_map_get<'a, V>(map: &'a HashMap, key: ReflectValueRef) -> Option<&'a V> { + fn hash_map_get<'a, V>( + map: &'a HashMap, + key: ReflectValueRef, + ) -> Option<&'a V> { + match key { + ReflectValueRef::I64(i) => map.get(&i), + _ => None, + } + } + + fn btree_map_get<'a, V>( + map: &'a BTreeMap, + key: ReflectValueRef, + ) -> Option<&'a V> { match key { ReflectValueRef::I64(i) => map.get(&i), _ => None, @@ -435,6 +465,13 @@ impl RuntimeTypeMapKey for RuntimeTypeU32 { _ => None, } } + + fn btree_map_get<'a, V>(map: &'a BTreeMap, key: ReflectValueRef) -> Option<&'a V> { + match key { + ReflectValueRef::U32(i) => map.get(&i), + _ => None, + } + } } impl RuntimeTypeTrait for RuntimeTypeU64 { @@ -493,6 +530,13 @@ impl RuntimeTypeMapKey for RuntimeTypeU64 { _ => None, } } + + fn btree_map_get<'a, V>(map: &'a BTreeMap, key: ReflectValueRef) -> Option<&'a V> { + match key { + ReflectValueRef::U64(i) => map.get(&i), + _ => None, + } + } } impl RuntimeTypeTrait for RuntimeTypeBool { @@ -548,6 +592,16 @@ impl RuntimeTypeMapKey for RuntimeTypeBool { _ => None, } } + + fn btree_map_get<'a, V>( + map: &'a BTreeMap, + key: ReflectValueRef, + ) -> Option<&'a V> { + match key { + ReflectValueRef::Bool(i) => map.get(&i), + _ => None, + } + } } impl RuntimeTypeTrait for RuntimeTypeString { @@ -606,6 +660,20 @@ impl RuntimeTypeMapKey for RuntimeTypeString { _ => None, } } + + /// Query btree map with a given key. + fn btree_map_get<'a, V>( + map: &'a BTreeMap, + key: ReflectValueRef, + ) -> Option<&'a V> + where + Self::Value: Ord, + { + match key { + ReflectValueRef::String(s) => map.get(s), + _ => None, + } + } } impl RuntimeTypeTrait for RuntimeTypeVecU8 { @@ -770,6 +838,12 @@ impl RuntimeTypeMapKey for RuntimeTypeTokioChars { _ => None, } } + fn btree_map_get<'a, V>(map: &'a BTreeMap, key: ReflectValueRef) -> Option<&'a V> { + match key { + ReflectValueRef::String(s) => map.get(&*s), + _ => None, + } + } } impl RuntimeTypeTrait for RuntimeTypeEnumOrUnknown