1 use std::collections::HashMap;
2 use std::collections::HashSet;
3 use std::mem;
4 
5 use protobuf_support::toposort::toposort;
6 
7 use crate::descriptor::FileDescriptorProto;
8 use crate::reflect::error::ReflectError;
9 use crate::reflect::FileDescriptor;
10 
build_fds( protos: Vec<FileDescriptorProto>, dependencies: &[FileDescriptor], ) -> crate::Result<Vec<FileDescriptor>>11 pub(crate) fn build_fds(
12     protos: Vec<FileDescriptorProto>,
13     dependencies: &[FileDescriptor],
14 ) -> crate::Result<Vec<FileDescriptor>> {
15     let mut index_by_name: HashMap<&str, usize> = HashMap::new();
16     for (i, proto) in protos.iter().enumerate() {
17         let prev = index_by_name.insert(proto.name(), i);
18         if prev.is_some() {
19             return Err(ReflectError::NonUniqueFileDescriptor(proto.name().to_owned()).into());
20         }
21     }
22 
23     let sorted = match toposort(0..protos.len(), |&i| {
24         protos[i]
25             .dependency
26             .iter()
27             .filter_map(|d| index_by_name.get(d.as_str()).copied())
28     }) {
29         Ok(s) => s,
30         Err(_) => return Err(ReflectError::CycleInFileDescriptors.into()),
31     };
32 
33     let mut built_descriptors_by_index = vec![None; protos.len()];
34 
35     let mut protos: Vec<Option<FileDescriptorProto>> = protos.into_iter().map(Some).collect();
36 
37     let mut all_descriptors = dependencies.to_vec();
38     for f in sorted {
39         let proto = mem::take(&mut protos[f]).unwrap();
40         let d = FileDescriptor::new_dynamic(proto, &all_descriptors)?;
41         all_descriptors.push(d.clone());
42         built_descriptors_by_index[f] = Some(d);
43     }
44 
45     Ok(built_descriptors_by_index
46         .into_iter()
47         .map(Option::unwrap)
48         .collect())
49 }
50 
fds_extend_with_public(file_descriptors: Vec<FileDescriptor>) -> Vec<FileDescriptor>51 pub(crate) fn fds_extend_with_public(file_descriptors: Vec<FileDescriptor>) -> Vec<FileDescriptor> {
52     let mut visited = HashSet::new();
53 
54     let mut r = Vec::new();
55     let mut stack = file_descriptors;
56     stack.reverse();
57 
58     while let Some(f) = stack.pop() {
59         if !visited.insert(f.proto().name().to_owned()) {
60             continue;
61         }
62 
63         stack.extend(f.public_deps());
64 
65         r.push(f);
66     }
67     r
68 }
69