1pub mod rustfmt;
2
3use arora_module_core::{
4 header::generate_header_file, ImportAsset, ModuleAsset, ModuleDeclarationError,
5};
6use arora_registry::{
7 local::LocalRegistry, EnumerationFrozen, ModuleFrozen, ReadableRegistry, RegistryError,
8 StructureFrozen, TypeDefinitionFrozen,
9};
10use arora_types::record::ty::PrimitiveKind;
11use arora_types::record::{
12 module::frozen::{ExportKind, Parameter},
13 ty::{FrozenScalar, FrozenTy, Primitive},
14 FrozenReference,
15};
16use arora_types::record::{RecordType, Selector};
17use arora_types::ty::{
18 BOOLEAN_ID, F32_ID, F64_ID, I16_ID, I32_ID, I64_ID, I8_ID, STRING_ID, U16_ID, U32_ID, U64_ID,
19 U8_ID, UNIT_ID,
20};
21use arora_vfs::{Directory, Entry as VfsEntry, File, VfsError};
22use async_recursion::async_recursion;
23use convert_case::{Case, Casing};
24use derive_more::Display;
25use proc_macro2::Ident;
26use quote::{__private::TokenStream, format_ident, quote, ToTokens};
27use semver::VersionReq;
28use std::{
29 collections::{hash_map::Entry, HashMap, HashSet},
30 fmt::Display,
31 path,
32};
33use uuid::Uuid;
34
35pub async fn generate_sources(
39 assets: Vec<ModuleAsset>,
40 registry: &mut dyn ReadableRegistry,
41) -> Result<Directory, GenerationError> {
42 let mut result = generate_common_sources()?;
43 let mut imports_by_module: HashMap<Uuid, Vec<ImportAsset>> = HashMap::new();
44 let mut current_module = Option::<(Uuid, ModuleFrozen, String)>::None;
45 for asset in assets {
46 match asset {
47 ModuleAsset::Type(id, _, ty) => match ty {
48 TypeDefinitionFrozen::Primitive(_kind) => {}
49 TypeDefinitionFrozen::Enumeration(enumeration) => {
50 let parent_path = registry
51 .resolve_id(&enumeration.parent)
52 .await
53 .map_err(GenerationError::RegistryError)?;
54 let enum_sources = generate_enumeration_source(&id, &enumeration, &parent_path)
55 .map_err(GenerationError::VfsError)?;
56 result = result.merge_with(&enum_sources);
57 }
58 TypeDefinitionFrozen::Structure(structure) => {
59 let parent_path = registry
60 .resolve_id(&structure.parent)
61 .await
62 .map_err(GenerationError::RegistryError)?;
63 let struct_sources =
64 generate_structure_source(&id, &structure, registry, &parent_path).await?;
65 result = result.merge_with(&struct_sources);
66 }
67 },
68 ModuleAsset::Import(import) => {
69 match imports_by_module.entry(import.module_id.to_owned()) {
70 Entry::Occupied(mut entry) => entry.get_mut().push(import),
71 Entry::Vacant(entry) => {
72 entry.insert(vec![import]);
73 }
74 }
75 }
76 ModuleAsset::Module(ref module_id, _, ref module, ref executor) => {
77 let module_sources = generate_module_source(module, registry).await?;
78 result = result.merge_with(&module_sources);
79 assert!(current_module.is_none()); current_module =
81 Some((module_id.to_owned(), module.to_owned(), executor.to_owned()));
82 }
83 }
84 }
85
86 let mut all_imports = Vec::new();
87 for (module_id, ref mut imports) in imports_by_module {
88 let module_path = registry
90 .resolve_id(&module_id)
91 .await
92 .map_err(GenerationError::RegistryError)?;
93 let imports_sources =
94 generate_imports_from_module_source(&module_id, &module_path, imports, registry)
95 .await?;
96 result = result.merge_with(&imports_sources);
97 all_imports.append(imports);
98 }
99
100 let current_module = current_module.unwrap();
102 result = result.merge_with(
103 &generate_header_file(
104 ¤t_module.0,
105 ¤t_module.1,
106 &all_imports,
107 ¤t_module.2,
108 )
109 .map_err(GenerationError::ModuleDeclarationError)?,
110 );
111
112 let engine_functions_declarations = quote! {
117 #[cfg(target_arch = "wasm32")]
118 #[link(wasm_import_module = "env")]
119 extern "C" {
120 pub fn arora_dispatch(module_id: usize, method_id: usize, arg: usize) -> usize;
121 pub fn arora_dispatch_indirect(callable_id: u64) -> usize;
122 }
123
124 #[cfg(not(target_arch = "wasm32"))]
125 pub unsafe extern "C" fn arora_dispatch(
126 _module_id: usize,
127 _method_id: usize,
128 _arg: usize,
129 ) -> usize {
130 panic!(
131 "arora_dispatch called on the host; this module is meant to run as a wasm guest under the arora engine"
132 );
133 }
134
135 #[cfg(not(target_arch = "wasm32"))]
136 pub unsafe extern "C" fn arora_dispatch_indirect(_callable_id: u64) -> usize {
137 panic!(
138 "arora_dispatch_indirect called on the host; this module is meant to run as a wasm guest under the arora engine"
139 );
140 }
141 };
142 result = result.merge_with(
143 &token_stream_to_file("arora.rs", &engine_functions_declarations)
144 .map_err(GenerationError::VfsError)?,
145 );
146
147 generate_mods_in_directories(&mut result)?;
149
150 Ok(result)
151}
152
153pub fn generate_mods_in_directories(dir: &mut Directory) -> Result<bool, GenerationError> {
156 let mut mods = Vec::new();
157 for (path, entry) in dir.list_mut() {
158 if let VfsEntry::Directory(ref mut dir) = entry {
159 if generate_mods_in_directories(dir)? {
160 mods.push(path);
161 }
162 } else {
163 if path.ends_with(".rs") {
164 mods.push(path[..path.len() - 3].to_string());
165 }
166 }
167 }
168 if !mods.is_empty() {
169 let mods = mods
170 .into_iter()
171 .map(|mod_name| format_ident!("{}", mod_name.to_case(Case::Snake)));
172 let tokens = quote! {
173 #(pub mod #mods;)*
174 };
175 dir.insert("mod.rs", File::new(tokens.to_string()))
176 .map_err(GenerationError::VfsError)?;
177 Ok(true)
178 } else {
179 Ok(false)
180 }
181}
182
183pub fn generate_records(
187 assets: &[ModuleAsset],
188 registry: &LocalRegistry,
189) -> Result<Directory, GenerationError> {
190 use arora_registry::local::ROOT_ID;
191
192 let mut vfs = Directory::new();
193 vfs.ensure_directories(&path::PathBuf::from("folder"))
194 .map_err(GenerationError::VfsError)?;
195 vfs.ensure_directories(&path::PathBuf::from("enumeration"))
196 .map_err(GenerationError::VfsError)?;
197 vfs.ensure_directories(&path::PathBuf::from("structure"))
198 .map_err(GenerationError::VfsError)?;
199
200 let mut json_records: Vec<serde_json::Value> = vec![
201 serde_json::json!({"id": UNIT_ID.to_string(), "name": "unit"}),
202 serde_json::json!({"id": BOOLEAN_ID.to_string(), "name": "bool"}),
203 serde_json::json!({"id": U8_ID.to_string(), "name": "u8"}),
204 serde_json::json!({"id": U16_ID.to_string(), "name": "u16"}),
205 serde_json::json!({"id": U32_ID.to_string(), "name": "u32"}),
206 serde_json::json!({"id": U64_ID.to_string(), "name": "u64"}),
207 serde_json::json!({"id": I8_ID.to_string(), "name": "i8"}),
208 serde_json::json!({"id": I16_ID.to_string(), "name": "i16"}),
209 serde_json::json!({"id": I32_ID.to_string(), "name": "i32"}),
210 serde_json::json!({"id": I64_ID.to_string(), "name": "i64"}),
211 serde_json::json!({"id": F32_ID.to_string(), "name": "f32"}),
212 serde_json::json!({"id": F64_ID.to_string(), "name": "f64"}),
213 serde_json::json!({"id": STRING_ID.to_string(), "name": "str"}),
214 ];
215 let primitive_count = json_records.len();
219
220 let mut seen_folders: HashSet<Uuid> = HashSet::new();
221
222 for asset in assets {
223 let (id, version, ty) = match asset {
224 ModuleAsset::Type(id, version, ty) => (id, version, ty),
225 _ => continue,
226 };
227
228 match ty {
229 TypeDefinitionFrozen::Primitive(_) => {}
230 TypeDefinitionFrozen::Enumeration(e) => {
231 let yaml = serde_yaml::to_string(e)
232 .map_err(|err| GenerationError::Generic(err.to_string()))?;
233 let file_name = format!("{}@{}.yaml", id, version);
234 vfs.insert_at_path(
235 path::PathBuf::from("enumeration").join(&file_name),
236 File::new(yaml.as_bytes()),
237 )
238 .map_err(GenerationError::VfsError)?;
239
240 let mut entry = serde_json::json!({"id": id.to_string(), "name": e.name});
241 if e.parent != ROOT_ID {
242 entry["parent"] = serde_json::json!(e.parent.to_string());
243 }
244 json_records.push(entry);
245 add_folder_chain(
246 &e.parent,
247 registry,
248 &mut vfs,
249 &mut json_records,
250 &mut seen_folders,
251 )?;
252 }
253 TypeDefinitionFrozen::Structure(s) => {
254 let yaml = serde_yaml::to_string(s)
255 .map_err(|err| GenerationError::Generic(err.to_string()))?;
256 let file_name = format!("{}@{}.yaml", id, version);
257 vfs.insert_at_path(
258 path::PathBuf::from("structure").join(&file_name),
259 File::new(yaml.as_bytes()),
260 )
261 .map_err(GenerationError::VfsError)?;
262
263 let mut entry = serde_json::json!({"id": id.to_string(), "name": s.name});
264 if s.parent != ROOT_ID {
265 entry["parent"] = serde_json::json!(s.parent.to_string());
266 }
267 json_records.push(entry);
268 add_folder_chain(
269 &s.parent,
270 registry,
271 &mut vfs,
272 &mut json_records,
273 &mut seen_folders,
274 )?;
275 }
276 }
277 }
278
279 json_records[primitive_count..].sort_by(|a, b| a["id"].as_str().cmp(&b["id"].as_str()));
282
283 let records_json = serde_json::to_string(&json_records)
284 .map_err(|err| GenerationError::Generic(err.to_string()))?;
285 vfs.insert("records.json", File::new(records_json.as_bytes()))
286 .map_err(GenerationError::VfsError)?;
287
288 Ok(vfs)
289}
290
291fn add_folder_chain(
292 folder_id: &Uuid,
293 registry: &LocalRegistry,
294 vfs: &mut Directory,
295 json_records: &mut Vec<serde_json::Value>,
296 seen: &mut HashSet<Uuid>,
297) -> Result<(), GenerationError> {
298 use arora_registry::local::ROOT_ID;
299
300 if *folder_id == ROOT_ID || seen.contains(folder_id) {
301 return Ok(());
302 }
303
304 let Some((name, parent_opt)) = registry.record_name_and_parent(folder_id) else {
305 return Ok(());
306 };
307
308 seen.insert(*folder_id);
309
310 let yaml = match parent_opt {
311 Some(p) => format!("name: {}\nparent: {}\n", name, p),
312 None => format!("name: {}\n", name),
313 };
314 let file_name = format!("{}.yaml", folder_id);
315 vfs.insert_at_path(
316 path::PathBuf::from("folder").join(&file_name),
317 File::new(yaml.as_bytes()),
318 )
319 .map_err(GenerationError::VfsError)?;
320
321 let mut entry = serde_json::json!({"id": folder_id.to_string(), "name": name});
322 if let Some(p) = parent_opt {
323 if p != ROOT_ID {
324 entry["parent"] = serde_json::json!(p.to_string());
325 }
326 add_folder_chain(&p, registry, vfs, json_records, seen)?;
327 }
328 json_records.push(entry);
329
330 Ok(())
331}
332
333pub fn generate_common_sources() -> Result<Directory, GenerationError> {
334 let source = quote! {
335 use derive_more::Display;
336
337 #[derive(Display, Debug)]
338 pub struct DeserializationError {
339 #[display("deserialization error: {}", message)]
340 pub message: String,
341 }
342
343 impl std::error::Error for DeserializationError {}
344 };
345 token_stream_to_file("error.rs", &source).map_err(GenerationError::VfsError)
346}
347
348pub fn generate_enumeration_source(
353 id: &Uuid,
354 enumeration: &EnumerationFrozen,
355 parent_path: &str,
356) -> Result<Directory, VfsError> {
357 let uses = quote! {
358 use crate::arora_generated::error::DeserializationError;
359 use arora_buffers::*;
360 use arora_types::value::{ConversionError, Enumeration, Value};
361 use uuid::Uuid;
362 };
363
364 let name = &enumeration.name;
366 let enum_name = name.to_case(Case::UpperCamel);
367 let enum_ident = type_ident(&enum_name);
368 let variants = enumeration.variants.iter();
369 let enum_contents = variants.clone().map(|(_, variant)| {
370 let variant_ident = format_ident!("{}", variant.name.to_case(Case::UpperCamel));
371 quote! { #variant_ident, }
372 });
373 let enum_declaration = quote! {
374 #[derive(Debug, PartialEq, Clone)]
375 pub enum #enum_ident {
376 #(#enum_contents)*
377 }
378 };
379
380 let enum_id = id.to_string();
382 let enum_id_bytes = RawUuidValue(id);
383 let enum_upper_name = format_ident!("{}", enum_name.to_case(Case::UpperSnake));
384 let enum_const_id_ident = format_ident!("{}_ENUM_RAW_ID", enum_upper_name);
385 let enum_const_id_doc = format!("{}: {}", enum_name, enum_id);
386 let enum_id_declaration = quote! {
387 #[doc = #enum_const_id_doc]
388 pub const #enum_const_id_ident: [u8; 16] = #enum_id_bytes;
389 };
390
391 let variant_id_declarations = variants.clone().map(|(id, variant)| {
392 let id_string = id.to_string();
393 let id_bytes = RawUuidValue(id);
394 let variant_const_id_ident = enum_variant_const_id_ident(&enum_name, &variant.name);
395 let variant_doc = format!(
396 "{}: {}",
397 enum_variant_ident(&enum_name, &variant.name),
398 id_string
399 );
400 quote! {
401 #[doc = #variant_doc]
402 pub const #variant_const_id_ident: [u8; 16] = #id_bytes;
403 }
404 });
405
406 let serialization_match_branches = variants.clone().map(|(_, variant)| {
408 let variant_ident = enum_variant_ident(&enum_name, &variant.name);
409 let id_ident = enum_variant_const_id_ident(&enum_name, &variant.name);
410 quote! {
411 #variant_ident => #id_ident.as_slice(),
412 }
413 });
414
415 let into_impl = generate_into_impl(&enum_ident);
416 let serialization = quote! {
417 #into_impl
418
419 pub fn serialize_to_writer(value: &#enum_ident, writer: &mut BufferWriter) {
420 let enumeration_id = #enum_const_id_ident.as_slice();
421 let variant_id = match value {
422 #(#serialization_match_branches)*
423 };
424 writer.add_enumeration_value(enumeration_id, variant_id);
425 writer.add_unit();
426 }
427 };
428
429 let deserialization_cases = variants.clone().map(|(_, variant)| {
431 let variant_const_id_ident = enum_variant_const_id_ident(&enum_name, &variant.name);
432 let variant_ident = enum_variant_ident(&enum_name, &variant.name);
433 quote! {
434 #variant_const_id_ident => Ok(#variant_ident),
435 }
436 });
437
438 let deserialization = quote! {
439 impl TryFrom<&[u8]> for #enum_ident {
440 type Error = DeserializationError;
441
442 fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
443 let mut reader = BufferReader::new(buffer);
444 return deserialize_from_reader(&mut reader, true)
445 }
446 }
447
448 pub fn deserialize_from_reader(reader: &mut BufferReader, check_type: bool) -> Result<#enum_ident, DeserializationError> {
449 if check_type {
450 let type_raw_id_opt = reader.next_type();
451 if type_raw_id_opt.is_none() {
452 return Err(DeserializationError{ message: "missing next type information".to_string() })
453 }
454 if type_raw_id_opt.unwrap() != TYPE_ENUMERATION {
455 return Err(DeserializationError{ message: "next type is not an enumeration".to_string() })
456 }
457 }
458
459 if #enum_const_id_ident != reader.get_structure_field() {
460 return Err(DeserializationError{ message: "missing variant information".to_string() })
461 }
462
463 let variant_raw_id = reader.get_enumeration_value_raw();
464 match variant_raw_id.try_into().expect("enum id is of unexpected length") {
465 #(#deserialization_cases)*
466 _ => Err(DeserializationError{ message: "unexpected variant".to_string() })
467 }
468 }
469 };
470
471 let to_value_cases = variants.clone().map(|(_, variant)| {
473 let variant_ident = enum_variant_ident(&enum_name, &variant.name);
474 let id_ident = enum_variant_const_id_ident(&enum_name, &variant.name);
475 quote! {
476 #variant_ident => Value::Enumeration(Enumeration {
477 id: Uuid::from_bytes(#enum_const_id_ident),
478 variant_id: Uuid::from_bytes(#id_ident),
479 value: Box::new(Value::Unit),
480 }),
481 }
482 });
483
484 let to_value = quote! {
485 impl Into<Value> for #enum_ident {
486 fn into(self) -> Value {
487 match self {
488 #(#to_value_cases)*
489 }
490 }
491 }
492 };
493
494 let from_value_cases = variants.map(|(_, variant)| {
496 let variant_const_id_ident = enum_variant_const_id_ident(&enum_name, &variant.name);
497 let variant_ident = enum_variant_ident(&enum_name, &variant.name);
498 quote! {
499 #variant_const_id_ident => Ok(#variant_ident),
500 }
501 });
502
503 let from_value = quote! {
504 impl TryFrom<Value> for #enum_ident {
505 type Error = ConversionError;
506 fn try_from(value: Value) -> Result<Self, Self::Error> {
507 if let Value::Enumeration(as_enum) = value {
508 if *as_enum.id.as_bytes() == #enum_const_id_ident {
509 match *as_enum.variant_id.as_bytes() {
510 #(#from_value_cases)*
511 _ => Err(Self::Error { message: "unexpected variant".to_string() }),
512 }
513 } else {
514 Err(Self::Error {
515 message: "unexpected enum type ID".to_string(),
516 })
517 }
518 } else {
519 Err(Self::Error {
520 message: "unexpected kind".to_string(),
521 })
522 }
523 }
524 }
525 };
526
527 let type_source = quote! {
529 #uses
530 #enum_declaration
531 #serialization
532 #deserialization
533 #to_value
534 #from_value
535 #enum_id_declaration
536 #(#variant_id_declarations)*
537 };
538
539 let base_file_name = enumeration.name.to_case(Case::Snake);
540 let file_path = if parent_path.is_empty() {
541 format!("{}.rs", base_file_name)
542 } else {
543 format!("{}/{}.rs", parent_path.replace('.', "/"), base_file_name)
544 };
545 token_stream_to_file(file_path, &type_source)
546}
547
548pub async fn generate_structure_source(
553 id: &Uuid,
554 structure: &StructureFrozen,
555 registry: &mut dyn ReadableRegistry,
556 parent_path: &str,
557) -> Result<Directory, GenerationError> {
558 let name = &structure.name;
560 let struct_ident = type_ident(name);
561 let mut field_declarations = Vec::new();
562 for (_, field) in &structure.fields {
563 let field_ident = variable_ident(&field.name);
564 let field_type_ident =
565 type_ident_from_frozen(&field.ty, registry, PrefixWithMod::Yes).await?;
566 field_declarations.push(quote! { pub #field_ident: #field_type_ident });
567 }
568 let struct_declaration = quote! {
569 pub struct #struct_ident {
570 #(#field_declarations),*
571 }
572 };
573
574 let id_str = id.to_string();
576 let id_bytes = RawUuidValue(id);
577 let upper_name = format_ident!("{}", name.to_case(Case::UpperSnake));
578 let const_id_ident = format_ident!("{}_STRUCT_RAW_ID", upper_name);
579 let const_id_doc = format!("{}: {}", name, id_str);
580 let id_declaration = quote! {
581 #[doc = #const_id_doc]
582 pub const #const_id_ident: [u8; 16] = #id_bytes;
583 };
584
585 let field_id_declarations = structure.fields.iter().map(|(field_id, field)| {
586 let field_id_bytes = RawUuidValue(field_id);
587 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
588 let field_doc = format!("{}: {}", struct_field_ident(name, &field.name), field_id,);
589 quote! {
590 #[doc = #field_doc]
591 pub const #field_const_id_ident: [u8; 16] = #field_id_bytes;
592 }
593 });
594
595 let mut fields_serialization = Vec::new();
597 for (_, field) in &structure.fields {
598 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
599 let field_ident = variable_ident(&field.name);
600 let value_expression = quote! { value.#field_ident };
601 let serialize =
602 generate_serialize_from_frozen(&field.ty, value_expression, registry).await?;
603 fields_serialization.push(quote! {
604 writer.add_structure_field(&#field_const_id_ident);
605 #serialize
606 });
607 }
608 let field_count = fields_serialization.len() as u32;
609
610 let into_impl = generate_into_impl(&struct_ident);
611 let serialization = quote! {
612 #into_impl
613
614 pub fn serialize_to_writer(value: &#struct_ident, writer: &mut BufferWriter) {
615 let structure_id = #const_id_ident.as_slice();
616 writer.begin_structure(structure_id, #field_count);
617 #(#fields_serialization)*
618 }
619 };
620
621 let mut field_variable_declarations = Vec::new();
625 for (_, field) in &structure.fields {
626 let variable_ident = struct_field_intermediate_variable_ident(name, &field.name);
627 let type_ident = type_ident_from_frozen(&field.ty, registry, PrefixWithMod::Yes).await?;
628 field_variable_declarations
629 .push(quote! { let mut #variable_ident: Option<#type_ident> = None; });
630 }
631
632 let mut deserialization_cases = Vec::new();
633 for (_, field) in &structure.fields {
634 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
635 let field_variable_ident = struct_field_intermediate_variable_ident(name, &field.name);
636 let deserialize =
637 generate_deserialize_from_frozen(&field.ty, registry, CheckType::Yes).await?;
638 deserialization_cases.push(quote! {
639 if field_raw_id == #field_const_id_ident {
640 #field_variable_ident = Some(#deserialize);
641 }
642 });
643 }
644
645 let struct_field_assignment = structure.fields.iter().map(|(_, field)| {
646 let field_ident = variable_ident(&field.name);
647 let variable_ident = struct_field_intermediate_variable_ident(name, &field.name);
648 quote! { #field_ident: #variable_ident.unwrap() }
649 });
650
651 let try_from_impl = generate_try_from_impl(&struct_ident);
652 let expected_field_count = structure.fields.len();
653 let deserialization = quote! {
654 #try_from_impl
655
656 pub fn deserialize_from_reader(reader: &mut BufferReader, check_type: bool) -> Result<#struct_ident, DeserializationError> {
657 let field_count = if check_type {
658 let type_raw_id_opt = reader.next_type();
659 if type_raw_id_opt.is_none() {
660 return Err(DeserializationError{ message: "missing next type information".to_string() })
661 }
662 if type_raw_id_opt.unwrap() != TYPE_STRUCTURE {
663 return Err(DeserializationError{ message: "next type is not a structure".to_string() })
664 }
665 let (structure_raw_id, field_count) = reader.get_structure();
666 if #const_id_ident != structure_raw_id {
667 return Err(DeserializationError{ message: "structure id does not match".to_string() })
668 }
669 field_count
670 } else {
671 reader.get_structure_raw()
672 };
673 if #expected_field_count != field_count as usize {
674 return Err(DeserializationError{
675 message: format!("expected {} fields, found {}", #expected_field_count, field_count)
676 })
677 }
678
679 #(#field_variable_declarations)*
680 for _ in 0..field_count {
681 let field_raw_id = reader.get_structure_field();
682 #(#deserialization_cases) else* else {
683 return Err(DeserializationError {
684 message: format!("unexpected struct field {}", Uuid::from_slice(field_raw_id).unwrap().to_string())
685 })
686 }
687 }
688
689 Ok(#struct_ident {
690 #(#struct_field_assignment,)*
691 })
692 }
693 };
694
695 let mut to_value_fields = Vec::new();
699 for (_, field) in &structure.fields {
700 let field_ident = variable_ident(&field.name);
701 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
702 let field_value = generate_value_from_frozen(&field.ty, quote! { self.#field_ident });
703 to_value_fields.push(quote! {
704 StructureField {
705 id: Uuid::from_bytes(#field_const_id_ident),
706 value: Box::new(#field_value),
707 }
708 });
709 }
710 let to_value = quote! {
711 impl Into<Value> for #struct_ident {
712 fn into(self) -> Value {
713 Value::Structure(Structure {
714 id: Uuid::from_bytes(#const_id_ident),
715 fields: vec![#(#to_value_fields),*],
716 })
717 }
718 }
719 };
720
721 let mut from_value_field_vars = Vec::new();
722 let mut from_value_cases = Vec::new();
723 let mut from_value_assignments = Vec::new();
724 for (_, field) in &structure.fields {
725 let field_ident = variable_ident(&field.name);
726 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
727 let field_var = struct_field_intermediate_variable_ident(name, &field.name);
728 let field_type_ident =
729 type_ident_from_frozen(&field.ty, registry, PrefixWithMod::Yes).await?;
730 let extract = generate_field_from_value_frozen(
731 &field.ty,
732 quote! { *field.value },
733 &field.name,
734 registry,
735 )
736 .await?;
737 from_value_field_vars
738 .push(quote! { let mut #field_var: Option<#field_type_ident> = None; });
739 from_value_cases.push(quote! { #field_const_id_ident => { #field_var = Some(#extract); } });
740 let missing_message = format!("missing field {}", field.name);
741 from_value_assignments.push(quote! {
742 #field_ident: #field_var.ok_or_else(|| ConversionError { message: #missing_message.to_string() })?
743 });
744 }
745 let from_value = quote! {
746 impl TryFrom<Value> for #struct_ident {
747 type Error = ConversionError;
748 fn try_from(value: Value) -> Result<Self, Self::Error> {
749 if let Value::Structure(as_struct) = value {
750 if *as_struct.id.as_bytes() != #const_id_ident {
751 return Err(ConversionError { message: "unexpected structure type ID".to_string() });
752 }
753 #(#from_value_field_vars)*
754 for field in as_struct.fields {
755 match *field.id.as_bytes() {
756 #(#from_value_cases)*
757 _ => return Err(ConversionError { message: "unexpected struct field".to_string() }),
758 }
759 }
760 Ok(#struct_ident {
761 #(#from_value_assignments,)*
762 })
763 } else {
764 Err(ConversionError { message: "unexpected kind".to_string() })
765 }
766 }
767 }
768 };
769
770 let type_source = quote! {
771 use arora_buffers::*;
772 use uuid::Uuid;
773 use arora_types::value::{ConversionError, Structure, StructureField, Value};
774 use crate::arora_generated::error::DeserializationError;
775 #struct_declaration
776 #serialization
777 #deserialization
778 #to_value
779 #from_value
780 #id_declaration
781 #(#field_id_declarations)*
782 };
783
784 let base_file_name = structure.name.to_case(Case::Snake);
785 let file_path = if parent_path.is_empty() {
786 format!("{}.rs", base_file_name)
787 } else {
788 format!("{}/{}.rs", parent_path.replace('.', "/"), base_file_name)
789 };
790 token_stream_to_file(file_path, &type_source).map_err(GenerationError::VfsError)
791}
792
793async fn generate_imports_from_module_source(
797 module_id: &Uuid,
798 module_path: &str,
799 imports: &Vec<ImportAsset>,
800 registry: &mut dyn ReadableRegistry,
801) -> Result<Directory, GenerationError> {
802 let uses = {
804 let mut dependencies = HashSet::<&FrozenReference>::new();
805 for import in imports {
806 import.import.dependencies(&mut dependencies);
807 }
808 let mut uses = Vec::new();
809 for dep in dependencies {
810 let dep_selector = Selector::Id(dep.id);
811 let type_def = match registry
812 .get_type(
813 &dep_selector,
814 &VersionReq::parse(dep.version.to_string().as_str()).unwrap(),
815 )
816 .await
817 {
818 Ok(TypeDefinitionFrozen::Primitive(_)) => continue,
819 Ok(type_definition) => type_definition,
820 Err(RegistryError::NotAType { selector: _ }) => continue,
821 Err(err) => return Err(GenerationError::RegistryError(err)),
822 };
823 let type_ident =
824 type_ident_from_definition(&type_def, &dep.id, registry, PrefixWithMod::Yes)
825 .await?;
826 uses.push(type_ident);
827 }
828 uses
829 };
830
831 let splitted_module_path: Vec<&str> = module_path.split(".").collect();
832 let module_name = splitted_module_path.last().unwrap();
833
834 let module_const_id_ident =
836 format_ident!("{}_MODULE_ID", module_name.to_case(Case::UpperSnake),);
837 let module_id_declaration = generate_const_id_declaration(
838 &module_name.to_string(),
839 &module_const_id_ident,
840 module_id,
841 Public::No,
842 );
843
844 let mut functions_declarations = Vec::<TokenStream>::new();
846 for import in imports {
847 let ExportKind::Function(function_symbol) = &import.import.kind;
848 let function_name = &import.import.name;
849 let function_ident = format_ident!("{}", function_name);
850 let mut parameters_declarations = Vec::new();
851 for param in function_symbol.parameters.values() {
852 let maybe_mut = if param.mutable {
853 quote! { mut }
854 } else {
855 quote! {}
856 };
857 let param_name_ident = format_ident!("{}", param.name);
858 let param_type_ident =
859 type_ident_from_frozen(¶m.ty, registry, PrefixWithMod::Yes).await?;
860 parameters_declarations.push(quote! {
861 #maybe_mut #param_name_ident: #param_type_ident
862 });
863 }
864 let ret_type_ident =
865 type_ident_from_frozen(&function_symbol.return_ty, registry, PrefixWithMod::Yes)
866 .await?;
867
868 let function_const_id_ident = function_const_id_ident(function_name);
871 let function_id_declaration = generate_const_id_declaration(
872 function_name,
873 &function_const_id_ident,
874 &import.id,
875 Public::No,
876 );
877 let param_ids_declarations = {
878 let mut param_ids_declarations = Vec::new();
879 for (id, param) in &function_symbol.parameters {
880 param_ids_declarations.push(generate_const_id_declaration(
881 &format!("{}.{}", function_name, param.name),
882 &function_param_const_id_ident(function_name, ¶m.name),
883 id,
884 Public::No,
885 ));
886 }
887 param_ids_declarations
888 };
889
890 let ids_declaration = quote! {
891 #function_id_declaration
892 #(#param_ids_declarations)*
893 };
894
895 let add_args = {
899 let mut add_args = Vec::new();
900 for param in function_symbol.parameters.values() {
901 let function_param_const_id_ident =
902 function_param_const_id_ident(function_name, ¶m.name);
903 let param_name_ident = format_ident!("{}", param.name);
904 let serialize_arg = generate_serialize_from_frozen(
905 ¶m.ty,
906 param_name_ident.into_token_stream(),
907 registry,
908 )
909 .await?;
910 add_args.push(quote! {
911 writer.add_structure_field(#function_param_const_id_ident.as_slice());
912 #serialize_arg;
913 });
914 }
915 add_args
916 };
917 let nof_args = add_args.len() as u32;
918 let prepare_call_structure = quote! {
919 let mut writer = BufferWriter::new();
920 writer.begin_structure(#function_const_id_ident.as_slice(), #nof_args);
921 #(#add_args)*
922 let arg = writer.finalize();
923 };
924
925 let perform_call = quote! {
927 let result_buffer_addr = unsafe {
928 arora_dispatch(
929 #module_const_id_ident.as_ptr() as usize,
930 #function_const_id_ident.as_ptr() as usize,
931 arg.as_ptr() as usize,
932 )
933 };
934 };
935
936 let prepare_parsing = quote! {
938 let result_buffer_ptr = result_buffer_addr as *const u8;
939 let input_size_bytes: &[u8; 4] =
940 unsafe { std::slice::from_raw_parts(result_buffer_ptr, BUFFER_SIZE_SIZE) }
941 .try_into()
942 .expect("input is too small");
943 let input_size = u32::from_le_bytes(*input_size_bytes) as usize;
944 let input =
945 unsafe { std::slice::from_raw_parts(result_buffer_ptr, BUFFER_SIZE_SIZE + input_size) };
946 let mut reader = BufferReader::new(&input);
947 };
948
949 let check_result_struct = quote! {
951 let type_raw_id_opt = reader.next_type();
952 assert!(!type_raw_id_opt.is_none());
953 assert_eq!(type_raw_id_opt.unwrap(), TYPE_STRUCTURE);
954 let (result_struct_id, result_field_count) = reader.get_structure();
955 assert_eq!(result_struct_id, #function_const_id_ident);
956 };
957
958 let deserialize_ret =
963 generate_deserialize_from_frozen(&function_symbol.return_ty, registry, CheckType::Yes)
964 .await?;
965
966 let process_params = if nof_args > 1 {
967 let declare_mutable_params = {
968 let mut declare_mutable_params = Vec::new();
969 for param in function_symbol.parameters.values() {
970 if param.mutable {
971 let param_name_ident = format_ident!("{}", param.name);
972 declare_mutable_params.push(quote! {
973 let mut #param_name_ident = None;
974 })
975 }
976 }
977 declare_mutable_params
978 };
979
980 let deserialize_params = {
981 let mut deserialize_params = Vec::new();
982 for param in function_symbol.parameters.values() {
983 if param.mutable {
984 let param_name_ident = format_ident!("{}", param.name);
985 let function_param_const_id_ident =
986 function_param_const_id_ident(function_name, ¶m.name);
987 let deserialize_param =
988 generate_deserialize_from_frozen(¶m.ty, registry, CheckType::Yes)
989 .await?;
990 deserialize_params.push(quote! {
991 x if *x == #function_param_const_id_ident => *#param_name_ident = #deserialize_param,
992 });
993 }
994 }
995 deserialize_params
996 };
997
998 quote! {
999 #(#declare_mutable_params)*
1000 for _i in 1u32..#nof_args {
1001 let next_field_id = reader.get_structure_field();
1002 match next_field_id {
1003 #(#deserialize_params)*
1004 x => panic!("found unexpected mutated argument id: {:#?}", x),
1005 }
1006 }
1007 }
1008 } else {
1009 quote! {}
1010 };
1011
1012 let process_result = quote! {
1013 assert_eq!(result_field_count, #nof_args);
1014 let first_field_id = reader.get_structure_field();
1015 assert_eq!(first_field_id, #function_const_id_ident);
1016 let ret = #deserialize_ret;
1017 #process_params
1018 ret
1019 };
1020
1021 functions_declarations.push(quote! {
1023 pub fn #function_ident (#(#parameters_declarations),*) -> #ret_type_ident {
1024 #ids_declaration
1025 #prepare_call_structure
1026 #perform_call
1027 #prepare_parsing
1028 #check_result_struct
1029 #process_result
1030 }
1031 });
1032 }
1033
1034 let source = quote! {
1036 #(#uses)*
1037 use arora_buffers::*;
1038 use crate::arora_generated::arora::arora_dispatch;
1039 #module_id_declaration
1040 #(#functions_declarations)*
1041 };
1042
1043 let file_path = splitted_module_path
1044 .iter()
1045 .map(|name| name.to_case(Case::Snake))
1046 .fold(String::new(), |acc, name| {
1047 if acc.is_empty() {
1048 name
1049 } else {
1050 format!("{}/{}", acc, name)
1051 }
1052 })
1053 + ".rs";
1054 token_stream_to_file(file_path, &source).map_err(GenerationError::VfsError)
1055}
1056
1057async fn generate_module_source(
1059 module: &ModuleFrozen,
1060 registry: &mut dyn ReadableRegistry,
1061) -> Result<Directory, GenerationError> {
1062 let exports = &module.exports;
1064 let use_functions = exports
1065 .values()
1066 .map(|export| format_ident!("{}", export.name));
1067
1068 let function_ids = exports.iter().flat_map(|(function_id, export)| {
1070 let ExportKind::Function(function_symbol) = &export.kind;
1071 let mut id_declarations = Vec::with_capacity(function_symbol.parameters.len() + 1);
1072 id_declarations.push(generate_const_id_declaration(
1073 &export.name,
1074 &function_const_id_ident(&export.name),
1075 function_id,
1076 Public::Yes,
1077 ));
1078 for (param_id, param) in &function_symbol.parameters {
1079 id_declarations.push(generate_const_id_declaration(
1080 &format!("{}.{}", export.name, param.name),
1081 &function_param_const_id_ident(&export.name, ¶m.name),
1082 param_id,
1083 Public::Yes,
1084 ));
1085 }
1086 id_declarations
1087 });
1088
1089 let function_declarations = {
1091 let mut function_declarations = Vec::new();
1092 for (export_id, export) in exports {
1093 let function_ident = format_ident!("{}", export.name);
1094 let ExportKind::Function(function_symbol) = &export.kind;
1095 let const_id_ident = function_const_id_ident(&export.name);
1096
1097 let call_check = quote! {
1098 let mut reader = BufferReader::new(&input);
1099 let type_raw_id_opt = reader.next_type();
1100 if type_raw_id_opt.is_none() {
1101 return Err("input is empty".to_string());
1102 }
1103 if type_raw_id_opt.unwrap() != TYPE_STRUCTURE {
1104 return Err(format!("expected structure input, got type {:?}", type_raw_id_opt));
1105 }
1106 let (structure_raw_id, field_count) = reader.get_structure();
1107 if structure_raw_id != &#const_id_ident {
1108 return Err("function id mismatch in input".to_string());
1109 }
1110 };
1111
1112 let param_declarations = {
1113 let mut param_declarations = Vec::new();
1114 for (param_id, param) in &function_symbol.parameters {
1115 let param_var_ident = param_ident(param_id, param);
1116 let param_type_ident =
1117 type_ident_from_frozen(¶m.ty, registry, PrefixWithMod::Yes).await?;
1118 param_declarations.push(
1119 quote! { let mut #param_var_ident: Option<#param_type_ident> = None; },
1120 );
1121 }
1122 param_declarations
1123 };
1124
1125 let deserialization_cases = {
1126 let mut deserialization_cases = Vec::new();
1127 for (param_id, param) in &function_symbol.parameters {
1128 let param_const_id_ident =
1129 function_param_const_id_ident(&export.name, ¶m.name);
1130 let param_var_ident = param_ident(param_id, param);
1131 let deserialize =
1132 generate_deserialize_from_frozen(¶m.ty, registry, CheckType::YesResult)
1133 .await?;
1134 deserialization_cases.push(quote! {
1135 if field_raw_id == #param_const_id_ident {
1136 #param_var_ident = Some(#deserialize);
1137 }
1138 });
1139 }
1140 deserialization_cases
1141 };
1142
1143 let deserialize_params = if function_symbol.parameters.is_empty() {
1144 quote! {
1145 if field_count != 0 {
1146 return Err(format!("expected 0 parameters but got {}", field_count));
1147 }
1148 }
1149 } else {
1150 quote! {
1151 #(#param_declarations)*
1152 for _ in 0..field_count {
1153 let field_raw_id = reader.get_structure_field();
1154 #(#deserialization_cases else)* {
1155 return Err(format!("unexpected parameter {:?}", field_raw_id));
1156 }
1157 }
1158 }
1159 };
1160
1161 let param_args = function_symbol.parameter_ordering.iter().map(|param_id| {
1162 let param = function_symbol.parameters.get(param_id).unwrap();
1163 let param_var_ident = param_ident(param_id, param);
1164 if param.mutable {
1165 quote! { &mut #param_var_ident }
1166 } else {
1167 quote! { #param_var_ident }
1168 }
1169 });
1170
1171 let call_and_write_result = {
1172 let result_ident = match &function_symbol.return_ty {
1173 FrozenTy::Primitive(Primitive { kind }) if *kind == PrimitiveKind::Unit => {
1174 quote! { _ }
1175 }
1176 _ => quote! { result },
1177 };
1178 let serialize_result = generate_serialize_from_frozen(
1179 &function_symbol.return_ty,
1180 result_ident.clone(),
1181 registry,
1182 )
1183 .await?;
1184 quote! {
1185 let #result_ident = #function_ident (#(#param_args),*);
1186 #serialize_result;
1187 }
1188 };
1189
1190 let write_mutated_params: Vec<TokenStream> = {
1191 let mut write_mutated_params = Vec::new();
1192 for (param_id, param) in &function_symbol.parameters {
1193 if param.mutable {
1194 let param_var_ident = param_ident(param_id, param);
1195 let param_const_id_ident =
1196 function_param_const_id_ident(&export.name, ¶m.name);
1197 let serialize_param = generate_serialize_from_frozen(
1198 ¶m.ty,
1199 quote! {#param_var_ident.unwrap()},
1200 registry,
1201 )
1202 .await?;
1203 write_mutated_params.push(quote! {
1204 writer.add_structure_field(&#param_const_id_ident);
1205 #serialize_param;
1206 });
1207 }
1208 }
1209 write_mutated_params
1210 };
1211 let nof_mutated_params = write_mutated_params.len();
1212
1213 let uuid_suffix = export_id.to_string().replace("-", "_");
1214 let arora_function_ident = format_ident!("arora_function_{}", uuid_suffix);
1215 let doc = export.name.to_string();
1216 function_declarations.push(quote! {
1217 #[doc = #doc]
1218 #[no_mangle]
1219 pub extern "C" fn #arora_function_ident (input_addr: usize) -> usize {
1220 let input_ptr = input_addr as *const u8;
1221 const INPUT_SIZE_SIZE: usize = std::mem::size_of::<u32>();
1222 let input_size_bytes: &[u8; 4] = unsafe {
1223 std::slice::from_raw_parts(input_ptr, INPUT_SIZE_SIZE)
1224 }.try_into().expect("input is too small");
1225 let input_size = u32::from_le_bytes(*input_size_bytes) as usize;
1226 let input = unsafe {
1227 std::slice::from_raw_parts(input_ptr, INPUT_SIZE_SIZE + input_size)
1228 };
1229 let _result: ::std::result::Result<::std::boxed::Box<[u8]>, ::std::string::String> = (|| {
1230 #call_check
1231 #deserialize_params
1232 let mut writer = BufferWriter::new();
1233 writer.begin_structure(&#const_id_ident, (#nof_mutated_params + 1) as u32);
1234 writer.add_structure_field(&#const_id_ident);
1235 #call_and_write_result
1236 #(#write_mutated_params)*
1237 ::std::result::Result::Ok(writer.finalize())
1238 })();
1239 match _result {
1240 ::std::result::Result::Ok(buf) => ::std::boxed::Box::leak(buf).as_ptr() as usize,
1241 ::std::result::Result::Err(msg) => {
1242 let mut writer = BufferWriter::new();
1243 writer.add_error(&msg);
1244 ::std::boxed::Box::leak(writer.finalize()).as_ptr() as usize
1245 }
1246 }
1247 }
1248 });
1249 }
1250 function_declarations
1251 };
1252
1253 let source = quote! {
1255 use arora_buffers::*;
1256 use crate::{arora_generated, #(#use_functions),*};
1257 #(#function_declarations)*
1258 #(#function_ids)*
1259 };
1260 token_stream_to_file("export.rs", &source).map_err(GenerationError::VfsError)
1261}
1262
1263pub fn generate_into_impl(type_ident: &Ident) -> TokenStream {
1264 quote! {
1265 impl Into<Box<[u8]>> for #type_ident {
1266 fn into(self) -> Box<[u8]> {
1267 let mut writer = BufferWriter::new();
1268 serialize_to_writer(&self, &mut writer);
1269 writer.finalize()
1270 }
1271 }
1272 }
1273}
1274
1275pub fn generate_try_from_impl(type_ident: &Ident) -> TokenStream {
1276 quote! {
1277 impl TryFrom<&[u8]> for #type_ident {
1278 type Error = DeserializationError;
1279
1280 fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
1281 let mut reader = BufferReader::new(buffer);
1282 return deserialize_from_reader(&mut reader, true)
1283 }
1284 }
1285 }
1286}
1287
1288fn generate_value_from_frozen(ty: &FrozenTy, value_expression: TokenStream) -> TokenStream {
1292 match ty {
1293 FrozenTy::Primitive(primitive) => match primitive.kind {
1294 PrimitiveKind::Unit => quote! { Value::Unit },
1295 PrimitiveKind::Boolean => quote! { Value::Boolean(#value_expression) },
1296 PrimitiveKind::U8 => quote! { Value::U8(#value_expression) },
1297 PrimitiveKind::U16 => quote! { Value::U16(#value_expression) },
1298 PrimitiveKind::U32 => quote! { Value::U32(#value_expression) },
1299 PrimitiveKind::U64 => quote! { Value::U64(#value_expression) },
1300 PrimitiveKind::I8 => quote! { Value::I8(#value_expression) },
1301 PrimitiveKind::I16 => quote! { Value::I16(#value_expression) },
1302 PrimitiveKind::I32 => quote! { Value::I32(#value_expression) },
1303 PrimitiveKind::I64 => quote! { Value::I64(#value_expression) },
1304 PrimitiveKind::F32 => quote! { Value::F32(#value_expression) },
1305 PrimitiveKind::F64 => quote! { Value::F64(#value_expression) },
1306 PrimitiveKind::String => quote! { Value::String(#value_expression) },
1307 PrimitiveKind::ArrayBoolean => quote! { Value::ArrayBoolean(#value_expression) },
1308 PrimitiveKind::ArrayU8 => quote! { Value::ArrayU8(#value_expression) },
1309 PrimitiveKind::ArrayU16 => quote! { Value::ArrayU16(#value_expression) },
1310 PrimitiveKind::ArrayU32 => quote! { Value::ArrayU32(#value_expression) },
1311 PrimitiveKind::ArrayU64 => quote! { Value::ArrayU64(#value_expression) },
1312 PrimitiveKind::ArrayI8 => quote! { Value::ArrayI8(#value_expression) },
1313 PrimitiveKind::ArrayI16 => quote! { Value::ArrayI16(#value_expression) },
1314 PrimitiveKind::ArrayI32 => quote! { Value::ArrayI32(#value_expression) },
1315 PrimitiveKind::ArrayI64 => quote! { Value::ArrayI64(#value_expression) },
1316 PrimitiveKind::ArrayF32 => quote! { Value::ArrayF32(#value_expression) },
1317 PrimitiveKind::ArrayF64 => quote! { Value::ArrayF64(#value_expression) },
1318 PrimitiveKind::ArrayString => quote! { Value::ArrayString(#value_expression) },
1319 },
1320 FrozenTy::FrozenScalar(_) => quote! { Into::<Value>::into(#value_expression) },
1322 FrozenTy::FrozenArray(_) => quote! {
1324 Value::ArrayValue(
1325 #value_expression.into_iter().map(|__element| Into::<Value>::into(__element)).collect()
1326 )
1327 },
1328 }
1329}
1330
1331#[async_recursion(?Send)]
1335async fn generate_field_from_value_frozen(
1336 ty: &FrozenTy,
1337 value_expression: TokenStream,
1338 field_name: &str,
1339 registry: &mut dyn ReadableRegistry,
1340) -> Result<TokenStream, GenerationError> {
1341 match ty {
1342 FrozenTy::Primitive(primitive) => {
1343 let mismatch = format!("field {}: unexpected value kind", field_name);
1344 let arm = match primitive.kind {
1345 PrimitiveKind::Unit => quote! { Value::Unit => () },
1346 PrimitiveKind::Boolean => quote! { Value::Boolean(__v) => __v },
1347 PrimitiveKind::U8 => quote! { Value::U8(__v) => __v },
1348 PrimitiveKind::U16 => quote! { Value::U16(__v) => __v },
1349 PrimitiveKind::U32 => quote! { Value::U32(__v) => __v },
1350 PrimitiveKind::U64 => quote! { Value::U64(__v) => __v },
1351 PrimitiveKind::I8 => quote! { Value::I8(__v) => __v },
1352 PrimitiveKind::I16 => quote! { Value::I16(__v) => __v },
1353 PrimitiveKind::I32 => quote! { Value::I32(__v) => __v },
1354 PrimitiveKind::I64 => quote! { Value::I64(__v) => __v },
1355 PrimitiveKind::F32 => quote! { Value::F32(__v) => __v },
1356 PrimitiveKind::F64 => quote! { Value::F64(__v) => __v },
1357 PrimitiveKind::String => quote! { Value::String(__v) => __v },
1358 PrimitiveKind::ArrayBoolean => quote! { Value::ArrayBoolean(__v) => __v },
1359 PrimitiveKind::ArrayU8 => quote! { Value::ArrayU8(__v) => __v },
1360 PrimitiveKind::ArrayU16 => quote! { Value::ArrayU16(__v) => __v },
1361 PrimitiveKind::ArrayU32 => quote! { Value::ArrayU32(__v) => __v },
1362 PrimitiveKind::ArrayU64 => quote! { Value::ArrayU64(__v) => __v },
1363 PrimitiveKind::ArrayI8 => quote! { Value::ArrayI8(__v) => __v },
1364 PrimitiveKind::ArrayI16 => quote! { Value::ArrayI16(__v) => __v },
1365 PrimitiveKind::ArrayI32 => quote! { Value::ArrayI32(__v) => __v },
1366 PrimitiveKind::ArrayI64 => quote! { Value::ArrayI64(__v) => __v },
1367 PrimitiveKind::ArrayF32 => quote! { Value::ArrayF32(__v) => __v },
1368 PrimitiveKind::ArrayF64 => quote! { Value::ArrayF64(__v) => __v },
1369 PrimitiveKind::ArrayString => quote! { Value::ArrayString(__v) => __v },
1370 };
1371 Ok(quote! {
1372 match #value_expression {
1373 #arm,
1374 _ => return Err(ConversionError { message: #mismatch.to_string() }),
1375 }
1376 })
1377 }
1378 FrozenTy::FrozenScalar(_) => {
1379 let type_ident = type_ident_from_frozen(ty, registry, PrefixWithMod::Yes).await?;
1380 Ok(quote! { <#type_ident as TryFrom<Value>>::try_from(#value_expression)? })
1381 }
1382 FrozenTy::FrozenArray(array) => {
1383 let element_ty = FrozenTy::FrozenScalar(FrozenScalar {
1384 reference: array.reference.to_owned(),
1385 });
1386 let element_conversion = generate_field_from_value_frozen(
1387 &element_ty,
1388 quote! { __element },
1389 field_name,
1390 registry,
1391 )
1392 .await?;
1393 let mismatch = format!("field {}: expected array value", field_name);
1394 Ok(quote! {
1395 match #value_expression {
1396 Value::ArrayValue(__items) => {
1397 let mut __out = Vec::with_capacity(__items.len());
1398 for __element in __items {
1399 __out.push(#element_conversion);
1400 }
1401 __out
1402 }
1403 _ => return Err(ConversionError { message: #mismatch.to_string() }),
1404 }
1405 })
1406 }
1407 }
1408}
1409
1410async fn generate_serialize_from_frozen(
1411 ty: &FrozenTy,
1412 value_expression: TokenStream,
1413 registry: &mut dyn ReadableRegistry,
1414) -> Result<TokenStream, GenerationError> {
1415 match ty {
1416 FrozenTy::Primitive(primitive) => {
1417 let generate_serialize_primitive_array =
1418 |primitive_type_id: &Uuid, write_function: TokenStream| {
1419 let id_bytes = RawUuidValue(primitive_type_id);
1420 quote! {
1421 writer.add_array_primitive(#id_bytes, #value_expression.len() as u32);
1422 #write_function (#value_expression);
1423 }
1424 };
1425 Ok(match primitive.kind {
1426 PrimitiveKind::Unit => quote! { writer.add_unit() },
1427 PrimitiveKind::Boolean => quote! { writer.add_boolean(#value_expression) },
1428 PrimitiveKind::U8 => quote! { writer.add_u8(#value_expression) },
1429 PrimitiveKind::U16 => quote! { writer.add_u16(#value_expression) },
1430 PrimitiveKind::U32 => quote! { writer.add_u32(#value_expression) },
1431 PrimitiveKind::U64 => quote! { writer.add_u64(#value_expression) },
1432 PrimitiveKind::I8 => quote! { writer.add_i8(#value_expression) },
1433 PrimitiveKind::I16 => quote! { writer.add_i16(#value_expression) },
1434 PrimitiveKind::I32 => quote! { writer.add_i32(#value_expression) },
1435 PrimitiveKind::I64 => quote! { writer.add_i64(#value_expression) },
1436 PrimitiveKind::F32 => quote! { writer.add_f32(#value_expression) },
1437 PrimitiveKind::F64 => quote! { writer.add_f64(#value_expression) },
1438 PrimitiveKind::String => quote! { writer.add_string(#value_expression.as_str()) },
1439 PrimitiveKind::ArrayBoolean => generate_serialize_primitive_array(
1440 &BOOLEAN_ID,
1441 quote! { writer.add_boolean_bulk },
1442 ),
1443 PrimitiveKind::ArrayU8 => {
1444 generate_serialize_primitive_array(&U8_ID, quote! { writer.add_u8_bulk })
1445 }
1446 PrimitiveKind::ArrayU16 => {
1447 generate_serialize_primitive_array(&U16_ID, quote! { writer.add_u16_bulk })
1448 }
1449 PrimitiveKind::ArrayU32 => {
1450 generate_serialize_primitive_array(&U32_ID, quote! { writer.add_u32_bulk })
1451 }
1452 PrimitiveKind::ArrayU64 => {
1453 generate_serialize_primitive_array(&U64_ID, quote! { writer.add_u64_bulk })
1454 }
1455 PrimitiveKind::ArrayI8 => {
1456 generate_serialize_primitive_array(&I8_ID, quote! { writer.add_i8_bulk })
1457 }
1458 PrimitiveKind::ArrayI16 => {
1459 generate_serialize_primitive_array(&I16_ID, quote! { writer.add_i16_bulk })
1460 }
1461 PrimitiveKind::ArrayI32 => {
1462 generate_serialize_primitive_array(&I32_ID, quote! { writer.add_i32_bulk })
1463 }
1464 PrimitiveKind::ArrayI64 => {
1465 generate_serialize_primitive_array(&I64_ID, quote! { writer.add_i64_bulk })
1466 }
1467 PrimitiveKind::ArrayF32 => {
1468 generate_serialize_primitive_array(&F32_ID, quote! { writer.add_f32_bulk })
1469 }
1470 PrimitiveKind::ArrayF64 => {
1471 generate_serialize_primitive_array(&F64_ID, quote! { writer.add_f64_bulk })
1472 }
1473 PrimitiveKind::ArrayString => {
1474 let id_bytes = RawUuidValue(&STRING_ID);
1475 quote! {
1476 writer.add_array_primitive(#id_bytes, #value_expression.len() as u32);
1477 for s in #value_expression {
1478 writer.add_string(s.as_str());
1479 }
1480 }
1481 }
1482 })
1483 }
1484 FrozenTy::FrozenScalar(scalar) => {
1485 let mod_prefix = generated_mod_ident_from_id(&scalar.reference.id, registry)
1486 .await
1487 .map_err(GenerationError::RegistryError)?;
1488 Ok(quote! { #mod_prefix serialize_to_writer(&#value_expression, &mut writer) })
1489 }
1490 FrozenTy::FrozenArray(array) => {
1491 let type_def = registry
1492 .get_type(
1493 &Selector::Id(array.reference.id),
1494 &VersionReq::parse(array.reference.version.0.to_string().as_str()).unwrap(),
1495 )
1496 .await
1497 .map_err(GenerationError::RegistryError)?;
1498 let id_bytes = RawUuidValue(&array.reference.id);
1499 let add_array_args = quote! { #id_bytes, #value_expression.len() };
1500 let prepare_array = match type_def {
1501 TypeDefinitionFrozen::Primitive(_) => {
1502 unreachable!("got an array of primitive type instead of a primitive array type")
1503 }
1504 TypeDefinitionFrozen::Enumeration(_) => {
1505 quote! { writer.add_array_enumeration(#add_array_args); }
1506 }
1507 TypeDefinitionFrozen::Structure(_) => {
1508 quote! { writer.add_array_structure(#add_array_args); }
1509 }
1510 };
1511 let mod_prefix = generated_mod_ident_from_id(&array.reference.id, registry)
1512 .await
1513 .map_err(GenerationError::RegistryError)?;
1514 let serialize_element =
1515 quote! { #mod_prefix serialize_to_writer(&#value_expression, &mut writer) };
1516 Ok(quote! {
1517 #prepare_array
1518 for element in #value_expression {
1519 #serialize_element;
1520 }
1521 })
1522 }
1523 }
1524}
1525
1526#[async_recursion(?Send)]
1527async fn generate_deserialize_from_frozen(
1528 ty: &FrozenTy,
1529 registry: &mut dyn ReadableRegistry,
1530 check_type: CheckType,
1531) -> Result<TokenStream, GenerationError> {
1532 match ty {
1533 FrozenTy::Primitive(primitive) => {
1534 let type_kind_ident = type_kind_ident_from_primitive(&primitive.kind);
1535
1536 let generate_deserialize = |deserialize: TokenStream| {
1537 let type_check = match check_type {
1538 CheckType::Yes => quote! {
1539 {
1540 let _next_type = reader.next_type();
1541 assert_eq!(_next_type, Some(#type_kind_ident), "type mismatch");
1542 }
1543 },
1544 CheckType::YesResult => quote! {
1545 {
1546 let _next_type = reader.next_type();
1547 if _next_type != Some(#type_kind_ident) {
1548 return Err(format!("type mismatch: expected {:?} but got {:?}", #type_kind_ident, _next_type));
1549 }
1550 }
1551 },
1552 CheckType::No => quote! {},
1553 };
1554 quote! {{
1555 #type_check
1556 #deserialize
1557 }
1558 }
1559 };
1560
1561 let generate_deserialize_base_type = |type_ident: TokenStream| {
1562 let getter = format_ident!("get_{}", type_ident.to_string());
1563 generate_deserialize(quote! { reader.#getter() })
1564 };
1565
1566 let generate_deserialize_array = |deserialize_array: TokenStream| {
1567 let array_type_check = match check_type {
1568 CheckType::Yes => quote! {
1569 {
1570 let _at = reader.next_type();
1571 assert_eq!(_at, Some(TYPE_ARRAY));
1572 }
1573 let (ty, count) = reader.get_array();
1574 assert_eq!(ty, #type_kind_ident);
1575 },
1576 _ => quote! {
1577 {
1578 let _at = reader.next_type();
1579 if _at != Some(TYPE_ARRAY) {
1580 return Err(format!("expected array, got {:?}", _at));
1581 }
1582 }
1583 let (ty, count) = reader.get_array();
1584 if ty != #type_kind_ident {
1585 return Err(format!("expected array element type {:?}, got {:?}", #type_kind_ident, ty));
1586 }
1587 },
1588 };
1589 quote! {{
1590 #array_type_check
1591 #deserialize_array
1592 }
1593 }
1594 };
1595 Ok(match primitive.kind {
1596 PrimitiveKind::Unit => {
1597 quote! { Result::<(), DeserializationError>::Ok(reader.get_unit()) }
1598 }
1599 PrimitiveKind::Boolean => generate_deserialize(quote! { reader.get_boolean() }),
1600 PrimitiveKind::U8 => generate_deserialize_base_type(quote! {u8}),
1601 PrimitiveKind::U16 => generate_deserialize_base_type(quote! {u16}),
1602 PrimitiveKind::U32 => generate_deserialize_base_type(quote! {u32}),
1603 PrimitiveKind::U64 => generate_deserialize_base_type(quote! {u64}),
1604 PrimitiveKind::I8 => generate_deserialize_base_type(quote! {i8}),
1605 PrimitiveKind::I16 => generate_deserialize_base_type(quote! {i16}),
1606 PrimitiveKind::I32 => generate_deserialize_base_type(quote! {i32}),
1607 PrimitiveKind::I64 => generate_deserialize_base_type(quote! {i64}),
1608 PrimitiveKind::F32 => generate_deserialize_base_type(quote! {f32}),
1609 PrimitiveKind::F64 => generate_deserialize_base_type(quote! {f64}),
1610 PrimitiveKind::String => generate_deserialize(quote! {
1611 reader.get_string().to_string()
1612 }),
1613 PrimitiveKind::ArrayBoolean => generate_deserialize_array(quote! {
1614 reader.get_boolean_bulk(count)
1615 }),
1616 PrimitiveKind::ArrayU8 => generate_deserialize_array(quote! {
1617 reader.get_u8_bulk(count)
1618 }),
1619 PrimitiveKind::ArrayU16 => generate_deserialize_array(quote! {
1620 reader.get_u16_bulk(count)
1621 }),
1622 PrimitiveKind::ArrayU32 => generate_deserialize_array(quote! {
1623 reader.get_u32_bulk(count)
1624 }),
1625 PrimitiveKind::ArrayU64 => generate_deserialize_array(quote! {
1626 reader.get_u64_bulk(count)
1627 }),
1628 PrimitiveKind::ArrayI8 => generate_deserialize_array(quote! {
1629 reader.get_i8_bulk(count)
1630 }),
1631 PrimitiveKind::ArrayI16 => generate_deserialize_array(quote! {
1632 reader.get_i16_bulk(count)
1633 }),
1634 PrimitiveKind::ArrayI32 => generate_deserialize_array(quote! {
1635 reader.get_i32_bulk(count)
1636 }),
1637 PrimitiveKind::ArrayI64 => generate_deserialize_array(quote! {
1638 reader.get_i64_bulk(count)
1639 }),
1640 PrimitiveKind::ArrayF32 => generate_deserialize_array(quote! {
1641 reader.get_f32_bulk(count)
1642 }),
1643 PrimitiveKind::ArrayF64 => generate_deserialize_array(quote! {
1644 reader.get_f64_bulk(count)
1645 }),
1646 PrimitiveKind::ArrayString => {
1647 let deserialize_element = generate_deserialize(quote! {
1648 Result::<String, DeserializationError>::Ok(reader.get_string().to_string())
1649 });
1650 generate_deserialize_array(quote! {
1651 let mut res = Vec::<String>::with_capacity(count as usize);
1652 for _i in 0..count {
1653 res.push(#deserialize_element);
1654 }
1655 res
1656 })
1657 }
1658 })
1659 }
1660 FrozenTy::FrozenScalar(scalar) => {
1661 let mod_prefix = generated_mod_ident_from_id(&scalar.reference.id, registry)
1662 .await
1663 .map_err(GenerationError::RegistryError)?;
1664 let check_type_bool = check_type != CheckType::No;
1665 let type_ident =
1666 type_ident_from_id(&scalar.reference.id, registry, PrefixWithMod::Yes).await?;
1667 let type_str = type_ident.to_string();
1668 Ok(match check_type {
1669 CheckType::YesResult => quote! {
1670 #mod_prefix deserialize_from_reader(&mut reader, #check_type_bool)
1671 .map_err(|e| format!("failed to deserialize {}: {}", #type_str, e))?
1672 },
1673 _ => quote! {
1674 #mod_prefix deserialize_from_reader(&mut reader, #check_type_bool)
1675 .expect(&format!("failed to deserialize {}", #type_str))
1676 },
1677 })
1678 }
1679 FrozenTy::FrozenArray(array) => {
1680 let type_ident =
1681 type_ident_from_id(&array.reference.id, registry, PrefixWithMod::Yes).await?;
1682 let deserialize_element = generate_deserialize_from_frozen(
1683 &FrozenTy::FrozenScalar(FrozenScalar {
1684 reference: array.reference.to_owned(),
1685 }),
1686 registry,
1687 CheckType::No,
1688 )
1689 .await?;
1690 let type_enum = match registry
1691 .type_of(&Selector::Id(array.reference.id.to_owned()))
1692 .await
1693 .map_err(GenerationError::RegistryError)?
1694 {
1695 RecordType::Enumeration => quote! { TYPE_ENUMERATION },
1696 RecordType::Structure => quote! { TYPE_STRUCTURE },
1697 _ => unreachable!("unexpected type of element in array"),
1698 };
1699 let raw_id = RawUuidValue(&array.reference.id);
1700 let array_checks = match check_type {
1701 CheckType::Yes => quote! {
1702 {
1703 let _at = reader.next_type();
1704 assert_eq!(_at, Some(TYPE_ARRAY));
1705 }
1706 let (ty, count) = reader.get_array();
1707 assert_eq!(ty, #type_enum);
1708 {
1709 let _id = reader.get_structure_field();
1710 assert_eq!(_id, &#raw_id);
1711 }
1712 },
1713 _ => quote! {
1714 {
1715 let _at = reader.next_type();
1716 if _at != Some(TYPE_ARRAY) {
1717 return Err(format!("expected array, got {:?}", _at));
1718 }
1719 }
1720 let (ty, count) = reader.get_array();
1721 if ty != #type_enum {
1722 return Err(format!("expected array element type {:?}, got {:?}", #type_enum, ty));
1723 }
1724 {
1725 let _id = reader.get_structure_field();
1726 if _id != &#raw_id {
1727 return Err("array type id mismatch".to_string());
1728 }
1729 }
1730 },
1731 };
1732 Ok(quote! {{
1733 #array_checks
1734 let mut res = Vec::<#type_ident>::with_capacity(count as usize);
1735 for _i in 0..count {
1736 res.push(#deserialize_element);
1737 }
1738 res
1739 }})
1740 }
1741 }
1742}
1743
1744pub fn token_stream_to_file<P: AsRef<path::Path>>(
1745 file_path: P,
1746 tokens: &TokenStream,
1747) -> Result<Directory, VfsError> {
1748 let file_path = file_path.as_ref();
1749 let file_name = file_path.file_name().unwrap().to_str().unwrap();
1750 let parent_path = file_path.parent().unwrap();
1751 let mut output = Directory::new();
1752 let parent_dir = match output.ensure_directories(parent_path) {
1753 Ok(dir) => dir,
1754 Err(VfsError::EmptyPath) => &mut output,
1755 Err(err) => return Err(err),
1756 };
1757 parent_dir.insert(file_name, File::new(tokens.to_string()))?;
1758 Ok(output)
1759}
1760
1761pub fn type_ident(type_name: &String) -> Ident {
1762 format_ident!("{}", type_name.to_case(Case::UpperCamel))
1763}
1764
1765pub fn struct_field_const_id_ident(struct_name: &String, field_name: &String) -> Ident {
1766 format_ident!(
1767 "{}_{}_FIELD_RAW_ID",
1768 struct_name.to_case(Case::UpperSnake),
1769 field_name.to_case(Case::UpperSnake)
1770 )
1771}
1772
1773pub fn struct_field_ident(struct_name: &String, field_name: &String) -> TokenStream {
1774 format!(
1775 "{}::{}",
1776 struct_name.to_case(Case::UpperCamel),
1777 field_name.to_case(Case::UpperCamel)
1778 )
1779 .parse()
1780 .unwrap()
1781}
1782
1783pub fn struct_field_intermediate_variable_ident(
1784 struct_name: &String,
1785 field_name: &String,
1786) -> Ident {
1787 format_ident!(
1788 "{}_{}",
1789 struct_name.to_case(Case::Snake),
1790 field_name.to_case(Case::Snake),
1791 )
1792}
1793
1794pub fn enum_variant_ident(enum_name: &String, variant_name: &String) -> TokenStream {
1795 format!(
1796 "{}::{}",
1797 enum_name.to_case(Case::UpperCamel),
1798 variant_name.to_case(Case::UpperCamel),
1799 )
1800 .parse()
1801 .unwrap()
1802}
1803
1804pub fn enum_variant_const_id_ident(enum_name: &String, variant_name: &String) -> Ident {
1805 format_ident!(
1806 "{}_{}_VARIANT_RAW_ID",
1807 enum_name.to_case(Case::UpperSnake),
1808 variant_name.to_case(Case::UpperSnake),
1809 )
1810}
1811
1812pub fn generate_const_id_declaration(
1814 name: &String,
1815 ident: &Ident,
1816 id: &Uuid,
1817 public: Public,
1818) -> TokenStream {
1819 let id_str = id.to_string();
1820 let id_bytes = RawUuidValue(id);
1821 let const_id_doc = format!("{}: {}", name, id_str);
1822 let maybe_pub = match public {
1823 Public::Yes => quote! { pub },
1824 Public::No => quote! {},
1825 };
1826 quote! {
1827 #[doc = #const_id_doc]
1828 #maybe_pub const #ident: [u8; 16] = #id_bytes;
1829 }
1830}
1831
1832pub fn function_const_id_ident(function_name: &String) -> Ident {
1833 format_ident!(
1834 "{}_FUNCTION_RAW_ID",
1835 function_name.to_case(Case::UpperSnake),
1836 )
1837}
1838
1839pub fn function_param_const_id_ident(function_name: &String, param_name: &String) -> Ident {
1840 format_ident!(
1841 "{}_{}_PARAMETER_RAW_ID",
1842 function_name.to_case(Case::UpperSnake),
1843 param_name.to_case(Case::UpperSnake),
1844 )
1845}
1846
1847fn param_ident(param_id: &Uuid, param: &Parameter) -> Ident {
1848 let param_id_sanitized = param_id.to_string().replace("-", "");
1849 format_ident!(
1850 "param_{}_{}",
1851 param.name.to_case(Case::Snake),
1852 param_id_sanitized
1853 )
1854}
1855
1856pub fn variable_ident(name: &String) -> Ident {
1857 format_ident!("{}", name.to_case(Case::Snake))
1858}
1859
1860async fn type_ident_from_frozen(
1861 ty: &FrozenTy,
1862 registry: &mut dyn ReadableRegistry,
1863 with_mod: PrefixWithMod,
1864) -> Result<TokenStream, GenerationError> {
1865 Ok(match ty {
1866 FrozenTy::Primitive(primitive) => match *primitive {
1867 Primitive::UNIT => quote! { () },
1868 Primitive::BOOLEAN => quote!(bool),
1869 Primitive::U8 => quote!(u8),
1870 Primitive::U16 => quote!(u16),
1871 Primitive::U32 => quote!(u32),
1872 Primitive::U64 => quote!(u64),
1873 Primitive::I8 => quote!(i8),
1874 Primitive::I16 => quote!(i16),
1875 Primitive::I32 => quote!(i32),
1876 Primitive::I64 => quote!(i64),
1877 Primitive::F32 => quote!(f32),
1878 Primitive::F64 => quote!(f64),
1879 Primitive::STRING => quote!(String),
1880 Primitive::ARRAY_BOOLEAN => quote!(Vec<bool>),
1881 Primitive::ARRAY_U8 => quote!(Vec<u8>),
1882 Primitive::ARRAY_U16 => quote!(Vec<u16>),
1883 Primitive::ARRAY_U32 => quote!(Vec<u32>),
1884 Primitive::ARRAY_U64 => quote!(Vec<u64>),
1885 Primitive::ARRAY_I8 => quote!(Vec<i8>),
1886 Primitive::ARRAY_I16 => quote!(Vec<i16>),
1887 Primitive::ARRAY_I32 => quote!(Vec<i32>),
1888 Primitive::ARRAY_I64 => quote!(Vec<i64>),
1889 Primitive::ARRAY_F32 => quote!(Vec<f32>),
1890 Primitive::ARRAY_F64 => quote!(Vec<f64>),
1891 Primitive::ARRAY_STRING => quote!(Vec<String>),
1892 },
1893 FrozenTy::FrozenScalar(scalar) => {
1894 type_ident_from_id(&scalar.reference.id, registry, with_mod).await?
1895 }
1896 FrozenTy::FrozenArray(array) => {
1897 let type_ident = type_ident_from_id(&array.reference.id, registry, with_mod).await?;
1898 quote! { Vec<#type_ident> }
1899 }
1900 })
1901}
1902
1903async fn type_ident_from_id(
1904 id: &Uuid,
1905 registry: &mut dyn ReadableRegistry,
1906 with_mod: PrefixWithMod,
1907) -> Result<TokenStream, GenerationError> {
1908 let type_def = registry
1909 .get_type(&Selector::Id(id.to_owned()), &VersionReq::STAR)
1910 .await
1911 .map_err(GenerationError::RegistryError)?;
1912 type_ident_from_definition(&type_def, id, registry, with_mod).await
1913}
1914
1915async fn type_ident_from_definition(
1916 type_def: &TypeDefinitionFrozen,
1917 id: &Uuid,
1918 registry: &mut dyn ReadableRegistry,
1919 with_mod: PrefixWithMod,
1920) -> Result<TokenStream, GenerationError> {
1921 Ok(match type_def {
1922 TypeDefinitionFrozen::Primitive(primitive) => match primitive {
1923 PrimitiveKind::Unit => quote! { () },
1924 PrimitiveKind::Boolean => quote!(bool),
1925 PrimitiveKind::U8 => quote!(u8),
1926 PrimitiveKind::U16 => quote!(u16),
1927 PrimitiveKind::U32 => quote!(u32),
1928 PrimitiveKind::U64 => quote!(u64),
1929 PrimitiveKind::I8 => quote!(i8),
1930 PrimitiveKind::I16 => quote!(i16),
1931 PrimitiveKind::I32 => quote!(i32),
1932 PrimitiveKind::I64 => quote!(i64),
1933 PrimitiveKind::F32 => quote!(f32),
1934 PrimitiveKind::F64 => quote!(f64),
1935 PrimitiveKind::String => quote!(String),
1936 PrimitiveKind::ArrayBoolean => quote!(Vec<bool>),
1937 PrimitiveKind::ArrayU8 => quote!(Vec<u8>),
1938 PrimitiveKind::ArrayU16 => quote!(Vec<u16>),
1939 PrimitiveKind::ArrayU32 => quote!(Vec<u32>),
1940 PrimitiveKind::ArrayU64 => quote!(Vec<u64>),
1941 PrimitiveKind::ArrayI8 => quote!(Vec<i8>),
1942 PrimitiveKind::ArrayI16 => quote!(Vec<i16>),
1943 PrimitiveKind::ArrayI32 => quote!(Vec<i32>),
1944 PrimitiveKind::ArrayI64 => quote!(Vec<i64>),
1945 PrimitiveKind::ArrayF32 => quote!(Vec<f32>),
1946 PrimitiveKind::ArrayF64 => quote!(Vec<f64>),
1947 PrimitiveKind::ArrayString => quote!(Vec<String>),
1948 },
1949 TypeDefinitionFrozen::Enumeration(enumeration) => {
1950 type_ident_from_name_and_id(&enumeration.name, id, registry, with_mod)
1951 .await
1952 .map_err(GenerationError::RegistryError)?
1953 }
1954 TypeDefinitionFrozen::Structure(structure) => {
1955 type_ident_from_name_and_id(&structure.name, id, registry, with_mod)
1956 .await
1957 .map_err(GenerationError::RegistryError)?
1958 }
1959 })
1960}
1961
1962async fn type_ident_from_name_and_id(
1963 name: &String,
1964 id: &Uuid,
1965 registry: &mut dyn ReadableRegistry,
1966 with_mod: PrefixWithMod,
1967) -> Result<TokenStream, RegistryError> {
1968 let mod_prefix = match with_mod {
1969 PrefixWithMod::Yes => generated_mod_ident_from_id(id, registry).await?,
1970 PrefixWithMod::No => quote! {},
1971 };
1972 let type_ident = type_ident(name);
1973 Ok(quote! { #mod_prefix #type_ident })
1974}
1975
1976fn type_kind_ident_from_primitive(primitive: &PrimitiveKind) -> TokenStream {
1977 match primitive {
1978 PrimitiveKind::Unit => quote! { TYPE_UNIT },
1979 PrimitiveKind::Boolean => quote! { TYPE_BOOLEAN },
1980 PrimitiveKind::U8 => quote! { TYPE_U8 },
1981 PrimitiveKind::U16 => quote! { TYPE_U16 },
1982 PrimitiveKind::U32 => quote! { TYPE_U32 },
1983 PrimitiveKind::U64 => quote! { TYPE_U64 },
1984 PrimitiveKind::I8 => quote! { TYPE_I8 },
1985 PrimitiveKind::I16 => quote! { TYPE_I16 },
1986 PrimitiveKind::I32 => quote! { TYPE_I32 },
1987 PrimitiveKind::I64 => quote! { TYPE_I64 },
1988 PrimitiveKind::F32 => quote! { TYPE_F32 },
1989 PrimitiveKind::F64 => quote! { TYPE_F64 },
1990 PrimitiveKind::String => quote! { TYPE_STRING },
1991 PrimitiveKind::ArrayBoolean
1992 | PrimitiveKind::ArrayU8
1993 | PrimitiveKind::ArrayU16
1994 | PrimitiveKind::ArrayU32
1995 | PrimitiveKind::ArrayU64
1996 | PrimitiveKind::ArrayI8
1997 | PrimitiveKind::ArrayI16
1998 | PrimitiveKind::ArrayI32
1999 | PrimitiveKind::ArrayI64
2000 | PrimitiveKind::ArrayF32
2001 | PrimitiveKind::ArrayF64
2002 | PrimitiveKind::ArrayString => quote! { TYPE_ARRAY },
2003 }
2004}
2005
2006async fn generated_mod_ident_from_id(
2008 id: &Uuid,
2009 registry: &mut dyn ReadableRegistry,
2010) -> Result<TokenStream, RegistryError> {
2011 let mod_path = registry.resolve_id(id).await?;
2012 let mod_ident = mod_ident_from_path(&mod_path);
2013 Ok(quote! { arora_generated::#mod_ident })
2014}
2015
2016fn mod_ident_from_path(path: &str) -> TokenStream {
2017 let path_parts = path.split(".").collect::<Vec<&str>>();
2018 let path_parts = path_parts
2019 .iter()
2020 .map(|part| format_ident!("{}", part.to_case(Case::Snake)));
2021 quote! { #(#path_parts ::)* }
2022}
2023
2024#[derive(Clone, Copy, Eq, PartialEq)]
2025pub enum CheckType {
2026 Yes,
2028 YesResult,
2030 No,
2031}
2032
2033#[derive(Clone, Copy, Eq, PartialEq)]
2034pub enum PrefixWithMod {
2035 Yes,
2036 No,
2037}
2038
2039#[derive(Clone, Copy, Eq, PartialEq)]
2040pub enum Public {
2041 Yes,
2042 No,
2043}
2044
2045#[derive(Display, Debug)]
2046pub enum GenerationError {
2047 ModuleDeclarationError(ModuleDeclarationError),
2048 RegistryError(RegistryError),
2049 VfsError(VfsError),
2050 IoError(std::io::Error),
2051 Generic(String),
2052}
2053
2054impl std::error::Error for GenerationError {}
2055
2056pub struct RawUuidValue<'a>(pub &'a Uuid);
2058
2059impl<'a> Display for RawUuidValue<'a> {
2060 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2061 write!(f, "{:#04x?}", self.0.as_bytes())
2062 }
2063}
2064
2065impl<'a> ToTokens for RawUuidValue<'a> {
2066 fn to_tokens(&self, tokens: &mut TokenStream) {
2067 let new_tokens: TokenStream = self.to_string().parse().unwrap();
2068 tokens.extend(new_tokens);
2069 }
2070}