reproto_core/
rp_decl.rs

1//! Model for declarations
2
3use errors::Result;
4use serde::Serialize;
5use std::fmt;
6use std::vec;
7use {Diagnostics, Flavor, Loc, RpEnumBody, RpInterfaceBody, RpReg, RpServiceBody, RpSubType,
8     RpTupleBody, RpTypeBody, RpVariantRef, Span, Translate, Translator};
9
10/// Iterator over declarations.
11pub struct Decls<'a, F: 'static>
12where
13    F: Flavor,
14{
15    iter: vec::IntoIter<&'a RpDecl<F>>,
16}
17
18impl<'a, F: 'static> Iterator for Decls<'a, F>
19where
20    F: Flavor,
21{
22    type Item = &'a RpDecl<F>;
23
24    fn next(&mut self) -> Option<Self::Item> {
25        self.iter.next()
26    }
27}
28
29#[derive(Debug, Clone)]
30pub enum RpNamed<'a, F: 'static>
31where
32    F: Flavor,
33{
34    Type(&'a Loc<RpTypeBody<F>>),
35    Tuple(&'a Loc<RpTupleBody<F>>),
36    Interface(&'a Loc<RpInterfaceBody<F>>),
37    SubType(&'a Loc<RpSubType<F>>),
38    Enum(&'a Loc<RpEnumBody<F>>),
39    EnumVariant(RpVariantRef<'a, F>),
40    Service(&'a Loc<RpServiceBody<F>>),
41}
42
43impl<'a, F: 'static> RpNamed<'a, F>
44where
45    F: Flavor,
46{
47    /// Get the name of the named element.
48    pub fn name(&self) -> &F::Name {
49        use self::RpNamed::*;
50
51        match *self {
52            Type(ref body) => &body.name,
53            Tuple(ref tuple) => &tuple.name,
54            Interface(ref interface) => &interface.name,
55            SubType(ref sub_type) => &sub_type.name,
56            Enum(ref en) => &en.name,
57            EnumVariant(ref variant) => variant.name,
58            Service(ref service) => &service.name,
59        }
60    }
61
62    /// Get the position of the named element.
63    pub fn span(&self) -> Span {
64        use self::RpNamed::*;
65
66        match *self {
67            Type(ref body) => Loc::span(body),
68            Tuple(ref tuple) => Loc::span(tuple),
69            Interface(ref interface) => Loc::span(interface),
70            SubType(ref sub_type) => Loc::span(sub_type),
71            Enum(ref en) => Loc::span(en),
72            EnumVariant(ref variant) => variant.span,
73            Service(ref service) => Loc::span(service),
74        }
75    }
76}
77
78#[derive(Debug, Clone, Serialize)]
79#[serde(bound = "F: Serialize, F::Field: Serialize, F::Endpoint: Serialize, F::Package: \
80                 Serialize, F::Name: Serialize, F::EnumType: Serialize")]
81#[serde(tag = "type", rename_all = "snake_case")]
82pub enum RpDecl<F: 'static>
83where
84    F: Flavor,
85{
86    Type(Loc<RpTypeBody<F>>),
87    Tuple(Loc<RpTupleBody<F>>),
88    Interface(Loc<RpInterfaceBody<F>>),
89    Enum(Loc<RpEnumBody<F>>),
90    Service(Loc<RpServiceBody<F>>),
91}
92
93impl<F: 'static> RpDecl<F>
94where
95    F: Flavor,
96{
97    pub fn decls(&self) -> Decls<F> {
98        use self::RpDecl::*;
99
100        let iter = match *self {
101            Type(ref body) => body.decls.iter().collect::<Vec<_>>().into_iter(),
102            Interface(ref body) => {
103                let mut decls = body.decls.iter().collect::<Vec<_>>();
104                decls.extend(body.sub_types.iter().flat_map(|s| s.decls.iter()));
105                decls.into_iter()
106            }
107            Enum(ref body) => body.decls.iter().collect::<Vec<_>>().into_iter(),
108            Tuple(ref body) => body.decls.iter().collect::<Vec<_>>().into_iter(),
109            Service(ref body) => body.decls.iter().collect::<Vec<_>>().into_iter(),
110        };
111
112        Decls { iter: iter }
113    }
114
115    pub fn ident(&self) -> &str {
116        use self::RpDecl::*;
117
118        match *self {
119            Type(ref body) => body.ident.as_str(),
120            Interface(ref body) => body.ident.as_str(),
121            Enum(ref body) => body.ident.as_str(),
122            Tuple(ref body) => body.ident.as_str(),
123            Service(ref body) => body.ident.as_str(),
124        }
125    }
126
127    pub fn name(&self) -> &F::Name {
128        use self::RpDecl::*;
129
130        match *self {
131            Type(ref body) => &body.name,
132            Interface(ref body) => &body.name,
133            Enum(ref body) => &body.name,
134            Tuple(ref body) => &body.name,
135            Service(ref body) => &body.name,
136        }
137    }
138
139    pub fn comment(&self) -> &[String] {
140        use self::RpDecl::*;
141
142        match *self {
143            Type(ref body) => &body.comment,
144            Interface(ref body) => &body.comment,
145            Enum(ref body) => &body.comment,
146            Tuple(ref body) => &body.comment,
147            Service(ref body) => &body.comment,
148        }
149    }
150
151    /// Convert a declaration into its registered types.
152    pub fn to_reg(&self) -> Vec<(&F::Name, Span, RpReg)> {
153        use self::RpDecl::*;
154
155        let mut out = Vec::new();
156
157        match *self {
158            Type(ref ty) => {
159                out.push((&ty.name, Loc::span(ty), RpReg::Type));
160            }
161            Interface(ref interface) => {
162                for sub_type in interface.sub_types.iter() {
163                    out.push((&sub_type.name, Loc::span(sub_type), RpReg::SubType));
164                }
165
166                out.push((&interface.name, Loc::span(interface), RpReg::Interface));
167            }
168            Enum(ref en) => {
169                for variant in &en.variants {
170                    out.push((variant.name, variant.span, RpReg::EnumVariant));
171                }
172
173                out.push((&en.name, Loc::span(en), RpReg::Enum));
174            }
175            Tuple(ref tuple) => {
176                out.push((&tuple.name, Loc::span(tuple), RpReg::Tuple));
177            }
178            Service(ref service) => {
179                out.push((&service.name, Loc::span(service), RpReg::Service));
180            }
181        }
182
183        out.extend(self.decls().flat_map(|d| d.to_reg()));
184        out
185    }
186
187    /// Convert a declaration into its names.
188    pub fn to_named(&self) -> Vec<RpNamed<F>> {
189        use self::RpDecl::*;
190
191        let mut out = Vec::new();
192
193        match *self {
194            Type(ref ty) => {
195                out.push(RpNamed::Type(ty));
196            }
197            Interface(ref interface) => {
198                for sub_type in interface.sub_types.iter() {
199                    out.push(RpNamed::SubType(sub_type));
200                }
201
202                out.push(RpNamed::Interface(interface));
203            }
204            Enum(ref en) => {
205                for variant in &en.variants {
206                    out.push(RpNamed::EnumVariant(variant));
207                }
208
209                out.push(RpNamed::Enum(en));
210            }
211            Tuple(ref tuple) => {
212                out.push(RpNamed::Tuple(tuple));
213            }
214            Service(ref service) => {
215                out.push(RpNamed::Service(service));
216            }
217        }
218
219        out.extend(self.decls().flat_map(|d| d.to_named()));
220        out
221    }
222
223    /// Get stringy kind of the declaration.
224    pub fn kind(&self) -> &str {
225        use self::RpDecl::*;
226
227        match *self {
228            Type(_) => "type",
229            Interface(_) => "interface",
230            Enum(_) => "enum",
231            Tuple(_) => "tuple",
232            Service(_) => "service",
233        }
234    }
235
236    /// Get the position of the declaration.
237    pub fn span(&self) -> Span {
238        use self::RpDecl::*;
239
240        match *self {
241            Type(ref body) => Loc::span(body),
242            Interface(ref body) => Loc::span(body),
243            Enum(ref body) => Loc::span(body),
244            Tuple(ref body) => Loc::span(body),
245            Service(ref body) => Loc::span(body),
246        }
247    }
248}
249
250impl<F: 'static, T> Translate<T> for RpDecl<F>
251where
252    F: Flavor,
253    T: Translator<Source = F>,
254{
255    type Source = F;
256    type Out = RpDecl<T::Target>;
257
258    /// Translate into different flavor.
259    fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpDecl<T::Target>> {
260        use self::RpDecl::*;
261
262        let out = match self {
263            Type(body) => Type(body.translate(diag, translator)?),
264            Tuple(body) => Tuple(body.translate(diag, translator)?),
265            Interface(body) => Interface(body.translate(diag, translator)?),
266            Enum(body) => Enum(body.translate(diag, translator)?),
267            Service(body) => Service(body.translate(diag, translator)?),
268        };
269
270        Ok(out)
271    }
272}
273
274impl<F: 'static> fmt::Display for RpDecl<F>
275where
276    F: Flavor,
277{
278    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279        use self::RpDecl::*;
280
281        match *self {
282            Type(ref body) => write!(f, "type {}", body.name),
283            Interface(ref body) => write!(f, "interface {}", body.name),
284            Enum(ref body) => write!(f, "enum {}", body.name),
285            Tuple(ref body) => write!(f, "tuple {}", body.name),
286            Service(ref body) => write!(f, "service {}", body.name),
287        }
288    }
289}
290
291impl<'a, F: 'static> From<&'a RpDecl<F>> for Span
292where
293    F: Flavor,
294{
295    fn from(value: &'a RpDecl<F>) -> Self {
296        value.span().clone()
297    }
298}