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