<commit_before>//! Single client connection

use std::result::Result as std_Result;
use std::net::SocketAddr;
use std::sync::Arc;
use std::io;

use error;
use error::Error;
use result;

use solicit::StreamId;
use solicit::header::*;
use solicit::connection::EndStream;
use solicit::frame::settings::*;
use solicit::DEFAULT_SETTINGS;

use service::Service;

use futures::future;
use futures::future::Future;
use futures::stream::Stream;
use futures::sync::oneshot;
use futures::sync::mpsc::unbounded;
use futures::sync::mpsc::UnboundedSender;

use native_tls::TlsConnector;

use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_timer::Timer;
use tokio_io::AsyncWrite;
use tokio_io::AsyncRead;
use tokio_tls::TlsConnectorExt;

use futures_misc::*;

use solicit_async::*;

use common::*;
use stream_part::*;
use client_conf::*;
use client_tls::*;

use rc_mut::*;

struct ClientTypes;

impl Types for ClientTypes {
    type HttpStream = ClientStream;
    type HttpStreamSpecific = ClientStreamData;
    type ConnDataSpecific = ClientConnData;
    type ToWriteMessage = ClientToWriteMessage;

    fn first_id() -> StreamId {
        1
    }
}

pub struct ClientStreamData {
}

impl HttpStreamDataSpecific for ClientStreamData {
}

type ClientStream = HttpStreamCommon<ClientTypes>;

impl HttpStream for ClientStream {
    type Types = ClientTypes;
}

pub struct ClientConnData {
    callbacks: Box<ClientConnectionCallbacks>,
}

impl ConnDataSpecific for ClientConnData {
}

type ClientInner = ConnData<ClientTypes>;

impl ClientInner {
    fn insert_stream(&mut self, stream: ClientStream) -> StreamId {
        let id = self.next_local_stream_id();
        self.streams.insert(id, stream);
        id
    }
}

impl ConnInner for ClientInner {
    type Types = ClientTypes;

    fn process_headers(&mut self, _self_rc: RcMut<Self>, stream_id: StreamId, end_stream: EndStream, headers: Headers)
        -> result::Result<Option<HttpStreamRef<ClientTypes>>>
    {
        if let Some(mut stream) = self.get_stream_or_send_stream_closed(stream_id)? {
            if let Some(ref mut response_handler) = stream.stream().peer_tx {
                drop(response_handler.send(ResultOrEof::Item(HttpStreamPart {
                    content: HttpStreamPartContent::Headers(headers),
                    last: end_stream == EndStream::Yes,
                })));
            } else {
                // TODO: reset stream
            }

            Ok(Some(stream))
        } else {
            Ok(None)
        }
    }

    fn goaway_received(&mut self, stream_id: StreamId, raw_error_code: u32) {
        self.specific.callbacks.goaway(stream_id, raw_error_code);
    }
}

pub struct ClientConnection {
    write_tx: UnboundedSender<ClientToWriteMessage>,
    command_tx: UnboundedSender<ClientCommandMessage>,
}

unsafe impl Sync for ClientConnection {}

pub struct StartRequestMessage {
    pub headers: Headers,
    pub body: HttpPartStream,
    pub resp_tx: UnboundedSender<ResultOrEof<HttpStreamPart, Error>>,
}

enum ClientToWriteMessage {
    Start(StartRequestMessage),
    Common(CommonToWriteMessage),
}

impl From<CommonToWriteMessage> for ClientToWriteMessage {
    fn from(m: CommonToWriteMessage) -> Self {
        ClientToWriteMessage::Common(m)
    }
}

enum ClientCommandMessage {
    DumpState(oneshot::Sender<ConnectionStateSnapshot>),
    WaitForHandshake(oneshot::Sender<result::Result<()>>),
}

impl<I : AsyncWrite + Send + 'static> ClientWriteLoop<I> {
    fn process_start(self, start: StartRequestMessage) -> HttpFuture<Self> {
        let StartRequestMessage { headers, body, resp_tx } = start;

        let inner_rc = self.inner.clone();

        let stream_id = self.inner.with(move |inner: &mut ClientInner| {

            let (latch_ctr, latch) = latch();

            // TODO
            latch_ctr.open();

            let mut stream = HttpStreamCommon::new(
                inner.conn.peer_settings.initial_window_size,
                resp_tx,
                latch_ctr,
                ClientStreamData { });

            stream.outgoing.push_back(HttpStreamPartContent::Headers(headers));

            let stream_id = inner.insert_stream(stream);

            inner.pump_stream_to_write_loop(inner_rc, stream_id, body, latch);

            stream_id
        });

        self.send_outg_stream(stream_id)
    }

    fn process_message(self, message: ClientToWriteMessage) -> HttpFuture<Self> {
        match message {
            ClientToWriteMessage::Start(start) => self.process_start(start),
            ClientToWriteMessage::Common(common) => self.process_common(common),
        }
    }

    pub fn run(self, requests: HttpFutureStreamSend<ClientToWriteMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |wl, message: ClientToWriteMessage| {
                wl.process_message(message)
            })
            .map(|_| ()))
    }
}

type ClientReadLoop<I> = ReadLoopData<I, ClientTypes>;
type ClientWriteLoop<I> = WriteLoopData<I, ClientTypes>;
type ClientCommandLoop = CommandLoopData<ClientTypes>;

pub trait ClientConnectionCallbacks : 'static {
    // called at most once
    fn goaway(&self, stream_id: StreamId, raw_error_code: u32);
}

impl ClientConnection {
    fn connected<I, C>(
        lh: reactor::Handle, connect: HttpFutureSend<I>,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where
            I : AsyncWrite + AsyncRead + Send + 'static,
            C : ClientConnectionCallbacks,
    {
        let (to_write_tx, to_write_rx) = unbounded();
        let (command_tx, command_rx) = unbounded();

        let to_write_rx = Box::new(to_write_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "to_write"))));
        let command_rx = Box::new(command_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "to_write"))));

        let c = ClientConnection {
            write_tx: to_write_tx.clone(),
            command_tx: command_tx,
        };

        let settings_frame = SettingsFrame::from_settings(vec![ HttpSetting::EnablePush(false) ]);
        let mut settings = DEFAULT_SETTINGS;
        settings.apply_from_frame(&settings_frame);

        let handshake = connect.and_then(|conn| client_handshake(conn, settings_frame));

        let future = handshake.and_then(move |conn| {
            debug!("handshake done");
            let (read, write) = conn.split();

            let inner = RcMut::new(ConnData::new(
                lh,
                ClientConnData {
                    callbacks: Box::new(callbacks),
                },
                conf.common,
                settings,
                to_write_tx.clone()));

            let run_write = ClientWriteLoop { write: write, inner: inner.clone() }.run(to_write_rx);
            let run_read = ClientReadLoop { read: read, inner: inner.clone() }.run();
            let run_command = ClientCommandLoop { inner: inner.clone() }.run(command_rx);

            run_write.join(run_read).join(run_command).map(|_| ())
        });

        (c, Box::new(future))
    }

    pub fn new<C>(
        lh: reactor::Handle,
        addr: &SocketAddr,
        tls: ClientTlsOption,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where C : ClientConnectionCallbacks
    {
        match tls {
            ClientTlsOption::Plain =>
                ClientConnection::new_plain(lh, addr, conf, callbacks),
            ClientTlsOption::Tls(domain, connector) =>
                ClientConnection::new_tls(lh, &domain, connector, addr, conf, callbacks),
        }
    }

    pub fn new_plain<C>(
        lh: reactor::Handle,
        addr: &SocketAddr,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where C : ClientConnectionCallbacks
    {
        let addr = addr.clone();

        let no_delay = conf.no_delay.unwrap_or(true);
        let connect = TcpStream::connect(&addr, &lh).map_err(Into::into);
        let map_callback = move |socket: TcpStream| {
            info!("connected to {}", addr);

            socket.set_nodelay(no_delay).expect("failed to set TCP_NODELAY");

            socket
        };

        let connect = if let Some(timeout) = conf.connection_timeout {
            let timer = Timer::default();
            timer.timeout(connect, timeout).map(map_callback).boxed()
        } else {
            connect.map(map_callback).boxed()
        };

        ClientConnection::connected(lh, connect, conf, callbacks)
    }

    pub fn new_tls<C>(
        lh: reactor::Handle,
        domain: &str,
        connector: Arc<TlsConnector>,
        addr: &SocketAddr,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where C : ClientConnectionCallbacks
    {
        let domain = domain.to_owned();
        let addr = addr.clone();

        let connect = TcpStream::connect(&addr, &lh)
            .map(move |c| { info!("connected to {}", addr); c })
            .map_err(|e| e.into());

        let tls_conn = connect.and_then(move |conn| {
            connector.connect_async(&domain, conn).map_err(|e| {
                Error::IoError(io::Error::new(io::ErrorKind::Other, e))
            })
        });

        let tls_conn = tls_conn.map_err(Error::from);

        ClientConnection::connected(lh, Box::new(tls_conn), conf, callbacks)
    }

    pub fn start_request_with_resp_sender(
        &self,
        start: StartRequestMessage)
            -> Result<(), StartRequestMessage>
    {
        self.write_tx.send(ClientToWriteMessage::Start(start))
            .map_err(|send_error| {
                match send_error.into_inner() {
                    ClientToWriteMessage::Start(start) => start,
                    _ => unreachable!(),
                }
            })
    }

    pub fn dump_state_with_resp_sender(&self, tx: oneshot::Sender<ConnectionStateSnapshot>) {
        // ignore error
        drop(self.command_tx.send(ClientCommandMessage::DumpState(tx)));
    }

    /// For tests
    pub fn dump_state(&self) -> HttpFutureSend<ConnectionStateSnapshot> {
        let (tx, rx) = oneshot::channel();

        self.dump_state_with_resp_sender(tx);

        let rx = rx.map_err(|_| Error::from(io::Error::new(io::ErrorKind::Other, "oneshot canceled")));

        Box::new(rx)
    }

    pub fn wait_for_connect_with_resp_sender(&self, tx: oneshot::Sender<result::Result<()>>)
        -> std_Result<(), oneshot::Sender<result::Result<()>>>
    {
        self.command_tx.send(ClientCommandMessage::WaitForHandshake(tx))
            .map_err(|send_error| {
                match send_error.into_inner() {
                    ClientCommandMessage::WaitForHandshake(tx) => tx,
                    _ => unreachable!(),
                }
            })
    }
}

impl Service for ClientConnection {
    fn start_request(
        &self,
        headers: Headers,
        body: HttpPartStream)
            -> Response
    {
        let (resp_tx, resp_rx) = unbounded();

        let start = StartRequestMessage {
            headers: headers,
            body: body,
            resp_tx: resp_tx,
        };

        if let Err(_) = self.start_request_with_resp_sender(start) {
            return Response::err(error::Error::Other("client died"));
        }

        let req_rx = resp_rx.map_err(|()| Error::from(io::Error::new(io::ErrorKind::Other, "req")));

        let req_rx = stream_with_eof_and_error(req_rx, || error::Error::Other("client is likely died"));

        Response::from_stream(req_rx)
    }
}

impl ClientCommandLoop {
    fn process_dump_state(self, sender: oneshot::Sender<ConnectionStateSnapshot>) -> HttpFuture<Self> {
        // ignore send error, client might be already dead
        drop(sender.send(self.inner.with(|inner| inner.dump_state())));
        Box::new(future::finished(self))
    }

    fn process_message(self, message: ClientCommandMessage) -> HttpFuture<Self> {
        match message {
            ClientCommandMessage::DumpState(sender) => self.process_dump_state(sender),
            ClientCommandMessage::WaitForHandshake(tx) => {
                // ignore error
                drop(tx.send(Ok(())));
                Box::new(future::ok(self))
            },
        }
    }

    fn run(self, requests: HttpFutureStreamSend<ClientCommandMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |l, message: ClientCommandMessage| {
                l.process_message(message)
            })
            .map(|_| ()))
    }
}
<commit_msg>Properly open latch<commit_after>//! Single client connection

