1use core::fmt::Debug;
14
15use alloc::format;
16use alloc::vec::Vec;
17
18use iceoryx2_bb_container::semantic_string::SemanticString;
19use iceoryx2_bb_posix::config::TEMP_DIRECTORY;
20use iceoryx2_bb_posix::directory::{Directory, DirectoryRemoveError};
21pub use iceoryx2_bb_system_types::file_name::FileName;
22pub use iceoryx2_bb_system_types::file_path::FilePath;
23pub use iceoryx2_bb_system_types::path::Path;
24use iceoryx2_log::{fail, fatal_panic};
25
26#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
27pub enum NamedConceptDoesExistError {
28 InsufficientPermissions,
29 UnderlyingResourcesBeingSetUp,
30 UnderlyingResourcesCorrupted,
31 InternalError,
32}
33
34impl core::fmt::Display for NamedConceptDoesExistError {
35 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36 write!(f, "NamedConceptDoesExistError::{self:?}")
37 }
38}
39
40impl core::error::Error for NamedConceptDoesExistError {}
41
42#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
43pub enum NamedConceptRemoveError {
44 InsufficientPermissions,
45 InternalError,
46}
47
48impl core::fmt::Display for NamedConceptRemoveError {
49 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
50 write!(f, "NamedConceptRemoveError::{self:?}")
51 }
52}
53
54impl core::error::Error for NamedConceptRemoveError {}
55
56#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
57pub enum NamedConceptListError {
58 InsufficientPermissions,
59 InternalError,
60}
61
62impl core::fmt::Display for NamedConceptListError {
63 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64 write!(f, "NamedConceptListError::{self:?}")
65 }
66}
67
68impl core::error::Error for NamedConceptListError {}
69
70#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
71pub enum NamedConceptPathHintRemoveError {
72 InsufficientPermissions,
73 InternalError,
74}
75
76impl core::fmt::Display for NamedConceptPathHintRemoveError {
77 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
78 write!(f, "NamedConceptPathHintRemoveError::{self:?}")
79 }
80}
81
82impl core::error::Error for NamedConceptPathHintRemoveError {}
83
84pub trait NamedConceptConfiguration: Default + Clone + Debug + Send {
89 fn prefix(self, value: &FileName) -> Self;
91
92 fn get_prefix(&self) -> &FileName;
94
95 fn suffix(self, value: &FileName) -> Self;
97
98 fn path_hint(self, value: &Path) -> Self;
102
103 fn get_suffix(&self) -> &FileName;
105
106 fn get_path_hint(&self) -> &Path;
108
109 fn path_for(&self, value: &FileName) -> FilePath {
111 let mut path = *self.get_path_hint();
112 fatal_panic!(from self, when path.add_path_entry(&self.get_prefix().into()),
113 "The path hint \"{}\" in combination with the prefix \"{}\" exceed the maximum supported path length of {} of the operating system.",
114 path, value, Path::max_len());
115 fatal_panic!(from self, when path.push_bytes(value.as_string()),
116 "The path hint \"{}\" in combination with the file name \"{}\" exceed the maximum supported path length of {} of the operating system.",
117 path, value, Path::max_len());
118 fatal_panic!(from self, when path.push_bytes(self.get_suffix()),
119 "The path hint \"{}\" in combination with the file name \"{}\" and the suffix \"{}\" exceed the maximum supported path length of {} of the operating system.",
120 path, value, self.get_suffix(), Path::max_len());
121
122 unsafe { FilePath::new_unchecked(path.as_bytes()) }
123 }
124
125 fn extract_name_from_path(&self, value: &FilePath) -> Option<FileName> {
127 if *self.get_path_hint() != value.path() {
128 return None;
129 }
130
131 self.extract_name_from_file(&value.file_name())
132 }
133
134 fn extract_name_from_file(&self, value: &FileName) -> Option<FileName> {
136 let mut file = *value;
137
138 if !fatal_panic!(from self, when file.strip_prefix(self.get_prefix().as_bytes()),
139 "Stripping the prefix \"{}\" from the file name \"{}\" leads to invalid content.",
140 self.get_prefix(), file)
141 {
142 return None;
143 }
144
145 if !fatal_panic!(from self, when file.strip_suffix(self.get_suffix().as_bytes()),
146 "Stripping the suffix \"{}\" from the file name \"{}\" leads to invalid content.",
147 self.get_suffix(), file)
148 {
149 return None;
150 }
151
152 Some(file)
153 }
154}
155
156pub trait NamedConceptBuilder<T: NamedConceptMgmt> {
158 fn new(name: &FileName) -> Self;
160
161 fn config(self, config: &T::Configuration) -> Self;
163}
164
165pub trait NamedConcept: Debug {
169 fn name(&self) -> &FileName;
171}
172
173pub trait NamedConceptMgmt: Debug {
180 type Configuration: NamedConceptConfiguration;
181
182 unsafe fn remove(name: &FileName) -> Result<bool, NamedConceptRemoveError> {
190 unsafe { Self::remove_cfg(name, &Self::Configuration::default()) }
191 }
192
193 fn does_exist(name: &FileName) -> Result<bool, NamedConceptDoesExistError> {
195 Self::does_exist_cfg(name, &Self::Configuration::default())
196 }
197
198 fn list() -> Result<Vec<FileName>, NamedConceptListError> {
200 Self::list_cfg(&Self::Configuration::default())
201 }
202
203 unsafe fn remove_cfg(
211 name: &FileName,
212 cfg: &Self::Configuration,
213 ) -> Result<bool, NamedConceptRemoveError>;
214
215 fn does_exist_cfg(
217 name: &FileName,
218 cfg: &Self::Configuration,
219 ) -> Result<bool, NamedConceptDoesExistError>;
220
221 fn list_cfg(cfg: &Self::Configuration) -> Result<Vec<FileName>, NamedConceptListError>;
223
224 fn default_prefix() -> FileName {
226 unsafe { FileName::new_unchecked(b"iox2_") }
227 }
228
229 fn default_path_hint() -> Path {
231 TEMP_DIRECTORY
232 }
233
234 fn remove_path_hint(value: &Path) -> Result<(), NamedConceptPathHintRemoveError>;
237}
238
239pub(crate) fn remove_path_hint(value: &Path) -> Result<(), NamedConceptPathHintRemoveError> {
240 let origin = format!("remove_path_hint({value:?})");
241 let msg = "Unable to remove path hint";
242 match Directory::remove_empty(value) {
243 Ok(()) | Err(DirectoryRemoveError::DirectoryDoesNotExist) => Ok(()),
244 Err(DirectoryRemoveError::InsufficientPermissions) => {
245 fail!(from origin, with NamedConceptPathHintRemoveError::InsufficientPermissions,
246 "{} due to insufficient permissions.", msg);
247 }
248 Err(e) => {
249 fail!(from origin, with NamedConceptPathHintRemoveError::InternalError,
250 "{} due to an internal error ({:?}).", msg, e);
251 }
252 }
253}