use core::fmt::Debug;
use alloc::format;
use alloc::vec::Vec;
use iceoryx2_bb_container::semantic_string::SemanticString;
use iceoryx2_bb_posix::config::TEMP_DIRECTORY;
use iceoryx2_bb_posix::directory::{Directory, DirectoryRemoveError};
pub use iceoryx2_bb_system_types::file_name::FileName;
pub use iceoryx2_bb_system_types::file_path::FilePath;
pub use iceoryx2_bb_system_types::path::Path;
use iceoryx2_log::{fail, fatal_panic};
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub enum NamedConceptDoesExistError {
InsufficientPermissions,
UnderlyingResourcesBeingSetUp,
UnderlyingResourcesCorrupted,
InternalError,
}
impl core::fmt::Display for NamedConceptDoesExistError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "NamedConceptDoesExistError::{self:?}")
}
}
impl core::error::Error for NamedConceptDoesExistError {}
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub enum NamedConceptRemoveError {
InsufficientPermissions,
InternalError,
}
impl core::fmt::Display for NamedConceptRemoveError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "NamedConceptRemoveError::{self:?}")
}
}
impl core::error::Error for NamedConceptRemoveError {}
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub enum NamedConceptListError {
InsufficientPermissions,
InternalError,
}
impl core::fmt::Display for NamedConceptListError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "NamedConceptListError::{self:?}")
}
}
impl core::error::Error for NamedConceptListError {}
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub enum NamedConceptPathHintRemoveError {
InsufficientPermissions,
InternalError,
}
impl core::fmt::Display for NamedConceptPathHintRemoveError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "NamedConceptPathHintRemoveError::{self:?}")
}
}
impl core::error::Error for NamedConceptPathHintRemoveError {}
pub trait NamedConceptConfiguration: Default + Clone + Debug + Send {
fn prefix(self, value: &FileName) -> Self;
fn get_prefix(&self) -> &FileName;
fn suffix(self, value: &FileName) -> Self;
fn path_hint(self, value: &Path) -> Self;
fn get_suffix(&self) -> &FileName;
fn get_path_hint(&self) -> &Path;
fn path_for(&self, value: &FileName) -> FilePath {
let mut path = *self.get_path_hint();
fatal_panic!(from self, when path.add_path_entry(&self.get_prefix().into()),
"The path hint \"{}\" in combination with the prefix \"{}\" exceed the maximum supported path length of {} of the operating system.",
path, value, Path::max_len());
fatal_panic!(from self, when path.push_bytes(value.as_string()),
"The path hint \"{}\" in combination with the file name \"{}\" exceed the maximum supported path length of {} of the operating system.",
path, value, Path::max_len());
fatal_panic!(from self, when path.push_bytes(self.get_suffix()),
"The path hint \"{}\" in combination with the file name \"{}\" and the suffix \"{}\" exceed the maximum supported path length of {} of the operating system.",
path, value, self.get_suffix(), Path::max_len());
unsafe { FilePath::new_unchecked(path.as_bytes()) }
}
fn extract_name_from_path(&self, value: &FilePath) -> Option<FileName> {
if *self.get_path_hint() != value.path() {
return None;
}
self.extract_name_from_file(&value.file_name())
}
fn extract_name_from_file(&self, value: &FileName) -> Option<FileName> {
let mut file = *value;
if !fatal_panic!(from self, when file.strip_prefix(self.get_prefix().as_bytes()),
"Stripping the prefix \"{}\" from the file name \"{}\" leads to invalid content.",
self.get_prefix(), file)
{
return None;
}
if !fatal_panic!(from self, when file.strip_suffix(self.get_suffix().as_bytes()),
"Stripping the suffix \"{}\" from the file name \"{}\" leads to invalid content.",
self.get_suffix(), file)
{
return None;
}
Some(file)
}
}
pub trait NamedConceptBuilder<T: NamedConceptMgmt> {
fn new(name: &FileName) -> Self;
fn config(self, config: &T::Configuration) -> Self;
}
pub trait NamedConcept: Debug {
fn name(&self) -> &FileName;
}
pub trait NamedConceptMgmt: Debug {
type Configuration: NamedConceptConfiguration;
unsafe fn remove(name: &FileName) -> Result<bool, NamedConceptRemoveError> {
unsafe { Self::remove_cfg(name, &Self::Configuration::default()) }
}
fn does_exist(name: &FileName) -> Result<bool, NamedConceptDoesExistError> {
Self::does_exist_cfg(name, &Self::Configuration::default())
}
fn list() -> Result<Vec<FileName>, NamedConceptListError> {
Self::list_cfg(&Self::Configuration::default())
}
unsafe fn remove_cfg(
name: &FileName,
cfg: &Self::Configuration,
) -> Result<bool, NamedConceptRemoveError>;
fn does_exist_cfg(
name: &FileName,
cfg: &Self::Configuration,
) -> Result<bool, NamedConceptDoesExistError>;
fn list_cfg(cfg: &Self::Configuration) -> Result<Vec<FileName>, NamedConceptListError>;
fn default_prefix() -> FileName {
unsafe { FileName::new_unchecked(b"iox2_") }
}
fn default_path_hint() -> Path {
TEMP_DIRECTORY
}
fn remove_path_hint(value: &Path) -> Result<(), NamedConceptPathHintRemoveError>;
}
pub(crate) fn remove_path_hint(value: &Path) -> Result<(), NamedConceptPathHintRemoveError> {
let origin = format!("remove_path_hint({value:?})");
let msg = "Unable to remove path hint";
match Directory::remove_empty(value) {
Ok(()) | Err(DirectoryRemoveError::DirectoryDoesNotExist) => Ok(()),
Err(DirectoryRemoveError::InsufficientPermissions) => {
fail!(from origin, with NamedConceptPathHintRemoveError::InsufficientPermissions,
"{} due to insufficient permissions.", msg);
}
Err(e) => {
fail!(from origin, with NamedConceptPathHintRemoveError::InternalError,
"{} due to an internal error ({:?}).", msg, e);
}
}
}