<commit_before>use std::io::{BufWriter, BufRead, Write};
use std::io;

pub struct ByteStreamSplitter<'a> {
    buffer: Vec<u8>,
    match_pointer: usize,
    peek_buffer: Vec<u8>,
    separator: &'a [u8],
    input: &'a mut BufRead,
    started_splitting: bool,
    end_of_stream_reached: bool,
}

pub type SplitResult<T> = Result<T,SplitError>;

#[derive(Debug)]
pub enum SplitType {
    Prefix,
    FullMatch,
    Suffix
}

#[derive(Debug)]
pub enum SplitError {
    Io(io::Error),
    Internal(String)
}

impl std::fmt::Display for SplitError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            SplitError::Io(ref e) => e.fmt(f),
            SplitError::Internal(ref s) => write!(f,"{}", s)
        }
    }
}

impl std::error::Error for SplitError {
    fn description(&self) -> &str{
        match *self {
            SplitError::Io(ref e) => e.description(),
            SplitError::Internal(ref s) => s
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            SplitError::Io(ref e) => Some(e),
            SplitError::Internal(_) => None
        }
    }
}

impl From<io::Error> for SplitError {
    fn from(e: io::Error) -> Self {
        SplitError::Io(e)
    }
}

impl<'a> ByteStreamSplitter<'a> {
    pub fn new(input: &'a mut BufRead, separator: &'a [u8]) -> ByteStreamSplitter<'a>{
        ByteStreamSplitter{
            input: input,
            match_pointer: 0,
            separator: separator,
            buffer: Vec::new(),
            peek_buffer:Vec::new(),
            started_splitting: false,
            end_of_stream_reached: false,
        }
    }

    pub fn read_until_next_matching_byte(&mut self) -> io::Result<usize> {
        self.input.read_until(self.separator[self.match_pointer], &mut self.buffer)
    }

    pub fn next_to_buf(&mut self, output: &mut Write) -> SplitResult<SplitType>{

        if self.end_of_stream_reached {
            return Err(SplitError::Io(io::Error::new(io::ErrorKind::InvalidInput, "Stream has no more data.")));
        }

        let mut part_result: Option<SplitType> = Option::None;
        while part_result.is_none() {
            let num_bytes = try!(self.read_until_next_matching_byte());

            part_result = match num_bytes {
                0 => {
                    self.end_of_stream_reached = true;
                    try!(output.write_all(&self.peek_buffer));
                    self.peek_buffer.clear();
                    Some(SplitType::Suffix)
                },
                1 => {
                    self.peek_buffer.push(self.buffer[0]);

                    if self.match_pointer < self.separator.len()-1 {
                        self.match_pointer +=1;
                        None
                    }else {
                        self.match_pointer = 0;
                        if self.started_splitting {
                            Some(SplitType::FullMatch)
                        } else {
                            self.started_splitting = true;
                            Some(SplitType::Prefix)
                        }
                    }
                },
                _ => {
                    try!(output.write_all(&self.peek_buffer));
                    self.peek_buffer.clear();

                    match self.match_pointer {
                        0 => {
                            self.match_pointer+=1;
                            self.peek_buffer.push(self.buffer[self.buffer.len()-1]);
                            try!(output.write_all(&self.buffer[..self.buffer.len()-1]));
                        },
                        _ => {
                            self.match_pointer=0;
                            try!(output.write_all(&self.buffer));
                        }
                    }
                    None
                }
            };
            self.buffer.clear();
        }
        part_result.ok_or(SplitError::Internal("Scan finished without succeeding or failing. This should never happen!".to_string()))
    }
}

impl <'a> Iterator for ByteStreamSplitter<'a> {
    type Item = SplitResult<Vec<u8>>;

    fn next(&mut self) -> Option<SplitResult<Vec<u8>>> {
        if self.end_of_stream_reached {
            None
        } else {
            let mut part = BufWriter::new(Vec::new());
            let result = self.next_to_buf(&mut part)
            .and(part.flush().map_err(SplitError::Io))
            .and(part.into_inner().map_err(|e|SplitError::Internal(e.to_string())));
            match result {
                Ok(inner) => Some(Ok(inner)),
                _   => None
            }
        }
   }
}

#[test]
fn test_with_prefix() {
    let separator = [0x00, 0x00];
    let mut data = io::Cursor::new(vec![
        0xAA, 0xAB,                     // Prefix
        0x00, 0x00, 0x01, 0x02, 0x03,   // FullMatch
        0x00, 0x00, 0x04, 0x05, 0x06,   // FullMatch
        0x00, 0x00, 0x07, 0x08          // Suffix
        ]);

    let mut splitter = ByteStreamSplitter::new(&mut data, &separator);
    let prefix = splitter.next().unwrap().unwrap();
    let match1 = splitter.next().unwrap().unwrap();
    let match2 = splitter.next().unwrap().unwrap();
    let suffix = splitter.next().unwrap().unwrap();

    assert_eq!(prefix, vec![0xAA, 0xAB]);
    assert_eq!(match1, vec![0x00, 0x00, 0x01, 0x02, 0x03]);
    assert_eq!(match2, vec![0x00, 0x00, 0x04, 0x05, 0x06]);
    assert_eq!(suffix, vec![0x00, 0x00, 0x07, 0x08]);
}

#[test]
fn test_without_prefix() {
    let separator = [0x00, 0x00];
    let mut data = io::Cursor::new(vec![
        0x00, 0x00, 0x01, 0x02, 0x03,   // FullMatch
        0x00, 0x00, 0x04, 0x05, 0x06,   // FullMatch
        0x00, 0x00, 0x07, 0x08          // Suffix
        ]);

    let mut splitter = ByteStreamSplitter::new(&mut data, &separator);
    let prefix = splitter.next().unwrap().unwrap();
    let match1 = splitter.next().unwrap().unwrap();
    let match2 = splitter.next().unwrap().unwrap();
    let suffix = splitter.next().unwrap().unwrap();

    assert_eq!(prefix, vec![]);
    assert_eq!(match1, vec![0x00, 0x00, 0x01, 0x02, 0x03]);
    assert_eq!(match2, vec![0x00, 0x00, 0x04, 0x05, 0x06]);
    assert_eq!(suffix, vec![0x00, 0x00, 0x07, 0x08]);
}
<commit_msg>completely refactored matching algorithm and the separator pattern is no more part of the matches<commit_after>use std::io::{BufWriter, BufRead, Write, Bytes};
use std::io;
use std::collections::VecDeque;

pub struct ByteStreamSplitter<'a,T: 'a> {
    separator: &'a [u8],
    input: Bytes<T>,
    started_splitting: bool,
    end_of_stream_reached: bool
}

pub type SplitResult<T> = Result<T,SplitError>;

#[derive(Debug)]
pub enum SplitType {
    Prefix,
    FullMatch,
    Suffix
}

#[derive(Debug)]
pub enum SplitError {
    Io(io::Error),
    Internal(String)
}

impl std::fmt::Display for SplitError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            SplitError::Io(ref e) => e.fmt(f),
            SplitError::Internal(ref s) => write!(f,"{}", s)
        }
    }
}

impl std::error::Error for SplitError {
    fn description(&self) -> &str{
        match *self {
            SplitError::Io(ref e) => e.description(),
            SplitError::Internal(ref s) => s
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            SplitError::Io(ref e) => Some(e),
            SplitError::Internal(_) => None
        }
    }
}

impl From<io::Error> for SplitError {
    fn from(e: io::Error) -> Self {
        SplitError::Io(e)
    }
}

impl<'a, T> ByteStreamSplitter<'a,T> where T: BufRead + Sized{
    pub fn new(input: T, separator: &'a [u8]) -> ByteStreamSplitter<'a, T>{
        ByteStreamSplitter{
            input: input.bytes(),
            separator: separator,
            started_splitting: false,
            end_of_stream_reached: false
        }
    }

    pub fn next_to_buf(&mut self, output: &mut Write) -> SplitResult<SplitType>{

        if self.end_of_stream_reached {
            return Err(SplitError::Io(io::Error::new(io::ErrorKind::InvalidInput, "Stream has no more data.")));
        }

        let mut bytes = VecDeque::new();
        for b in self.input.by_ref().take(self.separator.len()) {
            bytes.push_back(try!(b));
        }
        while self.separator.iter().ne(bytes.iter()){
            let front_byte = try!(bytes.pop_front().ok_or(SplitError::Internal("This should never fail and must be a bug!".to_string())));
            try!(output.write(&[front_byte]));
            let next_byte = self.input.by_ref().next();
            if let Some(r) = next_byte {
                bytes.push_back(try!(r));
            }else {
                self.end_of_stream_reached = true;
                break;
            }
        }

        if self.end_of_stream_reached {
            try!(output.write_all(&bytes.into_iter().collect::<Vec<_>>()[..]));
            Ok(SplitType::Suffix)
        }else if self.started_splitting {
            Ok(SplitType::FullMatch)
        }else {
            self.started_splitting = true;
            Ok(SplitType::Prefix)
        }

    }
}

impl <'a,T> Iterator for ByteStreamSplitter<'a,T> where T: BufRead + Sized{
    type Item = SplitResult<Vec<u8>>;

