<commit_before>use std::sync::Arc;
use std::thread;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::io;
use std::iter;
use std::sync::mpsc;
use std::panic::catch_unwind;
use std::panic::AssertUnwindSafe;

use solicit::http::server::StreamFactory;
use solicit::http::server::ServerSession;
use solicit::http::session::Server;
use solicit::http::session::DefaultSessionState;
use solicit::http::session::DefaultStream;
use solicit::http::session::StreamState;
use solicit::http::session::StreamDataChunk;
use solicit::http::session::StreamDataError;
use solicit::http::session::Stream as solicit_Stream;
use solicit::http::connection::HttpConnection;
use solicit::http::connection::EndStream;
use solicit::http::connection::DataChunk;
use solicit::http::HttpScheme;
use solicit::http::StreamId;
use solicit::http::Header;
use solicit::http::session::SessionState;

use futures;
use futures::Future;
use futures::stream;
use futures::stream::Stream;
use tokio_core::io as tokio_io;
use tokio_core::io::IoFuture;
use tokio_core::io::TaskIo;
use tokio_core::io::TaskIoRead;
use tokio_core::io::TaskIoWrite;
use tokio_core;
use tokio_core::Loop;
use tokio_core::LoopHandle;
use tokio_core::TcpStream;
use tokio_core::Sender;
use tokio_core::Receiver;

use method::*;
use error::*;
use result::*;
use futures_grpc::*;
use futures_misc::*;
use solicit_async::*;
use solicit_misc::*;
use grpc::*;

pub trait MethodHandler<Req, Resp> {
    fn handle(&self, req: Req) -> GrpcStream<Resp>;
}

pub struct MethodHandlerFn<F> {
    f: F
}

impl<F> MethodHandlerFn<F> {
    pub fn new<Req, Resp>(f: F)
        -> Self
        where F : Fn(Req) -> GrpcFuture<Resp>
    {
        MethodHandlerFn {
            f: f,
        }
    }
}

impl<Req, Resp, F> MethodHandler<Req, Resp> for MethodHandlerFn<F>
    where
        Resp : Send + 'static,
        F : Fn(Req) -> GrpcFuture<Resp>,
{
    fn handle(&self, req: Req) -> GrpcStream<Resp> {
        future_to_stream((self.f)(req))
            .boxed()
    }
}

trait MethodHandlerDispatch {
    fn on_message(&self, message: &[u8]) -> GrpcStream<Vec<u8>>;
}

struct MethodHandlerDispatchAsyncImpl<Req, Resp> {
    desc: Arc<MethodDescriptor<Req, Resp>>,
    method_handler: Box<MethodHandler<Req, Resp> + Sync + Send>,
}

impl<Req, Resp> MethodHandlerDispatch for MethodHandlerDispatchAsyncImpl<Req, Resp>
    where
        Req : Send + 'static,
        Resp : Send + 'static,
{
    fn on_message(&self, message: &[u8]) -> GrpcStream<Vec<u8>> {
        let req = match self.desc.req_marshaller.read(message) {
            Ok(req) => req,
            Err(e) => return future_to_stream(futures::done(Err(e))).boxed(),
        };
        let resp =
            catch_unwind(AssertUnwindSafe(|| self.method_handler.handle(req)));
        match resp {
            Ok(resp) => {
                let desc_copy = self.desc.clone();
                resp
                    .and_then(move |resp| desc_copy.resp_marshaller.write(&resp))
                    .boxed()
            }
            Err(..) => future_to_stream(futures::done(Err(GrpcError::Other("panic in handler"))))
                .boxed(),
        }
    }
}

pub struct ServerMethod {
    name: String,
    dispatch: Box<MethodHandlerDispatch + Sync + Send>,
}

impl ServerMethod {
    pub fn new<Req, Resp, H>(method: Arc<MethodDescriptor<Req, Resp>>, handler: H) -> ServerMethod
        where
            Req : Send + 'static,
            Resp : Send + 'static,
            H : MethodHandler<Req, Resp> + 'static + Sync + Send,
    {
        ServerMethod {
            name: method.name.clone(),
            dispatch: Box::new(MethodHandlerDispatchAsyncImpl {
                desc: method,
                method_handler: Box::new(handler),
            }),
        }
    }
}

pub struct ServerServiceDefinition {
    methods: Vec<ServerMethod>,
}

impl ServerServiceDefinition {
    pub fn new(methods: Vec<ServerMethod>) -> ServerServiceDefinition {
        ServerServiceDefinition {
            methods: methods,
        }
    }

    pub fn find_method(&self, name: &str) -> &ServerMethod {
        self.methods.iter()
            .filter(|m| m.name == name)
            .next()
            .expect(&format!("unknown method: {}", name))
    }

    pub fn handle_method(&self, name: &str, message: &[u8]) -> GrpcStream<Vec<u8>> {
        self.find_method(name).dispatch.on_message(message)
    }
}

struct LoopToServer {
    // used only once to send shutdown signal
    shutdown_tx: tokio_core::Sender<()>,
    local_addr: SocketAddr,
}

pub struct GrpcServer {
    loop_to_server: LoopToServer,
    thread_join_handle: Option<thread::JoinHandle<()>>,
}

impl GrpcServer {
    pub fn new(port: u16, service_definition: ServerServiceDefinition) -> GrpcServer {
        let listen_addr = ("::", port).to_socket_addrs().unwrap().next().unwrap();

        let (get_from_loop_tx, get_from_loop_rx) = mpsc::channel();

        let join_handle = thread::spawn(move || {
            run_server_event_loop(listen_addr, service_definition, get_from_loop_tx);
        });

        let loop_to_server = get_from_loop_rx.recv().unwrap();

        GrpcServer {
            loop_to_server: loop_to_server,
            thread_join_handle: Some(join_handle),
        }
    }

    pub fn local_addr(&self) -> &SocketAddr {
        &self.loop_to_server.local_addr
    }
}

// We shutdown client in destructor.
impl Drop for GrpcServer {
    fn drop(&mut self) {
        // ignore error because even loop may be already dead
        self.loop_to_server.shutdown_tx.send(()).ok();

        // do not ignore errors because we own event loop thread
        self.thread_join_handle.take().unwrap().join().unwrap();
    }
}

struct GrpcHttp2ServerStream {
    stream: DefaultStream,
    service_definition: Arc<ServerServiceDefinition>,
    path: String,
    sender: Sender<ReadToWriteMessage>,
}

impl solicit_Stream for GrpcHttp2ServerStream {
    fn set_headers(&mut self, headers: Vec<Header>) {
        for h in &headers {
            if h.name() == b":path" {
                self.path = String::from_utf8(h.value().to_owned()).unwrap();
            }
        }

        self.stream.set_headers(headers)
    }

    fn new_data_chunk(&mut self, data: &[u8]) {
        self.stream.new_data_chunk(data)
    }

    fn set_state(&mut self, state: StreamState) {
        println!("set state {:?}", state);
        if state == StreamState::HalfClosedRemote {
            let stream_id = self.stream.stream_id.unwrap();

            let message = parse_grpc_frame_completely(&self.stream.body).unwrap();

            let sender = self.sender.clone();
            self.service_definition.handle_method(&self.path, message)
                .fold(sender.clone(), move |sender, result| {
                    sender.send(ReadToWriteMessage {
                        stream_id: stream_id,
                        content: Ok(result),
                    }).unwrap();
                    futures::done::<_, GrpcError>(Ok(sender))
                })
                .then(move |result| {
                    // TODO: send EOF flag
                    if let Err(e) = result {
                        sender.send(ReadToWriteMessage {
                            stream_id: stream_id,
                            content: Err(e),
                        }).unwrap();
                    }

                    futures::done::<_, GrpcError>(Ok(()))
                })
                .forget();
        }
        self.stream.set_state(state)
    }

    fn get_data_chunk(&mut self, buf: &mut [u8]) -> Result<StreamDataChunk, StreamDataError> {
        self.stream.get_data_chunk(buf)
    }

    fn state(&self) -> StreamState {
        self.stream.state()
    }
}

struct GrpcStreamFactory {
    service_definition: Arc<ServerServiceDefinition>,
    sender: Sender<ReadToWriteMessage>,
}

impl StreamFactory for GrpcStreamFactory {
	type Stream = GrpcHttp2ServerStream;

	fn create(&mut self, stream_id: StreamId) -> GrpcHttp2ServerStream {
        println!("new stream {}", stream_id);
        GrpcHttp2ServerStream {
            stream: DefaultStream::with_id(stream_id),
            service_definition: self.service_definition.clone(),
            path: String::new(),
            sender: self.sender.clone(),
        }
	}
}

struct ServerSharedState {
    conn: HttpConnection,
    factory: GrpcStreamFactory,
    state: DefaultSessionState<Server, GrpcHttp2ServerStream>,
}

struct ReadToWriteMessage {
    stream_id: StreamId,
    content: GrpcResult<Vec<u8>>,
}

fn run_read(
    read: TaskIoRead<TcpStream>,
    shared: TaskDataMutex<ServerSharedState>)
        -> GrpcFuture<()>
{
    let stream = stream::iter(iter::repeat(()).map(|x| Ok(x)));

    let future = stream.fold((read, shared), |(read, shared), _| {
        recv_raw_frame(read)
            .map(|(read, raw_frame)| {
                println!("received frame");

                shared.with(|shared: &mut ServerSharedState| {

                    let mut send_buf = VecSendFrame(Vec::new());

                    let mut session = ServerSession::new(&mut shared.state, &mut shared.factory, &mut send_buf);
                    shared.conn.handle_next_frame(
                        &mut OnceReceiveFrame::new(raw_frame),
                        &mut session).unwrap();

                    // TODO: process send
                });
                (read, shared)
            })
    });

    future
        .map(|_| ())
        .boxed()
}

fn run_write(
    write: TaskIoWrite<TcpStream>,
    shared: TaskDataMutex<ServerSharedState>,
    receiver: Receiver<ReadToWriteMessage>)
        -> GrpcFuture<()>
{
    println!("run_write");
    let future = receiver.fold((write, shared), |(write, shared), message: ReadToWriteMessage| {
        println!("writer got message from reader");

        let send_buf = shared.with(move |shared: &mut ServerSharedState| {
            let mut send_buf = VecSendFrame(Vec::new());

            match message.content {
                Ok(resp_bytes) => {
                    // TODO: might be not the first message
                    shared.conn.sender(&mut send_buf).send_headers(
                        vec![
                            Header::new(b":status", b"200"),
                            Header::new(&b"content-type"[..], &b"application/grpc"[..]),
                        ],
                        message.stream_id,
                        EndStream::No).unwrap();

                    let mut body = Vec::new();
                    write_grpc_frame(&mut body, &resp_bytes);

                    shared.conn.sender(&mut send_buf).send_data(
                        DataChunk::new_borrowed(&body[..], message.stream_id, EndStream::No)).unwrap();

                    shared.conn.sender(&mut send_buf).send_headers(
                        vec![
                            Header::new(HEADER_GRPC_STATUS.as_bytes(), b"0"),
                        ],
                        message.stream_id,
                        EndStream::Yes)
                            .unwrap();

                    shared.state.remove_stream(message.stream_id).expect("unknown stream id");
                }
                Err(e) => {
                    shared.conn.sender(&mut send_buf).send_headers(
                        vec![
                            Header::new(&b":status"[..], &b"500"[..]),
                            Header::new(HEADER_GRPC_MESSAGE.as_bytes(), format!("{:?}", e).into_bytes()),
                        ],
                        message.stream_id,
                        EndStream::Yes).unwrap();
                }
            }

            send_buf.0
        });

        tokio_io::write_all(write, send_buf)
            .map(|(write, _)| (write, shared))
    });

    future
        .map(|_| ())
        .map_err(GrpcError::from)
        .boxed()
}

