1 use std::collections::HashMap;
2 use std::sync::Arc;
3 
4 use crate::descriptor::FileDescriptorProto;
5 use crate::owning_ref::OwningRef;
6 use crate::reflect::error::ReflectError;
7 use crate::reflect::file::index::FileDescriptorCommon;
8 use crate::reflect::FileDescriptor;
9 
10 #[derive(Debug)]
11 pub(crate) struct DynamicFileDescriptor {
12     pub(crate) proto: Arc<FileDescriptorProto>,
13     pub(crate) common: FileDescriptorCommon,
14 }
15 
16 impl DynamicFileDescriptor {
new( proto: FileDescriptorProto, dependencies: &[FileDescriptor], ) -> crate::Result<DynamicFileDescriptor>17     pub(crate) fn new(
18         proto: FileDescriptorProto,
19         dependencies: &[FileDescriptor],
20     ) -> crate::Result<DynamicFileDescriptor> {
21         // Remove undeclared dependencies.
22         let dependencies_index: HashMap<_, &FileDescriptor> =
23             dependencies.iter().map(|d| (d.proto().name(), d)).collect();
24 
25         if dependencies_index.len() != dependencies.len() {
26             return Err(ReflectError::NonUniqueDependencies(
27                 dependencies
28                     .iter()
29                     .map(|d| d.proto().name())
30                     .collect::<Vec<_>>()
31                     .join(", "),
32             )
33             .into());
34         }
35 
36         let dependencies: Vec<FileDescriptor> = proto
37             .dependency
38             .iter()
39             .map(|d| {
40                 let dep = dependencies_index.get(d.as_str());
41                 match dep {
42                     Some(dep) => Ok((*dep).clone()),
43                     None => Err(ReflectError::DependencyNotFound(
44                         d.clone(),
45                         proto.name().to_owned(),
46                         dependencies
47                             .iter()
48                             .map(|d| d.proto().name())
49                             .collect::<Vec<_>>()
50                             .join(", "),
51                     )
52                     .into()),
53                 }
54             })
55             .collect::<crate::Result<Vec<_>>>()?;
56 
57         let proto = Arc::new(proto);
58 
59         let common = FileDescriptorCommon::new(OwningRef::new_arc(proto.clone()), dependencies)?;
60 
61         Ok(DynamicFileDescriptor { proto, common })
62     }
63 }
64