    fn next(&mut self) -> Option<SplitResult<Vec<u8>>> {
        if self.end_of_stream_reached {
            None
        } else {
            let mut part = BufWriter::new(Vec::new());
            let result = self.next_to_buf(&mut part)
            .and(part.flush().map_err(SplitError::Io))
            .and(part.into_inner().map_err(|e|SplitError::Internal(e.to_string())));
            match result {
                Ok(inner) => Some(Ok(inner)),
                _   => None
            }
        }
   }
}

#[test]
fn test_with_prefix() {
    let separator = [0x00, 0x00];
    let mut data = io::Cursor::new(vec![
        0xAA, 0xAB,                     // Prefix
        0x00, 0x00, 0x01, 0x02, 0x03,   // FullMatch
        0x00, 0x00, 0x04, 0x05, 0x06,   // FullMatch
        0x00, 0x00, 0x07, 0x08          // Suffix
        ]);

    let mut splitter = ByteStreamSplitter::new(&mut data, &separator);
    let prefix = splitter.next().unwrap().unwrap();
    let match1 = splitter.next().unwrap().unwrap();
    let match2 = splitter.next().unwrap().unwrap();
    let suffix = splitter.next().unwrap().unwrap();

    assert_eq!(prefix, vec![0xAA, 0xAB]);
    assert_eq!(match1, vec![0x01, 0x02, 0x03]);
    assert_eq!(match2, vec![0x04, 0x05, 0x06]);
    assert_eq!(suffix, vec![0x07, 0x08]);
}

#[test]
fn test_without_prefix() {
    let separator = [0x00, 0x00];
    let mut data = io::Cursor::new(vec![
        0x00, 0x00, 0x01, 0x02, 0x03,   // FullMatch
        0x00, 0x00, 0x04, 0x05, 0x06,   // FullMatch
        0x00, 0x00, 0x07, 0x08          // Suffix
        ]);

    let mut splitter = ByteStreamSplitter::new(&mut data, &separator);
    let prefix = splitter.next().unwrap().unwrap();
    let match1 = splitter.next().unwrap().unwrap();
    let match2 = splitter.next().unwrap().unwrap();
    let suffix = splitter.next().unwrap().unwrap();

    assert_eq!(prefix, vec![]);
    assert_eq!(match1, vec![0x01, 0x02, 0x03]);
    assert_eq!(match2, vec![0x04, 0x05, 0x06]);
    assert_eq!(suffix, vec![0x07, 0x08]);
}

#[test]
fn test_skip_bug() {
    let separator = [0x00, 0x00];
    let mut data = io::Cursor::new(vec![
        0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x00, 0x00, 0x00, 0x04, 0x05, 0x06,
        0x00, 0x00, 0x07, 0x08
        ]);

    let mut splitter = ByteStreamSplitter::new(&mut data, &separator);
    let prefix = splitter.next().unwrap().unwrap();
    println!("p{:?}", prefix);
    let match1 = splitter.next().unwrap().unwrap();
    println!("1m{:?}", match1);
    let match2 = splitter.next().unwrap().unwrap();
    println!("1m{:?}", match2);
    let suffix = splitter.next().unwrap().unwrap();
    println!("s{:?}", suffix);

    assert_eq!(prefix, vec![]);
    assert_eq!(match1, vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]);
    assert_eq!(match2, vec![0x00, 0x04, 0x05, 0x06]);
    assert_eq!(suffix, vec![0x07, 0x08]);
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate rand;
#[macro_use]
extern crate tokio_core;

pub use kcp::KCP;

mod kcp;

use std::io::{self, Read, Write};
use std::net::{SocketAddr, Shutdown};
use std::str;

use futures::{Future, failed, Poll, Async};
use tokio_core::io::{Io, IoFuture};
use tokio_core::net::UdpSocket;
use tokio_core::reactor::{Handle, PollEvented};

struct KcpTunnel {
    socket: UdpSocket,
    addr: SocketAddr,
}

impl Write for KcpTunnel {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = self.socket.send_to(buf, &self.addr).unwrap();
        if n == buf.len() {
            Ok(n)
        } else {
            Err(io::Error::new(io::ErrorKind::WouldBlock, "failed to send"))
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct KcpStream {
    io: UdpSocket,
    kcp: KCP,
    peer_addr: SocketAddr,
}

pub struct KcpStreamNew {
    inner: IoFuture<KcpStream>,
}

enum KcpStreamConnect {
    Waiting(KcpStream),
    Empty,
}

impl KcpStream {
    pub fn connect(addr: &SocketAddr, handle: &Handle) -> KcpStreamNew {
        let any = str::FromStr::from_str("0.0.0.0:0").unwrap();
        let future = match UdpSocket::bind(&any, handle) {
            Ok(udp) => KcpStream::new(udp, addr, handle),
            Err(e) => failed(e).boxed(),
        };
        KcpStreamNew { inner: future }
    }

    fn new(socket: UdpSocket, addr: &SocketAddr, handle: &Handle) -> IoFuture<KcpStream> {
        let conv = rand::random::<u32>();
        let kcp = KCP::new(conv);
        KcpStreamConnect::Waiting(KcpStream {
                io: socket,
                kcp: kcp,
                peer_addr: *addr,
            })
            .boxed()
    }

    pub fn connect_stream(// stream: net::TcpStream,
                          addr: &SocketAddr,
                          handle: &Handle)
                          -> IoFuture<KcpStream> {
        unimplemented!()
    }

    pub fn poll_read(&self) -> Async<()> {
        self.io.poll_read()
    }

    pub fn poll_write(&self) -> Async<()> {
        self.io.poll_write()
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.local_addr()
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        Ok(self.peer_addr)
    }

    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        unimplemented!()
    }

    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
        unimplemented!()
    }

    pub fn nodelay(&self) -> io::Result<bool> {
        unimplemented!()
    }

    pub fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
        unimplemented!()
    }

    pub fn keepalive_ms(&self) -> io::Result<Option<u32>> {
        unimplemented!()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.set_ttl(ttl)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.io.ttl()
    }
}

impl Read for KcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // self.io.read(buf)
        unimplemented!()
    }
}

impl Write for KcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // self.io.write(buf)
        unimplemented!()
    }
    fn flush(&mut self) -> io::Result<()> {
        // self.io.flush()
        unimplemented!()
    }
}

impl Io for KcpStream {
    fn poll_read(&mut self) -> Async<()> {
        <KcpStream>::poll_read(self)
    }

    fn poll_write(&mut self) -> Async<()> {
        <KcpStream>::poll_write(self)
    }
}

impl<'a> Read for &'a KcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // (&self.io).read(buf)
        unimplemented!()
    }
}

impl<'a> Write for &'a KcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // (&self.io).write(buf)
        unimplemented!()
    }

    fn flush(&mut self) -> io::Result<()> {
        // (&self.io).flush()
        unimplemented!()
    }
}

impl<'a> Io for &'a KcpStream {
    fn poll_read(&mut self) -> Async<()> {
        <KcpStream>::poll_read(self)
    }

    fn poll_write(&mut self) -> Async<()> {
        <KcpStream>::poll_write(self)
    }
}

impl Future for KcpStreamNew {
    type Item = KcpStream;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<KcpStream, io::Error> {
        self.inner.poll()
    }
}

impl Future for KcpStreamConnect {
    type Item = KcpStream;
    type Error = io::Error;

    fn poll(&mut self) -> futures::Poll<KcpStream, io::Error> {
        unimplemented!()
    }
}
<commit_msg>Update<commit_after>extern crate futures;
extern crate rand;
#[macro_use]
extern crate tokio_core;
extern crate time;

pub use kcp::KCP;

mod kcp;

use std::io::{self, Read, Write};
use std::net::{SocketAddr, Shutdown};
use std::str;

use futures::{Future, failed, Poll, Async};
use tokio_core::io::{Io, IoFuture};
use tokio_core::net::UdpSocket;
use tokio_core::reactor::{Handle, PollEvented};

