3

我正在探索Rust 的 Iron Web 框架,并创建了一个小型处理程序,它将读取从请求 URL 派生的图像,调整其大小,然后传递结果。据我所知,可以从几种不同的类型构建Iron Response ,包括实现Read trait的类型。

image crate中的save 函数采用实现Write trait的类型。

感觉这两个函数应该能够连接起来,以便写入器写入读取器读取的缓冲区。我找到了pipe crate,它似乎实现了这种行为,但我无法将Read管道的末端变成 Iron 可以接受的东西。

我的函数的一个稍微简化的版本:

fn artwork(req: &mut Request) -> IronResult<Response> {
    let mut filepath = PathBuf::from("artwork/sample.png");

    let img = match image::open(&filepath) {
        Ok(img) => img,
        Err(e) => return Err(IronError::new(e, status::InternalServerError))
    };

    let (mut read, mut write) = pipe::pipe();

    thread::spawn(move || {
        let thumb = img.resize(128, 128, image::FilterType::Triangle);
        thumb.save(&mut write, image::JPEG).unwrap();
    });

    let mut res = Response::new();
    res.status = Some(iron::status::Ok);
    res.body = Some(Box::new(read));

    Ok(res)
}

我收到的错误:

src/main.rs:70:21: 70:35 error: the trait `iron::response::WriteBody` is not implemented for the type `pipe::PipeReader` [E0277]
src/main.rs:70     res.body = Some(Box::new(read));
                                   ^~~~~~~~~~~~~~

PipeReader实现ReadWriteBody实现,Read所以我觉得这应该工作。我也试过:

let reader: Box<Read> = Box::new(read);

let mut res = Response::new();
res.status = Some(iron::status::Ok);
res.body = Some(reader);

但这给出了错误:

src/main.rs:72:21: 72:27 error: mismatched types:
 expected `Box<iron::response::WriteBody + Send>`,
    found `Box<std::io::Read>`
(expected trait `iron::response::WriteBody`,
    found trait `std::io::Read`) [E0308]
src/main.rs:72     res.body = Some(reader);
                                   ^~~~~~

如何将save功能连接到 Iron 响应体?

4

2 回答 2

1

你不能在这里使用implfor Box<Read>,因为 Rust 不能保证它实现了Send. 但是,如果您有一个Box<Read + Send>,那就是这种情况。不幸的是,虽然Box<Read>implements没有WriteBodyBox<Read + Send>所以你不能使用这种类型。

查看源代码WriteBody及其实现,有一个注释掉的实现,它将WriteBody为所有实现的类型实现Read,但它现在还没有编译(正如评论所说,这需要专门化,这有望成为语言很快)。

您可以向 Iron 提交拉取请求以添加implfor WriteBodyon Box<Read + Send>;然后,您可以使用该类型(demo)。另一种选择是为自己定义一个包装结构PipeReader并实现WriteBody(可能基于的实现Box<Read>)。

于 2015-09-20T06:56:56.967 回答
0

如果您可以缓冲内存中的所有内容(我认为这已经发生了),您可以使用 a Vec<u8>plus a Cursor

use std::io::{self, Read, Write, Cursor};
use std::borrow::BorrowMut;

fn writer<W>(mut w: W) -> io::Result<()>
    where W: Write
{
    writeln!(w, "I am the writer")
}

fn reader<R>(mut r: R) -> io::Result<String>
    where R: Read
{
    let mut s = String::new();
    try!(r.read_to_string(&mut s));
    Ok(s)
}

fn inner_main() -> io::Result<()> {
    let mut buffer = vec![];

    try!(writer(&mut buffer));
    let s = try!(reader(Cursor::new(buffer.borrow_mut())));

    println!("Got >>{}<<", s);

    Ok(())
}

fn main() {
    inner_main().unwrap();
}

Cursor跟踪您在缓冲区中的距离,以便您始终读取或写入而无需重新读取或覆盖现有数据。

于 2015-09-20T19:39:17.937 回答