// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the MIT License, . // This file may not be copied, modified, or distributed except according to those terms. use serde; use futures::{self, Async}; use bincode::{SizeLimit, serde as bincode}; use std::{io, thread}; use std::collections::VecDeque; use std::sync::mpsc; use util::Never; use tokio_core::io::{FramedIo, Io}; use tokio_core::reactor::{Core, Remote}; use tokio_proto::pipeline::Frame; lazy_static! { #[doc(hidden)] pub static ref LOOP_HANDLE: Remote = { let (tx, rx) = mpsc::channel(); thread::spawn(move || { let mut lupe = Core::new().unwrap(); tx.send(lupe.handle().remote().clone()).unwrap(); // Run forever lupe.run(futures::empty::<(), !>()).unwrap(); }); rx.recv().unwrap() }; } pub use self::writer::Packet; pub mod reader; pub mod writer; /// A helper trait to provide the `map_non_block` function on Results. trait MapNonBlock { /// Maps a `Result` to a `Result>` by converting /// operation-would-block errors into `Ok(None)`. fn map_non_block(self) -> io::Result>; } impl MapNonBlock for io::Result { fn map_non_block(self) -> io::Result> { use std::io::ErrorKind::WouldBlock; match self { Ok(value) => Ok(Some(value)), Err(err) => { if let WouldBlock = err.kind() { Ok(None) } else { Err(err) } } } } } /// Deserialize a buffer into a `D` and its ID. On error, returns `tarpc::Error`. pub fn deserialize(mut buf: &[u8]) -> Result { bincode::deserialize_from(&mut buf, SizeLimit::Infinite) } pub struct TarpcTransport { stream: T, read_state: reader::ReadState, outbound: VecDeque, head: Option, } impl TarpcTransport { pub fn new(stream: T) -> Self { TarpcTransport { stream: stream, read_state: reader::ReadState::init(), outbound: VecDeque::new(), head: None, } } } impl FramedIo for TarpcTransport where T: Io { type In = Frame; type Out = Frame, Never, io::Error>; fn poll_read(&mut self) -> Async<()> { self.stream.poll_read() } fn poll_write(&mut self) -> Async<()> { self.stream.poll_write() } fn read(&mut self) -> io::Result, Never, io::Error>>> { self.read_state.next(&mut self.stream) } fn write(&mut self, req: Self::In) -> io::Result> { self.outbound.push_back(req.unwrap_msg()); self.flush() } fn flush(&mut self) -> io::Result> { writer::NextWriteState::next(&mut self.head, &mut self.stream, &mut self.outbound) } }