file_system/fundamentals/identifiers/
local_file.rs

1use core::{
2    fmt::Debug,
3    ops::{Add, AddAssign},
4};
5
6use task::{TaskIdentifier, TaskIdentifierInner};
7
8use super::{FileIdentifier, FileIdentifierInner, FileSystemIdentifier, UniqueFileIdentifier};
9
10/// Local file type
11///
12/// This type is used to identify an opened file in a file system.
13/// It is used for the file identification between the file system and the virtual file system.
14/// It is a wrapper around a tuple of [`TaskIdentifier`] and [`FileIdentifier`].
15/// It is unique from the file system point of view.
16///
17/// # Example
18///
19/// ```rust
20/// use file_system::{Local_file_identifier_type, File_identifier_type, File_system_identifier_type, Unique_file_identifier_type};
21///
22/// use task::TaskIdentifier;
23///
24/// let Identifier = Local_file_identifier_type::new(
25///     TaskIdentifier::from(0x1234),
26///     File_identifier_type::from(0x5678),
27/// );
28///
29/// let (Task, File) = Identifier.Split();
30///
31/// assert_eq!(Task, TaskIdentifier::from(0x1234));
32/// assert_eq!(File, File_identifier_type::from(0x5678));
33///
34/// let Minimum = Local_file_identifier_type::get_minimum(Task);
35/// assert_eq!(Minimum, Local_file_identifier_type::new(Task, File_identifier_type::Minimum));
36///
37/// let Maximum = Local_file_identifier_type::get_maximum(Task);
38/// assert_eq!(Maximum, Local_file_identifier_type::new(Task, File_identifier_type::Maximum));
39///
40/// let (Task, Unique_file_identifier) = Identifier.Into_unique_file_identifier(File_system_identifier_type::from(0x9ABC));
41///
42/// assert_eq!(Task, TaskIdentifier::from(0x1234));
43/// assert_eq!(Unique_file_identifier, Unique_file_identifier_type::new(File_system_identifier_type::from(0x9ABC), File_identifier_type::from(0x5678)));
44/// ```
45#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
46#[repr(transparent)]
47pub struct LocalFileIdentifier(usize);
48
49impl LocalFileIdentifier {
50    const TASK_POSITION: u8 = FileIdentifier::SIZE_BITS;
51
52    pub const fn new(task: TaskIdentifier, file: FileIdentifier) -> Self {
53        let task = task.into_inner();
54        let file = file.into_inner();
55
56        Self((task as usize) << Self::TASK_POSITION | file as usize)
57    }
58
59    pub const fn split(self) -> (TaskIdentifier, FileIdentifier) {
60        let task = self.0 >> FileIdentifier::SIZE_BITS;
61        let task = TaskIdentifier::new(task as TaskIdentifierInner);
62
63        let file = self.0 as FileIdentifierInner;
64        let file = FileIdentifier::new(file);
65
66        (task, file)
67    }
68
69    pub const fn get_minimum(task: TaskIdentifier) -> Self {
70        Self::new(task, FileIdentifier::MINIMUM)
71    }
72
73    pub const fn get_maximum(task: TaskIdentifier) -> Self {
74        Self::new(task, FileIdentifier::MAXIMUM)
75    }
76
77    pub const fn into_unique_file_identifier(
78        self,
79        file_system: FileSystemIdentifier,
80    ) -> (TaskIdentifier, UniqueFileIdentifier) {
81        let (task, file) = self.split();
82
83        let unique_file = UniqueFileIdentifier::new(file_system, file);
84
85        (task, unique_file)
86    }
87
88    pub const fn into_inner(self) -> usize {
89        self.0
90    }
91}
92
93impl Debug for LocalFileIdentifier {
94    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95        let (task, file) = self.split();
96
97        formatter
98            .debug_struct("Local_file_identifier_type")
99            .field("Task", &task)
100            .field("File", &file)
101            .finish()
102    }
103}
104
105impl AddAssign<usize> for LocalFileIdentifier {
106    fn add_assign(&mut self, rhs: usize) {
107        self.0 += rhs;
108    }
109}
110
111impl Add<usize> for LocalFileIdentifier {
112    type Output = Self;
113
114    fn add(self, rhs: usize) -> Self::Output {
115        Self(self.0 + rhs)
116    }
117}
118
119impl IntoIterator for LocalFileIdentifier {
120    type Item = LocalFileIdentifier;
121    type IntoIter = LocalFileIdentifierIterator;
122
123    fn into_iter(self) -> Self::IntoIter {
124        let (task, _) = self.split();
125
126        LocalFileIdentifierIterator {
127            current: self,
128            end: LocalFileIdentifier::get_maximum(task),
129        }
130    }
131}
132
133pub struct LocalFileIdentifierIterator {
134    current: LocalFileIdentifier,
135    end: LocalFileIdentifier,
136}
137
138impl Iterator for LocalFileIdentifierIterator {
139    type Item = LocalFileIdentifier;
140
141    fn next(&mut self) -> Option<Self::Item> {
142        if self.current < self.end {
143            let current = self.current;
144            self.current += 1;
145            Some(current)
146        } else {
147            None
148        }
149    }
150}