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 reader.next_type();
469 match variant_raw_id.try_into().expect("enum id is of unexpected length") {
470 #(#deserialization_cases)*
471 _ => Err(DeserializationError{ message: "unexpected variant".to_string() })
472 }
473 }
474 };
475
476 let to_value_cases = variants.clone().map(|(_, variant)| {
478 let variant_ident = enum_variant_ident(&enum_name, &variant.name);
479 let id_ident = enum_variant_const_id_ident(&enum_name, &variant.name);
480 quote! {
481 #variant_ident => Value::Enumeration(Enumeration {
482 id: Uuid::from_bytes(#enum_const_id_ident),
483 variant_id: Uuid::from_bytes(#id_ident),
484 value: Box::new(Value::Unit),
485 }),
486 }
487 });
488
489 let to_value = quote! {
490 impl Into<Value> for #enum_ident {
491 fn into(self) -> Value {
492 match self {
493 #(#to_value_cases)*
494 }
495 }
496 }
497 };
498
499 let from_value_cases = variants.map(|(_, variant)| {
501 let variant_const_id_ident = enum_variant_const_id_ident(&enum_name, &variant.name);
502 let variant_ident = enum_variant_ident(&enum_name, &variant.name);
503 quote! {
504 #variant_const_id_ident => Ok(#variant_ident),
505 }
506 });
507
508 let from_value = quote! {
509 impl TryFrom<Value> for #enum_ident {
510 type Error = ConversionError;
511 fn try_from(value: Value) -> Result<Self, Self::Error> {
512 if let Value::Enumeration(as_enum) = value {
513 if *as_enum.id.as_bytes() == #enum_const_id_ident {
514 match *as_enum.variant_id.as_bytes() {
515 #(#from_value_cases)*
516 _ => Err(Self::Error { message: "unexpected variant".to_string() }),
517 }
518 } else {
519 Err(Self::Error {
520 message: "unexpected enum type ID".to_string(),
521 })
522 }
523 } else {
524 Err(Self::Error {
525 message: "unexpected kind".to_string(),
526 })
527 }
528 }
529 }
530 };
531
532 let type_source = quote! {
534 #uses
535 #enum_declaration
536 #serialization
537 #deserialization
538 #to_value
539 #from_value
540 #enum_id_declaration
541 #(#variant_id_declarations)*
542 };
543
544 let base_file_name = enumeration.name.to_case(Case::Snake);
545 let file_path = if parent_path.is_empty() {
546 format!("{}.rs", base_file_name)
547 } else {
548 format!("{}/{}.rs", parent_path.replace('.', "/"), base_file_name)
549 };
550 token_stream_to_file(file_path, &type_source)
551}
552
553pub async fn generate_structure_source(
558 id: &Uuid,
559 structure: &StructureFrozen,
560 registry: &mut dyn ReadableRegistry,
561 parent_path: &str,
562) -> Result<Directory, GenerationError> {
563 let name = &structure.name;
565 let struct_ident = type_ident(name);
566 let is_self_ref = |field: &arora_types::record::structure::frozen::StructureField| matches!(&field.ty, FrozenTy::FrozenScalar(scalar) if scalar.reference.id == *id);
571 let mut field_declarations = Vec::new();
572 for (_, field) in &structure.fields {
573 let field_ident = variable_ident(&field.name);
574 let mut field_type_ident =
575 type_ident_from_frozen(&field.ty, registry, PrefixWithMod::Yes).await?;
576 if is_self_ref(field) {
577 field_type_ident = quote! { Box<#field_type_ident> };
578 }
579 field_declarations.push(quote! { pub #field_ident: #field_type_ident });
580 }
581 let struct_declaration = quote! {
582 #[derive(Debug, PartialEq, Clone)]
583 pub struct #struct_ident {
584 #(#field_declarations),*
585 }
586 };
587
588 let id_str = id.to_string();
590 let id_bytes = RawUuidValue(id);
591 let upper_name = format_ident!("{}", name.to_case(Case::UpperSnake));
592 let const_id_ident = format_ident!("{}_STRUCT_RAW_ID", upper_name);
593 let const_id_doc = format!("{}: {}", name, id_str);
594 let id_declaration = quote! {
595 #[doc = #const_id_doc]
596 pub const #const_id_ident: [u8; 16] = #id_bytes;
597 };
598
599 let field_id_declarations = structure.fields.iter().map(|(field_id, field)| {
600 let field_id_bytes = RawUuidValue(field_id);
601 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
602 let field_doc = format!("{}: {}", struct_field_ident(name, &field.name), field_id,);
603 quote! {
604 #[doc = #field_doc]
605 pub const #field_const_id_ident: [u8; 16] = #field_id_bytes;
606 }
607 });
608
609 let mut fields_serialization = Vec::new();
611 for (_, field) in &structure.fields {
612 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
613 let field_ident = variable_ident(&field.name);
614 let value_expression = quote! { value.#field_ident };
615 let serialize =
616 generate_serialize_from_frozen(&field.ty, value_expression, registry).await?;
617 fields_serialization.push(quote! {
621 writer.add_structure_field(&#field_const_id_ident);
622 #serialize;
623 });
624 }
625 let field_count = fields_serialization.len() as u32;
626
627 let into_impl = generate_into_impl(&struct_ident);
628 let serialization = quote! {
629 #into_impl
630
631 pub fn serialize_to_writer(value: &#struct_ident, writer: &mut BufferWriter) {
632 let structure_id = #const_id_ident.as_slice();
633 writer.begin_structure(structure_id, #field_count);
634 #(#fields_serialization)*
635 }
636 };
637
638 let mut field_variable_declarations = Vec::new();
642 for (_, field) in &structure.fields {
643 let variable_ident = struct_field_intermediate_variable_ident(name, &field.name);
644 let mut type_ident =
645 type_ident_from_frozen(&field.ty, registry, PrefixWithMod::Yes).await?;
646 if is_self_ref(field) {
647 type_ident = quote! { Box<#type_ident> };
648 }
649 field_variable_declarations
650 .push(quote! { let mut #variable_ident: Option<#type_ident> = None; });
651 }
652
653 let mut deserialization_cases = Vec::new();
654 for (_, field) in &structure.fields {
655 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
656 let field_variable_ident = struct_field_intermediate_variable_ident(name, &field.name);
657 let deserialize =
658 generate_deserialize_from_frozen(&field.ty, registry, CheckType::Yes).await?;
659 let deserialize = if is_self_ref(field) {
660 quote! { Box::new(#deserialize) }
661 } else {
662 deserialize
663 };
664 deserialization_cases.push(quote! {
665 if field_raw_id == #field_const_id_ident {
666 #field_variable_ident = Some(#deserialize);
667 }
668 });
669 }
670
671 let struct_field_assignment = structure.fields.iter().map(|(_, field)| {
672 let field_ident = variable_ident(&field.name);
673 let variable_ident = struct_field_intermediate_variable_ident(name, &field.name);
674 quote! { #field_ident: #variable_ident.unwrap() }
675 });
676
677 let try_from_impl = generate_try_from_impl(&struct_ident);
678 let expected_field_count = structure.fields.len();
679 let deserialization = quote! {
680 #try_from_impl
681
682 pub fn deserialize_from_reader(reader: &mut BufferReader, check_type: bool) -> Result<#struct_ident, DeserializationError> {
683 let field_count = if check_type {
684 let type_raw_id_opt = reader.next_type();
685 if type_raw_id_opt.is_none() {
686 return Err(DeserializationError{ message: "missing next type information".to_string() })
687 }
688 if type_raw_id_opt.unwrap() != TYPE_STRUCTURE {
689 return Err(DeserializationError{ message: "next type is not a structure".to_string() })
690 }
691 let (structure_raw_id, field_count) = reader.get_structure();
692 if #const_id_ident != structure_raw_id {
693 return Err(DeserializationError{ message: "structure id does not match".to_string() })
694 }
695 field_count
696 } else {
697 reader.get_structure_raw()
698 };
699 if #expected_field_count != field_count as usize {
700 return Err(DeserializationError{
701 message: format!("expected {} fields, found {}", #expected_field_count, field_count)
702 })
703 }
704
705 #(#field_variable_declarations)*
706 for _ in 0..field_count {
707 let field_raw_id = reader.get_structure_field();
708 #(#deserialization_cases) else* else {
709 return Err(DeserializationError {
710 message: format!("unexpected struct field {}", Uuid::from_slice(field_raw_id).unwrap().to_string())
711 })
712 }
713 }
714
715 Ok(#struct_ident {
716 #(#struct_field_assignment,)*
717 })
718 }
719 };
720
721 let mut to_value_fields = Vec::new();
725 for (_, field) in &structure.fields {
726 let field_ident = variable_ident(&field.name);
727 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
728 let field_access = if is_self_ref(field) {
730 quote! { *self.#field_ident }
731 } else {
732 quote! { self.#field_ident }
733 };
734 let field_value = generate_value_from_frozen(&field.ty, field_access);
735 to_value_fields.push(quote! {
736 StructureField {
737 id: Uuid::from_bytes(#field_const_id_ident),
738 value: Box::new(#field_value),
739 }
740 });
741 }
742 let to_value = quote! {
743 impl Into<Value> for #struct_ident {
744 fn into(self) -> Value {
745 Value::Structure(Structure {
746 id: Uuid::from_bytes(#const_id_ident),
747 fields: vec![#(#to_value_fields),*],
748 })
749 }
750 }
751 };
752
753 let mut from_value_field_vars = Vec::new();
754 let mut from_value_cases = Vec::new();
755 let mut from_value_assignments = Vec::new();
756 for (_, field) in &structure.fields {
757 let field_ident = variable_ident(&field.name);
758 let field_const_id_ident = struct_field_const_id_ident(name, &field.name);
759 let field_var = struct_field_intermediate_variable_ident(name, &field.name);
760 let mut field_type_ident =
761 type_ident_from_frozen(&field.ty, registry, PrefixWithMod::Yes).await?;
762 let extract = generate_field_from_value_frozen(
763 &field.ty,
764 quote! { *field.value },
765 &field.name,
766 registry,
767 )
768 .await?;
769 let extract = if is_self_ref(field) {
770 field_type_ident = quote! { Box<#field_type_ident> };
771 quote! { Box::new(#extract) }
772 } else {
773 extract
774 };
775 from_value_field_vars
776 .push(quote! { let mut #field_var: Option<#field_type_ident> = None; });
777 from_value_cases.push(quote! { #field_const_id_ident => { #field_var = Some(#extract); } });
778 let missing_message = format!("missing field {}", field.name);
779 from_value_assignments.push(quote! {
780 #field_ident: #field_var.ok_or_else(|| ConversionError { message: #missing_message.to_string() })?
781 });
782 }
783 let from_value = quote! {
784 impl TryFrom<Value> for #struct_ident {
785 type Error = ConversionError;
786 fn try_from(value: Value) -> Result<Self, Self::Error> {
787 if let Value::Structure(as_struct) = value {
788 if *as_struct.id.as_bytes() != #const_id_ident {
789 return Err(ConversionError { message: "unexpected structure type ID".to_string() });
790 }
791 #(#from_value_field_vars)*
792 for field in as_struct.fields {
793 match *field.id.as_bytes() {
794 #(#from_value_cases)*
795 _ => return Err(ConversionError { message: "unexpected struct field".to_string() }),
796 }
797 }
798 Ok(#struct_ident {
799 #(#from_value_assignments,)*
800 })
801 } else {
802 Err(ConversionError { message: "unexpected kind".to_string() })
803 }
804 }
805 }
806 };
807
808 let references_generated_modules = structure.fields.values().any(|field| match &field.ty {
813 FrozenTy::Primitive(_) => false,
814 FrozenTy::FrozenScalar(scalar) => !is_dynamic_value_id(&scalar.reference.id),
815 FrozenTy::FrozenArray(array) => !is_dynamic_value_id(&array.reference.id),
816 });
817 let generated_modules_use = if references_generated_modules {
818 quote! { use crate::arora_generated; }
819 } else {
820 quote! {}
821 };
822 let type_source = quote! {
823 use arora_buffers::*;
824 use uuid::Uuid;
825 use arora_types::value::{ConversionError, Structure, StructureField, Value};
826 use crate::arora_generated::error::DeserializationError;
827 #generated_modules_use
828 #struct_declaration
829 #serialization
830 #deserialization
831 #to_value
832 #from_value
833 #id_declaration
834 #(#field_id_declarations)*
835 };
836
837 let base_file_name = structure.name.to_case(Case::Snake);
838 let file_path = if parent_path.is_empty() {
839 format!("{}.rs", base_file_name)
840 } else {
841 format!("{}/{}.rs", parent_path.replace('.', "/"), base_file_name)
842 };
843 token_stream_to_file(file_path, &type_source).map_err(GenerationError::VfsError)
844}
845
846async fn generate_imports_from_module_source(
850 module_id: &Uuid,
851 module_path: &str,
852 imports: &Vec<ImportAsset>,
853 registry: &mut dyn ReadableRegistry,
854) -> Result<Directory, GenerationError> {
855 let uses = {
857 let mut dependencies = HashSet::<&FrozenReference>::new();
858 for import in imports {
859 import.import.dependencies(&mut dependencies);
860 }
861 let mut uses = Vec::new();
862 for dep in dependencies {
863 let dep_selector = Selector::Id(dep.id);
864 let type_def = match registry
865 .get_type(
866 &dep_selector,
867 &VersionReq::parse(dep.version.to_string().as_str()).unwrap(),
868 )
869 .await
870 {
871 Ok(TypeDefinitionFrozen::Primitive(_)) => continue,
872 Ok(type_definition) => type_definition,
873 Err(RegistryError::NotAType { selector: _ }) => continue,
874 Err(err) => return Err(GenerationError::RegistryError(err)),
875 };
876 let type_ident =
877 type_ident_from_definition(&type_def, &dep.id, registry, PrefixWithMod::Yes)
878 .await?;
879 uses.push(type_ident);
880 }
881 uses
882 };
883
884 let splitted_module_path: Vec<&str> = module_path.split(".").collect();
885 let module_name = splitted_module_path.last().unwrap();
886
887 let module_const_id_ident =
889 format_ident!("{}_MODULE_ID", module_name.to_case(Case::UpperSnake),);
890 let module_id_declaration = generate_const_id_declaration(
891 &module_name.to_string(),
892 &module_const_id_ident,
893 module_id,
894 Public::No,
895 );
896
897 let mut functions_declarations = Vec::<TokenStream>::new();
899 for import in imports {
900 let ExportKind::Function(function_symbol) = &import.import.kind;
901 let function_name = &import.import.name;
902 let function_ident = format_ident!("{}", function_name);
903 let mut parameters_declarations = Vec::new();
904 for param in function_symbol.parameters.values() {
905 let maybe_mut = if param.mutable {
906 quote! { mut }
907 } else {
908 quote! {}
909 };
910 let param_name_ident = format_ident!("{}", param.name);
911 let param_type_ident =
912 type_ident_from_frozen(¶m.ty, registry, PrefixWithMod::Yes).await?;
913 parameters_declarations.push(quote! {
914 #maybe_mut #param_name_ident: #param_type_ident
915 });
916 }
917 let ret_type_ident =
918 type_ident_from_frozen(&function_symbol.return_ty, registry, PrefixWithMod::Yes)
919 .await?;
920
921 let function_const_id_ident = function_const_id_ident(function_name);
924 let function_id_declaration = generate_const_id_declaration(
925 function_name,
926 &function_const_id_ident,
927 &import.id,
928 Public::No,
929 );
930 let param_ids_declarations = {
931 let mut param_ids_declarations = Vec::new();
932 for (id, param) in &function_symbol.parameters {
933 param_ids_declarations.push(generate_const_id_declaration(
934 &format!("{}.{}", function_name, param.name),
935 &function_param_const_id_ident(function_name, ¶m.name),
936 id,
937 Public::No,
938 ));
939 }
940 param_ids_declarations
941 };
942
943 let ids_declaration = quote! {
944 #function_id_declaration
945 #(#param_ids_declarations)*
946 };
947
948 let add_args = {
952 let mut add_args = Vec::new();
953 for param in function_symbol.parameters.values() {
954 let function_param_const_id_ident =
955 function_param_const_id_ident(function_name, ¶m.name);
956 let param_name_ident = format_ident!("{}", param.name);
957 let serialize_arg = generate_serialize_from_frozen(
958 ¶m.ty,
959 param_name_ident.into_token_stream(),
960 registry,
961 )
962 .await?;
963 add_args.push(quote! {
964 writer.add_structure_field(#function_param_const_id_ident.as_slice());
965 #serialize_arg;
966 });
967 }
968 add_args
969 };
970 let nof_args = add_args.len() as u32;
971 let prepare_call_structure = quote! {
972 let mut writer = BufferWriter::new();
973 let writer = &mut writer;
974 writer.begin_structure(#function_const_id_ident.as_slice(), #nof_args);
975 #(#add_args)*
976 let arg = writer.finalize();
977 };
978
979 let perform_call = quote! {
981 let result_buffer_addr = unsafe {
982 arora_dispatch(
983 #module_const_id_ident.as_ptr() as usize,
984 #function_const_id_ident.as_ptr() as usize,
985 arg.as_ptr() as usize,
986 )
987 };
988 };
989
990 let prepare_parsing = quote! {
992 let result_buffer_ptr = result_buffer_addr as *const u8;
993 let input_size_bytes: &[u8; 4] =
994 unsafe { std::slice::from_raw_parts(result_buffer_ptr, BUFFER_SIZE_SIZE) }
995 .try_into()
996 .expect("input is too small");
997 let input_size = u32::from_le_bytes(*input_size_bytes) as usize;
998 let input =
999 unsafe { std::slice::from_raw_parts(result_buffer_ptr, BUFFER_SIZE_SIZE + input_size) };
1000 let mut reader = BufferReader::new(&input);
1001 let reader = &mut reader;
1002 };
1003
1004 let check_result_struct = quote! {
1006 let type_raw_id_opt = reader.next_type();
1007 assert!(!type_raw_id_opt.is_none());
1008 assert_eq!(type_raw_id_opt.unwrap(), TYPE_STRUCTURE);
1009 let (result_struct_id, result_field_count) = reader.get_structure();
1010 assert_eq!(result_struct_id, #function_const_id_ident);
1011 };
1012
1013 let deserialize_ret =
1018 generate_deserialize_from_frozen(&function_symbol.return_ty, registry, CheckType::Yes)
1019 .await?;
1020
1021 let process_params = if nof_args > 1 {
1022 let declare_mutable_params = {
1023 let mut declare_mutable_params = Vec::new();
1024 for param in function_symbol.parameters.values() {
1025 if param.mutable {
1026 let param_name_ident = format_ident!("{}", param.name);
1027 declare_mutable_params.push(quote! {
1028 let mut #param_name_ident = None;
1029 })
1030 }
1031 }
1032 declare_mutable_params
1033 };
1034
1035 let deserialize_params = {
1036 let mut deserialize_params = Vec::new();
1037 for param in function_symbol.parameters.values() {
1038 if param.mutable {
1039 let param_name_ident = format_ident!("{}", param.name);
1040 let function_param_const_id_ident =
1041 function_param_const_id_ident(function_name, ¶m.name);
1042 let deserialize_param =
1043 generate_deserialize_from_frozen(¶m.ty, registry, CheckType::Yes)
1044 .await?;
1045 deserialize_params.push(quote! {
1046 x if *x == #function_param_const_id_ident => *#param_name_ident = #deserialize_param,
1047 });
1048 }
1049 }
1050 deserialize_params
1051 };
1052
1053 quote! {
1054 #(#declare_mutable_params)*
1055 for _i in 1u32..#nof_args {
1056 let next_field_id = reader.get_structure_field();
1057 match next_field_id {
1058 #(#deserialize_params)*
1059 x => panic!("found unexpected mutated argument id: {:#?}", x),
1060 }
1061 }
1062 }
1063 } else {
1064 quote! {}
1065 };
1066
1067 let process_result = quote! {
1068 assert_eq!(result_field_count, #nof_args);
1069 let first_field_id = reader.get_structure_field();
1070 assert_eq!(first_field_id, #function_const_id_ident);
1071 let ret = #deserialize_ret;
1072 #process_params
1073 ret
1074 };
1075
1076 functions_declarations.push(quote! {
1078 pub fn #function_ident (#(#parameters_declarations),*) -> #ret_type_ident {
1079 #ids_declaration
1080 #prepare_call_structure
1081 #perform_call
1082 #prepare_parsing
1083 #check_result_struct
1084 #process_result
1085 }
1086 });
1087 }
1088
1089 let source = quote! {
1091 #(#uses)*
1092 use arora_buffers::*;
1093 use crate::arora_generated::arora::arora_dispatch;
1094 #module_id_declaration
1095 #(#functions_declarations)*
1096 };
1097
1098 let file_path = splitted_module_path
1099 .iter()
1100 .map(|name| name.to_case(Case::Snake))
1101 .fold(String::new(), |acc, name| {
1102 if acc.is_empty() {
1103 name
1104 } else {
1105 format!("{}/{}", acc, name)
1106 }
1107 })
1108 + ".rs";
1109 token_stream_to_file(file_path, &source).map_err(GenerationError::VfsError)
1110}
1111
1112async fn generate_module_source(
1114 module: &ModuleFrozen,
1115 registry: &mut dyn ReadableRegistry,
1116) -> Result<Directory, GenerationError> {
1117 let exports = &module.exports;
1119 let use_functions = exports
1120 .values()
1121 .map(|export| format_ident!("{}", export.name));
1122
1123 let function_ids = exports.iter().flat_map(|(function_id, export)| {
1125 let ExportKind::Function(function_symbol) = &export.kind;
1126 let mut id_declarations = Vec::with_capacity(function_symbol.parameters.len() + 1);
1127 id_declarations.push(generate_const_id_declaration(
1128 &export.name,
1129 &function_const_id_ident(&export.name),
1130 function_id,
1131 Public::Yes,
1132 ));
1133 for (param_id, param) in &function_symbol.parameters {
1134 id_declarations.push(generate_const_id_declaration(
1135 &format!("{}.{}", export.name, param.name),
1136 &function_param_const_id_ident(&export.name, ¶m.name),
1137 param_id,
1138 Public::Yes,
1139 ));
1140 }
1141 id_declarations
1142 });
1143
1144 let function_declarations = {
1146 let mut function_declarations = Vec::new();
1147 for (export_id, export) in exports {
1148 let function_ident = format_ident!("{}", export.name);
1149 let ExportKind::Function(function_symbol) = &export.kind;
1150 let const_id_ident = function_const_id_ident(&export.name);
1151
1152 let call_check = quote! {
1153 let mut reader = BufferReader::new(&input);
1154 let reader = &mut reader;
1155 let type_raw_id_opt = reader.next_type();
1156 if type_raw_id_opt.is_none() {
1157 return Err("input is empty".to_string());
1158 }
1159 if type_raw_id_opt.unwrap() != TYPE_STRUCTURE {
1160 return Err(format!("expected structure input, got type {:?}", type_raw_id_opt));
1161 }
1162 let (structure_raw_id, field_count) = reader.get_structure();
1163 if structure_raw_id != &#const_id_ident {
1164 return Err("function id mismatch in input".to_string());
1165 }
1166 };
1167
1168 let param_declarations = {
1169 let mut param_declarations = Vec::new();
1170 for (param_id, param) in &function_symbol.parameters {
1171 let param_var_ident = param_ident(param_id, param);
1172 let param_type_ident =
1173 type_ident_from_frozen(¶m.ty, registry, PrefixWithMod::Yes).await?;
1174 param_declarations.push(
1175 quote! { let mut #param_var_ident: Option<#param_type_ident> = None; },
1176 );
1177 }
1178 param_declarations
1179 };
1180
1181 let deserialization_cases = {
1182 let mut deserialization_cases = Vec::new();
1183 for (param_id, param) in &function_symbol.parameters {
1184 let param_const_id_ident =
1185 function_param_const_id_ident(&export.name, ¶m.name);
1186 let param_var_ident = param_ident(param_id, param);
1187 let deserialize =
1188 generate_deserialize_from_frozen(¶m.ty, registry, CheckType::YesResult)
1189 .await?;
1190 deserialization_cases.push(quote! {
1191 if field_raw_id == #param_const_id_ident {
1192 #param_var_ident = Some(#deserialize);
1193 }
1194 });
1195 }
1196 deserialization_cases
1197 };
1198
1199 let deserialize_params = if function_symbol.parameters.is_empty() {
1200 quote! {
1201 if field_count != 0 {
1202 return Err(format!("expected 0 parameters but got {}", field_count));
1203 }
1204 }
1205 } else {
1206 quote! {
1207 #(#param_declarations)*
1208 for _ in 0..field_count {
1209 let field_raw_id = reader.get_structure_field();
1210 #(#deserialization_cases else)* {
1211 return Err(format!("unexpected parameter {:?}", field_raw_id));
1212 }
1213 }
1214 }
1215 };
1216
1217 let param_args = function_symbol.parameter_ordering.iter().map(|param_id| {
1218 let param = function_symbol.parameters.get(param_id).unwrap();
1219 let param_var_ident = param_ident(param_id, param);
1220 if param.mutable {
1221 quote! { &mut #param_var_ident }
1222 } else {
1223 quote! { #param_var_ident }
1224 }
1225 });
1226
1227 let call_and_write_result = {
1228 let result_ident = match &function_symbol.return_ty {
1229 FrozenTy::Primitive(Primitive { kind }) if *kind == PrimitiveKind::Unit => {
1230 quote! { _ }
1231 }
1232 _ => quote! { result },
1233 };
1234 let serialize_result = generate_serialize_from_frozen(
1235 &function_symbol.return_ty,
1236 result_ident.clone(),
1237 registry,
1238 )
1239 .await?;
1240 quote! {
1241 let #result_ident = #function_ident (#(#param_args),*);
1242 #serialize_result;
1243 }
1244 };
1245
1246 let write_mutated_params: Vec<TokenStream> = {
1247 let mut write_mutated_params = Vec::new();
1248 for (param_id, param) in &function_symbol.parameters {
1249 if param.mutable {
1250 let param_var_ident = param_ident(param_id, param);
1251 let param_const_id_ident =
1252 function_param_const_id_ident(&export.name, ¶m.name);
1253 let serialize_param = generate_serialize_from_frozen(
1254 ¶m.ty,
1255 quote! {#param_var_ident.unwrap()},
1256 registry,
1257 )
1258 .await?;
1259 write_mutated_params.push(quote! {
1260 writer.add_structure_field(&#param_const_id_ident);
1261 #serialize_param;
1262 });
1263 }
1264 }
1265 write_mutated_params
1266 };
1267 let nof_mutated_params = write_mutated_params.len();
1268
1269 let uuid_suffix = export_id.to_string().replace("-", "_");
1270 let arora_function_ident = format_ident!("arora_function_{}", uuid_suffix);
1271 let doc = export.name.to_string();
1272 function_declarations.push(quote! {
1273 #[doc = #doc]
1274 #[no_mangle]
1275 pub extern "C" fn #arora_function_ident (input_addr: usize) -> usize {
1276 let input_ptr = input_addr as *const u8;
1277 const INPUT_SIZE_SIZE: usize = std::mem::size_of::<u32>();
1278 let input_size_bytes: &[u8; 4] = unsafe {
1279 std::slice::from_raw_parts(input_ptr, INPUT_SIZE_SIZE)
1280 }.try_into().expect("input is too small");
1281 let input_size = u32::from_le_bytes(*input_size_bytes) as usize;
1282 let input = unsafe {
1283 std::slice::from_raw_parts(input_ptr, INPUT_SIZE_SIZE + input_size)
1284 };
1285 let _result: ::std::result::Result<::std::boxed::Box<[u8]>, ::std::string::String> = (|| {
1286 #call_check
1287 #deserialize_params
1288 let mut writer = BufferWriter::new();
1289 let writer = &mut writer;
1290 writer.begin_structure(&#const_id_ident, (#nof_mutated_params + 1) as u32);
1291 writer.add_structure_field(&#const_id_ident);
1292 #call_and_write_result
1293 #(#write_mutated_params)*
1294 ::std::result::Result::Ok(writer.finalize())
1295 })();
1296 match _result {
1297 ::std::result::Result::Ok(buf) => ::std::boxed::Box::leak(buf).as_ptr() as usize,
1298 ::std::result::Result::Err(msg) => {
1299 let mut writer = BufferWriter::new();
1300 writer.add_error(&msg);
1301 ::std::boxed::Box::leak(writer.finalize()).as_ptr() as usize
1302 }
1303 }
1304 }
1305 });
1306 }
1307 function_declarations
1308 };
1309
1310 let source = quote! {
1312 use arora_buffers::*;
1313 use crate::{arora_generated, #(#use_functions),*};
1314 #(#function_declarations)*
1315 #(#function_ids)*
1316 };
1317 token_stream_to_file("export.rs", &source).map_err(GenerationError::VfsError)
1318}
1319
1320pub fn generate_into_impl(type_ident: &Ident) -> TokenStream {
1321 quote! {
1322 impl Into<Box<[u8]>> for #type_ident {
1323 fn into(self) -> Box<[u8]> {
1324 let mut writer = BufferWriter::new();
1325 serialize_to_writer(&self, &mut writer);
1326 writer.finalize()
1327 }
1328 }
1329 }
1330}
1331
1332pub fn generate_try_from_impl(type_ident: &Ident) -> TokenStream {
1333 quote! {
1334 impl TryFrom<&[u8]> for #type_ident {
1335 type Error = DeserializationError;
1336
1337 fn try_from(buffer: &[u8]) -> Result<Self, Self::Error> {
1338 let mut reader = BufferReader::new(buffer);
1339 return deserialize_from_reader(&mut reader, true)
1340 }
1341 }
1342 }
1343}
1344
1345fn generate_value_from_frozen(ty: &FrozenTy, value_expression: TokenStream) -> TokenStream {
1349 match ty {
1350 FrozenTy::Primitive(primitive) => match primitive.kind {
1351 PrimitiveKind::Unit => quote! { Value::Unit },
1352 PrimitiveKind::Boolean => quote! { Value::Boolean(#value_expression) },
1353 PrimitiveKind::U8 => quote! { Value::U8(#value_expression) },
1354 PrimitiveKind::U16 => quote! { Value::U16(#value_expression) },
1355 PrimitiveKind::U32 => quote! { Value::U32(#value_expression) },
1356 PrimitiveKind::U64 => quote! { Value::U64(#value_expression) },
1357 PrimitiveKind::I8 => quote! { Value::I8(#value_expression) },
1358 PrimitiveKind::I16 => quote! { Value::I16(#value_expression) },
1359 PrimitiveKind::I32 => quote! { Value::I32(#value_expression) },
1360 PrimitiveKind::I64 => quote! { Value::I64(#value_expression) },
1361 PrimitiveKind::F32 => quote! { Value::F32(#value_expression) },
1362 PrimitiveKind::F64 => quote! { Value::F64(#value_expression) },
1363 PrimitiveKind::String => quote! { Value::String(#value_expression) },
1364 PrimitiveKind::ArrayBoolean => quote! { Value::ArrayBoolean(#value_expression) },
1365 PrimitiveKind::ArrayU8 => quote! { Value::ArrayU8(#value_expression) },
1366 PrimitiveKind::ArrayU16 => quote! { Value::ArrayU16(#value_expression) },
1367 PrimitiveKind::ArrayU32 => quote! { Value::ArrayU32(#value_expression) },
1368 PrimitiveKind::ArrayU64 => quote! { Value::ArrayU64(#value_expression) },
1369 PrimitiveKind::ArrayI8 => quote! { Value::ArrayI8(#value_expression) },
1370 PrimitiveKind::ArrayI16 => quote! { Value::ArrayI16(#value_expression) },
1371 PrimitiveKind::ArrayI32 => quote! { Value::ArrayI32(#value_expression) },
1372 PrimitiveKind::ArrayI64 => quote! { Value::ArrayI64(#value_expression) },
1373 PrimitiveKind::ArrayF32 => quote! { Value::ArrayF32(#value_expression) },
1374 PrimitiveKind::ArrayF64 => quote! { Value::ArrayF64(#value_expression) },
1375 PrimitiveKind::ArrayString => quote! { Value::ArrayString(#value_expression) },
1376 },
1377 FrozenTy::FrozenScalar(scalar) if is_dynamic_value_id(&scalar.reference.id) => {
1379 quote! { #value_expression }
1380 }
1381 FrozenTy::FrozenScalar(_) => quote! { Into::<Value>::into(#value_expression) },
1383 FrozenTy::FrozenArray(_) => quote! {
1385 Value::ArrayValue(
1386 #value_expression.into_iter().map(|__element| Into::<Value>::into(__element)).collect()
1387 )
1388 },
1389 }
1390}
1391
1392#[async_recursion(?Send)]
1396async fn generate_field_from_value_frozen(
1397 ty: &FrozenTy,
1398 value_expression: TokenStream,
1399 field_name: &str,
1400 registry: &mut dyn ReadableRegistry,
1401) -> Result<TokenStream, GenerationError> {
1402 match ty {
1403 FrozenTy::Primitive(primitive) => {
1404 let mismatch = format!("field {}: unexpected value kind", field_name);
1405 let arm = match primitive.kind {
1406 PrimitiveKind::Unit => quote! { Value::Unit => () },
1407 PrimitiveKind::Boolean => quote! { Value::Boolean(__v) => __v },
1408 PrimitiveKind::U8 => quote! { Value::U8(__v) => __v },
1409 PrimitiveKind::U16 => quote! { Value::U16(__v) => __v },
1410 PrimitiveKind::U32 => quote! { Value::U32(__v) => __v },
1411 PrimitiveKind::U64 => quote! { Value::U64(__v) => __v },
1412 PrimitiveKind::I8 => quote! { Value::I8(__v) => __v },
1413 PrimitiveKind::I16 => quote! { Value::I16(__v) => __v },
1414 PrimitiveKind::I32 => quote! { Value::I32(__v) => __v },
1415 PrimitiveKind::I64 => quote! { Value::I64(__v) => __v },
1416 PrimitiveKind::F32 => quote! { Value::F32(__v) => __v },
1417 PrimitiveKind::F64 => quote! { Value::F64(__v) => __v },
1418 PrimitiveKind::String => quote! { Value::String(__v) => __v },
1419 PrimitiveKind::ArrayBoolean => quote! { Value::ArrayBoolean(__v) => __v },
1420 PrimitiveKind::ArrayU8 => quote! { Value::ArrayU8(__v) => __v },
1421 PrimitiveKind::ArrayU16 => quote! { Value::ArrayU16(__v) => __v },
1422 PrimitiveKind::ArrayU32 => quote! { Value::ArrayU32(__v) => __v },
1423 PrimitiveKind::ArrayU64 => quote! { Value::ArrayU64(__v) => __v },
1424 PrimitiveKind::ArrayI8 => quote! { Value::ArrayI8(__v) => __v },
1425 PrimitiveKind::ArrayI16 => quote! { Value::ArrayI16(__v) => __v },
1426 PrimitiveKind::ArrayI32 => quote! { Value::ArrayI32(__v) => __v },
1427 PrimitiveKind::ArrayI64 => quote! { Value::ArrayI64(__v) => __v },
1428 PrimitiveKind::ArrayF32 => quote! { Value::ArrayF32(__v) => __v },
1429 PrimitiveKind::ArrayF64 => quote! { Value::ArrayF64(__v) => __v },
1430 PrimitiveKind::ArrayString => quote! { Value::ArrayString(__v) => __v },
1431 };
1432 Ok(quote! {
1433 match #value_expression {
1434 #arm,
1435 _ => return Err(ConversionError { message: #mismatch.to_string() }),
1436 }
1437 })
1438 }
1439 FrozenTy::FrozenScalar(scalar) if is_dynamic_value_id(&scalar.reference.id) => {
1440 Ok(quote! { #value_expression })
1442 }
1443 FrozenTy::FrozenScalar(_) => {
1444 let type_ident = type_ident_from_frozen(ty, registry, PrefixWithMod::Yes).await?;
1445 Ok(quote! { <#type_ident as TryFrom<Value>>::try_from(#value_expression)? })
1446 }
1447 FrozenTy::FrozenArray(array) => {
1448 let element_ty = FrozenTy::FrozenScalar(FrozenScalar {
1449 reference: array.reference.to_owned(),
1450 });
1451 let element_conversion = generate_field_from_value_frozen(
1452 &element_ty,
1453 quote! { __element },
1454 field_name,
1455 registry,
1456 )
1457 .await?;
1458 let mismatch = format!("field {}: expected array value", field_name);
1459 Ok(quote! {
1460 match #value_expression {
1461 Value::ArrayValue(__items) => {
1462 let mut __out = Vec::with_capacity(__items.len());
1463 for __element in __items {
1464 __out.push(#element_conversion);
1465 }
1466 __out
1467 }
1468 _ => return Err(ConversionError { message: #mismatch.to_string() }),
1469 }
1470 })
1471 }
1472 }
1473}
1474
1475async fn generate_serialize_from_frozen(
1476 ty: &FrozenTy,
1477 value_expression: TokenStream,
1478 registry: &mut dyn ReadableRegistry,
1479) -> Result<TokenStream, GenerationError> {
1480 match ty {
1481 FrozenTy::Primitive(primitive) => {
1482 let generate_serialize_primitive_array =
1483 |primitive_type_id: &Uuid, write_function: TokenStream| {
1484 let id_bytes = RawUuidValue(primitive_type_id);
1485 quote! {
1486 writer.add_array_primitive(#id_bytes, #value_expression.len() as u32);
1487 #write_function (#value_expression);
1488 }
1489 };
1490 Ok(match primitive.kind {
1491 PrimitiveKind::Unit => quote! { writer.add_unit() },
1492 PrimitiveKind::Boolean => quote! { writer.add_boolean(#value_expression) },
1493 PrimitiveKind::U8 => quote! { writer.add_u8(#value_expression) },
1494 PrimitiveKind::U16 => quote! { writer.add_u16(#value_expression) },
1495 PrimitiveKind::U32 => quote! { writer.add_u32(#value_expression) },
1496 PrimitiveKind::U64 => quote! { writer.add_u64(#value_expression) },
1497 PrimitiveKind::I8 => quote! { writer.add_i8(#value_expression) },
1498 PrimitiveKind::I16 => quote! { writer.add_i16(#value_expression) },
1499 PrimitiveKind::I32 => quote! { writer.add_i32(#value_expression) },
1500 PrimitiveKind::I64 => quote! { writer.add_i64(#value_expression) },
1501 PrimitiveKind::F32 => quote! { writer.add_f32(#value_expression) },
1502 PrimitiveKind::F64 => quote! { writer.add_f64(#value_expression) },
1503 PrimitiveKind::String => quote! { writer.add_string(#value_expression.as_str()) },
1504 PrimitiveKind::ArrayBoolean => generate_serialize_primitive_array(
1505 &BOOLEAN_ID,
1506 quote! { writer.add_boolean_bulk },
1507 ),
1508 PrimitiveKind::ArrayU8 => {
1509 generate_serialize_primitive_array(&U8_ID, quote! { writer.add_u8_bulk })
1510 }
1511 PrimitiveKind::ArrayU16 => {
1512 generate_serialize_primitive_array(&U16_ID, quote! { writer.add_u16_bulk })
1513 }
1514 PrimitiveKind::ArrayU32 => {
1515 generate_serialize_primitive_array(&U32_ID, quote! { writer.add_u32_bulk })
1516 }
1517 PrimitiveKind::ArrayU64 => {
1518 generate_serialize_primitive_array(&U64_ID, quote! { writer.add_u64_bulk })
1519 }
1520 PrimitiveKind::ArrayI8 => {
1521 generate_serialize_primitive_array(&I8_ID, quote! { writer.add_i8_bulk })
1522 }
1523 PrimitiveKind::ArrayI16 => {
1524 generate_serialize_primitive_array(&I16_ID, quote! { writer.add_i16_bulk })
1525 }
1526 PrimitiveKind::ArrayI32 => {
1527 generate_serialize_primitive_array(&I32_ID, quote! { writer.add_i32_bulk })
1528 }
1529 PrimitiveKind::ArrayI64 => {
1530 generate_serialize_primitive_array(&I64_ID, quote! { writer.add_i64_bulk })
1531 }
1532 PrimitiveKind::ArrayF32 => {
1533 generate_serialize_primitive_array(&F32_ID, quote! { writer.add_f32_bulk })
1534 }
1535 PrimitiveKind::ArrayF64 => {
1536 generate_serialize_primitive_array(&F64_ID, quote! { writer.add_f64_bulk })
1537 }
1538 PrimitiveKind::ArrayString => {
1539 let id_bytes = RawUuidValue(&STRING_ID);
1540 quote! {
1541 writer.add_array_primitive(#id_bytes, #value_expression.len() as u32);
1542 for s in #value_expression {
1543 writer.add_string(s.as_str());
1544 }
1545 }
1546 }
1547 })
1548 }
1549 FrozenTy::FrozenScalar(scalar) => {
1550 if is_dynamic_value_id(&scalar.reference.id) {
1553 return Ok(quote! {
1554 arora_buffers::serde_uuid::serialize_to_writer(&#value_expression, writer)
1555 });
1556 }
1557 let mod_prefix = generated_mod_ident_from_id(&scalar.reference.id, registry)
1558 .await
1559 .map_err(GenerationError::RegistryError)?;
1560 Ok(quote! { #mod_prefix serialize_to_writer(&#value_expression, writer) })
1563 }
1564 FrozenTy::FrozenArray(array) => {
1565 let type_def = registry
1566 .get_type(
1567 &Selector::Id(array.reference.id),
1568 &VersionReq::parse(array.reference.version.0.to_string().as_str()).unwrap(),
1569 )
1570 .await
1571 .map_err(GenerationError::RegistryError)?;
1572 let id_bytes = RawUuidValue(&array.reference.id);
1573 let add_array_args = quote! { &#id_bytes, #value_expression.len() as u32 };
1576 let prepare_array = match type_def {
1577 TypeDefinitionFrozen::Primitive(_) => {
1578 unreachable!("got an array of primitive type instead of a primitive array type")
1579 }
1580 TypeDefinitionFrozen::Enumeration(_) => {
1581 quote! { writer.add_array_enumeration(#add_array_args); }
1582 }
1583 TypeDefinitionFrozen::Structure(_) => {
1584 quote! { writer.add_array_structure(#add_array_args); }
1585 }
1586 };
1587 let mod_prefix = generated_mod_ident_from_id(&array.reference.id, registry)
1588 .await
1589 .map_err(GenerationError::RegistryError)?;
1590 Ok(quote! {
1595 #prepare_array
1596 for element in &#value_expression {
1597 #mod_prefix serialize_to_writer(element, writer);
1598 }
1599 })
1600 }
1601 }
1602}
1603
1604#[async_recursion(?Send)]
1605async fn generate_deserialize_from_frozen(
1606 ty: &FrozenTy,
1607 registry: &mut dyn ReadableRegistry,
1608 check_type: CheckType,
1609) -> Result<TokenStream, GenerationError> {
1610 match ty {
1611 FrozenTy::Primitive(primitive) => {
1612 let type_kind_ident = type_kind_ident_from_primitive(&primitive.kind);
1613
1614 let generate_deserialize = |deserialize: TokenStream| {
1615 let type_check = match check_type {
1616 CheckType::Yes => quote! {
1617 {
1618 let _next_type = reader.next_type();
1619 assert_eq!(_next_type, Some(#type_kind_ident), "type mismatch");
1620 }
1621 },
1622 CheckType::YesResult => quote! {
1623 {
1624 let _next_type = reader.next_type();
1625 if _next_type != Some(#type_kind_ident) {
1626 return Err(format!("type mismatch: expected {:?} but got {:?}", #type_kind_ident, _next_type));
1627 }
1628 }
1629 },
1630 CheckType::No => quote! {},
1631 };
1632 quote! {{
1633 #type_check
1634 #deserialize
1635 }
1636 }
1637 };
1638
1639 let generate_deserialize_base_type = |type_ident: TokenStream| {
1640 let getter = format_ident!("get_{}", type_ident.to_string());
1641 generate_deserialize(quote! { reader.#getter() })
1642 };
1643
1644 let generate_deserialize_array = |deserialize_array: TokenStream| {
1645 let array_type_check = match check_type {
1646 CheckType::Yes => quote! {
1647 {
1648 let _at = reader.next_type();
1649 assert_eq!(_at, Some(TYPE_ARRAY));
1650 }
1651 let (ty, count) = reader.get_array();
1652 assert_eq!(ty, #type_kind_ident);
1653 },
1654 _ => quote! {
1655 {
1656 let _at = reader.next_type();
1657 if _at != Some(TYPE_ARRAY) {
1658 return Err(format!("expected array, got {:?}", _at));
1659 }
1660 }
1661 let (ty, count) = reader.get_array();
1662 if ty != #type_kind_ident {
1663 return Err(format!("expected array element type {:?}, got {:?}", #type_kind_ident, ty));
1664 }
1665 },
1666 };
1667 quote! {{
1668 #array_type_check
1669 #deserialize_array
1670 }
1671 }
1672 };
1673 Ok(match primitive.kind {
1674 PrimitiveKind::Unit => {
1675 quote! { Result::<(), DeserializationError>::Ok(reader.get_unit()) }
1676 }
1677 PrimitiveKind::Boolean => generate_deserialize(quote! { reader.get_boolean() }),
1678 PrimitiveKind::U8 => generate_deserialize_base_type(quote! {u8}),
1679 PrimitiveKind::U16 => generate_deserialize_base_type(quote! {u16}),
1680 PrimitiveKind::U32 => generate_deserialize_base_type(quote! {u32}),
1681 PrimitiveKind::U64 => generate_deserialize_base_type(quote! {u64}),
1682 PrimitiveKind::I8 => generate_deserialize_base_type(quote! {i8}),
1683 PrimitiveKind::I16 => generate_deserialize_base_type(quote! {i16}),
1684 PrimitiveKind::I32 => generate_deserialize_base_type(quote! {i32}),
1685 PrimitiveKind::I64 => generate_deserialize_base_type(quote! {i64}),
1686 PrimitiveKind::F32 => generate_deserialize_base_type(quote! {f32}),
1687 PrimitiveKind::F64 => generate_deserialize_base_type(quote! {f64}),
1688 PrimitiveKind::String => generate_deserialize(quote! {
1689 reader.get_string().to_string()
1690 }),
1691 PrimitiveKind::ArrayBoolean => generate_deserialize_array(quote! {
1692 reader.get_boolean_bulk(count)
1693 }),
1694 PrimitiveKind::ArrayU8 => generate_deserialize_array(quote! {
1695 reader.get_u8_bulk(count)
1696 }),
1697 PrimitiveKind::ArrayU16 => generate_deserialize_array(quote! {
1698 reader.get_u16_bulk(count)
1699 }),
1700 PrimitiveKind::ArrayU32 => generate_deserialize_array(quote! {
1701 reader.get_u32_bulk(count)
1702 }),
1703 PrimitiveKind::ArrayU64 => generate_deserialize_array(quote! {
1704 reader.get_u64_bulk(count)
1705 }),
1706 PrimitiveKind::ArrayI8 => generate_deserialize_array(quote! {
1707 reader.get_i8_bulk(count)
1708 }),
1709 PrimitiveKind::ArrayI16 => generate_deserialize_array(quote! {
1710 reader.get_i16_bulk(count)
1711 }),
1712 PrimitiveKind::ArrayI32 => generate_deserialize_array(quote! {
1713 reader.get_i32_bulk(count)
1714 }),
1715 PrimitiveKind::ArrayI64 => generate_deserialize_array(quote! {
1716 reader.get_i64_bulk(count)
1717 }),
1718 PrimitiveKind::ArrayF32 => generate_deserialize_array(quote! {
1719 reader.get_f32_bulk(count)
1720 }),
1721 PrimitiveKind::ArrayF64 => generate_deserialize_array(quote! {
1722 reader.get_f64_bulk(count)
1723 }),
1724 PrimitiveKind::ArrayString => {
1725 let deserialize_element = generate_deserialize(quote! {
1726 Result::<String, DeserializationError>::Ok(reader.get_string().to_string())
1727 });
1728 generate_deserialize_array(quote! {
1729 let mut res = Vec::<String>::with_capacity(count as usize);
1730 for _i in 0..count {
1731 res.push(#deserialize_element);
1732 }
1733 res
1734 })
1735 }
1736 })
1737 }
1738 FrozenTy::FrozenScalar(scalar) => {
1739 if is_dynamic_value_id(&scalar.reference.id) {
1741 return Ok(quote! {
1742 arora_buffers::serde_uuid::deserialize_from_reader(reader)
1743 });
1744 }
1745 let mod_prefix = generated_mod_ident_from_id(&scalar.reference.id, registry)
1746 .await
1747 .map_err(GenerationError::RegistryError)?;
1748 let check_type_bool = check_type != CheckType::No;
1749 let type_ident =
1750 type_ident_from_id(&scalar.reference.id, registry, PrefixWithMod::Yes).await?;
1751 let type_str = type_ident.to_string();
1752 Ok(match check_type {
1757 CheckType::YesResult => quote! {
1758 #mod_prefix deserialize_from_reader(reader, #check_type_bool)
1759 .map_err(|e| format!("failed to deserialize {}: {}", #type_str, e))?
1760 },
1761 _ => quote! {
1762 #mod_prefix deserialize_from_reader(reader, #check_type_bool)
1763 .expect(&format!("failed to deserialize {}", #type_str))
1764 },
1765 })
1766 }
1767 FrozenTy::FrozenArray(array) => {
1768 let type_ident =
1769 type_ident_from_id(&array.reference.id, registry, PrefixWithMod::Yes).await?;
1770 let element_check_type = match check_type {
1775 CheckType::YesResult => CheckType::YesResult,
1776 _ => CheckType::Yes,
1777 };
1778 let deserialize_element = generate_deserialize_from_frozen(
1779 &FrozenTy::FrozenScalar(FrozenScalar {
1780 reference: array.reference.to_owned(),
1781 }),
1782 registry,
1783 element_check_type,
1784 )
1785 .await?;
1786 let type_enum = match registry
1787 .type_of(&Selector::Id(array.reference.id.to_owned()))
1788 .await
1789 .map_err(GenerationError::RegistryError)?
1790 {
1791 RecordType::Enumeration => quote! { TYPE_ENUMERATION },
1792 RecordType::Structure => quote! { TYPE_STRUCTURE },
1793 _ => unreachable!("unexpected type of element in array"),
1794 };
1795 let raw_id = RawUuidValue(&array.reference.id);
1796 let array_checks = match check_type {
1797 CheckType::Yes => quote! {
1798 {
1799 let _at = reader.next_type();
1800 assert_eq!(_at, Some(TYPE_ARRAY));
1801 }
1802 let (ty, count) = reader.get_array();
1803 assert_eq!(ty, #type_enum);
1804 {
1805 let _id = reader.get_structure_field();
1806 assert_eq!(_id, &#raw_id);
1807 }
1808 },
1809 _ => quote! {
1810 {
1811 let _at = reader.next_type();
1812 if _at != Some(TYPE_ARRAY) {
1813 return Err(format!("expected array, got {:?}", _at));
1814 }
1815 }
1816 let (ty, count) = reader.get_array();
1817 if ty != #type_enum {
1818 return Err(format!("expected array element type {:?}, got {:?}", #type_enum, ty));
1819 }
1820 {
1821 let _id = reader.get_structure_field();
1822 if _id != &#raw_id {
1823 return Err("array type id mismatch".to_string());
1824 }
1825 }
1826 },
1827 };
1828 Ok(quote! {{
1829 #array_checks
1830 let mut res = Vec::<#type_ident>::with_capacity(count as usize);
1831 for _i in 0..count {
1832 res.push(#deserialize_element);
1833 }
1834 res
1835 }})
1836 }
1837 }
1838}
1839
1840pub fn token_stream_to_file<P: AsRef<path::Path>>(
1841 file_path: P,
1842 tokens: &TokenStream,
1843) -> Result<Directory, VfsError> {
1844 let file_path = file_path.as_ref();
1845 let file_name = file_path.file_name().unwrap().to_str().unwrap();
1846 let parent_path = file_path.parent().unwrap();
1847 let mut output = Directory::new();
1848 let parent_dir = match output.ensure_directories(parent_path) {
1849 Ok(dir) => dir,
1850 Err(VfsError::EmptyPath) => &mut output,
1851 Err(err) => return Err(err),
1852 };
1853 parent_dir.insert(file_name, File::new(tokens.to_string()))?;
1854 Ok(output)
1855}
1856
1857pub fn type_ident(type_name: &String) -> Ident {
1858 format_ident!("{}", type_name.to_case(Case::UpperCamel))
1859}
1860
1861pub fn struct_field_const_id_ident(struct_name: &String, field_name: &String) -> Ident {
1862 format_ident!(
1863 "{}_{}_FIELD_RAW_ID",
1864 struct_name.to_case(Case::UpperSnake),
1865 field_name.to_case(Case::UpperSnake)
1866 )
1867}
1868
1869pub fn struct_field_ident(struct_name: &String, field_name: &String) -> TokenStream {
1870 format!(
1871 "{}::{}",
1872 struct_name.to_case(Case::UpperCamel),
1873 field_name.to_case(Case::UpperCamel)
1874 )
1875 .parse()
1876 .unwrap()
1877}
1878
1879pub fn struct_field_intermediate_variable_ident(
1880 struct_name: &String,
1881 field_name: &String,
1882) -> Ident {
1883 format_ident!(
1884 "{}_{}",
1885 struct_name.to_case(Case::Snake),
1886 field_name.to_case(Case::Snake),
1887 )
1888}
1889
1890pub fn enum_variant_ident(enum_name: &String, variant_name: &String) -> TokenStream {
1891 format!(
1892 "{}::{}",
1893 enum_name.to_case(Case::UpperCamel),
1894 variant_name.to_case(Case::UpperCamel),
1895 )
1896 .parse()
1897 .unwrap()
1898}
1899
1900pub fn enum_variant_const_id_ident(enum_name: &String, variant_name: &String) -> Ident {
1901 format_ident!(
1902 "{}_{}_VARIANT_RAW_ID",
1903 enum_name.to_case(Case::UpperSnake),
1904 variant_name.to_case(Case::UpperSnake),
1905 )
1906}
1907
1908pub fn generate_const_id_declaration(
1910 name: &String,
1911 ident: &Ident,
1912 id: &Uuid,
1913 public: Public,
1914) -> TokenStream {
1915 let id_str = id.to_string();
1916 let id_bytes = RawUuidValue(id);
1917 let const_id_doc = format!("{}: {}", name, id_str);
1918 let maybe_pub = match public {
1919 Public::Yes => quote! { pub },
1920 Public::No => quote! {},
1921 };
1922 quote! {
1923 #[doc = #const_id_doc]
1924 #maybe_pub const #ident: [u8; 16] = #id_bytes;
1925 }
1926}
1927
1928pub fn function_const_id_ident(function_name: &String) -> Ident {
1929 format_ident!(
1930 "{}_FUNCTION_RAW_ID",
1931 function_name.to_case(Case::UpperSnake),
1932 )
1933}
1934
1935pub fn function_param_const_id_ident(function_name: &String, param_name: &String) -> Ident {
1936 format_ident!(
1937 "{}_{}_PARAMETER_RAW_ID",
1938 function_name.to_case(Case::UpperSnake),
1939 param_name.to_case(Case::UpperSnake),
1940 )
1941}
1942
1943fn param_ident(param_id: &Uuid, param: &Parameter) -> Ident {
1944 let param_id_sanitized = param_id.to_string().replace("-", "");
1945 format_ident!(
1946 "param_{}_{}",
1947 param.name.to_case(Case::Snake),
1948 param_id_sanitized
1949 )
1950}
1951
1952pub fn variable_ident(name: &String) -> Ident {
1953 format_ident!("{}", name.to_case(Case::Snake))
1954}
1955
1956async fn type_ident_from_frozen(
1957 ty: &FrozenTy,
1958 registry: &mut dyn ReadableRegistry,
1959 with_mod: PrefixWithMod,
1960) -> Result<TokenStream, GenerationError> {
1961 Ok(match ty {
1962 FrozenTy::Primitive(primitive) => match *primitive {
1963 Primitive::UNIT => quote! { () },
1964 Primitive::BOOLEAN => quote!(bool),
1965 Primitive::U8 => quote!(u8),
1966 Primitive::U16 => quote!(u16),
1967 Primitive::U32 => quote!(u32),
1968 Primitive::U64 => quote!(u64),
1969 Primitive::I8 => quote!(i8),
1970 Primitive::I16 => quote!(i16),
1971 Primitive::I32 => quote!(i32),
1972 Primitive::I64 => quote!(i64),
1973 Primitive::F32 => quote!(f32),
1974 Primitive::F64 => quote!(f64),
1975 Primitive::STRING => quote!(String),
1976 Primitive::ARRAY_BOOLEAN => quote!(Vec<bool>),
1977 Primitive::ARRAY_U8 => quote!(Vec<u8>),
1978 Primitive::ARRAY_U16 => quote!(Vec<u16>),
1979 Primitive::ARRAY_U32 => quote!(Vec<u32>),
1980 Primitive::ARRAY_U64 => quote!(Vec<u64>),
1981 Primitive::ARRAY_I8 => quote!(Vec<i8>),
1982 Primitive::ARRAY_I16 => quote!(Vec<i16>),
1983 Primitive::ARRAY_I32 => quote!(Vec<i32>),
1984 Primitive::ARRAY_I64 => quote!(Vec<i64>),
1985 Primitive::ARRAY_F32 => quote!(Vec<f32>),
1986 Primitive::ARRAY_F64 => quote!(Vec<f64>),
1987 Primitive::ARRAY_STRING => quote!(Vec<String>),
1988 },
1989 FrozenTy::FrozenScalar(scalar) => {
1990 type_ident_from_id(&scalar.reference.id, registry, with_mod).await?
1991 }
1992 FrozenTy::FrozenArray(array) => {
1993 let type_ident = type_ident_from_id(&array.reference.id, registry, with_mod).await?;
1994 quote! { Vec<#type_ident> }
1995 }
1996 })
1997}
1998
1999fn is_dynamic_value_id(id: &Uuid) -> bool {
2005 *id == *arora_types::ty::ARRAY_VALUE_ID || *id == *arora_types::ty::KEY_VALUE_ID
2006}
2007
2008fn dynamic_value_type() -> TokenStream {
2010 quote! { arora_types::value::Value }
2011}
2012
2013async fn type_ident_from_id(
2014 id: &Uuid,
2015 registry: &mut dyn ReadableRegistry,
2016 with_mod: PrefixWithMod,
2017) -> Result<TokenStream, GenerationError> {
2018 if is_dynamic_value_id(id) {
2019 return Ok(dynamic_value_type());
2020 }
2021 let type_def = registry
2022 .get_type(&Selector::Id(id.to_owned()), &VersionReq::STAR)
2023 .await
2024 .map_err(GenerationError::RegistryError)?;
2025 type_ident_from_definition(&type_def, id, registry, with_mod).await
2026}
2027
2028async fn type_ident_from_definition(
2029 type_def: &TypeDefinitionFrozen,
2030 id: &Uuid,
2031 registry: &mut dyn ReadableRegistry,
2032 with_mod: PrefixWithMod,
2033) -> Result<TokenStream, GenerationError> {
2034 Ok(match type_def {
2035 TypeDefinitionFrozen::Primitive(primitive) => match primitive {
2036 PrimitiveKind::Unit => quote! { () },
2037 PrimitiveKind::Boolean => quote!(bool),
2038 PrimitiveKind::U8 => quote!(u8),
2039 PrimitiveKind::U16 => quote!(u16),
2040 PrimitiveKind::U32 => quote!(u32),
2041 PrimitiveKind::U64 => quote!(u64),
2042 PrimitiveKind::I8 => quote!(i8),
2043 PrimitiveKind::I16 => quote!(i16),
2044 PrimitiveKind::I32 => quote!(i32),
2045 PrimitiveKind::I64 => quote!(i64),
2046 PrimitiveKind::F32 => quote!(f32),
2047 PrimitiveKind::F64 => quote!(f64),
2048 PrimitiveKind::String => quote!(String),
2049 PrimitiveKind::ArrayBoolean => quote!(Vec<bool>),
2050 PrimitiveKind::ArrayU8 => quote!(Vec<u8>),
2051 PrimitiveKind::ArrayU16 => quote!(Vec<u16>),
2052 PrimitiveKind::ArrayU32 => quote!(Vec<u32>),
2053 PrimitiveKind::ArrayU64 => quote!(Vec<u64>),
2054 PrimitiveKind::ArrayI8 => quote!(Vec<i8>),
2055 PrimitiveKind::ArrayI16 => quote!(Vec<i16>),
2056 PrimitiveKind::ArrayI32 => quote!(Vec<i32>),
2057 PrimitiveKind::ArrayI64 => quote!(Vec<i64>),
2058 PrimitiveKind::ArrayF32 => quote!(Vec<f32>),
2059 PrimitiveKind::ArrayF64 => quote!(Vec<f64>),
2060 PrimitiveKind::ArrayString => quote!(Vec<String>),
2061 },
2062 TypeDefinitionFrozen::Enumeration(enumeration) => {
2063 type_ident_from_name_and_id(&enumeration.name, id, registry, with_mod)
2064 .await
2065 .map_err(GenerationError::RegistryError)?
2066 }
2067 TypeDefinitionFrozen::Structure(structure) => {
2068 type_ident_from_name_and_id(&structure.name, id, registry, with_mod)
2069 .await
2070 .map_err(GenerationError::RegistryError)?
2071 }
2072 })
2073}
2074
2075async fn type_ident_from_name_and_id(
2076 name: &String,
2077 id: &Uuid,
2078 registry: &mut dyn ReadableRegistry,
2079 with_mod: PrefixWithMod,
2080) -> Result<TokenStream, RegistryError> {
2081 let mod_prefix = match with_mod {
2082 PrefixWithMod::Yes => generated_mod_ident_from_id(id, registry).await?,
2083 PrefixWithMod::No => quote! {},
2084 };
2085 let type_ident = type_ident(name);
2086 Ok(quote! { #mod_prefix #type_ident })
2087}
2088
2089fn type_kind_ident_from_primitive(primitive: &PrimitiveKind) -> TokenStream {
2090 match primitive {
2091 PrimitiveKind::Unit => quote! { TYPE_UNIT },
2092 PrimitiveKind::Boolean => quote! { TYPE_BOOLEAN },
2093 PrimitiveKind::U8 => quote! { TYPE_U8 },
2094 PrimitiveKind::U16 => quote! { TYPE_U16 },
2095 PrimitiveKind::U32 => quote! { TYPE_U32 },
2096 PrimitiveKind::U64 => quote! { TYPE_U64 },
2097 PrimitiveKind::I8 => quote! { TYPE_I8 },
2098 PrimitiveKind::I16 => quote! { TYPE_I16 },
2099 PrimitiveKind::I32 => quote! { TYPE_I32 },
2100 PrimitiveKind::I64 => quote! { TYPE_I64 },
2101 PrimitiveKind::F32 => quote! { TYPE_F32 },
2102 PrimitiveKind::F64 => quote! { TYPE_F64 },
2103 PrimitiveKind::String => quote! { TYPE_STRING },
2104 PrimitiveKind::ArrayBoolean
2105 | PrimitiveKind::ArrayU8
2106 | PrimitiveKind::ArrayU16
2107 | PrimitiveKind::ArrayU32
2108 | PrimitiveKind::ArrayU64
2109 | PrimitiveKind::ArrayI8
2110 | PrimitiveKind::ArrayI16
2111 | PrimitiveKind::ArrayI32
2112 | PrimitiveKind::ArrayI64
2113 | PrimitiveKind::ArrayF32
2114 | PrimitiveKind::ArrayF64
2115 | PrimitiveKind::ArrayString => quote! { TYPE_ARRAY },
2116 }
2117}
2118
2119async fn generated_mod_ident_from_id(
2121 id: &Uuid,
2122 registry: &mut dyn ReadableRegistry,
2123) -> Result<TokenStream, RegistryError> {
2124 let mod_path = registry.resolve_id(id).await?;
2125 let mod_ident = mod_ident_from_path(&mod_path);
2126 Ok(quote! { arora_generated::#mod_ident })
2127}
2128
2129fn mod_ident_from_path(path: &str) -> TokenStream {
2130 let path_parts = path.split(".").collect::<Vec<&str>>();
2131 let path_parts = path_parts
2132 .iter()
2133 .map(|part| format_ident!("{}", part.to_case(Case::Snake)));
2134 quote! { #(#path_parts ::)* }
2135}
2136
2137#[derive(Clone, Copy, Eq, PartialEq)]
2138pub enum CheckType {
2139 Yes,
2141 YesResult,
2143 No,
2144}
2145
2146#[derive(Clone, Copy, Eq, PartialEq)]
2147pub enum PrefixWithMod {
2148 Yes,
2149 No,
2150}
2151
2152#[derive(Clone, Copy, Eq, PartialEq)]
2153pub enum Public {
2154 Yes,
2155 No,
2156}
2157
2158#[derive(Display, Debug)]
2159pub enum GenerationError {
2160 ModuleDeclarationError(ModuleDeclarationError),
2161 RegistryError(RegistryError),
2162 VfsError(VfsError),
2163 IoError(std::io::Error),
2164 Generic(String),
2165}
2166
2167impl std::error::Error for GenerationError {}
2168
2169pub struct RawUuidValue<'a>(pub &'a Uuid);
2171
2172impl<'a> Display for RawUuidValue<'a> {
2173 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2174 write!(f, "{:#04x?}", self.0.as_bytes())
2175 }
2176}
2177
2178impl<'a> ToTokens for RawUuidValue<'a> {
2179 fn to_tokens(&self, tokens: &mut TokenStream) {
2180 let new_tokens: TokenStream = self.to_string().parse().unwrap();
2181 tokens.extend(new_tokens);
2182 }
2183}