1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::cell::RefCell;
use std::collections::{hash_map::Entry as HashMapEntry, HashMap};
use std::rc::Rc;
use crate::common::FilePosition;
use crate::idl;
use super::errors::ValidationError;
use super::fieldset::Fieldset;
use super::r#enum::Enum;
use super::r#struct::Struct;
use super::r#type::UserDefinedType;
use super::service::Service;
use super::typemap::TypeMap;
#[derive(Default)]
pub struct Namespace {
pub path: Vec<String>,
pub types: HashMap<String, Rc<RefCell<UserDefinedType>>>,
pub services: HashMap<String, Service>,
pub namespaces: HashMap<String, Namespace>,
}
impl Namespace {
pub(crate) fn from_idl(ins: &crate::idl::Namespace) -> Result<Self, ValidationError> {
let mut ns = Self::default();
let mut type_map = TypeMap::new();
ns.idl_convert(ins, &mut type_map)?;
ns.resolve(&type_map)?;
Ok(ns)
}
fn add_type(&mut self, type_: UserDefinedType, type_map: &mut TypeMap) {
let type_rc = Rc::new(RefCell::new(type_));
type_map.insert(&type_rc);
let name = type_rc.borrow().name().to_owned();
self.types.insert(name, type_rc);
}
fn idl_convert(
&mut self,
ins: &crate::idl::Namespace,
type_map: &mut TypeMap,
) -> Result<(), ValidationError> {
let mut names: HashMap<String, FilePosition> = HashMap::new();
for ipart in ins.parts.iter() {
match names.entry(ipart.name().to_owned()) {
HashMapEntry::Occupied(entry) => {
return Err(ValidationError::DuplicateIdentifier {
position: entry.get().clone(),
identifier: ipart.name().to_owned(),
});
}
HashMapEntry::Vacant(entry) => {
entry.insert(ipart.position().clone());
}
}
match ipart {
idl::NamespacePart::Enum(ienum) => {
self.add_type(
UserDefinedType::Enum(Enum::from_idl(&ienum, self)),
type_map,
);
}
idl::NamespacePart::Struct(istruct) => {
self.add_type(
UserDefinedType::Struct(Struct::from_idl(&istruct, self)),
type_map,
);
}
idl::NamespacePart::Fieldset(ifieldset) => {
self.add_type(
UserDefinedType::Fieldset(Fieldset::from_idl(&ifieldset, self)),
type_map,
);
}
idl::NamespacePart::Service(iservice) => {
self.services
.insert(iservice.name.clone(), Service::from_idl(iservice, self));
}
idl::NamespacePart::Namespace(inamespace) => {
let mut child_ns = Self::default();
child_ns.path = self.path.clone();
child_ns.path.push(ipart.name().to_owned());
child_ns.idl_convert(&inamespace, type_map)?;
self.namespaces.insert(inamespace.name.to_owned(), child_ns);
}
};
}
Ok(())
}
fn resolve(&mut self, type_map: &TypeMap) -> Result<(), ValidationError> {
for type_rc in self.types.values() {
type_rc.borrow_mut().resolve(type_map)?;
}
for service in self.services.values_mut() {
service.resolve(type_map)?;
}
for child_ns in self.namespaces.values_mut() {
child_ns.resolve(type_map)?;
}
Ok(())
}
pub fn name(&self) -> &str {
self.path.last().unwrap()
}
}