1use errors::Result;
4use serde::Serialize;
5use std::slice;
6use std::vec;
7use translator;
8use {Diagnostics, Flavor, FlavorField, Loc, RpCode, RpDecl, RpReg, Translate, Translator};
9
10pub const DEFAULT_TAG: &str = "type";
12
13#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
14#[serde(tag = "type", rename_all = "snake_case")]
15pub enum RpSubTypeStrategy {
16 Tagged { tag: String },
18 Untagged,
22}
23
24impl Default for RpSubTypeStrategy {
25 fn default() -> Self {
26 RpSubTypeStrategy::Tagged {
27 tag: DEFAULT_TAG.to_string(),
28 }
29 }
30}
31
32decl_body!(pub struct RpInterfaceBody<F> {
33 pub fields: Vec<Loc<F::Field>>,
34 pub codes: Vec<Loc<RpCode>>,
35 pub sub_types: Vec<Loc<RpSubType<F>>>,
36 pub sub_type_strategy: RpSubTypeStrategy,
37});
38
39pub struct Fields<'a, F: 'static>
41where
42 F: Flavor,
43{
44 iter: slice::Iter<'a, Loc<F::Field>>,
45}
46
47impl<'a, F: 'static> Iterator for Fields<'a, F>
48where
49 F: Flavor,
50{
51 type Item = &'a Loc<F::Field>;
52
53 fn next(&mut self) -> Option<Self::Item> {
54 self.iter.next()
55 }
56}
57
58pub struct DiscriminatingFields<'a, F: 'static>
63where
64 F: Flavor,
65{
66 iter: vec::IntoIter<&'a Loc<F::Field>>,
67}
68
69impl<'a, F: 'static> Iterator for DiscriminatingFields<'a, F>
70where
71 F: Flavor,
72{
73 type Item = &'a Loc<F::Field>;
74
75 fn next(&mut self) -> Option<Self::Item> {
76 self.iter.next()
77 }
78}
79
80impl<F: 'static> RpInterfaceBody<F>
81where
82 F: Flavor,
83{
84 pub fn fields(&self) -> Fields<F> {
85 Fields {
86 iter: self.fields.iter(),
87 }
88 }
89}
90
91impl<F: 'static, T> Translate<T> for RpInterfaceBody<F>
92where
93 F: Flavor,
94 T: Translator<Source = F>,
95{
96 type Source = F;
97 type Out = RpInterfaceBody<T::Target>;
98
99 fn translate(
101 self,
102 diag: &mut Diagnostics,
103 translator: &T,
104 ) -> Result<RpInterfaceBody<T::Target>> {
105 translator.visit(diag, &self.name)?;
106
107 let name = translator.translate_local_name(diag, RpReg::Interface, self.name)?;
108
109 Ok(RpInterfaceBody {
110 name: name,
111 ident: self.ident,
112 comment: self.comment,
113 decls: self.decls.translate(diag, translator)?,
114 fields: translator::Fields(self.fields).translate(diag, translator)?,
115 codes: self.codes,
116 sub_types: self.sub_types.translate(diag, translator)?,
117 sub_type_strategy: self.sub_type_strategy,
118 })
119 }
120}
121
122#[derive(Debug, Clone, Serialize)]
123#[serde(bound = "F: Serialize, F::Field: Serialize, F::Endpoint: Serialize, F::Package: \
124 Serialize, F::Name: Serialize, F::EnumType: Serialize")]
125pub struct RpSubType<F: 'static>
126where
127 F: Flavor,
128{
129 pub name: F::Name,
130 pub ident: String,
131 pub comment: Vec<String>,
132 pub decls: Vec<RpDecl<F>>,
134 pub fields: Vec<Loc<F::Field>>,
135 pub codes: Vec<Loc<RpCode>>,
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub sub_type_name: Option<Loc<String>>,
138}
139
140impl<F: 'static> RpSubType<F>
141where
142 F: Flavor,
143{
144 pub fn name(&self) -> &str {
145 self.sub_type_name
146 .as_ref()
147 .map(|t| t.as_str())
148 .unwrap_or(&self.ident)
149 }
150
151 pub fn discriminating_fields(&self) -> DiscriminatingFields<F> {
153 let fields = self.fields
154 .iter()
155 .filter(|f| f.is_discriminating())
156 .collect::<Vec<_>>();
157
158 DiscriminatingFields {
159 iter: fields.into_iter(),
160 }
161 }
162}
163
164impl<F: 'static, T> Translate<T> for RpSubType<F>
165where
166 F: Flavor,
167 T: Translator<Source = F>,
168{
169 type Source = F;
170 type Out = RpSubType<T::Target>;
171
172 fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpSubType<T::Target>> {
174 translator.visit(diag, &self.name)?;
175
176 let name = translator.translate_local_name(diag, RpReg::SubType, self.name)?;
177
178 Ok(RpSubType {
179 name: name,
180 ident: self.ident,
181 comment: self.comment,
182 decls: self.decls.translate(diag, translator)?,
183 fields: translator::Fields(self.fields).translate(diag, translator)?,
184 codes: self.codes,
185 sub_type_name: self.sub_type_name,
186 })
187 }
188}