1use std::borrow::Cow;
2use std::collections::BTreeMap;
3use std::path::PathBuf;
4
5use super::*;
6
7#[derive(Default)]
8pub(crate) struct ContextBuilder
9{
10 pub(crate) packages: Vec<PackageBuilder>,
11}
12
13#[derive(Default, Debug, PartialEq)]
14pub(crate) struct PackageBuilder
15{
16 pub(crate) path: PathBuf,
17 pub(crate) name: Option<String>,
18 pub(crate) imported_types: Vec<String>,
19 pub(crate) types: Vec<ProtobufItemBuilder>,
20}
21
22#[derive(Debug, PartialEq)]
23pub(crate) enum ProtobufItemBuilder
24{
25 Type(ProtobufTypeBuilder),
26 Service(ServiceBuilder),
27}
28
29#[derive(Debug, PartialEq)]
30pub(crate) enum ProtobufTypeBuilder
31{
32 Message(MessageBuilder),
33 Enum(EnumBuilder),
34}
35
36#[derive(Default, Debug, PartialEq, Clone)]
37pub(crate) struct MessageBuilder
38{
39 pub(crate) name: String,
40 pub(crate) fields: Vec<FieldBuilder>,
41 pub(crate) oneofs: Vec<OneofBuilder>,
42 pub(crate) inner_types: Vec<InnerTypeBuilder>,
43 pub(crate) options: Vec<ProtoOption>,
44}
45
46#[derive(Debug, PartialEq, Clone)]
47pub(crate) enum InnerTypeBuilder
48{
49 Message(MessageBuilder),
50 Enum(EnumBuilder),
51}
52
53#[derive(Default, Debug, PartialEq, Clone)]
54pub(crate) struct EnumBuilder
55{
56 pub(crate) name: String,
57 pub(crate) fields: Vec<EnumField>,
58 pub(crate) options: Vec<ProtoOption>,
59}
60
61#[derive(Default, Debug, PartialEq)]
62pub(crate) struct ServiceBuilder
63{
64 pub(crate) name: String,
65 pub(crate) rpcs: Vec<RpcBuilder>,
66 pub(crate) options: Vec<ProtoOption>,
67}
68
69#[derive(Debug, PartialEq, Clone)]
70pub(crate) struct FieldBuilder
71{
72 pub(crate) multiplicity: Multiplicity,
73 pub(crate) field_type: FieldTypeBuilder,
74 pub(crate) name: String,
75 pub(crate) number: u64,
76 pub(crate) options: Vec<ProtoOption>,
77}
78
79#[derive(Default, Debug, PartialEq, Clone)]
80pub(crate) struct OneofBuilder
81{
82 pub(crate) name: String,
83 pub(crate) fields: Vec<FieldBuilder>,
84 pub(crate) options: Vec<ProtoOption>,
85}
86
87#[derive(Debug, PartialEq, Clone)]
88pub(crate) enum FieldTypeBuilder
89{
90 Builtin(ValueType),
91 Unknown(String),
92}
93
94#[derive(Default, Debug, PartialEq)]
95pub(crate) struct RpcBuilder
96{
97 pub(crate) name: String,
98 pub(crate) input: RpcArgBuilder,
99 pub(crate) output: RpcArgBuilder,
100 pub(crate) options: Vec<ProtoOption>,
101}
102
103#[derive(Default, Debug, PartialEq)]
104pub(crate) struct RpcArgBuilder
105{
106 pub(crate) stream: bool,
107 pub(crate) message: String,
108}
109
110impl ContextBuilder
111{
112 pub fn build(mut self) -> Result<Context, ParseError>
113 {
114 let mut cache = BuildCache::default();
115 for (i, p) in self.packages.iter().enumerate() {
116 p.populate(&mut cache, &mut vec![i])?;
117 }
118
119 let mut types = vec![];
123 for cache_data in &cache.types {
124 match cache_data.item_type {
125 ItemType::Message | ItemType::Enum => {
126 let ty = self.take_type(&cache_data.idx_path);
127 let mut t = ty.build(cache_data, &cache)?;
128 match &mut t {
129 TypeInfo::Message(m) => assert_eq!(m.self_ref.0 .0, types.len()),
130 TypeInfo::Enum(e) => assert_eq!(e.self_ref.0 .0, types.len()),
131 }
132 types.push(t);
133 }
134 ItemType::Service => unreachable!("Service in type cache"),
135 }
136 }
137
138 let services: Vec<_> = cache
139 .services
140 .iter()
141 .map(|s| self.take_service(&s.idx_path).build(s, &cache))
142 .collect::<Result<_, _>>()?;
143
144 let types_by_name = types
145 .iter()
146 .enumerate()
147 .map(|(idx, t)| (t.full_name().to_string(), idx))
148 .collect();
149 let services_by_name = services
150 .iter()
151 .enumerate()
152 .map(|(idx, t)| (t.full_name.clone(), idx))
153 .collect();
154
155 let mut packages: Vec<Package> = self
156 .packages
157 .into_iter()
158 .enumerate()
159 .map(|(idx, p)| Package {
160 name: p.name,
161 self_ref: PackageRef(InternalRef(idx)),
162 types: Vec::new(),
163 services: Vec::new(),
164 })
165 .collect();
166
167 for s in &services {
168 let p = &mut packages[s.parent.0 .0];
169 p.services.push(s.self_ref.0 .0);
170 }
171
172 for t in &types {
173 let (raw_self_ref, parent) = match t {
174 TypeInfo::Message(m) => (TypeRef::Message(m.self_ref), &m.parent),
175 TypeInfo::Enum(e) => (TypeRef::Enum(e.self_ref), &e.parent),
176 };
177 match parent {
178 TypeParent::Package(p_ref) => {
179 let p = &mut packages[p_ref.0 .0];
180 p.types.push(raw_self_ref);
181 }
182 TypeParent::Message(_) => {
183 }
185 }
186 }
187
188 Ok(Context {
189 packages,
190 types,
191 types_by_name,
192 services,
193 services_by_name,
194 })
195 }
196
197 fn take_type(&mut self, idx: &[usize]) -> ProtobufTypeBuilder
198 {
199 self.packages[idx[0]].take_type(&idx[1..])
200 }
201
202 fn take_service(&mut self, idx: &[usize]) -> ServiceBuilder
203 {
204 self.packages[idx[0]].take_service(&idx[1..])
205 }
206}
207
208impl PackageBuilder
209{
210 fn populate(&self, cache: &mut BuildCache, idx: &mut Vec<usize>) -> Result<(), ParseError>
211 {
212 let mut path = match &self.name {
213 Some(name) => name.split('.').collect(),
214 None => vec![],
215 };
216
217 idx.push(0);
218 for (i, t) in self.types.iter().enumerate() {
219 *idx.last_mut().unwrap() = i;
220
221 match t {
222 ProtobufItemBuilder::Type(ProtobufTypeBuilder::Message(m)) => {
223 m.populate(cache, &mut path, idx)?
224 }
225 ProtobufItemBuilder::Type(ProtobufTypeBuilder::Enum(e)) => {
226 e.populate(cache, &mut path, idx)?
227 }
228 ProtobufItemBuilder::Service(m) => m.populate(cache, &mut path, idx)?,
229 }
230 }
231 idx.pop();
232
233 Ok(())
234 }
235
236 fn take_type(&mut self, idx: &[usize]) -> ProtobufTypeBuilder
237 {
238 match &mut self.types[idx[0]] {
239 ProtobufItemBuilder::Type(t) => match t {
240 ProtobufTypeBuilder::Message(m) => m.take_type(&idx[1..]),
241 ProtobufTypeBuilder::Enum(e) => e.take_type(&idx[1..]),
242 },
243
244 ProtobufItemBuilder::Service(..) => {
246 panic!("Trying to take a service as a type");
247 }
248 }
249 }
250
251 fn take_service(&mut self, idx: &[usize]) -> ServiceBuilder
252 {
253 match &mut self.types[idx[0]] {
254 ProtobufItemBuilder::Service(e) => std::mem::take(e),
255
256 _ => panic!("Trying to take a non-service as a service"),
258 }
259 }
260}
261
262impl ProtobufTypeBuilder
263{
264 fn build(self, self_data: &CacheData, cache: &BuildCache) -> Result<TypeInfo, ParseError>
265 {
266 Ok(match self {
267 ProtobufTypeBuilder::Message(m) => TypeInfo::Message(m.build(self_data, cache)?),
268 ProtobufTypeBuilder::Enum(e) => TypeInfo::Enum(e.build(self_data, cache)?),
269 })
270 }
271}
272
273impl MessageBuilder
274{
275 fn populate<'a>(
279 &'a self,
280 cache: &mut BuildCache,
281 path: &mut Vec<&'a str>,
282 idx: &mut Vec<usize>,
283 ) -> Result<(), ParseError>
284 {
285 path.push(&self.name);
286 let full_name = path.join(".");
287 let cache_idx = cache.types.len();
288 if cache
289 .items
290 .insert(full_name.clone(), (ItemType::Message, cache_idx))
291 .is_some()
292 || cache
293 .items_by_idx
294 .insert(idx.clone(), (ItemType::Message, cache_idx))
295 .is_some()
296 {
297 return Err(ParseError::DuplicateType {
298 name: path.join("."),
299 });
300 }
301
302 cache.types.push(CacheData {
305 item_type: ItemType::Message,
306 full_name,
307 idx_path: idx.clone(),
308 final_idx: cache_idx,
309 });
310
311 idx.push(0);
312 for (i, t) in self.inner_types.iter().enumerate() {
313 *idx.last_mut().unwrap() = i;
314 t.populate(cache, path, idx)?;
315 }
316
317 idx.pop();
318 path.pop();
319
320 Ok(())
321 }
322
323 fn take_type(&mut self, idx: &[usize]) -> ProtobufTypeBuilder
324 {
325 if idx.is_empty() {
326 ProtobufTypeBuilder::Message(MessageBuilder {
327 name: self.name.clone(),
328 fields: std::mem::take(&mut self.fields),
329 oneofs: std::mem::take(&mut self.oneofs),
330 options: std::mem::take(&mut self.options),
331 inner_types: self
332 .inner_types
333 .iter()
334 .map(InnerTypeBuilder::clone_name)
335 .collect(),
336 })
337 } else {
338 self.inner_types[idx[0]].take_type(&idx[1..])
339 }
340 }
341
342 fn build(self, self_data: &CacheData, cache: &BuildCache) -> Result<MessageInfo, ParseError>
343 {
344 let inner_types: Vec<_> = self
345 .inner_types
346 .iter()
347 .map(|inner| match inner {
348 InnerTypeBuilder::Message(m) => TypeRef::Message(MessageRef::from(
349 cache
350 .type_by_full_name(&format!("{}.{}", self_data.full_name, m.name))
351 .expect("Existing type wasn't added to the cache"),
352 )),
353 InnerTypeBuilder::Enum(e) => TypeRef::Enum(EnumRef::from(
354 cache
355 .type_by_full_name(&format!("{}.{}", self_data.full_name, e.name))
356 .expect("Existing type wasn't added to the cache"),
357 )),
358 })
359 .collect();
360
361 let mut fields: Vec<_> = self
362 .fields
363 .into_iter()
364 .map(|field| field.build(self_data, cache, None))
365 .collect::<Result<_, _>>()?;
366
367 let mut oneofs: Vec<_> = self
368 .oneofs
369 .into_iter()
370 .enumerate()
371 .map(|(idx, oneof)| {
372 let oneof_ref = OneofRef(InternalRef(idx));
373 let mut new_fields: Vec<_> = oneof
374 .fields
375 .into_iter()
376 .map(|field| field.build(self_data, cache, Some(oneof_ref)))
377 .collect::<Result<_, _>>()?;
378 fields.append(&mut new_fields);
379 Ok(Oneof {
380 name: oneof.name,
381 self_ref: oneof_ref,
382 options: oneof.options,
383 fields: vec![],
384 })
385 })
386 .collect::<Result<_, _>>()?;
387
388 let fields: BTreeMap<u64, MessageField> =
390 fields.into_iter().map(|f| (f.number, f)).collect();
391 for (idx, oneof) in oneofs.iter_mut().enumerate() {
392 oneof.fields = fields
393 .iter()
394 .filter_map(
395 |(num, f)| match f.oneof == Some(OneofRef(InternalRef(idx))) {
396 true => Some(*num),
397 false => None,
398 },
399 )
400 .collect();
401 }
402
403 let parent = cache.parent_type(&self_data.idx_path);
404 let fields_by_name = fields
405 .iter()
406 .map(|(i, f)| (f.name.to_string(), *i))
407 .collect();
408
409 Ok(MessageInfo {
410 name: self.name,
411 full_name: self_data.full_name.clone(),
412 parent,
413 self_ref: MessageRef(InternalRef(self_data.final_idx)),
414 inner_types,
415 oneofs,
416 fields,
417 fields_by_name,
418 })
419 }
420}
421
422impl InnerTypeBuilder
423{
424 fn clone_name(&self) -> InnerTypeBuilder
425 {
426 match self {
427 InnerTypeBuilder::Message(m) => InnerTypeBuilder::Message(MessageBuilder {
428 name: m.name.clone(),
429 ..Default::default()
430 }),
431 InnerTypeBuilder::Enum(e) => InnerTypeBuilder::Enum(EnumBuilder {
432 name: e.name.clone(),
433 ..Default::default()
434 }),
435 }
436 }
437}
438
439impl FieldBuilder
440{
441 fn build(
442 self,
443 self_data: &CacheData,
444 cache: &BuildCache,
445 oneof: Option<OneofRef>,
446 ) -> Result<MessageField, ParseError>
447 {
448 let multiplicity = resolve_multiplicity(self.multiplicity, &self.field_type, &self.options);
449 Ok(MessageField {
450 name: self.name,
451 number: self.number,
452 multiplicity,
453 field_type: self.field_type.build(self_data, cache)?,
454 oneof,
455 options: self.options,
456 })
457 }
458}
459
460fn resolve_multiplicity(
461 proto_multiplicity: Multiplicity,
462 field_type: &FieldTypeBuilder,
463 options: &[ProtoOption],
464) -> Multiplicity
465{
466 if proto_multiplicity != Multiplicity::Repeated {
468 return proto_multiplicity;
469 }
470
471 match field_type {
473 FieldTypeBuilder::Unknown(..) => return Multiplicity::Repeated,
475 FieldTypeBuilder::Builtin(vt) if vt.wire_type() == 2 => return Multiplicity::Repeated,
476
477 _ => {}
479 }
480
481 if let Some(opt) = options.iter().find(|o| o.name == "packed") {
483 return match opt.value {
484 Constant::Bool(true) => Multiplicity::RepeatedPacked,
485 _ => Multiplicity::Repeated,
486 };
487 }
488
489 Multiplicity::RepeatedPacked
490}
491
492impl FieldTypeBuilder
493{
494 fn build(self, self_data: &CacheData, cache: &BuildCache) -> Result<ValueType, ParseError>
495 {
496 Ok(match self {
497 FieldTypeBuilder::Builtin(vt) => vt,
498 FieldTypeBuilder::Unknown(s) => {
499 let t = cache
500 .resolve_type(&s, &self_data.full_name)
501 .ok_or_else(|| ParseError::TypeNotFound {
502 name: s,
503 context: self_data.full_name.to_string(),
504 })?;
505
506 match t.item_type {
507 ItemType::Message => ValueType::Message(MessageRef(InternalRef(t.final_idx))),
508 ItemType::Enum => ValueType::Enum(EnumRef(InternalRef(t.final_idx))),
509 _ => unreachable!("Service as field type"),
510 }
511 }
512 })
513 }
514}
515
516impl InnerTypeBuilder
517{
518 fn populate<'a>(
519 &'a self,
520 cache: &mut BuildCache,
521 path: &mut Vec<&'a str>,
522 idx: &mut Vec<usize>,
523 ) -> Result<(), ParseError>
524 {
525 match self {
526 InnerTypeBuilder::Message(m) => m.populate(cache, path, idx),
527 InnerTypeBuilder::Enum(e) => e.populate(cache, path, idx),
528 }
529 }
530
531 fn take_type(&mut self, idx: &[usize]) -> ProtobufTypeBuilder
532 {
533 match self {
534 InnerTypeBuilder::Message(m) => m.take_type(idx),
535 InnerTypeBuilder::Enum(e) => e.take_type(idx),
536 }
537 }
538}
539
540impl EnumBuilder
541{
542 fn populate<'a>(
546 &'a self,
547 cache: &mut BuildCache,
548 path: &mut Vec<&'a str>,
549 idx: &mut Vec<usize>,
550 ) -> Result<(), ParseError>
551 {
552 path.push(&self.name);
553 let full_name = path.join(".");
554 let cache_idx = cache.types.len();
555 if cache
556 .items
557 .insert(full_name.clone(), (ItemType::Enum, cache_idx))
558 .is_some()
559 {
560 return Err(ParseError::DuplicateType {
561 name: path.join("."),
562 });
563 }
564 path.pop();
565
566 cache.types.push(CacheData {
567 item_type: ItemType::Enum,
568 full_name,
569 idx_path: idx.clone(),
570 final_idx: cache_idx,
571 });
572
573 Ok(())
574 }
575
576 fn build(self, self_data: &CacheData, cache: &BuildCache) -> Result<EnumInfo, ParseError>
577 {
578 let fields_by_name = self
579 .fields
580 .iter()
581 .map(|f| (f.name.clone(), f.value))
582 .collect();
583 let fields_by_value = self.fields.into_iter().map(|f| (f.value, f)).collect();
584
585 let parent = cache.parent_type(&self_data.idx_path);
586
587 Ok(EnumInfo {
588 name: self.name,
589 full_name: self_data.full_name.to_string(),
590 self_ref: EnumRef(InternalRef(self_data.final_idx)),
591 parent,
592 fields_by_value,
593 fields_by_name,
594 })
595 }
596
597 fn take_type(&mut self, idx: &[usize]) -> ProtobufTypeBuilder
598 {
599 if !idx.is_empty() {
600 panic!("Trying to take an inner type from an enum");
601 }
602
603 ProtobufTypeBuilder::Enum(std::mem::take(self))
604 }
605}
606
607impl ServiceBuilder
608{
609 fn populate<'a>(
613 &'a self,
614 cache: &mut BuildCache,
615 path: &mut Vec<&'a str>,
616 idx: &mut Vec<usize>,
617 ) -> Result<(), ParseError>
618 {
619 path.push(&self.name);
620 let full_name = path.join(".");
621 let cache_idx = cache.services.len();
622 if let Some(..) = cache
623 .items
624 .insert(full_name.clone(), (ItemType::Service, cache_idx))
625 {
626 return Err(ParseError::DuplicateType {
627 name: path.join("."),
628 });
629 }
630 path.pop();
631
632 cache.services.push(CacheData {
633 item_type: ItemType::Service,
634 full_name,
635 idx_path: idx.clone(),
636 final_idx: cache_idx,
637 });
638
639 Ok(())
640 }
641
642 fn build(self, self_data: &CacheData, cache: &BuildCache) -> Result<Service, ParseError>
643 {
644 let rpcs: Vec<_> = self
645 .rpcs
646 .into_iter()
647 .map(|rpc| rpc.build(self_data, cache))
648 .collect::<Result<_, _>>()?;
649 let rpcs_by_name = rpcs
650 .iter()
651 .enumerate()
652 .map(|(idx, rpc)| (rpc.name.to_string(), idx))
653 .collect();
654
655 let parent = match cache.parent_type(&self_data.idx_path) {
656 TypeParent::Package(p) => p,
657 _ => panic!("Service inside a message"),
658 };
659
660 Ok(Service {
661 name: self.name,
662 self_ref: ServiceRef(InternalRef(self_data.final_idx)),
663 parent,
664 full_name: self_data.full_name.clone(),
665 rpcs,
666 rpcs_by_name,
667 options: vec![],
668 })
669 }
670}
671
672impl RpcBuilder
673{
674 fn build(self, self_data: &CacheData, cache: &BuildCache) -> Result<Rpc, ParseError>
675 {
676 Ok(Rpc {
677 name: self.name,
678 input: self.input.build(self_data, cache)?,
679 output: self.output.build(self_data, cache)?,
680 options: vec![],
681 })
682 }
683}
684
685impl RpcArgBuilder
686{
687 fn build(self, rpc_data: &CacheData, cache: &BuildCache) -> Result<RpcArg, ParseError>
688 {
689 let self_data = match cache.resolve_type(&self.message, &rpc_data.full_name) {
691 Some(data) => data,
692 None => {
693 return Err(ParseError::TypeNotFound {
694 name: self.message,
695 context: rpc_data.full_name.clone(),
696 })
697 }
698 };
699
700 if self_data.item_type != ItemType::Message {
702 return Err(ParseError::InvalidTypeKind {
703 type_name: self.message,
704 context: "service input/output",
705 expected: ItemType::Message,
706 actual: self_data.item_type,
707 });
708 }
709
710 let message = MessageRef(InternalRef(self_data.final_idx));
711 Ok(RpcArg {
712 stream: self.stream,
713 message,
714 })
715 }
716}
717
718impl MessageRef
719{
720 fn from(data: &CacheData) -> Self
721 {
722 if data.item_type != ItemType::Message {
723 panic!("Trying to create MessageRef for {:?}", data.item_type);
724 }
725 MessageRef(InternalRef(data.final_idx))
726 }
727}
728
729impl EnumRef
730{
731 fn from(data: &CacheData) -> Self
732 {
733 if data.item_type != ItemType::Enum {
734 panic!("Trying to create EnumRef for {:?}", data.item_type);
735 }
736 EnumRef(InternalRef(data.final_idx))
737 }
738}
739
740#[derive(Default)]
741struct BuildCache
742{
743 items: BTreeMap<String, (ItemType, usize)>,
744 items_by_idx: BTreeMap<Vec<usize>, (ItemType, usize)>,
745 types: Vec<CacheData>,
746 services: Vec<CacheData>,
747}
748
749struct CacheData
750{
751 item_type: ItemType,
752 idx_path: Vec<usize>,
753 final_idx: usize,
754 full_name: String,
755}
756
757impl BuildCache
758{
759 fn resolve_type(&self, relative_name: &str, mut current_path: &str) -> Option<&CacheData>
760 {
761 if let Some(absolute) = relative_name.strip_prefix('.') {
762 return self.type_by_full_name(absolute);
763 }
764
765 loop {
766 let lookup: Cow<str> = match current_path.is_empty() {
767 true => relative_name.into(),
768 false => format!("{}.{}", current_path, relative_name).into(),
769 };
770
771 if let Some(t) = self.type_by_full_name(&lookup) {
772 return Some(t);
773 }
774
775 if current_path.is_empty() {
776 return None;
777 }
778
779 match current_path.rfind('.') {
780 Some(i) => {
781 let (start, _) = current_path.split_at(i);
782 current_path = start;
783 }
784 None => {
785 current_path = "";
786 }
787 }
788 }
789 }
790
791 fn parent_type(&self, current: &[usize]) -> TypeParent
792 {
793 match current.len() {
794 0 | 1 => panic!("Empty type ID path"),
795 2 => TypeParent::Package(PackageRef(InternalRef(current[0]))),
796 _ => self
797 .type_by_idx_path(¤t[..current.len() - 1])
798 .map(|data| TypeParent::Message(MessageRef(InternalRef(data.final_idx))))
799 .unwrap_or_else(|| panic!("Parent type not found: {:?}", current)),
800 }
801 }
802
803 fn type_by_full_name(&self, full_name: &str) -> Option<&CacheData>
804 {
805 self.items
806 .get(full_name)
807 .and_then(|(ty, i)| self.type_by_idx(*ty, *i))
808 }
809
810 fn type_by_idx_path(&self, idx: &[usize]) -> Option<&CacheData>
811 {
812 self.items_by_idx
813 .get(idx)
814 .and_then(|(ty, i)| self.type_by_idx(*ty, *i))
815 }
816
817 fn type_by_idx(&self, item_type: ItemType, idx: usize) -> Option<&CacheData>
818 {
819 match item_type {
820 ItemType::Message => self.types.get(idx),
821 ItemType::Enum => self.types.get(idx),
822 ItemType::Service => self.services.get(idx),
823 }
824 }
825}