1use crate::InferredType;
16use bincode::{Decode, Encode};
17use golem_wasm_ast::analysis::analysed_type::{bool, field, option, record, tuple};
18use golem_wasm_ast::analysis::{
19 AnalysedResourceId, AnalysedResourceMode, AnalysedType, NameOptionTypePair, NameTypePair,
20 TypeBool, TypeChr, TypeEnum, TypeF32, TypeF64, TypeFlags, TypeHandle, TypeList, TypeOption,
21 TypeRecord, TypeResult, TypeS16, TypeS32, TypeS64, TypeS8, TypeStr, TypeTuple, TypeU16,
22 TypeU32, TypeU64, TypeU8, TypeVariant,
23};
24use serde::{Deserialize, Serialize};
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)]
27pub enum AnalysedTypeWithUnit {
28 Unit,
29 Type(AnalysedType),
30}
31
32impl AnalysedTypeWithUnit {
33 pub fn unit() -> Self {
34 AnalysedTypeWithUnit::Unit
35 }
36
37 pub fn analysed_type(typ: AnalysedType) -> Self {
38 AnalysedTypeWithUnit::Type(typ)
39 }
40}
41
42impl TryFrom<AnalysedTypeWithUnit> for AnalysedType {
43 type Error = String;
44
45 fn try_from(value: AnalysedTypeWithUnit) -> Result<Self, Self::Error> {
46 match value {
47 AnalysedTypeWithUnit::Unit => Ok(tuple(vec![])),
48 AnalysedTypeWithUnit::Type(typ) => Ok(typ),
49 }
50 }
51}
52
53impl TryFrom<&InferredType> for AnalysedType {
54 type Error = String;
55
56 fn try_from(value: &InferredType) -> Result<Self, Self::Error> {
57 let with_unit = AnalysedTypeWithUnit::try_from(value)?;
58 AnalysedType::try_from(with_unit)
59 }
60}
61
62impl TryFrom<&InferredType> for AnalysedTypeWithUnit {
63 type Error = String;
64
65 fn try_from(inferred_type: &InferredType) -> Result<Self, Self::Error> {
66 match inferred_type {
67 InferredType::Instance { .. } => {
68 Err("Cannot convert Instance type to AnalysedType".to_string())
69 }
70 InferredType::Range { from, to } => {
71 let from: AnalysedType = AnalysedType::try_from(from.as_ref())?;
72 let to: Option<AnalysedType> = to
73 .as_ref()
74 .map(|t| AnalysedType::try_from(t.as_ref()))
75 .transpose()?;
76 let analysed_type = match (from, to) {
77 (from_type, Some(to_type)) => record(vec![
78 field("from", option(from_type)),
79 field("to", option(to_type)),
80 field("inclusive", bool()),
81 ]),
82
83 (from_type, None) => record(vec![
84 field("from", option(from_type)),
85 field("inclusive", bool()),
86 ]),
87 };
88 Ok(AnalysedTypeWithUnit::analysed_type(analysed_type))
89 }
90 InferredType::Bool => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::Bool(
91 TypeBool,
92 ))),
93 InferredType::S8 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::S8(
94 TypeS8,
95 ))),
96 InferredType::U8 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::U8(
97 TypeU8,
98 ))),
99 InferredType::S16 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::S16(
100 TypeS16,
101 ))),
102 InferredType::U16 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::U16(
103 TypeU16,
104 ))),
105 InferredType::S32 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::S32(
106 TypeS32,
107 ))),
108 InferredType::U32 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::U32(
109 TypeU32,
110 ))),
111 InferredType::S64 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::S64(
112 TypeS64,
113 ))),
114 InferredType::U64 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::U64(
115 TypeU64,
116 ))),
117 InferredType::F32 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::F32(
118 TypeF32,
119 ))),
120 InferredType::F64 => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::F64(
121 TypeF64,
122 ))),
123 InferredType::Chr => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::Chr(
124 TypeChr,
125 ))),
126 InferredType::Str => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::Str(
127 TypeStr,
128 ))),
129 InferredType::List(inferred_type) => Ok(AnalysedTypeWithUnit::analysed_type(
130 AnalysedType::List(TypeList {
131 inner: Box::new(inferred_type.as_ref().try_into()?),
132 }),
133 )),
134 InferredType::Tuple(tuple) => Ok(AnalysedTypeWithUnit::analysed_type(
135 AnalysedType::Tuple(TypeTuple {
136 items: tuple
137 .iter()
138 .map(|t| t.try_into())
139 .collect::<Result<Vec<AnalysedType>, String>>()?,
140 }),
141 )),
142 InferredType::Record(record) => Ok(AnalysedTypeWithUnit::analysed_type(
143 AnalysedType::Record(TypeRecord {
144 fields: record
145 .iter()
146 .map(|(name, typ)| {
147 Ok(NameTypePair {
148 name: name.to_string(),
149 typ: typ.try_into()?,
150 })
151 })
152 .collect::<Result<Vec<NameTypePair>, String>>()?,
153 }),
154 )),
155 InferredType::Flags(flags) => Ok(AnalysedTypeWithUnit::analysed_type(
156 AnalysedType::Flags(TypeFlags {
157 names: flags.clone(),
158 }),
159 )),
160 InferredType::Enum(enums) => Ok(AnalysedTypeWithUnit::analysed_type(
161 AnalysedType::Enum(TypeEnum {
162 cases: enums.clone(),
163 }),
164 )),
165 InferredType::Option(option) => Ok(AnalysedTypeWithUnit::analysed_type(
166 AnalysedType::Option(TypeOption {
167 inner: Box::new(option.as_ref().try_into()?),
168 }),
169 )),
170 InferredType::Result { ok, error } => Ok(AnalysedTypeWithUnit::analysed_type(
171 AnalysedType::Result(TypeResult {
173 ok: ok
174 .as_ref()
175 .and_then(|t| t.as_ref().try_into().ok().map(Box::new)),
176 err: error
177 .as_ref()
178 .and_then(|t| t.as_ref().try_into().ok().map(Box::new)),
179 }),
180 )),
181 InferredType::Variant(variant) => Ok(AnalysedTypeWithUnit::analysed_type(
182 AnalysedType::Variant(TypeVariant {
183 cases: variant
184 .iter()
185 .map(|(name, typ)| {
186 Ok(NameOptionTypePair {
187 name: name.clone(),
188 typ: typ.as_ref().map(|t| t.try_into()).transpose()?,
189 })
190 })
191 .collect::<Result<Vec<NameOptionTypePair>, String>>()?,
192 }),
193 )),
194 InferredType::Resource {
195 resource_id,
196 resource_mode,
197 } => Ok(AnalysedTypeWithUnit::analysed_type(AnalysedType::Handle(
198 TypeHandle {
199 resource_id: AnalysedResourceId(*resource_id),
200 mode: if resource_mode == &0 {
201 AnalysedResourceMode::Owned
202 } else {
203 AnalysedResourceMode::Borrowed
204 },
205 },
206 ))),
207
208 InferredType::OneOf(_) => Err(
209 "Cannot convert OneOf types (different possibilities of types) to AnalysedType"
210 .to_string(),
211 ),
212 InferredType::AllOf(types) => Err(format!(
213 "Cannot convert AllOf types (multiple types) to AnalysedType. {:?}",
214 types
215 )),
216 InferredType::Unknown => Err(" convert Unknown type to AnalysedType".to_string()),
217 InferredType::Sequence(vec) => {
220 if vec.is_empty() {
221 Ok(AnalysedTypeWithUnit::unit())
222 } else if vec.len() == 1 {
223 let first = &vec[0];
224 Ok(first.try_into()?)
225 } else {
226 Err("Cannot convert Sequence type to AnalysedType".to_string())
227 }
228 }
229 }
230 }
231}