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