| use std::fmt; |
| |
| use crate::descriptor::field_descriptor_proto; |
| use crate::descriptor::FieldDescriptorProto; |
| use crate::message_dyn::MessageDyn; |
| use crate::reflect::acc::v2::map::MapFieldAccessorHolder; |
| use crate::reflect::acc::v2::repeated::RepeatedFieldAccessorHolder; |
| use crate::reflect::acc::v2::singular::SingularFieldAccessorHolder; |
| use crate::reflect::acc::v2::AccessorV2; |
| use crate::reflect::acc::GeneratedFieldAccessor; |
| use crate::reflect::dynamic::DynamicMessage; |
| use crate::reflect::field::dynamic::DynamicFieldDescriptorRef; |
| use crate::reflect::field::index::FieldIndex; |
| use crate::reflect::field::index::FieldKind; |
| use crate::reflect::field::protobuf_field_type::ProtobufFieldType; |
| use crate::reflect::field::runtime_field_type::RuntimeFieldType; |
| use crate::reflect::map::ReflectMapMut; |
| use crate::reflect::map::ReflectMapRef; |
| use crate::reflect::message::message_ref::MessageRef; |
| use crate::reflect::message::MessageDescriptorImplRef; |
| use crate::reflect::oneof::OneofDescriptor; |
| use crate::reflect::protobuf_type_box::ProtobufType; |
| use crate::reflect::reflect_eq::ReflectEq; |
| use crate::reflect::reflect_eq::ReflectEqMode; |
| use crate::reflect::repeated::ReflectRepeatedMut; |
| use crate::reflect::repeated::ReflectRepeatedRef; |
| use crate::reflect::value::value_ref::ReflectValueMut; |
| use crate::reflect::FileDescriptor; |
| use crate::reflect::MessageDescriptor; |
| use crate::reflect::ReflectOptionalRef; |
| use crate::reflect::ReflectValueBox; |
| use crate::reflect::ReflectValueRef; |
| use crate::reflect::RuntimeType; |
| |
| pub(crate) mod dynamic; |
| pub(crate) mod index; |
| pub(crate) mod protobuf_field_type; |
| pub(crate) mod runtime_field_type; |
| |
| /// Reference to a value stored in a field, optional, repeated or map. |
| #[derive(PartialEq)] |
| pub enum ReflectFieldRef<'a> { |
| /// Singular field, optional or required in proto3 and just plain field in proto3 |
| Optional(ReflectOptionalRef<'a>), |
| /// Repeated field |
| Repeated(ReflectRepeatedRef<'a>), |
| /// Map field |
| Map(ReflectMapRef<'a>), |
| } |
| |
| impl<'a> ReflectFieldRef<'a> { |
| pub(crate) fn default_for_field(field: &FieldDescriptor) -> ReflectFieldRef<'a> { |
| match field.runtime_field_type() { |
| RuntimeFieldType::Singular(elem) => { |
| ReflectFieldRef::Optional(ReflectOptionalRef::none(elem)) |
| } |
| RuntimeFieldType::Repeated(elem) => { |
| ReflectFieldRef::Repeated(ReflectRepeatedRef::new_empty(elem)) |
| } |
| RuntimeFieldType::Map(k, v) => ReflectFieldRef::Map(ReflectMapRef::new_empty(k, v)), |
| } |
| } |
| } |
| |
| impl<'a> ReflectEq for ReflectFieldRef<'a> { |
| fn reflect_eq(&self, that: &Self, mode: &ReflectEqMode) -> bool { |
| match (self, that) { |
| (ReflectFieldRef::Optional(a), ReflectFieldRef::Optional(b)) => { |
| match (a.value(), b.value()) { |
| (Some(av), Some(bv)) => av.reflect_eq(&bv, mode), |
| (None, None) => true, |
| _ => false, |
| } |
| } |
| (ReflectFieldRef::Repeated(a), ReflectFieldRef::Repeated(b)) => a.reflect_eq(b, mode), |
| (ReflectFieldRef::Map(a), ReflectFieldRef::Map(b)) => a.reflect_eq(b, mode), |
| _ => false, |
| } |
| } |
| } |
| |
| fn _assert_sync<'a>() { |
| fn _assert_send_sync<T: Sync>() {} |
| _assert_send_sync::<ReflectFieldRef<'a>>(); |
| } |
| |
| /// Field descriptor. |
| /// |
| /// Can be used for runtime reflection. |
| #[derive(Eq, PartialEq, Clone)] |
| pub struct FieldDescriptor { |
| pub(crate) file_descriptor: FileDescriptor, |
| pub(crate) index: usize, |
| } |
| |
| impl fmt::Display for FieldDescriptor { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| match &self.index().kind { |
| FieldKind::MessageField(m) => write!( |
| f, |
| "{}.{}", |
| self.file_descriptor.message_by_index(*m), |
| self.name() |
| ), |
| FieldKind::Extension(Some(m), _) => write!( |
| f, |
| "{}.{}", |
| self.file_descriptor.message_by_index(*m), |
| self.name() |
| ), |
| FieldKind::Extension(None, _) => { |
| if self.file_descriptor.proto().package().is_empty() { |
| write!(f, "{}", self.name()) |
| } else { |
| write!( |
| f, |
| "{}.{}", |
| self.file_descriptor.proto().package(), |
| self.name() |
| ) |
| } |
| } |
| } |
| } |
| } |
| |
| impl FieldDescriptor { |
| pub(crate) fn regular(&self) -> (MessageDescriptor, usize) { |
| match self.index().kind { |
| FieldKind::MessageField(_) => { |
| let m = self.containing_message(); |
| ( |
| m.clone(), |
| self.index - m.index().message_index.first_field_index, |
| ) |
| } |
| // TODO: implement and remove. |
| _ => panic!("regular field"), |
| } |
| } |
| |
| pub(crate) fn file_descriptor(&self) -> &FileDescriptor { |
| &self.file_descriptor |
| } |
| |
| /// Get `.proto` description of field |
| pub fn proto(&self) -> &FieldDescriptorProto { |
| &self.index().proto |
| } |
| |
| /// Field name as specified in `.proto` file. |
| pub fn name(&self) -> &str { |
| self.proto().name() |
| } |
| |
| /// Field number as specified in `.proto` file. |
| pub fn number(&self) -> i32 { |
| self.proto().number() |
| } |
| |
| /// Fully qualified name of the field: fully qualified name of the declaring type |
| /// followed by the field name. |
| /// |
| /// Declaring type is a message (for regular field or extensions) or a package |
| /// (for top-level extensions). |
| pub fn full_name(&self) -> String { |
| self.to_string() |
| } |
| |
| /// Oneof descriptor containing this field. Do not skip synthetic oneofs. |
| pub fn containing_oneof_including_synthetic(&self) -> Option<OneofDescriptor> { |
| if let FieldKind::MessageField(..) = self.index().kind { |
| let proto = self.proto(); |
| if proto.has_oneof_index() { |
| Some(OneofDescriptor { |
| file_descriptor: self.file_descriptor().clone(), |
| index: self.containing_message().index().oneofs.start |
| + proto.oneof_index() as usize, |
| }) |
| } else { |
| None |
| } |
| } else { |
| None |
| } |
| } |
| |
| /// Oneof containing this field. |
| /// |
| /// Return `None` if this field is not part of oneof or if it is synthetic oneof. |
| pub fn containing_oneof(&self) -> Option<OneofDescriptor> { |
| self.containing_oneof_including_synthetic() |
| .filter(|o| !o.is_synthetic()) |
| } |
| |
| /// Message which declares this field (for extension, **not** the message we extend). |
| fn _declaring_message(&self) -> Option<MessageDescriptor> { |
| match &self.index().kind { |
| FieldKind::MessageField(m) => Some(self.file_descriptor.message_by_index(*m)), |
| FieldKind::Extension(m, _) => Some(self.file_descriptor.message_by_index(*m.as_ref()?)), |
| } |
| } |
| |
| /// Message which contains this field. |
| /// |
| /// For extension fields, this is the message being extended. |
| pub fn containing_message(&self) -> MessageDescriptor { |
| match &self.index().kind { |
| FieldKind::MessageField(m) => self.file_descriptor().message_by_index(*m), |
| FieldKind::Extension(_, extendee) => extendee.resolve_message(self.file_descriptor()), |
| } |
| } |
| |
| fn index(&self) -> &FieldIndex { |
| &self.file_descriptor.common().fields[self.index] |
| } |
| |
| fn index_with_message_lifetime<'a>(&self, m: &'a dyn MessageDyn) -> &'a FieldIndex { |
| let (descriptor, index) = self.regular(); |
| let file_fields = match self.singular() { |
| SingularFieldAccessorRef::Generated(..) => { |
| &descriptor |
| .file_descriptor |
| .common_for_generated_descriptor() |
| .fields |
| } |
| SingularFieldAccessorRef::Dynamic(..) => { |
| &DynamicMessage::downcast_ref(m) |
| .descriptor() |
| .file_descriptor |
| .common() |
| .fields |
| } |
| }; |
| &descriptor.index().message_index.slice_fields(file_fields)[index] |
| } |
| |
| /// JSON field name. |
| /// |
| /// Can be different from `.proto` field name. |
| /// |
| /// See [JSON mapping][json] for details. |
| /// |
| /// [json]: https://developers.google.com/protocol-buffers/docs/proto3#json |
| pub fn json_name(&self) -> &str { |
| &self.index().json_name |
| } |
| |
| /// If this field is optional or required. |
| pub fn is_singular(&self) -> bool { |
| match self.proto().label() { |
| field_descriptor_proto::Label::LABEL_REQUIRED => true, |
| field_descriptor_proto::Label::LABEL_OPTIONAL => true, |
| field_descriptor_proto::Label::LABEL_REPEATED => false, |
| } |
| } |
| |
| /// Is this field required. |
| pub fn is_required(&self) -> bool { |
| self.proto().label() == field_descriptor_proto::Label::LABEL_REQUIRED |
| } |
| |
| /// If this field repeated or map? |
| pub fn is_repeated_or_map(&self) -> bool { |
| self.proto().label() == field_descriptor_proto::Label::LABEL_REPEATED |
| } |
| |
| /// Is this field repeated, but not map field? |
| pub fn is_repeated(&self) -> bool { |
| match self.runtime_field_type() { |
| RuntimeFieldType::Repeated(..) => true, |
| _ => false, |
| } |
| } |
| |
| fn get_impl(&self) -> FieldDescriptorImplRef { |
| let (descriptor, index) = self.regular(); |
| match descriptor.get_impl() { |
| MessageDescriptorImplRef::Generated(g) => { |
| FieldDescriptorImplRef::Generated(&g.non_map().fields[index].accessor) |
| } |
| MessageDescriptorImplRef::Dynamic => { |
| FieldDescriptorImplRef::Dynamic(DynamicFieldDescriptorRef { field: self }) |
| } |
| } |
| } |
| |
| /// If this field a map field? |
| pub fn is_map(&self) -> bool { |
| match self.runtime_field_type() { |
| RuntimeFieldType::Map(..) => true, |
| _ => false, |
| } |
| } |
| |
| /// Check if field is set in given message. |
| /// |
| /// For repeated field or map field return `true` if |
| /// collection is not empty. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type. |
| pub fn has_field(&self, m: &dyn MessageDyn) -> bool { |
| match self.get_reflect(m) { |
| ReflectFieldRef::Optional(v) => v.value().is_some(), |
| ReflectFieldRef::Repeated(r) => !r.is_empty(), |
| ReflectFieldRef::Map(m) => !m.is_empty(), |
| } |
| } |
| |
| // accessors |
| |
| fn singular(&self) -> SingularFieldAccessorRef { |
| match self.get_impl() { |
| FieldDescriptorImplRef::Generated(GeneratedFieldAccessor::V2( |
| AccessorV2::Singular(ref a), |
| )) => SingularFieldAccessorRef::Generated(a), |
| FieldDescriptorImplRef::Generated(GeneratedFieldAccessor::V2(..)) => { |
| panic!("not a singular field: {}", self) |
| } |
| FieldDescriptorImplRef::Dynamic(d) => SingularFieldAccessorRef::Dynamic(d), |
| } |
| } |
| |
| fn repeated(&self) -> RepeatedFieldAccessorRef { |
| match self.get_impl() { |
| FieldDescriptorImplRef::Generated(GeneratedFieldAccessor::V2( |
| AccessorV2::Repeated(ref a), |
| )) => RepeatedFieldAccessorRef::Generated(a), |
| FieldDescriptorImplRef::Generated(GeneratedFieldAccessor::V2(..)) => { |
| panic!("not a repeated field: {}", self) |
| } |
| FieldDescriptorImplRef::Dynamic(d) => RepeatedFieldAccessorRef::Dynamic(d), |
| } |
| } |
| |
| fn map(&self) -> MapFieldAccessorRef { |
| match self.get_impl() { |
| FieldDescriptorImplRef::Generated(GeneratedFieldAccessor::V2(AccessorV2::Map( |
| ref a, |
| ))) => MapFieldAccessorRef::Generated(a), |
| FieldDescriptorImplRef::Generated(GeneratedFieldAccessor::V2(..)) => { |
| panic!("not a map field: {}", self) |
| } |
| FieldDescriptorImplRef::Dynamic(d) => MapFieldAccessorRef::Dynamic(d), |
| } |
| } |
| |
| /// Obtain type of map key and value. |
| pub(crate) fn map_proto_type(&self) -> (ProtobufType, ProtobufType) { |
| match self.protobuf_field_type() { |
| ProtobufFieldType::Map(k, v) => (k, v), |
| _ => panic!("not a map field: {}", self), |
| } |
| } |
| |
| /// Get message field or default instance if field is unset. |
| /// |
| /// # Panics |
| /// If this field belongs to a different message type or |
| /// field type is not message. |
| pub fn get_message<'a>(&self, m: &'a dyn MessageDyn) -> MessageRef<'a> { |
| match self.get_singular_field_or_default(m) { |
| ReflectValueRef::Message(m) => m, |
| _ => panic!("not message field: {}", self), |
| } |
| } |
| |
| /// Get a mutable reference to a message field. |
| /// Initialize field with default message if unset. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or |
| /// field type is not singular message. |
| pub fn mut_message<'a>(&self, m: &'a mut dyn MessageDyn) -> &'a mut dyn MessageDyn { |
| match self.mut_singular_field_or_default(m) { |
| ReflectValueMut::Message(m) => m, |
| } |
| } |
| |
| /// Default value. |
| /// |
| /// # Panics |
| /// |
| /// If field is not singular. |
| pub fn singular_default_value(&self) -> ReflectValueRef { |
| self.index().default_value(self) |
| } |
| |
| /// Get singular field value. |
| /// |
| /// Return field default value if field is unset. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or fields is not singular. |
| pub fn get_singular_field_or_default<'a>(&self, m: &'a dyn MessageDyn) -> ReflectValueRef<'a> { |
| match self.get_singular(m) { |
| Some(m) => m, |
| None => self.index_with_message_lifetime(m).default_value(self), |
| } |
| } |
| |
| // Not public because it is not implemented for all types |
| fn mut_singular_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a> { |
| match self.singular() { |
| SingularFieldAccessorRef::Generated(g) => g.accessor.mut_field_or_default(m), |
| SingularFieldAccessorRef::Dynamic(..) => { |
| DynamicMessage::downcast_mut(m).mut_singular_field_or_default(self) |
| } |
| } |
| } |
| |
| /// Runtime representation of singular field. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or field is not singular. |
| pub fn singular_runtime_type(&self) -> RuntimeType { |
| match self.runtime_field_type() { |
| RuntimeFieldType::Singular(s) => s, |
| _ => panic!("Not a singular field: {}", self), |
| } |
| } |
| |
| /// Set singular field. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or |
| /// field is not singular or value is of different type. |
| pub fn set_singular_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox) { |
| match self.singular() { |
| SingularFieldAccessorRef::Generated(g) => g.accessor.set_field(m, value), |
| SingularFieldAccessorRef::Dynamic(d) => d.set_field(m, value), |
| } |
| } |
| |
| /// Clear a field. |
| pub fn clear_field(&self, m: &mut dyn MessageDyn) { |
| if self.is_singular() { |
| match self.singular() { |
| SingularFieldAccessorRef::Generated(g) => g.accessor.clear_field(m), |
| SingularFieldAccessorRef::Dynamic(d) => d.clear_field(m), |
| } |
| } else if self.is_repeated() { |
| self.mut_repeated(m).clear(); |
| } else if self.is_map() { |
| self.mut_map(m).clear(); |
| } |
| } |
| |
| /// Dynamic representation of field type with wire type. |
| pub(crate) fn protobuf_field_type(&self) -> ProtobufFieldType { |
| self.index().field_type.resolve(self.file_descriptor()) |
| } |
| |
| /// Dynamic representation of field type. |
| pub fn runtime_field_type(&self) -> RuntimeFieldType { |
| self.protobuf_field_type().runtime() |
| } |
| |
| /// Get field of any type. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type. |
| pub fn get_reflect<'a>(&self, m: &'a dyn MessageDyn) -> ReflectFieldRef<'a> { |
| match self.get_impl() { |
| FieldDescriptorImplRef::Generated(g) => g.get_reflect(m), |
| FieldDescriptorImplRef::Dynamic(d) => d.get_reflect(m), |
| } |
| } |
| |
| /// Get singular field value. |
| /// |
| /// Return `None` if field is unset. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or fields is not singular. |
| pub fn get_singular<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>> { |
| match self.get_reflect(m) { |
| ReflectFieldRef::Optional(o) => o.value(), |
| _ => panic!("not a singular field"), |
| } |
| } |
| |
| // repeated |
| |
| /// Get repeated field. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or field is not repeated. |
| pub fn get_repeated<'a>(&self, m: &'a dyn MessageDyn) -> ReflectRepeatedRef<'a> { |
| match self.get_reflect(m) { |
| ReflectFieldRef::Repeated(r) => r, |
| _ => panic!("not a repeated field"), |
| } |
| } |
| |
| /// Get a mutable reference to `repeated` field. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or field is not `repeated`. |
| pub fn mut_repeated<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectRepeatedMut<'a> { |
| match self.repeated() { |
| RepeatedFieldAccessorRef::Generated(g) => g.accessor.mut_repeated(m), |
| RepeatedFieldAccessorRef::Dynamic(d) => d.mut_repeated(m), |
| } |
| } |
| |
| // map |
| |
| /// Get `map` field. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or field is not `map`. |
| pub fn get_map<'a>(&self, m: &'a dyn MessageDyn) -> ReflectMapRef<'a> { |
| match self.get_reflect(m) { |
| ReflectFieldRef::Map(m) => m, |
| _ => panic!("not a map field"), |
| } |
| } |
| |
| /// Get a mutable reference to `map` field. |
| /// |
| /// # Panics |
| /// |
| /// If this field belongs to a different message type or field is not `map`. |
| pub fn mut_map<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectMapMut<'a> { |
| match self.map() { |
| MapFieldAccessorRef::Generated(g) => g.accessor.mut_reflect(m), |
| MapFieldAccessorRef::Dynamic(d) => d.mut_map(m), |
| } |
| } |
| } |
| |
| enum SingularFieldAccessorRef<'a> { |
| Generated(&'a SingularFieldAccessorHolder), |
| Dynamic(DynamicFieldDescriptorRef<'a>), |
| } |
| |
| enum RepeatedFieldAccessorRef<'a> { |
| Generated(&'a RepeatedFieldAccessorHolder), |
| Dynamic(DynamicFieldDescriptorRef<'a>), |
| } |
| |
| enum MapFieldAccessorRef<'a> { |
| Generated(&'a MapFieldAccessorHolder), |
| Dynamic(DynamicFieldDescriptorRef<'a>), |
| } |
| |
| pub(crate) enum FieldDescriptorImplRef<'a> { |
| Generated(&'static GeneratedFieldAccessor), |
| Dynamic(DynamicFieldDescriptorRef<'a>), |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use std::collections::HashMap; |
| |
| use crate::descriptor::DescriptorProto; |
| use crate::reflect::ReflectValueBox; |
| use crate::well_known_types::struct_::Struct; |
| use crate::well_known_types::struct_::Value; |
| use crate::MessageFull; |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] |
| fn display() { |
| let field = DescriptorProto::descriptor() |
| .field_by_name("enum_type") |
| .unwrap(); |
| assert_eq!( |
| "google.protobuf.DescriptorProto.enum_type", |
| field.to_string() |
| ); |
| } |
| } |