<commit_before>use Result;
use core::SegmentReader;
use schema::Document;
use collector::Collector;
use common::TimerTree;
use query::Query;
use DocId;
use DocAddress;
use schema::Term;
use core::TermIterator;
use std::fmt;

/// Holds a list of `SegmentReader`s ready for search.
///
/// It guarantees that the `Segment` will not be removed before
/// the destruction of the `Searcher`.
///
pub struct Searcher {
    segment_readers: Vec<SegmentReader>,
}

impl Searcher {
    /// Fetches a document from tantivy's store given a `DocAddress`.
    ///
    /// The searcher uses the segment ordinal to route the
    /// the request to the right `Segment`.
    pub fn doc(&self, doc_address: &DocAddress) -> Result<Document> {
        let DocAddress(segment_local_id, doc_id) = *doc_address;
        let segment_reader = &self.segment_readers[segment_local_id as usize];
        segment_reader.doc(doc_id)
    }

    /// Returns the overall number of documents in the index.
    pub fn num_docs(&self) -> DocId {
        self.segment_readers
            .iter()
            .map(|segment_reader| segment_reader.num_docs())
            .fold(0u32, |acc, val| acc + val)
    }

    /// Return the overall number of documents containing
    /// the given term.
    pub fn doc_freq(&self, term: &Term) -> u32 {
        self.segment_readers
            .iter()
            .map(|segment_reader| segment_reader.doc_freq(term))
            .fold(0u32, |acc, val| acc + val)
    }

    /// Returns a Stream over all of the sorted unique terms of
    /// the searcher.
    ///
    /// This includes all of the fields from all of the segment_readers.
    /// See [TermIterator](struct.TermIterator.html).
    ///
    /// # Warning
    /// This API is very likely to change in the future.
    pub fn terms<'a>(&'a self) -> TermIterator<'a> {
        TermIterator::from(self.segment_readers())
    }

    /// Return the list of segment readers
    pub fn segment_readers(&self) -> &[SegmentReader] {
        &self.segment_readers
    }

    /// Returns the segment_reader associated with the given segment_ordinal
    pub fn segment_reader(&self, segment_ord: u32) -> &SegmentReader {
        &self.segment_readers[segment_ord as usize]
    }

    /// Runs a query on the segment readers wrapped by the searcher
    pub fn search<C: Collector>(&self, query: &Query, collector: &mut C) -> Result<TimerTree> {
        query.search(self, collector)
    }
}

impl From<Vec<SegmentReader>> for Searcher {
    fn from(segment_readers: Vec<SegmentReader>) -> Searcher {
        Searcher { segment_readers: segment_readers }
    }
}

impl fmt::Debug for Searcher {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let segment_ids = self.segment_readers
            .iter()
            .map(|segment_reader| segment_reader.segment_id())
            .collect::<Vec<_>>();
        write!(f, "Searcher({:?})", segment_ids)
    }
}
<commit_msg>clippy: fix needless_lifetimes warnings<commit_after>use Result;
use core::SegmentReader;
use schema::Document;
use collector::Collector;
use common::TimerTree;
use query::Query;
use DocId;
use DocAddress;
use schema::Term;
use core::TermIterator;
use std::fmt;

/// Holds a list of `SegmentReader`s ready for search.
///
/// It guarantees that the `Segment` will not be removed before
/// the destruction of the `Searcher`.
///
pub struct Searcher {
    segment_readers: Vec<SegmentReader>,
}

impl Searcher {
    /// Fetches a document from tantivy's store given a `DocAddress`.
    ///
    /// The searcher uses the segment ordinal to route the
    /// the request to the right `Segment`.
    pub fn doc(&self, doc_address: &DocAddress) -> Result<Document> {
        let DocAddress(segment_local_id, doc_id) = *doc_address;
        let segment_reader = &self.segment_readers[segment_local_id as usize];
        segment_reader.doc(doc_id)
    }

    /// Returns the overall number of documents in the index.
    pub fn num_docs(&self) -> DocId {
        self.segment_readers
            .iter()
            .map(|segment_reader| segment_reader.num_docs())
            .fold(0u32, |acc, val| acc + val)
    }

    /// Return the overall number of documents containing
    /// the given term.
    pub fn doc_freq(&self, term: &Term) -> u32 {
        self.segment_readers
            .iter()
            .map(|segment_reader| segment_reader.doc_freq(term))
            .fold(0u32, |acc, val| acc + val)
    }

    /// Returns a Stream over all of the sorted unique terms of
    /// the searcher.
    ///
    /// This includes all of the fields from all of the segment_readers.
    /// See [TermIterator](struct.TermIterator.html).
    ///
    /// # Warning
    /// This API is very likely to change in the future.
    pub fn terms(&self) -> TermIterator {
        TermIterator::from(self.segment_readers())
    }

    /// Return the list of segment readers
    pub fn segment_readers(&self) -> &[SegmentReader] {
        &self.segment_readers
    }

    /// Returns the segment_reader associated with the given segment_ordinal
    pub fn segment_reader(&self, segment_ord: u32) -> &SegmentReader {
        &self.segment_readers[segment_ord as usize]
    }

    /// Runs a query on the segment readers wrapped by the searcher
    pub fn search<C: Collector>(&self, query: &Query, collector: &mut C) -> Result<TimerTree> {
        query.search(self, collector)
    }
}

impl From<Vec<SegmentReader>> for Searcher {
    fn from(segment_readers: Vec<SegmentReader>) -> Searcher {
        Searcher { segment_readers: segment_readers }
    }
}

impl fmt::Debug for Searcher {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let segment_ids = self.segment_readers
            .iter()
            .map(|segment_reader| segment_reader.segment_id())
            .collect::<Vec<_>>();
        write!(f, "Searcher({:?})", segment_ids)
    }
}
<|endoftext|>


<commit_before>use super::ffi;
use cuda;
use std::ptr;

pub struct Cudnn {
    handle: ffi::Handle
}

impl Cudnn {
    pub fn new() -> Result<Cudnn, &'static str> {
        let mut handle: ffi::Handle = ptr::null_mut();
        match unsafe { ffi::cudnnCreate(&mut handle) } {
            ffi::Status::Success => Ok(Cudnn { handle : handle }),
            ffi::Status::NotInitialized => Err("CUDA Runtime API initialization failed."),
            ffi::Status::AllocFailed => Err("The resources could not be allocated."),
            _ => Err("Unknown Error")
        }
    }

    pub fn sigmoid_forward(self,
                           src_desc: super::Tensor,
                           src: &cuda::Memory<f32>,
                           dst_desc: super::Tensor,
                           dst: &mut cuda::Memory<f32>) -> Result<(), &'static str> {
        match unsafe { ffi::cudnnActivationForward(self.handle,
                                                   ffi::ActivationDescriptor::Sigmoid,
                                                   *&[1.0f32].as_ptr() as *const ::libc::c_void,
                                                   src_desc.descriptor,
                                                   src.data,
                                                   *&[0.0f32].as_ptr() as *const ::libc::c_void,
                                                   dst_desc.descriptor,
                                                   dst.data) } {
            ffi::Status::Success => Ok(()),
            ffi::Status::BadParam => Err("Bad Parameters."),
            ffi::Status::ExecutionFailed => Err("The function failed to launch on the GPU."),
            _ => Err("Unknown Error")
        }
    }
}
<commit_msg>add dropper for Cudnn<commit_after>use super::ffi;
use cuda;
use std::ptr;

pub struct Cudnn {
    handle: ffi::Handle
}

impl Drop for Cudnn {
    fn drop(&mut self) {
        unsafe { ffi::cudnnDestroy(self.handle) };
    }
}

impl Cudnn {
    pub fn new() -> Result<Cudnn, &'static str> {
        let mut handle: ffi::Handle = ptr::null_mut();
        match unsafe { ffi::cudnnCreate(&mut handle) } {
            ffi::Status::Success => Ok(Cudnn { handle : handle }),
            ffi::Status::NotInitialized => Err("CUDA Runtime API initialization failed."),
            ffi::Status::AllocFailed => Err("The resources could not be allocated."),
            _ => Err("Unknown Error")
        }
    }

    pub fn sigmoid_forward(self,
                           src_desc: super::Tensor,
                           src: &cuda::Memory<f32>,
                           dst_desc: super::Tensor,
                           dst: &mut cuda::Memory<f32>) -> Result<(), &'static str> {
        match unsafe { ffi::cudnnActivationForward(self.handle,
                                                   ffi::ActivationDescriptor::Sigmoid,
                                                   *&[1.0f32].as_ptr() as *const ::libc::c_void,
                                                   src_desc.descriptor,
                                                   src.data,
                                                   *&[0.0f32].as_ptr() as *const ::libc::c_void,
                                                   dst_desc.descriptor,
                                                   dst.data) } {
            ffi::Status::Success => Ok(()),
            ffi::Status::BadParam => Err("Bad Parameters."),
            ffi::Status::ExecutionFailed => Err("The function failed to launch on the GPU."),
            _ => Err("Unknown Error")
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, ErrorKind, Read};

use bytes::BytesMut;
use bytes::buf::{Buf, BufMut, Reader};
use futures::{Async, Poll, Stream};
use hyper::body::Chunk;
use libflate::non_blocking::gzip;