use std::result::Result as std_Result;
use std::net::SocketAddr;
use std::sync::Arc;
use std::io;

use error;
use error::Error;
use result;

use solicit::StreamId;
use solicit::header::*;
use solicit::connection::EndStream;
use solicit::frame::settings::*;
use solicit::DEFAULT_SETTINGS;

use service::Service;

use futures::future;
use futures::future::Future;
use futures::stream::Stream;
use futures::sync::oneshot;
use futures::sync::mpsc::unbounded;
use futures::sync::mpsc::UnboundedSender;

use native_tls::TlsConnector;

use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_timer::Timer;
use tokio_io::AsyncWrite;
use tokio_io::AsyncRead;
use tokio_tls::TlsConnectorExt;

use futures_misc::*;

use solicit_async::*;

use common::*;
use stream_part::*;
use client_conf::*;
use client_tls::*;

use rc_mut::*;

struct ClientTypes;

impl Types for ClientTypes {
    type HttpStream = ClientStream;
    type HttpStreamSpecific = ClientStreamData;
    type ConnDataSpecific = ClientConnData;
    type ToWriteMessage = ClientToWriteMessage;

    fn first_id() -> StreamId {
        1
    }
}

pub struct ClientStreamData {
}

impl HttpStreamDataSpecific for ClientStreamData {
}

type ClientStream = HttpStreamCommon<ClientTypes>;

impl HttpStream for ClientStream {
    type Types = ClientTypes;
}

pub struct ClientConnData {
    callbacks: Box<ClientConnectionCallbacks>,
}

impl ConnDataSpecific for ClientConnData {
}

type ClientInner = ConnData<ClientTypes>;

impl ClientInner {
    fn insert_stream(&mut self, stream: ClientStream) -> StreamId {
        let id = self.next_local_stream_id();
        self.streams.insert(id, stream);
        id
    }
}

impl ConnInner for ClientInner {
    type Types = ClientTypes;

    fn process_headers(&mut self, _self_rc: RcMut<Self>, stream_id: StreamId, end_stream: EndStream, headers: Headers)
        -> result::Result<Option<HttpStreamRef<ClientTypes>>>
    {
        if let Some(mut stream) = self.get_stream_or_send_stream_closed(stream_id)? {
            if let Some(ref mut response_handler) = stream.stream().peer_tx {
                drop(response_handler.send(ResultOrEof::Item(HttpStreamPart {
                    content: HttpStreamPartContent::Headers(headers),
                    last: end_stream == EndStream::Yes,
                })));
            } else {
                // TODO: reset stream
            }

            Ok(Some(stream))
        } else {
            Ok(None)
        }
    }

    fn goaway_received(&mut self, stream_id: StreamId, raw_error_code: u32) {
        self.specific.callbacks.goaway(stream_id, raw_error_code);
    }
}

pub struct ClientConnection {
    write_tx: UnboundedSender<ClientToWriteMessage>,
    command_tx: UnboundedSender<ClientCommandMessage>,
}

unsafe impl Sync for ClientConnection {}

pub struct StartRequestMessage {
    pub headers: Headers,
    pub body: HttpPartStream,
    pub resp_tx: UnboundedSender<ResultOrEof<HttpStreamPart, Error>>,
}

enum ClientToWriteMessage {
    Start(StartRequestMessage),
    Common(CommonToWriteMessage),
}

impl From<CommonToWriteMessage> for ClientToWriteMessage {
    fn from(m: CommonToWriteMessage) -> Self {
        ClientToWriteMessage::Common(m)
    }
}

enum ClientCommandMessage {
    DumpState(oneshot::Sender<ConnectionStateSnapshot>),
    WaitForHandshake(oneshot::Sender<result::Result<()>>),
}

impl<I : AsyncWrite + Send + 'static> ClientWriteLoop<I> {
    fn process_start(self, start: StartRequestMessage) -> HttpFuture<Self> {
        let StartRequestMessage { headers, body, resp_tx } = start;

        let inner_rc = self.inner.clone();

        let stream_id = self.inner.with(move |inner: &mut ClientInner| {

            let (latch_ctr, latch) = latch();

            let mut stream = HttpStreamCommon::new(
                inner.conn.peer_settings.initial_window_size,
                resp_tx,
                latch_ctr,
                ClientStreamData { });

            stream.outgoing.push_back(HttpStreamPartContent::Headers(headers));

            let stream_id = inner.insert_stream(stream);

            inner.pump_stream_to_write_loop(inner_rc, stream_id, body, latch);

            stream_id
        });

        // Also opens latch if necessary
        self.send_outg_stream(stream_id)
    }

    fn process_message(self, message: ClientToWriteMessage) -> HttpFuture<Self> {
        match message {
            ClientToWriteMessage::Start(start) => self.process_start(start),
            ClientToWriteMessage::Common(common) => self.process_common(common),
        }
    }

    pub fn run(self, requests: HttpFutureStreamSend<ClientToWriteMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |wl, message: ClientToWriteMessage| {
                wl.process_message(message)
            })
            .map(|_| ()))
    }
}

type ClientReadLoop<I> = ReadLoopData<I, ClientTypes>;
type ClientWriteLoop<I> = WriteLoopData<I, ClientTypes>;
type ClientCommandLoop = CommandLoopData<ClientTypes>;

pub trait ClientConnectionCallbacks : 'static {
    // called at most once
    fn goaway(&self, stream_id: StreamId, raw_error_code: u32);
}

