melodium_loader/
loader.rs1use crate::package::PackageTrait as Package;
2use crate::package_manager::{PackageManager, PackageManagerConfiguration};
3use crate::{LoadingConfig, PackageInfo};
4use melodium_common::descriptor::{
5 Collection, Context, Entry, Function, Identifier, IdentifierRequirement, Loader as LoaderTrait,
6 LoadingError, LoadingResult, Model, PackageRequirement, Treatment,
7};
8use melodium_repository::network::NetworkRepositoryConfiguration;
9use melodium_repository::{Repository, RepositoryConfig};
10use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard};
11
12#[derive(Debug)]
24pub struct Loader {
25 collection: RwLock<Collection>,
26 package_manager: PackageManager,
27}
28
29impl Loader {
30 pub fn new(config: LoadingConfig) -> Self {
31 Self {
32 collection: RwLock::new(Collection::new()),
33 package_manager: PackageManager::new(PackageManagerConfiguration {
34 repositories: vec![Arc::new(Mutex::new(Repository::new(RepositoryConfig {
35 repository_location: {
36 let mut path = std::env::var_os("MELODIUM_HOME")
37 .map(|var| var.into())
38 .or_else(|| {
39 simple_home_dir::home_dir().map(|mut path| {
40 path.push(".melodium");
41 path
42 })
43 })
44 .unwrap_or_else(|| {
45 let mut path = std::env::temp_dir();
46 path.push("melodium");
47 path
48 });
49 path.push(env!("CARGO_PKG_VERSION"));
50 path
51 },
52 network: if cfg!(feature = "network") {
53 Some(NetworkRepositoryConfiguration::new())
54 } else {
55 None
56 },
57 })))],
58 core_packages: config.core_packages,
59 search_locations: config.search_locations,
60 raw_elements: config.raw_elements,
61 allow_network: cfg!(feature = "network"),
62 }),
63 }
64 }
65
66 pub fn load_package(&self, requirement: &PackageRequirement) -> LoadingResult<()> {
73 self.package_manager
74 .get_package(requirement)
75 .and(LoadingResult::new_success(()))
76 }
77
78 pub fn load_raw(&self, raw_content: Arc<Vec<u8>>) -> LoadingResult<Arc<dyn PackageInfo>> {
87 self.package_manager
88 .add_raw_package(raw_content)
89 .and_then(|pkg| LoadingResult::new_success(Arc::clone(&pkg) as Arc<dyn PackageInfo>))
90 }
91
92 pub fn load(
96 &self,
97 identifier_requirement: &IdentifierRequirement,
98 ) -> LoadingResult<Identifier> {
99 self.get_with_load(identifier_requirement)
100 .and_then(|entry| LoadingResult::new_success(entry.identifier()))
101 }
102
103 pub fn load_all(&self) -> LoadingResult<()> {
109 let mut result = LoadingResult::new_success(());
110 for package in self.package_manager.get_packages() {
111 if let Some(additions) = result.merge_degrade_failure(package.full_collection(self)) {
112 self.add_collection(additions);
113 }
114 }
115 result
116 }
117
118 pub fn build(&self) -> LoadingResult<Arc<Collection>> {
122 let mut result = LoadingResult::new_success(());
123 let collection = Arc::new(self.collection.read().unwrap().clone());
124
125 for package in self.package_manager.get_packages() {
126 result.merge_degrade_failure(package.make_building(&collection));
127 }
128
129 result.and(LoadingResult::new_success(collection))
130 }
131
132 pub fn packages(&self) -> Vec<Arc<dyn PackageInfo>> {
133 self.package_manager
134 .get_packages()
135 .into_iter()
136 .map(|pkg| Arc::clone(&pkg) as Arc<dyn PackageInfo>)
137 .collect()
138 }
139
140 pub fn collection(&self) -> RwLockReadGuard<Collection> {
141 self.collection.read().unwrap()
142 }
143
144 pub fn get_with_load(
145 &self,
146 identifier_requirement: &IdentifierRequirement,
147 ) -> LoadingResult<Entry> {
148 let mut result = LoadingResult::new_success(());
149 let entry = self
150 .collection
151 .read()
152 .unwrap()
153 .get(identifier_requirement)
154 .cloned();
155 if let Some(entry) = entry {
156 result.and_degrade_failure(LoadingResult::new_success(entry))
157 } else if let Some(package) = result.merge_degrade_failure(
158 self.package_manager
159 .get_package(&identifier_requirement.package_requirement()),
160 ) {
161 package
162 .element(self, &identifier_requirement)
163 .and_then(|additions| {
164 self.add_collection(additions);
165 result.and_degrade_failure(LoadingResult::new_success(
166 self.collection
167 .read()
168 .unwrap()
169 .get(identifier_requirement)
170 .unwrap()
171 .clone(),
172 ))
173 })
174 } else {
175 result.and_degrade_failure(LoadingResult::new_failure(LoadingError::no_package(
176 167,
177 identifier_requirement.package_requirement(),
178 )))
179 }
180 }
181
182 fn add_collection(&self, other_collection: Collection) {
183 let existing = self.collection.read().unwrap().identifiers();
184 let mut others = other_collection.identifiers();
185
186 others.retain(|id| !existing.contains(id));
187
188 if !others.is_empty() {
189 let mut collection = self.collection.write().unwrap();
190 for id in &others {
191 collection.insert(other_collection.get(&id.into()).unwrap().clone());
192 }
193 }
194 }
195}
196
197impl LoaderTrait for Loader {
198 fn load_context(
199 &self,
200 identifier_requirement: &IdentifierRequirement,
201 ) -> LoadingResult<Arc<dyn Context>> {
202 self.get_with_load(identifier_requirement)
203 .and_then(|entry| match entry {
204 Entry::Context(context) => LoadingResult::new_success(context),
205 _ => LoadingResult::new_failure(LoadingError::context_expected(
206 168,
207 None,
208 identifier_requirement.clone(),
209 )),
210 })
211 }
212
213 fn load_function(
214 &self,
215 identifier_requirement: &IdentifierRequirement,
216 ) -> LoadingResult<Arc<dyn Function>> {
217 self.get_with_load(identifier_requirement)
218 .and_then(|entry| match entry {
219 Entry::Function(function) => LoadingResult::new_success(function),
220 _ => LoadingResult::new_failure(LoadingError::function_expected(
221 169,
222 None,
223 identifier_requirement.clone(),
224 )),
225 })
226 }
227
228 fn load_model(
229 &self,
230 identifier_requirement: &IdentifierRequirement,
231 ) -> LoadingResult<Arc<dyn Model>> {
232 self.get_with_load(identifier_requirement)
233 .and_then(|entry| match entry {
234 Entry::Model(model) => LoadingResult::new_success(model),
235 _ => LoadingResult::new_failure(LoadingError::model_expected(
236 170,
237 None,
238 identifier_requirement.clone(),
239 )),
240 })
241 }
242
243 fn load_treatment(
244 &self,
245 identifier_requirement: &IdentifierRequirement,
246 ) -> LoadingResult<Arc<dyn Treatment>> {
247 self.get_with_load(identifier_requirement)
248 .and_then(|entry| match entry {
249 Entry::Treatment(treatment) => LoadingResult::new_success(treatment),
250 _ => LoadingResult::new_failure(LoadingError::treatment_expected(
251 171,
252 None,
253 identifier_requirement.clone(),
254 )),
255 })
256 }
257}