use Error;

pub struct Gzip<S> where S: Stream {
    inner: ReadStream<gzip::Decoder<StreamRead<S>>>,
}

struct StreamRead<S> where S: Stream {
    body: S,
    buf: Reader<S::Item>,
    error: Option<S::Error>,
}

struct ReadStream<R> {
    inner: R,
    buf: BytesMut,
}

impl<S: Stream> Gzip<S> where S::Item: Buf+Default {
    pub fn new(body: S) -> Self {
        Gzip {
            inner: ReadStream::new(gzip::Decoder::new(StreamRead::new(body)))
        }
    }
}

impl<S: Stream<Error=Error>> Stream for Gzip<S> where S::Item: Buf {
    type Item = Chunk;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Chunk>, Error> {
        match self.inner.poll() {
            Ok(async) => Ok(async),
            Err(e) => if let Some(e) =
                self.inner.inner.as_inner_mut().error.take()
            {
                Err(e)
            } else {
                Err(Error::Custom(e.into()))
            }
        }
    }
}

impl<S: Stream> StreamRead<S> where S::Item: Buf+Default {
    pub fn new(body: S) -> Self {
        StreamRead {
            body,
            buf: S::Item::default().reader(),
            error: None,
        }
    }
}

impl<S: Stream> Read for StreamRead<S> where S::Item: Buf {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if ! self.buf.get_ref().has_remaining() {
            match self.body.poll() {
                Ok(Async::Ready(Some(data))) => self.buf = data.reader(),
                Ok(Async::Ready(None)) => return Ok(0),
                Ok(Async::NotReady) => return Err(ErrorKind::WouldBlock.into()),
                Err(e) => {
                    self.error = Some(e);
                    return Err(ErrorKind::Other.into())
                },
            }
        }
        self.buf.read(buf)
    }
}

const BUF_SIZE: usize = 8 * 1024;

impl<R: Read> ReadStream<R> {
    fn new(read: R) -> Self {
        ReadStream {
            inner: read,
            buf: BytesMut::with_capacity(BUF_SIZE),
        }
    }
}

impl<R: Read> Stream for ReadStream<R> {
    type Item = Chunk;
    type Error = io::Error;

    // This is almost a copy-and-paste from `reqwest` crate:
    // https://github.com/seanmonstar/reqwest/blob/fe8c7a2/src/async_impl/decoder.rs#L179-L214
    fn poll(&mut self) -> Poll<Option<Chunk>, io::Error> {
        if ! self.buf.has_remaining_mut() {
            self.buf.reserve(BUF_SIZE);
        }

        let read = unsafe {
            let buf = self.buf.bytes_mut();
            self.inner.read(buf)
        };

        match read {
            Ok(0) => Ok(None.into()),
            Ok(amt) => {
                unsafe { self.buf.advance_mut(amt); }
                let chunk = Chunk::from(self.buf.split_to(amt).freeze());
                Ok(Some(chunk).into())
            },
            Err(ref e) if ErrorKind::WouldBlock == e.kind() => {
                Ok(Async::NotReady)
            },
            Err(e) => Err(e),
        }
    }
}

#[cfg(test)]
mod tests {
    // TODO
}
<commit_msg>Add a test and fix an issue where `StreamRead::read` could `read` from an empty `Buf`<commit_after>use std::io::{self, ErrorKind, Read};

use bytes::BytesMut;
use bytes::buf::{Buf, BufMut, Reader};
use futures::{Async, Poll, Stream};
use hyper::body::Chunk;
use libflate::non_blocking::gzip;

use Error;

pub struct Gzip<S> where S: Stream {
    inner: ReadStream<gzip::Decoder<StreamRead<S>>>,
}

struct StreamRead<S> where S: Stream {
    body: S,
    buf: Reader<S::Item>,
    error: Option<S::Error>,
}

struct ReadStream<R> {
    inner: R,
    buf: BytesMut,
}

impl<S: Stream> Gzip<S> where S::Item: Buf+Default {
    pub fn new(body: S) -> Self {
        Gzip {
            inner: ReadStream::new(gzip::Decoder::new(StreamRead::new(body)))
        }
    }
}

impl<S: Stream<Error=Error>> Stream for Gzip<S> where S::Item: Buf {
    type Item = Chunk;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Chunk>, Error> {
        match self.inner.poll() {
            Ok(async) => Ok(async),
            Err(e) => if let Some(e) =
                self.inner.inner.as_inner_mut().error.take()
            {
                Err(e)
            } else {
                Err(Error::Custom(e.into()))
            }
        }
    }
}

impl<S: Stream> StreamRead<S> where S::Item: Buf+Default {
    pub fn new(body: S) -> Self {
        StreamRead {
            body,
            buf: S::Item::default().reader(),
            error: None,
        }
    }
}

impl<S: Stream> Read for StreamRead<S> where S::Item: Buf {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        while ! self.buf.get_ref().has_remaining() {
            match self.body.poll() {
                Ok(Async::Ready(Some(data))) => self.buf = data.reader(),
                Ok(Async::Ready(None)) => return Ok(0),
                Ok(Async::NotReady) => return Err(ErrorKind::WouldBlock.into()),
                Err(e) => {
                    self.error = Some(e);
                    return Err(ErrorKind::Other.into());
                },
            }
        }
        self.buf.read(buf)
    }
}

const BUF_SIZE: usize = 8 * 1024;

impl<R: Read> ReadStream<R> {
    fn new(read: R) -> Self {
        ReadStream {
            inner: read,
            buf: BytesMut::with_capacity(BUF_SIZE),
        }
    }
}

impl<R: Read> Stream for ReadStream<R> {
    type Item = Chunk;
    type Error = io::Error;