impl ClientConnection {
    fn connected<I, C>(
        lh: reactor::Handle, connect: HttpFutureSend<I>,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where
            I : AsyncWrite + AsyncRead + Send + 'static,
            C : ClientConnectionCallbacks,
    {
        let (to_write_tx, to_write_rx) = unbounded();
        let (command_tx, command_rx) = unbounded();

        let to_write_rx = Box::new(to_write_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "to_write"))));
        let command_rx = Box::new(command_rx.map_err(|()| Error::IoError(io::Error::new(io::ErrorKind::Other, "to_write"))));

        let c = ClientConnection {
            write_tx: to_write_tx.clone(),
            command_tx: command_tx,
        };

        let settings_frame = SettingsFrame::from_settings(vec![ HttpSetting::EnablePush(false) ]);
        let mut settings = DEFAULT_SETTINGS;
        settings.apply_from_frame(&settings_frame);

        let handshake = connect.and_then(|conn| client_handshake(conn, settings_frame));

        let future = handshake.and_then(move |conn| {
            debug!("handshake done");
            let (read, write) = conn.split();

            let inner = RcMut::new(ConnData::new(
                lh,
                ClientConnData {
                    callbacks: Box::new(callbacks),
                },
                conf.common,
                settings,
                to_write_tx.clone()));

            let run_write = ClientWriteLoop { write: write, inner: inner.clone() }.run(to_write_rx);
            let run_read = ClientReadLoop { read: read, inner: inner.clone() }.run();
            let run_command = ClientCommandLoop { inner: inner.clone() }.run(command_rx);

            run_write.join(run_read).join(run_command).map(|_| ())
        });

        (c, Box::new(future))
    }

    pub fn new<C>(
        lh: reactor::Handle,
        addr: &SocketAddr,
        tls: ClientTlsOption,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where C : ClientConnectionCallbacks
    {
        match tls {
            ClientTlsOption::Plain =>
                ClientConnection::new_plain(lh, addr, conf, callbacks),
            ClientTlsOption::Tls(domain, connector) =>
                ClientConnection::new_tls(lh, &domain, connector, addr, conf, callbacks),
        }
    }

    pub fn new_plain<C>(
        lh: reactor::Handle,
        addr: &SocketAddr,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where C : ClientConnectionCallbacks
    {
        let addr = addr.clone();

        let no_delay = conf.no_delay.unwrap_or(true);
        let connect = TcpStream::connect(&addr, &lh).map_err(Into::into);
        let map_callback = move |socket: TcpStream| {
            info!("connected to {}", addr);

            socket.set_nodelay(no_delay).expect("failed to set TCP_NODELAY");

            socket
        };

        let connect = if let Some(timeout) = conf.connection_timeout {
            let timer = Timer::default();
            timer.timeout(connect, timeout).map(map_callback).boxed()
        } else {
            connect.map(map_callback).boxed()
        };

        ClientConnection::connected(lh, connect, conf, callbacks)
    }

    pub fn new_tls<C>(
        lh: reactor::Handle,
        domain: &str,
        connector: Arc<TlsConnector>,
        addr: &SocketAddr,
        conf: ClientConf,
        callbacks: C)
            -> (Self, HttpFuture<()>)
        where C : ClientConnectionCallbacks
    {
        let domain = domain.to_owned();
        let addr = addr.clone();

        let connect = TcpStream::connect(&addr, &lh)
            .map(move |c| { info!("connected to {}", addr); c })
            .map_err(|e| e.into());

        let tls_conn = connect.and_then(move |conn| {
            connector.connect_async(&domain, conn).map_err(|e| {
                Error::IoError(io::Error::new(io::ErrorKind::Other, e))
            })
        });

        let tls_conn = tls_conn.map_err(Error::from);

        ClientConnection::connected(lh, Box::new(tls_conn), conf, callbacks)
    }

    pub fn start_request_with_resp_sender(
        &self,
        start: StartRequestMessage)
            -> Result<(), StartRequestMessage>
    {
        self.write_tx.send(ClientToWriteMessage::Start(start))
            .map_err(|send_error| {
                match send_error.into_inner() {
                    ClientToWriteMessage::Start(start) => start,
                    _ => unreachable!(),
                }
            })
    }

    pub fn dump_state_with_resp_sender(&self, tx: oneshot::Sender<ConnectionStateSnapshot>) {
        // ignore error
        drop(self.command_tx.send(ClientCommandMessage::DumpState(tx)));
    }

    /// For tests
    pub fn dump_state(&self) -> HttpFutureSend<ConnectionStateSnapshot> {
        let (tx, rx) = oneshot::channel();

        self.dump_state_with_resp_sender(tx);

        let rx = rx.map_err(|_| Error::from(io::Error::new(io::ErrorKind::Other, "oneshot canceled")));

        Box::new(rx)
    }

    pub fn wait_for_connect_with_resp_sender(&self, tx: oneshot::Sender<result::Result<()>>)
        -> std_Result<(), oneshot::Sender<result::Result<()>>>
    {
        self.command_tx.send(ClientCommandMessage::WaitForHandshake(tx))
            .map_err(|send_error| {
                match send_error.into_inner() {
                    ClientCommandMessage::WaitForHandshake(tx) => tx,
                    _ => unreachable!(),
                }
            })
    }
}

impl Service for ClientConnection {
    fn start_request(
        &self,
        headers: Headers,
        body: HttpPartStream)
            -> Response
    {
        let (resp_tx, resp_rx) = unbounded();

        let start = StartRequestMessage {
            headers: headers,
            body: body,
            resp_tx: resp_tx,
        };

        if let Err(_) = self.start_request_with_resp_sender(start) {
            return Response::err(error::Error::Other("client died"));
        }

        let req_rx = resp_rx.map_err(|()| Error::from(io::Error::new(io::ErrorKind::Other, "req")));

        let req_rx = stream_with_eof_and_error(req_rx, || error::Error::Other("client is likely died"));

        Response::from_stream(req_rx)
    }
}

impl ClientCommandLoop {
    fn process_dump_state(self, sender: oneshot::Sender<ConnectionStateSnapshot>) -> HttpFuture<Self> {
        // ignore send error, client might be already dead
        drop(sender.send(self.inner.with(|inner| inner.dump_state())));
        Box::new(future::finished(self))
    }

    fn process_message(self, message: ClientCommandMessage) -> HttpFuture<Self> {
        match message {
            ClientCommandMessage::DumpState(sender) => self.process_dump_state(sender),
            ClientCommandMessage::WaitForHandshake(tx) => {
                // ignore error
                drop(tx.send(Ok(())));
                Box::new(future::ok(self))
            },
        }
    }

    fn run(self, requests: HttpFutureStreamSend<ClientCommandMessage>) -> HttpFuture<()> {
        let requests = requests.map_err(Error::from);
        Box::new(requests
            .fold(self, move |l, message: ClientCommandMessage| {
                l.process_message(message)
            })
            .map(|_| ()))
    }
}
<|endoftext|>


<commit_before>//! JIT Compiler to generate code fragments in runtime.

#![feature(libc)]
extern crate libc;
extern crate llvm;

extern crate common;

use std::borrow::Borrow;
use std::marker::PhantomData;

use llvm::*;

use common::err::{Void, void_ok};

pub struct JitCompiler<'a>
{
  ctx   : CBox<Context>,
  module: Option<CSemiBox<'a, Module>>,
  ee    : Option<JitEngine<'a>>,

  _marker: PhantomData<&'a ()>
}

struct JitCompilerBuilder<'a>
{
  ctx   : CBox<Context>,
  module: Option<CSemiBox<'a, Module>>,
  ee    : Option<JitEngine<'a>>,
  _marker: PhantomData<&'a ()>
}

impl<'a> JitCompilerBuilder<'a>
{
  pub fn init_module(&'a mut self, name: &str) -> &'a mut JitCompilerBuilder
  {
    self.module = Some(Module::new(name, self.ctx.borrow()));
    self.ee     = Some(JitEngine::new((self.module.as_ref()).unwrap(), JitOptions {opt_level: 0}).unwrap());

    self
  }
}

/*
impl<'a> JitCompiler<'a>
{
  pub fn new() -> JitCompilerBuilder<'a>
  {
    JitCompiler {
      ctx    : Context::new(),
      module : None,
      ee     : None,

      _marker: PhantomData
    }
  }

  pub fn load_from_bitcode(&'a mut self, path: &str) -> Void
  {
    self.module = Some(Module::parse_bitcode(self.ctx.borrow(), path)
      .expect(&format!("loading {} failed...", path)));
    self.ee     = Some(JitEngine::new((self.module.as_ref()).unwrap(), JitOptions {opt_level: 0}).unwrap());

    void_ok
  }
}
*/<commit_msg>Add Builders for JitCompilers.<commit_after>//! JIT Compiler to generate code fragments in runtime.

#![feature(libc)]
extern crate libc;
extern crate llvm;

extern crate common;

use std::borrow::Borrow;
use std::marker::PhantomData;

use llvm::*;

use common::err::{Void, void_ok};

pub const JIT_OPT_LVEL: usize = 2;

pub struct JitCompiler<'a>
{
  ctx   : Option<CBox<Context>>,
  module: Option<CSemiBox<'a, Module>>,
  ee    : Option<JitEngine<'a>>,

  _marker: PhantomData<&'a ()>
}

impl<'a> JitCompiler<'a>
{
  pub fn new() -> JitCompiler<'a>
  {
    JitCompiler {
      ctx    : Some(Context::new()),
      module : None,
      ee     : None,

      _marker: PhantomData
    }
  }

  pub fn init_module(&'a mut self) -> Void
  {
    self.module = Some(Module::new("xxx", self.ctx.as_ref().unwrap()));
    self.ee     = Some(JitEngine::new((self.module.as_ref()).unwrap(), JitOptions {opt_level: JIT_OPT_LVEL}).unwrap());

    void_ok
  }

  pub fn load_from_bitcode(&'a mut self, path: &str) -> Void
  {
    self.module = Some(Module::parse_bitcode(self.ctx.as_ref().unwrap(), path)
      .expect(&format!("loading {} failed...", path)));
    self.ee     = Some(JitEngine::new((self.module.as_ref()).unwrap(), JitOptions {opt_level: JIT_OPT_LVEL}).unwrap());

    void_ok
  }
}

pub struct JitCompilerBuilder<'a>
{
  ctx: &'a Context
}

impl<'a> JitCompilerBuilder<'a>
{
  pub fn new(ctx: &'a Context) -> JitCompilerBuilder<'a>
  {
    JitCompilerBuilder {
      ctx: ctx
    }
  }

  pub fn new_module(&'a self, name: &str) -> ModuleBuilder<'a>
  {
    ModuleBuilder {
      ctx: self.ctx,
      module: Module::new(name, self.ctx)
    }
  }

  pub fn from_bitcode(&'a mut self, path: &str) -> ModuleBuilder<'a>
  {
    ModuleBuilder {
      ctx: self.ctx,
      module: Module::parse_bitcode(self.ctx, path)
                .expect(&format!("loading bitcode at '{}' failed...", path))
    }
  }

  pub fn from_ir(&'a mut self, path: &str) -> ModuleBuilder<'a>
  {
    ModuleBuilder {
      ctx: self.ctx,
      module: Module::parse_ir(self.ctx, path)
                .expect(&format!("loading IR at '{}' failed...", path))
    }
  }
}

pub struct ModuleBuilder<'a>
{
  ctx: &'a Context,
  module: CSemiBox<'a, Module>
}

<|endoftext|>


<commit_before>use std::convert::From;
use std::error::Error;
use std::result;
use std::fmt;
use snap;
use lz4_compress as lz4;

type Result<T> = result::Result<T, CompressionError>;

pub const LZ4: &'static str = "lz4";
pub const SNAPPY: &'static str = "snappy";

/// It's an error which may occure during encoding or deconding
/// frame body. As there are only two types of compressors it
/// contains two related enum options.
#[derive(Debug)]
pub enum CompressionError {
    /// Snappy error.
    Snappy(Box<Error>),
    /// Lz4 error.
    Lz4(String),
}

impl fmt::Display for CompressionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CompressionError::Snappy(ref err) => write!(f, "Snappy Error: {:?}", err),
            &CompressionError::Lz4(ref s) => write!(f, "Lz4 Error: {:?}", s),
        }
    }
}

impl Error for CompressionError {
    fn description(&self) -> &str {
        let desc = match self {
            &CompressionError::Snappy(ref err) => err.description(),
            &CompressionError::Lz4(ref s) => s.as_str(),
        };

        return desc;
    }
}

/// Compressor trait that defines functionality
/// which should be provided by typical compressor.
pub trait Compressor {
    /// Encodes given bytes and returns `Result` that contains either
    /// encoded data or an error which occures during the transformation.
    fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Encodes given encoded data and returns `Result` that contains either
    /// encoded bytes or an error which occures during the transformation.
    fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Returns a string which is a name of a compressor. This name should be
    /// exactly the same as one which returns a server in a response to
    /// `Options` request.
    fn into_string(&self) -> Option<String>;
}

/// Enum which represents a type of compression. Only non-startup frame's body can be compressen.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Compression {
    /// [lz4](https://code.google.com/p/lz4/) compression
    Lz4,
    /// [snappy](https://code.google.com/p/snappy/) compression
    Snappy,
    /// Non compression
    None,
}

impl Compression {
    /// It encodes `bytes` basing on type of `Compression`..
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///
    ///   let snappy_compression = Compression::Snappy;
    ///   let bytes = String::from("Hello World").into_bytes().to_vec();
    ///   let encoded = snappy_compression.encode(bytes.clone()).unwrap();
    ///   assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    ///
    /// ```
    pub fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        return match self {
            &Compression::Lz4 => Compression::encode_lz4(bytes),
            &Compression::Snappy => Compression::encode_snappy(bytes),
            &Compression::None => Ok(bytes),
        };
    }

    /// It decodes `bytes` basing on type of compression.
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///     let lz4_compression = Compression::Lz4;
    ///     let bytes = String::from("Hello World").into_bytes().to_vec();
    ///     let encoded = lz4_compression.encode(bytes.clone()).unwrap();
    ///     let len = encoded.len() as u8;
    ///     let mut input = vec![0, 0, 0, len];
    ///     input.extend_from_slice(encoded.as_slice());
    ///     assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    /// ```
    pub fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        return match self {
            &Compression::Lz4 => Compression::decode_lz4(bytes),
            &Compression::Snappy => Compression::decode_snappy(bytes),
            &Compression::None => Ok(bytes),
        };
    }

    /// It transforms compression method into a `&str`.
    pub fn as_str(&self) -> Option<&'static str> {
        return match self {
            &Compression::Lz4 => Some(LZ4),
            &Compression::Snappy => Some(SNAPPY),
            &Compression::None => None,
        };
    }

    fn encode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut encoder = snap::Encoder::new();
        return encoder.compress_vec(bytes.as_slice())
            .map_err(|err| CompressionError::Snappy(Box::new(err)));
    }

    fn decode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = snap::Decoder::new();
        return decoder.decompress_vec(bytes.as_slice())
            .map_err(|err| CompressionError::Snappy(Box::new(err)));
    }

    fn encode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        return Ok(lz4::compress(bytes.as_slice()));
    }

    fn decode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        // skip first 4 bytes in accordance to
        // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L805
        return lz4::decompress(&bytes[4..])
            .map_err(|err| CompressionError::Lz4(err.description().to_string()));
    }
}

