use derivative::Derivative;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid;
use wildland_corex::catlib_service::entities::CatlibContainerFilter;
use wildland_corex::catlib_service::error::CatlibError;
use wildland_corex::{
Container,
ContainerManager,
ContainerManagerError,
CoreXError,
StorageTemplate,
StorageTemplateError,
};
use super::cargo_lib::DfsApi;
use super::storage::ContainerStorage;
use crate::multidevice_state::error::MultideviceStateError;
use crate::multidevice_state::user_state::{UserMultideviceState, UserMultideviceStateContext};
#[derive(Debug, Clone)]
pub struct CargoContainerFilter {
inner: CatlibContainerFilter,
}
impl From<CargoContainerFilter> for CatlibContainerFilter {
fn from(val: CargoContainerFilter) -> CatlibContainerFilter {
val.inner
}
}
impl CargoContainerFilter {
#[tracing::instrument(level = "trace")]
pub fn has_exact_path(path: String) -> Self {
Self {
inner: CatlibContainerFilter::HasExactPath(path.into()),
}
}
#[tracing::instrument(level = "trace")]
pub fn has_path_starting_with(path: String) -> Self {
Self {
inner: CatlibContainerFilter::HasPathStartingWith(path.into()),
}
}
#[tracing::instrument(level = "trace")]
pub fn has_uuid(uuid: Uuid) -> Self {
Self {
inner: CatlibContainerFilter::HasUuid(uuid),
}
}
#[tracing::instrument(level = "trace")]
pub fn any(filters: Vec<Self>) -> Self {
Self {
inner: CatlibContainerFilter::Any(
filters.into_iter().map(|elem| elem.into()).collect(),
),
}
}
#[tracing::instrument(level = "trace")]
pub fn or(f1: Self, f2: Self) -> Self {
Self {
inner: CatlibContainerFilter::Or(Box::new(f1.into()), Box::new(f2.into())),
}
}
#[tracing::instrument(level = "trace")]
pub fn and(f1: Self, f2: Self) -> Self {
Self {
inner: CatlibContainerFilter::And(Box::new(f1.into()), Box::new(f2.into())),
}
}
#[tracing::instrument(level = "trace")]
#[allow(clippy::should_implement_trait)]
pub fn not(f: Self) -> Self {
Self {
inner: CatlibContainerFilter::Not(Box::new(f.into())),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum MountState {
Mounted,
Unmounted,
MountedOrUnmounted,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum Persistency {
GloballyPersistent,
LocallyPersistent,
}
#[derive(Error, Debug, Clone)]
#[repr(C)]
pub enum AddStorageError {
#[error("Catlib Error: {0}")]
CatlibErr(#[from] CatlibError),
#[error("Storage Template Error: {0}")]
StorageTemplateError(#[from] StorageTemplateError),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SharingMessage {}
#[derive(Derivative, Clone)]
#[derivative(Debug)]
pub struct CargoContainer {
#[derivative(Debug = "ignore")]
container_manager: ContainerManager,
#[derivative(Debug = "ignore")]
multi_device_state: UserMultideviceState,
#[derivative(Debug = "ignore")]
dfs_api: DfsApi,
corex_container: Container,
encrypted: bool,
}
impl CargoContainer {
pub fn new(
container_manager: ContainerManager,
corex_container: Container,
encrypted: bool,
multi_device_state: UserMultideviceState,
dfs_api: DfsApi,
) -> Self {
Self {
container_manager,
corex_container,
multi_device_state,
dfs_api,
encrypted,
}
}
pub fn mount(
&self,
persistent_mount: Option<Persistency>,
) -> Result<(), ContainerManagerError> {
self.container_manager.mount(&self.corex_container)?;
if let Some(persistency) = persistent_mount {
self.set_persistency(persistency).unwrap_or_else(|err| {
let container_uuid = self.corex_container.uuid();
tracing::error!(
"Setting container with uuid: {container_uuid} as automounted failed. Reason: {err}"
)
})
};
Ok(())
}
#[tracing::instrument(level = "trace")]
pub fn unmount(
&self,
persistent_unmount: Option<Persistency>,
) -> Result<(), ContainerManagerError> {
self.container_manager.unmount(&self.corex_container)?;
if let Some(persistency) = persistent_unmount {
self.unset_persistency(persistency)
.unwrap_or_else(|err| {
let container_uuid = self.uuid();
tracing::error!(
"Setting container with uuid: {container_uuid} as not automounted failed. Reason: {err}"
)
})
};
Ok(())
}
#[tracing::instrument(level = "trace")]
pub fn is_mounted(&self) -> bool {
self.container_manager.is_mounted(&self.corex_container)
}
#[tracing::instrument(level = "trace")]
fn get_context(&self, persistency: Persistency) -> &UserMultideviceStateContext {
match persistency {
Persistency::GloballyPersistent => self.multi_device_state.global_context(),
Persistency::LocallyPersistent => self.multi_device_state.local_context(),
}
}
#[tracing::instrument(level = "trace")]
pub fn is_automounted(&self) -> Result<bool, MultideviceStateError> {
Ok(self
.multi_device_state
.get_automounted_containers()?
.any(|(uuid, _time)| uuid == self.corex_container.uuid()))
}
pub fn set_persistency(&self, persistency: Persistency) -> Result<(), MultideviceStateError> {
self.get_context(persistency)
.set_container_as_automounted(self.uuid())
}
pub fn unset_persistency(&self, persistency: Persistency) -> Result<(), MultideviceStateError> {
self.get_context(persistency)
.remove_container_from_automount(self.uuid())
}
#[tracing::instrument(level = "trace")]
pub fn get_storages(&self) -> Result<Vec<ContainerStorage>, CoreXError> {
Ok(self
.corex_container
.get_storages()?
.into_iter()
.map(|s| ContainerStorage::from_corex_storage(s, self.dfs_api.clone()))
.collect())
}
#[tracing::instrument(level = "trace")]
pub fn add_storage(
&mut self,
storage_template: &StorageTemplate,
) -> Result<ContainerStorage, AddStorageError> {
let storage = self.corex_container.render_template(storage_template)?;
Ok(self
.corex_container
.add_storage(storage_template.catlib_uuid(), storage, self.encrypted)
.map(|s| ContainerStorage::from_corex_storage(s, self.dfs_api.clone()))?)
}
#[tracing::instrument(level = "trace")]
pub fn remove_storage(&mut self, uuid: &Uuid) -> Result<(), CoreXError> {
self.corex_container.remove_storage(uuid)
}
#[tracing::instrument(level = "trace")]
pub fn change_path(&self, path: String) -> Result<(), CatlibError> {
self.corex_container.change_path(path)
}
#[tracing::instrument(level = "trace")]
pub fn get_path(&self) -> Result<String, CatlibError> {
self.corex_container.get_path()
}
#[tracing::instrument(level = "trace")]
pub fn set_name(&self, new_name: String) -> Result<(), CatlibError> {
self.corex_container.set_name(new_name)
}
#[tracing::instrument(level = "trace")]
pub fn remove(&self) -> Result<(), CatlibError> {
self.corex_container.remove()
}
#[tracing::instrument(level = "trace")]
pub fn name(&self) -> Result<String, CatlibError> {
self.corex_container.name()
}
#[tracing::instrument(level = "trace")]
pub fn uuid(&self) -> Uuid {
self.corex_container.uuid()
}
}