Skip to content

Commit 5e30c9f

Browse files
committed
Use macro to implement our traits for std types
We want to implement the traits for more types which would be tedious without a macro and it'd risk forgetting to forward some method since they may be speialized. This also adds previously-forgotten specializations. It also relaxes the implicit `Sized` bound on `BufReader` and `BufWriter` in Rust versions above 1.72.
1 parent 505ecd8 commit 5e30c9f

File tree

3 files changed

+109
-14
lines changed

3 files changed

+109
-14
lines changed

io/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ all-features = true
2323
rustdoc-args = ["--cfg", "docsrs"]
2424

2525
[lints.rust]
26-
unexpected_cfgs = { level = "deny" }
26+
unexpected_cfgs = { level = "deny", check-cfg = ['cfg(rust_v_1_72)'] }

io/build.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
fn main() {
2+
let rustc = std::env::var_os("RUSTC");
3+
let rustc = rustc.as_ref().map(std::path::Path::new).unwrap_or_else(|| "rustc".as_ref());
4+
let output = std::process::Command::new(rustc)
5+
.arg("--version")
6+
.output()
7+
.unwrap_or_else(|error| panic!("failed to run `{:?} --version`: {:?}", rustc, error));
8+
assert!(output.status.success(), "{:?} -- version returned non-zero exit code", rustc);
9+
let stdout = String::from_utf8(output.stdout).expect("rustc produced non-UTF-8 output");
10+
let version_prefix = "rustc ";
11+
if !stdout.starts_with(version_prefix) {
12+
panic!("unexpected rustc output: {}", stdout);
13+
}
14+
15+
let version = &stdout[version_prefix.len()..];
16+
let end = version.find(&[' ', '-'] as &[_]).unwrap_or(version.len());
17+
let version = &version[..end];
18+
let mut version_components = version.split('.');
19+
let major = version_components.next().unwrap();
20+
assert_eq!(major, "1", "unexpected Rust major version");
21+
let minor = version_components
22+
.next()
23+
.unwrap_or("0")
24+
.parse::<u64>()
25+
.expect("invalid Rust minor version");
26+
27+
let msrv = std::env::var("CARGO_PKG_RUST_VERSION").unwrap();
28+
let mut msrv = msrv.split(".");
29+
let msrv_major = msrv.next().unwrap();
30+
assert_eq!(msrv_major, "1", "unexpected Rust major version");
31+
let msrv_minor = msrv.next().unwrap().parse::<u64>().unwrap();
32+
33+
// print cfg for all interesting versions less than or equal to minor
34+
for version in msrv_minor..=minor {
35+
println!("cargo:rustc-cfg=rust_v_1_{}", version);
36+
}
37+
}

io/src/bridge.rs

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -255,17 +255,73 @@ impl<T: super::Write> super::Write for ToStd<T> {
255255
}
256256
}
257257

258-
impl<R: std::io::Read> super::Read for std::io::BufReader<R> {
259-
#[inline]
260-
fn read(&mut self, buf: &mut [u8]) -> super::Result<usize> { Ok(std::io::Read::read(self, buf)?) }
258+
macro_rules! impl_our {
259+
(impl$(<$($gen:ident $(: $gent:path)?),*>)? Read for $std_type:ty $(where $($where:tt)*)?) => {
260+
impl$(<$($gen$(: $gent)?),*>)? super::Read for $std_type $(where $($where)*)? {
261+
#[inline]
262+
fn read(&mut self, buf: &mut [u8]) -> super::Result<usize> {
263+
std::io::Read::read(self, buf).map_err(Into::into)
264+
}
265+
266+
#[inline]
267+
fn read_exact(&mut self, buf: &mut [u8]) -> super::Result<()> {
268+
std::io::Read::read_exact(self, buf).map_err(Into::into)
269+
}
270+
}
271+
};
272+
273+
(impl$(<$($gen:ident $(: $gent:path)?),*>)? BufRead for $std_type:ty $(where $($where:tt)*)?) => {
274+
impl$(<$($gen$(: $gent)?),*>)? super::BufRead for $std_type $(where $($where)*)? {
275+
#[inline]
276+
fn fill_buf(&mut self) -> super::Result<&[u8]> {
277+
std::io::BufRead::fill_buf(self).map_err(Into::into)
278+
}
279+
280+
#[inline]
281+
fn consume(&mut self, amount: usize) {
282+
std::io::BufRead::consume(self, amount)
283+
}
284+
}
285+
};
286+
287+
(impl$(<$($gen:ident $(: $gent:path)?),*>)? Write for $std_type:ty $(where $($where:tt)*)?) => {
288+
impl$(<$($gen$(: $gent)?),*>)? super::Write for $std_type $(where $($where)*)? {
289+
#[inline]
290+
fn write(&mut self, buf: &[u8]) -> super::Result<usize> {
291+
std::io::Write::write(self, buf).map_err(Into::into)
292+
}
293+
294+
#[inline]
295+
fn flush(&mut self) -> super::Result<()> {
296+
std::io::Write::flush(self).map_err(Into::into)
297+
}
298+
299+
#[inline]
300+
fn write_all(&mut self, buf: &[u8]) -> super::Result<()> {
301+
std::io::Write::write_all(self, buf).map_err(Into::into)
302+
}
303+
}
304+
};
261305
}
262306

263-
impl<R: std::io::Read> super::BufRead for std::io::BufReader<R> {
264-
#[inline]
265-
fn fill_buf(&mut self) -> super::Result<&[u8]> { Ok(std::io::BufRead::fill_buf(self)?) }
307+
#[cfg(rust_v_1_72)]
308+
impl_our! {
309+
impl<R: std::io::Read> Read for std::io::BufReader<R> where R: ?Sized
310+
}
266311

267-
#[inline]
268-
fn consume(&mut self, amount: usize) { std::io::BufRead::consume(self, amount) }
312+
#[cfg(not(rust_v_1_72))]
313+
impl_our! {
314+
impl<R: std::io::Read> Read for std::io::BufReader<R>
315+
}
316+
317+
#[cfg(rust_v_1_72)]
318+
impl_our! {
319+
impl<R: std::io::Read> BufRead for std::io::BufReader<R> where R: ?Sized
320+
}
321+
322+
#[cfg(not(rust_v_1_72))]
323+
impl_our! {
324+
impl<R: std::io::Read> BufRead for std::io::BufReader<R>
269325
}
270326

271327
impl std::io::Write for super::Sink {
@@ -279,10 +335,12 @@ impl std::io::Write for super::Sink {
279335
fn flush(&mut self) -> std::io::Result<()> { Ok(()) }
280336
}
281337

282-
impl<W: std::io::Write> super::Write for std::io::BufWriter<W> {
283-
#[inline]
284-
fn write(&mut self, buf: &[u8]) -> super::Result<usize> { Ok(std::io::Write::write(self, buf)?) }
338+
#[cfg(rust_v_1_72)]
339+
impl_our! {
340+
impl<W: std::io::Write> Write for std::io::BufWriter<W> where W: ?Sized
341+
}
285342

286-
#[inline]
287-
fn flush(&mut self) -> super::Result<()> { Ok(std::io::Write::flush(self)?) }
343+
#[cfg(not(rust_v_1_72))]
344+
impl_our! {
345+
impl<W: std::io::Write> Write for std::io::BufWriter<W>
288346
}

0 commit comments

Comments
 (0)