1#![warn(missing_docs)]
2
3#[macro_use] extern crate log;
29extern crate rustc_hash;
30extern crate failure;
31#[macro_use] extern crate failure_derive;
32extern crate walkdir;
33extern crate typenum;
34extern crate generic_array;
35#[macro_use] extern crate downcast_rs;
36extern crate zip;
37#[cfg(feature = "serde")] extern crate serde;
38
39#[cfg(test)] mod tests;
40
41pub mod source;
43
44use crate::source::{PackageError, Source, SourceManager, SourceId, TrustLevel};
45
46use rustc_hash::FxHasher;
47use generic_array::{GenericArray, sequence::GenericSequence};
48use generic_array::typenum::U1024;
49use downcast_rs::Downcast;
50
51use std::any::TypeId;
52use std::cell::{RefCell, Ref, RefMut, Cell};
53use std::collections::HashMap;
54use std::fmt::{Debug, Formatter};
55use std::hash::{BuildHasherDefault, Hash, Hasher};
56use std::rc::Rc;
57use std::io::{Read, Seek};
58use std::marker::{Sized, PhantomData};
59use std::time::Instant;
60
61#[cfg(feature = "serde")]
62use serde::{Serialize, Deserialize};
63
64pub struct DataId<T : DataObject + 'static>
68{
69 index : usize,
70 _phantom : PhantomData<T>
71}
72
73impl<T : DataObject + 'static> DataId<T>
74{
75 pub fn new(index : usize) -> DataId<T>
78 {
79 DataId
80 {
81 index,
82 _phantom : PhantomData
83 }
84 }
85
86 pub fn index(&self) -> usize
89 {
90 self.index
91 }
92}
93
94impl<T : DataObject + 'static> Clone for DataId<T>
95{
96 fn clone(&self) -> Self
97 {
98 DataId
99 {
100 index : self.index,
101 _phantom : Default::default()
102 }
103 }
104}
105
106impl<T : DataObject + 'static> Copy for DataId<T> {}
107
108impl<T : DataObject + 'static> Default for DataId<T>
109{
110 fn default() -> Self
111 {
112 DataId::new(0)
113 }
114}
115
116impl<T : DataObject + 'static> Debug for DataId<T>
117{
118 fn fmt(&self, f : &mut Formatter<'_>) -> std::fmt::Result
119 {
120 self.index.fmt(f)
121 }
122}
123
124impl<T: DataObject + 'static> PartialEq<Self> for DataId<T>
125{
126 fn eq(&self, other : &Self) -> bool
127 {
128 self.index.eq(&other.index)
129 }
130}
131
132impl<T : DataObject + 'static> Eq for DataId<T> {}
133
134impl<T : DataObject + 'static> Hash for DataId<T>
135{
136 fn hash<H : Hasher>(&self, state : &mut H)
137 {
138 self.index.hash(state)
139 }
140}
141
142type DataStoreTypeMax = U1024;
143
144#[derive(Debug, PartialEq)]
146pub enum DataStoreOk
147{
148 Loaded,
150 AlreadyLoaded,
152}
153
154#[derive(Debug, Fail)]
156pub enum DataError
157{
158 #[fail(display = "The package was not found")]
160 PackageNotFound,
161 #[fail(display = "The package source was not trusted")]
163 SourceNotTrusted,
164 #[fail(display = "The data object was not found")]
166 DataNotFound,
167 #[fail(display = "Invalid character in name")]
169 BadName,
170 #[fail(display = "Invalid source ID")]
172 BadSource,
173 #[fail(display = "Operation not supported")]
175 NotSupported,
176 #[fail(display = "Package source failure: {}", _0)]
179 PackageSourceError(PackageError),
180 #[fail(display = "{}", _0)]
182 IoError(#[cause] std::io::Error),
183 #[fail(display = "The data object contained invalid data: {}", _0)]
185 BadData(String)
186}
187
188impl From<PackageError> for DataError
189{
190 fn from(error : PackageError) -> Self
191 {
192 DataError::PackageSourceError(error)
193 }
194}
195
196#[derive(Debug, Fail)]
198pub enum PreparedStoreError
199{
200 #[fail(display = "The provided DataStore is already associated with a PreparedStore.")]
203 AlreadyConnected,
204 #[fail(display = "The provided DataStore is not the one used to create this PreparedStore.")]
207 WrongDataStore
208}
209
210#[derive(Debug, Clone, Copy, Eq, PartialEq)]
212pub enum LoadErrorMode
213{
214 Fatal,
216 Warning
218}
219
220#[derive(Debug, Copy, Clone, Eq, PartialEq)]
222pub enum TrustPolicy
223{
224 UntrustedOk,
226 TrustRequired
228}
229
230impl From<std::io::Error> for DataError
231{
232 fn from(error : std::io::Error) -> DataError
233 {
234 DataError::IoError(error)
235 }
236}
237
238struct DataIdGeneration<T : DataObject + 'static>
239{
240 id : DataId<T>,
241 generation : u64
242}
243
244impl<T : DataObject + 'static> Clone for DataIdGeneration<T>
245{
246 fn clone(&self) -> Self
247 {
248 DataIdGeneration
249 {
250 id : self.id,
251 generation : self.generation
252 }
253 }
254}
255
256struct LoadedData<T : DataObject + 'static>
257{
258 data_object : T,
259 id_gen : DataIdGeneration<T>,
260 pathname : String
261}
262
263#[cfg(feature = "serde")]
264fn data_id_default<T : DataObject + 'static>() -> Cell<DataId<T>>
265{
266 Cell::new(DataId::new(usize::MAX))
267}
268
269#[cfg(feature = "serde")]
270fn use_token_default<T : DataObject + 'static>() -> RefCell<Option<PackageUseToken<T>>>
271{
272 RefCell::new(None)
273}
274
275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
288pub struct DataHandle<T : DataObject + 'static>
289{
290 #[cfg_attr(feature = "serde", serde(rename = "pkg"))]
291 #[cfg_attr(feature = "serde", serde(alias = "package"))]
292 package : String,
293 #[cfg_attr(feature = "serde", serde(rename = "pth"))]
294 #[cfg_attr(feature = "serde", serde(alias = "path"))]
295 path : String,
296 #[cfg_attr(feature = "serde", serde(skip, default = "data_id_default"))]
297 data_id : Cell<DataId<T>>,
298 #[cfg_attr(feature = "serde", serde(skip, default = "use_token_default"))]
299 use_token : RefCell<Option<PackageUseToken<T>>>,
300 #[cfg_attr(feature = "serde", serde(skip))]
301 _phantom : PhantomData<T>
302}
303
304impl<T : DataObject + 'static> Default for DataHandle<T>
305{
306 fn default() -> Self
307 {
308 DataHandle::null()
309 }
310}
311
312impl<T : DataObject + 'static> Clone for DataHandle<T>
313{
314 fn clone(&self) -> Self
315 {
316 DataHandle
317 {
318 package : self.package.clone(),
319 path : self.path.clone(),
320 data_id : self.data_id.clone(),
321 use_token : self.use_token.clone(),
322 _phantom : PhantomData
323 }
324 }
325}
326
327impl<T : DataObject + 'static> Debug for DataHandle<T>
328{
329 fn fmt(&self, f : &mut Formatter) -> std::fmt::Result
330 {
331 write!(f, "DataHandle {{ package: {:?}, path: {:?}, data_id: {:?} }}", self.package, self.path, self.data_id)
332 }
333}
334
335impl<T : DataObject + 'static> DataHandle<T>
336{
337 pub fn null() -> DataHandle<T>
340 {
341 DataHandle::<T>
342 {
343 package : String::new(),
344 path : String::new(),
345 data_id : Cell::new(DataId::new(usize::MAX)),
346 use_token : RefCell::new(None),
347 _phantom : PhantomData
348 }
349 }
350
351 pub fn with_path(package : &str, path : &str) -> DataHandle<T>
354 {
355 DataHandle::<T>
356 {
357 package : package.to_string(),
358 path : path.to_string(),
359 data_id : Cell::new(DataId::new(usize::MAX)),
360 use_token : RefCell::new(None),
361 _phantom : PhantomData
362 }
363 }
364
365 pub fn clone_without_path(&self) -> DataHandle<T>
369 {
370 DataHandle::<T>
371 {
372 package : String::new(),
373 path : String::new(),
374 data_id : self.data_id.clone(),
375 use_token : self.use_token.clone(),
376 _phantom : PhantomData
377 }
378 }
379
380 pub fn set_path(&mut self, package : &str, path : &str)
383 {
384 self.package.clear();
385 self.package.push_str(package);
386 self.path.clear();
387 self.path.push_str(path);
388 self.data_id = Cell::new(DataId::new(usize::MAX));
389 self.use_token = RefCell::new(None);
390 }
391
392 pub fn package(&self) -> &String
394 {
395 &self.package
396 }
397
398 pub fn path(&self) -> &String
400 {
401 &self.path
402 }
403
404 pub fn id(&self) -> DataId<T>
407 {
408 let id = self.data_id.get();
409
410 if id.index == usize::MAX
411 {
412 return DataId::new(0);
413 }
414
415 id
416 }
417
418 #[inline(always)]
420 pub fn resolved(&self) -> bool
421 {
422 self.data_id.get().index != usize::MAX
423 }
424
425 #[inline(always)]
429 pub fn resolve(&self, data_res : &mut DataStore<T>, load_error : LoadErrorMode) -> DataId<T>
430 {
431 if !self.resolved()
432 {
433 match data_res.get_id_mut(&self.package, &self.path)
434 {
435 Ok(data_id) => self.data_id.set(data_id),
436 Err(error) =>
437 {
438 if load_error == LoadErrorMode::Fatal
439 {
440 panic!("Failed to load \"{}/{}/{}\": {}",
441 self.package, T::folder_name(), self.path, error.to_string());
442 }
443 else
444 {
445 warn!("Failed to load \"{}/{}/{}\": {}",
446 self.package, T::folder_name(), self.path, error.to_string());
447 self.data_id.set(DataId::new(0));
448 }
449 }
450 }
451
452 self.use_token.replace(data_res.package_use_token(&self.package));
453 }
454
455 self.data_id.get()
456 }
457
458 #[inline(always)]
461 pub fn get<'a, 'b : 'a>(&self, data_res : &'b mut DataStore<T>, load_error : LoadErrorMode) -> Option<&'a T>
462 {
463 let id = self.resolve(data_res, load_error);
464
465 data_res.get(id)
466 }
467
468 #[inline(always)]
471 pub fn get_mut<'a, 'b : 'a>(&self, data_res : &'b mut DataStore<T>, load_error : LoadErrorMode) -> Option<&'a mut T>
472 {
473 let id = self.resolve(data_res, load_error);
474
475 data_res.get_mut(id)
476 }
477
478 #[inline(always)]
481 pub fn get_if_resolved<'a, 'b : 'a>(&self, data_res : &'b DataStore<T>) -> Option<&'a T>
482 {
483 data_res.get(self.id())
484 }
485
486 #[inline(always)]
489 pub fn get_mut_if_resolved<'a, 'b : 'a>(&self, data_res : &'b mut DataStore<T>) -> Option<&'a mut T>
490 {
491 data_res.get_mut(self.id())
492 }
493
494 #[inline(always)]
497 pub fn resolve_if_loaded(&self, data_res : &DataStore<T>) -> DataId<T>
498 {
499 if !self.resolved()
500 {
501 match data_res.get_id(&self.package, &self.path)
502 {
503 Ok(data_id) => self.data_id.set(data_id),
504 Err(_) => {}
505 }
506
507 self.use_token.replace(data_res.package_use_token(&self.package));
508 }
509
510 self.data_id.get()
511 }
512}
513
514pub struct PackageUseToken<T : DataObject + 'static>
516{
517 use_count : Rc<String>,
518 _phantom : PhantomData<T>
519}
520
521impl<T : DataObject + 'static> PackageUseToken<T>
522{
523 fn new(package : &str) -> PackageUseToken<T>
524 {
525 PackageUseToken
526 {
527 use_count : Rc::new(package.to_string()),
528 _phantom : PhantomData
529 }
530 }
531
532 pub fn package(&self) -> &String
534 {
535 self.use_count.as_ref()
536 }
537
538 pub fn uses(&self) -> usize
540 {
541 Rc::strong_count(&self.use_count).saturating_sub(1)
544 }
545}
546
547impl<T : DataObject + 'static> Clone for PackageUseToken<T>
548{
549 fn clone(&self) -> Self
550 {
551 PackageUseToken
552 {
553 use_count : Rc::clone(&self.use_count),
554 _phantom : PhantomData
555 }
556 }
557}
558
559impl<T : DataObject + 'static> Debug for PackageUseToken<T>
560{
561 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result
562 {
563 write!(f, "PackageUseToken<{}> {{ uses: {} }}", std::any::type_name::<T>(), self.uses())
564 }
565}
566
567pub trait ReadSeek : Read + Seek {}
570
571impl<T: Read + Seek> ReadSeek for T {}
572
573pub trait DataObject
576{
577 fn folder_name() -> &'static str where Self : Sized;
579 fn trust_policy() -> TrustPolicy;
581 fn want_file(pathname : &str) -> bool where Self : Sized;
583 fn from_package_source(source : &mut Box<dyn Source>, package_name : &str, pathname : &str) -> Result<Self, DataError> where Self : Sized;
585 #[allow(unused_variables)]
587 fn write(&mut self, package_name : &str, pathname : &str, source : &mut Box<dyn Source>) -> Result<(), DataError> { Err(DataError::NotSupported) }
588 fn generation(&self) -> u64 { 0 }
590 #[allow(unused_variables)]
592 fn set_generation(&mut self, generation : u64) {}
593}
594
595pub struct DataStore<T : DataObject + 'static>
597{
598 source_manager : Rc<RefCell<SourceManager>>,
599 unloaded_packages : HashMap<String, HashMap<String, DataIdGeneration<T>, BuildHasherDefault<FxHasher>>, BuildHasherDefault<FxHasher>>,
600 data_list : Vec<Option<T>>,
601 data_map : HashMap<String, HashMap<String, DataIdGeneration<T>, BuildHasherDefault<FxHasher>>, BuildHasherDefault<FxHasher>>,
602 package_use_tokens : HashMap<String, PackageUseToken<T>, BuildHasherDefault<FxHasher>>,
603 next_index : usize,
604 prepare_info : Option<Rc<RefCell<PrepareInfo<T>>>>
605}
606
607impl<T : DataObject + 'static> DataStore<T>
608{
609 pub fn new(source_manager : Rc<RefCell<SourceManager>>) -> DataStore<T>
612 {
613 DataStore::<T>
614 {
615 source_manager,
616 unloaded_packages : HashMap::with_hasher(BuildHasherDefault::<FxHasher>::default()),
617 data_list : Vec::new(),
618 data_map : HashMap::with_hasher(BuildHasherDefault::<FxHasher>::default()),
619 package_use_tokens : HashMap::with_hasher(BuildHasherDefault::<FxHasher>::default()),
620 next_index : 1,
621 prepare_info : None
622 }
623 }
624
625 pub fn load_package(&mut self, package_name : &str) -> Result<DataStoreOk, DataError>
627 {
628 if package_name.find('/').is_some()
629 {
630 return Err(DataError::BadName);
631 }
632
633 if self.package_loaded(package_name)
634 {
635 return Ok(DataStoreOk::AlreadyLoaded);
636 }
637
638 let load_start = Instant::now();
639
640 if let Some(mut source) = self.source_manager.borrow_mut().package_source(package_name)
641 {
642 if !source.has_package(package_name)
643 {
644 return Err(DataError::PackageNotFound);
645 }
646
647 if T::trust_policy() == TrustPolicy::TrustRequired
648 && source.trust_level(package_name) != TrustLevel::TrustedSource
649 {
650 return Err(DataError::SourceNotTrusted);
651 }
652
653 let type_folder = T::folder_name();
654
655 if type_folder.find('/').is_some()
656 {
657 return Err(DataError::BadName);
658 }
659
660 let iter : Vec<Result<String, PackageError>> = source.iter_entries(package_name, type_folder).collect();
661
662 let mut loaded_items : Vec<LoadedData<T>> = Vec::new();
663 let mut new_index = self.next_index;
664
665 if let Some(old_package_map) = self.unloaded_packages.get(package_name)
666 {
667 self.data_map.insert(package_name.to_string(), old_package_map.clone());
668 }
669 self.unloaded_packages.remove(package_name);
670
671 let package_map = self.data_map.entry(package_name.to_string()).or_insert(HashMap::with_hasher(BuildHasherDefault::<FxHasher>::default()));
672
673 for entry in iter
674 {
675 let pathname = entry.map_err(|error| DataError::PackageSourceError(error))?;
676
677 if pathname.starts_with('/') || pathname.ends_with('/')
678 {
679 return Err(DataError::BadName);
680 }
681
682 if !T::want_file(&pathname)
683 {
684 continue;
685 }
686
687 let full_pathname = format!("{}/{}", type_folder, pathname);
688
689 let mut data_object = T::from_package_source(&mut source, &package_name, &full_pathname)?;
690 let index_gen : DataIdGeneration<T>;
691
692 if let Some(entry) = package_map.get(&pathname)
693 {
694 let mut generation = entry.generation + 1;
695
696 if generation == 0
697 {
698 warn!("Generation overflow for package item {}!", pathname);
699 generation = 1;
700 }
701
702 index_gen = DataIdGeneration
703 {
704 id: entry.id,
705 generation
706 };
707 }
708 else
709 {
710 index_gen = DataIdGeneration
711 {
712 id: DataId::new(new_index),
713 generation : 1
714 };
715 new_index += 1;
716 }
717
718 data_object.set_generation(index_gen.generation);
719
720 loaded_items.push(LoadedData::<T> { data_object, id_gen: index_gen, pathname });
721 }
722
723 self.next_index = new_index;
724
725 while self.data_list.len() <= self.next_index
726 {
727 self.data_list.push(None);
728 }
729
730 for item in loaded_items.drain(..)
731 {
732 self.data_list[item.id_gen.id.index] = Some(item.data_object);
733 package_map.insert(item.pathname, item.id_gen.clone());
734
735 if let Some(prepare_info) = &self.prepare_info
736 {
737 prepare_info.borrow_mut().to_prepare.insert(item.id_gen.id, PrepareType::FullPrepare);
738 }
739 }
740
741 if !self.package_use_tokens.contains_key(package_name)
742 {
743 self.package_use_tokens.insert(package_name.to_string(), PackageUseToken::new(package_name));
744 }
745 }
746 else
747 {
748 return Err(DataError::PackageNotFound);
749 }
750
751 let load_time = (Instant::now() - load_start).as_millis();
752
753 info!("Loaded package \"{}/{}\" in {} ms", package_name, T::folder_name(), load_time);
754
755 Ok(DataStoreOk::Loaded)
756 }
757
758 pub fn get_id(&self, package_name : &str, pathname : &str) -> Result<DataId<T>, DataError>
760 {
761 if let Some(package_map) = self.data_map.get(package_name)
762 {
763 if let Some(id) = package_map.get(pathname)
764 {
765 return Ok(id.id);
766 }
767 else
768 {
769 return Err(DataError::DataNotFound);
770 }
771 }
772
773 Err(DataError::PackageNotFound)
774 }
775
776 pub fn get_id_mut(&mut self, package_name : &str, pathname : &str) -> Result<DataId<T>, DataError>
779 {
780 if let Some(package_map) = self.data_map.get(package_name)
781 {
782 if let Some(id) = package_map.get(pathname)
783 {
784 return Ok(id.id);
785 }
786 else
787 {
788 return Err(DataError::DataNotFound);
789 }
790 }
791 else
792 {
793 self.load_package(package_name)?;
794
795 return self.get_id_mut(package_name, pathname);
796 }
797 }
798
799 pub fn get(&self, id : DataId<T>) -> Option<&T>
802 {
803 if id.index >= self.data_list.len()
804 {
805 return None;
806 }
807
808 match &self.data_list[id.index]
809 {
810 Some(data) => Some(data),
811 None => None
812 }
813 }
814
815 pub fn get_mut(&mut self, id : DataId<T>) -> Option<&mut T>
818 {
819 if id.index >= self.data_list.len()
820 {
821 return None;
822 }
823
824 match &mut self.data_list[id.index]
825 {
826 Some(data) => Some(data),
827 None => None
828 }
829 }
830
831 pub fn list_package_contents(&self, package_name : &str) -> Vec<String>
835 {
836 let mut listing : Vec<String> = Vec::new();
837
838 if let Some(package_map) = self.data_map.get(package_name)
839 {
840 for (name, id_gen) in package_map.iter()
841 {
842 if self.data_list[id_gen.id.index].is_some()
843 {
844 listing.push(name.clone());
845 }
846 }
847
848 listing.sort();
849 }
850
851 listing
852 }
853
854 pub fn unload_package(&mut self, package_name : &str) -> bool
858 {
859 if let Some(package_map) = self.data_map.get_mut(package_name)
860 {
861 for id_gen in package_map.values_mut()
862 {
863 if let Some(data) = &self.data_list[id_gen.id.index]
864 {
865 id_gen.generation = data.generation();
866 }
867
868 self.data_list[id_gen.id.index] = None;
869
870 if let Some(prepare_info) = &self.prepare_info
871 {
872 prepare_info.borrow_mut().to_prepare.insert(id_gen.id, PrepareType::FullPrepare);
873 }
874 }
875
876 self.unloaded_packages.insert(package_name.to_string(), package_map.clone());
877 }
878 else
879 {
880 return false;
881 }
882
883 self.data_map.remove(package_name);
884
885 info!("Unloaded package \"{}/{}\"", package_name, T::folder_name());
886
887 true
888 }
889
890 pub fn unload_all(&mut self)
894 {
895 self.unload_all_internal();
896 info!("Unloaded all packages for \"{}\"", T::folder_name());
897 }
898
899 pub fn unload_unused(&mut self)
901 {
902 self.unload_unused_internal()
903 }
904
905 pub fn package_loaded(&self, package_name : &str) -> bool
907 {
908 self.data_map.contains_key(package_name)
909 }
910
911 pub fn package_use_token(&self, package_name : &str) -> Option<PackageUseToken<T>>
914 {
915 self.package_use_tokens.get(package_name).cloned()
916 }
917
918 pub fn save(&mut self, package_name : &str, pathname : &str, source_id : SourceId) -> Result<(), DataError>
920 {
921 let id = self.get_id_mut(package_name, pathname)?;
922 let data = match &mut self.data_list[id.index]
923 {
924 Some(data) => { data }
925 None => { return Err(DataError::DataNotFound); }
926 };
927
928 if let Some(source) = self.source_manager.borrow_mut().source(source_id)
929 {
930 let type_folder = T::folder_name();
931 let full_pathname = format!("{}/{}", type_folder, pathname);
932
933 return data.write(&package_name, &full_pathname, source);
934 }
935 else
936 {
937 return Err(DataError::BadSource);
938 }
939 }
940
941 pub fn reprepare(&mut self, id : DataId<T>) -> bool
945 {
946 if let Some(prepare_info) = &self.prepare_info
947 {
948 if id.index >= self.data_list.len()
949 {
950 return false;
951 }
952
953 match &mut self.data_list[id.index]
954 {
955 Some(_) =>
956 {
957 if !prepare_info.borrow_mut().to_prepare.contains_key(&id)
958 {
959 prepare_info.borrow_mut().to_prepare.insert(id, PrepareType::Reprepare);
960 return true;
961 }
962 },
963 _ => ()
964 }
965 }
966
967 false
968 }
969
970 pub fn reload(&mut self, package_name : &str, pathname : &str) -> Result<(), DataError>
972 {
973 let id = self.get_id_mut(package_name, pathname)?;
974
975 if let Some(mut source) = self.source_manager.borrow_mut().package_source(package_name)
976 {
977 let type_folder = T::folder_name();
978
979 if pathname.starts_with('/') || pathname.ends_with('/')
980 {
981 return Err(DataError::BadName);
982 }
983
984 if !T::want_file(&pathname)
985 {
986 return Err(DataError::DataNotFound);
987 }
988
989 let full_pathname = format!("{}/{}", type_folder, pathname);
990 let data_object = T::from_package_source(&mut source, &package_name, &full_pathname)?;
991
992 self.data_list[id.index] = Some(data_object);
993 }
994 else
995 {
996 return Err(DataError::DataNotFound);
997 }
998
999 self.reprepare(id);
1000
1001 Ok(())
1002 }
1003
1004 pub fn load_direct(&self, package_name : &str, pathname : &str, source_id : SourceId) -> Result<T, DataError>
1010 {
1011 if package_name.find('/').is_some()
1012 {
1013 return Err(DataError::BadName);
1014 }
1015
1016 if let Some(mut source) = self.source_manager.borrow_mut().source(source_id)
1017 {
1018 if T::trust_policy() == TrustPolicy::TrustRequired
1019 && source.trust_level(package_name) != TrustLevel::TrustedSource
1020 {
1021 return Err(DataError::SourceNotTrusted);
1022 }
1023
1024 let type_folder = T::folder_name();
1025
1026 if type_folder.find('/').is_some()
1027 {
1028 return Err(DataError::BadName);
1029 }
1030
1031 if pathname.starts_with('/') || pathname.ends_with('/')
1032 {
1033 return Err(DataError::BadName);
1034 }
1035
1036 let full_pathname = format!("{}/{}", type_folder, pathname);
1037 return Ok(T::from_package_source(&mut source, &package_name, &full_pathname)?);
1038 }
1039
1040 Err(DataError::BadSource)
1041 }
1042}
1043
1044trait DataStoreBase : Downcast
1045{
1046 fn unload_unused_internal(&mut self);
1047 fn unload_all_internal(&mut self);
1048}
1049impl_downcast!(DataStoreBase);
1050
1051impl<T : DataObject + 'static> DataStoreBase for DataStore<T>
1052{
1053 fn unload_unused_internal(&mut self)
1054 {
1055 let mut to_unload = Vec::new();
1056
1057 for (package_name, token) in &self.package_use_tokens
1058 {
1059 if token.uses() == 0
1060 {
1061 to_unload.push(package_name.clone());
1062 }
1063 }
1064
1065 for package in &to_unload
1066 {
1067 self.unload_package(package);
1068 }
1069 }
1070
1071 fn unload_all_internal(&mut self)
1072 {
1073 for (package_name, package_map) in &self.data_map
1074 {
1075 for id in package_map.values()
1076 {
1077 if let Some(prepare_info) = &self.prepare_info
1078 {
1079 prepare_info.borrow_mut().to_prepare.insert(id.id, PrepareType::FullPrepare);
1080 }
1081 }
1082
1083 self.unloaded_packages.insert(package_name.to_string(), package_map.clone());
1084 }
1085
1086 self.data_map.clear();
1087 self.data_list.clear();
1088 }
1089}
1090
1091struct NullDataStore {}
1092
1093impl DataStoreBase for NullDataStore
1094{
1095 fn unload_unused_internal(&mut self) {}
1096 fn unload_all_internal(&mut self) {}
1097}
1098
1099struct DataMultistoreLookup
1100{
1101 index_to_type_id : Vec<TypeId>,
1102 type_id_to_index : HashMap<TypeId, usize, BuildHasherDefault<FxHasher>>
1103}
1104
1105impl DataMultistoreLookup
1106{
1107 #[inline(always)]
1108 fn lookup(&self, type_id : &TypeId) -> Option<usize>
1109 {
1110 self.type_id_to_index.get(type_id).cloned()
1111 }
1112}
1113
1114pub struct DataMultistore
1117{
1118 source_manager : Rc<RefCell<SourceManager>>,
1119 stores : GenericArray<RefCell<Box<dyn DataStoreBase>>, DataStoreTypeMax>,
1120 lookup : RefCell<DataMultistoreLookup>,
1121 locked : bool
1122}
1123
1124impl DataMultistore
1125{
1126 pub fn new(source_manager : Rc<RefCell<SourceManager>>) -> DataMultistore
1129 {
1130 let stores = GenericArray::<RefCell<Box<dyn DataStoreBase>>, DataStoreTypeMax>::generate(|_| RefCell::new(Box::new(NullDataStore {})));
1131
1132 let lookup = DataMultistoreLookup
1133 {
1134 index_to_type_id : Vec::new(),
1135 type_id_to_index : HashMap::with_hasher(BuildHasherDefault::<FxHasher>::default())
1136 };
1137
1138 DataMultistore
1139 {
1140 source_manager,
1141 stores,
1142 lookup : RefCell::new(lookup),
1143 locked : false
1144 }
1145 }
1146
1147 pub fn register_type<D : DataObject + 'static>(&self) -> bool
1150 {
1151 let wanted_type = TypeId::of::<D>();
1152 let store = DataStore::<D>::new(self.source_manager.clone());
1153
1154 self.register_boxed_type(wanted_type, Box::new(store))
1155 }
1156
1157 fn register_boxed_type(&self, type_id : TypeId, mut store : Box<dyn DataStoreBase>) -> bool
1158 {
1159 let mut lookup = self.lookup.try_borrow_mut().expect("DataMultistore data already in use!");
1160
1161 if !lookup.type_id_to_index.contains_key(&type_id)
1162 {
1163 if lookup.index_to_type_id.len() >= self.stores.len()
1164 {
1165 panic!("Too many types registered! Limit is {}", self.stores.len());
1166 }
1167
1168 let insert_pos = lookup.index_to_type_id.len();
1169
1170 let mut placeholder = self.stores[insert_pos].try_borrow_mut().expect("Placeholder under use somehow!");
1171 std::mem::swap(&mut *placeholder, &mut store);
1172
1173 lookup.type_id_to_index.insert(type_id, insert_pos);
1174 lookup.index_to_type_id.push(type_id);
1175
1176 return true;
1177 }
1178
1179 false
1180 }
1181
1182 pub fn lock(&mut self, locked : bool)
1184 {
1185 self.locked = locked;
1186 }
1187
1188 pub fn store<D : DataObject + 'static>(&self) -> Ref<DataStore<D>>
1190 {
1191 if let Some(store) = self.try_store()
1192 {
1193 return store;
1194 }
1195
1196 panic!("DataObject type {} not registered.", std::any::type_name::<D>());
1197 }
1198
1199 pub fn store_mut<D : DataObject + 'static>(&self) -> RefMut<DataStore<D>>
1201 {
1202 if let Some(store) = self.try_store_mut()
1203 {
1204 return store;
1205 }
1206
1207 if self.locked
1208 {
1209 panic!("Mutable datastore access is currently restricted.");
1210 }
1211 else
1212 {
1213 panic!("DataObject type {} not registered.", std::any::type_name::<D>());
1214 }
1215 }
1216
1217 pub fn try_store<D : DataObject + 'static>(&self) -> Option<Ref<DataStore<D>>>
1219 {
1220 let wanted_type = TypeId::of::<D>();
1221 let mut index_opt = self.lookup.try_borrow().expect("DataMultistore data already in use!").lookup(&wanted_type);
1222
1223 if index_opt.is_none()
1224 {
1225 self.register_type::<D>();
1226 index_opt = self.lookup.try_borrow().expect("DataMultistore data already in use!").lookup(&wanted_type);
1227 }
1228
1229 if let Some(index) = index_opt
1230 {
1231 return Some(Ref::map(self.stores[index].borrow(),
1232 |b| b.downcast_ref::<DataStore<D>>().expect("DataMultistore borrow failed!")));
1233 }
1234
1235 None
1236 }
1237
1238 pub fn try_store_mut<D : DataObject + 'static>(&self) -> Option<RefMut<DataStore<D>>>
1240 {
1241 if self.locked
1242 {
1243 return None;
1244 }
1245
1246 let wanted_type = TypeId::of::<D>();
1247 let mut index_opt = self.lookup.try_borrow().expect("DataMultistore data already in use!").lookup(&wanted_type);
1248
1249 if index_opt.is_none()
1250 {
1251 self.register_type::<D>();
1252 index_opt = self.lookup.try_borrow().expect("DataMultistore data already in use!").lookup(&wanted_type);
1253 }
1254
1255 if let Some(index) = index_opt
1256 {
1257 return Some(RefMut::map(self.stores[index].borrow_mut(),
1258 |b| b.downcast_mut::<DataStore<D>>().expect("DataMultistore borrow failed!")));
1259 }
1260
1261 None
1262 }
1263
1264 pub fn unload_all(&self)
1268 {
1269 let lookup = self.lookup.try_borrow_mut().expect("DataMultistore data already in use!");
1270
1271 for index in (0..lookup.index_to_type_id.len()).rev()
1272 {
1273 self.stores[index].borrow_mut().unload_all_internal();
1274 }
1275
1276 info!("Unloaded all packages");
1277 }
1278
1279 pub fn unload_unused(&self)
1281 {
1282 let lookup = self.lookup.try_borrow_mut().expect("DataMultistore data already in use!");
1283
1284 for index in (0..lookup.index_to_type_id.len()).rev()
1285 {
1286 self.stores[index].borrow_mut().unload_unused_internal();
1287 }
1288 }
1289
1290 pub fn package_source_id(&self, package_name : &str) -> SourceId
1294 {
1295 let source_manager = self.source_manager.borrow_mut();
1296
1297 source_manager.package_source_id(package_name)
1298 }
1299}
1300
1301#[derive(Debug, Eq, PartialEq)]
1302enum PrepareType
1303{
1304 FullPrepare,
1305 Reprepare
1306}
1307
1308struct PrepareInfo<T : DataObject + 'static>
1309{
1310 to_prepare : HashMap<DataId<T>, PrepareType, BuildHasherDefault<FxHasher>>,
1311}
1312
1313impl<T : DataObject + 'static> PrepareInfo<T>
1314{
1315 fn new() -> PrepareInfo<T>
1316 {
1317 PrepareInfo
1318 {
1319 to_prepare : HashMap::with_hasher(BuildHasherDefault::<FxHasher>::default())
1320 }
1321 }
1322}
1323
1324pub trait DataPreparer<T : DataObject + 'static, U>
1327{
1328 fn prepare(&mut self, data : &mut T, id : DataId<T>) -> U;
1331 fn unprepare(&mut self, prepared : &mut U, id : DataId<T>);
1334 fn reprepare(&mut self, data : &mut T, prepared : &mut U, id : DataId<T>)
1337 {
1338 self.unprepare(prepared, id);
1339 *prepared = self.prepare(data, id);
1340 }
1341}
1342
1343pub struct PreparedStore<T : DataObject + 'static, U>
1358{
1359 data_list : Vec<Option<U>>,
1360 data_preparer : Box<dyn DataPreparer<T, U>>,
1361 prepare_info : Rc<RefCell<PrepareInfo<T>>>
1362}
1363
1364impl<T : DataObject + 'static, U> PreparedStore<T, U>
1365{
1366 pub fn new(data_store : &mut DataStore<T>, data_preparer : Box<dyn DataPreparer<T, U>>) -> Result<PreparedStore<T, U>, PreparedStoreError>
1369 {
1370 if data_store.prepare_info.is_some()
1371 {
1372 return Err(PreparedStoreError::AlreadyConnected);
1373 }
1374
1375 let prepare_info = Rc::new(RefCell::new(PrepareInfo::new()));
1376 data_store.prepare_info = Some(prepare_info.clone());
1377
1378 Ok(PreparedStore::<T, U>
1379 {
1380 data_list : Vec::new(),
1381 data_preparer,
1382 prepare_info
1383 })
1384 }
1385
1386 pub fn get(&self, id : DataId<T>) -> Option<&U>
1389 {
1390 if id.index >= self.data_list.len()
1391 {
1392 return None;
1393 }
1394
1395 match &self.data_list[id.index]
1396 {
1397 Some(data) => Some(data),
1398 None => None
1399 }
1400 }
1401
1402 pub fn get_mut(&mut self, id : DataId<T>) -> Option<&mut U>
1405 {
1406 if id.index >= self.data_list.len()
1407 {
1408 return None;
1409 }
1410
1411 match &mut self.data_list[id.index]
1412 {
1413 Some(data) => Some(data),
1414 None => None
1415 }
1416 }
1417
1418 pub fn sync(&mut self, data_store : &mut DataStore<T>) -> Result<(), PreparedStoreError>
1422 {
1423 if let Some(prepare_info) = &mut data_store.prepare_info
1424 {
1425 if !Rc::ptr_eq(&prepare_info, &self.prepare_info)
1426 {
1427 return Err(PreparedStoreError::WrongDataStore);
1428 }
1429 }
1430 else
1431 {
1432 return Err(PreparedStoreError::WrongDataStore);
1433 }
1434
1435 for (id, prepare_type) in &self.prepare_info.borrow_mut().to_prepare
1436 {
1437 if let Some(data) = data_store.get_mut(*id)
1438 {
1439 while self.data_list.len() <= id.index
1441 {
1442 self.data_list.push(None);
1443 }
1444
1445 let mut existing = false;
1446
1447 if let Some(prepared) = &mut self.data_list[id.index]
1448 {
1449 match *prepare_type
1450 {
1451 PrepareType::FullPrepare =>
1452 {
1453 self.data_preparer.unprepare(prepared, *id);
1455 },
1456 PrepareType::Reprepare =>
1457 {
1458 self.data_preparer.reprepare(data, prepared, *id);
1460 existing = true;
1461 }
1462 }
1463 }
1464
1465 if !existing
1466 {
1467 self.data_list[id.index] = Some(self.data_preparer.prepare(data, *id));
1468 }
1469 }
1470 else
1471 {
1472 if id.index < self.data_list.len()
1473 {
1474 if let Some(prepared) = &mut self.data_list[id.index]
1475 {
1476 self.data_preparer.unprepare(prepared, *id);
1477 }
1478
1479 self.data_list[id.index] = None;
1480 }
1481 }
1482 }
1483
1484 self.prepare_info.borrow_mut().to_prepare.clear();
1485
1486 Ok(())
1487 }
1488}