    // This is almost a copy-and-paste from `reqwest` crate:
    // https://github.com/seanmonstar/reqwest/blob/fe8c7a2/src/async_impl/decoder.rs#L179-L214
    fn poll(&mut self) -> Poll<Option<Chunk>, io::Error> {
        if ! self.buf.has_remaining_mut() {
            self.buf.reserve(BUF_SIZE);
        }

        let read = unsafe {
            let buf = self.buf.bytes_mut();
            self.inner.read(buf)
        };

        match read {
            Ok(0) => Ok(None.into()),
            Ok(amt) => {
                unsafe { self.buf.advance_mut(amt); }
                let chunk = Chunk::from(self.buf.split_to(amt).freeze());
                Ok(Some(chunk).into())
            },
            Err(ref e) if ErrorKind::WouldBlock == e.kind() => {
                Ok(Async::NotReady)
            },
            Err(e) => Err(e),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::Cursor;

    use bytes::Bytes;
    use futures::{stream, Future};

    use super::*;

    #[test]
    fn identity() {
        macro_rules! assert_id {
            ($($elm:expr),*) => {{
                let elms = [$(Bytes::from(&$elm[..])),*];
                assert_eq!(
                    *ReadStream::new(StreamRead {
                        body: stream::iter_ok::<_,()>(
                            elms.iter().cloned().map(Cursor::new)
                        ),
                        buf: Cursor::new(Bytes::new()).reader(),
                        error: None,
                    }).concat2().wait().unwrap(),
                    *elms.concat(),
                );
            }};
        }
        assert_id!();
        assert_id!([]);
        assert_id!([], [0], [], [], [1, 2]);
        assert_id!([0; BUF_SIZE+1], [1; BUF_SIZE-1], [2; BUF_SIZE*5/2]);
    }
}
<|endoftext|>


<commit_before>extern crate redis;

use flowgger::config::Config;
use flowgger::decoder::Decoder;
use flowgger::encoder::Encoder;
use self::redis::{Commands, Connection, RedisResult};
use std::io::{stderr, Write};
use std::sync::mpsc::SyncSender;
use std::thread;
use super::Input;

const DEFAULT_CONNECT: &'static str = "127.0.0.1";
const DEFAULT_QUEUE_KEY: &'static str = "logs";
const DEFAULT_THREADS: u32 = 1;

pub struct RedisInput {
    config: RedisConfig,
    threads: u32
}

struct RedisWorker {
    tid: u32,
    config: RedisConfig,
    redis_cnx: Connection,
    tx: SyncSender<Vec<u8>>,
    decoder: Box<Decoder + Send>,
    encoder: Box<Encoder + Send>
}

#[derive(Clone)]
struct RedisConfig {
    connect: String,
    queue_key: String
}

impl RedisInput {
    pub fn new(config: &Config) -> RedisInput {
        let connect = config.lookup("input.redis_connect").map_or(DEFAULT_CONNECT, |x|x.as_str().
            expect("input.redis_connect must be an ip:port string")).to_owned();
        let queue_key = config.lookup("input.redis_queue_key").map_or(DEFAULT_QUEUE_KEY, |x|x.as_str().
            expect("input.redis_queue_key must be a string")).to_owned();
        let threads = config.lookup("input.redis_threads").
            map_or(DEFAULT_THREADS, |x| x.as_integer().
                expect("input.redis_threads must be a 32-bit integer") as u32);
        let redis_config = RedisConfig {
            connect: connect,
            queue_key: queue_key
        };
        RedisInput {
            config: redis_config,
            threads: threads
        }
    }
}

impl RedisWorker {
    fn new(tid: u32, config: RedisConfig, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder + Send>, encoder: Box<Encoder + Send>) -> RedisWorker {
        let redis_cnx = match redis::Client::open(format!("redis://{}/", config.connect).as_ref()) {
            Err(_) => panic!("Invalid connection string for the Redis server: [{}]", config.connect),
            Ok(client) => match client.get_connection() {
                Err(_) => panic!("Unable to connect to the Redis server: [{}]", config.connect),
                Ok(redis_cnx) => redis_cnx
            }
        };
        RedisWorker {
            tid: tid,
            config: config,
            redis_cnx: redis_cnx,
            tx: tx,
            decoder: decoder,
            encoder: encoder
        }
    }

    fn run(self) {
        let queue_key: &str = &self.config.queue_key;
        let queue_key_tmp: &str = &format!("{}.tmp.{}", queue_key, self.tid);
        let redis_cnx = self.redis_cnx;
        println!("Connected to Redis [{}], pulling messages from key [{}]", self.config.connect, queue_key);
        while {
            let dummy: RedisResult<String> = redis_cnx.rpoplpush(queue_key_tmp, queue_key);
            dummy.is_ok()
        } { };
        let (decoder, encoder): (Box<Decoder>, Box<Encoder>) = (self.decoder, self.encoder);
        loop {
            let line: String = match redis_cnx.brpoplpush(queue_key, queue_key_tmp, 0) {
                Err(_) => panic!("Redis protocol error in BRPOPLPUSH"),
                Ok(line) => line
            };
            if let Err(e) = handle_line(&line, &self.tx, &decoder, &encoder) {
                let _ = writeln!(stderr(), "{}: [{}]", e, line.trim());
            }
            match redis_cnx.lrem(queue_key_tmp, 1, line) as RedisResult<u8> {
                Err(x) => panic!(format!("Redis protocol error in LREM [{}]", x)),
                Ok(_) => ()
            };
        }
    }
}

impl Input for RedisInput {
    fn accept(&self, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder + Send>, encoder: Box<Encoder + Send>) {
        let mut jids = Vec::new();
        for tid in (0..self.threads) {
            let config = self.config.clone();
            let (encoder, decoder) = (encoder.clone_boxed(), decoder.clone_boxed());
            let tx = tx.clone();
            jids.push(thread::spawn(move || {
                let worker = RedisWorker::new(tid, config, tx, decoder, encoder);
                worker.run();
            }));
        }
        for jid in jids {
            if let Err(_) = jid.join() {
                panic!("Redis connection lost");
            }
        }
    }
}

fn handle_line(line: &String, tx: &SyncSender<Vec<u8>>, decoder: &Box<Decoder>, encoder: &Box<Encoder>) -> Result<(), &'static str> {
    let decoded = try!(decoder.decode(&line));
    let reencoded = try!(encoder.encode(decoded));
    tx.send(reencoded).unwrap();
    Ok(())
}
<commit_msg>If a Redis task fails, abort all of them and exit right away<commit_after>extern crate redis;

use flowgger::config::Config;
use flowgger::decoder::Decoder;
use flowgger::encoder::Encoder;
use self::redis::{Commands, Connection, RedisResult};
use std::io::{stderr, Write};
use std::process::exit;
use std::sync::mpsc::SyncSender;
use std::thread;
use super::Input;

const DEFAULT_CONNECT: &'static str = "127.0.0.1";
const DEFAULT_QUEUE_KEY: &'static str = "logs";
const DEFAULT_THREADS: u32 = 1;

pub struct RedisInput {
    config: RedisConfig,
    threads: u32
}

struct RedisWorker {
    tid: u32,
    config: RedisConfig,
    redis_cnx: Connection,
    tx: SyncSender<Vec<u8>>,
    decoder: Box<Decoder + Send>,
    encoder: Box<Encoder + Send>
}

#[derive(Clone)]
struct RedisConfig {
    connect: String,
    queue_key: String
}

impl RedisInput {
    pub fn new(config: &Config) -> RedisInput {
        let connect = config.lookup("input.redis_connect").map_or(DEFAULT_CONNECT, |x|x.as_str().
            expect("input.redis_connect must be an ip:port string")).to_owned();
        let queue_key = config.lookup("input.redis_queue_key").map_or(DEFAULT_QUEUE_KEY, |x|x.as_str().
            expect("input.redis_queue_key must be a string")).to_owned();
        let threads = config.lookup("input.redis_threads").
            map_or(DEFAULT_THREADS, |x| x.as_integer().
                expect("input.redis_threads must be a 32-bit integer") as u32);
        let redis_config = RedisConfig {
            connect: connect,
            queue_key: queue_key
        };
        RedisInput {
            config: redis_config,
            threads: threads
        }
    }
}

impl RedisWorker {
    fn new(tid: u32, config: RedisConfig, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder + Send>, encoder: Box<Encoder + Send>) -> RedisWorker {
        let redis_cnx = match redis::Client::open(format!("redis://{}/", config.connect).as_ref()) {
            Err(_) => panic!("Invalid connection string for the Redis server: [{}]", config.connect),
            Ok(client) => match client.get_connection() {
                Err(_) => panic!("Unable to connect to the Redis server: [{}]", config.connect),
                Ok(redis_cnx) => redis_cnx
            }
        };
        RedisWorker {
            tid: tid,
            config: config,
            redis_cnx: redis_cnx,
            tx: tx,
            decoder: decoder,
            encoder: encoder
        }
    }

    fn run(self) -> Result<(), String> {
        let queue_key: &str = &self.config.queue_key;
        let queue_key_tmp: &str = &format!("{}.tmp.{}", queue_key, self.tid);
        let redis_cnx = self.redis_cnx;
        println!("Connected to Redis [{}], pulling messages from key [{}]", self.config.connect, queue_key);
        while {
            let dummy: RedisResult<String> = redis_cnx.rpoplpush(queue_key_tmp, queue_key);
            dummy.is_ok()
        } { };
        let (decoder, encoder): (Box<Decoder>, Box<Encoder>) = (self.decoder, self.encoder);
        loop {
            let line: String = match redis_cnx.brpoplpush(queue_key, queue_key_tmp, 0) {
                Err(e) => return Err(format!("Redis protocol error in BRPOPLPUSH: [{}]", e)),
                Ok(line) => line
            };
            if let Err(e) = handle_line(&line, &self.tx, &decoder, &encoder) {
                let _ = writeln!(stderr(), "{}: [{}]", e, line.trim());
            }
            match redis_cnx.lrem(queue_key_tmp, 1, line) as RedisResult<u8> {
                Err(e) => return Err(format!("Redis protocol error in LREM: [{}]", e)),
                Ok(_) => ()
            };
        }
    }
}

impl Input for RedisInput {
    fn accept(&self, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder + Send>, encoder: Box<Encoder + Send>) {
        let mut jids = Vec::new();
        for tid in (0..self.threads) {
            let config = self.config.clone();
            let (encoder, decoder) = (encoder.clone_boxed(), decoder.clone_boxed());
            let tx = tx.clone();
            jids.push(thread::spawn(move || {
                let worker = RedisWorker::new(tid, config, tx, decoder, encoder);
                if let Err(e) = worker.run() {
                    let _ = writeln!(stderr(), "Redis connection lost, aborting - {}", e);
                }
                exit(1);
            }));
        }
        for jid in jids {
            if let Err(_) = jid.join() {
                panic!("Redis connection lost");
            }
        }
    }
}

fn handle_line(line: &String, tx: &SyncSender<Vec<u8>>, decoder: &Box<Decoder>, encoder: &Box<Encoder>) -> Result<(), &'static str> {
    let decoded = try!(decoder.decode(&line));
    let reencoded = try!(encoder.encode(decoded));
    tx.send(reencoded).unwrap();
    Ok(())
}
<|endoftext|>


<commit_before>pub use self::cargo_clean::{clean, CleanOptions};
pub use self::cargo_compile::{compile, compile_with_exec, compile_ws, CompileOptions};
pub use self::cargo_compile::{CompileFilter, FilterRule, Packages};
pub use self::cargo_read_manifest::{read_package, read_packages};
pub use self::cargo_run::run;
pub use self::cargo_install::{install, install_list, uninstall};
pub use self::cargo_new::{init, new, NewOptions, VersionControl};
pub use self::cargo_doc::{doc, DocOptions};
pub use self::cargo_generate_lockfile::generate_lockfile;
pub use self::cargo_generate_lockfile::update_lockfile;
pub use self::cargo_generate_lockfile::UpdateOptions;
pub use self::lockfile::{load_pkg_lockfile, write_pkg_lockfile};
pub use self::cargo_test::{run_benches, run_tests, TestOptions};
pub use self::cargo_package::{package, PackageOpts};
pub use self::registry::{publish, registry_configuration, RegistryConfig};
pub use self::registry::{http_handle, needs_custom_http_transport, registry_login, search};
pub use self::registry::{modify_owners, yank, OwnersOptions, PublishOpts};
pub use self::registry::configure_http_handle;
pub use self::cargo_fetch::{fetch, FetchOptions};
pub use self::cargo_pkgid::pkgid;
pub use self::resolve::{resolve_with_previous, resolve_ws, resolve_ws_precisely,
                        resolve_ws_with_method};