impl From<String> for Compression {
    /// It converts `String` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_string: String) -> Compression {
        return Compression::from(compression_string.as_str());
    }
}

impl<'a> From<&'a str> for Compression {
    /// It converts `str` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_str: &'a str) -> Compression {
        return match compression_str {
            LZ4 => Compression::Lz4,
            SNAPPY => Compression::Snappy,
            _ => Compression::None,
        };
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_compression_from_str() {
        let lz4 = "lz4";
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy";
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x";
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_from_string() {
        let lz4 = "lz4".to_string();
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy".to_string();
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x".to_string();
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_encode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression.encode(bytes.clone()).expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = snappy_compression.encode(bytes.clone()).unwrap();
        assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4() {
        let snappy_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression.encode(bytes.clone()).expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_lz4() {
        let lz4_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let len = encoded.len() as u8;
        let mut input = vec![0, 0, 0, len];
        input.extend_from_slice(encoded.as_slice());
        assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        none_compression.encode(bytes.clone()).expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = none_compression.encode(bytes.clone()).unwrap();
        assert_eq!(none_compression.decode(encoded).unwrap(), bytes);
    }

}
<commit_msg>added test case for error<commit_after>use std::convert::From;
use std::error::Error;
use std::result;
use std::fmt;
use snap;
use lz4_compress as lz4;

type Result<T> = result::Result<T, CompressionError>;

pub const LZ4: &'static str = "lz4";
pub const SNAPPY: &'static str = "snappy";

/// It's an error which may occure during encoding or deconding
/// frame body. As there are only two types of compressors it
/// contains two related enum options.
#[derive(Debug)]
pub enum CompressionError {
    /// Snappy error.
    Snappy(Box<Error>),
    /// Lz4 error.
    Lz4(String),
}

impl fmt::Display for CompressionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CompressionError::Snappy(ref err) => write!(f, "Snappy Error: {:?}", err),
            &CompressionError::Lz4(ref s) => write!(f, "Lz4 Error: {:?}", s),
        }
    }
}

impl Error for CompressionError {
    fn description(&self) -> &str {
        let desc = match self {
            &CompressionError::Snappy(ref err) => err.description(),
            &CompressionError::Lz4(ref s) => s.as_str(),
        };

        return desc;
    }
}

/// Compressor trait that defines functionality
/// which should be provided by typical compressor.
pub trait Compressor {
    /// Encodes given bytes and returns `Result` that contains either
    /// encoded data or an error which occures during the transformation.
    fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Encodes given encoded data and returns `Result` that contains either
    /// encoded bytes or an error which occures during the transformation.
    fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Returns a string which is a name of a compressor. This name should be
    /// exactly the same as one which returns a server in a response to
    /// `Options` request.
    fn into_string(&self) -> Option<String>;
}

/// Enum which represents a type of compression. Only non-startup frame's body can be compressen.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Compression {
    /// [lz4](https://code.google.com/p/lz4/) compression
    Lz4,
    /// [snappy](https://code.google.com/p/snappy/) compression
    Snappy,
    /// Non compression
    None,
}

impl Compression {
    /// It encodes `bytes` basing on type of `Compression`..
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///
    ///   let snappy_compression = Compression::Snappy;
    ///   let bytes = String::from("Hello World").into_bytes().to_vec();
    ///   let encoded = snappy_compression.encode(bytes.clone()).unwrap();
    ///   assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    ///
    /// ```
    pub fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        return match self {
            &Compression::Lz4 => Compression::encode_lz4(bytes),
            &Compression::Snappy => Compression::encode_snappy(bytes),
            &Compression::None => Ok(bytes),
        };
    }

    /// It decodes `bytes` basing on type of compression.
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///     let lz4_compression = Compression::Lz4;
    ///     let bytes = String::from("Hello World").into_bytes().to_vec();
    ///     let encoded = lz4_compression.encode(bytes.clone()).unwrap();
    ///     let len = encoded.len() as u8;
    ///     let mut input = vec![0, 0, 0, len];
    ///     input.extend_from_slice(encoded.as_slice());
    ///     assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    /// ```
    pub fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        return match self {
            &Compression::Lz4 => Compression::decode_lz4(bytes),
            &Compression::Snappy => Compression::decode_snappy(bytes),
            &Compression::None => Ok(bytes),
        };
    }

    /// It transforms compression method into a `&str`.
    pub fn as_str(&self) -> Option<&'static str> {
        return match self {
            &Compression::Lz4 => Some(LZ4),
            &Compression::Snappy => Some(SNAPPY),
            &Compression::None => None,
        };
    }

    fn encode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut encoder = snap::Encoder::new();
        return encoder.compress_vec(bytes.as_slice())
            .map_err(|err| CompressionError::Snappy(Box::new(err)));
    }

    fn decode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = snap::Decoder::new();
        return decoder.decompress_vec(bytes.as_slice())
            .map_err(|err| CompressionError::Snappy(Box::new(err)));
    }

    fn encode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        return Ok(lz4::compress(bytes.as_slice()));
    }

    fn decode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        // skip first 4 bytes in accordance to
        // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L805
        return lz4::decompress(&bytes[4..])
            .map_err(|err| CompressionError::Lz4(err.description().to_string()));
    }
}

impl From<String> for Compression {
    /// It converts `String` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_string: String) -> Compression {
        return Compression::from(compression_string.as_str());
    }
}

impl<'a> From<&'a str> for Compression {
    /// It converts `str` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_str: &'a str) -> Compression {
        return match compression_str {
            LZ4 => Compression::Lz4,
            SNAPPY => Compression::Snappy,
            _ => Compression::None,
        };
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_compression_from_str() {
        let lz4 = "lz4";
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy";
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x";
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_from_string() {
        let lz4 = "lz4".to_string();
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy".to_string();
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x".to_string();
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_encode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression.encode(bytes.clone()).expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = snappy_compression.encode(bytes.clone()).unwrap();
        assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4() {
        let snappy_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression.encode(bytes.clone()).expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_lz4() {
        let lz4_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let len = encoded.len() as u8;
        let mut input = vec![0, 0, 0, len];
        input.extend_from_slice(encoded.as_slice());
        assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        none_compression.encode(bytes.clone()).expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = none_compression.encode(bytes.clone()).unwrap();
        assert_eq!(none_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_snappy_with_non_utf8() {
        let lz4_compression = Compression::Lz4;
        let bytes: Vec<u8> = vec![0x7f,0x7f,0x7f,0x7f,0x7f];
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let decode = lz4_compression.decode(encoded);
        assert_eq!(decode.is_err(),true);
    }

}
<|endoftext|>


<commit_before>use core::mapped_file::MappedFile;
use core::mapped_file::FileHandle;

//
pub type Id = u64;
pub type Offset = u64;
pub type PageSize = usize;

//
#[derive(Debug)]
pub enum OpenMode {
    ReadOnly = 0,
    ReadWrite = 1,
}

/// The **Buffer** represents a linear array of bytes.

/// it can be in memory only or backed by an on disk file.

/// The editor will **Modes** use this api to read/modify the content
/// of the file at the byte level
#[derive(Debug)]
pub struct Buffer<'a> {
    pub id: Id,
    /// the name of the file where the data will be synced
    pub file_name: String,
    /// the current size of the buffer
    pub size: usize,
    /// the number of changes (since last save TODO)
    pub nr_changes: u64,
    mode: OpenMode,
    pub data: FileHandle<'a>,
}

impl<'a> Buffer<'a> {
    /// Creates a new `Buffer`.
    ///
    /// file_name param[in] path to the file we want to load in the buffer,
    /// use "/dev/null" to create empty buffer
    /// this function allocate a buffer
    /// if file_name is null the content will be stored in heap
    /// if file_name is non null the the content will be read from the file
    /// if document_name is null , file_name will be used to give a name to the buffer
    /// mode = 0 : read only , mode 1 : read_write
    /// the allocated_bid pointer will be filled on successfull open operation
    pub fn new(file_name: String, mode: OpenMode) -> Option<Buffer<'a>> {
        // TODO: check permission
        // TODO: check file's type => ignore directory (for now)
        println!("-- mapping file {}", file_name);

        let page_size = 4096 * 256 * 2;
        let file = match MappedFile::new(file_name.clone(), page_size) {
            Some(file) => file,
            None => {
                eprintln!("cannot map file '{}'", file_name);
                return None;
            }
        };

        let size = file.as_ref().borrow().size() as usize;

        println!("'{}' opened size '{}'", file_name, size);

        Some(Buffer {
            id: 0,
            file_name: file_name.clone(),
            mode,
            size,
            nr_changes: 0,
            data: file,
        })
    }

    /// not implemented: close a previously opened buffer see buffer_open
    pub fn close(&mut self) -> bool {
        unimplemented!();
        // false
    }

    /// returns the name of the file associated to the buffer
    pub fn get_file_name(&self) -> String {
        self.file_name.clone()
    }

    /// change the on disk target file
    pub fn set_file_name(&mut self, name: String) -> bool {
        self.file_name = name;
        true
    }

    /// returns the number of bytes a given buffer contains
    pub fn size(&self) -> usize {
        self.size
    }

    /// returns the number of changes sine the last save

    ///     0  => the no change since last save

    ///     >0 => the number of changes since last save

    pub fn nr_changes(&self) -> u64 {
        self.nr_changes
    }

    /// copy the content of the buffer up to 'nr_bytes' into the data Vec
    /// the read bytes are appended to the data Vec
    /// return XXX on error (use ioresult)
    pub fn read(&self, offset: u64, nr_bytes: usize, mut data: &mut Vec<u8>) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::read(&mut it, nr_bytes, &mut data)
    }

    /// insert the 'data' Vec content in the buffer up to 'nr_bytes'
    /// return the number of written bytes (TODO: use io::Result)
    pub fn insert(&mut self, offset: u64, nr_bytes: usize, data: &[u8]) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::insert(&mut it, &data);

        self.size += nr_bytes;
        self.nr_changes += 1;

        nr_bytes
    }

    /// remove up to 'nr_bytes' from the buffer starting at offset
    /// if removed_data is provided will call self.read(offset, nr_bytes, data)
    /// before remove the bytes
    pub fn remove(
        &mut self,
        offset: u64,
        nr_bytes: usize,
        removed_data: Option<&mut Vec<u8>>,
    ) -> usize {
        let start_offset = ::std::cmp::min(offset as usize, self.size);
        let end_offset = ::std::cmp::min(start_offset + nr_bytes, self.size);
        let nr_bytes_removed = (end_offset - start_offset) as usize;

        // copy removed data
        if let Some(v) = removed_data {
            self.read(offset, nr_bytes_removed, v);
        }

        let mut it = MappedFile::iter_from(&self.data, start_offset as u64);
        MappedFile::remove(&mut it, nr_bytes_removed);

        self.size -= nr_bytes_removed;
        self.nr_changes += 1;

        nr_bytes_removed
    }

    /// can be used to know the number of blocks that compose the buffer,
    /// api to be used by indexer etc...
    pub fn nr_pages(&self) -> u64 {
        1
    }

    /*
    /// returns the position and size of a given page
    pub fn get_page_info(&self, page_index: u64) -> (Offset, PageSize) {
        // if page_index > 0 {
        //    (0, self.size)
        // } else {
        //    (0, self.size)
        // }
        (0, self.size)
    }
*/

    //
    // TODO: This is currently broken, because fd swapping is not implemented yet in mapped_file
    //
    //
    pub fn sync_to_disk(&self, tmp_file_name: &str) -> ::std::io::Result<()> {
        MappedFile::sync_to_disk(
            &mut self.data.as_ref().borrow_mut(),
            &tmp_file_name,
            &self.file_name,
        )
    }
}

#[test]
fn test_buffer() {
    let mut bb = Buffer::new("/dev/null".to_owned(), OpenMode::ReadWrite).unwrap();

    let data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    bb.insert(0, 10, &data);
    let mut rdata = Vec::new();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);
    assert_eq!(nread, bb.size());

