diff options
Diffstat (limited to 'src/reflect/accessor.rs')
-rw-r--r-- | src/reflect/accessor.rs | 789 |
1 files changed, 789 insertions, 0 deletions
diff --git a/src/reflect/accessor.rs b/src/reflect/accessor.rs new file mode 100644 index 0000000..8a586b2 --- /dev/null +++ b/src/reflect/accessor.rs @@ -0,0 +1,789 @@ +#![doc(hidden)] + +use std::collections::HashMap; +use std::fmt; +use std::hash::Hash; + +use core::message_down_cast; +use core::Message; +use enums::ProtobufEnum; +use reflect::EnumValueDescriptor; +use types::*; + +use repeated::RepeatedField; +use singular::SingularField; +use singular::SingularPtrField; + +use super::map::ReflectMap; +use super::optional::ReflectOptional; +use super::repeated::ReflectRepeated; +use super::repeated::ReflectRepeatedEnum; +use super::repeated::ReflectRepeatedMessage; +use super::value::ProtobufValue; +use super::value::ReflectValueRef; +use super::ReflectFieldRef; + +/// this trait should not be used directly, use `FieldDescriptor` instead +pub trait FieldAccessor { + fn name_generic(&self) -> &'static str; + fn has_field_generic(&self, m: &Message) -> bool; + fn len_field_generic(&self, m: &Message) -> usize; + // TODO: should it return default value or panic on unset field? + fn get_message_generic<'a>(&self, m: &'a Message) -> &'a Message; + fn get_enum_generic(&self, m: &Message) -> &'static EnumValueDescriptor; + fn get_str_generic<'a>(&self, m: &'a Message) -> &'a str; + fn get_bytes_generic<'a>(&self, m: &'a Message) -> &'a [u8]; + fn get_u32_generic(&self, m: &Message) -> u32; + fn get_u64_generic(&self, m: &Message) -> u64; + fn get_i32_generic(&self, m: &Message) -> i32; + fn get_i64_generic(&self, m: &Message) -> i64; + fn get_bool_generic(&self, m: &Message) -> bool; + fn get_f32_generic(&self, m: &Message) -> f32; + fn get_f64_generic(&self, m: &Message) -> f64; + + fn get_reflect<'a>(&self, m: &'a Message) -> ReflectFieldRef<'a>; +} + +trait GetSingularMessage<M> { + fn get_message<'a>(&self, m: &'a M) -> &'a Message; +} + +struct GetSingularMessageImpl<M, N> { + get: for<'a> fn(&'a M) -> &'a N, +} + +impl<M: Message, N: Message + 'static> GetSingularMessage<M> for GetSingularMessageImpl<M, N> { + fn get_message<'a>(&self, m: &'a M) -> &'a Message { + (self.get)(m) + } +} + +trait GetSingularEnum<M> { + fn get_enum(&self, m: &M) -> &'static EnumValueDescriptor; +} + +struct GetSingularEnumImpl<M, E> { + get: fn(&M) -> E, +} + +impl<M: Message, E: ProtobufEnum> GetSingularEnum<M> for GetSingularEnumImpl<M, E> { + fn get_enum(&self, m: &M) -> &'static EnumValueDescriptor { + (self.get)(m).descriptor() + } +} + +trait GetRepeatedMessage<M> { + fn len_field(&self, m: &M) -> usize; + fn get_message_item<'a>(&self, m: &'a M, index: usize) -> &'a Message; + fn reflect_repeated_message<'a>(&self, m: &'a M) -> Box<ReflectRepeatedMessage<'a> + 'a>; +} + +trait GetRepeatedEnum<M: Message + 'static> { + fn len_field(&self, m: &M) -> usize; + fn get_enum_item(&self, m: &M, index: usize) -> &'static EnumValueDescriptor; + fn reflect_repeated_enum<'a>(&self, m: &'a M) -> Box<ReflectRepeatedEnum<'a> + 'a>; +} + +trait GetSetCopyFns<M> { + fn get_field<'a>(&self, m: &'a M) -> ReflectValueRef<'a>; +} + +struct GetSetCopyFnsImpl<M, V: ProtobufValue + Copy> { + get: fn(&M) -> V, + _set: fn(&mut M, V), +} + +impl<M, V: ProtobufValue + Copy> GetSetCopyFns<M> for GetSetCopyFnsImpl<M, V> { + fn get_field<'a>(&self, m: &'a M) -> ReflectValueRef<'a> { + (&(self.get)(m) as &ProtobufValue).as_ref_copy() + } +} + +enum SingularGetSet<M> { + Copy(Box<GetSetCopyFns<M>>), + String(for<'a> fn(&'a M) -> &'a str, fn(&mut M, String)), + Bytes(for<'a> fn(&'a M) -> &'a [u8], fn(&mut M, Vec<u8>)), + Enum(Box<GetSingularEnum<M> + 'static>), + Message(Box<GetSingularMessage<M> + 'static>), +} + +impl<M: Message + 'static> SingularGetSet<M> { + fn get_ref<'a>(&self, m: &'a M) -> ReflectValueRef<'a> { + match self { + &SingularGetSet::Copy(ref copy) => copy.get_field(m), + &SingularGetSet::String(get, _) => ReflectValueRef::String(get(m)), + &SingularGetSet::Bytes(get, _) => ReflectValueRef::Bytes(get(m)), + &SingularGetSet::Enum(ref get) => ReflectValueRef::Enum(get.get_enum(m)), + &SingularGetSet::Message(ref get) => ReflectValueRef::Message(get.get_message(m)), + } + } +} + +trait FieldAccessor2<M, R: ?Sized> +where + M: Message + 'static, +{ + fn get_field<'a>(&self, &'a M) -> &'a R; + fn mut_field<'a>(&self, &'a mut M) -> &'a mut R; +} + +struct MessageGetMut<M, L> +where + M: Message + 'static, +{ + get_field: for<'a> fn(&'a M) -> &'a L, + mut_field: for<'a> fn(&'a mut M) -> &'a mut L, +} + +enum FieldAccessorFunctions<M> { + // up to 1.0.24 optional or required + SingularHasGetSet { + has: fn(&M) -> bool, + get_set: SingularGetSet<M>, + }, + // protobuf 3 simple field + Simple(Box<FieldAccessor2<M, ProtobufValue>>), + // optional, required or message + Optional(Box<FieldAccessor2<M, ReflectOptional>>), + // repeated + Repeated(Box<FieldAccessor2<M, ReflectRepeated>>), + // protobuf 3 map + Map(Box<FieldAccessor2<M, ReflectMap>>), +} + +impl<M> fmt::Debug for FieldAccessorFunctions<M> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &FieldAccessorFunctions::SingularHasGetSet { .. } => { + write!(f, "SingularHasGetSet {{ .. }}") + } + &FieldAccessorFunctions::Simple(..) => write!(f, "Simple(..)"), + &FieldAccessorFunctions::Optional(..) => write!(f, "Optional(..)"), + &FieldAccessorFunctions::Repeated(..) => write!(f, "Repeated(..)"), + &FieldAccessorFunctions::Map(..) => write!(f, "Map(..)"), + } + } +} + +struct FieldAccessorImpl<M> { + name: &'static str, + fns: FieldAccessorFunctions<M>, +} + +impl<M: Message> FieldAccessorImpl<M> { + fn get_value_option<'a>(&self, m: &'a M) -> Option<ReflectValueRef<'a>> { + match self.fns { + FieldAccessorFunctions::Repeated(..) | FieldAccessorFunctions::Map(..) => { + panic!("repeated") + } + FieldAccessorFunctions::Simple(ref a) => Some(a.get_field(m).as_ref()), + FieldAccessorFunctions::Optional(ref a) => { + a.get_field(m).to_option().map(|v| v.as_ref()) + } + FieldAccessorFunctions::SingularHasGetSet { + ref has, + ref get_set, + } => { + if !has(m) { + None + } else { + Some(get_set.get_ref(m)) + } + } + } + } +} + +impl<M: Message + 'static> FieldAccessor for FieldAccessorImpl<M> { + fn name_generic(&self) -> &'static str { + self.name + } + + fn has_field_generic(&self, m: &Message) -> bool { + match self.fns { + FieldAccessorFunctions::SingularHasGetSet { has, .. } => has(message_down_cast(m)), + FieldAccessorFunctions::Optional(ref a) => { + a.get_field(message_down_cast(m)).to_option().is_some() + } + FieldAccessorFunctions::Simple(ref a) => { + a.get_field(message_down_cast(m)).is_non_zero() + } + FieldAccessorFunctions::Map(..) | FieldAccessorFunctions::Repeated(..) => { + panic!("has_xxx is not implemented for repeated"); + } + } + } + + fn len_field_generic(&self, m: &Message) -> usize { + match self.fns { + FieldAccessorFunctions::Repeated(ref a) => a.get_field(message_down_cast(m)).len(), + FieldAccessorFunctions::Map(ref a) => a.get_field(message_down_cast(m)).len(), + FieldAccessorFunctions::Simple(..) + | FieldAccessorFunctions::SingularHasGetSet { .. } + | FieldAccessorFunctions::Optional(..) => { + panic!("not a repeated field"); + } + } + } + + fn get_message_generic<'a>(&self, m: &'a Message) -> &'a Message { + match self.fns { + FieldAccessorFunctions::SingularHasGetSet { + get_set: SingularGetSet::Message(ref get), + .. + } => get.get_message(message_down_cast(m)), + FieldAccessorFunctions::Optional(ref t) => { + match t + .get_field(message_down_cast(m)) + .to_option() + .expect("field unset") + .as_ref() + { + ReflectValueRef::Message(m) => m, + _ => panic!("not a message"), + } + } + ref fns => panic!("unknown accessor type: {:?}", fns), + } + } + + fn get_enum_generic(&self, m: &Message) -> &'static EnumValueDescriptor { + match self.fns { + FieldAccessorFunctions::SingularHasGetSet { + get_set: SingularGetSet::Enum(ref get), + .. + } => get.get_enum(message_down_cast(m)), + _ => panic!(), + } + } + + fn get_str_generic<'a>(&self, m: &'a Message) -> &'a str { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::String(v)) => v, + Some(_) => panic!("wrong type"), + None => "", // TODO: check type + } + } + + fn get_bytes_generic<'a>(&self, m: &'a Message) -> &'a [u8] { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::Bytes(v)) => v, + Some(_) => panic!("wrong type"), + None => b"", // TODO: check type + } + } + + fn get_u32_generic(&self, m: &Message) -> u32 { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::U32(v)) => v, + Some(_) => panic!("wrong type"), + None => 0, // TODO: check type + } + } + + fn get_u64_generic(&self, m: &Message) -> u64 { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::U64(v)) => v, + Some(_) => panic!("wrong type"), + None => 0, // TODO: check type + } + } + + fn get_i32_generic(&self, m: &Message) -> i32 { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::I32(v)) => v, + Some(_) => panic!("wrong type"), + None => 0, // TODO: check type + } + } + + fn get_i64_generic(&self, m: &Message) -> i64 { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::I64(v)) => v, + Some(_) => panic!("wrong type"), + None => 0, // TODO: check type + } + } + + fn get_f32_generic(&self, m: &Message) -> f32 { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::F32(v)) => v, + Some(_) => panic!("wrong type"), + None => 0.0, // TODO: check type + } + } + + fn get_f64_generic(&self, m: &Message) -> f64 { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::F64(v)) => v, + Some(_) => panic!("wrong type"), + None => 0.0, // TODO: check type + } + } + + fn get_bool_generic(&self, m: &Message) -> bool { + match self.get_value_option(message_down_cast(m)) { + Some(ReflectValueRef::Bool(v)) => v, + Some(_) => panic!("wrong type"), + None => false, // TODO: check type + } + } + + fn get_reflect<'a>(&self, m: &'a Message) -> ReflectFieldRef<'a> { + match self.fns { + FieldAccessorFunctions::Repeated(ref accessor2) => { + ReflectFieldRef::Repeated(accessor2.get_field(message_down_cast(m))) + } + FieldAccessorFunctions::Map(ref accessor2) => { + ReflectFieldRef::Map(accessor2.get_field(message_down_cast(m))) + } + FieldAccessorFunctions::Optional(ref accessor2) => ReflectFieldRef::Optional( + accessor2 + .get_field(message_down_cast(m)) + .to_option() + .map(|v| v.as_ref()), + ), + FieldAccessorFunctions::Simple(ref accessor2) => ReflectFieldRef::Optional({ + let v = accessor2.get_field(message_down_cast(m)); + if v.is_non_zero() { + Some(v.as_ref()) + } else { + None + } + }), + FieldAccessorFunctions::SingularHasGetSet { + ref has, + ref get_set, + } => ReflectFieldRef::Optional(if has(message_down_cast(m)) { + Some(get_set.get_ref(message_down_cast(m))) + } else { + None + }), + } + } +} + +// singular + +fn set_panic<A, B>(_: &mut A, _: B) { + panic!() +} + +// TODO: make_singular_xxx_accessor are used only for oneof fields +// oneof codegen should be changed + +pub fn make_singular_u32_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> u32, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { + get: get, + _set: set_panic, + })), + }, + }) +} + +pub fn make_singular_i32_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> i32, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { + get: get, + _set: set_panic, + })), + }, + }) +} + +pub fn make_singular_u64_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> u64, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { + get: get, + _set: set_panic, + })), + }, + }) +} + +pub fn make_singular_i64_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> i64, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { + get: get, + _set: set_panic, + })), + }, + }) +} + +pub fn make_singular_f32_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> f32, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { + get: get, + _set: set_panic, + })), + }, + }) +} + +pub fn make_singular_f64_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> f64, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { + get: get, + _set: set_panic, + })), + }, + }) +} + +pub fn make_singular_bool_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> bool, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { + get: get, + _set: set_panic, + })), + }, + }) +} + +pub fn make_singular_enum_accessor<M: Message + 'static, E: ProtobufEnum + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: fn(&M) -> E, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Enum(Box::new(GetSingularEnumImpl { get: get })), + }, + }) +} + +pub fn make_singular_string_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: for<'a> fn(&'a M) -> &'a str, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::String(get, set_panic), + }, + }) +} + +pub fn make_singular_bytes_accessor<M: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: for<'a> fn(&'a M) -> &'a [u8], +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Bytes(get, set_panic), + }, + }) +} + +pub fn make_singular_message_accessor<M: Message + 'static, F: Message + 'static>( + name: &'static str, + has: fn(&M) -> bool, + get: for<'a> fn(&'a M) -> &'a F, +) -> Box<FieldAccessor + 'static> { + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::SingularHasGetSet { + has: has, + get_set: SingularGetSet::Message(Box::new(GetSingularMessageImpl { get: get })), + }, + }) +} + +// repeated + +impl<M, V> FieldAccessor2<M, ReflectRepeated> for MessageGetMut<M, Vec<V>> +where + M: Message + 'static, + V: ProtobufValue + 'static, +{ + fn get_field<'a>(&self, m: &'a M) -> &'a ReflectRepeated { + (self.get_field)(m) as &ReflectRepeated + } + + fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectRepeated { + (self.mut_field)(m) as &mut ReflectRepeated + } +} + +pub fn make_vec_accessor<M, V>( + name: &'static str, + get_vec: for<'a> fn(&'a M) -> &'a Vec<V::Value>, + mut_vec: for<'a> fn(&'a mut M) -> &'a mut Vec<V::Value>, +) -> Box<FieldAccessor + 'static> +where + M: Message + 'static, + V: ProtobufType + 'static, +{ + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::Repeated(Box::new(MessageGetMut::<M, Vec<V::Value>> { + get_field: get_vec, + mut_field: mut_vec, + })), + }) +} + +impl<M, V> FieldAccessor2<M, ReflectRepeated> for MessageGetMut<M, RepeatedField<V>> +where + M: Message + 'static, + V: ProtobufValue + 'static, +{ + fn get_field<'a>(&self, m: &'a M) -> &'a ReflectRepeated { + (self.get_field)(m) as &ReflectRepeated + } + + fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectRepeated { + (self.mut_field)(m) as &mut ReflectRepeated + } +} + +pub fn make_repeated_field_accessor<M, V>( + name: &'static str, + get_vec: for<'a> fn(&'a M) -> &'a RepeatedField<V::Value>, + mut_vec: for<'a> fn(&'a mut M) -> &'a mut RepeatedField<V::Value>, +) -> Box<FieldAccessor + 'static> +where + M: Message + 'static, + V: ProtobufType + 'static, +{ + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::Repeated(Box::new(MessageGetMut::< + M, + RepeatedField<V::Value>, + > { + get_field: get_vec, + mut_field: mut_vec, + })), + }) +} + +impl<M, V> FieldAccessor2<M, ReflectOptional> for MessageGetMut<M, Option<V>> +where + M: Message + 'static, + V: ProtobufValue + Clone + 'static, +{ + fn get_field<'a>(&self, m: &'a M) -> &'a ReflectOptional { + (self.get_field)(m) as &ReflectOptional + } + + fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectOptional { + (self.mut_field)(m) as &mut ReflectOptional + } +} + +pub fn make_option_accessor<M, V>( + name: &'static str, + get_field: for<'a> fn(&'a M) -> &'a Option<V::Value>, + mut_field: for<'a> fn(&'a mut M) -> &'a mut Option<V::Value>, +) -> Box<FieldAccessor + 'static> +where + M: Message + 'static, + V: ProtobufType + 'static, +{ + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::Optional(Box::new(MessageGetMut::<M, Option<V::Value>> { + get_field: get_field, + mut_field: mut_field, + })), + }) +} + +impl<M, V> FieldAccessor2<M, ReflectOptional> for MessageGetMut<M, SingularField<V>> +where + M: Message + 'static, + V: ProtobufValue + Clone + 'static, +{ + fn get_field<'a>(&self, m: &'a M) -> &'a ReflectOptional { + (self.get_field)(m) as &ReflectOptional + } + + fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectOptional { + (self.mut_field)(m) as &mut ReflectOptional + } +} + +pub fn make_singular_field_accessor<M, V>( + name: &'static str, + get_field: for<'a> fn(&'a M) -> &'a SingularField<V::Value>, + mut_field: for<'a> fn(&'a mut M) -> &'a mut SingularField<V::Value>, +) -> Box<FieldAccessor + 'static> +where + M: Message + 'static, + V: ProtobufType + 'static, +{ + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::Optional(Box::new(MessageGetMut::< + M, + SingularField<V::Value>, + > { + get_field: get_field, + mut_field: mut_field, + })), + }) +} + +impl<M, V> FieldAccessor2<M, ReflectOptional> for MessageGetMut<M, SingularPtrField<V>> +where + M: Message + 'static, + V: ProtobufValue + Clone + 'static, +{ + fn get_field<'a>(&self, m: &'a M) -> &'a ReflectOptional { + (self.get_field)(m) as &ReflectOptional + } + + fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectOptional { + (self.mut_field)(m) as &mut ReflectOptional + } +} + +pub fn make_singular_ptr_field_accessor<M, V>( + name: &'static str, + get_field: for<'a> fn(&'a M) -> &'a SingularPtrField<V::Value>, + mut_field: for<'a> fn(&'a mut M) -> &'a mut SingularPtrField<V::Value>, +) -> Box<FieldAccessor + 'static> +where + M: Message + 'static, + V: ProtobufType + 'static, +{ + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::Optional(Box::new(MessageGetMut::< + M, + SingularPtrField<V::Value>, + > { + get_field: get_field, + mut_field: mut_field, + })), + }) +} + +impl<M, V> FieldAccessor2<M, ProtobufValue> for MessageGetMut<M, V> +where + M: Message + 'static, + V: ProtobufValue + Clone + 'static, +{ + fn get_field<'a>(&self, m: &'a M) -> &'a ProtobufValue { + (self.get_field)(m) as &ProtobufValue + } + + fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ProtobufValue { + (self.mut_field)(m) as &mut ProtobufValue + } +} + +pub fn make_simple_field_accessor<M, V>( + name: &'static str, + get_field: for<'a> fn(&'a M) -> &'a V::Value, + mut_field: for<'a> fn(&'a mut M) -> &'a mut V::Value, +) -> Box<FieldAccessor + 'static> +where + M: Message + 'static, + V: ProtobufType + 'static, +{ + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::Simple(Box::new(MessageGetMut::<M, V::Value> { + get_field: get_field, + mut_field: mut_field, + })), + }) +} + +impl<M, K, V> FieldAccessor2<M, ReflectMap> for MessageGetMut<M, HashMap<K, V>> +where + M: Message + 'static, + K: ProtobufValue + 'static, + V: ProtobufValue + 'static, + K: Hash + Eq, +{ + fn get_field<'a>(&self, m: &'a M) -> &'a ReflectMap { + (self.get_field)(m) as &ReflectMap + } + + fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut ReflectMap { + (self.mut_field)(m) as &mut ReflectMap + } +} + +pub fn make_map_accessor<M, K, V>( + name: &'static str, + get_field: for<'a> fn(&'a M) -> &'a HashMap<K::Value, V::Value>, + mut_field: for<'a> fn(&'a mut M) -> &'a mut HashMap<K::Value, V::Value>, +) -> Box<FieldAccessor + 'static> +where + M: Message + 'static, + K: ProtobufType + 'static, + V: ProtobufType + 'static, + <K as ProtobufType>::Value: Hash + Eq, +{ + Box::new(FieldAccessorImpl { + name: name, + fns: FieldAccessorFunctions::Map(Box::new( + MessageGetMut::<M, HashMap<K::Value, V::Value>> { + get_field: get_field, + mut_field: mut_field, + }, + )), + }) +} |