fn run_connection(
    socket: TcpStream,
    peer_addr: SocketAddr,
    service_defintion: Arc<ServerServiceDefinition>,
    loop_handle: LoopHandle)
    -> IoFuture<()>
{
    println!("accepted connection from {}", peer_addr);
    let handshake = server_handshake(socket).map_err(GrpcError::from);

    let loop_handle_for_channel = loop_handle.clone();
    let three = handshake.and_then(|conn| {
        let (sender, receiver_future) = loop_handle_for_channel.channel();
        receiver_future
            .map(|receiver| {
                (conn, sender, receiver)
            })
            .map_err(GrpcError::from)
    });

    let run = three.and_then(|(conn, sender, receiver_stream)| {
        let (read, write) = TaskIo::new(conn).split();

        let shared_for_read = TaskDataMutex::new(ServerSharedState {
            conn: HttpConnection::new(HttpScheme::Http),
            state: DefaultSessionState::<Server, _>::new(),
            factory: GrpcStreamFactory {
                service_definition: service_defintion,
                sender: sender,
            },
        });
        let shared_for_write = shared_for_read.clone();

        run_read(read, shared_for_read)
            .join(run_write(write, shared_for_write, receiver_stream))
    });

    let bye = run
        .then(move |x| {
            println!("closing connection from {}: {:?}", peer_addr, x);
            x
        });

    bye
        .map(|_| ())
        .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
        .boxed()
}

fn run_server_event_loop(
    listen_addr: SocketAddr,
    service_definition: ServerServiceDefinition,
    send_to_back: mpsc::Sender<LoopToServer>)
{
    let mut lp = Loop::new().expect("loop new");

    let (shutdown_tx, shutdown_rx) = lp.handle().channel();

    let shutdown_rx = shutdown_rx.map_err(GrpcError::from);

    let listen = lp.handle().tcp_listen(&listen_addr);

    let stuff = stream_repeat((Arc::new(service_definition), lp.handle()));

    let loop_run = listen.and_then(|socket| {
        let local_addr = socket.local_addr().unwrap();
        send_to_back
            .send(LoopToServer { shutdown_tx: shutdown_tx, local_addr: local_addr })
            .expect("send back");

        socket.incoming().zip(stuff).for_each(|((socket, peer_addr), (service_definition, loop_handle))| {
            run_connection(socket, peer_addr, service_definition, loop_handle).forget();
            Ok(())
        })
    }).map_err(GrpcError::from);

    let shutdown = shutdown_rx.and_then(|shutdown_rx| {
        shutdown_rx.into_future()
            .map_err(|_| GrpcError::Other("error in shutdown channel"))
            .and_then(|_| {
                // Must complete with error,
                // so `join` with this future cancels another future.
                let result: Result<(), _> = Err(GrpcError::Other("shutdown"));
                result
            })
    });

    // Wait for either completion of connection (i. e. error)
    // or shutdown signal.
    let done = loop_run.join(shutdown);

    // TODO: do not ignore error
    lp.run(done).ok();
}
<commit_msg>working on streaming<commit_after>use std::sync::Arc;
use std::thread;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::io;
use std::iter;
use std::sync::mpsc;
use std::panic::catch_unwind;
use std::panic::AssertUnwindSafe;

use solicit::http::server::StreamFactory;
use solicit::http::server::ServerSession;
use solicit::http::session::Server;
use solicit::http::session::DefaultSessionState;
use solicit::http::session::DefaultStream;
use solicit::http::session::StreamState;
use solicit::http::session::StreamDataChunk;
use solicit::http::session::StreamDataError;
use solicit::http::session::Stream as solicit_Stream;
use solicit::http::connection::HttpConnection;
use solicit::http::connection::EndStream;
use solicit::http::connection::DataChunk;
use solicit::http::HttpScheme;
use solicit::http::StreamId;
use solicit::http::Header;
use solicit::http::session::SessionState;

use futures;
use futures::Future;
use futures::stream;
use futures::stream::Stream;
use tokio_core::io as tokio_io;
use tokio_core::io::IoFuture;
use tokio_core::io::TaskIo;
use tokio_core::io::TaskIoRead;
use tokio_core::io::TaskIoWrite;
use tokio_core;
use tokio_core::Loop;
use tokio_core::LoopHandle;
use tokio_core::TcpStream;
use tokio_core::Sender;
use tokio_core::Receiver;

use method::*;
use error::*;
use futures_grpc::*;
use futures_misc::*;
use solicit_async::*;
use solicit_misc::*;
use grpc::*;

pub trait MethodHandler<Req, Resp> {
    fn handle(&self, req: Req) -> GrpcStream<Resp>;
}

pub struct MethodHandlerFn<F> {
    f: F
}

impl<F> MethodHandlerFn<F> {
    pub fn new<Req, Resp>(f: F)
        -> Self
        where F : Fn(Req) -> GrpcFuture<Resp>
    {
        MethodHandlerFn {
            f: f,
        }
    }
}

impl<Req, Resp, F> MethodHandler<Req, Resp> for MethodHandlerFn<F>
    where
        Resp : Send + 'static,
        F : Fn(Req) -> GrpcFuture<Resp>,
{
    fn handle(&self, req: Req) -> GrpcStream<Resp> {
        future_to_stream((self.f)(req))
            .boxed()
    }
}

trait MethodHandlerDispatch {
    fn on_message(&self, message: &[u8]) -> GrpcStream<Vec<u8>>;
}

struct MethodHandlerDispatchAsyncImpl<Req, Resp> {
    desc: Arc<MethodDescriptor<Req, Resp>>,
    method_handler: Box<MethodHandler<Req, Resp> + Sync + Send>,
}

impl<Req, Resp> MethodHandlerDispatch for MethodHandlerDispatchAsyncImpl<Req, Resp>
    where
        Req : Send + 'static,
        Resp : Send + 'static,
{
    fn on_message(&self, message: &[u8]) -> GrpcStream<Vec<u8>> {
        let req = match self.desc.req_marshaller.read(message) {
            Ok(req) => req,
            Err(e) => return future_to_stream(futures::done(Err(e))).boxed(),
        };
        let resp =
            catch_unwind(AssertUnwindSafe(|| self.method_handler.handle(req)));
        match resp {
            Ok(resp) => {
                let desc_copy = self.desc.clone();
                resp
                    .and_then(move |resp| desc_copy.resp_marshaller.write(&resp))
                    .boxed()
            }
            Err(..) => future_to_stream(futures::done(Err(GrpcError::Other("panic in handler"))))
                .boxed(),
        }
    }
}

pub struct ServerMethod {
    name: String,
    dispatch: Box<MethodHandlerDispatch + Sync + Send>,
}

impl ServerMethod {
    pub fn new<Req, Resp, H>(method: Arc<MethodDescriptor<Req, Resp>>, handler: H) -> ServerMethod
        where
            Req : Send + 'static,
            Resp : Send + 'static,
            H : MethodHandler<Req, Resp> + 'static + Sync + Send,
    {
        ServerMethod {
            name: method.name.clone(),
            dispatch: Box::new(MethodHandlerDispatchAsyncImpl {
                desc: method,
                method_handler: Box::new(handler),
            }),
        }
    }
}

pub struct ServerServiceDefinition {
    methods: Vec<ServerMethod>,
}

impl ServerServiceDefinition {
    pub fn new(methods: Vec<ServerMethod>) -> ServerServiceDefinition {
        ServerServiceDefinition {
            methods: methods,
        }
    }

    pub fn find_method(&self, name: &str) -> &ServerMethod {
        self.methods.iter()
            .filter(|m| m.name == name)
            .next()
            .expect(&format!("unknown method: {}", name))
    }

    pub fn handle_method(&self, name: &str, message: &[u8]) -> GrpcStream<Vec<u8>> {
        self.find_method(name).dispatch.on_message(message)
    }
}

struct LoopToServer {
    // used only once to send shutdown signal
    shutdown_tx: tokio_core::Sender<()>,
    local_addr: SocketAddr,
}

pub struct GrpcServer {
    loop_to_server: LoopToServer,
    thread_join_handle: Option<thread::JoinHandle<()>>,
}

impl GrpcServer {
    pub fn new(port: u16, service_definition: ServerServiceDefinition) -> GrpcServer {
        let listen_addr = ("::", port).to_socket_addrs().unwrap().next().unwrap();

        let (get_from_loop_tx, get_from_loop_rx) = mpsc::channel();

        let join_handle = thread::spawn(move || {
            run_server_event_loop(listen_addr, service_definition, get_from_loop_tx);
        });

        let loop_to_server = get_from_loop_rx.recv().unwrap();

        GrpcServer {
            loop_to_server: loop_to_server,
            thread_join_handle: Some(join_handle),
        }
    }

    pub fn local_addr(&self) -> &SocketAddr {
        &self.loop_to_server.local_addr
    }
}

// We shutdown client in destructor.
impl Drop for GrpcServer {
    fn drop(&mut self) {
        // ignore error because even loop may be already dead
        self.loop_to_server.shutdown_tx.send(()).ok();

        // do not ignore errors because we own event loop thread
        self.thread_join_handle.take().unwrap().join().unwrap();
    }
}

struct GrpcHttp2ServerStream {
    stream: DefaultStream,
    service_definition: Arc<ServerServiceDefinition>,
    path: String,
    sender: Sender<ReadToWriteMessage>,
}

impl solicit_Stream for GrpcHttp2ServerStream {
    fn set_headers(&mut self, headers: Vec<Header>) {
        for h in &headers {
            if h.name() == b":path" {
                self.path = String::from_utf8(h.value().to_owned()).unwrap();
            }
        }

        self.stream.set_headers(headers)
    }

    fn new_data_chunk(&mut self, data: &[u8]) {
        self.stream.new_data_chunk(data)
    }

    fn set_state(&mut self, state: StreamState) {
        println!("set state {:?}", state);
        if state == StreamState::HalfClosedRemote {
            let stream_id = self.stream.stream_id.unwrap();

            let message = parse_grpc_frame_completely(&self.stream.body).unwrap();

            let sender = self.sender.clone();
            self.service_definition.handle_method(&self.path, message)
                .fold((sender.clone(), 0), move |(sender, i), resp| {
                    sender.send(ReadToWriteMessage {
                        stream_id: stream_id,
                        content: ResponseChunk::Resp(resp, i == 0),
                    }).unwrap();
                    futures::done::<_, GrpcError>(Ok((sender, i + 1)))
                })
                .then(move |result| {
                    sender.send(ReadToWriteMessage {
                        stream_id: stream_id,
                        content: match result {
                            Ok(..) => ResponseChunk::DoneSuccess,
                            Err(e) => ResponseChunk::Error(e),
                        }
                    }).expect("send to write");

                    futures::done::<_, GrpcError>(Ok(()))
                })
                .forget();
        }
        self.stream.set_state(state)
    }