    let data = vec![0, 1, 2, 6, 7, 8, 9];
    let rm_expect = vec![3, 4, 5];

    let mut rm = vec![];
    let n = bb.remove(3, 3, Some(&mut rm));
    assert_eq!(n, 3);
    assert_eq!(rm, rm_expect);

    rdata.clear();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);
    assert_eq!(nread, bb.size());

    println!("rm {:?}", rm);
    println!("rm_expect {:?}", rm_expect);
}
<commit_msg>restore permission on save<commit_after>use core::mapped_file::MappedFile;
use core::mapped_file::FileHandle;

//
pub type Id = u64;
pub type Offset = u64;
pub type PageSize = usize;

//
#[derive(Debug)]
pub enum OpenMode {
    ReadOnly = 0,
    ReadWrite = 1,
}

/// The **Buffer** represents a linear array of bytes.

/// it can be in memory only or backed by an on disk file.

/// The editor will **Modes** use this api to read/modify the content
/// of the file at the byte level
#[derive(Debug)]
pub struct Buffer<'a> {
    pub id: Id,
    /// the name of the file where the data will be synced
    pub file_name: String,
    /// the current size of the buffer
    pub size: usize,
    /// the number of changes (since last save TODO)
    pub nr_changes: u64,
    mode: OpenMode,
    pub data: FileHandle<'a>,
}

impl<'a> Buffer<'a> {
    /// Creates a new `Buffer`.
    ///
    /// file_name param[in] path to the file we want to load in the buffer,
    /// use "/dev/null" to create empty buffer
    /// this function allocate a buffer
    /// if file_name is null the content will be stored in heap
    /// if file_name is non null the the content will be read from the file
    /// if document_name is null , file_name will be used to give a name to the buffer
    /// mode = 0 : read only , mode 1 : read_write
    /// the allocated_bid pointer will be filled on successfull open operation
    pub fn new(file_name: String, mode: OpenMode) -> Option<Buffer<'a>> {
        // TODO: check permission
        // TODO: check file's type => ignore directory (for now)
        println!("-- mapping file {}", file_name);

        let page_size = 4096 * 256 * 2;
        let file = match MappedFile::new(file_name.clone(), page_size) {
            Some(file) => file,
            None => {
                eprintln!("cannot map file '{}'", file_name);
                return None;
            }
        };

        let size = file.as_ref().borrow().size() as usize;

        println!("'{}' opened size '{}'", file_name, size);

        Some(Buffer {
            id: 0,
            file_name: file_name.clone(),
            mode,
            size,
            nr_changes: 0,
            data: file,
        })
    }

    /// not implemented: close a previously opened buffer see buffer_open
    pub fn close(&mut self) -> bool {
        unimplemented!();
        // false
    }

    /// returns the name of the file associated to the buffer
    pub fn get_file_name(&self) -> String {
        self.file_name.clone()
    }

    /// change the on disk target file
    pub fn set_file_name(&mut self, name: String) -> bool {
        self.file_name = name;
        true
    }

    /// returns the number of bytes a given buffer contains
    pub fn size(&self) -> usize {
        self.size
    }

    /// returns the number of changes sine the last save

    ///     0  => the no change since last save

    ///     >0 => the number of changes since last save

    pub fn nr_changes(&self) -> u64 {
        self.nr_changes
    }

    /// copy the content of the buffer up to 'nr_bytes' into the data Vec
    /// the read bytes are appended to the data Vec
    /// return XXX on error (use ioresult)
    pub fn read(&self, offset: u64, nr_bytes: usize, mut data: &mut Vec<u8>) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::read(&mut it, nr_bytes, &mut data)
    }

    /// insert the 'data' Vec content in the buffer up to 'nr_bytes'
    /// return the number of written bytes (TODO: use io::Result)
    pub fn insert(&mut self, offset: u64, nr_bytes: usize, data: &[u8]) -> usize {
        let mut it = MappedFile::iter_from(&self.data, offset);
        MappedFile::insert(&mut it, &data);

        self.size += nr_bytes;
        self.nr_changes += 1;

        nr_bytes
    }

    /// remove up to 'nr_bytes' from the buffer starting at offset
    /// if removed_data is provided will call self.read(offset, nr_bytes, data)
    /// before remove the bytes
    pub fn remove(
        &mut self,
        offset: u64,
        nr_bytes: usize,
        removed_data: Option<&mut Vec<u8>>,
    ) -> usize {
        let start_offset = ::std::cmp::min(offset as usize, self.size);
        let end_offset = ::std::cmp::min(start_offset + nr_bytes, self.size);
        let nr_bytes_removed = (end_offset - start_offset) as usize;

        // copy removed data
        if let Some(v) = removed_data {
            self.read(offset, nr_bytes_removed, v);
        }

        let mut it = MappedFile::iter_from(&self.data, start_offset as u64);
        MappedFile::remove(&mut it, nr_bytes_removed);

        self.size -= nr_bytes_removed;
        self.nr_changes += 1;

        nr_bytes_removed
    }

    /// can be used to know the number of blocks that compose the buffer,
    /// api to be used by indexer etc...
    pub fn nr_pages(&self) -> u64 {
        1
    }

    /*
    /// returns the position and size of a given page
    pub fn get_page_info(&self, page_index: u64) -> (Offset, PageSize) {
        // if page_index > 0 {
        //    (0, self.size)
        // } else {
        //    (0, self.size)
        // }
        (0, self.size)
    }
*/

    //
    // TODO: This is currently broken, because fd swapping is not implemented yet in mapped_file
    //
    //
    pub fn sync_to_disk(&self, tmp_file_name: &str) -> ::std::io::Result<()> {
        let metadata = ::std::fs::metadata(&self.file_name).unwrap();
        let perms = metadata.permissions();

        let res = MappedFile::sync_to_disk(
            &mut self.data.as_ref().borrow_mut(),
            &tmp_file_name,
            &self.file_name,
        );

        // TODO: check result, handle io results properly
        ::std::fs::set_permissions(&self.file_name, perms).unwrap();

        res
    }
}

#[test]
fn test_buffer() {
    let mut bb = Buffer::new("/dev/null".to_owned(), OpenMode::ReadWrite).unwrap();

    let data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    bb.insert(0, 10, &data);
    let mut rdata = Vec::new();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);
    assert_eq!(nread, bb.size());

    let data = vec![0, 1, 2, 6, 7, 8, 9];
    let rm_expect = vec![3, 4, 5];

    let mut rm = vec![];
    let n = bb.remove(3, 3, Some(&mut rm));
    assert_eq!(n, 3);
    assert_eq!(rm, rm_expect);

    rdata.clear();
    let nread = bb.read(0, bb.size(), &mut rdata);
    assert_eq!(rdata, data);
    assert_eq!(nread, bb.size());

    println!("rm {:?}", rm);
    println!("rm_expect {:?}", rm_expect);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

// https://leetcode.com/problems/operations-on-tree/
struct LockingTree {
    tree: HashMap<i32, Vec<i32>>,
    locks: HashMap<i32, i32>,
}

/**
 * `&self` means the method takes an immutable reference
 * If you need a mutable reference, change it to `&mut self` instead.
 */
impl LockingTree {
    fn new(parent: Vec<i32>) -> Self {
        let mut tree = HashMap::new();
        for (num, parent) in parent.into_iter().enumerate() {
            let children = tree.entry(parent).or_insert(vec![]);
            (*children).push(num as i32);
        }
        LockingTree {
            tree,
            locks: HashMap::new(),
        }
    }

    fn lock(&mut self, num: i32, user: i32) -> bool {
        match self.locks.get(&num) {
            Some(_) => false,
            None => {
                self.locks.insert(num, user);
                true
            }
        }
    }

    fn unlock(&mut self, num: i32, user: i32) -> bool {
        match self.locks.get(&num) {
            Some(u) => {
                if user != *u {
                    return false;
                }
                self.locks.remove(&num);
                true
            }
            None => false,
        }
    }

    fn upgrade(&mut self, num: i32, user: i32) -> bool {
        fn has_locked_ancestor(
            tree: &HashMap<i32, Vec<i32>>,
            locks: &HashMap<i32, i32>,
            num_target: i32,
            num: i32,
            locked: bool,
        ) -> bool {
            if num == num_target {
                return locked;
            }
            let mut has_locked = match locks.get(&num) {
                Some(_) => true && !tree.get(&num).is_none(),
                None => false,
            };
            for child in tree.get(&num).unwrap_or(&vec![]).iter() {
                has_locked |= has_locked_ancestor(tree, locks, num_target, *child, has_locked);
            }
            has_locked
        }

        fn has_locked_descendent(
            tree: &HashMap<i32, Vec<i32>>,
            locks: &mut HashMap<i32, i32>,
            num: i32,
        ) -> bool {
            let mut has_locked = match locks.get(&num) {
                Some(_) => {
                    locks.remove(&num);
                    true
                }
                None => false,
            };
            for child in tree.get(&num).unwrap_or(&vec![]).iter() {
                has_locked |= has_locked_descendent(tree, locks, *child);
            }
            has_locked
        }

        match self.locks.get(&num) {
            Some(_) => false,
            None => {
                if has_locked_ancestor(&self.tree, &self.locks, num, 0, false) {
                    return false;
                }
                if !has_locked_descendent(&self.tree, &mut self.locks, num) {
                    return false;
                }
                self.locks.insert(num, user);
                true
            }
        }
    }
}

