Skip to content

Commit f18a951

Browse files
committed
Implement Write trait for MaybeUninit<u8>
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
1 parent 1661e4c commit f18a951

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

library/std/src/io/impls.rs

+57-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::fmt;
77
use crate::io::{
88
self, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write,
99
};
10-
use crate::mem;
10+
use crate::{mem, ptr};
1111

1212
// =============================================================================
1313
// Forwarding implementations
@@ -410,3 +410,59 @@ impl<A: Allocator> Write for Vec<u8, A> {
410410
Ok(())
411411
}
412412
}
413+
414+
/// Write is implemented for `&mut [MaybeUninit<u8>]` by copying into the slice, overwriting
415+
/// its data. After a write, the sucessfully written elements are guaranteed to be initialized.
416+
///
417+
/// Note that writing updates the slice to point to the yet unwritten part.
418+
/// The slice will be empty when it has been completely overwritten.
419+
///
420+
/// If the number of bytes to be written exceeds the size of the slice, write operations will
421+
/// return short writes: ultimately, `Ok(0)`; in this situation, `write_all` returns an error of
422+
/// kind `ErrorKind::WriteZero`.
423+
#[stable(feature = "write_maybeuninit", since = "1.60.0")]
424+
impl Write for &mut [mem::MaybeUninit<u8>] {
425+
#[inline]
426+
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
427+
let amt = cmp::min(data.len(), self.len());
428+
let (a, b) = mem::replace(self, &mut []).split_at_mut(amt);
429+
// SAFETY: since self is a mutable slice, the aliasing rules prevent overlap
430+
unsafe {
431+
ptr::copy_nonoverlapping(data.as_ptr(), a.as_mut_ptr() as *mut u8, amt);
432+
}
433+
*self = b;
434+
Ok(amt)
435+
}
436+
437+
#[inline]
438+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
439+
let mut nwritten = 0;
440+
for buf in bufs {
441+
nwritten += self.write(buf)?;
442+
if self.is_empty() {
443+
break;
444+
}
445+
}
446+
447+
Ok(nwritten)
448+
}
449+
450+
#[inline]
451+
fn is_write_vectored(&self) -> bool {
452+
true
453+
}
454+
455+
#[inline]
456+
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
457+
if self.write(data)? == data.len() {
458+
Ok(())
459+
} else {
460+
Err(io::const_io_error!(ErrorKind::WriteZero, "failed to write whole buffer"))
461+
}
462+
}
463+
464+
#[inline]
465+
fn flush(&mut self) -> io::Result<()> {
466+
Ok(())
467+
}
468+
}

library/std/src/io/impls/tests.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::io::prelude::*;
2+
use crate::mem::MaybeUninit;
23

34
#[bench]
45
fn bench_read_slice(b: &mut test::Bencher) {
@@ -44,7 +45,21 @@ fn bench_read_vec(b: &mut test::Bencher) {
4445

4546
#[bench]
4647
fn bench_write_vec(b: &mut test::Bencher) {
47-
let mut buf = Vec::with_capacity(1024);
48+
let mut buf = Vec::<u8>::with_capacity(1024);
49+
let src = [5; 128];
50+
51+
b.iter(|| {
52+
let mut wr = &mut buf[..];
53+
for _ in 0..8 {
54+
let _ = wr.write_all(&src);
55+
test::black_box(&wr);
56+
}
57+
})
58+
}
59+
60+
#[bench]
61+
fn bench_write_maybeuninit(b: &mut test::Bencher) {
62+
let mut buf = [MaybeUninit::<u8>::uninit(); 1024];
4863
let src = [5; 128];
4964

5065
b.iter(|| {

0 commit comments

Comments
 (0)