fn clock() -> u32 {
    let timespec = time::get_time();
    let mills = timespec.sec * 1000 + timespec.nsec as i64 / 1000 / 1000;
    mills as u32
}

struct KcpTunnel {
    socket: UdpSocket,
    addr: SocketAddr,
}

impl Write for KcpTunnel {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = self.socket.send_to(buf, &self.addr).unwrap();
        if n == buf.len() {
            Ok(n)
        } else {
            Err(io::Error::new(io::ErrorKind::WouldBlock, "failed to send"))
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct KcpStream {
    io: UdpSocket,
    kcp: KCP,
    peer_addr: SocketAddr,
}

pub struct KcpStreamNew {
    inner: IoFuture<KcpStream>,
}

enum KcpStreamConnect {
    Waiting(KcpStream),
    Empty,
}

impl KcpStream {
    pub fn connect(addr: &SocketAddr, handle: &Handle) -> KcpStreamNew {
        let any = str::FromStr::from_str("0.0.0.0:0").unwrap();
        let future = match UdpSocket::bind(&any, handle) {
            Ok(udp) => KcpStream::new(udp, addr, handle),
            Err(e) => failed(e).boxed(),
        };
        KcpStreamNew { inner: future }
    }

    fn new(socket: UdpSocket, addr: &SocketAddr, handle: &Handle) -> IoFuture<KcpStream> {
        let conv = rand::random::<u32>();
        let kcp = KCP::new(conv);
        KcpStreamConnect::Waiting(KcpStream {
                io: socket,
                kcp: kcp,
                peer_addr: *addr,
            })
            .boxed()
    }

    pub fn connect_stream(// stream: net::TcpStream,
                          addr: &SocketAddr,
                          handle: &Handle)
                          -> IoFuture<KcpStream> {
        unimplemented!()
    }

    pub fn poll_read(&self) -> Async<()> {
        self.io.poll_read()
    }

    pub fn poll_write(&self) -> Async<()> {
        self.io.poll_write()
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.local_addr()
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        Ok(self.peer_addr)
    }

    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        unimplemented!()
    }

    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
        unimplemented!()
    }

    pub fn nodelay(&self) -> io::Result<bool> {
        unimplemented!()
    }

    pub fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
        unimplemented!()
    }

    pub fn keepalive_ms(&self) -> io::Result<Option<u32>> {
        unimplemented!()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.set_ttl(ttl)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.io.ttl()
    }
}

impl Read for KcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // self.io.read(buf)
        unimplemented!()
    }
}

impl Write for KcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // self.io.write(buf)
        unimplemented!()
    }
    fn flush(&mut self) -> io::Result<()> {
        // self.io.flush()
        unimplemented!()
    }
}

impl Io for KcpStream {
    fn poll_read(&mut self) -> Async<()> {
        <KcpStream>::poll_read(self)
    }

    fn poll_write(&mut self) -> Async<()> {
        <KcpStream>::poll_write(self)
    }
}

impl<'a> Read for &'a KcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // (&self.io).read(buf)
        unimplemented!()
    }
}

impl<'a> Write for &'a KcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // (&self.io).write(buf)
        unimplemented!()
    }

    fn flush(&mut self) -> io::Result<()> {
        // (&self.io).flush()
        unimplemented!()
    }
}

impl<'a> Io for &'a KcpStream {
    fn poll_read(&mut self) -> Async<()> {
        <KcpStream>::poll_read(self)
    }

    fn poll_write(&mut self) -> Async<()> {
        <KcpStream>::poll_write(self)
    }
}

impl Future for KcpStreamNew {
    type Item = KcpStream;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<KcpStream, io::Error> {
        self.inner.poll()
    }
}

impl Future for KcpStreamConnect {
    type Item = KcpStream;
    type Error = io::Error;

    fn poll(&mut self) -> futures::Poll<KcpStream, io::Error> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use ::std::str;
use self::rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Card {
    suit:  String,
    value: String,
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

pub fn make_standard_deck() -> Vec<Card> {
    let mut result = Vec::new();
    let suits  = &["♣", "♦", "♥", "♠"];
    let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "Jack", "Queen", "King", "Ace"];

    for suit in suits {
        for value in values {
            result.push(Card::new_from_str(*suit, value));
        }
    }
    return result;
}

pub fn make_fifth_dimension_deck() -> Vec<Card> {
    let mut result = Vec::new();
    let suits  = &["♣", "♦", "♥", "♠", "★"];
    let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "Jack", "Princess", "Queen", "King", "Joker"];

    for suit in suits {
        for value in values {
            result.push(Card::new_from_str(*suit, value));
        }
    }
    return result;
}

pub fn shuffle(deck: &mut Vec<Card>) {
    rand::thread_rng().shuffle(deck);
}
<commit_msg>trying some stuff<commit_after>extern crate rand;
use std::str;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Card {
    suit:  String,
    value: String,
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

pub fn make_standard_deck() -> Vec<Card> {
    let mut result = Vec::new();
    let suits  = &["♣", "♦", "♥", "♠"];
    let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "Jack", "Queen", "King", "Ace"];

    for suit in suits {
        for value in values {
            result.push(Card::new_from_str(*suit, value));
        }
    }
    return result;
}

pub fn make_fifth_dimension_deck() -> Vec<Card> {
    let mut result = Vec::new();
    let suits  = &["♣", "♦", "♥", "♠", "★"];
    let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                   "Jack", "Princess", "Queen", "King", "Joker"];

    for suit in suits {
        for value in values {
            result.push(Card::new_from_str(*suit, value));
        }
    }
    return result;
}

pub fn shuffle(deck: &mut Vec<Card>) {
    rand::thread_rng().shuffle(deck);
}
<|endoftext|>


<commit_before>extern crate proc_macro;
extern crate proc_macro2;
extern crate syn;

extern crate quote;

use syn::{parse_macro_input, DeriveInput};

mod body_impl;
mod default_attr;
mod util;

/// # Smart Default
///
/// This crate provides a custom derive for `SmartDefault`. `SmartDefault` is not a real type -
/// deriving it will actually `impl Default`. The difference from regular `#[derive(Default)]` is
/// that `#[derive(SmartDefault)]` allows you to use `#[default = "..."]` attributes to customize
/// the `::default()` method and to support `struct`s that don't have `Default` for all their
/// fields - and even `enum`s!
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate smart_default;
///
/// # fn main() {
/// #[derive(SmartDefault)]
/// # #[derive(PartialEq)]
/// # #[allow(dead_code)]
/// enum Foo {
///     Bar,
///     #[default]
///     Baz {
///         #[default = 12]
///         a: i32,
///         b: i32,
///         #[default(Some(Default::default()))]
///         c: Option<i32>,
///         #[default(_code = "vec![1, 2, 3]")]
///         d: Vec<u32>,
///         #[default = "four"]
///         e: String,
///     },
///     Qux(i32),
/// }
///
/// assert!(Foo::default() == Foo::Baz {
///     a: 12,
///     b: 0,
///     c: Some(0),
///     d: vec![1, 2, 3],
///     e: "four".to_owned(),
/// });
/// # }
/// ```
///
/// * `Baz` has the `#[default]` attribute. This means that the default `Foo` is a `Foo::Baz`. Only
///   one variant may have a `#[default]` attribute, and that attribute must have no value.
/// * `a` has a `#[default = 12]` attribute. This means that it's default value is `12`.
/// * `b` has no `#[default = ...]` attribute. It's default value will `i32`'s default value
///   instead - `0`.
/// * `c` is an `Option<i32>`, and it's default is `Some(Default::default())`. Rust cannot (currently)
///   parse `#[default = Some(Default::default())]` and therefore we have to use a special syntax:
///   `#[default(Some(Default::default))]`
/// * `d` has the `!` token in it, which cannot (currently) be parsed even with `#[default(...)]`,
///   so we have to encode it as a string and mark it as `_code = `.
/// * `e` is a `String`, so the string literal "four" is automatically converted to it. This
///   automatic conversion **only** happens to string (or byte string) literals - and only if
///   `_code` is not used.
/// * Documentation for the `impl Default` section is generated automatically, specifying the
///   default value returned from `::default()`.
#[proc_macro_derive(SmartDefault, attributes(default))]
pub fn derive_smart_default(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    match body_impl::impl_my_derive(&input) {
        Ok(output) => {
            output.into()
        },
        Err(error) =>{
            error.to_compile_error().into()
        }
    }
}
<commit_msg>Changed "type" to "trait" in description of macro.<commit_after>extern crate proc_macro;
extern crate proc_macro2;
extern crate syn;

