Skip to content

Commit e455b94

Browse files
committed
Address review comments, iterate.
1 parent 0ff0e14 commit e455b94

File tree

5 files changed

+97
-76
lines changed

5 files changed

+97
-76
lines changed

examples/new_read.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,50 @@
11
use rustix::io::read;
22
use rustix::stdio::stdin;
3+
use std::mem::MaybeUninit;
34

45
fn main() {
5-
let buf = Vec::new();
6+
let buf = vec![0_u8; 3];
67
let _x: Vec<u8> = read(stdin(), buf).unwrap();
78

8-
let mut buf = Vec::new();
9+
let mut buf = vec![0_u8; 3];
910
let _x: usize = read(stdin(), &mut buf).unwrap();
11+
let _x: usize = read(stdin(), &mut *buf).unwrap();
1012

1113
let mut buf = [0, 0, 0];
1214
let _x: usize = read(stdin(), &mut buf).unwrap();
1315

14-
// Why doesn't this work? This is reduced from src/fs/inotify.rs line 177.
16+
let mut buf = [0, 0, 0];
17+
let _x: usize = read(stdin(), &mut buf[..]).unwrap();
18+
19+
let mut buf = [
20+
MaybeUninit::uninit(),
21+
MaybeUninit::uninit(),
22+
MaybeUninit::uninit(),
23+
];
24+
let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(stdin(), &mut buf).unwrap();
25+
26+
let mut buf = [
27+
MaybeUninit::uninit(),
28+
MaybeUninit::uninit(),
29+
MaybeUninit::uninit(),
30+
];
31+
let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(stdin(), &mut buf[..]).unwrap();
32+
33+
// This is reduced from src/fs/inotify.rs line 177.
1534
struct Wrapper<'a>(&'a mut [u8]);
1635
impl<'a> Wrapper<'a> {
1736
fn read(&mut self) {
18-
let _x: usize = read(stdin(), self.0).unwrap();
37+
// Ideally we'd write this.
38+
//let _x: usize = read(stdin(), self.0).unwrap();
39+
// But we need to write this instead.
40+
let _x: usize = read(stdin(), &mut *self.0).unwrap();
1941
}
2042
}
21-
let mut buf = Vec::new();
43+
let mut buf = vec![0_u8; 3];
2244
let mut wrapper = Wrapper(&mut buf);
2345
wrapper.read();
2446

2547
// Why does this get two error messages?
26-
let mut buf = [0, 0, 0];
27-
let _x = read(stdin(), buf).unwrap();
48+
//let mut buf = [0, 0, 0];
49+
//let _x = read(stdin(), buf).unwrap();
2850
}

src/backend/linux_raw/io/syscalls.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,11 @@ use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
2424
use crate::io::{self, DupFlags, FdFlags, IoSlice, IoSliceMut, ReadWriteFlags};
2525
use crate::ioctl::{IoctlOutput, RawOpcode};
2626
use core::cmp;
27-
use core::mem::MaybeUninit;
2827
use linux_raw_sys::general::{F_DUPFD_CLOEXEC, F_GETFD, F_SETFD};
2928

3029
#[inline]
31-
pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
32-
unsafe {
33-
ret_usize(syscall!(
34-
__NR_read,
35-
fd,
36-
buf.as_mut_ptr(),
37-
pass_usize(buf.len())
38-
))
39-
}
30+
pub(crate) unsafe fn read(fd: BorrowedFd<'_>, buf: (*mut u8, usize)) -> io::Result<usize> {
31+
ret_usize(syscall!(__NR_read, fd, buf.0, pass_usize(buf.1)))
4032
}
4133

4234
#[inline]

src/buffer.rs

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,22 @@ use core::mem::MaybeUninit;
88
use core::slice;
99

1010
/// A memory buffer that may be uninitialized.
11-
pub trait Buffer<T> {
12-
/// The result of the process operation.
13-
type Result;
14-
15-
/// Convert this buffer into a maybe-unitiailized view.
16-
fn as_maybe_uninitialized(&mut self) -> &mut [MaybeUninit<T>];
17-
18-
/// Convert a finished buffer pointer into its result.
19-
///
20-
/// # Safety
21-
///
22-
/// At least `len` bytes of the buffer must now be initialized.
23-
unsafe fn finish(self, len: usize) -> Self::Result;
24-
}
11+
pub trait Buffer<T>: private::Sealed<T> {}
2512

