keeshond_datapack/
lib.rs

1#![warn(missing_docs)]
2
3//! `keeshond_datapack` lets you easily load resources for your game and cache them in memory,
4//!  mapped via pathname and accessible by handle objects. Define how they load
5//!  with the [DataObject] trait, by implementing a function that takes a [Read] + [Seek] object.
6//!  Define where they load from by instantiating a [source::Source].
7//!
8//! Datapack is used by Keeshond but can work with any engine.
9//!
10//! # How to use
11//!
12//! - Implement the [DataObject] trait for each type of object you want to be able to load in.
13//! - Instantiate a [source::SourceManager] object and give it a [source::Source] such as a
14//!  [source::FilesystemSource]
15//! - Create a folder for each package on disk (if using [FilesystemSource](source::FilesystemSource)).
16//! - Create subfolders within each package for each data type and place files within.
17//! - Instantiate a [DataStore] for each data type you want to load.
18//! - (Optional) use [DataStore::load_package()] to ensure the package is loaded at start.
19//! - When creating objects that need resources, instantiate a [DataHandle] with a desired path.
20//! - Resolve this path using a [DataStore] to access the data. Store this handle somewhere it can
21//!   be used later, as resolving does involve a couple hash lookups.
22//!
23//! Pathnames are of the form `path/to/file.png`. They must match exactly, including the use of one
24//!  forward slash as a separator, and no separators at the beginning or end. The package name and
25//!  data type folders are not included (they are implied). Pathnames are also case-sensitive even on
26//!  platforms with case-insensitive filesystems (Windows, macOS).
27
28#[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
41/// The `Source` trait and implementations.
42pub 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
64/// A numeric ID used to refer to a [DataObject] of a specific type. Should only be used directly
65///  when performing operations that need an index into an array or Vec. This value may change
66///  between sessions. In most cases you probably want to use a [DataHandle] instead.
67pub struct DataId<T : DataObject + 'static>
68{
69    index : usize,
70    _phantom : PhantomData<T>
71}
72
73impl<T : DataObject + 'static> DataId<T>
74{
75    /// Creates a new ID using the given numerical value. Passing a value of 0 will make this a
76    ///  "null" ID
77    pub fn new(index : usize) -> DataId<T>
78    {
79        DataId
80        {
81            index,
82            _phantom : PhantomData
83        }
84    }
85
86    /// Returns the numerical value associated with this ID, for use with array indexing. This value
87    ///  should not be serialized as its value may change between sessions.
88    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/// Return type when loading information from a [DataStore]
145#[derive(Debug, PartialEq)]
146pub enum DataStoreOk
147{
148    /// The package was loaded successfully
149    Loaded,
150    /// The package was already loaded, so no action was taken
151    AlreadyLoaded,
152}
153
154/// Return type when failing to load a [DataObject] from a [DataStore]
155#[derive(Debug, Fail)]
156pub enum DataError
157{
158    /// The given package was not found in the [source::Source]
159    #[fail(display = "The package was not found")]
160    PackageNotFound,
161    /// The given package is not trusted by the [source::Source]
162    #[fail(display = "The package source was not trusted")]
163    SourceNotTrusted,
164    /// The package is loaded, but has no [DataObject] by the given pathname
165    #[fail(display = "The data object was not found")]
166    DataNotFound,
167    /// An invalid character (forward slash) was used in a package or type folder name
168    #[fail(display = "Invalid character in name")]
169    BadName,
170    /// An invalid source ID was specified
171    #[fail(display = "Invalid source ID")]
172    BadSource,
173    /// The operation is not supported by this implementation
174    #[fail(display = "Operation not supported")]
175    NotSupported,
176    /// An error occurred while accessing a package's source
177    ///  from the [source::Source]
178    #[fail(display = "Package source failure: {}", _0)]
179    PackageSourceError(PackageError),
180    /// An error of type [std::io::Error] occurred.
181    #[fail(display = "{}", _0)]
182    IoError(#[cause] std::io::Error),
183    /// A logical error occurred while reading a [DataObject]
184    #[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/// Return type for when [PreparedStore] operations fail
197#[derive(Debug, Fail)]
198pub enum PreparedStoreError
199{
200    /// The DataStore provided in [PreparedStore::new()] is already associated with another
201    ///  [PreparedStore]
202    #[fail(display = "The provided DataStore is already associated with a PreparedStore.")]
203    AlreadyConnected,
204    /// The DataStore provided in [PreparedStore::sync()] is not the same one passed to
205    ///  [PreparedStore::new()]
206    #[fail(display = "The provided DataStore is not the one used to create this PreparedStore.")]
207    WrongDataStore
208}
209
210/// Behavior for when automatically loading a resource fails
211#[derive(Debug, Clone, Copy, Eq, PartialEq)]
212pub enum LoadErrorMode
213{
214    /// The application will panic if the load fails
215    Fatal,
216    /// The application will print a warning if the load fails, and the data ID will resolve to null
217    Warning
218}
219
220/// Trust settings for a given [DataObject] resource type
221#[derive(Debug, Copy, Clone, Eq, PartialEq)]
222pub enum TrustPolicy
223{
224    /// The resource may be loaded from an untrusted source.
225    UntrustedOk,
226    /// The resource may only be loaded from a trusted source
227    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/// A path to a data resource, resolvable to a cached [DataId].
276///
277/// This object serves three purposes:
278///
279/// - Conveniently resolving a path to an ID but only when resolution is necessary
280/// - Serializing data that needs to reference a DataObject
281/// - Keeping a package open so it doesn't get auto-unloaded.
282///
283/// If placing inside a DataObject struct, take care not to have a self-referencing type
284///  (i.e. a DataHandle\<T\> inside a T) or a type cycle
285///  (i.e. a DataHandle\<T\> inside a U and a DataHandle\<U\> inside a T). Otherwise the auto-unload
286///  mechanism may not be able to unload the package the object is from.
287#[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    /// Creates a new [DataHandle] that points to nothing. Resolving this data handle will fail
338    ///  until it is given a valid path, such as through set_path().
339    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    /// Creates a new [DataHandle] with the given resource path. The data ID will be unresolved.
352    ///  You will need to call resolve() for the data ID to point to a valid resource.
353    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    /// Clones the given [DataHandle] but only retains the ID, erasing the path. This is useful for
366    ///  instances where you want to store a lot of handles but don't need the path, to cut down on
367    ///  memory usage.
368    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    /// Changes the resource path. The data ID will reset to be unresolved.
381    ///  You will need to call resolve() for the data ID to point to a valid resource.
382    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    /// Returns the package name part of the resource path
393    pub fn package(&self) -> &String
394    {
395        &self.package
396    }
397
398    /// Returns the filepath to the resource
399    pub fn path(&self) -> &String
400    {
401        &self.path
402    }
403
404    /// Returns the data ID.
405    ///  You will need to call resolve() beforehand for the data ID to point to a valid resource.
406    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    /// Returns true if the path has been resolved via a call to resolve().
419    #[inline(always)]
420    pub fn resolved(&self) -> bool
421    {
422        self.data_id.get().index != usize::MAX
423    }
424
425    /// Resolves the data ID using the given [DataStore]. Returns the resolved data ID,
426    ///  which is cached inside the object. If load_error is Fatal, this function will panic
427    ///  if the load fails. Otherwise it will simply return a null data ID.
428    #[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    /// Returns a reference to data object in the store, if it exists. If the data object is not resolved,
459    ///  then resolve() will be called, and then the data object reference returned, if available.
460    #[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    /// Returns a mutable reference to data object in the store, if it exists. If the data object is not resolved,
469    ///  then resolve() will be called, and then the data object reference returned, if available.
470    #[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    /// Returns a reference to data object in the store, if it exists. If the data object is not resolved,
479    ///  returns None instead of attempting to resolve.
480    #[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    /// Returns a mutable reference to data object in the store, if it exists. If the data object is not resolved,
487    ///  returns None instead of attempting to resolve.
488    #[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    /// Resolves the data ID using the given [DataStore]. Returns the resolved data ID,
495    ///  which is cached inside the object. If the data is not yet loaded, returns a null ID.
496    #[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
514/// A token that indicates that a package is in use and should not be automatically unloaded.
515pub 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    /// Returns the name of the package associated with this token
533    pub fn package(&self) -> &String
534    {
535        self.use_count.as_ref()
536    }
537
538    /// Returns how many copies of the token reference this package
539    pub fn uses(&self) -> usize
540    {
541        // Subtracting 1 because a copy of the token is stored internally and cloned out as
542        //  necessary - this copy should not count toward the total use count
543        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
567/// A boxable trait that implements both [Read] and [Seek], used by the
568///  [source::Source] types.
569pub trait ReadSeek : Read + Seek {}
570
571impl<T: Read + Seek> ReadSeek for T {}
572
573/// Represents a data item loaded from a package. Implement this trait to allow the system
574///  to load new types of data.
575pub trait DataObject
576{
577    /// The folder name that [DataObjects](DataObject) of this type are stored in
578    fn folder_name() -> &'static str where Self : Sized;
579    /// The [TrustPolicy] for this resource type, which determines what sources are allowed to load it.
580    fn trust_policy() -> TrustPolicy;
581    /// Determines whether or not a given file should be loaded while iterating through a package.
582    fn want_file(pathname : &str) -> bool where Self : Sized;
583    /// A constructor that returns a new [DataObject] of this type given a path and a [Source] object.
584    fn from_package_source(source : &mut Box<dyn Source>, package_name : &str, pathname : &str) -> Result<Self, DataError> where Self : Sized;
585    /// A function that writes the object to the given [Source] to save its data
586    #[allow(unused_variables)]
587    fn write(&mut self, package_name : &str, pathname : &str, source : &mut Box<dyn Source>) -> Result<(), DataError> { Err(DataError::NotSupported) }
588    /// Implement this to support "generations" for detecting when the data for a given path is changed.
589    fn generation(&self) -> u64 { 0 }
590    /// Implement this to support "generations" for detecting when the data for a given path is changed.
591    #[allow(unused_variables)]
592    fn set_generation(&mut self, generation : u64) {}
593}
594
595/// Storage that allows lookup and access of [DataObjects](DataObject) of a given type
596pub 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    /// Constructs a new [DataStore] that gets its [Sources](source::Source) from the given
610    ///  [SourceManager]
611    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    /// Loads the package by the given name if it is not already loaded.
626    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    /// Gets the numeric ID of the [DataObject] from the given package at the given pathname.
759    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    /// Gets the numeric ID of the [DataObject] from the given package at the given pathname.
777    ///  If the package is not loaded, it will be loaded automatically.
778    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    /// Returns a reference to the [DataObject] by the given [DataId], if one exists.
800    ///  Otherwise returns [None].
801    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    /// Returns a mutable reference to the [DataObject] by the given [DataId], if one exists.
816    ///  Otherwise returns [None].
817    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    /// Returns a string list of the names of each [DataObject] in the given package.
832    ///  The package will need to have been loaded or this will return an empty list.
833    ///  Please do not call this repeatedly.
834    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    /// Unloads the given package from memory. Any [DataObjects](DataObject) will be dropped,
855    ///  but pathname-id mappings will be retained in memory so that existing references will
856    ///  not be invalidated. Returns true if the package was loaded.
857    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    /// Unloads all packages from memory. Any [DataObjects](DataObject) will be dropped,
891    ///  but pathname-id mappings will be retained in memory so that existing references will
892    ///  not be invalidated. Returns true if the package was loaded.
893    pub fn unload_all(&mut self)
894    {
895        self.unload_all_internal();
896        info!("Unloaded all packages for \"{}\"", T::folder_name());
897    }
898
899    /// Unloads all packages that do not have an active [PackageUseToken].
900    pub fn unload_unused(&mut self)
901    {
902        self.unload_unused_internal()
903    }
904
905    /// Returns true if the given package is loaded.
906    pub fn package_loaded(&self, package_name : &str) -> bool
907    {
908        self.data_map.contains_key(package_name)
909    }
910
911    /// Returns a [PackageUseToken] that can be used to keep the given package from being unloaded
912    ///  automatically.
913    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    /// Saves the indicated item using the [Source] given by [SourceId].
919    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    /// Marks the [DataObject] by the given [DataId] as needing to be "reprepared". Use this,
942    ///  for example, when data has been changed and it needs to be reflected in a backend via
943    ///  the [PreparedStore]. Returns true if the data was marked for reprepare, otherwise false.
944    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    /// Reloads an already-loaded resource by the given name.
971    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    /// Loads a single [DataObject] from the given source and returns it. This function does not
1005    ///  index, cache, or track the loaded object in any way. Loading the object through here will
1006    ///  result in a separate copy in memory even if it was previously loaded through the usual
1007    ///  package loading mechanism. For most cases you should use `load_package()` or
1008    ///  `get_id_mut()` instead.
1009    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
1114/// Storage that allows lookup and access of [DataObjects](DataObject) of multiple types by wrapping
1115///  multiple [DataStores](DataStore).
1116pub 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    /// Constructs a new [DataMultistore] that gets its [Sources](source::Source) from the given
1127    ///  [SourceManager]
1128    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    /// Informs the [DataMultistore] of a new [DataObject] to manage a [DataStore] for. Returns true
1148    ///  if successful.
1149    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    /// Sets whether mutable access to types is disallowed.
1183    pub fn lock(&mut self, locked : bool)
1184    {
1185        self.locked = locked;
1186    }
1187
1188    /// Returns a reference to the [DataStore] of the given type. Panics if it cannot be retrieved.
1189    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    /// Returns a mutable reference to the [DataStore] of the given type. Panics if it cannot be retrieved.
1200    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    /// Returns a reference to the [DataStore] of the given type. Returns None if it cannot be retrieved.
1218    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    /// Returns a mutable reference to the [DataStore] of the given type. Returns None if it cannot be retrieved.
1239    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    /// Unloads all packages from memory. Any [DataObjects](DataObject) will be dropped,
1265    ///  but pathname-id mappings will be retained in memory so that existing references will
1266    ///  not be invalidated. Returns true if the package was loaded.
1267    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    /// Unloads all packages that do not have an active [PackageUseToken].
1280    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    /// Returns the [SourceId] of the [Source] that has the given package, going in
1291    ///  reverse order of when they were added. If no suitable [Source] is available,
1292    ///  returns a "null" ID.
1293    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
1324/// Used with [PreparedStore], this allows the definition of behavior when initializing resources
1325///  with a backend. See [PreparedStore] for more information.
1326pub trait DataPreparer<T : DataObject + 'static, U>
1327{
1328    /// Called when data has been loaded but not "prepared" yet. You can use this, for example,
1329    ///  to load textures onto the GPU.
1330    fn prepare(&mut self, data : &mut T, id : DataId<T>) -> U;
1331    /// Called when data has been unloaded recently and should be cleared in the backend. For example,
1332    ///  use this to unload textures from GPU memory.
1333    fn unprepare(&mut self, prepared : &mut U, id : DataId<T>);
1334    /// Called when data is already loaded but needs to be "reprepared". You can use this, for example,
1335    ///  to update existing textures on the GPU.
1336    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
1343/// An optional companion to a [DataStore]. If you have data that needs initialization with a backend
1344///  (for example, textures you need to upload to a GPU), [PreparedStore] provides a way to handle this
1345///  in a two-step process that is borrow-checker-friendly.
1346///
1347/// Template parameter `T` is the type of the source DataObject, and template parameter `U` is the prepared
1348///  data. This system allows you to separate logical, backend-agnostic data from backend-specific resources.
1349///  For graphics, you might use `T` to represent the raw image data and metadata such as width and height,
1350///  and use `U` to represent a handle to the texture in VRAM.
1351///
1352/// In order to function, you should call [PreparedStore::sync()] once per frame before needing to use the resources in
1353///  question in your backend. This will "prepare" or "unprepare" any resources as needed.
1354///
1355/// The [PreparedStore] instance must be associated with a [DataStore]. Only one [PreparedStore] can be associated
1356///  with any given [DataStore].
1357pub 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    /// Creates a new [PreparedStore] that holds prepared versions `U` of [DataObjects](DataObject) `T`, and
1367    ///  associates with the given [DataStore].
1368    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    /// Returns a reference to the prepared data by the given [DataId], if one exists.
1387    ///  Otherwise returns [None].
1388    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    /// Returns a mutable reference to the prepared data by the given [DataId], if one exists.
1403    ///  Otherwise returns [None].
1404    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    /// Synchronizes this store with the associated [DataStore]. If any [DataObjects](DataObject) were recently
1419    ///  loaded, they will be prepared by calling [DataPreparer::prepare()]. If any were recently unloaded,
1420    ///  they will be "unprepared" (unloaded from the backend) by calling [DataPreparer::unprepare()].
1421    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                // TODO: Make faster
1440                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                            // Force unprepare() and then prepare() later
1454                            self.data_preparer.unprepare(prepared, *id);
1455                        },
1456                        PrepareType::Reprepare =>
1457                        {
1458                            // Reprepare, don't do full prepare()
1459                            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}