Implementing Read trait : trait bound `std::error:

2019-07-31 02:19发布

I want to implement the Read trait for a struct for the purpose of using it in a BufReader to pass to a library. The library uses a BufReader as input because it should work with Stdin and with an in-memory object that implements Read.

use std::error::Error;
use std::io::Read;

pub struct Test {
    counter: u8,
}

impl Test {
    pub fn new() -> Test {
        Test { counter: 0 }
    }
}

impl Iterator for Test {
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        if self.counter < 2 {
            self.counter += 1;
            return Some("String".to_string());
        }

        None
    }
}

impl Read for Test {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        let content = self.next();
        match content {
            None => Err(std::io::Error::new(
                std::io::ErrorKind::Other,
                "End of Iterator",
            )),
            Some(string) => {
                let mut i = 0;
                loop {
                    if i >= buf.len() || i >= string.len() {
                        break;
                    }

                    buf[i] = string[i];
                    i += 1;
                }

                Ok(i)
            }
        }
    }
}

fn main() {
    let test = Test::new();
    let reader = std::io::BufReader::new(test);
    // let filter = lib_that_uses_bufreader::useful_function(reader);
}

(playground)

When trying to implement Read for the struct, I get the error:

error[E0277]: the trait bound `std::error::Error + 'static: std::marker::Sized` is not satisfied
  --> src/main.rs:28:5
   |
28 | /     fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
29 | |         let content = self.next();
30 | |         match content {
31 | |             None => Err(std::io::Error::new(
...  |
48 | |         }
49 | |     }
   | |_____^ `std::error::Error + 'static` does not have a constant size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `std::error::Error + 'static`
   = note: required by `std::result::Result`

I built the library myself, so it could be changed but it works very well with Stdin and I now want to use it with a struct. The library uses BufReader::lines, so it could be exchanged with an iterator, but as I understood, this would break compatibility with Stdin, as I was only able to build a BufReader around Stdin, not an iterator.

How do I resolve this error? What error object has a constant size known at compile-time?

标签: rust
1条回答
欢心
2楼-- · 2019-07-31 03:04

Return

Result<usize, std::io::Error>

Instead of

Result<usize, Error>

std::error::Error, which you’re using in your signature, is a trait. You can’t return a trait directly.

You could also do

Result<usize, Box<dyn Error>>

A “trait object”, but I don’t see why you would in this case.

查看更多
登录 后发表回答