pub use self::cargo_output_metadata::{output_metadata, ExportInfo, OutputMetadataOptions};

mod cargo_clean;
mod cargo_compile;
mod cargo_doc;
mod cargo_fetch;
mod cargo_generate_lockfile;
mod cargo_install;
mod cargo_new;
mod cargo_output_metadata;
mod cargo_package;
mod cargo_pkgid;
mod cargo_read_manifest;
mod cargo_run;
mod cargo_test;
mod lockfile;
mod registry;
mod resolve;
<commit_msg>Auto merge of #5581 - kngwyu:for-racer, r=alexcrichton<commit_after>pub use self::cargo_clean::{clean, CleanOptions};
pub use self::cargo_compile::{compile, compile_with_exec, compile_ws, CompileOptions};
pub use self::cargo_compile::{CompileFilter, FilterRule, Packages};
pub use self::cargo_read_manifest::{read_package, read_packages};
pub use self::cargo_run::run;
pub use self::cargo_install::{install, install_list, uninstall};
pub use self::cargo_new::{init, new, NewOptions, VersionControl};
pub use self::cargo_doc::{doc, DocOptions};
pub use self::cargo_generate_lockfile::generate_lockfile;
pub use self::cargo_generate_lockfile::update_lockfile;
pub use self::cargo_generate_lockfile::UpdateOptions;
pub use self::lockfile::{load_pkg_lockfile, write_pkg_lockfile};
pub use self::cargo_test::{run_benches, run_tests, TestOptions};
pub use self::cargo_package::{package, PackageOpts};
pub use self::registry::{publish, registry_configuration, RegistryConfig};
pub use self::registry::{http_handle, needs_custom_http_transport, registry_login, search};
pub use self::registry::{modify_owners, yank, OwnersOptions, PublishOpts};
pub use self::registry::configure_http_handle;
pub use self::cargo_fetch::{fetch, FetchOptions};
pub use self::cargo_pkgid::pkgid;
pub use self::resolve::{add_overrides, get_resolved_packages, resolve_with_previous, resolve_ws,
                        resolve_ws_precisely, resolve_ws_with_method};
pub use self::cargo_output_metadata::{output_metadata, ExportInfo, OutputMetadataOptions};

mod cargo_clean;
mod cargo_compile;
mod cargo_doc;
mod cargo_fetch;
mod cargo_generate_lockfile;
mod cargo_install;
mod cargo_new;
mod cargo_output_metadata;
mod cargo_package;
mod cargo_pkgid;
mod cargo_read_manifest;
mod cargo_run;
mod cargo_test;
mod lockfile;
mod registry;
mod resolve;
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::error;
use std::env;

use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};

use config;
use output;

use super::error::CommandError;

use super::service;
use super::run_task;
use super::schedule_task;
use super::params;
use super::configtest;

pub struct MainCommand {}

impl MainCommand {
    fn validate_args_template_variables(tag_str: String) -> Result<(), String> {
        let pair: Vec<&str> = tag_str.split("=").collect();
        if pair.len() == 2 {
            Ok(())
        } else {
            Err(String::from(
                "The variable format should contain variable name and variable value, and those are seperated with `=` character",
            ))
        }
    }
    fn parse_args_template_variables(args: &ArgMatches) -> Option<BTreeMap<String, String>> {
        args.values_of("CONFIG_TEMPLATE_VARIABLES").map(|vars_str| {
            let mut data = BTreeMap::new();
            for var_str in vars_str {
                let pair: Vec<&str> = var_str.split("=").collect();
                data.insert(pair[0].to_owned(), pair[1].to_owned());
            }

            data
        })
    }

    fn config_file(args: &ArgMatches) -> String {
        if let Some(config_file) = args.value_of("CONFIG") {
            return config_file.to_owned();
        }
        if let Ok(config_file) = env::var("RACCO_CONFIG_PATH") {
            return config_file;
        }

        String::from("racco.yml")
    }

    pub fn run() -> Result<(), Box<error::Error>> {

        let matches = App::new("Racco")
            .version("0.1.0")
            .author("Daichi Sakai. <daisaru11@gmail.com>")
            .about("Deployment toolkit for AWS ECS")
            .arg(
                Arg::with_name("CONFIG")
                    .short("c")
                    .long("config")
                    .value_name("FILE")
                    .help("Specifies configuration file")
                    .takes_value(true),
            )
            .arg(
                Arg::with_name("CONFIG_TEMPLATE_VARIABLE_FILE")
                    .short("t")
                    .long("config-template-var-file")
                    .value_name("FILENAME")
                    .help("A File defines variables rendered in config template")
                    .takes_value(true)
            )
            .arg(
                Arg::with_name("CONFIG_TEMPLATE_VARIABLES")
                    .short("a")
                    .long("config-template-vars")
                    .value_name("NAME=VALUE")
                    .help("Variables to be rendered in config template.")
                    .takes_value(true)
                    .multiple(true)
                    .validator(MainCommand::validate_args_template_variables),
            )
            .subcommand(
                SubCommand::with_name("config")
                    .about("Display loaded config")
            )
            .subcommand(
                SubCommand::with_name("service")
                    .about("Manages ECS services")
                    .subcommand(
                        SubCommand::with_name("deploy")
                            .about("Deploys ECS service")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Deploy all services")
                                    .long("all")
                            )
                            .arg(
                                Arg::with_name("NO_WAIT")
                                    .help("Do not wait until new tasks to be running")
                                    .long("no-wait")
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("stop")
                            .about("Stops ECS service (change desired count to zero)")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Stop all services")
                                    .long("all")
                            )
                            .arg(
                                Arg::with_name("NO_WAIT")
                                    .help("Do not wait until new tasks to be stopped")
                                    .long("no-wait")
                            ),
                    ),
            )
            .subcommand(
                SubCommand::with_name("run-task")
                    .about("Runs single ESC task")
                    .arg(
                        Arg::with_name("NAME")
                            .help("Name of the entry in config")
                            .required(true)
                            .index(1),
                    )
                    .arg(
                        Arg::with_name("NO_WAIT")
                            .help("Do not wait until new tasks to be running")
                            .long("no-wait")
                    ),
            )
            .subcommand(
                SubCommand::with_name("schedule-task")
                    .about("Deploys ECS task scheduled by Cloudwatch events")
                    .subcommand(
                        SubCommand::with_name("put")
                            .about("Puts a scheduled task")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Put all schedule tasks")
                                    .long("all")
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("delete")
                            .about("Deletes a scheduled task")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Delete all schedule tasks")
                                    .long("all")
                            ),
                    ),
            )
            .subcommand(
                SubCommand::with_name("params")
                    .about("Manages parameters")
                    .subcommand(
                        SubCommand::with_name("get").about("Gets a parameter").arg(
                            Arg::with_name("NAME")
                                .help("Name of the parameter")
                                .required(true)
                                .index(1),
                        ),
                    )
                    .subcommand(SubCommand::with_name("list").about("Lists parameters"))
                    .subcommand(
                        SubCommand::with_name("put")
                            .about("Puts a parameter")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the parameter")
                                    .required(true)
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("VALUE")
                                    .help("Value of the parameter")
                                    .required(true)
                                    .index(2),
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("delete")
                            .about("Deletes a parameter")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the parameter")
                                    .required(true)
                                    .index(1),
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("exec")
                            .setting(AppSettings::AllowLeadingHyphen)
                            .about(
                                "Executes a command with the exported parameters as env variables",
                            )
                            .arg(
                                Arg::with_name("PROGRAM")
                                    .help("Program to be executed")
                                    .required(true)
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ARGS")
                                    .help("Arguments passed to the program")
                                    .multiple(true)
                                    .index(2),
                            ),
                    ),
            )
            .get_matches();

        let config_file = MainCommand::config_file(&matches);
        info!("config file: {}", config_file);

        let template_variables = MainCommand::parse_args_template_variables(&matches);

        let template_variable_file = matches.value_of("CONFIG_TEMPLATE_VARIABLE_FILE");

        match config::command::Config::from_file(
            config_file.as_str(),
            template_variables.as_ref(),
            template_variable_file,
        ) {
            Err(error) => {
                output::PrintLine::error(&format!("Failed loading the configuration: {}", error));
                return Err(error)
            }
            Ok(config) => {

                // service
                if let Some(sub0_matches) = matches.subcommand_matches("service") {
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("deploy") {

                        info!("start service deploy");

                        let cmd = service::deploy::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end service deploy");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(
                                    &format!("Failed deploying the service: {}", error),
                                );
                                return Err(error)
                            }
                        }

                    }

                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("stop") {

                        info!("start stopping service");

                        let cmd = service::stop::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end stopping service");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(
                                    &format!("Failed stopping the service: {}", error),
                                );
                                return Err(error)
                            }
                        }

                    }
                }

                // config
                if let Some(sub0_matches) = matches.subcommand_matches("config") {

                    info!("start config");

                    let cmd = configtest::Command::from_args(&config, sub0_matches);
                    match cmd.run() {
                        Ok(_) => {
                            info!("end config");
                            return Ok(())
                        }
                        Err(error) => {
                            output::PrintLine::error(
                                &format!("Failed display config: {}", error),
                            );
                            return Err(error)
                        }
                    }
                }

                // run-task
                if let Some(sub_matches) = matches.subcommand_matches("run-task") {

                    info!("start run-task");

                    let cmd = run_task::Command::from_args(&config, sub_matches);
                    match cmd.run() {
                        Ok(_) => {
                            info!("end run-task");
                            return Ok(())
                        }
                        Err(error) => {
                            output::PrintLine::error(
                                &format!("Failed running the task: {}", error),
                            );
                            return Err(error)
                        }
                    }

                }

                // schedule-task
                if let Some(sub0_matches) = matches.subcommand_matches("schedule-task") {
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                        info!("start schedule-task put");

                        let cmd = schedule_task::put::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end schdule-task put");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                        info!("start schedule-task delete");

                        let cmd = schedule_task::delete::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end schedule-task delete");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                }

                // params
                if let Some(sub0_matches) = matches.subcommand_matches("params") {
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("get") {
                        info!("start params get");

                        let cmd = params::get::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params get");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }

                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("list") {
                        info!("start params list");

                        let cmd = params::list::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params list");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                        info!("start params put");

                        let cmd = params::put::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params put");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                        info!("start params delete");

                        let cmd = params::delete::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params delete");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("exec") {
                        info!("start params exec");

                        let cmd = params::exec::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params exec");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }

                    }
                }
            }
        };

        Err(Box::new(CommandError::CommandNotFound))
    }
}
<commit_msg>Fix display version in command help<commit_after>use std::collections::BTreeMap;
use std::error;
use std::env;

