protobuf/reflect/field/
index.rs
1use protobuf_support::json_name::json_name;
2
3use crate::descriptor::field_descriptor_proto::Type;
4use crate::descriptor::FieldDescriptorProto;
5use crate::descriptor::FileDescriptorProto;
6use crate::owning_ref::OwningRef;
7use crate::reflect::error::ReflectError;
8use crate::reflect::field::protobuf_field_type::ProtobufFieldType;
9use crate::reflect::file::building::FileDescriptorBuilding;
10use crate::reflect::protobuf_type_box::ProtobufType;
11use crate::reflect::EnumDescriptor;
12use crate::reflect::EnumValueDescriptor;
13use crate::reflect::FieldDescriptor;
14use crate::reflect::FileDescriptor;
15use crate::reflect::MessageDescriptor;
16use crate::reflect::ReflectValueBox;
17use crate::reflect::ReflectValueRef;
18use crate::reflect::RuntimeType;
19
20#[derive(Debug)]
21pub(crate) enum ForwardProtobufTypeBox {
22 ProtobufTypeBox(ProtobufType),
23 CurrentFileEnum(usize),
24 CurrentFileMessage(usize),
25}
26
27impl ForwardProtobufTypeBox {
28 pub(crate) fn message(message: MessageDescriptor) -> ForwardProtobufTypeBox {
29 ForwardProtobufTypeBox::ProtobufTypeBox(ProtobufType::message(message))
30 }
31
32 pub(crate) fn enumeration(enumeration: EnumDescriptor) -> ForwardProtobufTypeBox {
33 ForwardProtobufTypeBox::ProtobufTypeBox(ProtobufType::enumeration(enumeration))
34 }
35
36 pub(crate) fn from_proto_type(t: Type) -> ForwardProtobufTypeBox {
37 ForwardProtobufTypeBox::ProtobufTypeBox(ProtobufType::from_proto_type(t))
38 }
39
40 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
52 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)]
61pub(crate) enum ForwardProtobufFieldType {
62 Singular(ForwardProtobufTypeBox),
63 Repeated(ForwardProtobufTypeBox),
64 Map(ForwardProtobufTypeBox, ForwardProtobufTypeBox),
65}
66
67impl ForwardProtobufFieldType {
68 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)]
80pub(crate) enum FieldDefaultValue {
81 ReflectValueBox(ReflectValueBox),
82 Enum(usize),
83}
84
85#[derive(Debug)]
86pub(crate) enum FieldKind {
87 MessageField(
88 usize,
90 ),
91 Extension(
92 Option<usize>,
94 ForwardProtobufTypeBox,
95 ),
96}
97
98#[derive(Debug)]
99pub(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
107impl FieldIndex {
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
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
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
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}