extern crate quote;

use syn::{parse_macro_input, DeriveInput};

mod body_impl;
mod default_attr;
mod util;

/// # Smart Default
///
/// This crate provides a custom derive for `SmartDefault`. `SmartDefault` is not a real trait -
/// deriving it will actually `impl Default`. The difference from regular `#[derive(Default)]` is
/// that `#[derive(SmartDefault)]` allows you to use `#[default = "..."]` attributes to customize
/// the `::default()` method and to support `struct`s that don't have `Default` for all their
/// fields - and even `enum`s!
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate smart_default;
///
/// # fn main() {
/// #[derive(SmartDefault)]
/// # #[derive(PartialEq)]
/// # #[allow(dead_code)]
/// enum Foo {
///     Bar,
///     #[default]
///     Baz {
///         #[default = 12]
///         a: i32,
///         b: i32,
///         #[default(Some(Default::default()))]
///         c: Option<i32>,
///         #[default(_code = "vec![1, 2, 3]")]
///         d: Vec<u32>,
///         #[default = "four"]
///         e: String,
///     },
///     Qux(i32),
/// }
///
/// assert!(Foo::default() == Foo::Baz {
///     a: 12,
///     b: 0,
///     c: Some(0),
///     d: vec![1, 2, 3],
///     e: "four".to_owned(),
/// });
/// # }
/// ```
///
/// * `Baz` has the `#[default]` attribute. This means that the default `Foo` is a `Foo::Baz`. Only
///   one variant may have a `#[default]` attribute, and that attribute must have no value.
/// * `a` has a `#[default = 12]` attribute. This means that it's default value is `12`.
/// * `b` has no `#[default = ...]` attribute. It's default value will `i32`'s default value
///   instead - `0`.
/// * `c` is an `Option<i32>`, and it's default is `Some(Default::default())`. Rust cannot (currently)
///   parse `#[default = Some(Default::default())]` and therefore we have to use a special syntax:
///   `#[default(Some(Default::default))]`
/// * `d` has the `!` token in it, which cannot (currently) be parsed even with `#[default(...)]`,
///   so we have to encode it as a string and mark it as `_code = `.
/// * `e` is a `String`, so the string literal "four" is automatically converted to it. This
///   automatic conversion **only** happens to string (or byte string) literals - and only if
///   `_code` is not used.
/// * Documentation for the `impl Default` section is generated automatically, specifying the
///   default value returned from `::default()`.
#[proc_macro_derive(SmartDefault, attributes(default))]
pub fn derive_smart_default(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    match body_impl::impl_my_derive(&input) {
        Ok(output) => {
            output.into()
        },
        Err(error) =>{
            error.to_compile_error().into()
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This library provides implementations of `Mutex`, `RwLock`, `Condvar` and
//! `Once` that are smaller, faster and more flexible than those in the Rust
//! standard library. It also provides a `ReentrantMutex` type.

#![warn(missing_docs)]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#![cfg_attr(feature = "nightly", feature(const_atomic_u8_new))]
#![cfg_attr(feature = "nightly", feature(const_atomic_usize_new))]
#![cfg_attr(feature = "nightly", feature(const_cell_new))]
#![cfg_attr(feature = "nightly", feature(const_ptr_null_mut))]
#![cfg_attr(feature = "nightly", feature(const_atomic_ptr_new))]
#![cfg_attr(feature = "nightly", feature(const_unsafe_cell_new))]
#![cfg_attr(feature = "nightly", feature(const_size_of))]
#![cfg_attr(feature = "nightly", feature(integer_atomics))]
#![cfg_attr(feature = "nightly", feature(asm))]

#[cfg(feature = "owning_ref")]
extern crate owning_ref;

extern crate parking_lot_core;

#[cfg(not(feature = "nightly"))]
mod stable;

mod util;
mod elision;
mod raw_mutex;
mod raw_remutex;
mod raw_rwlock;
mod condvar;
mod mutex;
mod remutex;
mod rwlock;
mod once;

#[cfg(feature = "deadlock_detection")]
pub mod deadlock;
#[cfg(not(feature = "deadlock_detection"))]
mod deadlock;

pub use once::{Once, ONCE_INIT, OnceState};
pub use mutex::{Mutex, MutexGuard};
pub use remutex::{ReentrantMutex, ReentrantMutexGuard};
pub use condvar::{Condvar, WaitTimeoutResult};
pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};

#[cfg(feature = "owning_ref")]
use owning_ref::OwningRef;

/// Typedef of an owning reference that uses a `MutexGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;

/// Typedef of an owning reference that uses a `ReentrantMutexGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type ReentrantMutexGuardRef<'a, T, U = T> = OwningRef<ReentrantMutexGuard<'a, T>, U>;

/// Typedef of an owning reference that uses a `RwLockReadGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;

/// Typedef of an owning reference that uses a `RwLockWriteGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
<commit_msg>add missing re-export and typedef for UpgradableGuard<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This library provides implementations of `Mutex`, `RwLock`, `Condvar` and
//! `Once` that are smaller, faster and more flexible than those in the Rust
//! standard library. It also provides a `ReentrantMutex` type.

#![warn(missing_docs)]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#![cfg_attr(feature = "nightly", feature(const_atomic_u8_new))]
#![cfg_attr(feature = "nightly", feature(const_atomic_usize_new))]
#![cfg_attr(feature = "nightly", feature(const_cell_new))]
#![cfg_attr(feature = "nightly", feature(const_ptr_null_mut))]
#![cfg_attr(feature = "nightly", feature(const_atomic_ptr_new))]
#![cfg_attr(feature = "nightly", feature(const_unsafe_cell_new))]
#![cfg_attr(feature = "nightly", feature(const_size_of))]
#![cfg_attr(feature = "nightly", feature(integer_atomics))]
#![cfg_attr(feature = "nightly", feature(asm))]

#[cfg(feature = "owning_ref")]
extern crate owning_ref;

extern crate parking_lot_core;

#[cfg(not(feature = "nightly"))]
mod stable;

mod util;
mod elision;
mod raw_mutex;
mod raw_remutex;
mod raw_rwlock;
mod condvar;
mod mutex;
mod remutex;
mod rwlock;
mod once;

#[cfg(feature = "deadlock_detection")]
pub mod deadlock;
#[cfg(not(feature = "deadlock_detection"))]
mod deadlock;

pub use once::{Once, ONCE_INIT, OnceState};
pub use mutex::{Mutex, MutexGuard};
pub use remutex::{ReentrantMutex, ReentrantMutexGuard};
pub use condvar::{Condvar, WaitTimeoutResult};
pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard, RwLockUpgradableReadGuard};

#[cfg(feature = "owning_ref")]
use owning_ref::OwningRef;

/// Typedef of an owning reference that uses a `MutexGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;

/// Typedef of an owning reference that uses a `ReentrantMutexGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type ReentrantMutexGuardRef<'a, T, U = T> = OwningRef<ReentrantMutexGuard<'a, T>, U>;

/// Typedef of an owning reference that uses a `RwLockReadGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;

/// Typedef of an owning reference that uses a `RwLockWriteGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;

/// Typedef of an owning reference that uses a `RwLockUpgradableReadGuard` as the owner.
#[cfg(feature = "owning_ref")]
pub type RwLockUpgradableReadGuardRef<'a, T, U = T> = OwningRef<RwLockUpgradableReadGuard<'a, T>, U>;
<|endoftext|>


<commit_before>#![deny(missing_docs, warnings)]
#![feature(io)]
#![feature(libc)]

//! Termios bindings + safe wrapper
//!
//! # Examples
//!
//! Check the [`Termios`](struct.Termios.html#method.fetch) struct.

extern crate libc;

use libc::c_int;
use std::default::Default;
use std::old_io::{IoError, IoResult};
use std::{fmt, mem};

use self::BaudRate::*;
use self::When::*;

pub mod control;
pub mod input;
pub mod local;
pub mod output;
pub mod prelude;
pub mod raw;
pub mod traits;

const FAILURE: c_int = -1;
const SUCCESS: c_int = 0;

/// Safe wrapper around `raw::Termios`
#[derive(Copy)]
#[repr(C)]
pub struct Termios {
    /// Input flags
    pub iflag: input::Flags,
    /// Output flags
    pub oflag: output::Flags,
    /// Control flags
    pub cflag: control::Flags,
    /// Local flags
    pub lflag: local::Flags,
    #[cfg(target_os = "linux")] _line: raw::cc_t,
    /// Control characters
    pub cc: control::Chars,
    _ispeed: raw::speed_t,
    _ospeed: raw::speed_t,
}

impl Termios {
    /// Returns the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Inspect your TTY.
    ///
    /// ``` ignore
    /// // examples/stdin.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     println!("{:?}", Termios::fetch(libc::STDIN_FILENO).unwrap());
    /// }
    /// ```
    ///
    /// ``` text
    /// $ ./stdin
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// $ echo 'this will panic!' | ./stdin
    /// called `Result::unwrap()` on an `Err` value: file descriptor is not a TTY
    /// ```
    ///
    /// The second call panicked because `./stdin`'s stdin was not connected to a TTY, the
    /// following ASCII art shows how the standard streams are wired in that case:
    ///
    /// ``` text
    ///        +-----------------+  `|`   +---------------------+
    /// TTY => |stdin      stdout| =====> |stdin          stdout| => TTY
    ///        |     `echo`      |        |     `./stdin`       |
    ///        |           stderr| => TTY |               stderr| => TTY
    ///        +-----------------+        +---------------------+
    /// ```
    pub fn fetch(fd: c_int) -> IoResult<Termios> {
        let mut termios: raw::Termios = Default::default();

        unsafe {
            match raw::tcgetattr(fd, &mut termios) {
                FAILURE => Err(IoError::last_error()),
                SUCCESS => Ok(Termios::from_raw(termios)),
                _ => unreachable!(),
            }
        }
    }

    /// Updates the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Unbuffered TTY input.
    ///
    /// Consider the following application:
    ///
    /// ``` ignore
    /// // examples/buffered.rs
    /// use std::old_io::{BytesReader, stdio};
    ///
    /// fn main() {
    ///     for byte in stdio::stdin().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    /// }
    /// ```
    ///
    /// You'll expect the application to print back each byte as you type, however if you run the
    /// application and type: `a b c ENTER CTRL+D`, you get the following output:
    ///
    /// ``` text
    /// $ ./buffered
    /// abc
    /// Got 97
    /// Got 98
    /// Got 99
    /// Got 10
    /// ```
    ///
    /// You'll notice two things:
    ///
    /// - The application prints back what you type.
    /// - The application doesn't process your input until you hit ENTER.
    ///
    /// The difference between the observed behavior and your expectations is caused by the TTY
    /// (the terminal emulator you are using). By default, the TTY echoes back what you type (this
    /// is essential when you are typing commands in a shell!), and also buffers (line by line)
    /// your input before sending it to the application.
    ///
    /// If you want the application to match your expectations, then you'll have to modify the
    /// behavior of the TTY using `Termios`. The following code disables both echoing and line
    /// buffering:
    ///
    /// ``` ignore
    /// // examples/unbuffered.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use std::old_io::{BytesReader, stdio};
    /// use termios::prelude::*;
    ///
    /// // a.k.a. "Ctrl+D"
    /// const END_OF_TRANSMISSION: u8 = 4;
    ///
    /// fn main() {
    ///     let old_termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     let mut new_termios = old_termios;
    ///
    ///     // Disable line buffering
    ///     new_termios.lflag.clear(local::Flag::ICANON);
    ///
    ///     // Disable echo
    ///     new_termios.lflag.clear(local::Flag::ECHO);
    ///
    ///     // Change the behavior of the TTY
    ///     new_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    ///
    ///     for byte in stdio::stdin().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(END_OF_TRANSMISSION) => break,
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    ///
    ///     // Restore the original behavior of the TTY
    ///     old_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    /// }
    /// ```
    ///
    /// If you run this example, you'll receive the `"Got XYZ"` message each time you press a key.
    pub fn update(&self, fd: c_int, when: When) -> IoResult<()> {
        unsafe {
            match raw::tcsetattr(fd, when.to_raw(), self.as_raw()) {
                FAILURE => Err(IoError::last_error()),
                SUCCESS => Ok(()),
                _ => unreachable!(),
            }
        }
    }

    /// Puts `Termios` in "raw" mode
    ///
    /// # Examples
    ///
    /// Compare "cooked" and "raw" modes
    ///
    /// ``` ignore
    /// // examples/raw.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     let mut termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     println!("Cooked:\n{:?}", termios);
    ///     termios.make_raw();
    ///     println!("\nRaw:\n{:?}", termios);
    /// }
    /// ```
    ///
    /// ``` text
    /// Cooked:
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// Raw:
    /// iflag:
    /// oflag:  ONLCR
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    /// ```
    pub fn make_raw(&mut self) {
        unsafe {
            raw::cfmakeraw(self.as_raw_mut())
        }
    }

    /// Returns the input baud rate
    pub fn ispeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetispeed(self.as_raw()))
        }
    }

    /// Returns the output baud rate
    pub fn ospeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetospeed(self.as_raw()))
        }
    }

    /// Sets the input baud rate
    pub fn set_ispeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetispeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets the output baud rate
    pub fn set_ospeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetospeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets both the input and the output baud rates
    pub fn set_speed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetspeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Borrows the safe wrapper as its raw representation
    pub fn as_raw(&self) -> &raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }

    /// Mutably borrows the safe wrapper as its raw representation
    pub unsafe fn as_raw_mut(&mut self) -> &mut raw::Termios {
        mem::transmute(self)
    }

    /// Puts `raw::Termios` into a safe wrapper without performing any check
    pub unsafe fn from_raw(termios: raw::Termios) -> Termios {
        mem::transmute(termios)
    }

    /// Converts the safe wrapper into its raw representation
    pub fn into_raw(self) -> raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }
}

