#![doc(hidden)] //! Version 1 reflection accessors. use std::collections::HashMap; use std::fmt; use std::hash::Hash; use crate::enums::ProtobufEnum; use crate::message::message_down_cast; use crate::message::Message; use crate::reflect::EnumValueDescriptor; use crate::reflect::ProtobufValue; use crate::reflect::ReflectFieldRef; use crate::reflect::ReflectValueRef; use crate::types::*; use crate::reflect::map::ReflectMap; use crate::reflect::optional::ReflectOptional; use crate::reflect::repeated::ReflectRepeated; use crate::reflect::repeated::ReflectRepeatedEnum; use crate::reflect::repeated::ReflectRepeatedMessage; use crate::reflect::rt::FieldAccessor; use crate::repeated::RepeatedField; use crate::singular::SingularField; use crate::singular::SingularPtrField; /// this trait should not be used directly, use `FieldDescriptor` instead pub trait FieldAccessorTrait: Sync + 'static { fn has_field_generic(&self, m: &dyn Message) -> bool; fn len_field_generic(&self, m: &dyn Message) -> usize; // TODO: should it return default value or panic on unset field? fn get_message_generic<'a>(&self, m: &'a dyn Message) -> &'a dyn Message; fn get_enum_generic(&self, m: &dyn Message) -> &'static EnumValueDescriptor; fn get_str_generic<'a>(&self, m: &'a dyn Message) -> &'a str; fn get_bytes_generic<'a>(&self, m: &'a dyn Message) -> &'a [u8]; fn get_u32_generic(&self, m: &dyn Message) -> u32; fn get_u64_generic(&self, m: &dyn Message) -> u64; fn get_i32_generic(&self, m: &dyn Message) -> i32; fn get_i64_generic(&self, m: &dyn Message) -> i64; fn get_bool_generic(&self, m: &dyn Message) -> bool; fn get_f32_generic(&self, m: &dyn Message) -> f32; fn get_f64_generic(&self, m: &dyn Message) -> f64; fn get_reflect<'a>(&self, m: &'a dyn Message) -> ReflectFieldRef<'a>; } pub(crate) trait GetSingularMessage: Sync { fn get_message<'a>(&self, m: &'a M) -> &'a dyn Message; } struct GetSingularMessageImpl { get: for<'a> fn(&'a M) -> &'a N, } impl GetSingularMessage for GetSingularMessageImpl { fn get_message<'a>(&self, m: &'a M) -> &'a dyn Message { (self.get)(m) } } pub(crate) trait GetSingularEnum: Sync { fn get_enum(&self, m: &M) -> &'static EnumValueDescriptor; } struct GetSingularEnumImpl { get: fn(&M) -> E, } impl GetSingularEnum for GetSingularEnumImpl { fn get_enum(&self, m: &M) -> &'static EnumValueDescriptor { (self.get)(m).descriptor() } } trait GetRepeatedMessage: Sync { fn len_field(&self, m: &M) -> usize; fn get_message_item<'a>(&self, m: &'a M, index: usize) -> &'a dyn Message; fn reflect_repeated_message<'a>(&self, m: &'a M) -> Box + 'a>; } trait GetRepeatedEnum: Sync { 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 + 'a>; } pub(crate) trait GetSetCopyFns: Sync { fn get_field<'a>(&self, m: &'a M) -> ReflectValueRef<'a>; } struct GetSetCopyFnsImpl { get: fn(&M) -> V, _set: fn(&mut M, V), } impl GetSetCopyFns for GetSetCopyFnsImpl { fn get_field<'a>(&self, m: &'a M) -> ReflectValueRef<'a> { (&(self.get)(m) as &dyn ProtobufValue).as_ref_copy() } } pub(crate) enum SingularGetSet { Copy(Box>), String(for<'a> fn(&'a M) -> &'a str, fn(&mut M, String)), Bytes(for<'a> fn(&'a M) -> &'a [u8], fn(&mut M, Vec)), Enum(Box + 'static>), Message(Box + 'static>), } impl SingularGetSet { 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)), } } } pub(crate) trait FieldAccessor2: Sync 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 where M: Message + 'static, { get_field: for<'a> fn(&'a M) -> &'a L, mut_field: for<'a> fn(&'a mut M) -> &'a mut L, } pub(crate) enum FieldAccessorFunctions { // up to 1.0.24 optional or required SingularHasGetSet { has: fn(&M) -> bool, get_set: SingularGetSet, }, // protobuf 3 simple field Simple(Box>), // optional, required or message Optional(Box>), // repeated Repeated(Box>), // protobuf 3 map Map(Box>), } impl fmt::Debug for FieldAccessorFunctions { 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(..)"), } } } pub(crate) struct FieldAccessorImpl { pub(crate) fns: FieldAccessorFunctions, } impl FieldAccessorImpl { fn get_value_option<'a>(&self, m: &'a M) -> Option> { 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 FieldAccessorTrait for FieldAccessorImpl { fn has_field_generic(&self, m: &dyn 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: &dyn 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 dyn Message) -> &'a dyn 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: &dyn 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 dyn 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 dyn 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: &dyn 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: &dyn 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: &dyn 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: &dyn 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_bool_generic(&self, m: &dyn 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_f32_generic(&self, m: &dyn 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: &dyn 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_reflect<'a>(&self, m: &'a dyn 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(_: &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( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> u32, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { get, _set: set_panic, })), }, ) } pub fn make_singular_i32_accessor( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> i32, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { get, _set: set_panic, })), }, ) } pub fn make_singular_u64_accessor( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> u64, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { get, _set: set_panic, })), }, ) } pub fn make_singular_i64_accessor( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> i64, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { get, _set: set_panic, })), }, ) } pub fn make_singular_f32_accessor( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> f32, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { get, _set: set_panic, })), }, ) } pub fn make_singular_f64_accessor( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> f64, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { get, _set: set_panic, })), }, ) } pub fn make_singular_bool_accessor( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> bool, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Copy(Box::new(GetSetCopyFnsImpl { get, _set: set_panic, })), }, ) } pub fn make_singular_enum_accessor( name: &'static str, has: fn(&M) -> bool, get: fn(&M) -> E, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Enum(Box::new(GetSingularEnumImpl { get })), }, ) } pub fn make_singular_string_accessor( name: &'static str, has: fn(&M) -> bool, get: for<'a> fn(&'a M) -> &'a str, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::String(get, set_panic), }, ) } pub fn make_singular_bytes_accessor( name: &'static str, has: fn(&M) -> bool, get: for<'a> fn(&'a M) -> &'a [u8], ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Bytes(get, set_panic), }, ) } pub fn make_singular_message_accessor( name: &'static str, has: fn(&M) -> bool, get: for<'a> fn(&'a M) -> &'a F, ) -> FieldAccessor { FieldAccessor::new_v1( name, FieldAccessorFunctions::SingularHasGetSet { has, get_set: SingularGetSet::Message(Box::new(GetSingularMessageImpl { get })), }, ) } // repeated impl FieldAccessor2 for MessageGetMut> where M: Message + 'static, V: ProtobufValue + 'static, { fn get_field<'a>(&self, m: &'a M) -> &'a dyn ReflectRepeated { (self.get_field)(m) as &dyn ReflectRepeated } fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut dyn ReflectRepeated { (self.mut_field)(m) as &mut dyn ReflectRepeated } } pub fn make_vec_accessor( name: &'static str, get_vec: for<'a> fn(&'a M) -> &'a Vec, mut_vec: for<'a> fn(&'a mut M) -> &'a mut Vec, ) -> FieldAccessor where M: Message + 'static, V: ProtobufType + 'static, { FieldAccessor::new_v1( name, FieldAccessorFunctions::Repeated(Box::new(MessageGetMut::> { get_field: get_vec, mut_field: mut_vec, })), ) } impl FieldAccessor2 for MessageGetMut> where M: Message + 'static, V: ProtobufValue + 'static, { fn get_field<'a>(&self, m: &'a M) -> &'a dyn ReflectRepeated { (self.get_field)(m) as &dyn ReflectRepeated } fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut dyn ReflectRepeated { (self.mut_field)(m) as &mut dyn ReflectRepeated } } pub fn make_repeated_field_accessor( name: &'static str, get_vec: for<'a> fn(&'a M) -> &'a RepeatedField, mut_vec: for<'a> fn(&'a mut M) -> &'a mut RepeatedField, ) -> FieldAccessor where M: Message + 'static, V: ProtobufType + 'static, { FieldAccessor::new_v1( name, FieldAccessorFunctions::Repeated(Box::new(MessageGetMut::> { get_field: get_vec, mut_field: mut_vec, })), ) } impl FieldAccessor2 for MessageGetMut> where M: Message + 'static, V: ProtobufValue + Clone + 'static, { fn get_field<'a>(&self, m: &'a M) -> &'a dyn ReflectOptional { (self.get_field)(m) as &dyn ReflectOptional } fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut dyn ReflectOptional { (self.mut_field)(m) as &mut dyn ReflectOptional } } pub fn make_option_accessor( name: &'static str, get_field: for<'a> fn(&'a M) -> &'a Option, mut_field: for<'a> fn(&'a mut M) -> &'a mut Option, ) -> FieldAccessor where M: Message + 'static, V: ProtobufType + 'static, { FieldAccessor::new_v1( name, FieldAccessorFunctions::Optional(Box::new(MessageGetMut::> { get_field, mut_field, })), ) } impl FieldAccessor2 for MessageGetMut> where M: Message + 'static, V: ProtobufValue + Clone + 'static, { fn get_field<'a>(&self, m: &'a M) -> &'a dyn ReflectOptional { (self.get_field)(m) as &dyn ReflectOptional } fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut dyn ReflectOptional { (self.mut_field)(m) as &mut dyn ReflectOptional } } pub fn make_singular_field_accessor( name: &'static str, get_field: for<'a> fn(&'a M) -> &'a SingularField, mut_field: for<'a> fn(&'a mut M) -> &'a mut SingularField, ) -> FieldAccessor where M: Message + 'static, V: ProtobufType + 'static, { FieldAccessor::new_v1( name, FieldAccessorFunctions::Optional(Box::new(MessageGetMut::> { get_field, mut_field, })), ) } impl FieldAccessor2 for MessageGetMut> where M: Message + 'static, V: ProtobufValue + Clone + 'static, { fn get_field<'a>(&self, m: &'a M) -> &'a dyn ReflectOptional { (self.get_field)(m) as &dyn ReflectOptional } fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut dyn ReflectOptional { (self.mut_field)(m) as &mut dyn ReflectOptional } } pub fn make_singular_ptr_field_accessor( name: &'static str, get_field: for<'a> fn(&'a M) -> &'a SingularPtrField, mut_field: for<'a> fn(&'a mut M) -> &'a mut SingularPtrField, ) -> FieldAccessor where M: Message + 'static, V: ProtobufType + 'static, { FieldAccessor::new_v1( name, FieldAccessorFunctions::Optional(Box::new( MessageGetMut::> { get_field, mut_field, }, )), ) } impl FieldAccessor2 for MessageGetMut where M: Message + 'static, V: ProtobufValue + Clone + 'static, { fn get_field<'a>(&self, m: &'a M) -> &'a dyn ProtobufValue { (self.get_field)(m) as &dyn ProtobufValue } fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut dyn ProtobufValue { (self.mut_field)(m) as &mut dyn ProtobufValue } } pub fn make_simple_field_accessor( 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, ) -> FieldAccessor where M: Message + 'static, V: ProtobufType + 'static, { FieldAccessor::new_v1( name, FieldAccessorFunctions::Simple(Box::new(MessageGetMut:: { get_field, mut_field, })), ) } impl FieldAccessor2 for MessageGetMut> where M: Message + 'static, K: ProtobufValue + 'static, V: ProtobufValue + 'static, K: Hash + Eq, { fn get_field<'a>(&self, m: &'a M) -> &'a dyn ReflectMap { (self.get_field)(m) as &dyn ReflectMap } fn mut_field<'a>(&self, m: &'a mut M) -> &'a mut dyn ReflectMap { (self.mut_field)(m) as &mut dyn ReflectMap } } pub fn make_map_accessor( name: &'static str, get_field: for<'a> fn(&'a M) -> &'a HashMap, mut_field: for<'a> fn(&'a mut M) -> &'a mut HashMap, ) -> FieldAccessor where M: Message + 'static, K: ProtobufType + 'static, V: ProtobufType + 'static, ::Value: Hash + Eq, { FieldAccessor::new_v1( name, FieldAccessorFunctions::Map(Box::new(MessageGetMut::> { get_field, mut_field, })), ) }