    fn get_data_chunk(&mut self, buf: &mut [u8]) -> Result<StreamDataChunk, StreamDataError> {
        self.stream.get_data_chunk(buf)
    }

    fn state(&self) -> StreamState {
        self.stream.state()
    }
}

struct GrpcStreamFactory {
    service_definition: Arc<ServerServiceDefinition>,
    sender: Sender<ReadToWriteMessage>,
}

impl StreamFactory for GrpcStreamFactory {
	type Stream = GrpcHttp2ServerStream;

	fn create(&mut self, stream_id: StreamId) -> GrpcHttp2ServerStream {
        println!("new stream {}", stream_id);
        GrpcHttp2ServerStream {
            stream: DefaultStream::with_id(stream_id),
            service_definition: self.service_definition.clone(),
            path: String::new(),
            sender: self.sender.clone(),
        }
	}
}

struct ServerSharedState {
    conn: HttpConnection,
    factory: GrpcStreamFactory,
    state: DefaultSessionState<Server, GrpcHttp2ServerStream>,
}

enum ResponseChunk {
    Resp(/* resp */ Vec<u8>, /* first */ bool),
    DoneSuccess,
    Error(GrpcError),
}

struct ReadToWriteMessage {
    stream_id: StreamId,
    content: ResponseChunk,
}

fn run_read(
    read: TaskIoRead<TcpStream>,
    shared: TaskDataMutex<ServerSharedState>)
        -> GrpcFuture<()>
{
    let stream = stream::iter(iter::repeat(()).map(|x| Ok(x)));

    let future = stream.fold((read, shared), |(read, shared), _| {
        recv_raw_frame(read)
            .map(|(read, raw_frame)| {
                println!("received frame");

                shared.with(|shared: &mut ServerSharedState| {

                    let mut send_buf = VecSendFrame(Vec::new());

                    let mut session = ServerSession::new(&mut shared.state, &mut shared.factory, &mut send_buf);
                    shared.conn.handle_next_frame(
                        &mut OnceReceiveFrame::new(raw_frame),
                        &mut session).unwrap();

                    // TODO: process send
                });
                (read, shared)
            })
    });

    future
        .map(|_| ())
        .boxed()
}

fn run_write(
    write: TaskIoWrite<TcpStream>,
    shared: TaskDataMutex<ServerSharedState>,
    receiver: Receiver<ReadToWriteMessage>)
        -> GrpcFuture<()>
{
    println!("run_write");
    let future = receiver.fold((write, shared), |(write, shared), message: ReadToWriteMessage| {
        println!("writer got message from reader");

        let send_buf = shared.with(move |shared: &mut ServerSharedState| {
            let mut send_buf = VecSendFrame(Vec::new());

            match message.content {
                ResponseChunk::Resp(resp_bytes, first) => {
                    if first {
                        shared.conn.sender(&mut send_buf).send_headers(
                            vec![
                            Header::new(b":status", b"200"),
                            Header::new(&b"content-type"[..], &b"application/grpc"[..]),
                        ],
                            message.stream_id,
                            EndStream::No).unwrap();
                    }

                    let mut body = Vec::new();
                    write_grpc_frame(&mut body, &resp_bytes);

                    shared.conn.sender(&mut send_buf).send_data(
                        DataChunk::new_borrowed(&body[..], message.stream_id, EndStream::No)).unwrap();
                }
                ResponseChunk::DoneSuccess => {
                    shared.conn.sender(&mut send_buf).send_headers(
                        vec![
                            Header::new(HEADER_GRPC_STATUS.as_bytes(), b"0"),
                        ],
                        message.stream_id,
                        EndStream::Yes)
                            .unwrap();
                }
                ResponseChunk::Error(e) => {
                    shared.conn.sender(&mut send_buf).send_headers(
                        vec![
                            Header::new(&b":status"[..], &b"500"[..]),
                            Header::new(HEADER_GRPC_MESSAGE.as_bytes(), format!("{:?}", e).into_bytes()),
                        ],
                        message.stream_id,
                        EndStream::Yes).unwrap();

                    shared.state.remove_stream(message.stream_id).expect("unknown stream id");
                }
            }

            send_buf.0
        });

        tokio_io::write_all(write, send_buf)
            .map(|(write, _)| (write, shared))
    });

    future
        .map(|_| ())
        .map_err(GrpcError::from)
        .boxed()
}

fn run_connection(
    socket: TcpStream,
    peer_addr: SocketAddr,
    service_defintion: Arc<ServerServiceDefinition>,
    loop_handle: LoopHandle)
    -> IoFuture<()>
{
    println!("accepted connection from {}", peer_addr);
    let handshake = server_handshake(socket).map_err(GrpcError::from);

    let loop_handle_for_channel = loop_handle.clone();
    let three = handshake.and_then(|conn| {
        let (sender, receiver_future) = loop_handle_for_channel.channel();
        receiver_future
            .map(|receiver| {
                (conn, sender, receiver)
            })
            .map_err(GrpcError::from)
    });

    let run = three.and_then(|(conn, sender, receiver_stream)| {
        let (read, write) = TaskIo::new(conn).split();

        let shared_for_read = TaskDataMutex::new(ServerSharedState {
            conn: HttpConnection::new(HttpScheme::Http),
            state: DefaultSessionState::<Server, _>::new(),
            factory: GrpcStreamFactory {
                service_definition: service_defintion,
                sender: sender,
            },
        });
        let shared_for_write = shared_for_read.clone();

        run_read(read, shared_for_read)
            .join(run_write(write, shared_for_write, receiver_stream))
    });

    let bye = run
        .then(move |x| {
            println!("closing connection from {}: {:?}", peer_addr, x);
            x
        });

    bye
        .map(|_| ())
        .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
        .boxed()
}

fn run_server_event_loop(
    listen_addr: SocketAddr,
    service_definition: ServerServiceDefinition,
    send_to_back: mpsc::Sender<LoopToServer>)
{
    let mut lp = Loop::new().expect("loop new");

    let (shutdown_tx, shutdown_rx) = lp.handle().channel();

    let shutdown_rx = shutdown_rx.map_err(GrpcError::from);

    let listen = lp.handle().tcp_listen(&listen_addr);

    let stuff = stream_repeat((Arc::new(service_definition), lp.handle()));

    let loop_run = listen.and_then(|socket| {
        let local_addr = socket.local_addr().unwrap();
        send_to_back
            .send(LoopToServer { shutdown_tx: shutdown_tx, local_addr: local_addr })
            .expect("send back");

        socket.incoming().zip(stuff).for_each(|((socket, peer_addr), (service_definition, loop_handle))| {
            run_connection(socket, peer_addr, service_definition, loop_handle).forget();
            Ok(())
        })
    }).map_err(GrpcError::from);

    let shutdown = shutdown_rx.and_then(|shutdown_rx| {
        shutdown_rx.into_future()
            .map_err(|_| GrpcError::Other("error in shutdown channel"))
            .and_then(|_| {
                // Must complete with error,
                // so `join` with this future cancels another future.
                let result: Result<(), _> = Err(GrpcError::Other("shutdown"));
                result
            })
    });

    // Wait for either completion of connection (i. e. error)
    // or shutdown signal.
    let done = loop_run.join(shutdown);

    // TODO: do not ignore error
    lp.run(done).ok();
}
<|endoftext|>


<commit_before>use std::thread;
use std::collections::HashSet;
use std::net::SocketAddr;
use std::error::FromError;

// MIO
use mio::tcp::{listen, TcpListener, TcpStream};
use mio::util::Slab;
use mio::Socket;
use mio::buf::{RingBuf};
use mio::{Interest, PollOpt, NonBlock, Token, EventLoop, Handler, ReadHint};
use mio::buf::Buf;
use mio::{TryRead, TryWrite};

use rand::{self, Rng};

// Data structures.
use store::Store;
use replica::{Replica, Emit, Broadcast};
use state_machine::StateMachine;

// Cap'n Proto
use capnp::serialize_packed;
use capnp::{
    MessageBuilder,
    MessageReader,
    ReaderOptions,
    MallocMessageBuilder,
    OwnedSpaceMessageReader,
};
use messages_capnp::{
    rpc_request,
    rpc_response,
    client_request,
    client_response,
    request_vote_response,
    append_entries_response,
    append_entries_request,
};
use super::{Error, Result};

// MIO Tokens
const ELECTION_TIMEOUT: Token = Token(0);
const HEARTBEAT_TIMEOUT: Token = Token(1);
const LISTENER:  Token = Token(2);

const ELECTION_MIN: u64 = 150;
const ELECTION_MAX: u64 = 300;
const HEARTBEAT_DURATION: u64 = 50;

/// The Raft Distributed Consensus Algorithm requires two RPC calls to be available:
///
///   * `append_entries` which is used as both a heartbeat (with no payload) and the primary
///     interface for requests.
///   * `request_vote` which is used by candidates during campaigns to obtain a vote.
///
/// A `Server` acts as a replicated state machine. The server's role in the cluster depends on it's
/// own status. It will maintain both volatile state (which can be safely lost) and persistent
/// state (which must be carefully stored and kept safe).
///
/// Currently, the `Server` API is not well defined. **We are looking for feedback and suggestions.**
pub struct Server<S, M> where S: Store, M: StateMachine {
    replica: Replica<S, M>,
    // Channels and Sockets
    listener: NonBlock<TcpListener>,
    connections: Slab<Connection>,
}

/// The implementation of the Server. In most use cases, creating a `Server` should just be
/// done via `::new()`.
impl<S, M> Server<S, M> where S: Store, M: StateMachine {

    /// Creates a new Raft node with the cluster members specified.
    ///
    /// # Arguments
    ///
    /// * `addr` - The address of the new node.
    /// * `peers` - The address of all peers in the Raft cluster.
    /// * `store` - The persitent log store.
    /// * `state_machine` - The client state machine to which client commands will be applied.
    pub fn spawn(addr: SocketAddr,
                 peers: HashSet<SocketAddr>,
                 store: S,
                 state_machine: M) {
        // Create an event loop
        let mut event_loop = EventLoop::<Server<S, M>>::new().unwrap();
        // Setup the socket, make it not block.
        let listener = listen(&addr).unwrap();
        listener.set_reuseaddr(true).unwrap();
        event_loop.register(&listener, LISTENER).unwrap();
        let timeout = rand::thread_rng().gen_range::<u64>(ELECTION_MIN, ELECTION_MAX);
        event_loop.timeout_ms(ELECTION_TIMEOUT, timeout).unwrap();
        event_loop.timeout_ms(HEARTBEAT_TIMEOUT, HEARTBEAT_DURATION).unwrap();
        let replica = Replica::new(addr, peers, store, state_machine);
        // Fire up the thread.
        thread::Builder::new().name(format!("Server {}", addr)).spawn(move || {
            let mut raft_node = Server {
                listener: listener,
                replica: replica,
                connections: Slab::new_starting_at(Token(2), 128),
            };
            event_loop.run(&mut raft_node).unwrap();
        }).unwrap();
    }

    fn broadcast(&mut self, builder: MallocMessageBuilder) {
        unimplemented!();
    }
}

impl<S, M> Handler for Server<S, M> where S: Store, M: StateMachine {

    type Message = ();
    type Timeout = Token;

