У меня есть клиент, работающий с Future
, который кое-что делает. Можно ли использовать impl Future<Item = (), Error = io::Error>
в качестве возвращаемого типа и улучшить обработку ошибок?
pub fn handle_client(client: Client) -> impl Future<Item = (), Error = io::Error> {
let magic = client.header.magic;
let stream_client = TcpStream::connect(&client.addr).and_then(|stream| {
let addr: Vec<u8> = serialize_addr(stream.local_addr()?, magic)?;
write_all(stream, addr).then(|result| {
// some code
Ok(())
})
});
stream_client
}
Я не могу сохранить тип io::Error
во всех вложенных закрытиях / фьючерсах. Компилятор выдает ошибку
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/client.rs:134:29
|
134 | let addr: Vec<u8> = serialize_addr(stream.local_addr()?, magic)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `futures::future::then::Then<tokio_io::io::write_all::WriteAll<tokio_tcp::stream::TcpStream, std::vec::Vec<u8>>, std::result::Result<(), std::io::Error>, [closure@src/client.rs:135:38: 138:10]>`
|
= help: the trait `std::ops::Try` is not implemented for `futures::future::then::Then<tokio_io::io::write_all::WriteAll<tokio_tcp::stream::TcpStream, std::vec::Vec<u8>>, std::result::Result<(), std::io::Error>, [closure@src/client.rs:135:38: 138:10]>`
= note: required by `std::ops::Try::from_error`
Я выполнил цепочку обработки ошибок map / and_then, но проблема в том, что я не знаю, как получить TcpStream
внутри окончательного .then
закрытия. Единственное место, где я нашел TcpStream
, - это внутри структуры WriteAll, но она приватная. Кроме того, write_all потребляет поток
use futures::Future;
use std::{io, net::SocketAddr};
use tokio::{
io::{write_all, AsyncRead, AsyncWrite},
net::TcpStream,
};
type Error = Box<dyn std::error::Error>;
fn serialize_addr(addr: SocketAddr) -> Result<Vec<u8>, Error> {
Ok(vec![])
}
fn handle_client(addr: &SocketAddr) -> impl Future<Item = (), Error = Error> {
TcpStream::connect(addr)
.map_err(Into::into)
.and_then(|stream| stream.local_addr().map(|stream_addr| (stream, stream_addr)))
.map_err(Into::into)
.and_then(|(stream, stream_addr)| serialize_addr(stream_addr).map(|info| (stream, info)))
.map(|(stream, info)| write_all(stream, info))
.then(|result| {
let result = result.unwrap();
let stream = match result.state {
Writing { a } => a,
_ => panic!("cannot get stream"),
};
// some code
Ok(())
})
}
fn main() {
let addr = "127.0.0.1:8900".parse().unwrap();
handle_client(&addr);
}
map(... write_all)
, когда в приведенном ниже коде используетсяand_then
? Вы не можете произвольно изменить вызываемые методы и ожидать, что они будут работать. При использованииand_then
значение успеха будущего равно(TcpStream, Vec<u8>)
. - person Shepmaster   schedule 01.03.2019serialize_addr(remote_addr).map_err(|_| io::Error::from(io::ErrorKind::AddrNotAvailable))
я не мог использовать.and_then
вместо.map
- person abritov   schedule 02.03.2019