use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};

use config;
use output;

use super::error::CommandError;

use super::service;
use super::run_task;
use super::schedule_task;
use super::params;
use super::configtest;

pub struct MainCommand {}

impl MainCommand {
    fn validate_args_template_variables(tag_str: String) -> Result<(), String> {
        let pair: Vec<&str> = tag_str.split("=").collect();
        if pair.len() == 2 {
            Ok(())
        } else {
            Err(String::from(
                "The variable format should contain variable name and variable value, and those are seperated with `=` character",
            ))
        }
    }
    fn parse_args_template_variables(args: &ArgMatches) -> Option<BTreeMap<String, String>> {
        args.values_of("CONFIG_TEMPLATE_VARIABLES").map(|vars_str| {
            let mut data = BTreeMap::new();
            for var_str in vars_str {
                let pair: Vec<&str> = var_str.split("=").collect();
                data.insert(pair[0].to_owned(), pair[1].to_owned());
            }

            data
        })
    }

    fn config_file(args: &ArgMatches) -> String {
        if let Some(config_file) = args.value_of("CONFIG") {
            return config_file.to_owned();
        }
        if let Ok(config_file) = env::var("RACCO_CONFIG_PATH") {
            return config_file;
        }

        String::from("racco.yml")
    }

    pub fn run() -> Result<(), Box<error::Error>> {

        let matches = App::new("Racco")
            .version(env!("CARGO_PKG_VERSION"))
            .author("Daichi Sakai. <daisaru11@gmail.com>")
            .about("Deployment toolkit for AWS ECS")
            .arg(
                Arg::with_name("CONFIG")
                    .short("c")
                    .long("config")
                    .value_name("FILE")
                    .help("Specifies configuration file")
                    .takes_value(true),
            )
            .arg(
                Arg::with_name("CONFIG_TEMPLATE_VARIABLE_FILE")
                    .short("t")
                    .long("config-template-var-file")
                    .value_name("FILENAME")
                    .help("A File defines variables rendered in config template")
                    .takes_value(true)
            )
            .arg(
                Arg::with_name("CONFIG_TEMPLATE_VARIABLES")
                    .short("a")
                    .long("config-template-vars")
                    .value_name("NAME=VALUE")
                    .help("Variables to be rendered in config template.")
                    .takes_value(true)
                    .multiple(true)
                    .validator(MainCommand::validate_args_template_variables),
            )
            .subcommand(
                SubCommand::with_name("config")
                    .about("Display loaded config")
            )
            .subcommand(
                SubCommand::with_name("service")
                    .about("Manages ECS services")
                    .subcommand(
                        SubCommand::with_name("deploy")
                            .about("Deploys ECS service")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Deploy all services")
                                    .long("all")
                            )
                            .arg(
                                Arg::with_name("NO_WAIT")
                                    .help("Do not wait until new tasks to be running")
                                    .long("no-wait")
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("stop")
                            .about("Stops ECS service (change desired count to zero)")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Stop all services")
                                    .long("all")
                            )
                            .arg(
                                Arg::with_name("NO_WAIT")
                                    .help("Do not wait until new tasks to be stopped")
                                    .long("no-wait")
                            ),
                    ),
            )
            .subcommand(
                SubCommand::with_name("run-task")
                    .about("Runs single ESC task")
                    .arg(
                        Arg::with_name("NAME")
                            .help("Name of the entry in config")
                            .required(true)
                            .index(1),
                    )
                    .arg(
                        Arg::with_name("NO_WAIT")
                            .help("Do not wait until new tasks to be running")
                            .long("no-wait")
                    ),
            )
            .subcommand(
                SubCommand::with_name("schedule-task")
                    .about("Deploys ECS task scheduled by Cloudwatch events")
                    .subcommand(
                        SubCommand::with_name("put")
                            .about("Puts a scheduled task")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Put all schedule tasks")
                                    .long("all")
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("delete")
                            .about("Deletes a scheduled task")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the entry in config")
                                    .required_unless("ALL")
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ALL")
                                    .help("Delete all schedule tasks")
                                    .long("all")
                            ),
                    ),
            )
            .subcommand(
                SubCommand::with_name("params")
                    .about("Manages parameters")
                    .subcommand(
                        SubCommand::with_name("get").about("Gets a parameter").arg(
                            Arg::with_name("NAME")
                                .help("Name of the parameter")
                                .required(true)
                                .index(1),
                        ),
                    )
                    .subcommand(SubCommand::with_name("list").about("Lists parameters"))
                    .subcommand(
                        SubCommand::with_name("put")
                            .about("Puts a parameter")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the parameter")
                                    .required(true)
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("VALUE")
                                    .help("Value of the parameter")
                                    .required(true)
                                    .index(2),
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("delete")
                            .about("Deletes a parameter")
                            .arg(
                                Arg::with_name("NAME")
                                    .help("Name of the parameter")
                                    .required(true)
                                    .index(1),
                            ),
                    )
                    .subcommand(
                        SubCommand::with_name("exec")
                            .setting(AppSettings::AllowLeadingHyphen)
                            .about(
                                "Executes a command with the exported parameters as env variables",
                            )
                            .arg(
                                Arg::with_name("PROGRAM")
                                    .help("Program to be executed")
                                    .required(true)
                                    .index(1),
                            )
                            .arg(
                                Arg::with_name("ARGS")
                                    .help("Arguments passed to the program")
                                    .multiple(true)
                                    .index(2),
                            ),
                    ),
            )
            .get_matches();

        let config_file = MainCommand::config_file(&matches);
        info!("config file: {}", config_file);

        let template_variables = MainCommand::parse_args_template_variables(&matches);

        let template_variable_file = matches.value_of("CONFIG_TEMPLATE_VARIABLE_FILE");

        match config::command::Config::from_file(
            config_file.as_str(),
            template_variables.as_ref(),
            template_variable_file,
        ) {
            Err(error) => {
                output::PrintLine::error(&format!("Failed loading the configuration: {}", error));
                return Err(error)
            }
            Ok(config) => {

                // service
                if let Some(sub0_matches) = matches.subcommand_matches("service") {
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("deploy") {

                        info!("start service deploy");

                        let cmd = service::deploy::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end service deploy");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(
                                    &format!("Failed deploying the service: {}", error),
                                );
                                return Err(error)
                            }
                        }

                    }

                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("stop") {

                        info!("start stopping service");

                        let cmd = service::stop::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end stopping service");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(
                                    &format!("Failed stopping the service: {}", error),
                                );
                                return Err(error)
                            }
                        }

                    }
                }

                // config
                if let Some(sub0_matches) = matches.subcommand_matches("config") {

                    info!("start config");

                    let cmd = configtest::Command::from_args(&config, sub0_matches);
                    match cmd.run() {
                        Ok(_) => {
                            info!("end config");
                            return Ok(())
                        }
                        Err(error) => {
                            output::PrintLine::error(
                                &format!("Failed display config: {}", error),
                            );
                            return Err(error)
                        }
                    }
                }

                // run-task
                if let Some(sub_matches) = matches.subcommand_matches("run-task") {

                    info!("start run-task");

                    let cmd = run_task::Command::from_args(&config, sub_matches);
                    match cmd.run() {
                        Ok(_) => {
                            info!("end run-task");
                            return Ok(())
                        }
                        Err(error) => {
                            output::PrintLine::error(
                                &format!("Failed running the task: {}", error),
                            );
                            return Err(error)
                        }
                    }

                }

                // schedule-task
                if let Some(sub0_matches) = matches.subcommand_matches("schedule-task") {
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                        info!("start schedule-task put");

                        let cmd = schedule_task::put::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end schdule-task put");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                        info!("start schedule-task delete");

                        let cmd = schedule_task::delete::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end schedule-task delete");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                }

                // params
                if let Some(sub0_matches) = matches.subcommand_matches("params") {
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("get") {
                        info!("start params get");

                        let cmd = params::get::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params get");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }

                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("list") {
                        info!("start params list");

                        let cmd = params::list::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params list");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("put") {
                        info!("start params put");

                        let cmd = params::put::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params put");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("delete") {
                        info!("start params delete");

                        let cmd = params::delete::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params delete");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }
                    }
                    if let Some(sub1_matches) = sub0_matches.subcommand_matches("exec") {
                        info!("start params exec");

                        let cmd = params::exec::Command::from_args(&config, sub1_matches);
                        match cmd.run() {
                            Ok(_) => {
                                info!("end params exec");
                                return Ok(())
                            }
                            Err(error) => {
                                output::PrintLine::error(&format!("Failed: {}", error));
                                return Err(error)
                            }
                        }

                    }
                }
            }
        };

        Err(Box::new(CommandError::CommandNotFound))
    }
}
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

