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
//! Fixed file operations using registered indices for the Ring.
use super::Ring;
use crate::error::Result;
use crate::future::{ReadFuture, WriteFuture};
use crate::operation::Operation;
impl<'ring> Ring<'ring> {
/// Read from a fixed file using its registered index.
///
/// Fixed files are pre-registered with the kernel and accessed by index
/// instead of file descriptor, providing better performance for frequently
/// used files. The file must be registered with the registry first.
///
/// # Arguments
///
/// * `fixed_file` - The fixed file to read from
/// * `buffer` - Pinned buffer to read data into
///
/// # Returns
///
/// Returns a ReadFuture that resolves to (bytes_read, buffer).
///
/// # Errors
///
/// Returns an error if the operation cannot be submitted or if the
/// fixed file is not registered.
///
/// # Example
///
/// ```rust,ignore
/// # use safer_ring::{Ring, PinnedBuffer, Registry};
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let mut registry = Registry::new();
/// let fixed_files = registry.register_fixed_files(vec![0])?; // stdin
/// let fixed_stdin = &fixed_files[0];
///
/// let ring = Ring::new(32)?;
/// let mut buffer = PinnedBuffer::with_capacity(1024);
///
/// let (bytes_read, buffer) = ring.read_fixed(fixed_stdin, buffer.as_mut_slice()).await?;
/// println!("Read {} bytes from fixed file", bytes_read);
/// # Ok(())
/// # }
/// ```
pub fn read_fixed<'buf>(
&'ring mut self,
fixed_file: &crate::registry::FixedFile,
buffer: std::pin::Pin<&'buf mut [u8]>,
) -> Result<ReadFuture<'ring, 'buf>>
where
'buf: 'ring,
{
let operation = Operation::read()
.fixed_file(fixed_file.clone())
.buffer(buffer);
let submitted = self.submit(operation)?;
Ok(ReadFuture::new(
submitted,
self,
self.waker_registry.clone(),
))
}
/// Write to a fixed file using its registered index.
///
/// Fixed files are pre-registered with the kernel and accessed by index
/// instead of file descriptor, providing better performance for frequently
/// used files. The file must be registered with the registry first.
///
/// # Arguments
///
/// * `fixed_file` - The fixed file to write to
/// * `buffer` - Pinned buffer containing data to write
///
/// # Returns
///
/// Returns a WriteFuture that resolves to (bytes_written, buffer).
///
/// # Errors
///
/// Returns an error if the operation cannot be submitted or if the
/// fixed file is not registered.
///
/// # Example
///
/// ```rust,ignore
/// # use safer_ring::{Ring, PinnedBuffer, Registry};
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let mut registry = Registry::new();
/// let fixed_files = registry.register_fixed_files(vec![1])?; // stdout
/// let fixed_stdout = &fixed_files[0];
///
/// let ring = Ring::new(32)?;
/// let mut buffer = PinnedBuffer::from_slice(b"Hello from fixed file!");
///
/// let (bytes_written, buffer) = ring.write_fixed(fixed_stdout, buffer.as_mut_slice()).await?;
/// println!("Wrote {} bytes to fixed file", bytes_written);
/// # Ok(())
/// # }
/// ```
pub fn write_fixed<'buf>(
&'ring mut self,
fixed_file: &crate::registry::FixedFile,
buffer: std::pin::Pin<&'buf mut [u8]>,
) -> Result<WriteFuture<'ring, 'buf>>
where
'buf: 'ring,
{
let operation = Operation::write()
.fixed_file(fixed_file.clone())
.buffer(buffer);
let submitted = self.submit(operation)?;
Ok(WriteFuture::new(
submitted,
self,
self.waker_registry.clone(),
))
}
// TODO: Add buffer selection operations when future types are implemented
// The read_with_buffer_selection method would go here once the appropriate
// future types are implemented for buffer selection operations.
}