26-
/// Implements [`Buffer`] around the a slice of bytes.
27-
///
28-
/// `Result` is a `usize` indicating how many bytes were written.
29-
impl<T> Buffer<T> for &mut [T] {
13+
// Implement `Buffer` for all the types that implement `Sealed`.
14+
impl<T> Buffer<T> for &mut [T] {}
15+
impl<T, const N: usize> Buffer<T> for &mut [T; N] {}
16+
impl<T> Buffer<T> for &mut Vec<T> {}
17+
impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>] {}
18+
impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N] {}
19+
impl<T> Buffer<T> for Vec<T> {}
20+
21+
impl<T> private::Sealed<T> for &mut [T] {
3022
type Result = usize;
3123

3224
#[inline]
33-
fn as_maybe_uninitialized(&mut self) -> &mut [MaybeUninit<T>] {
34-
// SAFETY: This just casts away the knowledge that the elements are
35-
// initialized.
36-
unsafe { core::mem::transmute::<&mut [T], &mut [MaybeUninit<T>]>(self) }
25+
fn as_raw_parts_mut(&mut self) -> (*mut T, usize) {
26+
(self.as_mut_ptr(), self.len())
3727
}
3828

3929
#[inline]
@@ -42,17 +32,12 @@ impl<T> Buffer<T> for &mut [T] {
4232
}
4333
}
4434

45-
/// Implements [`Buffer`] around the a slice of bytes.
46-
///
47-
/// `Result` is a `usize` indicating how many bytes were written.
48-
impl<T, const N: usize> Buffer<T> for &mut [T; N] {
35+
impl<T, const N: usize> private::Sealed<T> for &mut [T; N] {
4936
type Result = usize;
5037

5138
#[inline]
52-
fn as_maybe_uninitialized(&mut self) -> &mut [MaybeUninit<T>] {
53-
// SAFETY: This just casts away the knowledge that the elements are
54-
// initialized.
55-
unsafe { core::mem::transmute::<&mut [T], &mut [MaybeUninit<T>]>(*self) }
39+
fn as_raw_parts_mut(&mut self) -> (*mut T, usize) {
40+
(self.as_mut_ptr(), N)
5641
}
5742

5843
#[inline]
@@ -61,17 +46,15 @@ impl<T, const N: usize> Buffer<T> for &mut [T; N] {
6146
}
6247
}
6348

64-
/// Implements [`Buffer`] around the a slice of bytes.
65-
///
66-
/// `Result` is a `usize` indicating how many bytes were written.
67-
impl<T> Buffer<T> for &mut Vec<T> {
49+
// `Vec` implements `DerefMut` to `&mut [T]`, however it doesn't get
50+
// auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so that our users
51+
// don't have to add an extra `*` in these situations.
52+
impl<T> private::Sealed<T> for &mut Vec<T> {
6853
type Result = usize;
6954

7055
#[inline]
71-
fn as_maybe_uninitialized(&mut self) -> &mut [MaybeUninit<T>] {
72-
// SAFETY: This just casts away the knowledge that the elements are
73-
// initialized.
74-
unsafe { core::mem::transmute::<&mut [T], &mut [MaybeUninit<T>]>(self) }
56+
fn as_raw_parts_mut(&mut self) -> (*mut T, usize) {
57+
(self.as_mut_ptr(), self.len())
7558
}
7659

7760
#[inline]
@@ -80,16 +63,31 @@ impl<T> Buffer<T> for &mut Vec<T> {
8063
}
8164
}
8265

83-
/// Implements [`Buffer`] around the a slice of uninitialized bytes.
84-
///
85-
/// `Result` is a pair of slices giving the initialized and uninitialized
86-
/// subslices after the new data is written.
87-
impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>] {
66+
impl<'a, T> private::Sealed<T> for &'a mut [MaybeUninit<T>] {
8867
type Result = (&'a mut [T], &'a mut [MaybeUninit<T>]);
8968

9069
#[inline]
91-
fn as_maybe_uninitialized(&mut self) -> &mut [MaybeUninit<T>] {
92-
self
70+
fn as_raw_parts_mut(&mut self) -> (*mut T, usize) {
71+
(self.as_mut_ptr().cast(), self.len())
72+
}
73+
74+
#[inline]
75+
unsafe fn finish(self, len: usize) -> Self::Result {
76+
let (init, uninit) = self.split_at_mut(len);
77+
78+
// SAFETY: The user asserts that the slice is now initialized.
79+
let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
80+
81+
(init, uninit)
82+
}
83+
}
84+
85+
impl<'a, T, const N: usize> private::Sealed<T> for &'a mut [MaybeUninit<T>; N] {
86+
type Result = (&'a mut [T], &'a mut [MaybeUninit<T>]);
87+
88+
#[inline]
89+
fn as_raw_parts_mut(&mut self) -> (*mut T, usize) {
90+
(self.as_mut_ptr().cast(), self.len())
9391
}
9492

9593
#[inline]
@@ -103,18 +101,14 @@ impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>] {
103101
}
104102
}
105103

106-
/// Implements [`Buffer`] around the `Vec` type.
107-
///
108-
/// This implementation fills the buffer, overwriting any previous data, with
109-
/// the new data data and sets the length.
110104
#[cfg(feature = "alloc")]
111-
impl<T> Buffer<T> for Vec<T> {
105+
impl<T> private::Sealed<T> for Vec<T> {
112106
type Result = Vec<T>;
113107

114108
#[inline]
115-
fn as_maybe_uninitialized(&mut self) -> &mut [MaybeUninit<T>] {
109+
fn as_raw_parts_mut(&mut self) -> (*mut T, usize) {
116110
self.clear();
117-
self.spare_capacity_mut()
111+
(self.as_mut_ptr(), self.capacity())
118112
}
119113

120114
#[inline]
@@ -143,6 +137,23 @@ pub(super) unsafe fn split_init(
143137
(init, uninit)
144138
}
145139

140+
mod private {
141+
pub trait Sealed<T> {
142+
/// The result of the process operation.
143+
type Result;
144+
145+
/// Return a pointer and length for this buffer.
146+
fn as_raw_parts_mut(&mut self) -> (*mut T, usize);
147+
148+
/// Convert a finished buffer pointer into its result.
149+
///
150+
/// # Safety
151+
///
152+
/// At least `len` bytes of the buffer must now be initialized.
153+
unsafe fn finish(self, len: usize) -> Self::Result;
154+
}
155+
}
156+
146157
#[cfg(test)]
147158
mod tests {
148159
use super::*;

src/fs/inotify.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
//! # }
4141
4242
#![allow(unused_qualifications)]
43-
#![allow(dead_code)] // FIXME
44-
#![allow(unused_imports)] // FIXME
4543

4644
use super::inotify;
4745
pub use crate::backend::fs::inotify::{CreateFlags, ReadFlags, WatchFlags};
@@ -176,17 +174,14 @@ impl<'buf, Fd: AsFd> Reader<'buf, Fd> {
176174
#[allow(clippy::should_implement_trait)]
177175
pub fn next(&mut self) -> io::Result<Event<'_>> {
178176
if self.is_buffer_empty() {
179-
todo!("FIXME: see \"Why doesn't this work?\" in examples/new_read.rs");
180-
/*
181-
match read(self.fd.as_fd(), self.buf).map(|(init, _)| init.len()) {
177+
match read(self.fd.as_fd(), &mut *self.buf).map(|(init, _)| init.len()) {
182178
Ok(0) => return Err(Errno::INVAL),
183179
Ok(bytes_read) => {
184180
self.initialized = bytes_read;
185181
self.offset = 0;
186182
}
187183
Err(e) => return Err(e),
188184
}
189-
*/
190185
}
191186

192187
let ptr = self.buf[self.offset..].as_ptr();

src/io/read_write.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ pub use backend::io::types::ReadWriteFlags;
3838
/// [glibc]: https://sourceware.org/glibc/manual/latest/html_node/I_002fO-Primitives.html#index-reading-from-a-file-descriptor
3939
#[inline]
4040
pub fn read<Fd: AsFd, Buf: Buffer<u8>>(fd: Fd, mut buf: Buf) -> io::Result<Buf::Result> {
41-
let len = backend::io::syscalls::read(fd.as_fd(), buf.as_maybe_uninitialized())?;
41+
// SAFETY: `read` behaves.
42+
let len = unsafe { backend::io::syscalls::read(fd.as_fd(), buf.as_raw_parts_mut())? };
4243
// SAFETY: `read` works.
4344
unsafe { Ok(buf.finish(len)) }
4445
}

0 commit comments

Comments
 (0)