1mod db;
2mod macros;
3mod metrics;
4
5use icydb_schema::{
6 build::get_schema,
7 node::{Canister, Entity, Schema, Store},
8};
9use proc_macro2::TokenStream;
10use quote::quote;
11use std::sync::Arc;
12
13#[must_use]
16pub fn generate(canister_path: &str) -> String {
17 let schema = get_schema().expect("schema must be valid before codegen");
19
20 let canister = schema.cast_node::<Canister>(canister_path).unwrap();
22
23 let code = ActorBuilder::new(Arc::new(schema.clone()), canister.clone());
25 let tokens = code.generate();
26
27 tokens.to_string()
28}
29
30pub(crate) struct ActorBuilder {
35 pub(crate) schema: Arc<Schema>,
36 pub(crate) canister: Canister,
37}
38
39impl ActorBuilder {
40 #[must_use]
42 pub const fn new(schema: Arc<Schema>, canister: Canister) -> Self {
43 Self { schema, canister }
44 }
45
46 #[must_use]
48 pub fn generate(self) -> TokenStream {
49 let mut tokens = quote!();
50
51 tokens.extend(db::generate(&self));
53 tokens.extend(metrics::generate(&self));
54
55 quote! {
56 #tokens
57 }
58 }
59
60 #[must_use]
62 pub fn get_stores(&self) -> Vec<(String, Store)> {
63 let canister_path = self.canister.def().path();
64
65 self.schema
66 .filter_nodes::<Store>(|node| node.canister() == canister_path)
67 .map(|(path, store)| (path.to_string(), store.clone()))
68 .collect()
69 }
70
71 #[must_use]
73 pub fn get_entities(&self) -> Vec<(String, Entity)> {
74 let canister_path = self.canister.def().path();
75
76 self.schema
77 .get_nodes::<Entity>()
78 .filter_map(|(path, entity)| {
79 let store = self.schema.cast_node::<Store>(entity.store()).ok()?;
80 if store.canister() == canister_path {
81 Some((path.to_string(), entity.clone()))
82 } else {
83 None
84 }
85 })
86 .collect()
87 }
88}