Skip to main content

rib/compiler/
type_with_unit.rs

1use crate::wit_type::{bool, field, record, str, tuple};
2use crate::wit_type::{
3    AnalysedResourceId, AnalysedResourceMode, NameOptionTypePair, NameTypePair, TypeBool, TypeChr,
4    TypeEnum, TypeF32, TypeF64, TypeFlags, TypeHandle, TypeList, TypeOption, TypeRecord,
5    TypeResult, TypeS16, TypeS32, TypeS64, TypeS8, TypeStr, TypeTuple, TypeU16, TypeU32, TypeU64,
6    TypeU8, TypeVariant, WitType,
7};
8use crate::{GetTypeHint, InferredType, InstanceType, TypeInternal};
9use serde::{Deserialize, Serialize};
10
11// An absence of wit type is really `Unit`, however, we avoid
12// Option<WitType> in favor of `WitTypeWithUnit` for clarity.
13// and conversions such as what to print if its `unit` becomes more precise
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
15pub enum WitTypeWithUnit {
16    Unit,
17    Type(WitType),
18}
19
20impl WitTypeWithUnit {
21    pub fn unit() -> Self {
22        WitTypeWithUnit::Unit
23    }
24
25    pub fn analysed_type(typ: WitType) -> Self {
26        WitTypeWithUnit::Type(typ)
27    }
28}
29
30impl TryFrom<WitTypeWithUnit> for WitType {
31    type Error = String;
32
33    fn try_from(value: WitTypeWithUnit) -> Result<Self, Self::Error> {
34        match value {
35            WitTypeWithUnit::Unit => Ok(tuple(vec![])),
36            WitTypeWithUnit::Type(typ) => Ok(typ),
37        }
38    }
39}
40
41impl TryFrom<&InferredType> for WitType {
42    type Error = String;
43
44    fn try_from(value: &InferredType) -> Result<Self, Self::Error> {
45        let with_unit = WitTypeWithUnit::try_from(value)?;
46        WitType::try_from(with_unit)
47    }
48}
49
50impl TryFrom<&InferredType> for WitTypeWithUnit {
51    type Error = String;
52
53    fn try_from(inferred_type: &InferredType) -> Result<Self, Self::Error> {
54        match inferred_type.internal_type() {
55            TypeInternal::Instance { instance_type } => match instance_type.as_ref() {
56                InstanceType::Resource {
57                    analysed_resource_id,
58                    analysed_resource_mode,
59                    ..
60                } => {
61                    let analysed_resource_id = AnalysedResourceId(*analysed_resource_id);
62
63                    let analysed_resource_mode = if *analysed_resource_mode == 0 {
64                        AnalysedResourceMode::Owned
65                    } else {
66                        AnalysedResourceMode::Borrowed
67                    };
68
69                    Ok(WitTypeWithUnit::analysed_type(WitType::Handle(
70                        TypeHandle {
71                            resource_id: analysed_resource_id,
72                            mode: analysed_resource_mode,
73                            name: None,
74                            owner: None,
75                        },
76                    )))
77                }
78
79                _ => Ok(WitTypeWithUnit::analysed_type(str())),
80            },
81            TypeInternal::Range { from, to } => {
82                let from: WitType = WitType::try_from(from)?;
83                let to: Option<WitType> = to.as_ref().map(WitType::try_from).transpose()?;
84                let analysed_type = match (from, to) {
85                    (from_type, Some(to_type)) => record(vec![
86                        field("from", from_type),
87                        field("to", to_type),
88                        field("inclusive", bool()),
89                    ]),
90
91                    (from_type, None) => {
92                        record(vec![field("from", from_type), field("inclusive", bool())])
93                    }
94                };
95                Ok(WitTypeWithUnit::analysed_type(analysed_type))
96            }
97            TypeInternal::Bool => Ok(WitTypeWithUnit::analysed_type(WitType::Bool(TypeBool))),
98            TypeInternal::S8 => Ok(WitTypeWithUnit::analysed_type(WitType::S8(TypeS8))),
99            TypeInternal::U8 => Ok(WitTypeWithUnit::analysed_type(WitType::U8(TypeU8))),
100            TypeInternal::S16 => Ok(WitTypeWithUnit::analysed_type(WitType::S16(TypeS16))),
101            TypeInternal::U16 => Ok(WitTypeWithUnit::analysed_type(WitType::U16(TypeU16))),
102            TypeInternal::S32 => Ok(WitTypeWithUnit::analysed_type(WitType::S32(TypeS32))),
103            TypeInternal::U32 => Ok(WitTypeWithUnit::analysed_type(WitType::U32(TypeU32))),
104            TypeInternal::S64 => Ok(WitTypeWithUnit::analysed_type(WitType::S64(TypeS64))),
105            TypeInternal::U64 => Ok(WitTypeWithUnit::analysed_type(WitType::U64(TypeU64))),
106            TypeInternal::F32 => Ok(WitTypeWithUnit::analysed_type(WitType::F32(TypeF32))),
107            TypeInternal::F64 => Ok(WitTypeWithUnit::analysed_type(WitType::F64(TypeF64))),
108            TypeInternal::Chr => Ok(WitTypeWithUnit::analysed_type(WitType::Chr(TypeChr))),
109            TypeInternal::Str => Ok(WitTypeWithUnit::analysed_type(WitType::Str(TypeStr))),
110            TypeInternal::List(inferred_type) => {
111                Ok(WitTypeWithUnit::analysed_type(WitType::List(TypeList {
112                    inner: Box::new(inferred_type.try_into()?),
113                    name: None,
114                    owner: None,
115                })))
116            }
117            TypeInternal::Tuple(tuple) => {
118                Ok(WitTypeWithUnit::analysed_type(WitType::Tuple(TypeTuple {
119                    items: tuple
120                        .iter()
121                        .map(|t| t.try_into())
122                        .collect::<Result<Vec<WitType>, String>>()?,
123                    name: None,
124                    owner: None,
125                })))
126            }
127            TypeInternal::Record(record) => Ok(WitTypeWithUnit::analysed_type(WitType::Record(
128                TypeRecord {
129                    fields: record
130                        .iter()
131                        .map(|(name, typ)| {
132                            Ok(NameTypePair {
133                                name: name.to_string(),
134                                typ: typ.try_into()?,
135                            })
136                        })
137                        .collect::<Result<Vec<NameTypePair>, String>>()?,
138                    name: None,
139                    owner: None,
140                },
141            ))),
142            TypeInternal::Flags(flags) => {
143                Ok(WitTypeWithUnit::analysed_type(WitType::Flags(TypeFlags {
144                    names: flags.clone(),
145                    name: None,
146                    owner: None,
147                })))
148            }
149            TypeInternal::Enum(enums) => {
150                Ok(WitTypeWithUnit::analysed_type(WitType::Enum(TypeEnum {
151                    cases: enums.clone(),
152                    name: None,
153                    owner: None,
154                })))
155            }
156            TypeInternal::Option(option) => Ok(WitTypeWithUnit::analysed_type(WitType::Option(
157                TypeOption {
158                    inner: Box::new(option.try_into()?),
159                    name: None,
160                    owner: None,
161                },
162            ))),
163            TypeInternal::Result { ok, error } => Ok(WitTypeWithUnit::analysed_type(
164                // In the case of result, there are instances users give just 1 value with zero function calls, we need to be flexible here
165                WitType::Result(TypeResult {
166                    ok: ok.as_ref().and_then(|t| t.try_into().ok().map(Box::new)),
167                    err: error.as_ref().and_then(|t| t.try_into().ok().map(Box::new)),
168                    name: None,
169                    owner: None,
170                }),
171            )),
172            TypeInternal::Variant(variant) => Ok(WitTypeWithUnit::analysed_type(WitType::Variant(
173                TypeVariant {
174                    cases: variant
175                        .iter()
176                        .map(|(name, typ)| {
177                            Ok(NameOptionTypePair {
178                                name: name.clone(),
179                                typ: typ.as_ref().map(|t| t.try_into()).transpose()?,
180                            })
181                        })
182                        .collect::<Result<Vec<NameOptionTypePair>, String>>()?,
183                    name: None,
184                    owner: None,
185                },
186            ))),
187            TypeInternal::Resource {
188                resource_id,
189                resource_mode,
190                name: _,
191                owner: _,
192            } => Ok(WitTypeWithUnit::analysed_type(WitType::Handle(
193                TypeHandle {
194                    resource_id: AnalysedResourceId(*resource_id),
195                    mode: if resource_mode == &0 {
196                        AnalysedResourceMode::Owned
197                    } else {
198                        AnalysedResourceMode::Borrowed
199                    },
200                    name: None,
201                    owner: None,
202                },
203            ))),
204
205            TypeInternal::AllOf(types) => Err(format!(
206                "ambiguous types {}",
207                types
208                    .iter()
209                    .map(|x| x.get_type_hint().to_string())
210                    .collect::<Vec<_>>()
211                    .join(", ")
212            )),
213            TypeInternal::Unknown => Err("failed to infer type".to_string()),
214            // We don't expect to have a sequence type in the inferred type.as
215            // This implies Rib will not support multiple types from worker-function results
216            TypeInternal::Sequence(vec) => {
217                if vec.is_empty() {
218                    Ok(WitTypeWithUnit::unit())
219                } else if vec.len() == 1 {
220                    let first = &vec[0];
221                    Ok(first.try_into()?)
222                } else {
223                    Err("function with multiple return types not supported".to_string())
224                }
225            }
226        }
227    }
228}