[0.32] Bound decode methods on Read, rather than BufRead#3173
[0.32] Bound decode methods on Read, rather than BufRead#3173apoelstra merged 1 commit intorust-bitcoin:0.32.xfrom
Read, rather than BufRead#3173Conversation
The Rust world has, sadly, standardized on `Read` for the type from which objects are deserialized. This makes forcing users into `BufRead`s in a library crate somewhat impractical - a `rust-bitcoin` user may implement some deserialization trait provided by a third-party and be stuck with a `Read`. Now, to read a `rust-bitcoin` object they'll have to wrap the `Read` in some `BufRead` wrapper that only buffers single bytes, wrecking their performance. While the user who is using this library should pass a `BufRead` (and may do so), the library using `rust-bitcoin` may not have any choice in the matter. Thus, here, we standardize on the same trait that the entire Rust world has standardized on, using `Read` for bounds in deserialization methods rather than `BufRead`. Here we avoid implementing `bitcoin_io::Read` for all `std` types to encourage users who do have control over the types being passed to use `BufReader` where possible, though this decision should be revisited once we have feedback from downstream users.
d4802f4 to
79df48e
Compare
Kixunil
left a comment
There was a problem hiding this comment.
This severely conflicts with #2184 which requires BufRead for performance. You should implement #3172 (comment) instead if you really want that. Also this comes off as aggressive since the conversation is not resolved.
|
Note that this is against the 0.32 branch and intended for a point release, so it conflicting with other PRs isn't a big deal. We can do something smarter, like you link to, for new releases. |
Pull Request Test Coverage Report for Build 10406462165Details
💛 - Coveralls |
|
Let's not change it just to change it again later. |
|
This isn't a change, this is an API relaxation for the current version as people upgrade to it. And, honestly, not sure we'll ever upgrade past 0.32, so I don't care too much about future breakage :). |
You might not but I do. |
|
Sure, if you care about future breakage and are already on 0.32 this doesn't effect you at all :) |
|
I was thinking that this cannot be really non-breaking and add the proper fix because of trait objects. So instead I suggest these changes:
Downstream users that want to use I offer making a PR for this. |
|
I'd prefer |
|
The doc should still say it may be slower though. |
Oh? I don't see why this is breaking. |
|
I think it might be ok. This code works on the playground: fn myfn<T: std::io::Read + ?Sized>(test: &mut T) {
// blah blah
}
fn myfn2<T: std::io::BufRead + ?Sized>(test: &mut T) {
// blah blah
}
fn main() {
let mut works_with_old_code = std::io::BufReader::new(std::io::stdin());
myfn2(&mut works_with_old_code as &mut dyn std::io::BufRead);
myfn(&mut works_with_old_code as &mut dyn std::io::BufRead);
} |
|
Yea, I went and did this and it seems to work: trait A {}
trait B: A{}
struct BI {}
impl A for BI {}
impl B for BI {}
fn fb<T: B + ?Sized>(t: &T) {}
fn fa<T: A + ?Sized>(t: &T) {}
fn dynb(t: &dyn B) { fa(t); }
fn main() {
let b = BI {};
fb(&b);
fa(&b);
let bt: &dyn B = &b;
fa(bt);
fb(bt);
} |
|
I meant adding the associated types. |
|
Ah, right, okay. Yea, the "proper fix" (assuming we don't end up on a push-based decode total API rewrite anyway) I assume we'd want to do in a new release anyway, leaving this for 0.32. |
|
I would like to do this in 0.32. I think that a proper fix would involve having an API that can take either a So we will need to break things relative to |
|
The failing CI look unrelated to this PR. |
| /// performance hit. | ||
| #[inline] | ||
| fn consensus_decode_from_finite_reader<R: BufRead + ?Sized>( | ||
| fn consensus_decode_from_finite_reader<R: Read + ?Sized>( |
There was a problem hiding this comment.
I've just realized this is strictly a breaking change since people who started to rely on it in their own implementations would get broken by it.
There was a problem hiding this comment.
IMO making the API usable is still worth it. I am fairly skeptical people implemented Decodable, but if we're super worried about it we should ship an 0.33 with just this change.
There was a problem hiding this comment.
If we ship 0.33 then I'd also do the breaking bitcoin-io change. But I still prefer to have the unbuffered methods.
There was a problem hiding this comment.
I think it's ok to break the API in this way. Agreed that nobody has implemented the Decodable trait themselves.
There was a problem hiding this comment.
Maybe we should've made them sealed. :(
|
I rebased this locally on top of #3418 and it seems good to go in on top of that. |
The Rust world has, sadly, standardized on
Readfor the type from which objects are deserialized. This makes forcing users intoBufReads in a library crate somewhat impractical - arust-bitcoinuser may implement some deserialization trait provided by a third-party and be stuck with aRead. Now, to read arust-bitcoinobject they'll have to wrap theReadin someBufReadwrapper that only buffers single bytes, wrecking their performance. While the user who is using this library should pass aBufRead(and may do so), the library usingrust-bitcoinmay not have any choice in the matter.Thus, here, we standardize on the same trait that the entire Rust world has standardized on, using
Readfor bounds in deserialization methods rather thanBufRead.Here we avoid implementing
bitcoin_io::Readfor allstdtypes to encourage users who do have control over the types being passed to useBufReaderwhere possible, though this decision should be revisited once we have feedback from downstream users.I only bothered to implement this for 0.32 here (we'll have to do something similar upstream, but its super easy to just rebuild this patch and is probably less error-prone than trying to backport, plus we can discuss further if we want to do this on other version(s)).
See #3172 for further discussion.