use super::*;
use crate::util::expect_err;
use alloc::{borrow::ToOwned, vec};
use core::cmp::Ordering;

#[test]
fn test_error_convert() {
    match CoseError::from(crate::cbor::ser::Error::<String>::Value(
        "error message lost".to_owned(),
    )) {
        CoseError::EncodeFailed => {}
        _ => panic!("unexpected error enum after conversion"),
    }
}

#[test]
fn test_label_encode() {
    let tests = vec![
        (Label::Int(2), "02"),
        (Label::Int(-1), "20"),
        (Label::Text("abc".to_owned()), "63616263"),
    ];

    for (i, (label, label_data)) in tests.iter().enumerate() {
        let got = label.clone().to_vec().unwrap();
        assert_eq!(*label_data, hex::encode(&got), "case {}", i);

        let got = Label::from_slice(&got).unwrap();
        assert_eq!(*label, got);
    }
}

#[test]
fn test_label_sort() {
    // Pairs of `Label`s with the "smaller" first.
    let pairs = vec![
        (Label::Int(0x1234), Label::Text("a".to_owned())),
        (Label::Int(0x1234), Label::Text("ab".to_owned())),
        (Label::Int(0), Label::Text("ab".to_owned())),
        (Label::Int(-1), Label::Text("ab".to_owned())),
        (Label::Int(0), Label::Int(10)),
        (Label::Int(0), Label::Int(-10)),
        (Label::Int(10), Label::Int(-1)),
        (Label::Int(-1), Label::Int(-2)),
        (Label::Int(0x12), Label::Int(0x1234)),
        (Label::Int(0x99), Label::Int(0x1234)),
        (Label::Int(0x1234), Label::Int(0x1235)),
        (Label::Text("a".to_owned()), Label::Text("ab".to_owned())),
        (Label::Text("aa".to_owned()), Label::Text("ab".to_owned())),
    ];
    for (left, right) in pairs.into_iter() {
        let value_cmp = left.cmp(&right);
        let value_partial_cmp = left.partial_cmp(&right);
        let left_data = left.clone().to_vec().unwrap();
        let right_data = right.clone().to_vec().unwrap();
        let data_cmp = left_data.cmp(&right_data);
        let reverse_cmp = right.cmp(&left);
        let equal_cmp = left.cmp(&left);

        assert_eq!(value_cmp, Ordering::Less, "{:?} < {:?}", left, right);
        assert_eq!(
            value_partial_cmp,
            Some(Ordering::Less),
            "{:?} < {:?}",
            left,
            right
        );
        assert_eq!(
            data_cmp,
            Ordering::Less,
            "{:?}={} < {:?}={}",
            left,
            hex::encode(&left_data),
            right,
            hex::encode(&right_data)
        );
        assert_eq!(reverse_cmp, Ordering::Greater, "{:?} > {:?}", right, left);
        assert_eq!(equal_cmp, Ordering::Equal, "{:?} = {:?}", left, left);
    }
}

