1 use protobuf_support::json_name::json_name;
2 
3 use crate::descriptor::field_descriptor_proto::Type;
4 use crate::descriptor::FieldDescriptorProto;
5 use crate::descriptor::FileDescriptorProto;
6 use crate::owning_ref::OwningRef;
7 use crate::reflect::error::ReflectError;
8 use crate::reflect::field::protobuf_field_type::ProtobufFieldType;
9 use crate::reflect::file::building::FileDescriptorBuilding;
10 use crate::reflect::protobuf_type_box::ProtobufType;
11 use crate::reflect::EnumDescriptor;
12 use crate::reflect::EnumValueDescriptor;
13 use crate::reflect::FieldDescriptor;
14 use crate::reflect::FileDescriptor;
15 use crate::reflect::MessageDescriptor;
16 use crate::reflect::ReflectValueBox;
17 use crate::reflect::ReflectValueRef;
18 use crate::reflect::RuntimeType;
19 
20 #[derive(Debug)]
21 pub(crate) enum ForwardProtobufTypeBox {
22     ProtobufTypeBox(ProtobufType),
23     CurrentFileEnum(usize),
24     CurrentFileMessage(usize),
25 }
26 
27 impl ForwardProtobufTypeBox {
message(message: MessageDescriptor) -> ForwardProtobufTypeBox28     pub(crate) fn message(message: MessageDescriptor) -> ForwardProtobufTypeBox {
29         ForwardProtobufTypeBox::ProtobufTypeBox(ProtobufType::message(message))
30     }
31 
enumeration(enumeration: EnumDescriptor) -> ForwardProtobufTypeBox32     pub(crate) fn enumeration(enumeration: EnumDescriptor) -> ForwardProtobufTypeBox {
33         ForwardProtobufTypeBox::ProtobufTypeBox(ProtobufType::enumeration(enumeration))
34     }
35 
from_proto_type(t: Type) -> ForwardProtobufTypeBox36     pub(crate) fn from_proto_type(t: Type) -> ForwardProtobufTypeBox {
37         ForwardProtobufTypeBox::ProtobufTypeBox(ProtobufType::from_proto_type(t))
38     }
39 
resolve(&self, file: &FileDescriptor) -> ProtobufType40     pub(crate) fn resolve(&self, file: &FileDescriptor) -> ProtobufType {
41         match self {
42             ForwardProtobufTypeBox::ProtobufTypeBox(t) => t.clone(),
43             ForwardProtobufTypeBox::CurrentFileMessage(m) => {
44                 ProtobufType::message(MessageDescriptor::new(file.clone(), *m))
45             }
46             ForwardProtobufTypeBox::CurrentFileEnum(m) => {
47                 ProtobufType::enumeration(EnumDescriptor::new(file.clone(), *m))
48             }
49         }
50     }
51 
resolve_message(&self, file: &FileDescriptor) -> MessageDescriptor52     pub(crate) fn resolve_message(&self, file: &FileDescriptor) -> MessageDescriptor {
53         match self.resolve(file).runtime() {
54             RuntimeType::Message(m) => m.clone(),
55             _ => panic!("not message"),
56         }
57     }
58 }
59 
60 #[derive(Debug)]
61 pub(crate) enum ForwardProtobufFieldType {
62     Singular(ForwardProtobufTypeBox),
63     Repeated(ForwardProtobufTypeBox),
64     Map(ForwardProtobufTypeBox, ForwardProtobufTypeBox),
65 }
66 
67 impl ForwardProtobufFieldType {
resolve(&self, file: &FileDescriptor) -> ProtobufFieldType68     pub(crate) fn resolve(&self, file: &FileDescriptor) -> ProtobufFieldType {
69         match self {
70             ForwardProtobufFieldType::Singular(t) => ProtobufFieldType::Singular(t.resolve(file)),
71             ForwardProtobufFieldType::Repeated(t) => ProtobufFieldType::Repeated(t.resolve(file)),
72             ForwardProtobufFieldType::Map(k, v) => {
73                 ProtobufFieldType::Map(k.resolve(file), v.resolve(file))
74             }
75         }
76     }
77 }
78 
79 #[derive(Debug)]
80 pub(crate) enum FieldDefaultValue {
81     ReflectValueBox(ReflectValueBox),
82     Enum(usize),
83 }
84 
85 #[derive(Debug)]
86 pub(crate) enum FieldKind {
87     MessageField(
88         /// Message index.
89         usize,
90     ),
91     Extension(
92         /// Message index or `None` for file.
93         Option<usize>,
94         ForwardProtobufTypeBox,
95     ),
96 }
97 
98 #[derive(Debug)]
99 pub(crate) struct FieldIndex {
100     pub(crate) proto: OwningRef<FileDescriptorProto, FieldDescriptorProto>,
101     pub(crate) kind: FieldKind,
102     pub(crate) json_name: String,
103     pub(crate) field_type: ForwardProtobufFieldType,
104     pub(crate) default_value: Option<FieldDefaultValue>,
105 }
106 
107 impl FieldIndex {
enum_default_value( field: &FieldDescriptorProto, building: &FileDescriptorBuilding, ) -> crate::Result<FieldDefaultValue>108     fn enum_default_value(
109         field: &FieldDescriptorProto,
110         building: &FileDescriptorBuilding,
111     ) -> crate::Result<FieldDefaultValue> {
112         let en = building.find_enum(field.type_name());
113         let (n, _) = match en
114             .value
115             .iter()
116             .enumerate()
117             .find(|(_n, v)| v.name() == field.default_value())
118         {
119             Some(v) => v,
120             None => Err(ReflectError::CouldNotParseDefaultValueForField(
121                 field.name().to_owned(),
122             ))?,
123         };
124         Ok(FieldDefaultValue::Enum(n))
125     }
126 
parse_default_value( field: &FieldDescriptorProto, building: &FileDescriptorBuilding, ) -> crate::Result<FieldDefaultValue>127     fn parse_default_value(
128         field: &FieldDescriptorProto,
129         building: &FileDescriptorBuilding,
130     ) -> crate::Result<FieldDefaultValue> {
131         Ok(FieldDefaultValue::ReflectValueBox(match field.type_() {
132             Type::TYPE_GROUP | Type::TYPE_MESSAGE => {
133                 return Err(ReflectError::CouldNotParseDefaultValueForField(
134                     field.name().to_owned(),
135                 )
136                 .into());
137             }
138             Type::TYPE_ENUM => {
139                 return Self::enum_default_value(field, building);
140             }
141             t => RuntimeType::from_proto_type(t)
142                 .parse_proto_default_value(field.default_value())
143                 .map_err(|()| {
144                     ReflectError::CouldNotParseDefaultValueForField(field.name().to_owned())
145                 })?,
146         }))
147     }
148 
index( containing_message: Option<usize>, field: OwningRef<FileDescriptorProto, FieldDescriptorProto>, building: &FileDescriptorBuilding, ) -> crate::Result<FieldIndex>149     pub(crate) fn index(
150         containing_message: Option<usize>,
151         field: OwningRef<FileDescriptorProto, FieldDescriptorProto>,
152         building: &FileDescriptorBuilding,
153     ) -> crate::Result<FieldIndex> {
154         let default_value = if field.has_default_value() {
155             Some(Self::parse_default_value(&field, building)?)
156         } else {
157             None
158         };
159 
160         let json_name = if !field.json_name().is_empty() {
161             field.json_name().to_owned()
162         } else {
163             json_name(field.name())
164         };
165 
166         let extendee = if field.has_extendee() {
167             Some(building.resolve_message(field.extendee())?)
168         } else {
169             None
170         };
171 
172         let kind = match (containing_message, extendee) {
173             (Some(m), None) => FieldKind::MessageField(m),
174             (m, Some(extendee)) => FieldKind::Extension(m, extendee),
175             (None, None) => panic!("field must be in a message or an extension"),
176         };
177 
178         let field_type = building.resolve_field_type(&field)?;
179         Ok(FieldIndex {
180             proto: field,
181             kind,
182             default_value,
183             json_name,
184             field_type,
185         })
186     }
187 
default_value<'a>(&'a self, field: &FieldDescriptor) -> ReflectValueRef<'a>188     pub(crate) fn default_value<'a>(&'a self, field: &FieldDescriptor) -> ReflectValueRef<'a> {
189         match &self.default_value {
190             Some(FieldDefaultValue::ReflectValueBox(v)) => v.as_value_ref(),
191             Some(FieldDefaultValue::Enum(v)) => match field.singular_runtime_type() {
192                 RuntimeType::Enum(e) => {
193                     let ev = EnumValueDescriptor::new(e.clone(), *v);
194                     ReflectValueRef::from(ev)
195                 }
196                 t => panic!("wrong type {:?} for default value enum", t),
197             },
198             None => field.singular_runtime_type().default_value_ref(),
199         }
200     }
201 }
202