    /// A registered IoHandle has available writing space.
    fn writable(&mut self, reactor: &mut EventLoop<Server<S, M>>, token: Token) {
        match token {
            ELECTION_TIMEOUT => unreachable!(),
            HEARTBEAT_TIMEOUT => unreachable!(),
            LISTENER => unreachable!(),
            tok => {
                self.connections[tok].writable(reactor, &mut self.replica).unwrap();
            }
        }
    }

    /// A registered IoHandle has available data to read
    fn readable(&mut self, reactor: &mut EventLoop<Server<S, M>>, token: Token, _hint: ReadHint) {
        match token {
            ELECTION_TIMEOUT => unreachable!(),
            HEARTBEAT_TIMEOUT => unreachable!(),
            LISTENER => {
                let stream = match self.listener.accept().unwrap() {
                    Some(s) => s,
                    None => return, // Socket isn't quite ready.
                }; // Result<Option<_>,_>
                let conn = Connection::new(stream);
                let tok = self.connections.insert(conn)
                    .ok().expect("Could not add connection to slab.");

                // Register the connection
                self.connections[tok].token = tok;
                reactor.register_opt(&self.connections[tok].stream, tok, Interest::readable(), PollOpt::edge() | PollOpt::oneshot())
                    .ok().expect("Could not register socket with event loop.");
            },
            tok => {
                self.connections[tok].readable(reactor, &mut self.replica).unwrap();
            }
        }
    }

    /// A registered timer has expired
    fn timeout(&mut self, reactor: &mut EventLoop<Server<S, M>>, token: Token) {
        let mut message = MallocMessageBuilder::new_default();
        let mut send_message = None;
        match token {
            ELECTION_TIMEOUT => {
                let request = message.init_root::<rpc_request::Builder>();
                send_message = self.replica.election_timeout(request.init_request_vote());
                // Set timeout.
                let timeout = rand::thread_rng().gen_range::<u64>(ELECTION_MIN, ELECTION_MAX);
                reactor.timeout_ms(ELECTION_TIMEOUT, timeout).unwrap();

            },
            HEARTBEAT_TIMEOUT => {
                let request = message.init_root::<rpc_request::Builder>();
                send_message = self.replica.heartbeat_timeout(request.init_append_entries());
                // Set Timeout
                reactor.timeout_ms(HEARTBEAT_TIMEOUT, HEARTBEAT_DURATION).unwrap();
            },
            _ => unreachable!(),
        }
        // Send if necessary.
        match send_message {
            Some(Broadcast) => self.broadcast(message),
            None => (),
        }
    }
}

struct Connection {
    stream: NonBlock<TcpStream>,
    token: Token,
    interest: Interest,
    current_read: RingBuf,
    current_write: RingBuf,
    next_write: Option<MallocMessageBuilder>,
}

impl Connection {
    fn new(sock: NonBlock<TcpStream>) -> Connection {
        Connection {
            stream: sock,
            token: Token(-1),
            interest: Interest::hup(),
            current_read: RingBuf::new(4096),
            current_write: RingBuf::new(4096),
            next_write: None,
        }
    }

    fn writable<S, M>(&mut self, event_loop: &mut EventLoop<Server<S, M>>, replica: &mut Replica<S,M>)
                      -> Result<()>
    where S: Store, M: StateMachine {
        // Attempt to write data.
        // The `current_write` buffer will be advanced based on how much we wrote.
        match self.stream.write(&mut self.current_write) {
            Ok(None) => {
                // This is a buffer flush. WOULDBLOCK
                self.interest.insert(Interest::writable());
            },
            Ok(Some(r)) => {
                // We managed to write data!
                // TODO: We're *probably* not ready to shoot data again?
                match (self.current_write.has_remaining(), self.next_write.is_some()) {
                    // Need to write more of what we have.
                    (true, _) => (),
                    // Need to roll over.
                    (false, true) => try!(
                        serialize_packed::write_packed_message_unbuffered(&mut self.current_write,
                                                                          self.next_write.as_mut().unwrap())
                    ),
                    // We're done writing for now.
                    (false, false) => self.interest.remove(Interest::writable()),

                }
            },
            Err(e) => return Err(Error::from_error(e)),
        }

        match event_loop.reregister(&self.stream, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot()) {
            Ok(()) => Ok(()),
            Err(e) => Err(Error::from_error(e)),
        }
    }

    fn readable<S, M>(&mut self, event_loop: &mut EventLoop<Server<S, M>>, replica: &mut Replica<S,M>)
                      -> Result<()>
    where S: Store, M: StateMachine {
        let mut read = 0;
        match self.stream.read(&mut self.current_read) {
            Ok(Some(r)) => {
                // Just read `r` bytes.
                read = r;
            },
            Ok(None) => panic!("We just got readable, but were unable to read from the socket?"),
            Err(e) => return Err(Error::from_error(e)),
        };
        if read > 0 {
            match serialize_packed::new_reader_unbuffered(&mut self.current_read, ReaderOptions::new()) {
                // We have something reasonably interesting in the buffer!
                Ok(reader) => {
                    self.handle_reader(reader, event_loop, replica);
                },
                // It's not read entirely yet.
                // Should roll back, pending changes to bytes upstream.
                Err(_) => unimplemented!(),
            }
        }
        match event_loop.reregister(&self.stream, self.token, self.interest, PollOpt::edge()) {
            Ok(()) => Ok(()),
            Err(e) => Err(Error::from_error(e)),
        }
    }

    fn handle_reader<S, M>(&mut self, reader: OwnedSpaceMessageReader,
                           event_loop: &mut EventLoop<Server<S, M>>, replica: &mut Replica<S,M>)
    where S: Store, M: StateMachine {
        let mut builder_message = MallocMessageBuilder::new_default();
        let from = self.stream.peer_addr().unwrap();
        if let Ok(request) = reader.get_root::<rpc_request::Reader>() {
            match request.which().unwrap() {
                // TODO: Move these into replica?
                rpc_request::Which::AppendEntries(Ok(call)) => {
                    let builder = builder_message.init_root::<append_entries_response::Builder>();
                    match replica.append_entries_request(from, call, builder) {
                        Some(Emit) => {
                            // Special Cirsumstance Detection
                            unimplemented!();
                        },
                        None => (),
                    }
                },
                rpc_request::Which::RequestVote(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<request_vote_response::Builder>();
                        replica.request_vote_request(from, call, builder)
                    };
                    match respond {
                        Some(Emit) => {
                            // TODO
                            self.emit(builder_message);
                        },
                        None            => (),
                    }
                },
                _ => unimplemented!(),
            };
        } else if let Ok(response) = reader.get_root::<rpc_response::Reader>() {
            // We won't be responding. This is already a response.
            match response.which().unwrap() {
                rpc_response::Which::AppendEntries(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<append_entries_request::Builder>();
                        replica.append_entries_response(from, call, builder)
                    };
                    match respond {
                        Some(Emit) => {
                            // TODO
                            self.emit(builder_message);
                        },
                        None => (),
                    }
                },
                rpc_response::Which::RequestVote(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<append_entries_request::Builder>();
                        replica.request_vote_response(from, call, builder)
                    };
                    match respond {
                        Some(Broadcast) => {
                            // Won an election!
                            self.broadcast(builder_message);
                        },
                        None => (),
                    }

                },
                _ => unimplemented!(),
            }
        } else if let Ok(client_req) = reader.get_root::<client_request::Reader>() {
            let mut should_die = false;
            // We will be responding.
            match client_req.which().unwrap() {
                client_request::Which::Append(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<client_response::Builder>();
                        replica.client_append(from, call, builder)
                    };
                    match respond {
                        Some(emit) => {
                            self.emit(builder_message);
                        },
                        None => (),
                    }

                },
                client_request::Which::Die(Ok(call)) => {
                    should_die = true;
                    let mut builder = builder_message.init_root::<client_response::Builder>();
                    builder.set_success(());
                    self.interest.insert(Interest::writable());
                    debug!("Got a Die request from Client({}). Reason: {}", from, call);
                },
                client_request::Which::LeaderRefresh(()) => {
                    let respond = {
                        let builder = builder_message.init_root::<client_response::Builder>();
                        replica.client_leader_refresh(from, builder)
                    };
                    match respond {
                        Some(Emit) => {
                            self.emit(builder_message);
                        },
                        None => (),
                    }
                },
                _ => unimplemented!(),
            };

            // Do this here so that we can send the response.
            if should_die {
                panic!("Got a Die request.");
            }

        } else {
            // It's something we don't understand.
            unimplemented!();
        }
    }

    fn broadcast(&mut self, builder: MallocMessageBuilder) {
        unimplemented!();
    }

    /// If applicable, push the new message into `self.next_write`.
    ///
    // Because messages are passed asyncronously between Server instances, a Server could
    // get into a situation where multiple events are ready to be dispatched to a single
    // remote Server. In this situation, the Server will replace the existing event with
    // the new event, except in one special circumstance: if the new and existing messages
    // are both AppendEntryRequests with the same term, then the new message will be
    // dropped.
    fn emit(&mut self, mut builder: MallocMessageBuilder) {
        let overwrite = match self.next_write {
            Some(ref mut next) => {
                let opt_incoming = builder.get_root::<append_entries_request::Builder>();
                let opt_next = next.get_root::<append_entries_request::Builder>();
                match (opt_incoming, opt_next) {
                    (Ok(incoming), Ok(next)) => {
                        if incoming.get_term() == next.get_term() {
                            false
                        } else {
                            true
                        }
                    },
                    _ => true,
                }
            },
            None => true,
        };
        if overwrite {
            self.next_write = Some(builder);
        }
    }
}
<commit_msg>Timeout impl.<commit_after>use std::thread;
use std::collections::HashSet;
use std::net::SocketAddr;
use std::error::FromError;
use std::collections::VecDeque;

// MIO
use mio::tcp::{listen, TcpListener, TcpStream};
use mio::util::Slab;
use mio::Socket;
use mio::buf::{RingBuf};
use mio::{Interest, PollOpt, NonBlock, Token, EventLoop, Handler, ReadHint};
use mio::buf::Buf;
use mio::{TryRead, TryWrite};

use rand::{self, Rng};

// Data structures.
use store::Store;
use replica::{Replica, Emit, Broadcast};
use state_machine::StateMachine;

// Cap'n Proto
use capnp::serialize_packed;
use capnp::{
    MessageBuilder,
    MessageReader,
    ReaderOptions,
    MallocMessageBuilder,
    OwnedSpaceMessageReader,
};
use messages_capnp::{
    rpc_request,
    rpc_response,
    client_request,
    client_response,
    request_vote_response,
    append_entries_response,
    append_entries_request,
};
use super::{Error, Result};

// MIO Tokens
const ELECTION_TIMEOUT: Token = Token(0);
const HEARTBEAT_TIMEOUT: Token = Token(1);
const LISTENER:  Token = Token(2);

const ELECTION_MIN: u64 = 150;
const ELECTION_MAX: u64 = 300;
const HEARTBEAT_DURATION: u64 = 50;
const RINGBUF_SIZE: usize = 4096;

