I have some code which uses Read
implementations with signature:
pub fn expand<IN>(read: IN, ...) -> ...
where IN: Read
{ ... }
(I have omitted irrelevant bits.)
I was invoking this in two ways: once with files (using a file reader) and once with a byte iterator (Bytes
). [Actually I was going from a string, so there is a simpler solution in my case. But the problem still remains.]
In the byte-iterator case I couldn't find a converter to a Read
implementation from the Bytes
type (which is an iterator) so I did this:
expand(some_byte_iterator.collect::<Vec<u8>>().as_slice(), ...)
which worked because there is a Read
implementation for &[u8]
. However this seems very "non-streamy" to me, so I tried to create a simple Read
implementation for Bytes
(which is a byte iterator from strings). I can't do this directly (because of the "coherence" rules) so I invented an intermediate type to hang the Read
implementation on.
Here is what I defined (in a sub-module):
use std::str::Bytes;
use std::io::{Result, Read};
pub struct ByteReader<'a>(Bytes<'a>);
impl<'a> Into<ByteReader<'a>> for Bytes<'a>
{
fn into(self) -> ByteReader<'a>
{
ByteReader(self)
}
}
impl<'a> Read for ByteReader<'a>
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
{
let len = buf.len();
for i in 0..len {
match self.0.next() {
Some(byte) => buf[i] = byte,
None => return Ok(i)
}
}
Ok(len)
}
}
(Please forgive the slightly idiosyncratic layout; I prefer this line-spacing and separation of generic constraints for (my) readability.)
The I tried to use this as follows:
expand(some_string.bytes().into(), ...)
(I now know I could write some_string.as_bytes()
, but peace.)
The compiler rejects this with this message:
error[E0282]: type annotations needed
--> src/generate/mod.rs:65:5
|
65 | expand(some_string.bytes().into(), ...)
| ^^^^^^ cannot infer type for `IN`
Fair enough, I'm presuming that I need annotations on into()
. But I cannot convince the compiler with any annotations I try.
expand(some_string.bytes().into::<ByteReader>(), ...)
gives this error:
error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
--> src/generate/mod.rs:65:40
|
65 | expand(some_string.bytes().into::<ByteReader>(), ...)
| ^^^^^^^^^^ expected 0 type parameters
Which I don't understand at all.
What annotations would convince the compiler of what I want?
Note added after comment
It has been pointed out that my explicit problem can be solved by going directly from my string to a slice &[u8]
, which would then be known as implementing Read
; et voila. But I still think there is a question to answer.