// XXX (Debug) Formatting may change
impl fmt::Debug for Termios {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "iflag:\t{:?}", self.iflag));
        try!(writeln!(f, "oflag:\t{:?}", self.oflag));
        try!(writeln!(f, "cflag:\t{:?}", self.cflag));
        try!(writeln!(f, "lflag:\t{:?}", self.lflag));
        try!(writeln!(f, "cc:\t{:?}", self.cc));
        try!(writeln!(f, "ispeed:\t{:?}", self.ispeed()));
        try!(write!(f, "ospeed:\t{:?}", self.ospeed()));
        Ok(())
    }
}

/// Standard baud rates
#[allow(missing_docs)]
#[derive(Copy, Debug, PartialEq)]
pub enum BaudRate {
    B0,
    B50,
    B75,
    B110,
    B134,
    B150,
    B200,
    B300,
    B600,
    B1200,
    B1800,
    B2400,
    B4800,
    B9600,
    B19200,
    B38400,
    B57600,
    B115200,
    B230400,
}

impl BaudRate {
    fn from_raw(speed: raw::tcflag_t) -> BaudRate {
        use BaudRate::*;

        match speed {
            raw::B0 => B0,
            raw::B50 => B50,
            raw::B75 => B75,
            raw::B110 => B110,
            raw::B134 => B134,
            raw::B150 => B150,
            raw::B200 => B200,
            raw::B300 => B300,
            raw::B600 => B600,
            raw::B1200 => B1200,
            raw::B1800 => B1800,
            raw::B2400 => B2400,
            raw::B4800 => B4800,
            raw::B9600 => B9600,
            raw::B19200 => B19200,
            raw::B38400 => B38400,
            raw::B57600 => B57600,
            raw::B115200 => B115200,
            raw::B230400 => B230400,
            _ => panic!("Unknown baud rate flag: {}", speed),
        }
    }

    fn to_raw(&self) -> raw::speed_t {
        match *self {
            B0 => raw::B0,
            B50 => raw::B50,
            B75 => raw::B75,
            B110 => raw::B110,
            B134 => raw::B134,
            B150 => raw::B150,
            B200 => raw::B200,
            B300 => raw::B300,
            B600 => raw::B600,
            B1200 => raw::B1200,
            B1800 => raw::B1800,
            B2400 => raw::B2400,
            B4800 => raw::B4800,
            B9600 => raw::B9600,
            B19200 => raw::B19200,
            B38400 => raw::B38400,
            B57600 => raw::B57600,
            B115200 => raw::B115200,
            B230400 => raw::B230400,
        }
    }
}

/// When to update the underlying `raw::Termios` structure
pub enum When {
    /// Make change immediate
    Now,
    /// Drain output, then change
    AfterDrain,
    /// Drain output, flush input, then change
    AfterFlush,
}

impl When {
    fn to_raw(&self) -> c_int {
        match *self {
            Now => raw::TCSANOW,
            AfterDrain => raw::TCSADRAIN,
            AfterFlush => raw::TCSAFLUSH,
        }
    }
}

#[cfg(test)]
mod test {
    use libc;

    use Termios;

