1use std::fmt::Display;
16use std::ops::Deref;
17
18use bincode::{Decode, Encode};
19use combine::parser::char;
20use combine::parser::char::{char, spaces, string};
21use combine::{attempt, between, choice, optional, sep_by, Parser};
22use combine::{parser, ParseError};
23use golem_wasm_ast::analysis::{AnalysedType, TypeResult};
24
25use crate::parser::errors::RibParseError;
26use crate::rib_source_span::GetSourcePosition;
27use crate::{InferredNumber, InferredType};
28
29#[derive(Debug, Hash, Clone, Eq, PartialEq, Encode, Decode, Ord, PartialOrd)]
38pub enum TypeName {
39 Bool,
40 S8,
41 U8,
42 S16,
43 U16,
44 S32,
45 U32,
46 S64,
47 U64,
48 F32,
49 F64,
50 Chr,
51 Str,
52 List(Box<TypeName>),
53 Tuple(Vec<TypeName>),
54 Option(Box<TypeName>),
55 Result {
56 ok: Option<Box<TypeName>>,
57 error: Option<Box<TypeName>>,
58 },
59 Record(Vec<(String, Box<TypeName>)>),
60 Flags(Vec<String>),
61 Enum(Vec<String>),
62 Variant {
63 cases: Vec<(String, Option<Box<TypeName>>)>,
64 },
65}
66
67impl Display for TypeName {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 match self {
70 TypeName::Bool => write!(f, "bool"),
71 TypeName::S8 => write!(f, "s8"),
72 TypeName::U8 => write!(f, "u8"),
73 TypeName::S16 => write!(f, "s16"),
74 TypeName::U16 => write!(f, "u16"),
75 TypeName::S32 => write!(f, "s32"),
76 TypeName::U32 => write!(f, "u32"),
77 TypeName::S64 => write!(f, "s64"),
78 TypeName::U64 => write!(f, "u64"),
79 TypeName::F32 => write!(f, "f32"),
80 TypeName::F64 => write!(f, "f64"),
81 TypeName::Chr => write!(f, "char"),
82 TypeName::Str => write!(f, "string"),
83 TypeName::List(inner_type) => write!(f, "list<{}>", inner_type),
84 TypeName::Tuple(inner_types) => {
85 write!(f, "tuple<")?;
86 for (i, inner_type) in inner_types.iter().enumerate() {
87 if i > 0 {
88 write!(f, ", ")?;
89 }
90 write!(f, "{}", inner_type)?;
91 }
92 write!(f, ">")
93 }
94 TypeName::Option(inner_type) => write!(f, "option<{}>", inner_type),
95 TypeName::Result { ok, error } => match (ok, error) {
97 (Some(ok), Some(error)) => {
98 write!(f, "result<{}, {}>", ok, error)
99 }
100 (Some(ok), None) => {
101 write!(f, "result<{}>", ok)
102 }
103 (None, Some(error)) => {
104 write!(f, "result<_, {}>", error)
105 }
106 (None, None) => {
107 write!(f, "result")
108 }
109 },
110 TypeName::Record(fields) => {
111 write!(f, "record {{ ")?;
112 for (i, (field, typ)) in fields.iter().enumerate() {
113 if i > 0 {
114 write!(f, ", ")?;
115 }
116 write!(f, "{}: {}", field, typ)?;
117 }
118 write!(f, " }}")
119 }
120 TypeName::Flags(flags) => {
121 write!(f, "flags<")?;
122 for (i, flag) in flags.iter().enumerate() {
123 if i > 0 {
124 write!(f, ", ")?;
125 }
126 write!(f, "{}", flag)?;
127 }
128 write!(f, ">")
129 }
130 TypeName::Enum(cases) => {
131 write!(f, "enum {{ ")?;
132 for (i, case) in cases.iter().enumerate() {
133 if i > 0 {
134 write!(f, ", ")?;
135 }
136 write!(f, "{}", case)?;
137 }
138 write!(f, " }}")
139 }
140 TypeName::Variant { cases } => {
141 write!(f, "variant {{")?;
142 for (i, (case, typ)) in cases.iter().enumerate() {
143 if i > 0 {
144 write!(f, ", ")?;
145 }
146 write!(f, "{}", case)?;
147 if let Some(typ) = typ {
148 write!(f, "({})", typ)?;
149 }
150 }
151 write!(f, " }}")
152 }
153 }
154 }
155}
156
157impl From<&InferredNumber> for TypeName {
158 fn from(value: &InferredNumber) -> Self {
159 match value {
160 InferredNumber::S8 => TypeName::S8,
161 InferredNumber::U8 => TypeName::U8,
162 InferredNumber::S16 => TypeName::S16,
163 InferredNumber::U16 => TypeName::U16,
164 InferredNumber::S32 => TypeName::S32,
165 InferredNumber::U32 => TypeName::U32,
166 InferredNumber::S64 => TypeName::S64,
167 InferredNumber::U64 => TypeName::U64,
168 InferredNumber::F32 => TypeName::F32,
169 InferredNumber::F64 => TypeName::F64,
170 }
171 }
172}
173
174impl TryFrom<AnalysedType> for TypeName {
175 type Error = String;
176 fn try_from(analysed_type: AnalysedType) -> Result<Self, Self::Error> {
177 match analysed_type {
178 AnalysedType::Bool(_) => Ok(TypeName::Bool),
179 AnalysedType::S8(_) => Ok(TypeName::S8),
180 AnalysedType::U8(_) => Ok(TypeName::U8),
181 AnalysedType::S16(_) => Ok(TypeName::S16),
182 AnalysedType::U16(_) => Ok(TypeName::U16),
183 AnalysedType::S32(_) => Ok(TypeName::S32),
184 AnalysedType::U32(_) => Ok(TypeName::U32),
185 AnalysedType::S64(_) => Ok(TypeName::S64),
186 AnalysedType::U64(_) => Ok(TypeName::U64),
187 AnalysedType::F32(_) => Ok(TypeName::F32),
188 AnalysedType::F64(_) => Ok(TypeName::F64),
189 AnalysedType::Chr(_) => Ok(TypeName::Chr),
190 AnalysedType::Str(_) => Ok(TypeName::Str),
191 AnalysedType::List(inner_type) => Ok(TypeName::List(Box::new(
192 inner_type.inner.deref().clone().try_into()?,
193 ))),
194 AnalysedType::Tuple(inner_type) => Ok(TypeName::Tuple(
195 inner_type
196 .items
197 .into_iter()
198 .map(|x| x.try_into())
199 .collect::<Result<_, _>>()?,
200 )),
201 AnalysedType::Option(type_option) => Ok(TypeName::Option(Box::new(
202 type_option.inner.deref().clone().try_into()?,
203 ))),
204 AnalysedType::Result(TypeResult { ok, err }) => match (ok, err) {
205 (Some(ok), Some(err)) => Ok(TypeName::Result {
206 ok: Some(Box::new(ok.deref().clone().try_into()?)),
207 error: Some(Box::new(err.deref().clone().try_into()?)),
208 }),
209 (Some(ok), None) => Ok(TypeName::Result {
210 ok: Some(Box::new(ok.deref().clone().try_into()?)),
211 error: None,
212 }),
213 (None, Some(err)) => Ok(TypeName::Result {
214 ok: None,
215 error: Some(Box::new(err.deref().clone().try_into()?)),
216 }),
217 (None, None) => Ok(TypeName::Result {
218 ok: None,
219 error: None,
220 }),
221 },
222 AnalysedType::Record(type_record) => {
223 let mut fields = vec![];
224 for field in type_record.fields {
225 let name = field.name.clone();
226 let typ = field.typ.clone();
227 let type_name = typ.try_into()?;
228 fields.push((name, Box::new(type_name)));
229 }
230
231 Ok(TypeName::Record(fields))
232 }
233 AnalysedType::Flags(flags) => Ok(TypeName::Flags(flags.names)),
234 AnalysedType::Enum(cases) => Ok(TypeName::Enum(cases.cases)),
235 AnalysedType::Variant(cases) => {
236 let mut variant_cases = vec![];
237 for case in cases.cases {
238 let name = case.name.clone();
239 let typ = case.typ.clone();
240 match typ {
241 Some(typ) => {
242 let type_name = typ.try_into()?;
243 variant_cases.push((name, Some(Box::new(type_name))));
244 }
245 None => {
246 variant_cases.push((name, None));
247 }
248 }
249 }
250 Ok(TypeName::Variant {
251 cases: variant_cases,
252 })
253 }
254 AnalysedType::Handle(type_handle) => {
255 Err(format!("Handle type not supported: {:?}", type_handle))
256 }
257 }
258 }
259}
260
261impl From<TypeName> for InferredType {
262 fn from(type_name: TypeName) -> Self {
263 match type_name {
264 TypeName::Bool => InferredType::Bool,
265 TypeName::S8 => InferredType::S8,
266 TypeName::U8 => InferredType::U8,
267 TypeName::S16 => InferredType::S16,
268 TypeName::U16 => InferredType::U16,
269 TypeName::S32 => InferredType::S32,
270 TypeName::U32 => InferredType::U32,
271 TypeName::S64 => InferredType::S64,
272 TypeName::U64 => InferredType::U64,
273 TypeName::F32 => InferredType::F32,
274 TypeName::F64 => InferredType::F64,
275 TypeName::Chr => InferredType::Chr,
276 TypeName::Str => InferredType::Str,
277 TypeName::List(inner_type) => {
278 InferredType::List(Box::new(inner_type.deref().clone().into()))
279 }
280 TypeName::Tuple(inner_types) => {
281 InferredType::Tuple(inner_types.into_iter().map(|t| t.into()).collect())
282 }
283 TypeName::Option(type_name) => {
284 InferredType::Option(Box::new(type_name.deref().clone().into()))
285 }
286 TypeName::Result { ok, error } => InferredType::Result {
287 ok: ok.map(|x| Box::new(x.deref().clone().into())),
288 error: error.map(|x| Box::new(x.deref().clone().into())),
289 },
290 TypeName::Record(fields) => InferredType::Record(
291 fields
292 .into_iter()
293 .map(|(field, typ)| (field, typ.deref().clone().into()))
294 .collect(),
295 ),
296 TypeName::Flags(flags) => InferredType::Flags(flags),
297 TypeName::Enum(cases) => InferredType::Enum(cases),
298 TypeName::Variant { cases } => InferredType::Variant(
299 cases
300 .into_iter()
301 .map(|(case, typ)| (case, typ.map(|x| x.deref().clone().into())))
302 .collect(),
303 ),
304 }
305 }
306}
307
308impl TryFrom<InferredType> for TypeName {
309 type Error = String;
310
311 fn try_from(value: InferredType) -> Result<Self, Self::Error> {
312 match value {
313 InferredType::Bool => Ok(TypeName::Bool),
314 InferredType::S8 => Ok(TypeName::S8),
315 InferredType::U8 => Ok(TypeName::U8),
316 InferredType::S16 => Ok(TypeName::S16),
317 InferredType::U16 => Ok(TypeName::U16),
318 InferredType::S32 => Ok(TypeName::S32),
319 InferredType::U32 => Ok(TypeName::U32),
320 InferredType::S64 => Ok(TypeName::S64),
321 InferredType::U64 => Ok(TypeName::U64),
322 InferredType::F32 => Ok(TypeName::F32),
323 InferredType::F64 => Ok(TypeName::F64),
324 InferredType::Chr => Ok(TypeName::Chr),
325 InferredType::Str => Ok(TypeName::Str),
326 InferredType::List(inferred_type) => {
327 let verified = inferred_type.deref().clone().try_into()?;
328 Ok(TypeName::List(Box::new(verified)))
329 }
330 InferredType::Tuple(inferred_types) => {
331 let mut verified_types = vec![];
332 for typ in inferred_types {
333 let verified = typ.try_into()?;
334 verified_types.push(verified);
335 }
336 Ok(TypeName::Tuple(verified_types))
337 }
338 InferredType::Record(name_and_types) => {
339 let mut fields = vec![];
340 for (field, typ) in name_and_types {
341 let verified = typ.try_into()?;
342 fields.push((field, Box::new(verified)));
343 }
344 Ok(TypeName::Record(fields))
345 }
346 InferredType::Flags(flags) => Ok(TypeName::Flags(flags)),
347 InferredType::Enum(enums) => Ok(TypeName::Enum(enums)),
348 InferredType::Option(inferred_type) => {
349 let result = inferred_type.deref().clone().try_into()?;
350 Ok(TypeName::Option(Box::new(result)))
351 }
352 InferredType::Result { ok, error } => {
353 let ok_unified = ok.map(|ok| ok.deref().clone().try_into()).transpose()?;
354 let err_unified = error
355 .map(|err| err.deref().clone().try_into())
356 .transpose()?;
357 Ok(TypeName::Result {
358 ok: ok_unified.map(Box::new),
359 error: err_unified.map(Box::new),
360 })
361 }
362 InferredType::Variant(variant) => {
363 let mut cases = vec![];
364 for (case, typ) in variant {
365 let verified = typ.map(TypeName::try_from).transpose()?;
366 cases.push((case, verified.map(Box::new)));
367 }
368 Ok(TypeName::Variant { cases })
369 }
370 InferredType::Resource { .. } => {
371 Err("Cannot convert a resource type to a type name".to_string())
372 }
373 InferredType::OneOf(_) => {
374 Err("Cannot convert a one of type to a type name".to_string())
375 }
376 InferredType::AllOf(_) => {
377 Err("Cannot convert a all of type to a type name".to_string())
378 }
379 InferredType::Unknown => {
380 Err("Cannot convert an unknown type to a type name".to_string())
381 }
382 InferredType::Sequence(_) => {
383 Err("Cannot convert a sequence type to a type name".to_string())
384 }
385 InferredType::Instance { .. } => {
386 Err("Cannot convert an instance type to a type name".to_string())
387 }
388 InferredType::Range { .. } => {
389 Err("Cannot convert a range type to a type name".to_string())
390 }
391 }
392 }
393}
394
395pub fn parse_basic_type<Input>() -> impl Parser<Input, Output = TypeName>
396where
397 Input: combine::Stream<Token = char>,
398 RibParseError: Into<
399 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
400 >,
401 Input::Position: GetSourcePosition,
402{
403 choice((
404 attempt(string("bool").map(|_| TypeName::Bool)),
405 attempt(string("s8").map(|_| TypeName::S8)),
406 attempt(string("u8").map(|_| TypeName::U8)),
407 attempt(string("s16").map(|_| TypeName::S16)),
408 attempt(string("u16").map(|_| TypeName::U16)),
409 attempt(string("s32").map(|_| TypeName::S32)),
410 attempt(string("u32").map(|_| TypeName::U32)),
411 attempt(string("s64").map(|_| TypeName::S64)),
412 attempt(string("u64").map(|_| TypeName::U64)),
413 attempt(string("f32").map(|_| TypeName::F32)),
414 attempt(string("f64").map(|_| TypeName::F64)),
415 attempt(string("char").map(|_| TypeName::Chr)),
416 attempt(string("string").map(|_| TypeName::Str)),
417 ))
418 .skip(spaces().silent())
419}
420
421pub fn parse_list_type<Input>() -> impl Parser<Input, Output = TypeName>
422where
423 Input: combine::Stream<Token = char>,
424 RibParseError: Into<
425 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
426 >,
427 Input::Position: GetSourcePosition,
428{
429 string("list")
430 .skip(spaces().silent())
431 .with(between(
432 char('<').skip(spaces().silent().silent()),
433 char('>').skip(spaces().silent().silent()),
434 type_name(),
435 ))
436 .map(|inner_type| TypeName::List(Box::new(inner_type)))
437}
438
439pub fn parse_option_type<Input>() -> impl Parser<Input, Output = TypeName>
440where
441 Input: combine::Stream<Token = char>,
442 RibParseError: Into<
443 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
444 >,
445 Input::Position: GetSourcePosition,
446{
447 string("option")
448 .skip(spaces().silent())
449 .with(between(
450 char('<').skip(spaces().silent().silent()),
451 char('>').skip(spaces().silent().silent()),
452 type_name(),
453 ))
454 .map(|inner_type| TypeName::Option(Box::new(inner_type)))
455}
456
457enum ResultSuccess {
458 NoType,
459 WithType(TypeName),
460}
461
462pub fn parse_result_type<Input>() -> impl Parser<Input, Output = TypeName>
464where
465 Input: combine::Stream<Token = char>,
466 RibParseError: Into<
467 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
468 >,
469 Input::Position: GetSourcePosition,
470{
471 string("result")
472 .skip(spaces().silent())
473 .with(optional(between(
474 char('<').skip(spaces().silent()),
475 char('>').skip(spaces().silent()),
476 (
477 choice!(
478 string("_")
479 .skip(spaces().silent())
480 .map(|_| ResultSuccess::NoType),
481 type_name()
482 .skip(spaces().silent())
483 .map(ResultSuccess::WithType)
484 ),
485 optional(
486 char(',')
487 .skip(spaces().silent())
488 .with(type_name().skip(spaces().silent())),
489 ),
490 ),
491 )))
492 .map(|result| match result {
493 None => TypeName::Result {
494 ok: None,
495 error: None,
496 },
497 Some((ResultSuccess::NoType, None)) => TypeName::Result {
498 ok: None,
499 error: None,
500 },
501 Some((ResultSuccess::NoType, Some(error))) => TypeName::Result {
502 ok: None,
503 error: Some(Box::new(error)),
504 },
505 Some((ResultSuccess::WithType(ok), None)) => TypeName::Result {
506 ok: Some(Box::new(ok)),
507 error: None,
508 },
509 Some((ResultSuccess::WithType(ok), Some(error))) => TypeName::Result {
510 ok: Some(Box::new(ok)),
511 error: Some(Box::new(error)),
512 },
513 })
514}
515
516pub fn parse_tuple_type<Input>() -> impl Parser<Input, Output = TypeName>
517where
518 Input: combine::Stream<Token = char>,
519 RibParseError: Into<
520 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
521 >,
522 Input::Position: GetSourcePosition,
523{
524 string("tuple")
525 .skip(spaces().silent())
526 .with(between(
527 char('<').skip(spaces().silent()),
528 char('>').skip(spaces().silent()),
529 sep_by(type_name(), char(',').skip(spaces().silent())),
530 ))
531 .map(TypeName::Tuple)
532}
533
534pub fn type_name_<Input>() -> impl Parser<Input, Output = TypeName>
535where
536 Input: combine::Stream<Token = char>,
537 RibParseError: Into<
538 <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
539 >,
540 Input::Position: GetSourcePosition,
541{
542 spaces().silent().with(choice((
543 attempt(parse_basic_type()),
544 attempt(parse_list_type()),
545 attempt(parse_tuple_type()),
546 attempt(parse_option_type()),
547 attempt(parse_result_type()),
548 )))
549}
550
551parser! {
552 pub fn type_name[Input]()(Input) -> TypeName
553 where [Input: combine::Stream<Token = char>, RibParseError: Into<<Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError>, Input::Position: GetSourcePosition]
554 {
555 type_name_()
556 }
557}
558
559#[cfg(feature = "protobuf")]
560mod protobuf {
561 use golem_api_grpc::proto::golem::rib::type_name::Kind as InnerTypeName;
562 use golem_api_grpc::proto::golem::rib::{
563 BasicTypeName, EnumType, FlagType, KeyValue, ListType, OptionType, RecordType, ResultType,
564 TupleType, TypeName as ProtoTypeName, VariantCase, VariantType,
565 };
566 use std::ops::Deref;
567
568 use crate::TypeName;
569
570 impl From<TypeName> for ProtoTypeName {
571 fn from(value: TypeName) -> Self {
572 let inner = match value {
573 TypeName::Bool => InnerTypeName::BasicType(BasicTypeName::Bool as i32),
574 TypeName::S8 => InnerTypeName::BasicType(BasicTypeName::S8 as i32),
575 TypeName::U8 => InnerTypeName::BasicType(BasicTypeName::U8 as i32),
576 TypeName::S16 => InnerTypeName::BasicType(BasicTypeName::S16 as i32),
577 TypeName::U16 => InnerTypeName::BasicType(BasicTypeName::U16 as i32),
578 TypeName::S32 => InnerTypeName::BasicType(BasicTypeName::S32 as i32),
579 TypeName::U32 => InnerTypeName::BasicType(BasicTypeName::U32 as i32),
580 TypeName::S64 => InnerTypeName::BasicType(BasicTypeName::S64 as i32),
581 TypeName::U64 => InnerTypeName::BasicType(BasicTypeName::U64 as i32),
582 TypeName::F32 => InnerTypeName::BasicType(BasicTypeName::F32 as i32),
583 TypeName::F64 => InnerTypeName::BasicType(BasicTypeName::F64 as i32),
584 TypeName::Chr => InnerTypeName::BasicType(BasicTypeName::Chr as i32),
585 TypeName::Str => InnerTypeName::BasicType(BasicTypeName::Str as i32),
586 TypeName::List(inner_type) => InnerTypeName::ListType(Box::new(ListType {
587 inner_type: Some(Box::new(inner_type.deref().clone().into())),
588 })),
589 TypeName::Tuple(inner_types) => InnerTypeName::TupleType(TupleType {
590 types: inner_types.into_iter().map(|t| t.into()).collect(),
591 }),
592 TypeName::Option(type_name) => InnerTypeName::OptionType(Box::new(OptionType {
593 inner_type: Some(Box::new(type_name.deref().clone().into())),
594 })),
595 TypeName::Result { ok, error } => InnerTypeName::ResultType(Box::new(ResultType {
596 ok_type: ok.map(|ok| Box::new(ok.deref().clone().into())),
597 err_type: error.map(|error| Box::new(error.deref().clone().into())),
598 })),
599 TypeName::Record(fields) => InnerTypeName::RecordType(RecordType {
600 fields: fields
601 .into_iter()
602 .map(|(field, typ)| KeyValue {
603 key: field,
604 value: Some(typ.deref().clone().into()),
605 })
606 .collect(),
607 }),
608 TypeName::Flags(flags) => InnerTypeName::FlagType(FlagType {
609 flags: flags.into_iter().collect(),
610 }),
611 TypeName::Enum(cases) => InnerTypeName::EnumType(EnumType {
612 cases: cases.into_iter().collect(),
613 }),
614 TypeName::Variant { cases } => InnerTypeName::VariantType(VariantType {
615 cases: cases
616 .into_iter()
617 .map(|(case, typ)| VariantCase {
618 case_name: case,
619 variant_arg: typ.map(|x| x.deref().clone().into()),
620 })
621 .collect(),
622 }),
623 };
624
625 ProtoTypeName { kind: Some(inner) }
626 }
627 }
628
629 impl TryFrom<ProtoTypeName> for TypeName {
630 type Error = String;
631
632 fn try_from(value: ProtoTypeName) -> Result<Self, Self::Error> {
633 match value.kind {
634 Some(inner) => match inner {
635 InnerTypeName::BasicType(value) => match BasicTypeName::try_from(value) {
636 Ok(BasicTypeName::Bool) => Ok(TypeName::Bool),
637 Ok(BasicTypeName::S8) => Ok(TypeName::S8),
638 Ok(BasicTypeName::U8) => Ok(TypeName::U8),
639 Ok(BasicTypeName::S16) => Ok(TypeName::S16),
640 Ok(BasicTypeName::U16) => Ok(TypeName::U16),
641 Ok(BasicTypeName::S32) => Ok(TypeName::S32),
642 Ok(BasicTypeName::U32) => Ok(TypeName::U32),
643 Ok(BasicTypeName::S64) => Ok(TypeName::S64),
644 Ok(BasicTypeName::U64) => Ok(TypeName::U64),
645 Ok(BasicTypeName::F32) => Ok(TypeName::F32),
646 Ok(BasicTypeName::F64) => Ok(TypeName::F64),
647 Ok(BasicTypeName::Chr) => Ok(TypeName::Chr),
648 Ok(BasicTypeName::Str) => Ok(TypeName::Str),
649 _ => Err(format!("Unknown basic type: {:?}", value)),
650 },
651 InnerTypeName::ListType(inner_type) => {
652 let proto_list_type = inner_type
653 .inner_type
654 .ok_or("No inner type for list provided")?;
655 let list_type = proto_list_type.deref().clone().try_into()?;
656 Ok(TypeName::List(Box::new(list_type)))
657 }
658 InnerTypeName::TupleType(inner_types) => {
659 let tuple_type = inner_types
660 .types
661 .into_iter()
662 .map(|t| t.try_into())
663 .collect::<Result<Vec<TypeName>, String>>()?;
664 Ok(TypeName::Tuple(tuple_type))
665 }
666 InnerTypeName::OptionType(type_name) => {
667 let proto_option_type = type_name
668 .inner_type
669 .ok_or("No inner type for option provided")?;
670 let option_type = proto_option_type.deref().clone().try_into()?;
671 Ok(TypeName::Option(Box::new(option_type)))
672 }
673 InnerTypeName::ResultType(result_type) => {
674 let ok = result_type
675 .ok_type
676 .map(|ok| ok.deref().clone().try_into())
677 .transpose()?;
678 let error = result_type
679 .err_type
680 .map(|error| error.deref().clone().try_into())
681 .transpose()?;
682 Ok(TypeName::Result {
683 ok: ok.map(Box::new),
684 error: error.map(Box::new),
685 })
686 }
687 InnerTypeName::RecordType(fields) => {
688 let record_type = fields
689 .fields
690 .into_iter()
691 .map(|key_value| {
692 key_value
693 .value
694 .ok_or("Field type missing")?
695 .try_into()
696 .map(|typ| (key_value.key, Box::new(typ)))
697 })
698 .collect::<Result<Vec<(String, Box<TypeName>)>, String>>()?;
699 Ok(TypeName::Record(record_type))
700 }
701 InnerTypeName::FlagType(flag_type) => Ok(TypeName::Flags(flag_type.flags)),
702 InnerTypeName::EnumType(enum_type) => Ok(TypeName::Enum(enum_type.cases)),
703 InnerTypeName::VariantType(variant_type) => {
704 let mut cases = vec![];
705 for variant_case in variant_type.cases {
706 let case = variant_case.case_name;
707 let typ = match variant_case.variant_arg {
708 Some(typ) => Some(Box::new(TypeName::try_from(typ)?)),
709 None => None,
710 };
711 cases.push((case, typ));
712 }
713
714 Ok(TypeName::Variant { cases })
715 }
716 },
717 None => Err("No type kind provided".to_string()),
718 }
719 }
720 }
721}
722
723#[cfg(test)]
724mod type_name_tests {
725 use combine::stream::position;
726 use combine::EasyParser;
727 use test_r::test;
728
729 use super::*;
730
731 fn parse_and_compare(input: &str, expected: TypeName) {
732 let written = format!("{}", expected);
733 let result1 = type_name()
734 .easy_parse(position::Stream::new(input))
735 .map(|x| x.0);
736 let result2 = type_name()
737 .easy_parse(position::Stream::new(written.as_str()))
738 .map(|x| x.0);
739 assert_eq!(result1, Ok(expected.clone()));
740 assert_eq!(result2, Ok(expected));
741 }
742
743 #[test]
744 fn test_basic_types() {
745 parse_and_compare("bool", TypeName::Bool);
746 parse_and_compare("s8", TypeName::S8);
747 parse_and_compare("u8", TypeName::U8);
748 parse_and_compare("s16", TypeName::S16);
749 parse_and_compare("u16", TypeName::U16);
750 parse_and_compare("s32", TypeName::S32);
751 parse_and_compare("u32", TypeName::U32);
752 parse_and_compare("s64", TypeName::S64);
753 parse_and_compare("u64", TypeName::U64);
754 parse_and_compare("f32", TypeName::F32);
755 parse_and_compare("f64", TypeName::F64);
756 parse_and_compare("char", TypeName::Chr);
757 parse_and_compare("string", TypeName::Str);
758 }
759
760 #[test]
761 fn test_list_type_name() {
762 parse_and_compare("list<u8>", TypeName::List(Box::new(TypeName::U8)));
763 parse_and_compare(
764 "list<list<f32>>",
765 TypeName::List(Box::new(TypeName::List(Box::new(TypeName::F32)))),
766 );
767 }
768
769 #[test]
770 fn test_tuple_type_name() {
771 parse_and_compare(
772 "tuple<u8, u16>",
773 TypeName::Tuple(vec![TypeName::U8, TypeName::U16]),
774 );
775 parse_and_compare(
776 "tuple<s32, list<u8>>",
777 TypeName::Tuple(vec![TypeName::S32, TypeName::List(Box::new(TypeName::U8))]),
778 );
779 parse_and_compare(
780 "tuple<tuple<s8, s16>, u32>",
781 TypeName::Tuple(vec![
782 TypeName::Tuple(vec![TypeName::S8, TypeName::S16]),
783 TypeName::U32,
784 ]),
785 );
786 }
787
788 #[test]
789 fn test_option_type_name() {
790 parse_and_compare("option<u8>", TypeName::Option(Box::new(TypeName::U8)));
791 parse_and_compare(
792 "option<list<f32>>",
793 TypeName::Option(Box::new(TypeName::List(Box::new(TypeName::F32)))),
794 );
795 }
796
797 #[test]
798 fn test_nested_types() {
799 parse_and_compare(
800 "list<tuple<u8, s8>>",
801 TypeName::List(Box::new(TypeName::Tuple(vec![TypeName::U8, TypeName::S8]))),
802 );
803 parse_and_compare(
804 "tuple<list<u16>, list<f64>>",
805 TypeName::Tuple(vec![
806 TypeName::List(Box::new(TypeName::U16)),
807 TypeName::List(Box::new(TypeName::F64)),
808 ]),
809 );
810 }
811
812 #[test]
813 fn test_spaces_around_types() {
814 parse_and_compare(" u8 ", TypeName::U8);
815 parse_and_compare("list< u8 >", TypeName::List(Box::new(TypeName::U8)));
816 parse_and_compare(
817 "tuple< s32 , list< u8 > >",
818 TypeName::Tuple(vec![TypeName::S32, TypeName::List(Box::new(TypeName::U8))]),
819 );
820 }
821}