fn main() {
    let mut tree = LockingTree::new(vec![-1, 0, 0, 1, 1, 2, 2]);
    println!("{}", tree.lock(2, 2)); // true
    println!("{}", tree.unlock(2, 3)); // false
    println!("{}", tree.unlock(2, 2)); // true
    println!("{}", tree.lock(4, 5)); // true
    println!("{}", tree.lock(2, 3)); // true
    println!("{}", tree.upgrade(0, 1)); // true
    println!("{}", tree.lock(0, 1)); // false
    println!("{}", tree.unlock(0, 1)); // true
    println!("{}", tree.upgrade(3, 1)); // false
}
<commit_msg>Solve problem 1993<commit_after>use std::collections::HashMap;

// https://leetcode.com/problems/operatigions-on-tree/
struct LockingTree {
    parent_to_children: HashMap<i32, Vec<i32>>,
    child_to_parent: HashMap<i32, i32>,
    locks: HashMap<i32, i32>,
}

/**
 * `&self` means the method takes an immutable reference
 * If you need a mutable reference, change it to `&mut self` instead.
 */
impl LockingTree {
    fn new(parent: Vec<i32>) -> Self {
        let mut parent_to_children = HashMap::new();
        let mut child_to_parent = HashMap::new();
        for (num, parent) in parent.into_iter().enumerate() {
            let children = parent_to_children.entry(parent).or_insert(vec![]);
            (*children).push(num as i32);
            child_to_parent.insert(num as i32, parent);
        }
        LockingTree {
            parent_to_children,
            child_to_parent,
            locks: HashMap::new(),
        }
    }

    fn lock(&mut self, num: i32, user: i32) -> bool {
        match self.locks.get(&num) {
            Some(_) => false,
            None => {
                self.locks.insert(num, user);
                true
            }
        }
    }

    fn unlock(&mut self, num: i32, user: i32) -> bool {
        match self.locks.get(&num) {
            Some(u) => {
                if user != *u {
                    return false;
                }
                self.locks.remove(&num);
                true
            }
            None => false,
        }
    }

    fn upgrade(&mut self, num: i32, user: i32) -> bool {
        fn has_locked_ancestor(
            child_to_parent: &HashMap<i32, i32>,
            locks: &HashMap<i32, i32>,
            num: i32,
        ) -> bool {
            let mut parent = child_to_parent.get(&num);
            while let Some(p) = parent {
                if locks.get(p).is_some() {
                    return true;
                }
                parent = child_to_parent.get(p);
            }
            false
        }

        fn has_locked_descendent(
            parent_to_children: &HashMap<i32, Vec<i32>>,
            locks: &mut HashMap<i32, i32>,
            num: i32,
        ) -> bool {
            let mut has_locked = match locks.get(&num) {
                Some(_) => {
                    locks.remove(&num);
                    true
                }
                None => false,
            };
            for child in parent_to_children.get(&num).unwrap_or(&vec![]).iter() {
                has_locked |= has_locked_descendent(parent_to_children, locks, *child);
            }
            has_locked
        }

        match self.locks.get(&num) {
            Some(_) => false,
            None => {
                if has_locked_ancestor(&self.child_to_parent, &self.locks, num) {
                    return false;
                }
                if !has_locked_descendent(&self.parent_to_children, &mut self.locks, num) {
                    return false;
                }
                self.locks.insert(num, user);
                true
            }
        }
    }
}

fn main() {
    let mut tree = LockingTree::new(vec![-1, 0, 0, 1, 1, 2, 2]);
    println!("{}", tree.lock(2, 2)); // true
    println!("{}", tree.unlock(2, 3)); // false
    println!("{}", tree.unlock(2, 2)); // true
    println!("{}", tree.lock(4, 5)); // true
    println!("{}", tree.lock(2, 3)); // true
    println!("{}", tree.upgrade(0, 1)); // true
    println!("{}", tree.lock(0, 1)); // false
    println!("{}", tree.unlock(0, 1)); // true
    println!("{}", tree.upgrade(3, 1)); // false
}
<|endoftext|>


<commit_before>use util::errors::{
    Result,
    Error,
};

use term::terminfo::TermInfo;
use term::terminfo::parm;
use term::terminfo::parm::{
    Param,
    Variables,
};

// String constants correspond to terminfo capnames and are used inside the module for convenience.
const ENTER_CA: &'static str = "smcup";
const EXIT_CA: &'static str = "rmcup";
const SHOW_CURSOR: &'static str = "cnorm";
const HIDE_CURSOR: &'static str = "civis";
const SET_CURSOR: &'static str = "cup";
const CLEAR: &'static str = "clear";
const RESET: &'static str = "sgr0";
const UNDERLINE: &'static str = "smul";
const BOLD: &'static str = "bold";
const BLINK: &'static str = "blink";
const REVERSE: &'static str = "rev";
const SETFG: &'static str = "setaf";
const SETBG: &'static str = "setab";

// Array of terminal capabilities. Used as an iterator to test for functionality.
//
// At the moment all functionality is required, however in the future we should implement optional
// functionality checks so the absence of underlining or reverse video doesn't cause initialization
// to fail.
static CAPABILITIES: &'static [&'static str] = &[
    ENTER_CA,
    EXIT_CA,
    SHOW_CURSOR,
    HIDE_CURSOR,
    SET_CURSOR,
    CLEAR,
    RESET,
    UNDERLINE,
    BOLD,
    REVERSE,
    SETFG,
    SETBG,
];

// Driver capabilities are an enum instead of string constants (there are string constants private
// to the module however, those are only used for naming convenience and disambiguation)
// to take advantage of compile-time type-checking instead of hoping invalid strings aren't passed.
// This allows us to guarantee that driver accesses will succeed. In addition, using an enum means
// Driver doesn't need hard-coded methods for each capability we want to use.
#[allow(dead_code)]
pub enum DevFn {
    EnterCa,
    ExitCa,
    ShowCursor,
    HideCursor,
    SetCursor(usize, usize),
    Clear,
    Reset,
    Underline,
    Bold,
    Blink,
    Reverse,
    SetFg(u8),
    SetBg(u8),
}

impl DevFn {
    fn as_str(&self) -> &'static str {
        match *self {
            DevFn::EnterCa => ENTER_CA,
            DevFn::ExitCa => EXIT_CA,
            DevFn::ShowCursor => SHOW_CURSOR,
            DevFn::HideCursor => HIDE_CURSOR,
            DevFn::SetCursor(..) => SET_CURSOR,
            DevFn::Clear => CLEAR,
            DevFn::Reset => RESET,
            DevFn::Underline => UNDERLINE,
            DevFn::Bold => BOLD,
            DevFn::Blink => BLINK,
            DevFn::Reverse => REVERSE,
            DevFn::SetFg(..) => SETFG,
            DevFn::SetBg(..) => SETBG,
        }
    }
}

pub struct Driver {
    tinfo: &'static TermInfo,
}

lazy_static! {
    static ref TINFO: TermInfo = {
        TermInfo::from_env().unwrap_or({
            TermInfo {
                names: Default::default(),
                bools: Default::default(),
                numbers: Default::default(),
                strings: Default::default(),
            }
        })
    };
}

// Validates and returns a reference to the terminfo database.
//
// If this function returns Ok(..), the contained terminfo database is guaranteed to have the
// functionality found in CAPABILITIES.
//
// If this function returns Err(..), the terminfo database did not contain all the required
// functionality; the error returned will provide more specific detail.
fn get_tinfo() -> Result<&'static TermInfo> {
    let tinfo = &*TINFO;

    for capname in CAPABILITIES {
        if !tinfo.strings.contains_key(*capname) {
            return Err(Error::new(format!("terminal missing capability: '{}'", capname)));
        }
    }
    Ok(tinfo)
}

impl Driver {
    // Creates a new `Driver`
    //
    // If successful, the terminfo database is guaranteed to contain all capabilities we support.
    pub fn new() -> Result<Driver> {
        let tinfo = try!(get_tinfo());
        Ok(Driver {
            tinfo: tinfo,
        })
    }

    // Returns the device specific escape sequence for the given `DevFn`.
    //
    // get() will not return an error, and (in theory) should never panic. The `DevFn` enum
    // restricts possible inputs to a subset that will not fail when passed to `parm::expand()`.
    // This can be verified by examining the source of the `parm::expand()` function in the `term`
    // crate.
    //
    // Furthermore, the pre-flight checks on initialization of `Driver` ensure that every
    // capability is present, thus the call to `Hashmap::get()` should never fail.
    pub fn get(&self, dfn: DevFn) -> Vec<u8> {
        let capname = dfn.as_str();
        let cap = self.tinfo.strings.get(capname).unwrap();

        match dfn {
            DevFn::SetFg(attr) | DevFn::SetBg(attr) => {
                let params = &[Param::Number(attr as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            DevFn::SetCursor(x, y) => {
                let params = &[Param::Number(y as i16), Param::Number(x as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            _ => {
                cap.clone()
            },
        }
    }
}

<commit_msg>add keys to driver<commit_after>use util::errors::{
    Result,
    Error,
};

use term::terminfo::TermInfo;
use term::terminfo::parm;
use term::terminfo::parm::{
    Param,
    Variables,
};

// String constants correspond to terminfo capnames and are used inside the module for convenience.
const ENTER_CA: &'static str = "smcup";
const EXIT_CA: &'static str = "rmcup";
const SHOW_CURSOR: &'static str = "cnorm";
const HIDE_CURSOR: &'static str = "civis";
const SET_CURSOR: &'static str = "cup";
const CLEAR: &'static str = "clear";
const RESET: &'static str = "sgr0";
const UNDERLINE: &'static str = "smul";
const BOLD: &'static str = "bold";
const BLINK: &'static str = "blink";
const REVERSE: &'static str = "rev";
const SETFG: &'static str = "setaf";
const SETBG: &'static str = "setab";

// Terminfo keys. These are arrays because the terminfo database from the `term` crate sometimes
// uses the variable name and othertimes the capname.
//
// Arrays are formatted as ["variable_name", "cap_name"].
const KEY_F1: &'static [&'static str] = &["key_f1", "kf1"];
const KEY_F2: &'static [&'static str] = &["key_f2", "kf2"];
const KEY_F3: &'static [&'static str] = &["key_f3", "kf3"];
const KEY_F4: &'static [&'static str] = &["key_f4", "kf4"];
const KEY_F5: &'static [&'static str] = &["key_f5", "kf5"];
const KEY_F6: &'static [&'static str] = &["key_f6", "kf6"];
const KEY_F7: &'static [&'static str] = &["key_f7", "kf7"];
const KEY_F8: &'static [&'static str] = &["key_f8", "kf8"];
const KEY_F9: &'static [&'static str] = &["key_f9", "kf9"];
const KEY_F10: &'static [&'static str] = &["key_f10", "kf10"];
const KEY_F11: &'static [&'static str] = &["key_f11", "kf11"];
const KEY_F12: &'static [&'static str] = &["key_f12", "kf12"];
const KEY_UP: &'static [&'static str] = &["key_up", "kcuu1"];
const KEY_DOWN: &'static [&'static str] = &["key_down", "kcud1"];
const KEY_LEFT: &'static [&'static str] = &["key_left", "kcub1"];
const KEY_RIGHT: &'static [&'static str] = &["key_right", "kcuf1"];

