1use errors::Result;
4use serde::Serialize;
5use std::fmt;
6use std::vec;
7use {BigInt, Diagnostics, Flavor, Loc, RpCode, RpNumber, RpReg, RpValue, Span, Translate,
8 Translator};
9
10decl_body!(pub struct RpEnumBody<F> {
11 pub enum_type: F::EnumType,
13 pub variants: RpVariants<F>,
15 pub codes: Vec<Loc<RpCode>>,
17});
18
19impl<F: 'static, T> Translate<T> for RpEnumBody<F>
20where
21 F: Flavor,
22 T: Translator<Source = F>,
23{
24 type Source = F;
25 type Out = RpEnumBody<T::Target>;
26
27 fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpEnumBody<T::Target>> {
29 translator.visit(diag, &self.name)?;
30
31 let name = translator.translate_local_name(diag, RpReg::Enum, self.name)?;
32 let enum_type = translator.translate_enum_type(diag, self.enum_type)?;
33
34 Ok(RpEnumBody {
35 name: name,
36 ident: self.ident,
37 comment: self.comment,
38 decls: self.decls.translate(diag, translator)?,
39 enum_type,
40 variants: self.variants.translate(diag, translator)?,
41 codes: self.codes,
42 })
43 }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum RpVariantValue<'a> {
48 String(&'a str),
49 Number(&'a RpNumber),
50}
51
52impl<'a> From<&'a RpNumber> for RpVariantValue<'a> {
53 fn from(value: &'a RpNumber) -> Self {
54 RpVariantValue::Number(value)
55 }
56}
57
58impl<'a> From<&'a String> for RpVariantValue<'a> {
59 fn from(value: &'a String) -> Self {
60 RpVariantValue::String(value.as_str())
61 }
62}
63
64impl<'a> fmt::Display for RpVariantValue<'a> {
65 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
66 use self::RpVariantValue::*;
67
68 match *self {
69 String(string) => write!(fmt, "{:?}", string),
70 Number(value) => value.fmt(fmt),
71 }
72 }
73}
74
75#[derive(Debug, Clone, Copy)]
79pub struct RpVariantRef<'a, F: 'static>
80where
81 F: Flavor,
82{
83 pub span: Span,
84 pub name: &'a F::Name,
85 pub ident: &'a Loc<String>,
86 pub comment: &'a Vec<String>,
87 pub value: RpVariantValue<'a>,
88}
89
90impl<'a, F: 'static> RpVariantRef<'a, F>
91where
92 F: Flavor,
93{
94 pub fn ident(&self) -> &'a str {
96 self.ident.as_str()
97 }
98}
99
100impl<'a, F: 'static> fmt::Display for RpVariantRef<'a, F>
101where
102 F: Flavor,
103{
104 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
105 write!(fmt, "{} as {}", self.name, self.value)
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
111#[serde(bound = "F::Package: Serialize, F::Name: Serialize, V: Serialize")]
112pub struct RpVariant<F: 'static, V>
113where
114 F: Flavor,
115{
116 pub name: F::Name,
117 pub ident: Loc<String>,
118 pub comment: Vec<String>,
119 pub value: V,
120}
121
122impl<'a, F: 'static, V> RpVariant<F, V>
123where
124 F: Flavor,
125{
126 pub fn ident(&self) -> &str {
128 self.ident.as_str()
129 }
130}
131
132impl<'a, F: 'static, V: 'a> RpVariant<F, V>
133where
134 F: Flavor,
135 RpVariantValue<'a>: From<&'a V>,
136{
137 pub fn value(&'a self) -> RpVariantValue<'a> {
139 RpVariantValue::from(&self.value)
140 }
141}
142
143impl<F: 'static, T, V> Translate<T> for RpVariant<F, V>
144where
145 F: Flavor,
146 T: Translator<Source = F>,
147{
148 type Source = F;
149 type Out = RpVariant<T::Target, V>;
150
151 fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpVariant<T::Target, V>> {
153 translator.visit(diag, &self.name)?;
154
155 let name = translator.translate_local_name(diag, RpReg::EnumVariant, self.name)?;
156
157 Ok(RpVariant {
158 name: name,
159 ident: self.ident,
160 comment: self.comment,
161 value: self.value,
162 })
163 }
164}
165
166#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
168pub enum RpEnumType {
169 String,
170 U32,
171 U64,
172 I32,
173 I64,
174}
175
176impl RpEnumType {
177 pub fn is_assignable_from(&self, value: &RpValue) -> bool {
178 use self::RpEnumType::*;
179
180 match (self, value) {
181 (&String, &RpValue::String(_)) => true,
182 (&U32, &RpValue::Number(_)) => true,
183 (&U64, &RpValue::Number(_)) => true,
184 (&I32, &RpValue::Number(_)) => true,
185 (&I64, &RpValue::Number(_)) => true,
186 _ => false,
187 }
188 }
189
190 pub fn validate_number(&self, number: &RpNumber) -> Result<()> {
192 const MAX_SAFE_INTEGER: i64 = 9007199254740991i64;
194 const MIN_SAFE_INTEGER: i64 = -9007199254740991i64;
195
196 use self::RpEnumType::*;
197
198 let (mn, mx): (BigInt, BigInt) = match *self {
199 String => return Err("expected number, got `string`".into()),
200 U32 => (0u32.into(), i32::max_value().into()),
201 U64 => (0u64.into(), MAX_SAFE_INTEGER.into()),
202 I32 => (i32::min_value().into(), i32::max_value().into()),
203 I64 => (MIN_SAFE_INTEGER.into(), MAX_SAFE_INTEGER.into()),
204 };
205
206 let n = number.to_bigint().ok_or_else(|| "not a whole number")?;
207
208 if &mn <= n && n <= &mx {
210 return Ok(());
211 }
212
213 return Err(format!("number is not within {} to {} (inclusive)", mn, mx).into());
214 }
215}
216
217impl fmt::Display for RpEnumType {
218 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
219 use self::RpEnumType::*;
220
221 match *self {
222 String => "string".fmt(fmt),
223 U32 => "u32".fmt(fmt),
224 U64 => "u64".fmt(fmt),
225 I32 => "i32".fmt(fmt),
226 I64 => "i64".fmt(fmt),
227 }
228 }
229}
230
231#[derive(Debug, Clone, Serialize)]
232#[serde(bound = "F: Serialize, F::Package: Serialize, F::Name: Serialize")]
233#[serde(tag = "type", rename_all = "snake_case")]
234pub enum RpVariants<F: 'static>
235where
236 F: Flavor,
237{
238 String {
239 variants: Vec<Loc<RpVariant<F, String>>>,
240 },
241 Number {
242 variants: Vec<Loc<RpVariant<F, RpNumber>>>,
243 },
244}
245
246pub struct RpVariantsIter<'a, F: 'static>
247where
248 F: Flavor,
249{
250 iter: vec::IntoIter<RpVariantRef<'a, F>>,
251}
252
253impl<'a, F: 'static> Iterator for RpVariantsIter<'a, F>
254where
255 F: Flavor,
256{
257 type Item = RpVariantRef<'a, F>;
258
259 fn next(&mut self) -> Option<Self::Item> {
260 self.iter.next()
261 }
262}
263
264impl<F: 'static> RpVariants<F>
265where
266 F: Flavor,
267{
268 pub fn iter(&self) -> RpVariantsIter<F> {
270 use self::RpVariants::*;
271
272 macro_rules! variants {
273 ($slf:ident, $($ty:ident),*) => {
274 match *$slf {
275 $(
276 $ty { ref variants } => {
277 let mut __o = Vec::new();
278
279 for v in variants {
280 let (value, span) = Loc::borrow_pair(v);
281
282 __o.push(RpVariantRef {
283 span: span,
284 name: &value.name,
285 ident: &value.ident,
286 comment: &value.comment,
287 value: RpVariantValue::from(&value.value),
288 })
289 }
290
291 __o
292 },
293 )*
294 }
295 };
296 }
297
298 let variants: Vec<_> = variants!(self, String, Number);
299
300 RpVariantsIter {
301 iter: variants.into_iter(),
302 }
303 }
304}
305
306impl<F: 'static, T> Translate<T> for RpVariants<F>
307where
308 F: Flavor,
309 T: Translator<Source = F>,
310{
311 type Source = F;
312 type Out = RpVariants<T::Target>;
313
314 fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpVariants<T::Target>> {
316 use self::RpVariants::*;
317
318 let out = match self {
319 String { variants } => String {
320 variants: variants.translate(diag, translator)?,
321 },
322 Number { variants } => Number {
323 variants: variants.translate(diag, translator)?,
324 },
325 };
326
327 Ok(out)
328 }
329}
330
331impl<'a, F: 'static> IntoIterator for &'a RpVariants<F>
332where
333 F: Flavor,
334{
335 type Item = RpVariantRef<'a, F>;
336 type IntoIter = RpVariantsIter<'a, F>;
337
338 fn into_iter(self) -> Self::IntoIter {
339 self.iter()
340 }
341}