blackbox_core/
compiler.rs1use std::collections::HashSet;
2
3use blackbox_cast::*;
4
5use crate::{
6 builder::{ModuleBuilder, ProviderBuilder},
7 container::Container,
8 factory::Factory,
9 injectable::IInjectable,
10 instance_wrapper::{ContextId, InquirerId, InstanceToken, Scope},
11 module::{Module, ModuleToken},
12 reference::Ref,
13 reference_mut::RefMut,
14};
15
16pub struct ProviderCompilerContext {
17 pub inquirer_id: InquirerId,
18 pub context_id: ContextId,
19}
20impl ProviderCompilerContext {
21 pub fn new(context_id: ContextId, inquirer_id: InquirerId) -> ProviderCompilerContext {
22 ProviderCompilerContext {
23 context_id,
24 inquirer_id,
25 }
26 }
27}
28
29pub trait ProviderCompiler {
30 fn __blackbox_build(provider_builder: Ref<ProviderBuilder>);
31}
32
33pub struct ModuleCompilerContext {
34 pub stack: HashSet<ModuleToken>,
35 pub current_depth: u32,
36}
37
38impl ModuleCompilerContext {
39 pub fn new() -> ModuleCompilerContext {
40 ModuleCompilerContext {
41 stack: HashSet::new(),
42 current_depth: 0,
43 }
44 }
45}
46
47pub trait ModuleCompiler {
48 fn __blackbox_build(module_builder: Ref<ModuleBuilder>);
49}
50
51pub fn make_instance<T: Factory + CastFrom>(
52 token: InstanceToken,
53 module: RefMut<Module>,
54 container: RefMut<Container>,
55 context: RefMut<ProviderCompilerContext>,
56) -> Ref<dyn IInjectable> {
57 let instance_wrapper = container
58 .as_ref()
59 .get_provider_in_module(&token, module.clone())
60 .expect(
61 format!(
62 "The {} provider in the {} module was not found",
63 &token,
64 &module.as_ref().get_token(),
65 )
66 .as_ref(),
67 );
68
69 let scope = instance_wrapper.as_ref().get_scope();
70
71 match scope {
72 Scope::Transient => {
73 let context_id = context.as_ref().context_id.clone();
74 let inquirer_id = context.as_ref().inquirer_id.clone();
75
76 if let Some(instance) = instance_wrapper
77 .as_ref()
78 .get_instance_by_inquirer_id(&inquirer_id, &context_id)
79 {
80 return instance;
81 }
82
83 let instance = T::__blackbox_create().cast::<dyn IInjectable>().unwrap();
84
85 instance_wrapper.as_mut().set_instance_by_inquirer_id(
86 inquirer_id,
87 context_id,
88 instance.clone(),
89 );
90
91 return instance;
92 }
93 Scope::Singleton => {
94 if let Some(instance) = instance_wrapper.as_ref().get_instance() {
95 return instance;
96 }
97
98 let instance = T::__blackbox_create().cast::<dyn IInjectable>().unwrap();
99
100 instance_wrapper.as_mut().set_instance(instance.clone());
101
102 return instance;
103 }
104 _ => {
105 panic!("Unknown provider scope");
106 }
107 }
108}
109
110pub fn get_instance<T: Factory + CastFrom>(
111 token: InstanceToken,
112 module: RefMut<Module>,
113 container: RefMut<Container>,
114 context: RefMut<ProviderCompilerContext>,
115) -> Ref<T> {
116 let instance_wrapper = container
117 .as_ref()
118 .get_provider_in_module(&token, module.clone())
119 .expect(
120 format!(
121 "The {} provider in the {} module was not found",
122 &token,
123 &module.as_ref().get_token(),
124 )
125 .as_ref(),
126 );
127
128 let scope = instance_wrapper.as_ref().get_scope();
129
130 match scope {
131 Scope::Transient => {
132 let context_id = context.as_ref().context_id.clone();
133 let inquirer_id = context.as_ref().inquirer_id.clone();
134
135 return instance_wrapper
136 .as_mut()
137 .get_instance_by_inquirer_id(&inquirer_id, &context_id)
138 .expect(
139 format!(
140 "The {} instance of the {} inquirer was not found",
141 &token, &inquirer_id,
142 )
143 .as_ref(),
144 )
145 .cast::<T>()
146 .unwrap();
147 }
148 Scope::Singleton => {
149 return instance_wrapper
150 .as_mut()
151 .get_instance()
152 .expect(format!("The {} static instance was not found", &token,).as_ref())
153 .cast::<T>()
154 .unwrap();
155 }
156 _ => {
157 panic!("Unknown provider scope");
158 }
159 }
160}
161
162