我正在探索Iron web framework for Rust并创建了一个小型处理程序,它将读取从请求URL派生的图像,调整其大小然后传递结果。据我所知,Iron Response可以从几种不同的类型构建,包括实现Read trait的类型。
save function中的image crate采用实现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实施Read
,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
如何将PFFile
功能连接到Iron响应主体?
答案 0 :(得分:1)
您不能在impl
使用Box<Read>
,因为Rust无法保证它实现Send
。如果你有一个Box<Read + Send>
,那就是这种情况。不幸的是,虽然Box<Read>
实现了WriteBody
,但Box<Read + Send>
却没有,因此您无法使用此类型。
查看WriteBody
及其实现的源代码,a commented out implementation将为实现WriteBody
的所有类型实现Read
,但它不会编译为现在(正如评论所说,这需要专业化,希望很快就会出现这种语言)。
您可以向Iron提交拉取请求,以便在impl
上为WriteBody
添加Box<Read + Send>
;那么,你可以使用那种类型(demo)。另一种选择是为PipeReader
定义包装器结构并自己实现WriteBody
(可能基于the implementation for Box<Read>
)。
答案 1 :(得分:0)
如果你可以缓冲内存中的所有内容(我认为这就是已经发生的事情),你可以使用Vec<u8>
加上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
会跟踪您在缓冲区中的位置,以便您无需重新读取或覆盖现有数据即可进行读取或写入。