    #[test]
    fn stderr() {
        Termios::fetch(libc::STDERR_FILENO).unwrap();
    }

    #[test]
    fn stdin() {
        Termios::fetch(libc::STDIN_FILENO).unwrap();
    }

    #[test]
    fn stdout() {
        Termios::fetch(libc::STDOUT_FILENO).unwrap();
    }
}
<commit_msg>fix: update to rust nightly<commit_after>#![deny(missing_docs, warnings)]
#![feature(core)]
#![feature(libc)]
#![feature(old_io)]

//! Termios bindings + safe wrapper
//!
//! # Examples
//!
//! Check the [`Termios`](struct.Termios.html#method.fetch) struct.

extern crate libc;

use libc::c_int;
use std::default::Default;
use std::old_io::{IoError, IoResult};
use std::{fmt, mem};

use self::BaudRate::*;
use self::When::*;

pub mod control;
pub mod input;
pub mod local;
pub mod output;
pub mod prelude;
pub mod raw;
pub mod traits;

const FAILURE: c_int = -1;
const SUCCESS: c_int = 0;

/// Safe wrapper around `raw::Termios`
#[derive(Copy)]
#[repr(C)]
pub struct Termios {
    /// Input flags
    pub iflag: input::Flags,
    /// Output flags
    pub oflag: output::Flags,
    /// Control flags
    pub cflag: control::Flags,
    /// Local flags
    pub lflag: local::Flags,
    #[cfg(target_os = "linux")] _line: raw::cc_t,
    /// Control characters
    pub cc: control::Chars,
    _ispeed: raw::speed_t,
    _ospeed: raw::speed_t,
}

impl Termios {
    /// Returns the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Inspect your TTY.
    ///
    /// ``` ignore
    /// // examples/stdin.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     println!("{:?}", Termios::fetch(libc::STDIN_FILENO).unwrap());
    /// }
    /// ```
    ///
    /// ``` text
    /// $ ./stdin
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// $ echo 'this will panic!' | ./stdin
    /// called `Result::unwrap()` on an `Err` value: file descriptor is not a TTY
    /// ```
    ///
    /// The second call panicked because `./stdin`'s stdin was not connected to a TTY, the
    /// following ASCII art shows how the standard streams are wired in that case:
    ///
    /// ``` text
    ///        +-----------------+  `|`   +---------------------+
    /// TTY => |stdin      stdout| =====> |stdin          stdout| => TTY
    ///        |     `echo`      |        |     `./stdin`       |
    ///        |           stderr| => TTY |               stderr| => TTY
    ///        +-----------------+        +---------------------+
    /// ```
    pub fn fetch(fd: c_int) -> IoResult<Termios> {
        let mut termios: raw::Termios = Default::default();

        unsafe {
            match raw::tcgetattr(fd, &mut termios) {
                FAILURE => Err(IoError::last_error()),
                SUCCESS => Ok(Termios::from_raw(termios)),
                _ => unreachable!(),
            }
        }
    }

    /// Updates the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Unbuffered TTY input.
    ///
    /// Consider the following application:
    ///
    /// ``` ignore
    /// // examples/buffered.rs
    /// use std::old_io::{BytesReader, stdio};
    ///
    /// fn main() {
    ///     for byte in stdio::stdin().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    /// }
    /// ```
    ///
    /// You'll expect the application to print back each byte as you type, however if you run the
    /// application and type: `a b c ENTER CTRL+D`, you get the following output:
    ///
    /// ``` text
    /// $ ./buffered
    /// abc
    /// Got 97
    /// Got 98
    /// Got 99
    /// Got 10
    /// ```
    ///
    /// You'll notice two things:
    ///
    /// - The application prints back what you type.
    /// - The application doesn't process your input until you hit ENTER.
    ///
    /// The difference between the observed behavior and your expectations is caused by the TTY
    /// (the terminal emulator you are using). By default, the TTY echoes back what you type (this
    /// is essential when you are typing commands in a shell!), and also buffers (line by line)
    /// your input before sending it to the application.
    ///
    /// If you want the application to match your expectations, then you'll have to modify the
    /// behavior of the TTY using `Termios`. The following code disables both echoing and line
    /// buffering:
    ///
    /// ``` ignore
    /// // examples/unbuffered.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use std::old_io::{BytesReader, stdio};
    /// use termios::prelude::*;
    ///
    /// // a.k.a. "Ctrl+D"
    /// const END_OF_TRANSMISSION: u8 = 4;
    ///
    /// fn main() {
    ///     let old_termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     let mut new_termios = old_termios;
    ///
    ///     // Disable line buffering
    ///     new_termios.lflag.clear(local::Flag::ICANON);
    ///
    ///     // Disable echo
    ///     new_termios.lflag.clear(local::Flag::ECHO);
    ///
    ///     // Change the behavior of the TTY
    ///     new_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    ///
    ///     for byte in stdio::stdin().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(END_OF_TRANSMISSION) => break,
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    ///
    ///     // Restore the original behavior of the TTY
    ///     old_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    /// }
    /// ```
    ///
    /// If you run this example, you'll receive the `"Got XYZ"` message each time you press a key.
    pub fn update(&self, fd: c_int, when: When) -> IoResult<()> {
        unsafe {
            match raw::tcsetattr(fd, when.to_raw(), self.as_raw()) {
                FAILURE => Err(IoError::last_error()),
                SUCCESS => Ok(()),
                _ => unreachable!(),
            }
        }
    }

    /// Puts `Termios` in "raw" mode
    ///
    /// # Examples
    ///
    /// Compare "cooked" and "raw" modes
    ///
    /// ``` ignore
    /// // examples/raw.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     let mut termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     println!("Cooked:\n{:?}", termios);
    ///     termios.make_raw();
    ///     println!("\nRaw:\n{:?}", termios);
    /// }
    /// ```
    ///
    /// ``` text
    /// Cooked:
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// Raw:
    /// iflag:
    /// oflag:  ONLCR
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    /// ```
    pub fn make_raw(&mut self) {
        unsafe {
            raw::cfmakeraw(self.as_raw_mut())
        }
    }

    /// Returns the input baud rate
    pub fn ispeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetispeed(self.as_raw()))
        }
    }

    /// Returns the output baud rate
    pub fn ospeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetospeed(self.as_raw()))
        }
    }

    /// Sets the input baud rate
    pub fn set_ispeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetispeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets the output baud rate
    pub fn set_ospeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetospeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets both the input and the output baud rates
    pub fn set_speed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetspeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Borrows the safe wrapper as its raw representation
    pub fn as_raw(&self) -> &raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }

    /// Mutably borrows the safe wrapper as its raw representation
    pub unsafe fn as_raw_mut(&mut self) -> &mut raw::Termios {
        mem::transmute(self)
    }

    /// Puts `raw::Termios` into a safe wrapper without performing any check
    pub unsafe fn from_raw(termios: raw::Termios) -> Termios {
        mem::transmute(termios)
    }

    /// Converts the safe wrapper into its raw representation
    pub fn into_raw(self) -> raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }
}

// XXX (Debug) Formatting may change
impl fmt::Debug for Termios {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "iflag:\t{:?}", self.iflag));
        try!(writeln!(f, "oflag:\t{:?}", self.oflag));
        try!(writeln!(f, "cflag:\t{:?}", self.cflag));
        try!(writeln!(f, "lflag:\t{:?}", self.lflag));
        try!(writeln!(f, "cc:\t{:?}", self.cc));
        try!(writeln!(f, "ispeed:\t{:?}", self.ispeed()));
        try!(write!(f, "ospeed:\t{:?}", self.ospeed()));
        Ok(())
    }
}

/// Standard baud rates
#[allow(missing_docs)]
#[derive(Copy, Debug, PartialEq)]
pub enum BaudRate {
    B0,
    B50,
    B75,
    B110,
    B134,
    B150,
    B200,
    B300,
    B600,
    B1200,
    B1800,
    B2400,
    B4800,
    B9600,
    B19200,
    B38400,
    B57600,
    B115200,
    B230400,
}

impl BaudRate {
    fn from_raw(speed: raw::tcflag_t) -> BaudRate {
        use BaudRate::*;

        match speed {
            raw::B0 => B0,
            raw::B50 => B50,
            raw::B75 => B75,
            raw::B110 => B110,
            raw::B134 => B134,
            raw::B150 => B150,
            raw::B200 => B200,
            raw::B300 => B300,
            raw::B600 => B600,
            raw::B1200 => B1200,
            raw::B1800 => B1800,
            raw::B2400 => B2400,
            raw::B4800 => B4800,
            raw::B9600 => B9600,
            raw::B19200 => B19200,
            raw::B38400 => B38400,
            raw::B57600 => B57600,
            raw::B115200 => B115200,
            raw::B230400 => B230400,
            _ => panic!("Unknown baud rate flag: {}", speed),
        }
    }

