1use crate::{
2 resolve::{resolve_low_module, ModuleAndImports},
3 ImportAsset, ModuleDeclarationError,
4};
5use arora_registry::{ModuleFrozen, ReadableRegistry};
6use arora_types::record::{
7 module::frozen::ExportKind,
8 ty::{FrozenTy, PrimitiveKind},
9 Resolver,
10};
11use arora_types::{
12 module::low::{
13 Executor, ExportFunction, ExportSymbol, Header, ImportFunction, ImportSymbol, Parameter,
14 TypeRef,
15 },
16 ty::{
17 BOOLEAN_ID, F32_ID, F64_ID, I16_ID, I32_ID, I64_ID, I8_ID, STRING_ID, U16_ID, U32_ID,
18 U64_ID, U8_ID, UNIT_ID,
19 },
20 SemanticVersion,
21};
22use arora_vfs::{Directory, Entry, File};
23use semver::Version;
24use std::fs::read_to_string;
25use std::path::Path;
26use uuid::Uuid;
27
28pub fn generate_header_file(
30 id: &Uuid,
31 module: &ModuleFrozen,
32 imports: &[ImportAsset],
33 executor: &String,
34) -> Result<Directory, ModuleDeclarationError> {
35 let header = Header {
36 id: id.to_owned(),
37 name: module.name.to_owned(),
38 author: String::new(),
39 description: None,
40 license: String::new(),
41 version: SemanticVersion {
42 major: 0u32,
43 minor: 0u32,
44 patch: 0u32,
45 },
46 executor: Executor {
47 name: executor.to_owned(),
48 min_version: None,
49 max_version: None,
50 },
51 exports: module
52 .exports
53 .iter()
54 .map(|(export_id, export)| {
55 let ExportKind::Function(function) = &export.kind;
56 ExportSymbol::Function(ExportFunction {
57 id: export_id.to_owned(),
58 name: export.name.to_owned(),
59 parameters: function
60 .parameter_ordering
61 .iter()
62 .map(|parameter_id| {
63 let parameter = function.parameters.get(parameter_id).unwrap();
64 Parameter {
65 name: parameter.name.to_owned(),
66 ty: low_type_ref_from_unfrozen_ty(¶meter.ty),
67 mutable: parameter.mutable,
68 id: parameter_id.to_owned(),
69 default_value: None,
70 }
71 })
72 .collect(),
73 ret: low_type_ref_from_unfrozen_ty(&function.return_ty),
74 })
75 })
76 .collect(),
77 imports: imports
78 .iter()
79 .map(|import| {
80 let ExportKind::Function(import_function) = &import.import.kind;
81 ImportSymbol::Function(ImportFunction {
82 id: import.id.to_owned(),
83 name: import.import.name.to_owned(),
84 module: import.module_id.to_owned(),
85 parameters: import_function
86 .parameter_ordering
87 .iter()
88 .map(|parameter_id| {
89 let parameter = import_function.parameters.get(parameter_id).unwrap();
90 Parameter {
91 name: parameter.name.to_owned(),
92 ty: low_type_ref_from_unfrozen_ty(¶meter.ty),
93 mutable: parameter.mutable,
94 id: parameter_id.to_owned(),
95 default_value: None,
96 }
97 })
98 .collect(),
99 ret: low_type_ref_from_unfrozen_ty(&import_function.return_ty),
100 })
101 })
102 .collect(),
103 executable_mime: "".to_string(),
104 };
105 let mut result = Directory::new();
106 let header_file = File::new(serde_yaml::to_string(&header).unwrap().as_bytes());
107 result
108 .insert("module.yaml", Entry::File(header_file))
109 .map_err(ModuleDeclarationError::VfsError)?;
110 Ok(result)
111}
112
113pub async fn module_frozen_from_header_file<P: AsRef<Path>, R: ReadableRegistry + Resolver>(
116 header_path: P,
117 registry: &mut R,
118) -> Result<(Uuid, Version, ModuleAndImports), ModuleDeclarationError> {
119 let header: Header = serde_yaml::from_str(
120 &read_to_string(header_path.as_ref()).map_err(ModuleDeclarationError::IoError)?,
121 )
122 .map_err(|e| {
123 ModuleDeclarationError::Generic(format!(
124 "header file {} contains invalid yaml: {}",
125 header_path.as_ref().display(),
126 e
127 ))
128 })?;
129 Ok((
130 header.id.to_owned(),
131 header.version.to_owned().into(),
132 resolve_low_module(header, registry).await?,
133 ))
134}
135
136fn low_type_ref_from_unfrozen_ty(unfrozen: &FrozenTy) -> TypeRef {
137 match unfrozen {
138 FrozenTy::Primitive(primitive) => match primitive.kind {
139 PrimitiveKind::Unit => TypeRef::Scalar {
140 id: UNIT_ID.to_owned(),
141 },
142 PrimitiveKind::Boolean => TypeRef::Scalar {
143 id: BOOLEAN_ID.to_owned(),
144 },
145 PrimitiveKind::U8 => TypeRef::Scalar {
146 id: U8_ID.to_owned(),
147 },
148 PrimitiveKind::U16 => TypeRef::Scalar {
149 id: U16_ID.to_owned(),
150 },
151 PrimitiveKind::U32 => TypeRef::Scalar {
152 id: U32_ID.to_owned(),
153 },
154 PrimitiveKind::U64 => TypeRef::Scalar {
155 id: U64_ID.to_owned(),
156 },
157 PrimitiveKind::I8 => TypeRef::Scalar {
158 id: I8_ID.to_owned(),
159 },
160 PrimitiveKind::I16 => TypeRef::Scalar {
161 id: I16_ID.to_owned(),
162 },
163 PrimitiveKind::I32 => TypeRef::Scalar {
164 id: I32_ID.to_owned(),
165 },
166 PrimitiveKind::I64 => TypeRef::Scalar {
167 id: I64_ID.to_owned(),
168 },
169 PrimitiveKind::F32 => TypeRef::Scalar {
170 id: F32_ID.to_owned(),
171 },
172 PrimitiveKind::F64 => TypeRef::Scalar {
173 id: F64_ID.to_owned(),
174 },
175 PrimitiveKind::String => TypeRef::Scalar {
176 id: STRING_ID.to_owned(),
177 },
178 PrimitiveKind::ArrayBoolean => TypeRef::Array {
179 id: BOOLEAN_ID.to_owned(),
180 },
181 PrimitiveKind::ArrayU8 => TypeRef::Array {
182 id: U8_ID.to_owned(),
183 },
184 PrimitiveKind::ArrayU16 => TypeRef::Array {
185 id: U16_ID.to_owned(),
186 },
187 PrimitiveKind::ArrayU32 => TypeRef::Array {
188 id: U32_ID.to_owned(),
189 },
190 PrimitiveKind::ArrayU64 => TypeRef::Array {
191 id: U64_ID.to_owned(),
192 },
193 PrimitiveKind::ArrayI8 => TypeRef::Array {
194 id: I8_ID.to_owned(),
195 },
196 PrimitiveKind::ArrayI16 => TypeRef::Array {
197 id: I16_ID.to_owned(),
198 },
199 PrimitiveKind::ArrayI32 => TypeRef::Array {
200 id: I32_ID.to_owned(),
201 },
202 PrimitiveKind::ArrayI64 => TypeRef::Array {
203 id: I64_ID.to_owned(),
204 },
205 PrimitiveKind::ArrayF32 => TypeRef::Array {
206 id: F32_ID.to_owned(),
207 },
208 PrimitiveKind::ArrayF64 => TypeRef::Array {
209 id: F64_ID.to_owned(),
210 },
211 PrimitiveKind::ArrayString => TypeRef::Array {
212 id: STRING_ID.to_owned(),
213 },
214 },
215 FrozenTy::FrozenScalar(scalar) => TypeRef::Scalar {
216 id: scalar.reference.id.to_owned(),
217 },
218 FrozenTy::FrozenArray(array) => TypeRef::Array {
219 id: array.reference.id.to_owned(),
220 },
221 }
222}