mycelium_core 0.1.1

Library for Mycelium DDM
Documentation
use std::fs::{create_dir_all, File};
use std::io::{Read, Write};
use std::panic;
use std::path::PathBuf;

use ron::de::from_str;
use serde::de::DeserializeOwned;

pub trait Container {
    fn get_file_name(&self) -> &str;
    fn get_file_path(&self) -> &PathBuf;
}

/// Fetch logic will create a default for T where it does not yet exist.
/// Default serialize/deserialze will use bincode.
pub trait Fetchable {
    fn deserialize_l<T: DeserializeOwned + Default + Fetchable>(
        f_path: &PathBuf,
    ) -> std::io::Result<T>;
    /// Default deserializer bincode.
    /// Panics if deserialize fails.
    fn deserialize_bin<T: DeserializeOwned + Default>(f_path: &PathBuf) -> std::io::Result<T> {
        match File::open(f_path) {
            Ok(mut f) => {
                let mut buffer = Vec::new();
                f.read_to_end(&mut buffer)?;
                let item: T = match bincode::deserialize(&buffer) {
                    Ok(item) => item,
                    Err(_e) => T::default(),
                };
                buffer.clear();
                Ok(item)
            }
            Err(e) => panic!("Failed to deserialize requested object: {:?}", e),
        }
    }

    fn deserialize_ron<T: DeserializeOwned + Default>(f_path: &PathBuf) -> std::io::Result<T> {
        match File::open(f_path) {
            Ok(mut f) => {
                let mut buffer = String::new();
                f.read_to_string(&mut buffer)?;
                let item: T = match from_str(&buffer) {
                    Ok(item) => item,
                    Err(_e) => T::default(),
                };
                Ok(item)
            }
            Err(e) => panic!("Failed to deserialize requested object: {:?}", e),
        }
    }

    fn serialize_l(&self) -> std::io::Result<Vec<u8>>
    where
        Self: serde::Serialize + Fetchable;
    /// Default serializer bincode.
    /// Panics if serialization fails.
    fn serialize_bin(&self) -> std::io::Result<Vec<u8>>
    where
        Self: serde::Serialize,
    {
        let mut buf = vec![];
        buf.clear();
        buf = match bincode::serialize(self) {
            Ok(b) => b,
            Err(e) => panic!("Could not serialize: {:?}", e),
        };
        Ok(buf)
    }
    fn serialize_ron(&self) -> std::io::Result<Vec<u8>>
    where
        Self: serde::Serialize,
    {
        Ok(
            ron::ser::to_string_pretty(&self, ron::ser::PrettyConfig::default())
                .expect("Failed pretty string.")
                .as_bytes()
                .to_vec(),
        )
    }

    fn save(&self) -> std::io::Result<()>
    where
        Self: serde::Serialize + Container + Fetchable,
    {
        let mut path = self.get_file_path().to_path_buf();
        path.push(self.get_file_name());
        let mut f = File::create(path)?;
        let content = self.serialize_l()?; //crate::fetch::Fetchable::serialize(self).unwrap();
        f.write_all(content.as_slice())?;
        f.sync_all()
    }

    fn save_x(&self, tag: &str, file_name: &str, path: &PathBuf) -> std::io::Result<()>
    where
        Self: serde::Serialize + Fetchable,
    {
        let mut path = path.to_path_buf();
        path.push(tag);
        if !path.exists() {
            create_dir_all(&path)?;
        }
        path.push(file_name);
        let mut f = File::create(&path)?;
        let content = self.serialize_l()?; //crate::fetch::Fetchable::serialize(self).unwrap();
        f.write_all(content.as_slice())?;
        f.sync_all()
    }

    fn save_y(&self, path: &PathBuf) -> std::io::Result<()>
    where
        Self: serde::Serialize + Fetchable,
    {
        let mut f = File::create(&path)?;
        let content = self.serialize_l()?;
        f.write_all(content.as_slice())?;
        f.sync_all()
    }

    fn fetch<T: Default + DeserializeOwned + Fetchable>(
        tag: &str,
        file_name: &str,
        file_path: &PathBuf,
    ) -> std::io::Result<T> {
        let mut path = file_path.to_path_buf();
        path.push(tag);
        path.push(file_name);

        let result: T = if path.exists() {
            match T::deserialize_l(&path) {
                Ok(t) => t,
                Err(_) => T::default(),
            }
        } else {
            T::default()
        };

        Ok(result)
    }

    ///
    /// Fetch an item serialized to file
    /// # Arguments
    ///
    /// * `file_path` - Reference to path buffer of file of type T
    ///
    /// # Returns
    ///
    /// * `Result<(T, bool)>` - Returns tuple containing T and a bool value indicating if a config was retrieved or default. True for default config use.
    ///
    fn fetch_or_default<T: Default + DeserializeOwned + Fetchable>(
        file_path: &PathBuf,
    ) -> std::io::Result<(T, bool)> {
        let path = file_path.to_path_buf();
        let result: (T, bool) = if path.exists() {
            match T::deserialize_l(&path) {
                Ok(t) => (t, false),
                Err(_) => (T::default(), true),
            }
        } else {
            (T::default(), true)
        };

        Ok(result)
    }

    fn fetch_self(&self) -> Self
    where
        Self: Default + DeserializeOwned + Fetchable + Container,
    {
        let mut path = self.get_file_path().to_path_buf();
        path.push(self.get_file_name());
        let res: Self = match Self::deserialize_l(&path) {
            Ok(r) => r,
            Err(_e) => Self::default(),
        };
        res
    }
}