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#[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 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 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}