Skip to content

Commit 4417d63

Browse files
authored
Add method BoundedBuf::put_slice (tokio-rs#198)
Provide a generic, safe way to copy data into a buffer, possibly advancing the initialized length watermark. This method is especially useful for `FixedBuf`, which lacks other population methods available for the foreign types. This resolves a discussion started in tokio-rs#190 (comment)
1 parent e1b2f1a commit 4417d63

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

src/buf/bounded.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::{IoBuf, IoBufMut, Slice};
22

33
use std::ops;
4+
use std::ptr;
45

56
/// A possibly bounded view into an owned [`IoBuf`] buffer.
67
///
@@ -152,6 +153,29 @@ pub trait BoundedBufMut: BoundedBuf<Buf = Self::BufMut> {
152153
/// The caller must ensure that all bytes starting at `stable_mut_ptr()` up
153154
/// to `pos` are initialized and owned by the buffer.
154155
unsafe fn set_init(&mut self, pos: usize);
156+
157+
/// Copies the given byte slice into the buffer, starting at
158+
/// this view's offset.
159+
///
160+
/// # Panics
161+
///
162+
/// If the slice's length exceeds the destination's total capacity,
163+
/// this method panics.
164+
fn put_slice(&mut self, src: &[u8]) {
165+
assert!(self.bytes_total() >= src.len());
166+
let dst = self.stable_mut_ptr();
167+
168+
// Safety:
169+
// dst pointer validity is ensured by stable_mut_ptr;
170+
// the length is checked to not exceed the view's total capacity;
171+
// src (immutable) and dst (mutable) cannot point to overlapping memory;
172+
// after copying the amount of bytes given by the slice, it's safe
173+
// to mark them as initialized in the buffer.
174+
unsafe {
175+
ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len());
176+
self.set_init(src.len());
177+
}
178+
}
155179
}
156180

157181
impl<T: IoBufMut> BoundedBufMut for T {

tests/fs_file.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::{
22
io::prelude::*,
33
os::unix::io::{AsRawFd, FromRawFd, RawFd},
4-
ptr,
54
};
65

76
use tempfile::NamedTempFile;
@@ -263,15 +262,15 @@ fn write_fixed() {
263262

264263
let fixed_buf = buffers.check_out(0).unwrap();
265264
let mut buf = fixed_buf;
266-
push_slice_to_buf(&HELLO[..6], &mut buf);
265+
buf.put_slice(&HELLO[..6]);
267266

268267
let (res, _) = file.write_fixed_at(buf, 0).await;
269268
let n = res.unwrap();
270269
assert_eq!(n, 6);
271270

272271
let fixed_buf = buffers.check_out(1).unwrap();
273272
let mut buf = fixed_buf;
274-
push_slice_to_buf(&HELLO[6..], &mut buf);
273+
buf.put_slice(&HELLO[6..]);
275274

276275
let (res, _) = file.write_fixed_at(buf, 6).await;
277276
let n = res.unwrap();
@@ -312,12 +311,3 @@ fn assert_invalid_fd(fd: RawFd) {
312311
res => panic!("{:?}", res),
313312
}
314313
}
315-
316-
fn push_slice_to_buf(src: &[u8], buf: &mut impl BoundedBufMut) {
317-
assert!(buf.bytes_total() >= src.len());
318-
let dst = buf.stable_mut_ptr();
319-
unsafe {
320-
ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len());
321-
buf.set_init(src.len());
322-
}
323-
}

0 commit comments

Comments
 (0)