Skip to main content

arora_module_core/
header.rs

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
28/// Creates a YAML header file named `module.yaml` describing the module.
29pub 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(&parameter.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(&parameter.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
113/// Reads the YAML header file at the given path
114/// and returns a description compatible with the registry.
115pub 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}