use crate::prelude::*;
pub struct PersistentBuilder<R: Resource + Serialize + DeserializeOwned> {
pub(crate) name: Option<String>,
pub(crate) format: Option<StorageFormat>,
pub(crate) path: Option<PathBuf>,
pub(crate) loaded: bool,
pub(crate) default: Option<R>,
pub(crate) revertible: bool,
pub(crate) revert_to_default_on_deserialization_errors: bool,
}
impl<R: Resource + Serialize + DeserializeOwned> PersistentBuilder<R> {
pub fn name(mut self, name: impl ToString) -> PersistentBuilder<R> {
self.name = Some(name.to_string());
self
}
pub fn format(mut self, format: StorageFormat) -> PersistentBuilder<R> {
self.format = Some(format);
self
}
pub fn path(mut self, path: impl Into<PathBuf>) -> PersistentBuilder<R> {
self.path = Some(path.into());
self
}
pub fn loaded(mut self, loaded: bool) -> PersistentBuilder<R> {
self.loaded = loaded;
self
}
pub fn unloaded(mut self, unloaded: bool) -> PersistentBuilder<R> {
self.loaded = !unloaded;
self
}
pub fn default(mut self, resource: R) -> PersistentBuilder<R> {
self.default = Some(resource);
self
}
pub fn revertible(mut self, revertible: bool) -> PersistentBuilder<R> {
self.revertible = revertible;
self
}
pub fn revert_to_default_on_deserialization_errors(
mut self,
revert_to_default_on_deserialization_errors: bool,
) -> PersistentBuilder<R> {
self.revert_to_default_on_deserialization_errors =
revert_to_default_on_deserialization_errors;
self
}
}
impl<R: Resource + Serialize + DeserializeOwned> PersistentBuilder<R> {
#[cfg(any(
feature = "bincode",
feature = "ini",
feature = "json",
feature = "ron",
feature = "toml",
feature = "yaml",
))]
pub fn build(self) -> Result<Persistent<R>, PersistenceError> {
if self.name.is_none() {
panic!("persistent resource name is not set");
}
if self.format.is_none() {
panic!("persistent resource format is not set");
}
if self.path.is_none() {
panic!("persistent resource path is not set");
}
if self.default.is_none() {
panic!("persistent resource default is not set");
}
let name = self.name.unwrap();
let format = self.format.unwrap();
let path = self.path.unwrap();
let loaded = self.loaded;
let default = self.default.unwrap();
let revertible = self.revertible;
let revert_to_default_on_deserialization_errors =
self.revert_to_default_on_deserialization_errors;
let storage = {
#[cfg(not(target_family = "wasm"))]
{
Storage::Filesystem { path: path.canonicalize().unwrap_or(path) }
}
#[cfg(target_family = "wasm")]
{
let separator = std::path::MAIN_SEPARATOR_STR;
let path = path.strip_prefix(separator).unwrap_or(&path);
if let Ok(Some(key)) = path.strip_prefix("local").map(|p| p.to_str()) {
Storage::LocalStorage { key: key.to_owned() }
} else if let Ok(Some(key)) = path.strip_prefix("session").map(|p| p.to_str()) {
Storage::SessionStorage { key: key.to_owned() }
} else {
panic!(
"persistent resource path should start with \
\"local\" or \"session\" and be UTF-8 encoded in WebAssembly",
);
}
}
};
Persistent::new(
name,
format,
storage,
loaded,
default,
revertible,
revert_to_default_on_deserialization_errors,
)
}
#[cfg(not(any(
feature = "bincode",
feature = "ini",
feature = "json",
feature = "ron",
feature = "toml",
feature = "yaml",
)))]
pub fn build(self) -> Result<Persistent<R>, PersistenceError> {
unreachable!()
}
}