/// The Raft Distributed Consensus Algorithm requires two RPC calls to be available:
///
///   * `append_entries` which is used as both a heartbeat (with no payload) and the primary
///     interface for requests.
///   * `request_vote` which is used by candidates during campaigns to obtain a vote.
///
/// A `Server` acts as a replicated state machine. The server's role in the cluster depends on it's
/// own status. It will maintain both volatile state (which can be safely lost) and persistent
/// state (which must be carefully stored and kept safe).
///
/// Currently, the `Server` API is not well defined. **We are looking for feedback and suggestions.**
pub struct Server<S, M> where S: Store, M: StateMachine {
    replica: Replica<S, M>,
    // Channels and Sockets
    listener: NonBlock<TcpListener>,
    connections: Slab<Connection>,
}

/// The implementation of the Server. In most use cases, creating a `Server` should just be
/// done via `::new()`.
impl<S, M> Server<S, M> where S: Store, M: StateMachine {

    /// Creates a new Raft node with the cluster members specified.
    ///
    /// # Arguments
    ///
    /// * `addr` - The address of the new node.
    /// * `peers` - The address of all peers in the Raft cluster.
    /// * `store` - The persitent log store.
    /// * `state_machine` - The client state machine to which client commands will be applied.
    pub fn spawn(addr: SocketAddr,
                 peers: HashSet<SocketAddr>,
                 store: S,
                 state_machine: M) {
        // Create an event loop
        let mut event_loop = EventLoop::<Server<S, M>>::new().unwrap();
        // Setup the socket, make it not block.
        let listener = listen(&addr).unwrap();
        listener.set_reuseaddr(true).unwrap();
        event_loop.register(&listener, LISTENER).unwrap();
        let timeout = rand::thread_rng().gen_range::<u64>(ELECTION_MIN, ELECTION_MAX);
        event_loop.timeout_ms(ELECTION_TIMEOUT, timeout).unwrap();
        event_loop.timeout_ms(HEARTBEAT_TIMEOUT, HEARTBEAT_DURATION).unwrap();
        let replica = Replica::new(addr, peers, store, state_machine);
        // Fire up the thread.
        thread::Builder::new().name(format!("Server {}", addr)).spawn(move || {
            let mut raft_node = Server {
                listener: listener,
                replica: replica,
                connections: Slab::new_starting_at(Token(2), 128),
            };
            event_loop.run(&mut raft_node).unwrap();
        }).unwrap();
    }
}

impl<S, M> Handler for Server<S, M> where S: Store, M: StateMachine {

    type Message = RingBuf;
    type Timeout = Token;

    /// A registered IoHandle has available writing space.
    fn writable(&mut self, reactor: &mut EventLoop<Server<S, M>>, token: Token) {
        match token {
            ELECTION_TIMEOUT => unreachable!(),
            HEARTBEAT_TIMEOUT => unreachable!(),
            LISTENER => unreachable!(),
            tok => {
                self.connections[tok].writable(reactor, &mut self.replica).unwrap();
            }
        }
    }

    /// A registered IoHandle has available data to read
    fn readable(&mut self, reactor: &mut EventLoop<Server<S, M>>, token: Token, _hint: ReadHint) {
        match token {
            ELECTION_TIMEOUT => unreachable!(),
            HEARTBEAT_TIMEOUT => unreachable!(),
            LISTENER => {
                let stream = match self.listener.accept().unwrap() {
                    Some(s) => s,
                    None => return, // Socket isn't quite ready.
                }; // Result<Option<_>,_>
                let conn = Connection::new(stream);
                let tok = self.connections.insert(conn)
                    .ok().expect("Could not add connection to slab.");

                // Register the connection
                self.connections[tok].token = tok;
                reactor.register_opt(&self.connections[tok].stream, tok, Interest::readable(), PollOpt::edge() | PollOpt::oneshot())
                    .ok().expect("Could not register socket with event loop.");
            },
            tok => {
                self.connections[tok].readable(reactor, &mut self.replica).unwrap();
            }
        }
    }

    /// A registered timer has expired
    fn timeout(&mut self, reactor: &mut EventLoop<Server<S, M>>, token: Token) {
        let mut message = MallocMessageBuilder::new_default();
        let mut send_message = None;
        match token {
            ELECTION_TIMEOUT => {
                let request = message.init_root::<rpc_request::Builder>();
                send_message = self.replica.election_timeout(request.init_request_vote());
                // Set timeout.
                let timeout = rand::thread_rng().gen_range::<u64>(ELECTION_MIN, ELECTION_MAX);
                reactor.timeout_ms(ELECTION_TIMEOUT, timeout).unwrap();

            },
            HEARTBEAT_TIMEOUT => {
                let request = message.init_root::<rpc_request::Builder>();
                send_message = self.replica.heartbeat_timeout(request.init_append_entries());
                // Set Timeout
                reactor.timeout_ms(HEARTBEAT_TIMEOUT, HEARTBEAT_DURATION).unwrap();
            },
            _ => unreachable!(),
        }
        // Send if necessary.
        match send_message {
            Some(Broadcast) => {
                let mut buf = RingBuf::new(RINGBUF_SIZE);
                serialize_packed::write_packed_message_unbuffered(
                    &mut buf,
                    &mut message
                ).unwrap();
                for connection in self.connections.iter_mut() {
                    connection.add_write(buf.clone());
                }
            },
            None => (),
        }
    }
}

struct Connection {
    stream: NonBlock<TcpStream>,
    token: Token,
    interest: Interest,
    current_read: RingBuf,
    current_write: RingBuf,
    next_write: VecDeque<RingBuf>,
}

impl Connection {
    fn new(sock: NonBlock<TcpStream>) -> Connection {
        Connection {
            stream: sock,
            token: Token(-1),
            interest: Interest::hup(),
            current_read: RingBuf::new(4096),
            current_write: RingBuf::new(4096),
            next_write: VecDeque::with_capacity(10),
        }
    }

    fn writable<S, M>(&mut self, event_loop: &mut EventLoop<Server<S, M>>, replica: &mut Replica<S,M>)
                      -> Result<()>
    where S: Store, M: StateMachine {
        // Attempt to write data.
        // The `current_write` buffer will be advanced based on how much we wrote.
        match self.stream.write(&mut self.current_write) {
            Ok(None) => {
                // This is a buffer flush. WOULDBLOCK
                self.interest.insert(Interest::writable());
            },
            Ok(Some(r)) => {
                // We managed to write data!
                match (self.current_write.has_remaining(), self.next_write.is_empty()) {
                    // Need to write more of what we have.
                    (true, _) => (),
                    // Need to roll over.
                    (false, false) => self.current_write = self.next_write.pop_front().unwrap(),
                    // We're done writing for now.
                    (false, true) => self.interest.remove(Interest::writable()),

                }
            },
            Err(e) => return Err(Error::from_error(e)),
        }

        match event_loop.reregister(&self.stream, self.token, self.interest, PollOpt::edge() | PollOpt::oneshot()) {
            Ok(()) => Ok(()),
            Err(e) => Err(Error::from_error(e)),
        }
    }

    fn readable<S, M>(&mut self, event_loop: &mut EventLoop<Server<S, M>>, replica: &mut Replica<S,M>)
                      -> Result<()>
    where S: Store, M: StateMachine {
        let mut read = 0;
        match self.stream.read(&mut self.current_read) {
            Ok(Some(r)) => {
                // Just read `r` bytes.
                read = r;
            },
            Ok(None) => panic!("We just got readable, but were unable to read from the socket?"),
            Err(e) => return Err(Error::from_error(e)),
        };
        if read > 0 {
            match serialize_packed::new_reader_unbuffered(&mut self.current_read, ReaderOptions::new()) {
                // We have something reasonably interesting in the buffer!
                Ok(reader) => {
                    self.handle_reader(reader, event_loop, replica);
                },
                // It's not read entirely yet.
                // Should roll back, pending changes to bytes upstream.
                Err(_) => unimplemented!(),
            }
        }
        match event_loop.reregister(&self.stream, self.token, self.interest, PollOpt::edge()) {
            Ok(()) => Ok(()),
            Err(e) => Err(Error::from_error(e)),
        }
    }

    fn handle_reader<S, M>(&mut self, reader: OwnedSpaceMessageReader,
                           event_loop: &mut EventLoop<Server<S, M>>, replica: &mut Replica<S,M>)
    where S: Store, M: StateMachine {
        let mut builder_message = MallocMessageBuilder::new_default();
        let from = self.stream.peer_addr().unwrap();
        if let Ok(request) = reader.get_root::<rpc_request::Reader>() {
            match request.which().unwrap() {
                // TODO: Move these into replica?
                rpc_request::Which::AppendEntries(Ok(call)) => {
                    let builder = builder_message.init_root::<append_entries_response::Builder>();
                    match replica.append_entries_request(from, call, builder) {
                        Some(Emit) => {
                            // Special Cirsumstance Detection
                            unimplemented!();
                        },
                        None => (),
                    }
                },
                rpc_request::Which::RequestVote(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<request_vote_response::Builder>();
                        replica.request_vote_request(from, call, builder)
                    };
                    match respond {
                        Some(Emit) => {
                            // TODO
                            self.emit(builder_message);
                        },
                        None            => (),
                    }
                },
                _ => unimplemented!(),
            };
        } else if let Ok(response) = reader.get_root::<rpc_response::Reader>() {
            // We won't be responding. This is already a response.
            match response.which().unwrap() {
                rpc_response::Which::AppendEntries(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<append_entries_request::Builder>();
                        replica.append_entries_response(from, call, builder)
                    };
                    match respond {
                        Some(Emit) => {
                            // TODO
                            self.emit(builder_message);
                        },
                        None => (),
                    }
                },
                rpc_response::Which::RequestVote(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<append_entries_request::Builder>();
                        replica.request_vote_response(from, call, builder)
                    };
                    match respond {
                        Some(Broadcast) => {
                            // Won an election!
                            self.broadcast(builder_message);
                        },
                        None => (),
                    }

                },
                _ => unimplemented!(),
            }
        } else if let Ok(client_req) = reader.get_root::<client_request::Reader>() {
            let mut should_die = false;
            // We will be responding.
            match client_req.which().unwrap() {
                client_request::Which::Append(Ok(call)) => {
                    let respond = {
                        let builder = builder_message.init_root::<client_response::Builder>();
                        replica.client_append(from, call, builder)
                    };
                    match respond {
                        Some(emit) => {
                            self.emit(builder_message);
                        },
                        None => (),
                    }

                },
                client_request::Which::Die(Ok(call)) => {
                    should_die = true;
                    let mut builder = builder_message.init_root::<client_response::Builder>();
                    builder.set_success(());
                    self.interest.insert(Interest::writable());
                    debug!("Got a Die request from Client({}). Reason: {}", from, call);
                },
                client_request::Which::LeaderRefresh(()) => {
                    let respond = {
                        let builder = builder_message.init_root::<client_response::Builder>();
                        replica.client_leader_refresh(from, builder)
                    };
                    match respond {
                        Some(Emit) => {
                            self.emit(builder_message);
                        },
                        None => (),
                    }
                },
                _ => unimplemented!(),
            };

            // Do this here so that we can send the response.
            if should_die {
                panic!("Got a Die request.");
            }

        } else {
            // It's something we don't understand.
            unimplemented!();
        }
    }

    fn broadcast(&mut self, builder: MallocMessageBuilder) {
        unimplemented!();
    }

    /// Push the new message into `self.next_write`.
    pub fn emit(&mut self, mut builder: MallocMessageBuilder) {
        let mut buf = RingBuf::new(RINGBUF_SIZE);
        serialize_packed::write_packed_message_unbuffered(
            &mut buf,
            &mut builder
        ).unwrap();
        self.add_write(buf);
    }

    pub fn add_write(&mut self, buf: RingBuf) {
        self.next_write.push_back(buf);
    }
}
<|endoftext|>


