File_system/Fundamentals/Identifiers/
Local_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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use std::{
    fmt::Debug,
    ops::{Add, AddAssign},
};

use Task::{Task_identifier_inner_type, Task_identifier_type};

use super::{
    File_identifier_inner_type, File_identifier_type, File_system_identifier_type,
    Unique_file_identifier_type,
};

/// Local file type
///
/// This type is used to identify an opened file in a file system.
/// It is used for the file identification between the file system and the virtual file system.
/// It is a wrapper around a tuple of [`Task_identifier_type`] and [`File_identifier_type`].
/// It is unique from the file system point of view.
///
/// # Example
///
/// ```rust
/// use File_system::{Local_file_identifier_type, File_identifier_type, File_system_identifier_type, Unique_file_identifier_type};
///
/// use Task::Task_identifier_type;
///
/// let Identifier = Local_file_identifier_type::New(
///     Task_identifier_type::from(0x1234),
///     File_identifier_type::from(0x5678),
/// );
///
/// let (Task, File) = Identifier.Split();
///
/// assert_eq!(Task, Task_identifier_type::from(0x1234));
/// assert_eq!(File, File_identifier_type::from(0x5678));
///
/// let Minimum = Local_file_identifier_type::Get_minimum(Task);
/// assert_eq!(Minimum, Local_file_identifier_type::New(Task, File_identifier_type::Minimum));
///
/// let Maximum = Local_file_identifier_type::Get_maximum(Task);
/// assert_eq!(Maximum, Local_file_identifier_type::New(Task, File_identifier_type::Maximum));
///
/// let (Task, Unique_file_identifier) = Identifier.Into_unique_file_identifier(File_system_identifier_type::from(0x9ABC));
///
/// assert_eq!(Task, Task_identifier_type::from(0x1234));
/// assert_eq!(Unique_file_identifier, Unique_file_identifier_type::New(File_system_identifier_type::from(0x9ABC), File_identifier_type::from(0x5678)));
/// ```
#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct Local_file_identifier_type(usize);

impl Local_file_identifier_type {
    const Task_position: u8 = File_identifier_type::Size_bits;

    pub const fn New(Task: Task_identifier_type, File: File_identifier_type) -> Self {
        let Task = Task.Into_inner();
        let File = File.Into_inner();

        Self((Task as usize) << Self::Task_position | File as usize)
    }

    pub const fn Split(self) -> (Task_identifier_type, File_identifier_type) {
        let Task = self.0 >> File_identifier_type::Size_bits;
        let Task = Task_identifier_type::New(Task as Task_identifier_inner_type);

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

        (Task, File)
    }

    pub const fn Get_minimum(Task: Task_identifier_type) -> Self {
        Self::New(Task, File_identifier_type::Minimum)
    }

    pub const fn Get_maximum(Task: Task_identifier_type) -> Self {
        Self::New(Task, File_identifier_type::Maximum)
    }

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

        let Unique_file = Unique_file_identifier_type::New(File_system, File);

        (Task, Unique_file)
    }

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

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

        Formatter
            .debug_struct("Local_file_identifier_type")
            .field("Task", &Task)
            .field("File", &File)
            .finish()
    }
}

impl AddAssign<usize> for Local_file_identifier_type {
    fn add_assign(&mut self, rhs: usize) {
        self.0 += rhs;
    }
}

impl Add<usize> for Local_file_identifier_type {
    type Output = Self;

    fn add(self, rhs: usize) -> Self::Output {
        Self(self.0 + rhs)
    }
}

impl IntoIterator for Local_file_identifier_type {
    type Item = Local_file_identifier_type;
    type IntoIter = Local_file_identifier_iterator_type;

    fn into_iter(self) -> Self::IntoIter {
        let (Task, _) = self.Split();

        Local_file_identifier_iterator_type {
            Current: self,
            End: Local_file_identifier_type::Get_maximum(Task),
        }
    }
}

pub struct Local_file_identifier_iterator_type {
    Current: Local_file_identifier_type,
    End: Local_file_identifier_type,
}

impl Iterator for Local_file_identifier_iterator_type {
    type Item = Local_file_identifier_type;

    fn next(&mut self) -> Option<Self::Item> {
        if self.Current < self.End {
            let Current = self.Current;
            self.Current += 1;
            Some(Current)
        } else {
            None
        }
    }
}