1use crate::analysis::analysed_type::{
16 bool, chr, f32, f64, field, flags, handle, list, option, r#enum, record, s16, s32, s64, s8,
17 str, tuple, u16, u32, u64, u8, variant,
18};
19use crate::analysis::{AnalysedResourceId, AnalysedResourceMode, AnalysedType};
20use crate::protobuf::{
21 r#type, NameOptionTypePair, NameTypePair, PrimitiveType, Type, TypeEnum, TypeFlags, TypeHandle,
22 TypeList, TypeOption, TypePrimitive, TypeRecord, TypeResult, TypeTuple, TypeVariant,
23};
24use std::ops::Deref;
25
26impl TryFrom<&Type> for AnalysedType {
27 type Error = String;
28
29 fn try_from(typ: &Type) -> Result<Self, Self::Error> {
30 match &typ.r#type {
31 Some(r#type::Type::Primitive(primitive)) => {
32 match PrimitiveType::try_from(primitive.primitive) {
33 Ok(PrimitiveType::Bool) => Ok(bool()),
34 Ok(PrimitiveType::S8) => Ok(s8()),
35 Ok(PrimitiveType::U8) => Ok(u8()),
36 Ok(PrimitiveType::S16) => Ok(s16()),
37 Ok(PrimitiveType::U16) => Ok(u16()),
38 Ok(PrimitiveType::S32) => Ok(s32()),
39 Ok(PrimitiveType::U32) => Ok(u32()),
40 Ok(PrimitiveType::S64) => Ok(s64()),
41 Ok(PrimitiveType::U64) => Ok(u64()),
42 Ok(PrimitiveType::F32) => Ok(f32()),
43 Ok(PrimitiveType::F64) => Ok(f64()),
44 Ok(PrimitiveType::Chr) => Ok(chr()),
45 Ok(PrimitiveType::Str) => Ok(str()),
46 Err(_) => Err("Unknown primitive type".to_string()),
47 }
48 }
49 Some(r#type::Type::List(inner)) => {
50 let elem_type = inner
51 .elem
52 .as_ref()
53 .ok_or_else(|| "List element type is None".to_string())?;
54 let analysed_type = AnalysedType::try_from(elem_type.as_ref())?;
55 Ok(list(analysed_type)
56 .with_optional_name(inner.name.clone())
57 .with_optional_owner(inner.owner.clone()))
58 }
59 Some(r#type::Type::Tuple(inner)) => {
60 let elems = inner
61 .elems
62 .iter()
63 .map(AnalysedType::try_from)
64 .collect::<Result<Vec<_>, String>>()?;
65 Ok(tuple(elems)
66 .with_optional_name(inner.name.clone())
67 .with_optional_owner(inner.owner.clone()))
68 }
69 Some(r#type::Type::Record(inner)) => {
70 let fields = inner
71 .fields
72 .iter()
73 .map(|proto_field| {
74 let field_type = proto_field.typ.as_ref().ok_or_else(|| {
75 format!("Record field {} type is None", proto_field.name)
76 })?;
77 let analysed_type = AnalysedType::try_from(field_type)?;
78 Ok(field(&proto_field.name, analysed_type))
79 })
80 .collect::<Result<Vec<_>, String>>()?;
81 Ok(record(fields)
82 .with_optional_name(inner.name.clone())
83 .with_optional_owner(inner.owner.clone()))
84 }
85 Some(r#type::Type::Flags(inner)) => Ok(flags(
86 &inner
87 .names
88 .iter()
89 .map(|s| s.as_str())
90 .collect::<Vec<&str>>(),
91 )
92 .with_optional_name(inner.name.clone())
93 .with_optional_owner(inner.owner.clone())),
94 Some(r#type::Type::Enum(inner)) => Ok(r#enum(
95 &inner
96 .names
97 .iter()
98 .map(|s| s.as_str())
99 .collect::<Vec<&str>>(),
100 )
101 .with_optional_name(inner.name.clone())
102 .with_optional_owner(inner.owner.clone())),
103 Some(r#type::Type::Option(inner)) => {
104 let elem_type = inner
105 .elem
106 .as_ref()
107 .ok_or_else(|| "Option element type is None".to_string())?;
108 let analysed_type = AnalysedType::try_from(elem_type.as_ref())?;
109 Ok(option(analysed_type)
110 .with_optional_name(inner.name.clone())
111 .with_optional_owner(inner.owner.clone()))
112 }
113 Some(r#type::Type::Result(inner)) => {
114 let ok_type = inner
115 .ok
116 .as_ref()
117 .map(|tpe| AnalysedType::try_from(tpe.as_ref()))
118 .transpose()?;
119 let err_type = inner
120 .err
121 .as_ref()
122 .map(|tpe| AnalysedType::try_from(tpe.as_ref()))
123 .transpose()?;
124 Ok(AnalysedType::Result(crate::analysis::TypeResult {
125 ok: ok_type.map(Box::new),
126 err: err_type.map(Box::new),
127 name: inner.name.clone(),
128 owner: inner.owner.clone(),
129 })
130 .with_optional_name(inner.name.clone())
131 .with_optional_owner(inner.owner.clone()))
132 }
133 Some(r#type::Type::Variant(inner)) => {
134 let cases = inner
135 .cases
136 .iter()
137 .map(|case| {
138 let case_type =
139 case.typ.as_ref().map(AnalysedType::try_from).transpose()?;
140 Ok(crate::analysis::NameOptionTypePair {
141 name: case.name.clone(),
142 typ: case_type,
143 })
144 })
145 .collect::<Result<Vec<_>, String>>()?;
146 Ok(variant(cases)
147 .with_optional_name(inner.name.clone())
148 .with_optional_owner(inner.owner.clone()))
149 }
150 Some(r#type::Type::Handle(inner)) => {
151 let resource_mode = match inner.mode {
152 0 => Ok(AnalysedResourceMode::Owned),
153 1 => Ok(AnalysedResourceMode::Borrowed),
154 _ => Err("Invalid resource mode".to_string()),
155 }?;
156 Ok(handle(AnalysedResourceId(inner.resource_id), resource_mode)
157 .with_optional_name(inner.name.clone())
158 .with_optional_owner(inner.owner.clone()))
159 }
160 None => Err("Type is None".to_string()),
161 }
162 }
163}
164
165impl From<&AnalysedType> for Type {
166 fn from(value: &AnalysedType) -> Type {
167 let r#type = match value {
168 AnalysedType::Bool(_) => Some(r#type::Type::Primitive(TypePrimitive {
169 primitive: PrimitiveType::Bool as i32,
170 })),
171 AnalysedType::S8(_) => Some(r#type::Type::Primitive(TypePrimitive {
172 primitive: PrimitiveType::S8 as i32,
173 })),
174 AnalysedType::U8(_) => Some(r#type::Type::Primitive(TypePrimitive {
175 primitive: PrimitiveType::U8 as i32,
176 })),
177 AnalysedType::S16(_) => Some(r#type::Type::Primitive(TypePrimitive {
178 primitive: PrimitiveType::S16 as i32,
179 })),
180 AnalysedType::U16(_) => Some(r#type::Type::Primitive(TypePrimitive {
181 primitive: PrimitiveType::U16 as i32,
182 })),
183 AnalysedType::S32(_) => Some(r#type::Type::Primitive(TypePrimitive {
184 primitive: PrimitiveType::S32 as i32,
185 })),
186 AnalysedType::U32(_) => Some(r#type::Type::Primitive(TypePrimitive {
187 primitive: PrimitiveType::U32 as i32,
188 })),
189 AnalysedType::S64(_) => Some(r#type::Type::Primitive(TypePrimitive {
190 primitive: PrimitiveType::S64 as i32,
191 })),
192 AnalysedType::U64(_) => Some(r#type::Type::Primitive(TypePrimitive {
193 primitive: PrimitiveType::U64 as i32,
194 })),
195 AnalysedType::F32(_) => Some(r#type::Type::Primitive(TypePrimitive {
196 primitive: PrimitiveType::F32 as i32,
197 })),
198 AnalysedType::F64(_) => Some(r#type::Type::Primitive(TypePrimitive {
199 primitive: PrimitiveType::F64 as i32,
200 })),
201 AnalysedType::Chr(_) => Some(r#type::Type::Primitive(TypePrimitive {
202 primitive: PrimitiveType::Chr as i32,
203 })),
204 AnalysedType::Str(_) => Some(r#type::Type::Primitive(TypePrimitive {
205 primitive: PrimitiveType::Str as i32,
206 })),
207 AnalysedType::List(crate::analysis::TypeList { inner, name, owner }) => {
208 Some(r#type::Type::List(Box::new(TypeList {
209 elem: Some(Box::new(Type::from(inner.deref()))),
210 name: name.clone(),
211 owner: owner.clone(),
212 })))
213 }
214 AnalysedType::Tuple(crate::analysis::TypeTuple { items, name, owner }) => {
215 Some(r#type::Type::Tuple(TypeTuple {
216 elems: items
217 .iter()
218 .map(|analysed_type| analysed_type.into())
219 .collect(),
220 name: name.clone(),
221 owner: owner.clone(),
222 }))
223 }
224 AnalysedType::Record(crate::analysis::TypeRecord {
225 fields,
226 name,
227 owner,
228 }) => Some(r#type::Type::Record(TypeRecord {
229 fields: fields
230 .iter()
231 .map(|pair| NameTypePair {
232 name: pair.name.clone(),
233 typ: Some((&pair.typ).into()),
234 })
235 .collect(),
236 name: name.clone(),
237 owner: owner.clone(),
238 })),
239 AnalysedType::Flags(crate::analysis::TypeFlags { names, name, owner }) => {
240 Some(r#type::Type::Flags(TypeFlags {
241 names: names.clone(),
242 name: name.clone(),
243 owner: owner.clone(),
244 }))
245 }
246 AnalysedType::Enum(crate::analysis::TypeEnum { cases, name, owner }) => {
247 Some(r#type::Type::Enum(TypeEnum {
248 names: cases.clone(),
249 name: name.clone(),
250 owner: owner.clone(),
251 }))
252 }
253 AnalysedType::Option(crate::analysis::TypeOption { inner, name, owner }) => {
254 Some(r#type::Type::Option(Box::new(TypeOption {
255 elem: Some(Box::new(Type::from(inner.deref()))),
256 name: name.clone(),
257 owner: owner.clone(),
258 })))
259 }
260 AnalysedType::Result(crate::analysis::TypeResult {
261 ok,
262 err,
263 name,
264 owner,
265 }) => Some(r#type::Type::Result(Box::new(TypeResult {
266 ok: ok
267 .clone()
268 .map(|ok_type| Box::new(Type::from(ok_type.as_ref()))),
269 err: err
270 .clone()
271 .map(|err_type| Box::new(Type::from(err_type.as_ref()))),
272 name: name.clone(),
273 owner: owner.clone(),
274 }))),
275 AnalysedType::Variant(crate::analysis::TypeVariant { cases, name, owner }) => {
276 Some(r#type::Type::Variant(TypeVariant {
277 cases: cases
278 .iter()
279 .map(|pair| NameOptionTypePair {
280 name: pair.name.clone(),
281 typ: pair.typ.as_ref().map(|analysed_type| analysed_type.into()),
282 })
283 .collect(),
284 name: name.clone(),
285 owner: owner.clone(),
286 }))
287 }
288 AnalysedType::Handle(crate::analysis::TypeHandle {
289 resource_id,
290 mode,
291 name,
292 owner,
293 }) => Some(r#type::Type::Handle(TypeHandle {
294 resource_id: resource_id.0,
295 mode: match mode {
296 AnalysedResourceMode::Owned => 0,
297 AnalysedResourceMode::Borrowed => 1,
298 },
299 name: name.clone(),
300 owner: owner.clone(),
301 })),
302 };
303
304 Type { r#type }
305 }
306}