abi_context/
file.rs

1//! File identifier types for opened files.
2//!
3//! This module provides file identifier types used to identify opened files
4//! within a task's file descriptor table, similar to file descriptors in
5//! Unix-like systems.
6
7use crate::UniqueFileIdentifier;
8use core::num::NonZero;
9use task::TaskIdentifier;
10
11pub type FileIdentifierInner = u16;
12
13/// Type-safe wrapper for file identifiers.
14///
15/// File identifiers are used to reference opened files within a task's context,
16/// similar to file descriptors in Unix-like systems. Each task maintains its own
17/// file identifier space, allowing for task isolation and security.
18///
19/// # Standard File Identifiers
20///
21/// The following standard identifiers are predefined:
22/// - [`FileIdentifier::STANDARD_IN`] (0) - Standard input
23/// - [`FileIdentifier::STANDARD_OUT`] (1) - Standard output  
24/// - [`FileIdentifier::STANDARD_ERROR`] (2) - Standard error
25///
26/// # Examples
27///
28/// ```rust
29/// use abi_context::FileIdentifier;
30///
31/// // Standard file identifiers
32/// assert_eq!(1u16, FileIdentifier::STANDARD_IN.into());
33/// assert_eq!(2u16, FileIdentifier::STANDARD_OUT.into());
34/// assert_eq!(3u16, FileIdentifier::STANDARD_ERROR.into());
35///
36/// // Create a custom file identifier
37/// let file_id = FileIdentifier::new(42).unwrap();
38/// assert_eq!(42u16, file_id.into());
39/// ```
40#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
41#[repr(transparent)]
42pub struct FileIdentifier(NonZero<u16>);
43
44impl FileIdentifier {
45    /// Size in bits of the underlying identifier type.
46    pub const SIZE_BITS: u8 = core::mem::size_of::<FileIdentifierInner>() as u8 * 8;
47
48    const DIRECTORY_FLAG: FileIdentifierInner = 1 << (Self::SIZE_BITS - 1);
49
50    /// Standard input file identifier (traditionally 0).
51    pub const STANDARD_IN: Self = Self::new_panic(1);
52
53    /// Standard output file identifier (traditionally 1).
54    pub const STANDARD_OUT: Self = Self::new_panic(2);
55
56    /// Standard error file identifier (traditionally 2).
57    pub const STANDARD_ERROR: Self = Self::new_panic(3);
58
59    /// Minimum file identifier available for regular files.
60    ///
61    /// Regular files should use identifiers starting from this value to avoid
62    /// conflicts with internal or reserved identifiers.
63    pub const MINIMUM_FILE: Self = Self::new_panic(4);
64
65    /// Maximum possible file identifier value.
66    pub const MAXIMUM_FILE: Self = Self::new_panic(Self::DIRECTORY_FLAG - 1);
67
68    pub const MINIMUM_DIRECTORY: Self = Self::new_panic(Self::DIRECTORY_FLAG);
69
70    pub const MAXIMUM_DIRECTORY: Self = Self::new_panic(FileIdentifierInner::MAX);
71    /// Create a new file identifier from a raw value.
72    ///
73    /// # Arguments
74    ///
75    /// * `Identifier` - The raw identifier value.
76    pub const fn new(identifier: u16) -> Option<Self> {
77        if let Some(non_zero) = NonZero::new(identifier) {
78            Some(Self(non_zero))
79        } else {
80            None
81        }
82    }
83
84    pub const fn new_panic(identifier: u16) -> Self {
85        Self::new(identifier).expect("FileIdentifier cannot be zero")
86    }
87
88    /// Get the raw identifier value.
89    ///
90    /// # Returns
91    ///
92    /// The underlying raw identifier value.
93    pub const fn into_inner(self) -> FileIdentifierInner {
94        self.0.get()
95    }
96
97    pub const fn into_unique(self, task: TaskIdentifier) -> UniqueFileIdentifier {
98        UniqueFileIdentifier::new(task, self)
99    }
100
101    pub const fn is_directory(self) -> bool {
102        (self.0.get() & Self::DIRECTORY_FLAG) != 0
103    }
104}
105
106impl TryFrom<FileIdentifierInner> for FileIdentifier {
107    type Error = virtual_file_system::Error;
108
109    fn try_from(value: u16) -> Result<Self, Self::Error> {
110        NonZero::new(value)
111            .map(FileIdentifier)
112            .ok_or(virtual_file_system::Error::InvalidIdentifier)
113    }
114}
115
116impl From<FileIdentifier> for u16 {
117    fn from(file_identifier: FileIdentifier) -> Self {
118        file_identifier.0.get()
119    }
120}