protobuf/reflect/file/
dynamic.rs

1use std::collections::HashMap;
2use std::sync::Arc;
3
4use crate::descriptor::FileDescriptorProto;
5use crate::owning_ref::OwningRef;
6use crate::reflect::error::ReflectError;
7use crate::reflect::file::index::FileDescriptorCommon;
8use crate::reflect::FileDescriptor;
9
10#[derive(Debug)]
11pub(crate) struct DynamicFileDescriptor {
12    pub(crate) proto: Arc<FileDescriptorProto>,
13    pub(crate) common: FileDescriptorCommon,
14}
15
16impl 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}