<commit_before>//! Shapes in the game, like units (triangles) and buildings (squares).
extern crate graphics;
use self::graphics::types::Triangle;

pub struct Unit {
    pub rotation: f64,
    pub position: [f64; 2],
    pub target: [f64; 2],
    pub selected: bool,
    pub size: f64,
}

impl Unit {

    pub fn new(position: [f64;2], rotation: f64) -> Unit {
        println!("Create unit at {:?} with rotation {}", position, rotation);
        Unit {
            rotation: rotation,
            position: position,
            target: position,
            selected: false,
            size: 50.0,
        }
    }

    pub fn get_shape(&self) -> Triangle {
        let triangle: Triangle = [
            [0.0, self.size / 2.0], // Left
            [self.size, self.size], // Top right
            [self.size, 0.0],       // Bottom right
        ];
        triangle
    }

}
<commit_msg>Add apply_matrix function to shapes.rs<commit_after>//! Shapes in the game, like units (triangles) and buildings (squares).
extern crate graphics;
use self::graphics::types::Triangle;
use self::graphics::math::{rotate_radians, transform_vec, Matrix2d};

pub struct Unit {
    pub rotation: f64,
    pub position: [f64; 2],
    pub target: [f64; 2],
    pub selected: bool,
    pub size: f64,
}

impl Unit {

    pub fn new(position: [f64;2], rotation: f64) -> Unit {
        println!("Create unit at {:?} with rotation {}", position, rotation);
        Unit {
            rotation: rotation,
            position: position,
            target: position,
            selected: false,
            size: 50.0,
        }
    }

    pub fn get_shape(&self) -> Triangle {
        let triangle: Triangle = [
            [0.0, self.size / 2.0], // Left
            [self.size, self.size], // Top right
            [self.size, 0.0],       // Bottom right
        ];
        triangle
    }

}

/// Apply a transformation matrix to all points in the triangle.
fn apply_matrix(triangle: Triangle, m: Matrix2d) -> Triangle {
    [
        transform_vec(m, triangle[0]),
        transform_vec(m, triangle[1]),
        transform_vec(m, triangle[2]),
    ]
}

#[cfg(test)]
mod test {
    use std::f64::consts::FRAC_PI_2;
    use super::graphics::types::Triangle;
    use super::graphics::math::rotate_radians;
    use super::apply_matrix;

    #[test]
    fn test_apply_matrix() {
        //! Verify that the `apply_matrix` function works properly, by applying a
        //! 90° CCW rotation matrix.
        //!
        //! The initial triangle should look like this:
        //!
        //!       2
        //!        |\
        //!        |_\
        //!       1   3
        //!
        //! After the translation, it should be rotated to the left.
        //!
        //!        3
        //!       /|
        //!      /_|
        //!     2   1

        // Initial triangle.
        let t1: Triangle = [
            [0.0, 0.0],
            [0.0, 5.0],
            [5.0, 0.0],
        ];

        // Rotate by 90° ccw.
        let m = rotate_radians(FRAC_PI_2);
        let mut t2 = apply_matrix(t1, m);

        // Round result to full integers
        for i in 0..3 {
            for j in 0..2 {
                t2[i][j] = t2[i][j].round();
            }
        }

        // Verify result.
        assert_eq!(t2, [
            [0.0,  0.0],
            [-5.0, 0.0],
            [0.0,  5.0],
        ]);
    }
}
<|endoftext|>


<commit_before>use iron::{Middleware, Request, Response, Alloy};
use iron::middleware::Status;
use std::sync::Arc;

pub trait ShareableMiddleware {
    fn shared_enter(&self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status;
    fn shared_exit(&self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status;
}

pub struct Shared {
    pub middleware: Arc<Box<ShareableMiddleware + Send + Share>>
}

impl Shared {
    pub fn new<S: ShareableMiddleware + Send + Share>(s: S) -> Shared {
        Shared {
            middleware: Arc::new(box s as Box<ShareableMiddleware + Send + Share>)
        }
    }
}

// Needed to hack name resolution in our Clone impl
fn clone<T: Clone>(t: &T) -> T { t.clone() }

impl Clone for Shared {
    fn clone(&self) -> Shared {
        Shared {
            middleware: clone(&self.middleware)
        }
    }
}

impl Middleware for Shared {
    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        self.middleware.shared_enter(req, res, alloy)
    }

    fn exit(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        self.middleware.shared_exit(req, res, alloy)
    }
}

<commit_msg>(doc) Documented Shared.<commit_after>use iron::{Middleware, Request, Response, Alloy};
use iron::middleware::Status;
use std::sync::Arc;

/// `Middleware` implementing this trait can be linked using `Shared` so that
/// they are not cloned for each request. This can vastly improve performance
/// for immutable middleware that are not modified while handling requests.
pub trait ShareableMiddleware {
    /// `shared_enter` is an immutable version of `enter` from the `Middleware`
    /// trait - it receives an & reference to self rather than an &mut
    /// reference.
    fn shared_enter(&self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status;

    /// `shared_exit` is an immutable version of `exit` from the `Middleware`
    /// trait - it receives an & reference to self rather than an &mut
    /// reference.
    fn shared_exit(&self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status;
}

/// `Shared` is used to wrap `ShareableMiddleware` into `Middleware` so they
/// can be linked onto a `Chain` while still avoiding unnecessary copies.
pub struct Shared {
    /// The wrapped `ShareableMiddleware`
    pub middleware: Arc<Box<ShareableMiddleware + Send + Share>>
}

impl Shared {
    /// Creates a new instance of `Shared` containing the provided
    /// `ShareableMiddleware` and allowing it to be used as `Middleware`.
    pub fn new<S: ShareableMiddleware + Send + Share>(s: S) -> Shared {
        Shared {
            middleware: Arc::new(box s as Box<ShareableMiddleware + Send + Share>)
        }
    }
}

// Needed to hack name resolution in our Clone impl
fn clone<T: Clone>(t: &T) -> T { t.clone() }

impl Clone for Shared {
    fn clone(&self) -> Shared {
        Shared {
            middleware: clone(&self.middleware)
        }
    }
}

impl Middleware for Shared {
    fn enter(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        self.middleware.shared_enter(req, res, alloy)
    }

    fn exit(&mut self, req: &mut Request, res: &mut Response, alloy: &mut Alloy) -> Status {
        self.middleware.shared_exit(req, res, alloy)
    }
}

<|endoftext|>


<commit_before>//! Utility for `cranelift_serde`.

#![deny(trivial_numeric_casts)]
#![warn(unused_import_braces, unstable_features, unused_extern_crates)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic, mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else,
        unicode_not_nfc, use_self
    )
)]

extern crate cranelift_reader;
extern crate docopt;
#[macro_use]
extern crate serde_derive;
extern crate cranelift_codegen;

extern crate serde_json;

use cranelift_reader::parse_functions;
use docopt::Docopt;
use std::fs::File;
use std::io::prelude::*;
use std::io::{self, Write};
use std::process;
use std::vec::Vec;

mod serde_clif_json;

const USAGE: &str = "
Cranelift JSON serializer/deserializer utility

Usage:
    clif-json serialize [-p] <file>
    clif-json deserialize <file>

Options:
    -p, --pretty     print pretty json

";

#[derive(Deserialize, Debug)]
struct Args {
    cmd_serialize: bool,
    cmd_deserialize: bool,
    flag_pretty: bool,
    arg_file: Vec<String>,
}

/// A command either succeeds or fails with an error message.
pub type CommandResult = Result<(), String>;

/// Serialize Cranelift IR to JSON
fn call_ser(file: &str, pretty: bool) -> CommandResult {
    let ret_of_parse = parse_functions(file);
    match ret_of_parse {
        Ok(funcs) => {
            let ser_funcs = serde_clif_json::SerObj::new(&funcs);
            let ser_str: String;
            if pretty {
                ser_str = serde_json::to_string_pretty(&ser_funcs).unwrap();
            } else {
                ser_str = serde_json::to_string(&ser_funcs).unwrap();
            }
            println!("{}", ser_str);
            Ok(())
        }
        Err(_pe) => Err(format!("this was a parsing error")),
    }
}

/// Deserialize JSON to Cranelift IR
fn call_de(file: &File) -> CommandResult {
    let de: serde_clif_json::SerObj = match serde_json::from_reader(file) {
        Result::Ok(val) => val,
        Result::Err(err) => panic!("{}", err),
    };
    println!("{:?}", de);
    Ok(())
}

/// Parse the command line arguments and run the requested command.
fn clif_json() -> CommandResult {
    // Parse command line arguments.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).deserialize())
        .unwrap_or_else(|e| e.exit());

    // Find the sub-command to execute.
    let result = if args.cmd_serialize {
        if let Some(first_file) = args.arg_file.first() {
            let mut file = File::open(first_file).expect("Unable to open the file");
            let mut contents = String::new();
            file.read_to_string(&mut contents)
                .expect("Unable to read the file");
            call_ser(&contents, args.flag_pretty)
        } else {
            Err(format!("No file was passed"))
        }
    } else if args.cmd_deserialize {
        if let Some(first_file) = args.arg_file.first() {
            let mut file = File::open(first_file).expect("Unable to open the file");
            call_de(&file)
        } else {
            Err(format!("No file was passed"))
        }
    } else {
        // Debugging / shouldn't happen with proper command line handling above.
        Err(format!("Unhandled args: {:?}", args))
    };

    result
}

fn main() {
    if let Err(mut msg) = clif_json() {
        if !msg.ends_with('\n') {
            msg.push('\n');
        }
        io::stdout().flush().expect("flushing stdout");
        io::stderr().write_all(msg.as_bytes()).unwrap();
        process::exit(1);
    }
}
<commit_msg>Fixing serde formatting.<commit_after>//! Utility for `cranelift_serde`.

#![deny(trivial_numeric_casts)]
#![warn(unused_import_braces, unstable_features, unused_extern_crates)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic, mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else,
        unicode_not_nfc, use_self
    )
)]

extern crate cranelift_reader;
extern crate docopt;
#[macro_use]
extern crate serde_derive;
extern crate cranelift_codegen;

extern crate serde_json;

use cranelift_reader::parse_functions;
use docopt::Docopt;
use std::fs::File;
use std::io::prelude::*;
use std::io::{self, Write};
use std::process;
use std::vec::Vec;

mod serde_clif_json;

const USAGE: &str = "
Cranelift JSON serializer/deserializer utility

Usage:
    clif-json serialize [-p] <file>
    clif-json deserialize <file>

Options:
    -p, --pretty     print pretty json

";

#[derive(Deserialize, Debug)]
struct Args {
    cmd_serialize: bool,
    cmd_deserialize: bool,
    flag_pretty: bool,
    arg_file: Vec<String>,
}

/// A command either succeeds or fails with an error message.
pub type CommandResult = Result<(), String>;