// Array of terminal keys.
const KEYS: &'static [&'static [&'static str]] = &[
    KEY_F1,
    KEY_F2,
    KEY_F3,
    KEY_F4,
    KEY_F5,
    KEY_F6,
    KEY_F7,
    KEY_F8,
    KEY_F9,
    KEY_F10,
    KEY_F11,
    KEY_F12,
    KEY_UP,
    KEY_DOWN,
    KEY_LEFT,
    KEY_RIGHT,
];

// Array of terminal capabilities. Used as an iterator to test for functionality.
//
// At the moment all functionality is required, however in the future we should implement optional
// functionality checks so the absence of underlining or reverse video doesn't cause initialization
// to fail.
//
// TODO: Optional functionality testing.
const CAPABILITIES: &'static [&'static str] = &[
    ENTER_CA,
    EXIT_CA,
    SHOW_CURSOR,
    HIDE_CURSOR,
    SET_CURSOR,
    CLEAR,
    RESET,
    UNDERLINE,
    BOLD,
    REVERSE,
    SETFG,
    SETBG,
];

// Driver capabilities are an enum instead of string constants (there are string constants private
// to the module however, those are only used for naming convenience and disambiguation)
// to take advantage of compile-time type-checking instead of hoping invalid strings aren't passed.
// This allows us to guarantee that driver accesses will succeed. In addition, using an enum means
// Driver doesn't need hard-coded methods for each capability we want to use.
#[allow(dead_code)]
pub enum DevFn {
    EnterCa,
    ExitCa,
    ShowCursor,
    HideCursor,
    SetCursor(usize, usize),
    Clear,
    Reset,
    Underline,
    Bold,
    Blink,
    Reverse,
    SetFg(u8),
    SetBg(u8),
}

impl DevFn {
    fn as_str(&self) -> &'static str {
        match *self {
            DevFn::EnterCa => ENTER_CA,
            DevFn::ExitCa => EXIT_CA,
            DevFn::ShowCursor => SHOW_CURSOR,
            DevFn::HideCursor => HIDE_CURSOR,
            DevFn::SetCursor(..) => SET_CURSOR,
            DevFn::Clear => CLEAR,
            DevFn::Reset => RESET,
            DevFn::Underline => UNDERLINE,
            DevFn::Bold => BOLD,
            DevFn::Blink => BLINK,
            DevFn::Reverse => REVERSE,
            DevFn::SetFg(..) => SETFG,
            DevFn::SetBg(..) => SETBG,
        }
    }
}

pub struct Driver {
    tinfo: &'static TermInfo,
}

// We will never need to mutate the terminfo database, and it is only used internally as a lookup
// table for the driver. `lazy_static` seems to be the best approach at the moment.
lazy_static! {
    static ref TINFO: TermInfo = {
        TermInfo::from_env().unwrap_or({
            TermInfo {
                names: Default::default(),
                bools: Default::default(),
                numbers: Default::default(),
                strings: Default::default(),
            }
        })
    };
}

// Validates and returns a reference to the terminfo database.
//
// If this function returns Ok(..), the contained terminfo database is guaranteed to have the
// functionality found in CAPABILITIES.
//
// If this function returns Err(..), the terminfo database did not contain all the required
// functionality; the error returned will provide more specific detail.
fn get_tinfo() -> Result<&'static TermInfo> {
    let tinfo = &*TINFO;

    for capname in CAPABILITIES {
        if !tinfo.strings.contains_key(*capname) {
            return Err(Error::new(format!("terminal missing capability: '{}'", capname)));
        }
    }
    Ok(tinfo)
}

impl Driver {
    // Creates a new `Driver`
    //
    // If successful, the terminfo database is guaranteed to contain all capabilities we support.
    pub fn new() -> Result<Driver> {
        let tinfo = try!(get_tinfo());
        Ok(Driver {
            tinfo: tinfo,
        })
    }

    // Returns the device specific escape sequence for the given `DevFn`.
    //
    // get() will not return an error, and (in theory) should never panic. The `DevFn` enum
    // restricts possible inputs to a subset that will not fail when passed to `parm::expand()`.
    // This can be verified by examining the source of the `parm::expand()` function in the `term`
    // crate.
    //
    // Furthermore, the pre-flight checks on initialization of `Driver` ensure that every
    // capability is present, thus the call to `Hashmap::get()` should never fail.
    pub fn get(&self, dfn: DevFn) -> Vec<u8> {
        let capname = dfn.as_str();
        let cap = self.tinfo.strings.get(capname).unwrap();

        match dfn {
            DevFn::SetFg(attr) | DevFn::SetBg(attr) => {
                let params = &[Param::Number(attr as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            DevFn::SetCursor(x, y) => {
                let params = &[Param::Number(y as i16), Param::Number(x as i16)];
                let mut vars = Variables::new();
                parm::expand(cap, params, &mut vars).unwrap()
            },
            _ => {
                cap.clone()
            },
        }
    }
}

<|endoftext|>


<commit_before>use std::cmp::Reverse;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use itertools::Itertools;
use regex::Regex;

use common::Solution;

#[derive(Default, Debug, Eq, PartialEq, Clone)]
struct Group {
    power: u32,
    count: u32,
    hp: u32,
    initiative: i32,
    damage: String,
    weaknesses: Vec<String>,
    immunities: Vec<String>,
    faction: char,
}

impl Group {
    pub fn is_alive(&self) -> bool {
        self.count > 0
    }

    pub fn damage_to(&self, other: &Group) -> u32 {
        let damage = self.effective_power();

        if other.weaknesses.contains(&self.damage) {
            damage * 2
        } else if other.immunities.contains(&self.damage) {
            0
        } else {
            damage
        }
    }

    pub fn effective_power(&self) -> u32 {
        self.power * self.count
    }
}

#[derive(Default)]
pub struct Day24 {
    units: Vec<Group>,
}

impl Day24 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_input(&mut self, input: &mut Read) {
        let matcher = Regex::new(r"(\d+) units each with (\d+) hit points (\(([^)]+)\) )?with an attack that does (\d+) (\w+) damage at initiative (\d+)").unwrap();
        let weakness_matcher = Regex::new(r"(weak|immune) to ([^;)]+)").unwrap();
        let reader = BufReader::new(input);
        let mut fac = 'X';

        for line in reader.lines() {
            let line = line.unwrap();
            match line.as_str() {
                "Immune System:" => { fac = 'D' }
                "" => {}
                "Infection:" => { fac = 'I' }
                line => {
                    let caps = matcher.captures(line).unwrap_or_else(|| {
                        panic!("{}", line);
                    });

                    let mut group = Group {
                        count: caps[1].parse().unwrap(),
                        hp: caps[2].parse().unwrap(),
                        power: caps[5].parse().unwrap(),
                        damage: caps[6].to_string(),
                        initiative: caps[7].parse().unwrap(),
                        faction: fac,
                        ..Default::default()
                    };

                    if let Some(caps) = caps.get(4) {
                        for modified in weakness_matcher.captures_iter(caps.as_str()) {
                            let target = match &modified[1] {
                                "weak" => &mut group.weaknesses,
                                "immune" => &mut group.immunities,
                                _ => panic!(),
                            };

                            for t in modified[2].split(", ") {
                                target.push(t.to_string());
                            }
                        }
                    }
                    self.units.push(group)
                }
            }
        }
    }

    fn simulate(&mut self) -> bool {
        let mut order: Vec<usize> = (0..self.units.len()).collect();
        order.sort_unstable_by_key(|&x| Reverse((self.units[x].effective_power(), self.units[x].initiative)));

        // select targets
        let mut targets: Vec<Option<usize>> = vec![None; self.units.len()];
        let mut is_targeted = vec![false; self.units.len()];
        let mut changes = false;

        for &i in &order {
            let unit = &self.units[i];
            if !unit.is_alive() {
                continue;
            }
            let damage = self.units.iter().map(|x| unit.damage_to(x)).collect_vec();
            let target = (0..self.units.len())
                .filter(|&x| !is_targeted[x] && self.units[x].faction != unit.faction && self.units[x].is_alive())
                .max_by_key(|&x| (damage[x], self.units[x].effective_power(), self.units[x].initiative));

            if let Some(target) = target {
                targets[i] = Some(target);
                is_targeted[target] = true;
            }
        }

        order.sort_unstable_by_key(|&x| Reverse(self.units[x].initiative));

        for attacker in order {
            if !self.units[attacker].is_alive() {
                continue;
            }

            if let Some(id) = targets[attacker] {
                let damage = self.units[attacker].damage_to(&self.units[id]);
                let defender = &mut self.units[id];

                let losses = damage / defender.hp;
                if losses > 0 {
                    defender.count = defender.count.saturating_sub(losses);
                    changes = true;
                }
            }
        }
        changes
    }

    fn both_alive(&self) -> bool {
        let mut seen = None;

        for unit in self.units.iter().filter(|g| g.is_alive()) {
            if let Some(seen) = seen {
                if seen != unit.faction {
                    return true;
                }
                continue;
            }

            seen = Some(unit.faction);
        }

        return false;
    }

    fn full_simulation(&mut self) {
        let mut changes = true;
        while self.both_alive() && changes {
            changes = self.simulate();
        }
    }

    fn faction_won(&self, faction: char) -> bool {
        if self.both_alive() {
            false
        } else {
            self.units.iter().filter(|x| x.is_alive())
                .all(|x| x.faction == faction)
        }
    }
}

impl Solution for Day24 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        self.full_simulation();

        let result: u32 = self.units.iter().map(|x| x.count).sum();
        result.to_string()
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        let original = self.units.clone();

        for boost in 1.. {
            self.units = original.clone();
            for unit in self.units.iter_mut().filter(|unit| unit.faction == 'D') {
                unit.power += boost;
            }

            self.full_simulation();
            let result: u32 = self.units.iter().map(|x| x.count).sum();
            if self.faction_won('D') {
                let result: u32 = self.units.iter().map(|x| x.count).sum();
                return result.to_string();
            }
        }
        unreachable!();
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day24::Day24;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/24.txt");

    #[test]
    fn sample_part1() {
        let mut instance = Day24::new();
        assert_eq!("5216", instance.part1(&mut SAMPLE_INPUT))
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day24::new();
        assert_eq!("51", instance.part2(&mut SAMPLE_INPUT))
    }
}
<commit_msg>Fix day 24 part 2.<commit_after>use std::cmp::Reverse;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use itertools::Itertools;
use regex::Regex;

use common::Solution;

#[derive(Default, Debug, Eq, PartialEq, Clone)]
struct Group {
    power: u32,
    count: u32,
    hp: u32,
    initiative: i32,
    damage: String,
    weaknesses: Vec<String>,
    immunities: Vec<String>,
    faction: char,
}

impl Group {
    pub fn is_alive(&self) -> bool {
        self.count > 0
    }

