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, Identified, Identifier, IdentifierRequirement,
6 Loader as LoaderTrait, LoadingError, LoadingResult, Model, PackageRequirement, Treatment,
7};
8use std::collections::HashMap;
9use std::sync::{Arc, RwLock, RwLockReadGuard};
10
11#[derive(Debug)]
23pub struct Loader {
24 collection: RwLock<Collection>,
25 package_manager: PackageManager,
26}
27
28impl Loader {
29 pub fn new(config: LoadingConfig) -> Self {
30 Self {
31 collection: RwLock::new(Collection::new()),
32 package_manager: PackageManager::new(PackageManagerConfiguration {
33 repositories: vec![
34 #[cfg(feature = "filesystem")]
35 Arc::new(std::sync::Mutex::new(melodium_repository::Repository::new(
36 melodium_repository::RepositoryConfig {
37 repository_location: {
38 let mut path = std::env::var_os("MELODIUM_HOME")
39 .map(|var| var.into())
40 .or_else(|| {
41 simple_home_dir::home_dir().map(|mut path| {
42 path.push(".melodium");
43 path
44 })
45 })
46 .unwrap_or_else(|| {
47 let mut path = std::env::temp_dir();
48 path.push("melodium");
49 path
50 });
51 path.push(env!("CARGO_PKG_VERSION"));
52 path
53 },
54 network: if cfg!(feature = "network") {
55 Some(melodium_repository::network::NetworkRepositoryConfiguration::new())
56 } else {
57 None
58 },
59 },
60 ))),
61 ],
62 core_packages: config.core_packages,
63 search_locations: config.search_locations,
64 raw_elements: config.raw_elements,
65 allow_network: cfg!(feature = "network"),
66 }),
67 }
68 }
69
70 pub fn load_package(
77 &self,
78 requirement: &PackageRequirement,
79 ) -> LoadingResult<Arc<dyn PackageInfo>> {
80 self.package_manager
81 .get_package(requirement)
82 .and_then(|pkg| LoadingResult::new_success(Arc::clone(&pkg) as Arc<dyn PackageInfo>))
83 }
84
85 pub fn load_raw(&self, raw_content: Arc<Vec<u8>>) -> LoadingResult<Arc<dyn PackageInfo>> {
92 self.package_manager
93 .add_raw_package(raw_content)
94 .and_then(|pkg| LoadingResult::new_success(Arc::clone(&pkg) as Arc<dyn PackageInfo>))
95 }
96
97 pub fn load_mapped(
104 &self,
105 mapped_content: HashMap<String, Vec<u8>>,
106 ) -> LoadingResult<Arc<dyn PackageInfo>> {
107 self.package_manager
108 .add_map_package(mapped_content)
109 .and_then(|pkg| LoadingResult::new_success(Arc::clone(&pkg) as Arc<dyn PackageInfo>))
110 }
111
112 pub fn load(
116 &self,
117 identifier_requirement: &IdentifierRequirement,
118 ) -> LoadingResult<Identifier> {
119 self.get_with_load(identifier_requirement)
120 .and_then(|entry| LoadingResult::new_success(entry.identifier().clone()))
121 }
122
123 pub fn load_all(&self) -> LoadingResult<()> {
129 let mut result = LoadingResult::new_success(());
130 for package in self.package_manager.get_packages() {
131 if let Some(additions) = result.merge_degrade_failure(package.full_collection(self)) {
132 self.add_collection(additions);
133 }
134 }
135 result
136 }
137
138 pub fn build(&self) -> LoadingResult<Arc<Collection>> {
142 let mut result = LoadingResult::new_success(());
143 let collection = Arc::new(self.collection.read().unwrap().clone());
144
145 for package in self.package_manager.get_packages() {
146 result.merge_degrade_failure(package.make_building(&collection));
147 }
148
149 result.and(LoadingResult::new_success(collection))
150 }
151
152 pub fn packages(&self) -> Vec<Arc<dyn PackageInfo>> {
153 self.package_manager
154 .get_packages()
155 .into_iter()
156 .map(|pkg| Arc::clone(&pkg) as Arc<dyn PackageInfo>)
157 .collect()
158 }
159
160 pub fn collection(&'_ self) -> RwLockReadGuard<'_, Collection> {
161 self.collection.read().unwrap()
162 }
163
164 pub fn get_with_load(
165 &self,
166 identifier_requirement: &IdentifierRequirement,
167 ) -> LoadingResult<Entry> {
168 let mut result = LoadingResult::new_success(());
169 let entry = self
170 .collection
171 .read()
172 .unwrap()
173 .get(identifier_requirement)
174 .cloned();
175 if let Some(entry) = entry {
176 result.and_degrade_failure(LoadingResult::new_success(entry))
177 } else if let Some(package) = result.merge_degrade_failure(
178 self.package_manager
179 .get_package(&identifier_requirement.package_requirement()),
180 ) {
181 package
182 .element(self, &identifier_requirement)
183 .and_then(|additions| {
184 self.add_collection(additions);
185 if let Some(element) = self
186 .collection
187 .read()
188 .unwrap()
189 .get(identifier_requirement)
190 .cloned()
191 {
192 result.and_degrade_failure(LoadingResult::new_success(element))
193 } else {
194 result.and_degrade_failure(LoadingResult::new_failure(
195 LoadingError::not_found(249, identifier_requirement.to_string()),
196 ))
197 }
198 })
199 } else {
200 result.and_degrade_failure(LoadingResult::new_failure(LoadingError::no_package(
201 167,
202 identifier_requirement.package_requirement(),
203 )))
204 }
205 }
206
207 fn add_collection(&self, other_collection: Collection) {
208 let existing = self.collection.read().unwrap().identifiers();
209 let mut others = other_collection.identifiers();
210
211 others.retain(|id| !existing.contains(id));
212
213 if !others.is_empty() {
214 let mut collection = self.collection.write().unwrap();
215 for id in &others {
216 collection.insert(other_collection.get(&id.into()).unwrap().clone());
217 }
218 }
219 }
220}
221
222impl LoaderTrait for Loader {
223 fn load_context(
224 &self,
225 identifier_requirement: &IdentifierRequirement,
226 ) -> LoadingResult<Arc<dyn Context>> {
227 self.get_with_load(identifier_requirement)
228 .and_then(|entry| match entry {
229 Entry::Context(context) => LoadingResult::new_success(context),
230 _ => LoadingResult::new_failure(LoadingError::context_expected(
231 168,
232 None,
233 identifier_requirement.clone(),
234 )),
235 })
236 }
237
238 fn load_function(
239 &self,
240 identifier_requirement: &IdentifierRequirement,
241 ) -> LoadingResult<Arc<dyn Function>> {
242 self.get_with_load(identifier_requirement)
243 .and_then(|entry| match entry {
244 Entry::Function(function) => LoadingResult::new_success(function),
245 _ => LoadingResult::new_failure(LoadingError::function_expected(
246 169,
247 None,
248 identifier_requirement.clone(),
249 )),
250 })
251 }
252
253 fn load_model(
254 &self,
255 identifier_requirement: &IdentifierRequirement,
256 ) -> LoadingResult<Arc<dyn Model>> {
257 self.get_with_load(identifier_requirement)
258 .and_then(|entry| match entry {
259 Entry::Model(model) => LoadingResult::new_success(model),
260 _ => LoadingResult::new_failure(LoadingError::model_expected(
261 170,
262 None,
263 identifier_requirement.clone(),
264 )),
265 })
266 }
267
268 fn load_treatment(
269 &self,
270 identifier_requirement: &IdentifierRequirement,
271 ) -> LoadingResult<Arc<dyn Treatment>> {
272 self.get_with_load(identifier_requirement)
273 .and_then(|entry| match entry {
274 Entry::Treatment(treatment) => LoadingResult::new_success(treatment),
275 _ => LoadingResult::new_failure(LoadingError::treatment_expected(
276 171,
277 None,
278 identifier_requirement.clone(),
279 )),
280 })
281 }
282}