/// Serialize Cranelift IR to JSON
fn call_ser(file: &str, pretty: bool) -> CommandResult {
    let ret_of_parse = parse_functions(file);
    match ret_of_parse {
        Ok(funcs) => {
            let ser_funcs = serde_clif_json::SerObj::new(&funcs);
            let ser_str: String;
            if pretty {
                ser_str = serde_json::to_string_pretty(&ser_funcs).unwrap();
            } else {
                ser_str = serde_json::to_string(&ser_funcs).unwrap();
            }
            println!("{}", ser_str);
            Ok(())
        }
        Err(_pe) => Err(format!("this was a parsing error")),
    }
}

/// Deserialize JSON to Cranelift IR
fn call_de(file: &File) -> CommandResult {
    let de: serde_clif_json::SerObj = match serde_json::from_reader(file) {
        Result::Ok(val) => val,
        Result::Err(err) => panic!("{}", err),
    };
    println!("{:?}", de);
    Ok(())
}

/// Parse the command line arguments and run the requested command.
fn clif_json() -> CommandResult {
    // Parse command line arguments.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).deserialize())
        .unwrap_or_else(|e| e.exit());

    // Find the sub-command to execute.
    let result = if args.cmd_serialize {
        if let Some(first_file) = args.arg_file.first() {
            let mut file = File::open(first_file).expect("Unable to open the file");
            let mut contents = String::new();
            file.read_to_string(&mut contents)
                .expect("Unable to read the file");
            call_ser(&contents, args.flag_pretty)
        } else {
            Err(format!("No file was passed"))
        }
    } else if args.cmd_deserialize {
        if let Some(first_file) = args.arg_file.first() {
            let mut file = File::open(first_file).expect("Unable to open the file");
            call_de(&file)
        } else {
            Err(format!("No file was passed"))
        }
    } else {
        // Debugging / shouldn't happen with proper command line handling above.
        Err(format!("Unhandled args: {:?}", args))
    };

    result
}

fn main() {
    if let Err(mut msg) = clif_json() {
        if !msg.ends_with('\n') {
            msg.push('\n');
        }
        io::stdout().flush().expect("flushing stdout");
        io::stderr().write_all(msg.as_bytes()).unwrap();
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>//! Test for `boxed` mod.

use core::any::Any;
use core::clone::Clone;
use core::convert::TryInto;
use core::ops::Deref;
use core::result::Result::{Err, Ok};

use std::boxed::Box;

#[test]
fn test_owned_clone() {
    let a = Box::new(5);
    let b: Box<i32> = a.clone();
    assert!(a == b);
}

#[derive(PartialEq, Eq)]
struct Test;

#[test]
fn any_move() {
    let a = Box::new(8) as Box<dyn Any>;
    let b = Box::new(Test) as Box<dyn Any>;

    match a.downcast::<i32>() {
        Ok(a) => {
            assert!(a == Box::new(8));
        }
        Err(..) => panic!(),
    }
    match b.downcast::<Test>() {
        Ok(a) => {
            assert!(a == Box::new(Test));
        }
        Err(..) => panic!(),
    }

    let a = Box::new(8) as Box<dyn Any>;
    let b = Box::new(Test) as Box<dyn Any>;

    assert!(a.downcast::<Box<Test>>().is_err());
    assert!(b.downcast::<Box<i32>>().is_err());
}

#[test]
fn test_show() {
    let a = Box::new(8) as Box<dyn Any>;
    let b = Box::new(Test) as Box<dyn Any>;
    let a_str = format!("{:?}", a);
    let b_str = format!("{:?}", b);
    assert_eq!(a_str, "Any");
    assert_eq!(b_str, "Any");

    static EIGHT: usize = 8;
    static TEST: Test = Test;
    let a = &EIGHT as &dyn Any;
    let b = &TEST as &dyn Any;
    let s = format!("{:?}", a);
    assert_eq!(s, "Any");
    let s = format!("{:?}", b);
    assert_eq!(s, "Any");
}

#[test]
fn deref() {
    fn homura<T: Deref<Target = i32>>(_: T) {}
    homura(Box::new(765));
}

#[test]
fn raw_sized() {
    let x = Box::new(17);
    let p = Box::into_raw(x);
    unsafe {
        assert_eq!(17, *p);
        *p = 19;
        let y = Box::from_raw(p);
        assert_eq!(19, *y);
    }
}

#[test]
fn raw_trait() {
    trait Foo {
        fn get(&self) -> u32;
        fn set(&mut self, value: u32);
    }

    struct Bar(u32);

    impl Foo for Bar {
        fn get(&self) -> u32 {
            self.0
        }

        fn set(&mut self, value: u32) {
            self.0 = value;
        }
    }

    let x: Box<dyn Foo> = Box::new(Bar(17));
    let p = Box::into_raw(x);
    unsafe {
        assert_eq!(17, (*p).get());
        (*p).set(19);
        let y: Box<dyn Foo> = Box::from_raw(p);
        assert_eq!(19, y.get());
    }
}

#[test]
fn f64_slice() {
    let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY];
    let boxed: Box<[f64]> = Box::from(slice);
    assert_eq!(&*boxed, slice)
}

#[test]
fn i64_slice() {
    let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX];
    let boxed: Box<[i64]> = Box::from(slice);
    assert_eq!(&*boxed, slice)
}

#[test]
fn str_slice() {
    let s = "Hello, world!";
    let boxed: Box<str> = Box::from(s);
    assert_eq!(&*boxed, s)
}

#[test]
fn boxed_slice_from_iter() {
    let iter = 0..100;
    let boxed: Box<[u32]> = iter.collect();
    assert_eq!(boxed.len(), 100);
    assert_eq!(boxed[7], 7);
}

#[test]
fn test_array_from_slice() {
    let v = vec![1, 2, 3];
    let r: Box<[u32]> = v.into_boxed_slice();

    let a: Result<Box<[u32; 3]>, _> = r.clone().try_into();
    assert!(a.is_ok());

    let a: Result<Box<[u32; 2]>, _> = r.clone().try_into();
    assert!(a.is_err());
}
<commit_msg>Fix `alloc::test::test_show`<commit_after>//! Test for `boxed` mod.

use core::any::Any;
use core::clone::Clone;
use core::convert::TryInto;
use core::ops::Deref;
use core::result::Result::{Err, Ok};

use std::boxed::Box;

#[test]
fn test_owned_clone() {
    let a = Box::new(5);
    let b: Box<i32> = a.clone();
    assert!(a == b);
}

#[derive(PartialEq, Eq)]
struct Test;

#[test]
fn any_move() {
    let a = Box::new(8) as Box<dyn Any>;
    let b = Box::new(Test) as Box<dyn Any>;

    match a.downcast::<i32>() {
        Ok(a) => {
            assert!(a == Box::new(8));
        }
        Err(..) => panic!(),
    }
    match b.downcast::<Test>() {
        Ok(a) => {
            assert!(a == Box::new(Test));
        }
        Err(..) => panic!(),
    }

    let a = Box::new(8) as Box<dyn Any>;
    let b = Box::new(Test) as Box<dyn Any>;

    assert!(a.downcast::<Box<Test>>().is_err());
    assert!(b.downcast::<Box<i32>>().is_err());
}

#[test]
fn test_show() {
    let a = Box::new(8) as Box<dyn Any>;
    let b = Box::new(Test) as Box<dyn Any>;
    let a_str = format!("{:?}", a);
    let b_str = format!("{:?}", b);
    assert_eq!(a_str, "Any { .. }");
    assert_eq!(b_str, "Any { .. }");

    static EIGHT: usize = 8;
    static TEST: Test = Test;
    let a = &EIGHT as &dyn Any;
    let b = &TEST as &dyn Any;
    let s = format!("{:?}", a);
    assert_eq!(s, "Any { .. }");
    let s = format!("{:?}", b);
    assert_eq!(s, "Any { .. }");
}

#[test]
fn deref() {
    fn homura<T: Deref<Target = i32>>(_: T) {}
    homura(Box::new(765));
}

#[test]
fn raw_sized() {
    let x = Box::new(17);
    let p = Box::into_raw(x);
    unsafe {
        assert_eq!(17, *p);
        *p = 19;
        let y = Box::from_raw(p);
        assert_eq!(19, *y);
    }
}

#[test]
fn raw_trait() {
    trait Foo {
        fn get(&self) -> u32;
        fn set(&mut self, value: u32);
    }

    struct Bar(u32);

    impl Foo for Bar {
        fn get(&self) -> u32 {
            self.0
        }

        fn set(&mut self, value: u32) {
            self.0 = value;
        }
    }

    let x: Box<dyn Foo> = Box::new(Bar(17));
    let p = Box::into_raw(x);
    unsafe {
        assert_eq!(17, (*p).get());
        (*p).set(19);
        let y: Box<dyn Foo> = Box::from_raw(p);
        assert_eq!(19, y.get());
    }
}

#[test]
fn f64_slice() {
    let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY];
    let boxed: Box<[f64]> = Box::from(slice);
    assert_eq!(&*boxed, slice)
}

#[test]
fn i64_slice() {
    let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX];
    let boxed: Box<[i64]> = Box::from(slice);
    assert_eq!(&*boxed, slice)
}

#[test]
fn str_slice() {
    let s = "Hello, world!";
    let boxed: Box<str> = Box::from(s);
    assert_eq!(&*boxed, s)
}

#[test]
fn boxed_slice_from_iter() {
    let iter = 0..100;
    let boxed: Box<[u32]> = iter.collect();
    assert_eq!(boxed.len(), 100);
    assert_eq!(boxed[7], 7);
}

#[test]
fn test_array_from_slice() {
    let v = vec![1, 2, 3];
    let r: Box<[u32]> = v.into_boxed_slice();

    let a: Result<Box<[u32; 3]>, _> = r.clone().try_into();
    assert!(a.is_ok());

    let a: Result<Box<[u32; 2]>, _> = r.clone().try_into();
    assert!(a.is_err());
}
<|endoftext|>


<commit_before>use token::Token;
use logger::Logger;
use error::{Error, Result, Source};

use std::collections::HashMap;
use std::path::{Path,PathBuf};
use std::borrow::Cow;
use std::fs;
use std::io::Read;

use walkdir::WalkDir;
use rustc_serialize::base64::{self, ToBase64};
use mime_guess;

/// Resource Handler.
///
/// Its task is to make sure that some resource (image, link) is available
/// for the book and to list images used in Markdown files so they can be used for the book
#[derive(Debug)]
pub struct ResourceHandler<'r> {
    /// Maps an original url (e.g.) "foo/Readme.md" to a valid link
    /// (e.g.) chapter3.html
    links: HashMap<String, String>,
    /// Maps an original (local) file name to a new file name. Allows to
    // make sure all image files will be included in e.g. the Epub document.
    pub images: HashMap<String, String>,
    map_images: bool,
    logger: &'r Logger,
    base64: bool,
}

impl<'r> ResourceHandler<'r> {
    /// Creates a new, empty Resource Handler
    pub fn new(logger: &'r Logger) -> ResourceHandler {
        ResourceHandler {
            links: HashMap::new(),
            images: HashMap::new(),
            map_images: false,
            base64: false,
            logger: logger,
        }
    }

    /// Turns on mapping for image files
    ///
    /// # Argument: an offset (should be book.root)
    pub fn set_images_mapping(&mut self, b: bool) {
        self.map_images = b;
    }

    /// Sets base64 mode for image mapping
    ///
    /// If set to true, instead of returning a destination file path,
    /// `map_image` will include the image as base64
    pub fn set_base64(&mut self, b: bool) {
        self.base64 = b;
    }