    fn to_raw(&self) -> raw::speed_t {
        match *self {
            B0 => raw::B0,
            B50 => raw::B50,
            B75 => raw::B75,
            B110 => raw::B110,
            B134 => raw::B134,
            B150 => raw::B150,
            B200 => raw::B200,
            B300 => raw::B300,
            B600 => raw::B600,
            B1200 => raw::B1200,
            B1800 => raw::B1800,
            B2400 => raw::B2400,
            B4800 => raw::B4800,
            B9600 => raw::B9600,
            B19200 => raw::B19200,
            B38400 => raw::B38400,
            B57600 => raw::B57600,
            B115200 => raw::B115200,
            B230400 => raw::B230400,
        }
    }
}

/// When to update the underlying `raw::Termios` structure
pub enum When {
    /// Make change immediate
    Now,
    /// Drain output, then change
    AfterDrain,
    /// Drain output, flush input, then change
    AfterFlush,
}

impl When {
    fn to_raw(&self) -> c_int {
        match *self {
            Now => raw::TCSANOW,
            AfterDrain => raw::TCSADRAIN,
            AfterFlush => raw::TCSAFLUSH,
        }
    }
}

#[cfg(test)]
mod test {
    use libc;

    use Termios;

    #[test]
    fn stderr() {
        Termios::fetch(libc::STDERR_FILENO).unwrap();
    }

    #[test]
    fn stdin() {
        Termios::fetch(libc::STDIN_FILENO).unwrap();
    }

    #[test]
    fn stdout() {
        Termios::fetch(libc::STDOUT_FILENO).unwrap();
    }
}
<|endoftext|>


<commit_before>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{:?}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Display`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test

#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

#[cfg(feature = "rustc-serialize")] extern crate rustc_serialize;
#[cfg(feature = "serde")] extern crate serde;

use std::collections::BTreeMap;
use std::str::FromStr;

pub use parser::{Parser, ParserError};

#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::encoder::{Encoder, Error, encode, encode_str};
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::decoder::{Decoder, DecodeError, DecodeErrorKind, decode, decode_str};

mod parser;
mod display;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod encoder;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod decoder;

/// Representation of a TOML value.
#[derive(PartialEq, Clone, Debug)]
#[allow(missing_docs)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(String),
    Array(Array),
    Table(Table),
}

/// Type representing a TOML array, payload of the Value::Array variant
pub type Array = Vec<Value>;

/// Type representing a TOML table, payload of the Value::Table variant
pub type Table = BTreeMap<String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::String(..), &Value::String(..)) |
            (&Value::Integer(..), &Value::Integer(..)) |
            (&Value::Float(..), &Value::Float(..)) |
            (&Value::Boolean(..), &Value::Boolean(..)) |
            (&Value::Datetime(..), &Value::Datetime(..)) |
            (&Value::Array(..), &Value::Array(..)) |
            (&Value::Table(..), &Value::Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            Value::String(..) => "string",
            Value::Integer(..) => "integer",
            Value::Float(..) => "float",
            Value::Boolean(..) => "boolean",
            Value::Datetime(..) => "datetime",
            Value::Array(..) => "array",
            Value::Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str(&self) -> Option<&str> {
        match *self { Value::String(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Value::Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Value::Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Value::Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime(&self) -> Option<&str> {
        match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice(&self) -> Option<&[Value]> {
        match *self { Value::Array(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table(&self) -> Option<&Table> {
        match *self { Value::Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// Note: empty path returns self.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = toml.parse().unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let ref path = match Parser::new(path).lookup() {
            Some(path) => path,
            None => return None,
        };
        let mut cur_value = self;
        if path.len() == 0 {
            return Some(cur_value)
        }

        for key in path {
            match *cur_value {
                Value::Table(ref hm) => {
                    match hm.get(key) {
                        Some(v) => cur_value = v,
                        None => return None
                    }
                },
                Value::Array(ref v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)

    }
    /// Lookups for mutable value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// Note: empty path returns self.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let mut value: toml::Value = toml.parse().unwrap();
    /// {
    ///    let string = value.lookup_mut("test.foo").unwrap();
    ///    assert_eq!(string, &mut toml::Value::String(String::from("bar")));
    ///    *string = toml::Value::String(String::from("foo"));
    /// }
    /// let result = value.lookup_mut("test.foo").unwrap();
    /// assert_eq!(result.as_str().unwrap(), "foo");
    /// ```
    pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> {
        let mut cur = self;
        if path.len() == 0 {
            return Some(cur)
        }

        for key in path.split('.') {
            let tmp = cur;
            match *tmp {
                Value::Table(ref mut hm) => {
                    match hm.get_mut(key) {
                        Some(v) => cur = v,
                        None => return None
                    }
                }
                Value::Array(ref mut v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur = &mut v[idx],
                        _ => return None
                    }
                }
                _ => return None
           }
        }
        Some(cur)
    }
}

impl FromStr for Value {
    type Err = Vec<ParserError>;
    fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
        let mut p = Parser::new(s);
        match p.parse().map(Value::Table) {
            Some(n) => Ok(n),
            None => Err(p.errors),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Value;
        use parser::Parser;

    #[test]
    fn lookup_mut_change() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let mut value: Value = toml.parse().unwrap();
        {
          let foo = value.lookup_mut("values.0.foo").unwrap();
          *foo = Value::String(String::from("bar"));
        }
        let foo = value.lookup("values.0.foo").unwrap();
        assert_eq!(foo.as_str().unwrap(), "bar");
    }

    #[test]
    fn lookup_mut_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let mut value: Value = toml.parse().unwrap();

        {
            let test_foo = value.lookup_mut("test.foo").unwrap();
            assert_eq!(test_foo.as_str().unwrap(), "bar");
        }

        {
            let foo1 = value.lookup_mut("values.1.foo").unwrap();
            assert_eq!(foo1.as_str().unwrap(), "qux");
        }