    pub fn damage_to(&self, other: &Group) -> u32 {
        let damage = self.effective_power();

        if other.weaknesses.contains(&self.damage) {
            damage * 2
        } else if other.immunities.contains(&self.damage) {
            0
        } else {
            damage
        }
    }

    pub fn effective_power(&self) -> u32 {
        self.power * self.count
    }
}

#[derive(Default)]
pub struct Day24 {
    units: Vec<Group>,
}

impl Day24 {
    pub fn new() -> Self {
        Default::default()
    }

    fn read_input(&mut self, input: &mut Read) {
        let matcher = Regex::new(r"(\d+) units each with (\d+) hit points (\(([^)]+)\) )?with an attack that does (\d+) (\w+) damage at initiative (\d+)").unwrap();
        let weakness_matcher = Regex::new(r"(weak|immune) to ([^;)]+)").unwrap();
        let reader = BufReader::new(input);
        let mut fac = 'X';

        for line in reader.lines() {
            let line = line.unwrap();
            match line.as_str() {
                "Immune System:" => { fac = 'D' }
                "" => {}
                "Infection:" => { fac = 'I' }
                line => {
                    let caps = matcher.captures(line).unwrap_or_else(|| {
                        panic!("{}", line);
                    });

                    let mut group = Group {
                        count: caps[1].parse().unwrap(),
                        hp: caps[2].parse().unwrap(),
                        power: caps[5].parse().unwrap(),
                        damage: caps[6].to_string(),
                        initiative: caps[7].parse().unwrap(),
                        faction: fac,
                        ..Default::default()
                    };

                    if let Some(caps) = caps.get(4) {
                        for modified in weakness_matcher.captures_iter(caps.as_str()) {
                            let target = match &modified[1] {
                                "weak" => &mut group.weaknesses,
                                "immune" => &mut group.immunities,
                                _ => panic!(),
                            };

                            for t in modified[2].split(", ") {
                                target.push(t.to_string());
                            }
                        }
                    }
                    self.units.push(group)
                }
            }
        }
    }

    fn simulate(&mut self) -> bool {
        let mut order: Vec<usize> = (0..self.units.len()).collect();
        order.sort_unstable_by_key(|&x| Reverse((self.units[x].effective_power(), self.units[x].initiative)));

        // select targets
        let mut targets: Vec<Option<usize>> = vec![None; self.units.len()];
        let mut is_targeted = vec![false; self.units.len()];
        let mut changes = false;

        for &i in &order {
            let unit = &self.units[i];
            if !unit.is_alive() {
                continue;
            }
            let damage = self.units.iter().map(|x| unit.damage_to(x)).collect_vec();
            let target = (0..self.units.len())
                .filter(|&x| !is_targeted[x] && self.units[x].faction != unit.faction && self.units[x].is_alive() && damage[x] > 0)
                .max_by_key(|&x| (damage[x], self.units[x].effective_power(), self.units[x].initiative));

            if let Some(target) = target {
                targets[i] = Some(target);
                is_targeted[target] = true;
            }
        }

        order.sort_unstable_by_key(|&x| Reverse(self.units[x].initiative));

        for attacker in order {
            if !self.units[attacker].is_alive() {
                continue;
            }

            if let Some(id) = targets[attacker] {
                let damage = self.units[attacker].damage_to(&self.units[id]);
                let defender = &mut self.units[id];

                let losses = damage / defender.hp;
                if losses > 0 {
                    defender.count = defender.count.saturating_sub(losses);
                    changes = true;
                }
            }
        }
        changes
    }

    fn both_alive(&self) -> bool {
        let mut seen = None;

        for unit in self.units.iter().filter(|g| g.is_alive()) {
            if let Some(seen) = seen {
                if seen != unit.faction {
                    return true;
                }
                continue;
            }

            seen = Some(unit.faction);
        }

        return false;
    }

    fn full_simulation(&mut self) {
        let mut changes = true;
        while self.both_alive() && changes {
            changes = self.simulate();
        }
    }

    fn faction_won(&self, faction: char) -> bool {
        if self.both_alive() {
            false
        } else {
            self.units.iter().filter(|x| x.is_alive())
                .all(|x| x.faction == faction)
        }
    }
}

impl Solution for Day24 {
    fn part1(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        self.full_simulation();

        let result: u32 = self.units.iter().map(|x| x.count).sum();
        result.to_string()
    }

    fn part2(&mut self, input: &mut Read) -> String {
        self.read_input(input);
        let original = self.units.clone();

        for boost in 1.. {
            self.units = original.clone();
            for unit in self.units.iter_mut().filter(|unit| unit.faction == 'D') {
                unit.power += boost;
            }

            self.full_simulation();
            if self.faction_won('D') {
                let result: u32 = self.units.iter().map(|x| x.count).sum();
                return result.to_string();
            }
        }
        unreachable!();
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;
    use day24::Day24;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/24.txt");

    #[test]
    fn sample_part1() {
        let mut instance = Day24::new();
        assert_eq!("5216", instance.part1(&mut SAMPLE_INPUT))
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day24::new();
        assert_eq!("51", instance.part2(&mut SAMPLE_INPUT))
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::result;

#[derive(Debug)]
pub struct JobDepend {
    pub id: i32,
    pub fk_job: i32,
    pub fk_provider: i32,
    pub sq_order: i32,
}

pub fn table_create_job_depend(conn: &Connection)  -> &Connection  {
    conn.execute("CREATE TABLE JOBDEPEND (
                  id                INTEGER PRIMARY KEY ASC,
                  fk_job            INTEGER NOT NULL,
                  fk_provider       INTEGER NOT NULL,
                  sq_order          INTEGER NOT NULL,
                  UNIQUE (fk_job, fk_provider) ON CONFLICT REPLACE
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_provider) REFERENCES PROVIDER(id) ON UPDATE CASCADE
                  )", &[]).unwrap();
    return conn;
}

pub fn insert_job_depend(conn: &Connection, job: &i32, provider: &i32, sq_order: &i32) -> Result<i32, &'static str> {
    let me = JobDepend {
        id: 0,
        fk_job: *job,
        fk_provider: *provider,
        sq_order: *sq_order,
    };
    let job_depend_instance = conn.execute("INSERT INTO JOBDEPEND (fk_job, fk_provider, sq_order)
                  VALUES (?1, ?2, ?3)",
                 &[&me.fk_job, &me.fk_provider, &me.sq_order]);
    if job_depend_instance.is_err() {
        return Err("Insert failed");
    }
    job_depend_instance.unwrap();
    return Ok(0);
}

pub fn list_job_depend(conn: &Connection)-> Vec<JobDepend> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider, sq_order  FROM JobDepend").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    });
    let mut items = Vec::<JobDepend>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_depend_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider, sq_order FROM JobDepend").unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    }).unwrap();

    for person in person_iter {
        println!("Found job_depend {:?}", person.unwrap());
    }
}

pub fn pk_job_depend_by_all(conn: &Connection, fk_job: &i32, provider: &i32, sq_order: &i32, pk: &mut i32) -> Result<i32, &'static str>{
    let mut stmt = conn.prepare("SELECT JobDepend.id, JobDepend.fk_job, JobDepend.fk_provider, JobDepend.sq_order  FROM JobDepend WHERE JobDepend.fk_job = ?1 AND JobDepend.fk_provider=?2 AND JobDepend.sq_order=?3 ").unwrap();
    let job_depend_iter = stmt.query_map(&[fk_job, provider, sq_order], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    });
    if job_depend_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_depend_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill= person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>clean up pk_job_depend_by_all<commit_after>use rusqlite::Connection;
use std::result;

#[derive(Debug)]
pub struct JobDepend {
    pub id: i32,
    pub fk_job: i32,
    pub fk_provider: i32,
    pub sq_order: i32,
}

pub fn table_create_job_depend(conn: &Connection)  -> &Connection  {
    conn.execute("CREATE TABLE JOBDEPEND (
                  id                INTEGER PRIMARY KEY ASC,
                  fk_job            INTEGER NOT NULL,
                  fk_provider       INTEGER NOT NULL,
                  sq_order          INTEGER NOT NULL,
                  UNIQUE (fk_job, fk_provider) ON CONFLICT REPLACE
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_provider) REFERENCES PROVIDER(id) ON UPDATE CASCADE
                  )", &[]).unwrap();
    return conn;
}

pub fn insert_job_depend(conn: &Connection, job: &i32, provider: &i32, sq_order: &i32) -> Result<i32, &'static str> {
    let me = JobDepend {
        id: 0,
        fk_job: *job,
        fk_provider: *provider,
        sq_order: *sq_order,
    };
    let job_depend_instance = conn.execute("INSERT INTO JOBDEPEND (fk_job, fk_provider, sq_order)
                  VALUES (?1, ?2, ?3)",
                 &[&me.fk_job, &me.fk_provider, &me.sq_order]);
    if job_depend_instance.is_err() {
        return Err("Insert failed");
    }
    job_depend_instance.unwrap();
    return Ok(0);
}

pub fn list_job_depend(conn: &Connection)-> Vec<JobDepend> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider, sq_order  FROM JobDepend").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    });
    let mut items = Vec::<JobDepend>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_depend_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_provider, sq_order FROM JobDepend").unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    }).unwrap();

    for person in person_iter {
        println!("Found job_depend {:?}", person.unwrap());
    }
}

pub fn pk_job_depend_by_all(conn: &Connection, fk_job: &i32, provider: &i32, sq_order: &i32) -> Result<i32, &'static str>{
    let mut output = 0;
    let mut stmt = conn.prepare("SELECT JobDepend.id, JobDepend.fk_job, JobDepend.fk_provider, JobDepend.sq_order  FROM JobDepend WHERE JobDepend.fk_job = ?1 AND JobDepend.fk_provider=?2 AND JobDepend.sq_order=?3 ").unwrap();
    let job_depend_iter = stmt.query_map(&[fk_job, provider, sq_order], |row| {
        JobDepend {
            id: row.get(0),
            fk_job: row.get(1),
            fk_provider: row.get(2),
            sq_order: row.get(3),
        }
    });
    if job_depend_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_depend_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill= person.unwrap();
        output = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(output);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>trait Environment {

}<commit_msg>Add an initial implementation of the environment class<commit_after>use tool::*;

///
/// Represents a tooling environment, which enables tools to be retrieved by name.
///
/// Environments make it possible to use tools without needing to know where the
/// precise implementation is located. Environments also provide a way to perform
/// dependency injection in other tools.
///
pub trait Environment {
    ///
    /// Retrieves a tool using a JSON interface by name
    ///
    fn get_json_tool<'a>(&self, name: &str) -> Result<&'a JsonTool, Error>;
}
<|endoftext|>