#[test]
fn test_label_decode_fail() {
    let tests = vec![
        ("43010203", "expected int/tstr"),
        ("", "decode CBOR failure: Io(EndOfFile"),
        ("1e", "decode CBOR failure: Syntax"),
        ("0202", "extraneous data"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = Label::from_slice(&data);
        expect_err(result, err_msg);
    }
}

#[test]
fn test_registered_label_encode() {
    let tests = vec![
        (RegisteredLabel::Assigned(iana::Algorithm::A192GCM), "02"),
        (RegisteredLabel::Assigned(iana::Algorithm::EdDSA), "27"),
        (RegisteredLabel::Text("abc".to_owned()), "63616263"),
    ];

    for (i, (label, label_data)) in tests.iter().enumerate() {
        let got = label.clone().to_vec().unwrap();
        assert_eq!(*label_data, hex::encode(&got), "case {}", i);

        let got = RegisteredLabel::from_slice(&got).unwrap();
        assert_eq!(*label, got);
    }
}

#[test]
fn test_registered_label_sort() {
    use RegisteredLabel::{Assigned, Text};
    // Pairs of `RegisteredLabel`s with the "smaller" first.
    let pairs = vec![
        (Assigned(iana::Algorithm::A192GCM), Text("a".to_owned())),
        (Assigned(iana::Algorithm::WalnutDSA), Text("ab".to_owned())),
        (Text("ab".to_owned()), Text("cd".to_owned())),
        (Text("ab".to_owned()), Text("abcd".to_owned())),
        (
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
            Assigned(iana::Algorithm::A128KW),
        ),
        (
            Assigned(iana::Algorithm::A192GCM),
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
        ),
    ];
    for (left, right) in pairs.into_iter() {
        let value_cmp = left.cmp(&right);
        let value_partial_cmp = left.partial_cmp(&right);
        let left_data = left.clone().to_vec().unwrap();
        let right_data = right.clone().to_vec().unwrap();
        let data_cmp = left_data.cmp(&right_data);
        let reverse_cmp = right.cmp(&left);
        let equal_cmp = left.cmp(&left);

        assert_eq!(value_cmp, Ordering::Less, "{:?} < {:?}", left, right);
        assert_eq!(
            value_partial_cmp,
            Some(Ordering::Less),
            "{:?} < {:?}",
            left,
            right
        );
        assert_eq!(
            data_cmp,
            Ordering::Less,
            "{:?}={} < {:?}={}",
            left,
            hex::encode(&left_data),
            right,
            hex::encode(&right_data)
        );
        assert_eq!(reverse_cmp, Ordering::Greater, "{:?} > {:?}", right, left);
        assert_eq!(equal_cmp, Ordering::Equal, "{:?} = {:?}", left, left);
    }
}

#[test]
fn test_registered_label_decode_fail() {
    let tests = vec![
        ("43010203", "expected int/tstr"),
        ("", "decode CBOR failure: Io(EndOfFile"),
        ("09", "expected recognized IANA value"),
        ("394e1f", "expected recognized IANA value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabel::<iana::EllipticCurve>::from_slice(&data);
        expect_err(result, err_msg);
    }
}

iana_registry! {
    TestPrivateLabel {
        Reserved: 0,
        Something: 1,
    }
}

impl WithPrivateRange for TestPrivateLabel {
    fn is_private(i: i64) -> bool {
        i > 10 || i < 1000
    }
}

#[test]
fn test_registered_label_with_private_encode() {
    let tests = vec![
        (
            RegisteredLabelWithPrivate::Assigned(TestPrivateLabel::Something),
            "01",
        ),
        (
            RegisteredLabelWithPrivate::Text("abc".to_owned()),
            "63616263",
        ),
        (
            RegisteredLabelWithPrivate::PrivateUse(-70_000),
            "3a0001116f",
        ),
        (RegisteredLabelWithPrivate::PrivateUse(11), "0b"),
    ];

    for (i, (label, label_data)) in tests.iter().enumerate() {
        let got = label.clone().to_vec().unwrap();
        assert_eq!(*label_data, hex::encode(&got), "case {}", i);

        let got = RegisteredLabelWithPrivate::from_slice(&got).unwrap();
        assert_eq!(*label, got);
    }
}

#[test]
fn test_registered_label_with_private_sort() {
    use RegisteredLabelWithPrivate::{Assigned, PrivateUse, Text};
    // Pairs of `RegisteredLabelWithPrivate`s with the "smaller" first.
    let pairs = vec![
        (Assigned(iana::Algorithm::A192GCM), Text("a".to_owned())),
        (Assigned(iana::Algorithm::WalnutDSA), Text("ab".to_owned())),
        (Text("ab".to_owned()), Text("cd".to_owned())),
        (Text("ab".to_owned()), Text("abcd".to_owned())),
        (
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
            Assigned(iana::Algorithm::A128KW),
        ),
        (
            Assigned(iana::Algorithm::A192GCM),
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
        ),
        (
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
            PrivateUse(-70_000),
        ),
        (PrivateUse(-70_000), PrivateUse(-70_001)),
        (PrivateUse(-70_000), Text("a".to_owned())),
    ];
    for (left, right) in pairs.into_iter() {
        let value_cmp = left.cmp(&right);
        let value_partial_cmp = left.partial_cmp(&right);
        let left_data = left.clone().to_vec().unwrap();
        let right_data = right.clone().to_vec().unwrap();
        let data_cmp = left_data.cmp(&right_data);
        let reverse_cmp = right.cmp(&left);
        let equal_cmp = left.cmp(&left);

        assert_eq!(value_cmp, Ordering::Less, "{:?} < {:?}", left, right);
        assert_eq!(
            value_partial_cmp,
            Some(Ordering::Less),
            "{:?} < {:?}",
            left,
            right
        );
        assert_eq!(
            data_cmp,
            Ordering::Less,
            "{:?}={} < {:?}={}",
            left,
            hex::encode(&left_data),
            right,
            hex::encode(&right_data)
        );
        assert_eq!(reverse_cmp, Ordering::Greater, "{:?} > {:?}", right, left);
        assert_eq!(equal_cmp, Ordering::Equal, "{:?} = {:?}", left, left);
    }
}

#[test]
fn test_registered_label_with_private_decode_fail() {
    let tests = vec![
        ("43010203", "expected int/tstr"),
        ("", "decode CBOR failure: Io(EndOfFile"),
        ("09", "expected value in IANA or private use range"),
        ("394e1f", "expected value in IANA or private use range"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabelWithPrivate::<iana::Algorithm>::from_slice(&data);
        expect_err(result, err_msg);
    }
}

// The most negative integer value that can be encoded in CBOR is:
//    0x3B (0b001_11011) 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
// which is -18_446_744_073_709_551_616 (-1 - 18_446_744_073_709_551_615).
//
// However, this crate uses `i64` for all integers, which cannot hold
// negative values below `i64::MIN` (=-2^63 = 0x8000000000000000).
const CBOR_NINT_MIN_HEX: &str = "3b7fffffffffffffff";
const CBOR_NINT_OUT_OF_RANGE_HEX: &str = "3b8000000000000000";

// The largest positive integer value that can be encoded in CBOR is:
//    0x1B (0b000_11011) 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
// which is 18_446_744_073_709_551_615.
//
// However, this crate uses `i64` for all integers, which cannot hold
// positive values above `i64::MAX` (=-2^63 - 1 = 0x7fffffffffffffff).
const CBOR_INT_MAX_HEX: &str = "1b7fffffffffffffff";
const CBOR_INT_OUT_OF_RANGE_HEX: &str = "1b8000000000000000";

#[test]
fn test_large_label_decode() {
    let tests = vec![(CBOR_NINT_MIN_HEX, i64::MIN), (CBOR_INT_MAX_HEX, i64::MAX)];
    for (label_data, want) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let got = Label::from_slice(&data).unwrap();
        assert_eq!(got, Label::Int(*want))
    }
}

#[test]
fn test_large_label_decode_fail() {
    let tests = vec![
        (CBOR_NINT_OUT_OF_RANGE_HEX, "out of range integer value"),
        (CBOR_INT_OUT_OF_RANGE_HEX, "out of range integer value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = Label::from_slice(&data);
        expect_err(result, err_msg);
    }
}

#[test]
fn test_large_registered_label_decode_fail() {
    let tests = vec![
        (CBOR_NINT_OUT_OF_RANGE_HEX, "out of range integer value"),
        (CBOR_INT_OUT_OF_RANGE_HEX, "out of range integer value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabel::<crate::iana::HeaderParameter>::from_slice(&data);
        expect_err(result, err_msg);
    }
}

#[test]
fn test_large_registered_label_with_private_decode_fail() {
    let tests = vec![
        (CBOR_NINT_OUT_OF_RANGE_HEX, "out of range integer value"),
        (CBOR_INT_OUT_OF_RANGE_HEX, "out of range integer value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabelWithPrivate::<crate::iana::HeaderParameter>::from_slice(&data);
        expect_err(result, err_msg);
    }
}
<commit_msg>Extra test case for formatting EncodeFailed<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

use super::*;
use crate::util::expect_err;
use alloc::{borrow::ToOwned, format, vec};
use core::cmp::Ordering;

#[test]
fn test_error_convert() {
    let e = CoseError::from(crate::cbor::ser::Error::<String>::Value(
        "error message lost".to_owned(),
    ));
    match e {
        CoseError::EncodeFailed => {
            assert!(format!("{:?}", e).contains("encode CBOR failure"));
        }
        _ => panic!("unexpected error enum after conversion"),
    }
}

#[test]
fn test_label_encode() {
    let tests = vec![
        (Label::Int(2), "02"),
        (Label::Int(-1), "20"),
        (Label::Text("abc".to_owned()), "63616263"),
    ];

    for (i, (label, label_data)) in tests.iter().enumerate() {
        let got = label.clone().to_vec().unwrap();
        assert_eq!(*label_data, hex::encode(&got), "case {}", i);

        let got = Label::from_slice(&got).unwrap();
        assert_eq!(*label, got);
    }
}

#[test]
fn test_label_sort() {
    // Pairs of `Label`s with the "smaller" first.
    let pairs = vec![
        (Label::Int(0x1234), Label::Text("a".to_owned())),
        (Label::Int(0x1234), Label::Text("ab".to_owned())),
        (Label::Int(0), Label::Text("ab".to_owned())),
        (Label::Int(-1), Label::Text("ab".to_owned())),
        (Label::Int(0), Label::Int(10)),
        (Label::Int(0), Label::Int(-10)),
        (Label::Int(10), Label::Int(-1)),
        (Label::Int(-1), Label::Int(-2)),
        (Label::Int(0x12), Label::Int(0x1234)),
        (Label::Int(0x99), Label::Int(0x1234)),
        (Label::Int(0x1234), Label::Int(0x1235)),
        (Label::Text("a".to_owned()), Label::Text("ab".to_owned())),
        (Label::Text("aa".to_owned()), Label::Text("ab".to_owned())),
    ];
    for (left, right) in pairs.into_iter() {
        let value_cmp = left.cmp(&right);
        let value_partial_cmp = left.partial_cmp(&right);
        let left_data = left.clone().to_vec().unwrap();
        let right_data = right.clone().to_vec().unwrap();
        let data_cmp = left_data.cmp(&right_data);
        let reverse_cmp = right.cmp(&left);
        let equal_cmp = left.cmp(&left);

        assert_eq!(value_cmp, Ordering::Less, "{:?} < {:?}", left, right);
        assert_eq!(
            value_partial_cmp,
            Some(Ordering::Less),
            "{:?} < {:?}",
            left,
            right
        );
        assert_eq!(
            data_cmp,
            Ordering::Less,
            "{:?}={} < {:?}={}",
            left,
            hex::encode(&left_data),
            right,
            hex::encode(&right_data)
        );
        assert_eq!(reverse_cmp, Ordering::Greater, "{:?} > {:?}", right, left);
        assert_eq!(equal_cmp, Ordering::Equal, "{:?} = {:?}", left, left);
    }
}

#[test]
fn test_label_decode_fail() {
    let tests = vec![
        ("43010203", "expected int/tstr"),
        ("", "decode CBOR failure: Io(EndOfFile"),
        ("1e", "decode CBOR failure: Syntax"),
        ("0202", "extraneous data"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = Label::from_slice(&data);
        expect_err(result, err_msg);
    }
}

#[test]
fn test_registered_label_encode() {
    let tests = vec![
        (RegisteredLabel::Assigned(iana::Algorithm::A192GCM), "02"),
        (RegisteredLabel::Assigned(iana::Algorithm::EdDSA), "27"),
        (RegisteredLabel::Text("abc".to_owned()), "63616263"),
    ];

    for (i, (label, label_data)) in tests.iter().enumerate() {
        let got = label.clone().to_vec().unwrap();
        assert_eq!(*label_data, hex::encode(&got), "case {}", i);

        let got = RegisteredLabel::from_slice(&got).unwrap();
        assert_eq!(*label, got);
    }
}

#[test]
fn test_registered_label_sort() {
    use RegisteredLabel::{Assigned, Text};
    // Pairs of `RegisteredLabel`s with the "smaller" first.
    let pairs = vec![
        (Assigned(iana::Algorithm::A192GCM), Text("a".to_owned())),
        (Assigned(iana::Algorithm::WalnutDSA), Text("ab".to_owned())),
        (Text("ab".to_owned()), Text("cd".to_owned())),
        (Text("ab".to_owned()), Text("abcd".to_owned())),
        (
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
            Assigned(iana::Algorithm::A128KW),
        ),
        (
            Assigned(iana::Algorithm::A192GCM),
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
        ),
    ];
    for (left, right) in pairs.into_iter() {
        let value_cmp = left.cmp(&right);
        let value_partial_cmp = left.partial_cmp(&right);
        let left_data = left.clone().to_vec().unwrap();
        let right_data = right.clone().to_vec().unwrap();
        let data_cmp = left_data.cmp(&right_data);
        let reverse_cmp = right.cmp(&left);
        let equal_cmp = left.cmp(&left);

        assert_eq!(value_cmp, Ordering::Less, "{:?} < {:?}", left, right);
        assert_eq!(
            value_partial_cmp,
            Some(Ordering::Less),
            "{:?} < {:?}",
            left,
            right
        );
        assert_eq!(
            data_cmp,
            Ordering::Less,
            "{:?}={} < {:?}={}",
            left,
            hex::encode(&left_data),
            right,
            hex::encode(&right_data)
        );
        assert_eq!(reverse_cmp, Ordering::Greater, "{:?} > {:?}", right, left);
        assert_eq!(equal_cmp, Ordering::Equal, "{:?} = {:?}", left, left);
    }
}

#[test]
fn test_registered_label_decode_fail() {
    let tests = vec![
        ("43010203", "expected int/tstr"),
        ("", "decode CBOR failure: Io(EndOfFile"),
        ("09", "expected recognized IANA value"),
        ("394e1f", "expected recognized IANA value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabel::<iana::EllipticCurve>::from_slice(&data);
        expect_err(result, err_msg);
    }
}

iana_registry! {
    TestPrivateLabel {
        Reserved: 0,
        Something: 1,
    }
}

impl WithPrivateRange for TestPrivateLabel {
    fn is_private(i: i64) -> bool {
        i > 10 || i < 1000
    }
}

#[test]
fn test_registered_label_with_private_encode() {
    let tests = vec![
        (
            RegisteredLabelWithPrivate::Assigned(TestPrivateLabel::Something),
            "01",
        ),
        (
            RegisteredLabelWithPrivate::Text("abc".to_owned()),
            "63616263",
        ),
        (
            RegisteredLabelWithPrivate::PrivateUse(-70_000),
            "3a0001116f",
        ),
        (RegisteredLabelWithPrivate::PrivateUse(11), "0b"),
    ];

    for (i, (label, label_data)) in tests.iter().enumerate() {
        let got = label.clone().to_vec().unwrap();
        assert_eq!(*label_data, hex::encode(&got), "case {}", i);

        let got = RegisteredLabelWithPrivate::from_slice(&got).unwrap();
        assert_eq!(*label, got);
    }
}

#[test]
fn test_registered_label_with_private_sort() {
    use RegisteredLabelWithPrivate::{Assigned, PrivateUse, Text};
    // Pairs of `RegisteredLabelWithPrivate`s with the "smaller" first.
    let pairs = vec![
        (Assigned(iana::Algorithm::A192GCM), Text("a".to_owned())),
        (Assigned(iana::Algorithm::WalnutDSA), Text("ab".to_owned())),
        (Text("ab".to_owned()), Text("cd".to_owned())),
        (Text("ab".to_owned()), Text("abcd".to_owned())),
        (
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
            Assigned(iana::Algorithm::A128KW),
        ),
        (
            Assigned(iana::Algorithm::A192GCM),
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
        ),
        (
            Assigned(iana::Algorithm::AES_CCM_16_64_128),
            PrivateUse(-70_000),
        ),
        (PrivateUse(-70_000), PrivateUse(-70_001)),
        (PrivateUse(-70_000), Text("a".to_owned())),
    ];
    for (left, right) in pairs.into_iter() {
        let value_cmp = left.cmp(&right);
        let value_partial_cmp = left.partial_cmp(&right);
        let left_data = left.clone().to_vec().unwrap();
        let right_data = right.clone().to_vec().unwrap();
        let data_cmp = left_data.cmp(&right_data);
        let reverse_cmp = right.cmp(&left);
        let equal_cmp = left.cmp(&left);

        assert_eq!(value_cmp, Ordering::Less, "{:?} < {:?}", left, right);
        assert_eq!(
            value_partial_cmp,
            Some(Ordering::Less),
            "{:?} < {:?}",
            left,
            right
        );
        assert_eq!(
            data_cmp,
            Ordering::Less,
            "{:?}={} < {:?}={}",
            left,
            hex::encode(&left_data),
            right,
            hex::encode(&right_data)
        );
        assert_eq!(reverse_cmp, Ordering::Greater, "{:?} > {:?}", right, left);
        assert_eq!(equal_cmp, Ordering::Equal, "{:?} = {:?}", left, left);
    }
}

#[test]
fn test_registered_label_with_private_decode_fail() {
    let tests = vec![
        ("43010203", "expected int/tstr"),
        ("", "decode CBOR failure: Io(EndOfFile"),
        ("09", "expected value in IANA or private use range"),
        ("394e1f", "expected value in IANA or private use range"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabelWithPrivate::<iana::Algorithm>::from_slice(&data);
        expect_err(result, err_msg);
    }
}

// The most negative integer value that can be encoded in CBOR is:
//    0x3B (0b001_11011) 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
// which is -18_446_744_073_709_551_616 (-1 - 18_446_744_073_709_551_615).
//
// However, this crate uses `i64` for all integers, which cannot hold
// negative values below `i64::MIN` (=-2^63 = 0x8000000000000000).
const CBOR_NINT_MIN_HEX: &str = "3b7fffffffffffffff";
const CBOR_NINT_OUT_OF_RANGE_HEX: &str = "3b8000000000000000";

// The largest positive integer value that can be encoded in CBOR is:
//    0x1B (0b000_11011) 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
// which is 18_446_744_073_709_551_615.
//
// However, this crate uses `i64` for all integers, which cannot hold
// positive values above `i64::MAX` (=-2^63 - 1 = 0x7fffffffffffffff).
const CBOR_INT_MAX_HEX: &str = "1b7fffffffffffffff";
const CBOR_INT_OUT_OF_RANGE_HEX: &str = "1b8000000000000000";

#[test]
fn test_large_label_decode() {
    let tests = vec![(CBOR_NINT_MIN_HEX, i64::MIN), (CBOR_INT_MAX_HEX, i64::MAX)];
    for (label_data, want) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let got = Label::from_slice(&data).unwrap();
        assert_eq!(got, Label::Int(*want))
    }
}

#[test]
fn test_large_label_decode_fail() {
    let tests = vec![
        (CBOR_NINT_OUT_OF_RANGE_HEX, "out of range integer value"),
        (CBOR_INT_OUT_OF_RANGE_HEX, "out of range integer value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = Label::from_slice(&data);
        expect_err(result, err_msg);
    }
}

#[test]
fn test_large_registered_label_decode_fail() {
    let tests = vec![
        (CBOR_NINT_OUT_OF_RANGE_HEX, "out of range integer value"),
        (CBOR_INT_OUT_OF_RANGE_HEX, "out of range integer value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabel::<crate::iana::HeaderParameter>::from_slice(&data);
        expect_err(result, err_msg);
    }
}

#[test]
fn test_large_registered_label_with_private_decode_fail() {
    let tests = vec![
        (CBOR_NINT_OUT_OF_RANGE_HEX, "out of range integer value"),
        (CBOR_INT_OUT_OF_RANGE_HEX, "out of range integer value"),
    ];
    for (label_data, err_msg) in tests.iter() {
        let data = hex::decode(label_data).unwrap();
        let result = RegisteredLabelWithPrivate::<crate::iana::HeaderParameter>::from_slice(&data);
        expect_err(result, err_msg);
    }
}
<|endoftext|>


<commit_before>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey};
use lib::setting::Cron;

#[derive(Debug)]
pub struct Start;

impl Command for Start {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Start);
    }

    fn main(&self) -> Result<(), CliError> {
        let cron = try!(Cron::read());

        let pair_for_burn = ("0 0 * * *", "burn");

        let config        = try!(Config::read());
        let day_and_month = match try!(config.get(ConfigKey::SweepPeriod)).as_ref() {
            "daily"  => "* * *",
            "weekly" => "* * 0",
            _        => unreachable!("Mistake SweepPeriod's validation!!"),
        };
        let (hour, minute) = Config::to_hour_and_minute(try!(config.get(ConfigKey::SweepTime)));
        let when = format!("{} {} {}", minute, hour, day_and_month);
        let pair_for_sweep = (&when as &str, "sweep");

        let new_cron = try!(cron.update(&[pair_for_burn, pair_for_sweep]));
        try!(new_cron.set());

        Ok(())
    }
}
<commit_msg>[Refactoring] Use Result.and_then()<commit_after>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey};
use lib::setting::Cron;

#[derive(Debug)]
pub struct Start;

impl Command for Start {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Start);
    }

    fn main(&self) -> Result<(), CliError> {
        let cron = try!(Cron::read());

        let pair_for_burn = ("0 0 * * *", "burn");

        let config        = try!(Config::read());
        let day_and_month = match try!(config.get(ConfigKey::SweepPeriod)).as_ref() {
            "daily"  => "* * *",
            "weekly" => "* * 0",
            _        => unreachable!("Mistake SweepPeriod's validation!!"),
        };
        let (hour, minute) = Config::to_hour_and_minute(try!(config.get(ConfigKey::SweepTime)));
        let when = format!("{} {} {}", minute, hour, day_and_month);
        let pair_for_sweep = (&when as &str, "sweep");

        cron
            .update(&[pair_for_burn, pair_for_sweep])
            .and_then(|new_cron| new_cron.set())
    }
}
<|endoftext|>