        assert!(value.lookup_mut("test.bar").is_none());
        assert!(value.lookup_mut("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_mut_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let mut value: Value = toml.parse().unwrap();

        {
            let foo = value.lookup_mut("test.foo");
            assert!(foo.is_none());
        }

        {
            let foo = value.lookup_mut("values.100.foo");
            assert!(foo.is_none());
        }

        {
            let foo = value.lookup_mut("values.str.foo");
            assert!(foo.is_none());
        }
    }

    #[test]
    fn lookup_mut_self() {
        let mut value: Value = r#"foo = "bar""#.parse().unwrap();

        {
            let foo = value.lookup_mut("foo").unwrap();
            assert_eq!(foo.as_str().unwrap(), "bar");
        }

        let foo = value.lookup_mut("").unwrap();
        assert!(foo.as_table().is_some());

        let baz = foo.lookup_mut("foo").unwrap();
        assert_eq!(baz.as_str().unwrap(), "bar");
    }

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = toml.parse().unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        assert!(value.lookup("test.bar").is_none());
        assert!(value.lookup("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = toml.parse().unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }

    #[test]
    fn lookup_self() {
        let value: Value = r#"foo = "bar""#.parse().unwrap();

        let foo = value.lookup("foo").unwrap();
        assert_eq!(foo.as_str().unwrap(), "bar");

        let foo = value.lookup("").unwrap();
        assert!(foo.as_table().is_some());

        let baz = foo.lookup("foo").unwrap();
        assert_eq!(baz.as_str().unwrap(), "bar");
    }

    #[test]
    fn lookup_advanced() {
        let value: Value = "[table]\n\"value\" = 0".parse().unwrap();
        let looked = value.lookup("table.\"value\"").unwrap();
        assert_eq!(*looked, Value::Integer(0));
    }

    #[test]
    fn lookup_internal() {
        let mut parser = Parser::new(r#"hello."world\t".a.0.'escaped'.value"#);
        let result = vec![
          String::from("hello"),
          String::from("world\t"),
          String::from("a"),
          String::from("0"),
          String::from("escaped"),
          String::from("value")
        ];

        assert_eq!(parser.lookup().unwrap(), result);
    }

    #[test]
    fn lookup_internal_void() {
        let mut parser = Parser::new("");
        assert_eq!(parser.lookup().unwrap(), Vec::<String>::new());
    }

    #[test]
    fn lookup_internal_simple() {
        let mut parser = Parser::new("value");
        assert_eq!(parser.lookup().unwrap(), vec![String::from("value")]);
    }

    // This is due to key_name not parsing an empty "" correctly. Disabled for now.
    #[test]
    #[ignore]
    fn lookup_internal_quoted_void() {
        let mut parser = Parser::new("\"\"");
        assert_eq!(parser.lookup().unwrap(), vec![String::from("")]);
    }

}
<commit_msg>Implement advanced key lookup for lookup_mut<commit_after>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{:?}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Display`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test

#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

#[cfg(feature = "rustc-serialize")] extern crate rustc_serialize;
#[cfg(feature = "serde")] extern crate serde;

use std::collections::BTreeMap;
use std::str::FromStr;

pub use parser::{Parser, ParserError};

#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::encoder::{Encoder, Error, encode, encode_str};
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::decoder::{Decoder, DecodeError, DecodeErrorKind, decode, decode_str};

mod parser;
mod display;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod encoder;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod decoder;

/// Representation of a TOML value.
#[derive(PartialEq, Clone, Debug)]
#[allow(missing_docs)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(String),
    Array(Array),
    Table(Table),
}

/// Type representing a TOML array, payload of the Value::Array variant
pub type Array = Vec<Value>;

/// Type representing a TOML table, payload of the Value::Table variant
pub type Table = BTreeMap<String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::String(..), &Value::String(..)) |
            (&Value::Integer(..), &Value::Integer(..)) |
            (&Value::Float(..), &Value::Float(..)) |
            (&Value::Boolean(..), &Value::Boolean(..)) |
            (&Value::Datetime(..), &Value::Datetime(..)) |
            (&Value::Array(..), &Value::Array(..)) |
            (&Value::Table(..), &Value::Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            Value::String(..) => "string",
            Value::Integer(..) => "integer",
            Value::Float(..) => "float",
            Value::Boolean(..) => "boolean",
            Value::Datetime(..) => "datetime",
            Value::Array(..) => "array",
            Value::Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str(&self) -> Option<&str> {
        match *self { Value::String(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Value::Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Value::Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Value::Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime(&self) -> Option<&str> {
        match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice(&self) -> Option<&[Value]> {
        match *self { Value::Array(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table(&self) -> Option<&Table> {
        match *self { Value::Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// Note: empty path returns self.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = toml.parse().unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let ref path = match Parser::new(path).lookup() {
            Some(path) => path,
            None => return None,
        };
        let mut cur_value = self;
        if path.len() == 0 {
            return Some(cur_value)
        }

        for key in path {
            match *cur_value {
                Value::Table(ref hm) => {
                    match hm.get(key) {
                        Some(v) => cur_value = v,
                        None => return None
                    }
                },
                Value::Array(ref v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)

    }
    /// Lookups for mutable value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// Note: empty path returns self.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let mut value: toml::Value = toml.parse().unwrap();
    /// {
    ///    let string = value.lookup_mut("test.foo").unwrap();
    ///    assert_eq!(string, &mut toml::Value::String(String::from("bar")));
    ///    *string = toml::Value::String(String::from("foo"));
    /// }
    /// let result = value.lookup_mut("test.foo").unwrap();
    /// assert_eq!(result.as_str().unwrap(), "foo");
    /// ```
    pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> {
       let ref path = match Parser::new(path).lookup() {
            Some(path) => path,
            None => return None,
        };

        let mut cur = self;
        if path.len() == 0 {
            return Some(cur)
        }

        for key in path {
            let tmp = cur;
            match *tmp {
                Value::Table(ref mut hm) => {
                    match hm.get_mut(key) {
                        Some(v) => cur = v,
                        None => return None
                    }
                }
                Value::Array(ref mut v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur = &mut v[idx],
                        _ => return None
                    }
                }
                _ => return None
           }
        }
        Some(cur)
    }
}

impl FromStr for Value {
    type Err = Vec<ParserError>;
    fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
        let mut p = Parser::new(s);
        match p.parse().map(Value::Table) {
            Some(n) => Ok(n),
            None => Err(p.errors),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Value;

    #[test]
    fn lookup_mut_change() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let mut value: Value = toml.parse().unwrap();
        {
          let foo = value.lookup_mut("values.0.foo").unwrap();
          *foo = Value::String(String::from("bar"));
        }
        let foo = value.lookup("values.0.foo").unwrap();
        assert_eq!(foo.as_str().unwrap(), "bar");
    }

    #[test]
    fn lookup_mut_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let mut value: Value = toml.parse().unwrap();

        {
            let test_foo = value.lookup_mut("test.foo").unwrap();
            assert_eq!(test_foo.as_str().unwrap(), "bar");
        }

        {
            let foo1 = value.lookup_mut("values.1.foo").unwrap();
            assert_eq!(foo1.as_str().unwrap(), "qux");
        }

        assert!(value.lookup_mut("test.bar").is_none());
        assert!(value.lookup_mut("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_mut_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let mut value: Value = toml.parse().unwrap();

        {
            let foo = value.lookup_mut("test.foo");
            assert!(foo.is_none());
        }

        {
            let foo = value.lookup_mut("values.100.foo");
            assert!(foo.is_none());
        }

        {
            let foo = value.lookup_mut("values.str.foo");
            assert!(foo.is_none());
        }
    }

    #[test]
    fn lookup_mut_self() {
        let mut value: Value = r#"foo = "bar""#.parse().unwrap();

        {
            let foo = value.lookup_mut("foo").unwrap();
            assert_eq!(foo.as_str().unwrap(), "bar");
        }

        let foo = value.lookup_mut("").unwrap();
        assert!(foo.as_table().is_some());

        let baz = foo.lookup_mut("foo").unwrap();
        assert_eq!(baz.as_str().unwrap(), "bar");
    }

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = toml.parse().unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        assert!(value.lookup("test.bar").is_none());
        assert!(value.lookup("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = toml.parse().unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }

    #[test]
    fn lookup_self() {
        let value: Value = r#"foo = "bar""#.parse().unwrap();

        let foo = value.lookup("foo").unwrap();
        assert_eq!(foo.as_str().unwrap(), "bar");

        let foo = value.lookup("").unwrap();
        assert!(foo.as_table().is_some());

        let baz = foo.lookup("foo").unwrap();
        assert_eq!(baz.as_str().unwrap(), "bar");
    }

    #[test]
    fn lookup_advanced() {
        let value: Value = "[table]\n\"value\" = 0".parse().unwrap();
        let looked = value.lookup("table.\"value\"").unwrap();
        assert_eq!(*looked, Value::Integer(0));
    }

}
<|endoftext|>


<commit_before>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

//! This crate exports functionality to import and export taskwarrior-compatible JSON by
//! translating the JSON into rust types and vice-versa.
//!
//! For example:
//!
//! ```
//!   use std::io::stdin;
//!
//!   use task_hookrs::task::Task;
//!   use task_hookrs::import::import;
//!
//!   if let Ok(tasks) = import(stdin()) {
//!       for task in tasks {
//!           println!("Task: {}, entered {:?} is {} -> {}",
//!                     task.uuid(),
//!                     task.entry(),
//!                     task.status(),
//!                     task.description());
//!       }
//!   }
//! ```
//!
#![deny(missing_docs)]
#![doc(html_root_url = "https://matthiasbeyer.github.io/task-hookrs/")]
#![deny(
    dead_code,
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate chrono;
extern crate log;
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate uuid;

pub mod annotation;
pub mod date;
pub mod error;
pub mod import;
pub mod priority;
pub mod project;
pub mod result;
pub mod status;
pub mod tag;
pub mod task;

<commit_msg>Remove "log" dependency<commit_after>//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

//! This crate exports functionality to import and export taskwarrior-compatible JSON by
//! translating the JSON into rust types and vice-versa.
//!
//! For example:
//!
//! ```
//!   use std::io::stdin;
//!
//!   use task_hookrs::task::Task;
//!   use task_hookrs::import::import;
//!
//!   if let Ok(tasks) = import(stdin()) {
//!       for task in tasks {
//!           println!("Task: {}, entered {:?} is {} -> {}",
//!                     task.uuid(),
//!                     task.entry(),
//!                     task.status(),
//!                     task.description());
//!       }
//!   }
//! ```
//!
#![deny(missing_docs)]
#![doc(html_root_url = "https://matthiasbeyer.github.io/task-hookrs/")]
#![deny(
    dead_code,
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate chrono;
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate uuid;

pub mod annotation;
pub mod date;
pub mod error;
pub mod import;
pub mod priority;
pub mod project;
pub mod result;
pub mod status;
pub mod tag;
pub mod task;

<|endoftext|>