1mod api;
2mod build;
3mod error;
4mod global;
5mod tag;
6#[cfg(test)]
7mod tests;
8pub(crate) mod types;
9
10pub use self::error::DescriptorError;
11use self::types::{DescriptorProto, EnumDescriptorProto};
12
13use std::{
14 collections::{BTreeMap, HashMap, HashSet},
15 convert::TryInto,
16 fmt,
17 ops::Range,
18 sync::Arc,
19};
20
21use crate::{descriptor::types::FileDescriptorProto, Value};
22
23pub(crate) const MAP_ENTRY_KEY_NUMBER: u32 = 1;
24pub(crate) const MAP_ENTRY_VALUE_NUMBER: u32 = 2;
25
26pub(crate) const RESERVED_MESSAGE_FIELD_NUMBERS: Range<i32> = 19_000..20_000;
27pub(crate) const VALID_MESSAGE_FIELD_NUMBERS: Range<i32> = 1..536_870_912;
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
31pub enum Cardinality {
32 Optional,
34 Required,
36 Repeated,
38}
39
40#[derive(Copy, Clone, PartialEq, Eq, Hash)]
42pub enum Syntax {
43 Proto2,
45 Proto3,
47}
48
49#[derive(Clone, PartialEq, Eq)]
51pub enum Kind {
52 Double,
54 Float,
56 Int32,
58 Int64,
60 Uint32,
62 Uint64,
64 Sint32,
66 Sint64,
68 Fixed32,
70 Fixed64,
72 Sfixed32,
74 Sfixed64,
76 Bool,
78 String,
80 Bytes,
82 Message(MessageDescriptor),
84 Enum(EnumDescriptor),
86}
87
88#[derive(Copy, Clone)]
89enum KindIndex {
90 Double,
91 Float,
92 Int32,
93 Int64,
94 Uint32,
95 Uint64,
96 Sint32,
97 Sint64,
98 Fixed32,
99 Fixed64,
100 Sfixed32,
101 Sfixed64,
102 Bool,
103 String,
104 Bytes,
105 Message(MessageIndex),
106 Enum(EnumIndex),
107 Group(MessageIndex),
108}
109
110type DescriptorIndex = u32;
111type FileIndex = DescriptorIndex;
112type ServiceIndex = DescriptorIndex;
113type MethodIndex = DescriptorIndex;
114type MessageIndex = DescriptorIndex;
115type FieldIndex = DescriptorIndex;
116type OneofIndex = DescriptorIndex;
117type ExtensionIndex = DescriptorIndex;
118type EnumIndex = DescriptorIndex;
119type EnumValueIndex = DescriptorIndex;
120
121#[derive(Clone, Default)]
131pub struct DescriptorPool {
132 inner: Arc<DescriptorPoolInner>,
133}
134
135#[derive(Clone, Default)]
136struct DescriptorPoolInner {
137 names: HashMap<Box<str>, Definition>,
138 file_names: HashMap<Box<str>, FileIndex>,
139 files: Vec<FileDescriptorInner>,
140 messages: Vec<MessageDescriptorInner>,
141 enums: Vec<EnumDescriptorInner>,
142 extensions: Vec<ExtensionDescriptorInner>,
143 services: Vec<ServiceDescriptorInner>,
144}
145
146#[derive(Clone)]
147struct Identity {
148 file: FileIndex,
149 path: Box<[i32]>,
150 full_name: Box<str>,
151 name_index: usize,
152}
153
154#[derive(Clone, Debug)]
155struct Definition {
156 file: FileIndex,
157 path: Box<[i32]>,
158 kind: DefinitionKind,
159}
160
161#[derive(Copy, Clone, Debug)]
162enum DefinitionKind {
163 Package,
164 Message(MessageIndex),
165 Field(MessageIndex),
166 Oneof(MessageIndex),
167 Service(ServiceIndex),
168 Method(ServiceIndex),
169 Enum(EnumIndex),
170 EnumValue(EnumIndex),
171 Extension(ExtensionIndex),
172}
173
174#[derive(Clone, PartialEq, Eq)]
176pub struct FileDescriptor {
177 pool: DescriptorPool,
178 index: FileIndex,
179}
180
181#[derive(Clone)]
182struct FileDescriptorInner {
183 syntax: Syntax,
184 raw: FileDescriptorProto,
185 prost: prost_types::FileDescriptorProto,
186 dependencies: Vec<FileIndex>,
187 transitive_dependencies: HashSet<FileIndex>,
188}
189
190#[derive(Clone, PartialEq, Eq)]
192pub struct MessageDescriptor {
193 pool: DescriptorPool,
194 index: MessageIndex,
195}
196
197#[derive(Clone)]
198struct MessageDescriptorInner {
199 id: Identity,
200 parent: Option<MessageIndex>,
201 extensions: Vec<ExtensionIndex>,
202 fields: Vec<FieldDescriptorInner>,
203 field_numbers: BTreeMap<u32, FieldIndex>,
204 field_names: HashMap<Box<str>, FieldIndex>,
205 field_json_names: HashMap<Box<str>, FieldIndex>,
206 oneofs: Vec<OneofDescriptorInner>,
207}
208
209#[derive(Clone, PartialEq, Eq)]
211pub struct OneofDescriptor {
212 message: MessageDescriptor,
213 index: OneofIndex,
214}
215
216#[derive(Clone)]
217struct OneofDescriptorInner {
218 id: Identity,
219 fields: Vec<FieldIndex>,
220}
221
222#[derive(Clone, PartialEq, Eq)]
224pub struct FieldDescriptor {
225 message: MessageDescriptor,
226 index: FieldIndex,
227}
228
229#[derive(Clone)]
230struct FieldDescriptorInner {
231 id: Identity,
232 number: u32,
233 json_name: Box<str>,
234 kind: KindIndex,
235 oneof: Option<OneofIndex>,
236 is_packed: bool,
237 supports_presence: bool,
238 cardinality: Cardinality,
239 default: Option<Value>,
240}
241
242#[derive(Clone, PartialEq, Eq)]
244pub struct ExtensionDescriptor {
245 pool: DescriptorPool,
246 index: ExtensionIndex,
247}
248
249#[derive(Clone)]
250pub struct ExtensionDescriptorInner {
251 id: Identity,
252 parent: Option<MessageIndex>,
253 number: u32,
254 json_name: Box<str>,
255 extendee: MessageIndex,
256 kind: KindIndex,
257 is_packed: bool,
258 cardinality: Cardinality,
259 default: Option<Value>,
260}
261
262#[derive(Clone, PartialEq, Eq)]
264pub struct EnumDescriptor {
265 pool: DescriptorPool,
266 index: EnumIndex,
267}
268
269#[derive(Clone)]
270struct EnumDescriptorInner {
271 id: Identity,
272 parent: Option<MessageIndex>,
273 values: Vec<EnumValueDescriptorInner>,
274 value_numbers: Vec<(i32, EnumValueIndex)>,
275 value_names: HashMap<Box<str>, EnumValueIndex>,
276 allow_alias: bool,
277}
278
279#[derive(Clone, PartialEq, Eq)]
281pub struct EnumValueDescriptor {
282 parent: EnumDescriptor,
283 index: EnumValueIndex,
284}
285
286#[derive(Clone)]
287struct EnumValueDescriptorInner {
288 id: Identity,
289 number: i32,
290}
291
292#[derive(Clone, PartialEq, Eq)]
294pub struct ServiceDescriptor {
295 pool: DescriptorPool,
296 index: ServiceIndex,
297}
298
299#[derive(Clone)]
300struct ServiceDescriptorInner {
301 id: Identity,
302 methods: Vec<MethodDescriptorInner>,
303}
304
305#[derive(Clone, PartialEq, Eq)]
307pub struct MethodDescriptor {
308 service: ServiceDescriptor,
309 index: MethodIndex,
310}
311
312#[derive(Clone)]
313struct MethodDescriptorInner {
314 id: Identity,
315 input: MessageIndex,
316 output: MessageIndex,
317}
318
319impl Identity {
320 fn new(file: FileIndex, path: &[i32], full_name: &str, name: &str) -> Identity {
321 debug_assert!(full_name.ends_with(name));
322 let name_index = full_name.len() - name.len();
323 debug_assert!(name_index == 0 || full_name.as_bytes()[name_index - 1] == b'.');
324 Identity {
325 file,
326 path: path.into(),
327 full_name: full_name.into(),
328 name_index,
329 }
330 }
331
332 fn full_name(&self) -> &str {
333 &self.full_name
334 }
335
336 fn name(&self) -> &str {
337 &self.full_name[self.name_index..]
338 }
339}
340
341impl KindIndex {
342 fn is_packable(&self) -> bool {
343 match self {
344 KindIndex::Double
345 | KindIndex::Float
346 | KindIndex::Int32
347 | KindIndex::Int64
348 | KindIndex::Uint32
349 | KindIndex::Uint64
350 | KindIndex::Sint32
351 | KindIndex::Sint64
352 | KindIndex::Fixed32
353 | KindIndex::Fixed64
354 | KindIndex::Sfixed32
355 | KindIndex::Sfixed64
356 | KindIndex::Bool
357 | KindIndex::Enum(_) => true,
358 KindIndex::String | KindIndex::Bytes | KindIndex::Message(_) | KindIndex::Group(_) => {
359 false
360 }
361 }
362 }
363
364 fn is_message(&self) -> bool {
365 matches!(self, KindIndex::Message(_) | KindIndex::Group(_))
366 }
367}
368
369impl fmt::Debug for KindIndex {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 match self {
372 KindIndex::Double => write!(f, "double"),
373 KindIndex::Float => write!(f, "float"),
374 KindIndex::Int32 => write!(f, "int32"),
375 KindIndex::Int64 => write!(f, "int64"),
376 KindIndex::Uint32 => write!(f, "uint32"),
377 KindIndex::Uint64 => write!(f, "uint64"),
378 KindIndex::Sint32 => write!(f, "sint32"),
379 KindIndex::Sint64 => write!(f, "sint64"),
380 KindIndex::Fixed32 => write!(f, "fixed32"),
381 KindIndex::Fixed64 => write!(f, "fixed64"),
382 KindIndex::Sfixed32 => write!(f, "sfixed32"),
383 KindIndex::Sfixed64 => write!(f, "sfixed64"),
384 KindIndex::Bool => write!(f, "bool"),
385 KindIndex::String => write!(f, "string"),
386 KindIndex::Bytes => write!(f, "bytes"),
387 KindIndex::Message(_) | KindIndex::Group(_) => write!(f, "message"),
388 KindIndex::Enum(_) => write!(f, "enum"),
389 }
390 }
391}
392
393impl DefinitionKind {
394 fn is_parent(&self) -> bool {
395 match self {
396 DefinitionKind::Package => true,
397 DefinitionKind::Message(_) => true,
398 DefinitionKind::Field(_) => false,
399 DefinitionKind::Oneof(_) => false,
400 DefinitionKind::Service(_) => true,
401 DefinitionKind::Method(_) => false,
402 DefinitionKind::Enum(_) => true,
403 DefinitionKind::EnumValue(_) => false,
404 DefinitionKind::Extension(_) => false,
405 }
406 }
407}
408
409impl DescriptorPoolInner {
410 fn get_by_name(&self, name: &str) -> Option<&Definition> {
411 let name = name.strip_prefix('.').unwrap_or(name);
412 self.names.get(name)
413 }
414}
415
416fn to_index(i: usize) -> DescriptorIndex {
417 i.try_into().expect("index too large")
418}
419
420fn find_message_proto<'a>(file: &'a FileDescriptorProto, path: &[i32]) -> &'a DescriptorProto {
421 debug_assert_ne!(path.len(), 0);
422 debug_assert_eq!(path.len() % 2, 0);
423
424 let mut message: Option<&'a types::DescriptorProto> = None;
425 for part in path.chunks(2) {
426 match part[0] {
427 tag::file::MESSAGE_TYPE => message = Some(&file.message_type[part[1] as usize]),
428 tag::message::NESTED_TYPE => {
429 message = Some(&message.unwrap().nested_type[part[1] as usize])
430 }
431 _ => panic!("invalid message path"),
432 }
433 }
434
435 message.unwrap()
436}
437
438fn find_enum_proto<'a>(file: &'a FileDescriptorProto, path: &[i32]) -> &'a EnumDescriptorProto {
439 debug_assert_ne!(path.len(), 0);
440 debug_assert_eq!(path.len() % 2, 0);
441 if path.len() == 2 {
442 debug_assert_eq!(path[0], tag::file::ENUM_TYPE);
443 &file.enum_type[path[1] as usize]
444 } else {
445 let message = find_message_proto(file, &path[..path.len() - 2]);
446 debug_assert_eq!(path[path.len() - 2], tag::message::ENUM_TYPE);
447 &message.enum_type[path[path.len() - 1] as usize]
448 }
449}
450
451#[test]
452fn assert_descriptor_send_sync() {
453 fn test_send_sync<T: Send + Sync>() {}
454
455 test_send_sync::<DescriptorPool>();
456 test_send_sync::<Kind>();
457 test_send_sync::<DescriptorError>();
458}