File_system/Fundamentals/Identifiers/
Unique_file.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::fmt::Debug;

use Task::Task_identifier_type;

use super::{
    File_identifier_inner_type, File_identifier_type, File_system_identifier_inner_type,
    File_system_identifier_type, Local_file_identifier_type,
};

/// Unique file identifier type
///
/// This type is used to identify an opened file in the virtual file system.
/// It is used for the file identification between the virtual file system and the outside world.
/// It is similar to a file descriptor in Unix-like systems.
/// It is a wrapper around a tuple of [`File_system_identifier_type`] and [`File_identifier_type`].
/// It is unique from the virtual file system point of view.
///
/// # Example
///
/// ```rust
/// use File_system::{Unique_file_identifier_type, File_identifier_type, File_system_identifier_type, Local_file_identifier_type};
///
/// use Task::Task_identifier_type;
///
/// let Identifier = Unique_file_identifier_type::New(
///     File_system_identifier_type::from(0x1234),
///     File_identifier_type::from(0x5678),
/// );
///
/// let (File_system, File) = Identifier.Split();
///
/// assert_eq!(File_system, File_system_identifier_type::from(0x1234));
/// assert_eq!(File, File_identifier_type::from(0x5678));
///
/// let (File_system, Local_file) = Identifier.Into_local_file_identifier(Task_identifier_type::from(0x9ABC));
///
/// assert_eq!(File_system, File_system_identifier_type::from(0x1234));
/// assert_eq!(Local_file, Local_file_identifier_type::New(Task_identifier_type::from(0x9ABC), File_identifier_type::from(0x5678)));
/// ```
#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct Unique_file_identifier_type(usize);

impl Debug for Unique_file_identifier_type {
    fn fmt(&self, Formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let (File_system_identifier, File_identifier) = self.Split();

        Formatter
            .debug_struct("Unique_file_identifier_type")
            .field("File_system_identifier", &File_system_identifier)
            .field("File_identifier", &File_identifier)
            .finish()
    }
}

impl Unique_file_identifier_type {
    const File_system_identifier_position: u8 = File_identifier_type::Size_bits;

    pub const fn New(File_system: File_system_identifier_type, File: File_identifier_type) -> Self {
        let File_system_identifier = File_system.As_inner();
        let File_identifier = File.Into_inner();

        Self(
            (File_system_identifier as usize) << Self::File_system_identifier_position
                | File_identifier as usize,
        )
    }

    pub const fn Split(&self) -> (File_system_identifier_type, File_identifier_type) {
        let File_system = self.0 >> File_identifier_inner_type::BITS;
        let File_system =
            File_system_identifier_type::New(File_system as File_system_identifier_inner_type);

        let File = self.0 as File_identifier_inner_type;
        let File = File_identifier_type::New(File);

        (File_system, File)
    }

    pub const fn Into_local_file_identifier(
        self,
        Task: Task_identifier_type,
    ) -> (File_system_identifier_type, Local_file_identifier_type) {
        let (File_system, File) = self.Split();

        let Local_file = Local_file_identifier_type::New(Task, File);

        (File_system, Local_file)
    }

    pub const fn Into_inner(self) -> usize {
        self.0
    }

    /// This function is shouldn't be used because it doesn't check the validity of the file identifier.
    pub const fn From_raw(Inner: usize) -> Self {
        Self(Inner)
    }
}

impl From<Unique_file_identifier_type> for usize {
    fn from(Identifier: Unique_file_identifier_type) -> Self {
        Identifier.0
    }
}

impl From<usize> for Unique_file_identifier_type {
    fn from(Identifier: usize) -> Self {
        Unique_file_identifier_type(Identifier)
    }
}

#[cfg(test)]
mod Tests {
    use super::*;

    #[test]
    fn Test_unique_file_identifier() {
        let Identifier = Unique_file_identifier_type::New(
            File_system_identifier_type::from(0x1234),
            File_identifier_type::from(0x5678),
        );
        assert_eq!(
            Identifier.Split(),
            (
                File_system_identifier_type::New(0x1234),
                File_identifier_type::New(0x5678)
            )
        );
    }
}