We attempted to release with the current 0.1.0 version forgetting that
we had previously released an empty crate with that version to reserve
the name on crates.io.
Bump the version to 0.1.1 and release the actual code.
Remove the blanket impls of `Read`, `BufRead`, and `Write`. Replace them
with a set of sane impls.
Note, we add code to the `impl_write` macro to implement both
`crate::Write` and `std::io::Write` when "std" feature is
enabled.
Fix: #2432
Done in preparation for an initial v0.1.0 release of the new `io` crate.
Add a changelog file with a brief description of whats in the initial release.
Currently `Take::read_to_end` is private forcing users to use our
"custom" `read_to_limit`, for seasoned Rust hackers
`foo.take(16).read_to_end(buf)` make be more unsurprising.
Make `read_to_end` public.
Make the trait level attributes uniform across all released crates in
the repo. Excludes things that are obviously not needed, eg, bench stuff
if there is not bench code.
- Remove `uninhabited_references` - this is allow by default now.
- Remove `unconditional_recursion` and mark the single false positive we
have with an `allow`.
Note, this does not add `missing_docs` to the `io` crate. There is an
open PR at the moment to add that along with the required docs.
The `std::io::Read` trait includes `read_to_end` but that method
provides a denial of service attack vector since an unbounded reader
will exhaust all system memory.
Add a method to our `Read` trait called `read_to_limit` that does the
same as `std::io::Read::read_to_end` but with memory exhaustion
protection.
Add a `read_to_end` method on our `Take` trait and call through to it
from the new method on our `Read` trait called `read_to_limit`.
Add a `BufRead` trait for types that perform buffered reading.
Implement it for:
- `Take`
- `Cursor`
- `std::io::BufRead` readers
- (in no-std builds) for slice of u8s
Move error code to a private `error` submodule and re-export it at the
crate root.
(Puts private `sealed` module at the bottom of the file i.e., this patch
is strictly a code move but we re-order the code while moving it.)
Its not immediately obvious why we nest the whole `io` code in an `io`
submodule within `lib.rs`. As far as I can tell we can inline it and
re-export from `rust-bitcoin` same as we do for our other dependencies.
This change would effect other users of the crate but since the `io`
crate is unreleased this effects no-one except us.
In preparation for inlining the `io` molule, move the public macros to a
private `macros` module.
Includes removal of the public re-export of `std` as `_std` - flaggin
this because I do not understand why it is here in the first place, we
can use `std::io::Write` in code that is feature gated on "std".
In order to move towards our own I/O traits in the `rust-bitcoin`
ecosystem, we have to slowly replace our use of the `std` and
`core2` traits.
This is the final step in removing the explicit `core2` dependency
for I/O in no-std - replacing the `io::Error` type with our own.
Sadly the `std::io::Error` type requires `std::error::Error` as a
bound on the inner error, which is rather difficult to duplicate in
a way that allows for mapping to `std` and back.
To take a more general approach, we use bound on any `Debug`
instead.
In order to move towards our own I/O traits in the `rust-bitcoin`
ecosystem, we have to slowly replace our use of the `std` and
`core2` traits.
Here we take the second big step, replacing
`{std,core2}::io::Read` with our own `bitcoin_io::io::Read`. We
provide a blanket impl for our trait for all `std::io::Read`, if
the `std` feature is enabled, allowing users who use their own
streams or `std` streams to call `rust-bitcoin` methods directly.
With the new `bitcoin_io` library, implementing `io::Write`
manually is somewhat tricky - for `std` users we really want to
provide an `std::io::Write` implementation, however for `no-std`
users we want to implement against our internal trait.
Sadly we cannot provide a blanket implementation of
`std::io::Write` for all types whcih implement our `io::Write`
trait as its an out-of-crate impl.
Instead, we provide a macro which will either implement
`std::io::Write` or our `io::Write` depending on the feature flags
set on `bitcoin_io`.
In order to move towards our own I/O traits in the `rust-bitcoin`
ecosystem, we have to slowly replace our use of the `std` and
`core2` traits.
Here we take the first real step, replacing
`{std,core2}::io::Write` withour own `bitcoin_io::io::Write`. We
provide a blanket impl for our trait for all `std::io::Write`, if
the `std` feature is enabled, allowing users who use their own
streams or `std` streams to call `rust-bitcoin` methods directly.
In the coming commits we'll move our `io` module to having its own
implementations of the usual I/O traits and structs. Here we first
move to re-exporting only exactly what we need, allowing us to
whittle the list down from a fixed set.
In order to support standard (de)serialization of structs, the
`rust-bitcoin` ecosystem uses the standard `std::io::{Read,Write}`
traits. This works great for environments with `std`, however sadly
the `std::io` module has not yet been added to the `core` crate.
Thus, in `no-std`, the `rust-bitcoin` ecosystem has historically
used the `core2` crate to provide copies of the `std::io` module
without any major dependencies. Sadly, its one dependency,
`memchr`, recently broke our MSRV.
Worse, because we didn't want to take on any excess dependencies
for `std` builds, `rust-bitcoin` has had to have
mutually-exclusive `std` and `no-std` builds. This breaks general
assumptions about how features work in Rust, causing substantial
pain for applications far downstream of `rust-bitcoin` crates.
Here, we add a new `bitcoin_io` crate, making it an unconditional
dependency and using its `io` module in the in-repository crates
in place of `std::io` and `core2::io`. As it is not substantial
additional code, the `hashes` io implementations are no longer
feature-gated.
This doesn't actually accomplish anything on its own, only adding
the new crate which still depends on `core2`.