Skip to content

Commit 53eb961

Browse files
committed
Report the number of received bytes in recv_uninit and recvfrom_uninit.
As discussed in #1159, add a length to the return value of `recv_uninit` and `recvfrom_uninit` to report the original received length, which with `RecvFlags::TRUNC` may differ from the returned buffer length.
1 parent f377e85 commit 53eb961

2 files changed

Lines changed: 18 additions & 18 deletions

File tree

src/net/send_recv/mod.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,26 +70,23 @@ pub fn recv<Fd: AsFd>(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result<us
7070
/// `recv(fd, buf, flags)`—Reads data from a socket.
7171
///
7272
/// This is equivalent to [`recv`], except that it can read into uninitialized
73-
/// memory. It returns the slice that was initialized by this function and the
74-
/// slice that remains uninitialized.
75-
///
76-
/// Because this interface returns the length via the returned slice, it's
77-
/// unsable to return the untruncated length that would be returned when the
78-
/// `RecvFlags::TRUNC` flag is used. If you need the untruncated length, use
79-
/// [`recv`].
73+
/// memory. It returns the slice that was initialized by this function, the
74+
/// slice that remains uninitialized, and the number of bytes received before
75+
/// any truncation due to the `RecvFlags::TRUNC` flag.
8076
#[inline]
8177
pub fn recv_uninit<Fd: AsFd>(
8278
fd: Fd,
8379
buf: &mut [MaybeUninit<u8>],
8480
flags: RecvFlags,
85-
) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>])> {
81+
) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>], usize)> {
8682
let length = unsafe {
8783
backend::net::syscalls::recv(fd.as_fd(), buf.as_mut_ptr().cast::<u8>(), buf.len(), flags)?
8884
};
8985

9086
// If the `TRUNC` flag is set, the returned `length` may be longer than the
9187
// buffer length.
92-
Ok(unsafe { split_init(buf, min(length, buf.len())) })
88+
let (init, uninit) = unsafe { split_init(buf, min(length, buf.len())) };
89+
Ok((init, uninit, length))
9390
}
9491

9592
/// `send(fd, buf, flags)`—Writes data to a socket.
@@ -167,19 +164,21 @@ pub fn recvfrom<Fd: AsFd>(
167164
///
168165
/// This is equivalent to [`recvfrom`], except that it can read into
169166
/// uninitialized memory. It returns the slice that was initialized by this
170-
/// function and the slice that remains uninitialized.
171-
///
172-
/// Because this interface returns the length via the returned slice, it's
173-
/// unsable to return the untruncated length that would be returned when the
174-
/// `RecvFlags::TRUNC` flag is used. If you need the untruncated length, use
175-
/// [`recvfrom`].
167+
/// function, the slice that remains uninitialized, the number of bytes
168+
/// received before any truncation due to the `RecvFlags::TRUNC` flag, and
169+
/// the address of the sender if known.
176170
#[allow(clippy::type_complexity)]
177171
#[inline]
178172
pub fn recvfrom_uninit<Fd: AsFd>(
179173
fd: Fd,
180174
buf: &mut [MaybeUninit<u8>],
181175
flags: RecvFlags,
182-
) -> io::Result<(&mut [u8], &mut [MaybeUninit<u8>], Option<SocketAddrAny>)> {
176+
) -> io::Result<(
177+
&mut [u8],
178+
&mut [MaybeUninit<u8>],
179+
usize,
180+
Option<SocketAddrAny>,
181+
)> {
183182
let (length, addr) = unsafe {
184183
backend::net::syscalls::recvfrom(
185184
fd.as_fd(),
@@ -192,7 +191,7 @@ pub fn recvfrom_uninit<Fd: AsFd>(
192191
// If the `TRUNC` flag is set, the returned `length` may be longer than the
193192
// buffer length.
194193
let (init, uninit) = unsafe { split_init(buf, min(length, buf.len())) };
195-
Ok((init, uninit, addr))
194+
Ok((init, uninit, length, addr))
196195
}
197196

198197
/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP

tests/net/recv_trunc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ fn net_recv_uninit_trunc() {
2020
drop(sender);
2121

2222
let mut response = [MaybeUninit::<u8>::zeroed(); 5];
23-
let (init, uninit) =
23+
let (init, uninit, length) =
2424
rustix::net::recv_uninit(&receiver, &mut response, RecvFlags::TRUNC).expect("recv_uninit");
2525

2626
// We used the `TRUNC` flag, so we should have only gotten 5 bytes.
2727
assert_eq!(init, b"Hello");
2828
assert!(uninit.is_empty());
29+
assert_eq!(length, 15);
2930
}

0 commit comments

Comments
 (0)