thot-local 0.10.0-intermediate

Local functionality for Thot data management and analysis software.
Documentation
/// Asset and Assets.
use super::standard_properties::LocalStandardProperties;
use crate::common::assets_file_of;
use crate::result::Result;
use cluFlock::FlockLock;
use serde::{Deserialize, Serialize};
use settings_manager::list_setting::ListSetting;
use settings_manager::local_settings::{LocalSettings, LockSettingsFile};
use settings_manager::result::{
    Error as SettingsError, LocalSettingsError, Result as SettingsResult,
};
use settings_manager::settings::Settings;
use settings_manager::types::Priority as SettingsPriority;
use std::fs::File;
use std::path::{Path, PathBuf};
use thot_core::project::Asset;
use thot_core::types::{ResourceId, ResourcePath};

// *******************
// *** Local Asset ***
// *******************

pub struct LocalAsset;

impl LocalAsset {
    /// Creates an [`Asset`] with the `properties` field filled actively from
    /// [`LocalStandardProperties`].
    pub fn new(path: ResourcePath) -> Result<Asset> {
        let props = LocalStandardProperties::new()?;
        Ok(Asset {
            properties: props,
            path: Some(path),
        })
    }
}

// **************
// *** Assets ***
// **************

#[derive(Serialize, Deserialize, Debug, Default)]
pub struct Assets {
    #[serde(skip)]
    _file_lock: Option<FlockLock<File>>,

    #[serde(skip)]
    _base_path: Option<PathBuf>,

    pub assets: Vec<Asset>,
}

impl Assets {
    pub fn new() -> Self {
        Assets {
            _file_lock: None,
            _base_path: None,

            assets: Vec::new(),
        }
    }

    /// Returns an Asset given its resource id or `None` if not found.
    pub fn get(&self, rid: &ResourceId) -> Option<&Asset> {
        for asset in &self.assets {
            if &asset.properties.rid == rid {
                return Some(&asset);
            }
        }

        None
    }

    /// Returns an Asset's index given its local id or `None` if not found.
    ///
    /// # See also
    /// + [`Self.index_py_path`]
    pub fn index_by_lid(&self, lid: &str) -> Option<usize> {
        let lid = &Some(String::from(lid));
        self.assets
            .iter()
            .position(|a| &a.properties.rid.lid == lid)
    }

    /// Returns an Asset's index given its path or `None` if not found.
    ///
    /// # See also
    /// + [`Self.index_py_lid`]    
    pub fn index_by_path(&self, path: &ResourcePath) -> Option<usize> {
        let path = Some(path.clone());
        self.assets.iter().position(|a| a.path == path)
    }

    /// Returns whether the given resource id is registered as an Asset.
    pub fn contains(&self, rid: &ResourceId) -> bool {
        self.get(rid).is_some()
    }

    /// Returns whether an [`Asset`] with the given local id is registered.
    pub fn contains_lid(&self, lid: &str) -> bool {
        self.index_by_lid(lid).is_some()
    }

    /// Returns whether the path is contained in the Assets.
    pub fn contains_path(&self, path: &ResourcePath) -> bool {
        self.rid_of_path(path).is_some()
    }

    /// Returns the resource id of the given path, or None if it is not found.
    pub fn rid_of_path(&self, path: &ResourcePath) -> Option<ResourceId> {
        let path = Some(path.clone());
        for asset in &self.assets {
            if asset.path == path {
                return Some(asset.properties.rid.clone());
            }
        }
        return None;
    }
}

impl Settings for Assets {
    fn store_lock(&mut self, lock: FlockLock<File>) {
        self._file_lock = Some(lock);
    }

    fn controls_file(&self) -> bool {
        self._file_lock.is_some()
    }

    fn priority(&self) -> SettingsPriority {
        SettingsPriority::Project
    }
}

impl LocalSettings for Assets {
    fn rel_path() -> SettingsResult<PathBuf> {
        Ok(assets_file_of(Path::new("")))
    }

    fn base_path(&self) -> SettingsResult<PathBuf> {
        self._base_path
            .clone()
            .ok_or(SettingsError::LocalSettingsError(
                LocalSettingsError::PathNotSet,
            ))
    }

    fn set_base_path(&mut self, path: PathBuf) -> SettingsResult {
        self._base_path = Some(path);
        Ok(())
    }
}

impl ListSetting for Assets {
    type Item = Asset;

    fn items(&mut self) -> &mut Vec<Asset> {
        &mut self.assets
    }
}

impl LockSettingsFile for Assets {}

#[cfg(test)]
#[path = "./asset_test.rs"]
mod asset_test;