file_system/fundamentals/identifiers/
unique_file.rs

1use core::fmt::Debug;
2
3use task::TaskIdentifier;
4
5use super::{
6    FileIdentifier, FileIdentifierInner, FileSystemIdentifier, FileSystemIdentifierInner,
7    LocalFileIdentifier,
8};
9
10/// Unique file identifier type
11///
12/// This type is used to identify an opened file in the virtual file system.
13/// It is used for the file identification between the virtual file system and the outside world.
14/// It is similar to a file descriptor in Unix-like systems.
15/// It is a wrapper around a tuple of [`FileSystemIdentifier`] and [`FileIdentifier`].
16/// It is unique from the virtual file system point of view.
17///
18/// # Example
19///
20/// ```rust
21/// use file_system::{Unique_file_identifier_type, File_identifier_type, File_system_identifier_type, Local_file_identifier_type};
22///
23/// use task::TaskIdentifier;
24///
25/// let Identifier = Unique_file_identifier_type::new(
26///     File_system_identifier_type::from(0x1234),
27///     File_identifier_type::from(0x5678),
28/// );
29///
30/// let (File_system, File) = Identifier.Split();
31///
32/// assert_eq!(File_system, File_system_identifier_type::from(0x1234));
33/// assert_eq!(File, File_identifier_type::from(0x5678));
34///
35/// let (File_system, Local_file) = Identifier.Into_local_file_identifier(TaskIdentifier::from(0x9ABC));
36///
37/// assert_eq!(File_system, File_system_identifier_type::from(0x1234));
38/// assert_eq!(Local_file, Local_file_identifier_type::new(TaskIdentifier::from(0x9ABC), File_identifier_type::from(0x5678)));
39/// ```
40#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
41#[repr(transparent)]
42pub struct UniqueFileIdentifier(usize);
43
44impl Debug for UniqueFileIdentifier {
45    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46        let (file_system_identifier, file_identifier) = self.split();
47
48        formatter
49            .debug_struct("Unique_file_identifier_type")
50            .field("File_system_identifier", &file_system_identifier)
51            .field("File_identifier", &file_identifier)
52            .finish()
53    }
54}
55
56impl UniqueFileIdentifier {
57    const FILE_SYSTEM_IDENTIFIER_POSITION: u8 = FileIdentifier::SIZE_BITS;
58
59    pub const fn new(file_system: FileSystemIdentifier, file: FileIdentifier) -> Self {
60        let file_system_identifier = file_system.as_inner();
61        let file_identifier = file.into_inner();
62
63        Self(
64            (file_system_identifier as usize) << Self::FILE_SYSTEM_IDENTIFIER_POSITION
65                | file_identifier as usize,
66        )
67    }
68
69    pub const fn split(&self) -> (FileSystemIdentifier, FileIdentifier) {
70        let file_system = self.0 >> FileIdentifierInner::BITS;
71        let file_system = FileSystemIdentifier::new(file_system as FileSystemIdentifierInner);
72
73        let file = self.0 as FileIdentifierInner;
74        let file = FileIdentifier::new(file);
75
76        (file_system, file)
77    }
78
79    pub const fn into_local_file_identifier(
80        self,
81        task: TaskIdentifier,
82    ) -> (FileSystemIdentifier, LocalFileIdentifier) {
83        let (file_system, file) = self.split();
84
85        let local_file = LocalFileIdentifier::new(task, file);
86
87        (file_system, local_file)
88    }
89
90    pub const fn into_inner(self) -> usize {
91        self.0
92    }
93
94    /// This function is shouldn't be used because it doesn't check the validity of the file identifier.
95    pub const fn from_raw(inner: usize) -> Self {
96        Self(inner)
97    }
98}
99
100impl From<UniqueFileIdentifier> for usize {
101    fn from(identifier: UniqueFileIdentifier) -> Self {
102        identifier.0
103    }
104}
105
106impl From<usize> for UniqueFileIdentifier {
107    fn from(identifier: usize) -> Self {
108        UniqueFileIdentifier(identifier)
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115
116    #[test]
117    fn test_unique_file_identifier() {
118        let identifier = UniqueFileIdentifier::new(
119            FileSystemIdentifier::from(0x1234),
120            FileIdentifier::from(0x5678),
121        );
122        assert_eq!(
123            identifier.split(),
124            (
125                FileSystemIdentifier::new(0x1234),
126                FileIdentifier::new(0x5678)
127            )
128        );
129    }
130}