将采用 Write 的函数连接到采用 Read 的函数
Connect function that takes Write to function that takes Read
我正在探索Iron web framework for Rust and have created a small handler that will read an image derived from the request URL, resize it and then deliver the result. From what I can tell an Iron Response can be built from a several different types, including types that implement the Read trait。
save function in the image crate takes a type that implements the Write trait.
感觉这两个函数应该能够连接起来,这样作者就可以写入一个缓冲区,reader 从中读取。我找到了 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 implements Read
and WriteBody 是为 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 响应体?
你不能在这里为 Box<Read>
使用 impl
,因为 Rust 不能保证它实现了 Send
。不过,如果您有 Box<Read + Send>
,情况就是这样。不幸的是,虽然 Box<Read>
实现了 WriteBody
,但 Box<Read + Send>
没有,所以你不能使用这种类型。
查看 WriteBody
及其实现的源代码,a commented out implementation 会为所有实现 Read
的类型实现 WriteBody
,但它不会从现在开始编译(正如评论所说,这需要专业化,希望很快就会出现在该语言中)。
您可以向 Iron 提交拉取请求以在 Box<Read + Send>
上为 WriteBody
添加 impl
;然后,您可以使用该类型 (demo). Another option is to define a wrapper struct for PipeReader
and implement WriteBody
yourself (possibly based on the implementation for Box<Read>
).
如果您可以在内存中缓冲所有内容(我认为这已经发生了),您可以只使用 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
跟踪您在缓冲区中的距离,以便您始终读取或写入而无需重新读取或覆盖现有数据。
我正在探索Iron web framework for Rust and have created a small handler that will read an image derived from the request URL, resize it and then deliver the result. From what I can tell an Iron Response can be built from a several different types, including types that implement the Read trait。
save function in the image crate takes a type that implements the Write trait.
感觉这两个函数应该能够连接起来,这样作者就可以写入一个缓冲区,reader 从中读取。我找到了 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 implements Read
and WriteBody 是为 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 响应体?
你不能在这里为 Box<Read>
使用 impl
,因为 Rust 不能保证它实现了 Send
。不过,如果您有 Box<Read + Send>
,情况就是这样。不幸的是,虽然 Box<Read>
实现了 WriteBody
,但 Box<Read + Send>
没有,所以你不能使用这种类型。
查看 WriteBody
及其实现的源代码,a commented out implementation 会为所有实现 Read
的类型实现 WriteBody
,但它不会从现在开始编译(正如评论所说,这需要专业化,希望很快就会出现在该语言中)。
您可以向 Iron 提交拉取请求以在 Box<Read + Send>
上为 WriteBody
添加 impl
;然后,您可以使用该类型 (demo). Another option is to define a wrapper struct for PipeReader
and implement WriteBody
yourself (possibly based on the implementation for Box<Read>
).
如果您可以在内存中缓冲所有内容(我认为这已经发生了),您可以只使用 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
跟踪您在缓冲区中的距离,以便您始终读取或写入而无需重新读取或覆盖现有数据。