    /// Add a local image file and get the resulting transformed
    /// file name
    pub fn map_image<'a>(&'a mut self, source: &Source, file: Cow<'a, str>) -> Result<Cow<'a, str>> {
        // If image is not local, do nothing much
        if !Self::is_local(file.as_ref()) {
            self.logger.warning(format!("Resources: book includes non-local image {}, which might cause problem for proper inclusion.", file));
            return Ok(file);
        }

        // Check exisence of the file
        if fs::metadata(file.as_ref()).is_err() {
            return Err(Error::FileNotFound(source.clone(),
                                           "image".to_owned(),
                                           format!("{}", file)));
        }

        // if image mapping is not activated do nothing else
        if !self.map_images {
            return Ok(file);
        }

        // If this image has already been registered, returns it
        if self.images.contains_key(file.as_ref()) {
            return Ok(Cow::Borrowed(self.images.get(file.as_ref()).unwrap()));
        }

        // Else, create a new file name that has same extension
        // (or a base64 version of the file)
        let dest_file = if !(self.base64) {
            if let Some(extension) = Path::new(file.as_ref()).extension() {
                format!("images/image_{}.{}", self.images.len(), extension.to_string_lossy())
            } else {
                self.logger.warning(format!("Resources: book includes image {} which doesn't have an extension", file));
                format!("images/image_{}", self.images.len())
            }
        } else {
            let mut f = match fs::File::open(file.as_ref()) {
                Ok(f) => f,
                Err(_) => {
                    return Err(Error::FileNotFound(source.clone(),
                                                   "image".to_owned(),
                                                   format!("{}", file)));
                }
            };
            let mut content: Vec<u8> = vec!();
            if f.read_to_end(&mut content).is_err() {
                self.logger.error(format!("Resources: could not read file {}", file));
                return Ok(file);
            }
            let base64 = content.to_base64(base64::STANDARD);
            match mime_guess::guess_mime_type_opt(file.as_ref()) {
                None => {
                    self.logger.error(format!("Resources: could not guess mime type of file {}", file));
                    return Ok(file);
                },
                Some(s) => format!("data:{};base64,{}", s.to_string(), base64)
            }
        };

        self.images.insert(file.into_owned(), dest_file.clone());
        Ok(Cow::Owned(dest_file))
    }

    /// Returns an iterator the the images files mapping
    pub fn images_mapping(&self) -> &HashMap<String,String> {
        &self.images
    }

    /// Add a match between an original file and a dest file
    pub fn add_link(&mut self, from: String, to: String) {
        self.links.insert(from, to);
    }

    /// Get a destination link from an original link
    pub fn get_link<'a>(&'a self, from: &'a str) -> &'a str {
        if let Some(link) = self.links.get(from) {
            link
        } else {
            self.logger.warning(format!("Resources: could not find a in-book match for link {}", from));
            from
        }
    }

    /// Tell whether a file name is a local resource or net
    pub fn is_local(path: &str) -> bool{
        !path.contains("://") // todo: use better algorithm
    }

    /// Add a path offset to all linked urls and images src
    pub fn add_offset(link_offset: &Path, image_offset: &Path, ast: &mut [Token]) {
        if link_offset == Path::new("") && image_offset == Path::new("") {
            //nothing do to
            return;
        }
        for mut token in ast {
            match *token {
                Token::Link(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", link_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                Token::Image (ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", image_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                _ => {
                    if let Some(ref mut inner) = token.inner_mut() {
                            Self::add_offset(link_offset, image_offset, inner);
                    }
                }
            }
        }
    }

    /// Get the list of all files, walking recursively in directories
    ///
    /// # Arguments
    /// - list: a list of files
    /// - base: the path where to get them
    ///
    /// # Returns
    /// A list of files (relative to `base`), or an error.
    pub fn get_files(list: Vec<String>, base: &str) -> Result<Vec<String>> {
        let mut out:Vec<String> = vec!();
        let base = Path::new(base);
        for path in list.into_iter() {
            let abs_path = base.join(&path);
            let res= fs::metadata(&abs_path);
            match res {
                Err(err) => return Err(Error::Render(format!("error reading file {}: {}", abs_path.display(), err))),
                Ok(metadata) => {
                    if metadata.is_file() {
                        out.push(path);
                    } else if metadata.is_dir() {
                        let files = WalkDir::new(&abs_path)
                            .follow_links(true)
                            .into_iter()
                            .filter_map(|e| e.ok())
                            .filter(|e| e.file_type().is_file())
                            .map(|e| PathBuf::from(e.path().strip_prefix(base)
                                                   .unwrap()));
                        for file in files {
                            out.push(file.to_string_lossy().into_owned());
                        }
                    } else {
                        return Err(Error::Render(format!("error in epub rendering: {} is neither a file nor a directory", &path)));
                    }
                }
            }
        }
        Ok(out)
    }
}
<commit_msg>Move wronk link to error instead of warning<commit_after>use token::Token;
use logger::Logger;
use error::{Error, Result, Source};

use std::collections::HashMap;
use std::path::{Path,PathBuf};
use std::borrow::Cow;
use std::fs;
use std::io::Read;

use walkdir::WalkDir;
use rustc_serialize::base64::{self, ToBase64};
use mime_guess;

/// Resource Handler.
///
/// Its task is to make sure that some resource (image, link) is available
/// for the book and to list images used in Markdown files so they can be used for the book
#[derive(Debug)]
pub struct ResourceHandler<'r> {
    /// Maps an original url (e.g.) "foo/Readme.md" to a valid link
    /// (e.g.) chapter3.html
    links: HashMap<String, String>,
    /// Maps an original (local) file name to a new file name. Allows to
    // make sure all image files will be included in e.g. the Epub document.
    pub images: HashMap<String, String>,
    map_images: bool,
    logger: &'r Logger,
    base64: bool,
}

impl<'r> ResourceHandler<'r> {
    /// Creates a new, empty Resource Handler
    pub fn new(logger: &'r Logger) -> ResourceHandler {
        ResourceHandler {
            links: HashMap::new(),
            images: HashMap::new(),
            map_images: false,
            base64: false,
            logger: logger,
        }
    }

    /// Turns on mapping for image files
    ///
    /// # Argument: an offset (should be book.root)
    pub fn set_images_mapping(&mut self, b: bool) {
        self.map_images = b;
    }

    /// Sets base64 mode for image mapping
    ///
    /// If set to true, instead of returning a destination file path,
    /// `map_image` will include the image as base64
    pub fn set_base64(&mut self, b: bool) {
        self.base64 = b;
    }

    /// Add a local image file and get the resulting transformed
    /// file name
    pub fn map_image<'a>(&'a mut self, source: &Source, file: Cow<'a, str>) -> Result<Cow<'a, str>> {
        // If image is not local, do nothing much
        if !Self::is_local(file.as_ref()) {
            self.logger.warning(format!("Resources: book includes non-local image {}, which might cause problem for proper inclusion.", file));
            return Ok(file);
        }

        // Check exisence of the file
        if fs::metadata(file.as_ref()).is_err() {
            return Err(Error::FileNotFound(source.clone(),
                                           "image".to_owned(),
                                           format!("{}", file)));
        }

        // if image mapping is not activated do nothing else
        if !self.map_images {
            return Ok(file);
        }

        // If this image has already been registered, returns it
        if self.images.contains_key(file.as_ref()) {
            return Ok(Cow::Borrowed(self.images.get(file.as_ref()).unwrap()));
        }

        // Else, create a new file name that has same extension
        // (or a base64 version of the file)
        let dest_file = if !(self.base64) {
            if let Some(extension) = Path::new(file.as_ref()).extension() {
                format!("images/image_{}.{}", self.images.len(), extension.to_string_lossy())
            } else {
                self.logger.warning(format!("Resources: book includes image {} which doesn't have an extension", file));
                format!("images/image_{}", self.images.len())
            }
        } else {
            let mut f = match fs::File::open(file.as_ref()) {
                Ok(f) => f,
                Err(_) => {
                    return Err(Error::FileNotFound(source.clone(),
                                                   "image".to_owned(),
                                                   format!("{}", file)));
                }
            };
            let mut content: Vec<u8> = vec!();
            if f.read_to_end(&mut content).is_err() {
                self.logger.error(format!("Resources: could not read file {}", file));
                return Ok(file);
            }
            let base64 = content.to_base64(base64::STANDARD);
            match mime_guess::guess_mime_type_opt(file.as_ref()) {
                None => {
                    self.logger.error(format!("Resources: could not guess mime type of file {}", file));
                    return Ok(file);
                },
                Some(s) => format!("data:{};base64,{}", s.to_string(), base64)
            }
        };

        self.images.insert(file.into_owned(), dest_file.clone());
        Ok(Cow::Owned(dest_file))
    }

    /// Returns an iterator the the images files mapping
    pub fn images_mapping(&self) -> &HashMap<String,String> {
        &self.images
    }

    /// Add a match between an original file and a dest file
    pub fn add_link(&mut self, from: String, to: String) {
        self.links.insert(from, to);
    }

    /// Get a destination link from an original link
    pub fn get_link<'a>(&'a self, from: &'a str) -> &'a str {
        if let Some(link) = self.links.get(from) {
            link
        } else {
            self.logger.error(format!("Resources: could not find a in-book match for link {}", from));
            from
        }
    }

    /// Tell whether a file name is a local resource or net
    pub fn is_local(path: &str) -> bool{
        !path.contains("://") // todo: use better algorithm
    }

    /// Add a path offset to all linked urls and images src
    pub fn add_offset(link_offset: &Path, image_offset: &Path, ast: &mut [Token]) {
        if link_offset == Path::new("") && image_offset == Path::new("") {
            //nothing do to
            return;
        }
        for mut token in ast {
            match *token {
                Token::Link(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", link_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                Token::Image (ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", image_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                _ => {
                    if let Some(ref mut inner) = token.inner_mut() {
                            Self::add_offset(link_offset, image_offset, inner);
                    }
                }
            }
        }
    }

    /// Get the list of all files, walking recursively in directories
    ///
    /// # Arguments
    /// - list: a list of files
    /// - base: the path where to get them
    ///
    /// # Returns
    /// A list of files (relative to `base`), or an error.
    pub fn get_files(list: Vec<String>, base: &str) -> Result<Vec<String>> {
        let mut out:Vec<String> = vec!();
        let base = Path::new(base);
        for path in list.into_iter() {
            let abs_path = base.join(&path);
            let res= fs::metadata(&abs_path);
            match res {
                Err(err) => return Err(Error::Render(format!("error reading file {}: {}", abs_path.display(), err))),
                Ok(metadata) => {
                    if metadata.is_file() {
                        out.push(path);
                    } else if metadata.is_dir() {
                        let files = WalkDir::new(&abs_path)
                            .follow_links(true)
                            .into_iter()
                            .filter_map(|e| e.ok())
                            .filter(|e| e.file_type().is_file())
                            .map(|e| PathBuf::from(e.path().strip_prefix(base)
                                                   .unwrap()));
                        for file in files {
                            out.push(file.to_string_lossy().into_owned());
                        }
                    } else {
                        return Err(Error::Render(format!("error in epub rendering: {} is neither a file nor a directory", &path)));
                    }
                }
            }
        }
        Ok(out)
    }
}
<|endoftext|>