<commit_before>use std::io;
use std::rc::Rc;
use std::time::Duration;

use futures::{future, Future, Stream, Poll, Async};
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::{Core, Timeout};

use super::v3;
use super::socks5;
use super::transfer;
use super::buffer::{BufRange, SharedBuf};
use super::crypto::{KeyPair, Crypto};
use super::config::ClientConfig;
use super::util::RandomBytes;

pub struct Client {
    config: Rc<ClientConfig>,
    socks5_reply: Rc<socks5::Reply>,
}

impl Client {
    pub fn new(config: ClientConfig) -> Client {
        let reply = socks5::Reply::new(config.listen);
        Client {
            config: Rc::new(config),
            socks5_reply: Rc::new(reply),
        }
    }

    pub fn serve(&self) -> io::Result<()> {
        let mut core = Core::new()?;
        let handle = core.handle();

        let timeout = Duration::new(v3::HANDSHAKE_TIMEOUT, 0);
        let config = self.config.clone();
        let socks5_reply = self.socks5_reply.clone();

        let listener = TcpListener::bind(&config.listen, &handle).map_err(|e| {
            other(&format!("bind on {}, {}", config.listen, e))
        })?;

        info!("Listening for socks5 proxy on local {}", config.listen);

        let clients = listener.incoming().for_each(|(conn, addr)| {
            let client = Rc::new(conn);

            let socks5 = socks5::Handshake::new(
                handle.clone(),
                socks5_reply.clone(),
                addr,
                client.clone(),
                config.server,
            );

            let handshake_config = config.clone();
            let handshake = socks5.and_then(move |(conn, reqaddr)| {
                conn.set_nodelay(true).unwrap();

                let config = handshake_config.clone();
                let req = reqaddr.get().unwrap();
                let req = format!("{}:{}", req.0, req.1);
                let server = Rc::new(conn);

                match Handshake::new(config, server.clone(), reqaddr) {
                    Ok(hand) => future::ok(hand.map(|keypair| (req, keypair, server))),
                    Err(e) => future::err(e),
                }.flatten()
            });

            let timeout = Timeout::new(timeout, &handle).unwrap();
            let handshake = handshake.map(Ok).select(timeout.map(Err)).then(
                |res| match res {
                    Ok((Ok(hand), _timeout)) => Ok(hand),
                    Ok((Err(()), _handshake)) => Err(other("handshake timeout")),
                    Err((e, _other)) => Err(e),
                },
            );

            let transfer_config = config.clone();
            let transfer = handshake.and_then(move |(reqaddr, keypair, server)| {
                let (ckey, skey) = keypair.split();
                let trans =
                    transfer::encrypt(client.clone(), server.clone(), transfer_config.cipher, ckey)
                        .join(transfer::decrypt(
                            server.clone(),
                            client.clone(),
                            transfer_config.cipher,
                            skey,
                        ));

                trans.map(|(enc, dec)| (reqaddr, transfer::Stat::new(enc, dec)))
            });

            handle.spawn(transfer.then(move |res| {
                match res {
                    Ok((req, stat)) => info!("{} - request {} success, {}", addr, req, stat),
                    Err(e) => error!("{} - failed by {}", addr, e),
                }
                future::ok(())
            }));
            Ok(())
        });

        core.run(clients).unwrap();
        Ok(())
    }
}

#[derive(Copy, Clone, Debug)]
enum HandshakeState {
    Init,
    ClientReq(BufRange),
    ServerRespHeader(BufRange),
    ServerRespData(BufRange),
    Done,
}

struct Handshake {
    config: Rc<ClientConfig>,
    server: Rc<TcpStream>,
    addr: socks5::ReqAddr,

    crypto: Crypto,
    buf: SharedBuf,
    state: HandshakeState,
}

impl Handshake {
    fn new(
        config: Rc<ClientConfig>,
        server: Rc<TcpStream>,
        addr: socks5::ReqAddr,
    ) -> io::Result<Handshake> {
        let crypto = Crypto::new(
            v3::HANDSHAKE_CIPHER,
            config.password.as_ref(),
            config.password.as_ref(),
        )?;
        Ok(Handshake {
            config: config,
            server: server,
            addr: addr,
            crypto: crypto,
            buf: SharedBuf::new(v3::MAX_BUFFER_SIZE),
            state: HandshakeState::Init,
        })
    }

    // +---------------+------+--------------------------------------------------+
    // |     Header    | Plain|                      Data                        |
    // +-----+---------+------+---------+-----+------+-----+----------+----------+
    // | LEN | LEN TAG | USER | PADDING | VER | CTYP |ATYP | DST.ADDR | DST.PORT |
    // +-----+---------+------+---------+-----+------+----------------+----------+
    // |  2  |   Var.  |  32  |   Var.  |  1  |   1  |  1  |   Var.   |    2     |
    // +-----+---------+------+---------+-----+------+-----+----------+----------+
    fn request(&mut self) -> io::Result<BufRange> {
        let tag_len = self.crypto.tag_len();
        let header_len = v3::DATA_LEN_LEN + tag_len;

        // USER
        let range = BufRange {
            start: header_len,
            end: header_len + v3::DEFAULT_DIGEST_LEN,
        };
        self.buf.copy_from_slice(
            range,
            self.config.username.as_ref(),
        );

        // PADDING
        let random_bytes = RandomBytes::new()?;
        let bytes = random_bytes.get();
        let range = BufRange {
            start: range.end,
            end: range.end + bytes.len(),
        };
        self.buf.copy_from_slice(range, bytes);

        // VER and CTYP
        let range = BufRange {
            start: range.end,
            end: range.end + 2,
        };
        {
            let b = self.buf.get_mut_range(range);
            b[0] = v3::VERSION;
            b[1] = self.config.cipher.to_no();
        }

        // ADDR
        let bytes = self.addr.get_bytes();
        let range = BufRange {
            start: range.end,
            end: range.end + bytes.len(),
        };
        self.buf.copy_from_slice(range, bytes);

        // Encrypt it
        let data_len = range.end - header_len;
        {
            let range = BufRange {
                start: 0,
                end: header_len,
            };
            let head = self.buf.get_mut_range(range);

            // Big Endian
            let data_len = data_len + tag_len;
            head[0] = (data_len >> 8) as u8;
            head[1] = data_len as u8;
            self.crypto.encrypt(head, 2)?;
        }
        {
            let len = data_len - v3::DEFAULT_DIGEST_LEN;
            let range = BufRange {
                start: header_len + v3::DEFAULT_DIGEST_LEN,
                end: range.end + tag_len,
            };
            let data = self.buf.get_mut_range(range);
            self.crypto.encrypt(data, len)?;
        }

        Ok(BufRange {
            start: 0,
            end: range.end + tag_len,
        })
    }
}

impl Future for Handshake {
    type Item = KeyPair;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<KeyPair, io::Error> {
        loop {
            match self.state {
                HandshakeState::Init => {
                    let range = self.request()?;
                    self.state = HandshakeState::ClientReq(range);
                }
                HandshakeState::ClientReq(range) => {
                    try_ready!(self.buf.write_exact(&mut (&*self.server), range));

                    let resp_header_len = v3::DATA_LEN_LEN + self.crypto.tag_len();
                    self.state = HandshakeState::ServerRespHeader(BufRange {
                        start: 0,
                        end: resp_header_len,
                    });
                }
                HandshakeState::ServerRespHeader(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.server), range));
                    let buf = self.buf.get_mut_range(range);
                    let len = self.crypto.decrypt(buf)?;

                    // +-----+---------+
                    // | LEN | LEN TAG |
                    // +-----+---------+
                    // |  2  |   Var.  |
                    // +-----+---------+
                    debug_assert!(len == v3::DATA_LEN_LEN);
                    let data_len = ((buf[0] as usize) << 8) + (buf[1] as usize);
                    // Padding len 1 + resp 1
                    if data_len < 2 + self.crypto.tag_len() {
                        return Err(other("response data length too small"));
                    }

                    self.state = HandshakeState::ServerRespData(BufRange {
                        start: 0,
                        end: data_len,
                    });
                }
                HandshakeState::ServerRespData(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.server), range));
                    let len = {
                        let buf = self.buf.get_mut_range(range);
                        self.crypto.decrypt(buf)?
                    };

                    // +---------+-------+-------+------+
                    // | PADDING |  RESP |  EKEY | DKEY |
                    // +---------+-------+-------+------+
                    // |   Var.  |    1  |  Var. | Var. |
                    // +---------+-------+-------+------+
                    let buf = self.buf.get_ref_range(BufRange {
                        start: range.start,
                        end: range.start + len,
                    });
                    let padding_len = (buf[0] as usize) + 1;
                    if len < padding_len + 1 {
                        return Err(other("response data length too small"));
                    }

                    match buf[padding_len] {
                        v3::SERVER_RESP_SUCCESSD => debug!("server resp success"),
                        v3::SERVER_RESP_CIPHER_ERROR => {
                            return Err(other("server not support cipher"))
                        }
                        v3::SERVER_RESP_ERROR => return Err(other("server internal error")),
                        v3::SERVER_RESP_REMOTE_FAILED => {
                            return Err(other("server connect request addr error"))
                        }
                        _ => return Err(other("server resp unkown")),
                    }
                    let key_len = len - padding_len - 1;
                    if key_len != 2 * self.config.cipher.key_len() {
                        return Err(other("server resp key length not match"));
                    }

                    let keypair = KeyPair::from(&buf[padding_len + 1..]);

                    self.state = HandshakeState::Done;

                    return Ok(Async::Ready(keypair));
                }
                HandshakeState::Done => panic!("poll a done future"),
            }
        }
    }
}

fn other(desc: &str) -> io::Error {
    io::Error::new(io::ErrorKind::Other, desc)
}
<commit_msg>fix rustfmt<commit_after>use std::io;
use std::rc::Rc;
use std::time::Duration;

use futures::{future, Future, Stream, Poll, Async};
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::{Core, Timeout};

use super::v3;
use super::socks5;
use super::transfer;
use super::buffer::{BufRange, SharedBuf};
use super::crypto::{KeyPair, Crypto};
use super::config::ClientConfig;
use super::util::RandomBytes;

pub struct Client {
    config: Rc<ClientConfig>,
    socks5_reply: Rc<socks5::Reply>,
}

impl Client {
    pub fn new(config: ClientConfig) -> Client {
        let reply = socks5::Reply::new(config.listen);
        Client {
            config: Rc::new(config),
            socks5_reply: Rc::new(reply),
        }
    }

    pub fn serve(&self) -> io::Result<()> {
        let mut core = Core::new()?;
        let handle = core.handle();

        let timeout = Duration::new(v3::HANDSHAKE_TIMEOUT, 0);
        let config = self.config.clone();
        let socks5_reply = self.socks5_reply.clone();

        let listener = TcpListener::bind(&config.listen, &handle).map_err(|e| {
            other(&format!("bind on {}, {}", config.listen, e))
        })?;

        info!("Listening for socks5 proxy on local {}", config.listen);

        let clients = listener.incoming().for_each(|(conn, addr)| {
            let client = Rc::new(conn);

            let socks5 = socks5::Handshake::new(
                handle.clone(),
                socks5_reply.clone(),
                addr,
                client.clone(),
                config.server,
            );

            let handshake_config = config.clone();
            let handshake = socks5.and_then(move |(conn, reqaddr)| {
                conn.set_nodelay(true).unwrap();

                let config = handshake_config.clone();
                let req = reqaddr.get().unwrap();
                let req = format!("{}:{}", req.0, req.1);
                let server = Rc::new(conn);

                match Handshake::new(config, server.clone(), reqaddr) {
                    Ok(hand) => future::ok(hand.map(|keypair| (req, keypair, server))),
                    Err(e) => future::err(e),
                }.flatten()
            });

            let timeout = Timeout::new(timeout, &handle).unwrap();
            let handshake = handshake.map(Ok).select(timeout.map(Err)).then(
                |res| match res {
                    Ok((Ok(hand), _timeout)) => Ok(hand),
                    Ok((Err(()), _handshake)) => Err(other("handshake timeout")),
                    Err((e, _other)) => Err(e),
                },
            );

            let transfer_config = config.clone();

            let transfer = handshake.and_then(move |(reqaddr, keypair, server)| {
                let (ckey, skey) = keypair.split();

                #[cfg_attr(rustfmt, rustfmt_skip)]
                transfer::encrypt(
                    client.clone(),
                    server.clone(),
                    transfer_config.cipher,
                    ckey
                ).join(transfer::decrypt(
                    server.clone(),
                    client.clone(),
                    transfer_config.cipher,
                    skey,
                )).map(|(enc, dec)| (reqaddr, transfer::Stat::new(enc, dec)))
            });

            handle.spawn(transfer.then(move |res| {
                match res {
                    Ok((req, stat)) => info!("{} - request {} success, {}", addr, req, stat),
                    Err(e) => error!("{} - failed by {}", addr, e),
                }
                future::ok(())
            }));
            Ok(())
        });

        core.run(clients).unwrap();
        Ok(())
    }
}

#[derive(Copy, Clone, Debug)]
enum HandshakeState {
    Init,
    ClientReq(BufRange),
    ServerRespHeader(BufRange),
    ServerRespData(BufRange),
    Done,
}

struct Handshake {
    config: Rc<ClientConfig>,
    server: Rc<TcpStream>,
    addr: socks5::ReqAddr,

    crypto: Crypto,
    buf: SharedBuf,
    state: HandshakeState,
}

impl Handshake {
    fn new(
        config: Rc<ClientConfig>,
        server: Rc<TcpStream>,
        addr: socks5::ReqAddr,
    ) -> io::Result<Handshake> {
        let crypto = Crypto::new(
            v3::HANDSHAKE_CIPHER,
            config.password.as_ref(),
            config.password.as_ref(),
        )?;
        Ok(Handshake {
            config: config,
            server: server,
            addr: addr,
            crypto: crypto,
            buf: SharedBuf::new(v3::MAX_BUFFER_SIZE),
            state: HandshakeState::Init,
        })
    }

    // +---------------+------+--------------------------------------------------+
    // |     Header    | Plain|                      Data                        |
    // +-----+---------+------+---------+-----+------+-----+----------+----------+
    // | LEN | LEN TAG | USER | PADDING | VER | CTYP |ATYP | DST.ADDR | DST.PORT |
    // +-----+---------+------+---------+-----+------+----------------+----------+
    // |  2  |   Var.  |  32  |   Var.  |  1  |   1  |  1  |   Var.   |    2     |
    // +-----+---------+------+---------+-----+------+-----+----------+----------+
    fn request(&mut self) -> io::Result<BufRange> {
        let tag_len = self.crypto.tag_len();
        let header_len = v3::DATA_LEN_LEN + tag_len;

        // USER
        let range = BufRange {
            start: header_len,
            end: header_len + v3::DEFAULT_DIGEST_LEN,
        };
        self.buf.copy_from_slice(
            range,
            self.config.username.as_ref(),
        );

        // PADDING
        let random_bytes = RandomBytes::new()?;
        let bytes = random_bytes.get();
        let range = BufRange {
            start: range.end,
            end: range.end + bytes.len(),
        };
        self.buf.copy_from_slice(range, bytes);

        // VER and CTYP
        let range = BufRange {
            start: range.end,
            end: range.end + 2,
        };
        {
            let b = self.buf.get_mut_range(range);
            b[0] = v3::VERSION;
            b[1] = self.config.cipher.to_no();
        }

        // ADDR
        let bytes = self.addr.get_bytes();
        let range = BufRange {
            start: range.end,
            end: range.end + bytes.len(),
        };
        self.buf.copy_from_slice(range, bytes);

        // Encrypt it
        let data_len = range.end - header_len;
        {
            let range = BufRange {
                start: 0,
                end: header_len,
            };
            let head = self.buf.get_mut_range(range);

            // Big Endian
            let data_len = data_len + tag_len;
            head[0] = (data_len >> 8) as u8;
            head[1] = data_len as u8;
            self.crypto.encrypt(head, 2)?;
        }
        {
            let len = data_len - v3::DEFAULT_DIGEST_LEN;
            let range = BufRange {
                start: header_len + v3::DEFAULT_DIGEST_LEN,
                end: range.end + tag_len,
            };
            let data = self.buf.get_mut_range(range);
            self.crypto.encrypt(data, len)?;
        }

        Ok(BufRange {
            start: 0,
            end: range.end + tag_len,
        })
    }
}

impl Future for Handshake {
    type Item = KeyPair;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<KeyPair, io::Error> {
        loop {
            match self.state {
                HandshakeState::Init => {
                    let range = self.request()?;
                    self.state = HandshakeState::ClientReq(range);
                }
                HandshakeState::ClientReq(range) => {
                    try_ready!(self.buf.write_exact(&mut (&*self.server), range));

                    let resp_header_len = v3::DATA_LEN_LEN + self.crypto.tag_len();
                    self.state = HandshakeState::ServerRespHeader(BufRange {
                        start: 0,
                        end: resp_header_len,
                    });
                }
                HandshakeState::ServerRespHeader(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.server), range));
                    let buf = self.buf.get_mut_range(range);
                    let len = self.crypto.decrypt(buf)?;

                    // +-----+---------+
                    // | LEN | LEN TAG |
                    // +-----+---------+
                    // |  2  |   Var.  |
                    // +-----+---------+
                    debug_assert!(len == v3::DATA_LEN_LEN);
                    let data_len = ((buf[0] as usize) << 8) + (buf[1] as usize);
                    // Padding len 1 + resp 1
                    if data_len < 2 + self.crypto.tag_len() {
                        return Err(other("response data length too small"));
                    }

                    self.state = HandshakeState::ServerRespData(BufRange {
                        start: 0,
                        end: data_len,
                    });
                }
                HandshakeState::ServerRespData(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.server), range));
                    let len = {
                        let buf = self.buf.get_mut_range(range);
                        self.crypto.decrypt(buf)?
                    };

                    // +---------+-------+-------+------+
                    // | PADDING |  RESP |  EKEY | DKEY |
                    // +---------+-------+-------+------+
                    // |   Var.  |    1  |  Var. | Var. |
                    // +---------+-------+-------+------+
                    let buf = self.buf.get_ref_range(BufRange {
                        start: range.start,
                        end: range.start + len,
                    });
                    let padding_len = (buf[0] as usize) + 1;
                    if len < padding_len + 1 {
                        return Err(other("response data length too small"));
                    }

                    match buf[padding_len] {
                        v3::SERVER_RESP_SUCCESSD => debug!("server resp success"),
                        v3::SERVER_RESP_CIPHER_ERROR => {
                            return Err(other("server not support cipher"))
                        }
                        v3::SERVER_RESP_ERROR => return Err(other("server internal error")),
                        v3::SERVER_RESP_REMOTE_FAILED => {
                            return Err(other("server connect request addr error"))
                        }
                        _ => return Err(other("server resp unkown")),
                    }
                    let key_len = len - padding_len - 1;
                    if key_len != 2 * self.config.cipher.key_len() {
                        return Err(other("server resp key length not match"));
                    }

                    let keypair = KeyPair::from(&buf[padding_len + 1..]);

                    self.state = HandshakeState::Done;

                    return Ok(Async::Ready(keypair));
                }
                HandshakeState::Done => panic!("poll a done future"),
            }
        }
    }
}

fn other(desc: &str) -> io::Error {
    io::Error::new(io::ErrorKind::Other, desc)
}
<|endoftext|>


<commit_before>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

/*!
Basic types used by the library.
*/

use std::io ;

use nom::IResult ;

/** Alias for `io` results of unit. */
pub type IoResUnit = io::Result<()> ;
/** Alias for `io` results of `bool`. */
pub type IoResBool = io::Result<bool> ;
/** Alias for generic `io` results. */
pub type IoRes<T> = io::Result<T> ;

/** Unexpected result for an SMT Lib 2 command. */
#[derive(Debug)]
pub enum UnexSmtRes {
  /** An unsupported command was issued. */
  Unsupported,
  /** A command produced an error. */
  Error(String),
  /** An input/output error occured. */
  IoError(io::Error),
}

/** Result of an SMT query. */
pub type SmtRes<T> = Result<T, UnexSmtRes> ;

/** Result of an SMT statement. */
pub type UnitSmtRes = SmtRes<()> ;

/** A symbol printable in the SMT Lib 2 standard given some info. */
pub trait Sym2Smt<Info> {
  /** Prints a symbol to a writer given some info. */
  fn sym_to_smt2(& self, writer: & mut io::Write, & Info) -> IoResUnit ;
}

/** An expression printable in the SMT Lib 2 standard given some info. */
pub trait Expr2Smt<Info> {
  /** Prints an expression to a writer given some info. */
  fn expr_to_smt2(& self, writer: & mut io::Write, & Info) -> IoResUnit ;
}

/** A sort printable in the SMT Lib 2 standard. */
pub trait Sort2Smt {
  /** Prints a sort to a writer info. */
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}

impl<'a> Sym2Smt<()>  for & 'a str {
  fn sym_to_smt2(& self, writer: & mut io::Write, _: & ()) -> IoResUnit {
    write!(writer, "{}", self)
  }
}
impl<'a> Expr2Smt<()> for & 'a str {
  fn expr_to_smt2(& self, writer: & mut io::Write, info: & ()) -> IoResUnit {
    self.sym_to_smt2(writer, info)
  }
}
impl<'a> Sort2Smt for & 'a str {
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.sym_to_smt2(writer, & ())
  }
}

/** Generic type for the parsing of an SMT Lib 2 answer.

Either a value of the expected type or an unexpected error. */
pub type SmtParseResult<T> = Result<T, UnexSmtRes> ;

/** Parsers on the user's structure.

Not all of them are necessary depending on the queries wanted. See each method
for details.*/
pub trait ParseSmt2 {
  /** Type of identifiers in the user's structure. */
  type Ident : ::std::fmt::Debug ;
  /** Type of values in the user's structure. */
  type Value : ::std::fmt::Debug ;
  /** Type of expressions in the user's structure. */
  type Expr :  ::std::fmt::Debug ;
  /** Type of proofs in the user's structure. */
  type Proof : ::std::fmt::Debug ;
  /** Type of the info passed when parsing expressions. */
  type I ;

  /** Parses an ident from self, viewed as a reader.

  Required by

  * `get-assignment`
  * `get-model`
  * `get-unsat-assumptions`
  * `get-unsat-core` */
  #[inline(always)]
  fn parse_ident<'a>(
    & self, & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Ident> ;

  /** Parses a value from self, viewed as a reader.

  Required by

  * `get-value`
  * `get-assignment`
  * `get-model` */
  #[inline(always)]
  fn parse_value<'a>(
    & self, & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Value> ;

  /** Parses an expression from self, viewed as a reader.

  Required by

  * `get_assertions` */
  #[inline(always)]
  fn parse_expr<'a>(
    & self, & 'a [u8], & Self::I
  ) -> IResult<& 'a [u8], Self::Expr> ;

  /** Parses a proof from self, viewed as a reader.

  Required by

  * `get_proof` */
  #[inline(always)]
  fn parse_proof<'a>(
    & self, & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Proof> ;
}

impl ParseSmt2 for () {
  type Ident = () ;
  type Value = () ;
  type Expr = () ;
  type Proof = () ;
  type I = () ;
  fn parse_ident<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Ident> {
    panic!("parser on () called")
  }
  fn parse_value<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Value> {
    panic!("parser on () called")
  }
  fn parse_expr<'a>(
    & self, _: & 'a [u8], _: & ()
  ) -> IResult<& 'a [u8], Self::Expr> {
    panic!("parser on () called")
  }
  fn parse_proof<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Proof> {
    panic!("parser on () called")
  }
}

/** SMT Lib 2 logics. */
#[allow(non_camel_case_types)]
pub enum Logic {
  /** Quantifier-free uninterpreted functions. */
  QF_UF,
  /** Quantifier-free linear integer arithmetic. */
  QF_LIA,
  /** Quantifier-free non-linear integer arithmetic. */
  QF_NIA,
  /** Quantifier-free linear real arithmetic. */
  QF_LRA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  QF_AUFLIA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  AUFLIA,
  /** Arrays, uninterpreted functions, linear integer/real arithmetic. */
  AUFLIRA,
  /** arrays, uninterpreted functions, non-linear integer/real arithmetic. */
  AUFNIRA,
  /** Linear real arithmetic. */
  LRA,
}

impl Logic {
  /** Prints the logic in a writer in SMT Lib 2 format. */
  pub fn to_smt2(& self, writer: & mut io::Write, _: ()) -> IoResUnit {
    use self::Logic::* ;
    match * self {
      QF_UF => write!(writer, "QF_UF"),
      QF_LIA => write!(writer, "QF_LIA"),
      QF_NIA => write!(writer, "QF_NIA"),
      QF_LRA => write!(writer, "QF_LRA"),
      QF_AUFLIA => write!(writer, "QF_AUFLIA"),
      AUFLIA => write!(writer, "AUFLIA"),
      AUFLIRA => write!(writer, "AUFLIRA"),
      AUFNIRA => write!(writer, "AUFNIRA"),
      LRA => write!(writer, "LRA"),
    }
  }
}<commit_msg>Display for UnexSmtRes<commit_after>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

/*!
Basic types used by the library.
*/

use std::io ;
use std::fmt ;

use nom::IResult ;

/** Alias for `io` results of unit. */
pub type IoResUnit = io::Result<()> ;
/** Alias for `io` results of `bool`. */
pub type IoResBool = io::Result<bool> ;
/** Alias for generic `io` results. */
pub type IoRes<T> = io::Result<T> ;

/** Unexpected result for an SMT Lib 2 command. */
#[derive(Debug)]
pub enum UnexSmtRes {
  /** An unsupported command was issued. */
  Unsupported,
  /** A command produced an error. */
  Error(String),
  /** An input/output error occured. */
  IoError(io::Error),
}
impl fmt::Display for UnexSmtRes {
  fn fmt(& self, fmt: & mut fmt::Formatter) -> fmt::Result {
    match * self {
      UnexSmtRes::Unsupported => write!(fmt, "unsupported"),
      UnexSmtRes::Error(ref s) => write!(fmt, "{}", s),
      UnexSmtRes::IoError(ref e) => write!(fmt, "io error: {}", e),
    }
  }
}

/** Result of an SMT query. */
pub type SmtRes<T> = Result<T, UnexSmtRes> ;

/** Result of an SMT statement. */
pub type UnitSmtRes = SmtRes<()> ;

/** A symbol printable in the SMT Lib 2 standard given some info. */
pub trait Sym2Smt<Info> {
  /** Prints a symbol to a writer given some info. */
  fn sym_to_smt2(& self, writer: & mut io::Write, & Info) -> IoResUnit ;
}

/** An expression printable in the SMT Lib 2 standard given some info. */
pub trait Expr2Smt<Info> {
  /** Prints an expression to a writer given some info. */
  fn expr_to_smt2(& self, writer: & mut io::Write, & Info) -> IoResUnit ;
}

/** A sort printable in the SMT Lib 2 standard. */
pub trait Sort2Smt {
  /** Prints a sort to a writer info. */
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit ;
}

impl<'a> Sym2Smt<()>  for & 'a str {
  fn sym_to_smt2(& self, writer: & mut io::Write, _: & ()) -> IoResUnit {
    write!(writer, "{}", self)
  }
}
impl<'a> Expr2Smt<()> for & 'a str {
  fn expr_to_smt2(& self, writer: & mut io::Write, info: & ()) -> IoResUnit {
    self.sym_to_smt2(writer, info)
  }
}
impl<'a> Sort2Smt for & 'a str {
  fn sort_to_smt2(& self, writer: & mut io::Write) -> IoResUnit {
    self.sym_to_smt2(writer, & ())
  }
}

/** Generic type for the parsing of an SMT Lib 2 answer.

Either a value of the expected type or an unexpected error. */
pub type SmtParseResult<T> = Result<T, UnexSmtRes> ;

/** Parsers on the user's structure.

Not all of them are necessary depending on the queries wanted. See each method
for details.*/
pub trait ParseSmt2 {
  /** Type of identifiers in the user's structure. */
  type Ident : ::std::fmt::Debug ;
  /** Type of values in the user's structure. */
  type Value : ::std::fmt::Debug ;
  /** Type of expressions in the user's structure. */
  type Expr :  ::std::fmt::Debug ;
  /** Type of proofs in the user's structure. */
  type Proof : ::std::fmt::Debug ;
  /** Type of the info passed when parsing expressions. */
  type I ;

  /** Parses an ident from self, viewed as a reader.

  Required by

  * `get-assignment`
  * `get-model`
  * `get-unsat-assumptions`
  * `get-unsat-core` */
  #[inline(always)]
  fn parse_ident<'a>(
    & self, & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Ident> ;

  /** Parses a value from self, viewed as a reader.

  Required by

  * `get-value`
  * `get-assignment`
  * `get-model` */
  #[inline(always)]
  fn parse_value<'a>(
    & self, & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Value> ;

  /** Parses an expression from self, viewed as a reader.

  Required by

  * `get_assertions` */
  #[inline(always)]
  fn parse_expr<'a>(
    & self, & 'a [u8], & Self::I
  ) -> IResult<& 'a [u8], Self::Expr> ;

  /** Parses a proof from self, viewed as a reader.

  Required by

  * `get_proof` */
  #[inline(always)]
  fn parse_proof<'a>(
    & self, & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Proof> ;
}

impl ParseSmt2 for () {
  type Ident = () ;
  type Value = () ;
  type Expr = () ;
  type Proof = () ;
  type I = () ;
  fn parse_ident<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Ident> {
    panic!("parser on () called")
  }
  fn parse_value<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Value> {
    panic!("parser on () called")
  }
  fn parse_expr<'a>(
    & self, _: & 'a [u8], _: & ()
  ) -> IResult<& 'a [u8], Self::Expr> {
    panic!("parser on () called")
  }
  fn parse_proof<'a>(
    & self, _: & 'a [u8]
  ) -> IResult<& 'a [u8], Self::Proof> {
    panic!("parser on () called")
  }
}

/** SMT Lib 2 logics. */
#[allow(non_camel_case_types)]
pub enum Logic {
  /** Quantifier-free uninterpreted functions. */
  QF_UF,
  /** Quantifier-free linear integer arithmetic. */
  QF_LIA,
  /** Quantifier-free non-linear integer arithmetic. */
  QF_NIA,
  /** Quantifier-free linear real arithmetic. */
  QF_LRA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  QF_AUFLIA,
  /** Quantifier-free arrays, uninterpreted functions, linear integer
  arithmetic. */
  AUFLIA,
  /** Arrays, uninterpreted functions, linear integer/real arithmetic. */
  AUFLIRA,
  /** arrays, uninterpreted functions, non-linear integer/real arithmetic. */
  AUFNIRA,
  /** Linear real arithmetic. */
  LRA,
}

impl Logic {
  /** Prints the logic in a writer in SMT Lib 2 format. */
  pub fn to_smt2(& self, writer: & mut io::Write, _: ()) -> IoResUnit {
    use self::Logic::* ;
    match * self {
      QF_UF => write!(writer, "QF_UF"),
      QF_LIA => write!(writer, "QF_LIA"),
      QF_NIA => write!(writer, "QF_NIA"),
      QF_LRA => write!(writer, "QF_LRA"),
      QF_AUFLIA => write!(writer, "QF_AUFLIA"),
      AUFLIA => write!(writer, "AUFLIA"),
      AUFLIRA => write!(writer, "AUFLIRA"),
      AUFNIRA => write!(writer, "AUFNIRA"),
      LRA => write!(writer, "LRA"),
    }
  }
}<|endoftext|>


<commit_before>use std::default::Default;
use std::fmt;

pub use self::ConfigError::{ZeroPoolSize, ZeroHelperTasks};

/// A struct specifying the runtime configuration of a pool.
///
/// `Config` implements `Default`, which provides a set of reasonable default
/// values.
#[deriving(Encodable, Decodable, Copy, Clone)]
pub struct Config {
    /// The number of connections managed by the pool.
    ///
    /// Must be positive.
    ///
    /// Defaults to 10.
    pub pool_size: uint,
    /// The number of tasks that the pool will use for asynchronous operations
    /// such as connection creation and health checks.
    ///
    /// Must be positive.
    ///
    /// Defaults to 3.
    pub helper_tasks: uint,
    /// If true, the health of a connection will be verified via a call to
    /// `PoolManager::is_valid` before it is checked out of the pool.
    ///
    /// Defaults to false.
    pub test_on_check_out: bool,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            pool_size: 10,
            helper_tasks: 3,
            test_on_check_out: false,
        }
    }
}

impl Config {
    /// Determines if the configuration is valid
    pub fn validate(&self) -> Result<(), ConfigError> {
        if self.pool_size == 0 {
            return Err(ZeroPoolSize);
        }

        if self.helper_tasks == 0 {
            return Err(ZeroHelperTasks);
        }

        Ok(())
    }
}

/// An enumeration of reasons that a `Config` is invalid
#[deriving(Copy, Clone, PartialEq, Eq)]
pub enum ConfigError {
    /// pool_size was zero
    ZeroPoolSize,
    /// helper_tasks was zero
    ZeroHelperTasks,
}

impl fmt::Show for ConfigError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ZeroPoolSize => write!(fmt, "pool_size must be positive"),
            ZeroHelperTasks => write!(fmt, "helper_tasks must be positive"),
        }
    }
}
<commit_msg>Impl Error for ConfigError<commit_after>use std::default::Default;
use std::fmt;
use std::error::Error;

/// A struct specifying the runtime configuration of a pool.
///
/// `Config` implements `Default`, which provides a set of reasonable default
/// values.
#[deriving(Encodable, Decodable, Copy, Clone)]
pub struct Config {
    /// The number of connections managed by the pool.
    ///
    /// Must be positive.
    ///
    /// Defaults to 10.
    pub pool_size: uint,
    /// The number of tasks that the pool will use for asynchronous operations
    /// such as connection creation and health checks.
    ///
    /// Must be positive.
    ///
    /// Defaults to 3.
    pub helper_tasks: uint,
    /// If true, the health of a connection will be verified via a call to
    /// `PoolManager::is_valid` before it is checked out of the pool.
    ///
    /// Defaults to false.
    pub test_on_check_out: bool,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            pool_size: 10,
            helper_tasks: 3,
            test_on_check_out: false,
        }
    }
}

impl Config {
    /// Determines if the configuration is valid
    pub fn validate(&self) -> Result<(), ConfigError> {
        if self.pool_size == 0 {
            return Err(ConfigError::ZeroPoolSize);
        }

        if self.helper_tasks == 0 {
            return Err(ConfigError::ZeroHelperTasks);
        }

        Ok(())
    }
}

/// An enumeration of reasons that a `Config` is invalid
#[deriving(Copy, Clone, PartialEq, Eq)]
pub enum ConfigError {
    /// pool_size was zero
    ZeroPoolSize,
    /// helper_tasks was zero
    ZeroHelperTasks,
}

impl fmt::Show for ConfigError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}", self.description())
    }
}

impl Error for ConfigError {
    fn description(&self) -> &str {
        match *self {
            ConfigError::ZeroPoolSize => "pool_size must be positive",
            ConfigError::ZeroHelperTasks => "helper_tasks must be positive",
        }
    }
}
<|endoftext|>


<commit_before>use crate::file::{FileType, SaveDir, SaveFile};
use serde_derive::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
    pub series_dir: PathBuf,
}

impl Config {
    pub fn new<P>(series_dir: P) -> Config
    where
        P: Into<PathBuf>,
    {
        Config {
            series_dir: series_dir.into(),
        }
    }
}

impl SaveFile for Config {
    fn filename() -> &'static str {
        "config.toml"
    }

    fn save_dir() -> SaveDir {
        SaveDir::Config
    }

    fn file_type() -> FileType {
        FileType::Toml
    }
}
<commit_msg>[config] Add reset_dates_on_rewatch option<commit_after>use crate::file::{FileType, SaveDir, SaveFile};
use serde_derive::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
    pub series_dir: PathBuf,
    pub reset_dates_on_rewatch: bool,
}

impl Config {
    pub fn new<P>(series_dir: P) -> Config
    where
        P: Into<PathBuf>,
    {
        Config {
            series_dir: series_dir.into(),
            reset_dates_on_rewatch: false,
        }
    }
}

impl SaveFile for Config {
    fn filename() -> &'static str {
        "config.toml"
    }

    fn save_dir() -> SaveDir {
        SaveDir::Config
    }

    fn file_type() -> FileType {
        FileType::Toml
    }
}
<|endoftext|>


<commit_before>use std::io::{Result, Read, Write, Seek, SeekFrom, Error, ErrorKind};
use std::ops::{Deref, DerefMut};
use super::{ReadAt, WriteAt, Size};

/// Adapts a `ReadAt` or `WriteAt` into a `Read` or `Write`.
///
/// This wraps anything that read and write at offsets, turning into an object that can
/// read or write at a file position. This allows you to use those types with all the many
/// functions that expect a `Read` or `Write`.
///
/// Note that seeking on `Cursor` has limited functionality. We don't know how many bytes are
/// available, so we can't use SeekFrom::End. See [`SizeCursor`][SizeCursor] for another option.
///
/// [SizeCursor]: struct.SizeCursor.html
///
/// # Examples
///
/// ```no_run
/// # use std::io::{self, Result, Read};
/// # use std::fs::File;
/// use positioned_io::{ReadAt, Cursor};
///
/// struct NetworkStorage {
///     // A remote disk that supports random access.
/// }
/// # impl NetworkStorage {
/// #   fn new(i: i32) -> Self { NetworkStorage { } }
/// # }
/// impl ReadAt for NetworkStorage {
///     // ...
/// #   fn read_at(&self, pos: u64, buf: &mut [u8]) -> Result<usize> {
/// #       Ok(0)
/// #   }
/// }
///
/// # const SOME_LOCATION: i32 = 1;
/// # fn foo() -> Result<()> {
/// // Adapt our storage into a Read.
/// let storage = NetworkStorage::new(SOME_LOCATION);
/// let curs = Cursor::new_pos(storage, 1 << 30);
///
/// // Copy a segment to a file.
/// let input = curs.take(1 << 20);
/// let output = try!(File::create("segment.out"));
/// try!(io::copy(&mut input, &mut output));
/// # Ok(())
/// # }
/// ```
pub struct Cursor<I> {
    io: I,
    pos: u64,
}
impl<I> Cursor<I> {
    /// Create a new `Cursor` which starts reading at a specified offset.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new_pos(io: I, pos: u64) -> Self {
        Cursor { io: io, pos: pos }
    }
    /// Create a new Cursor which starts reading at offset zero.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new(io: I) -> Self {
        Self::new_pos(io, 0)
    }

    /// Consume `self` and yield the inner `ReadAt` or `WriteAt`.
    pub fn into_inner(self) -> I {
        self.io
    }
    /// Borrow the inner `ReadAt` or `WriteAt`.
    pub fn get_ref(&self) -> &I {
        &self.io
    }
    /// Borrow the inner `ReadAt` or `WriteAt` mutably.
    pub fn get_mut(&mut self) -> &mut I {
        &mut self.io
    }

    /// Get the current read/write position.
    pub fn position(&self) -> u64 {
        self.pos
    }
    /// Set the current read/write position.
    pub fn set_position(&mut self, pos: u64) {
        self.pos = pos;
    }
}

impl<I> Seek for Cursor<I> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        match pos {
            SeekFrom::Start(p) => self.pos = p,
            SeekFrom::Current(p) => {
                let pos = self.pos as i64 + p;
                if pos < 0 {
                    return Err(Error::new(ErrorKind::InvalidInput, "seek to a negative position"));
                }
                self.pos = pos as u64;
            }
            SeekFrom::End(_) => {
                return Err(Error::new(ErrorKind::InvalidInput, "seek from unknown end"))
            }
        };
        Ok(self.pos)
    }
}

impl<I> Read for Cursor<I>
    where I: ReadAt
{
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let bytes = try!(self.get_ref().read_at(self.pos, buf));
        self.pos += bytes as u64;
        Ok(bytes)
    }
}
impl<I> Write for Cursor<I>
    where I: WriteAt
{
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let pos = self.pos;
        let bytes = try!(self.get_mut().write_at(pos, buf));
        self.pos += bytes as u64;
        Ok(bytes)
    }
    fn flush(&mut self) -> Result<()> {
        WriteAt::flush(self.get_mut())
    }
}

/// Adapts a `ReadAt` or `WriteAt` into a `Read` or `Write`, with better seeking.
///
/// This is just like [`Cursor`][Cursor], except that it requires an object that implements
/// [`Size`][Size], and that it can seek from the end of the I/O object.
///
/// Eventually it will be legal to specialize `Cursor` for types that implement `Size`, see
/// [RFC 1210][RFC].
///
/// [Cursor]: struct.Cursor.html
/// [Size]: trait.Size.html
/// [RFC]: https://github.com/rust-lang/rfcs/pull/1210
pub struct SizeCursor<I: Size>(Cursor<I>);
impl<I> SizeCursor<I>
    where I: Size
{
    /// Create a new `SizeCursor` which starts reading at a specified offset.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new_pos(io: I, pos: u64) -> Self {
        SizeCursor(Cursor::new_pos(io, pos))
    }
    /// Create a new `SizeCursor` which starts reading at offset zero.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new(io: I) -> Self {
        SizeCursor(Cursor::new(io))
    }
}

// Automatically fall back to Cursor.
impl<I> Deref for SizeCursor<I>
    where I: Size
{
    type Target = Cursor<I>;
    fn deref(&self) -> &Cursor<I> {
        &self.0
    }
}
impl<I> DerefMut for SizeCursor<I>
    where I: Size
{
    fn deref_mut(&mut self) -> &mut Cursor<I> {
        &mut self.0
    }
}

// We know how to seek from the end for SizeCursor.
impl<I> Seek for SizeCursor<I>
    where I: Size
{
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        let pos = match pos {
            SeekFrom::Start(p) => p as i64,
            SeekFrom::Current(p) => self.pos as i64 + p,
            SeekFrom::End(p) => {
                match self.get_ref().size() {
                    Err(e) => return Err(e),
                    Ok(None) => {
                        return Err(Error::new(ErrorKind::InvalidData, "seek from unknown end"))
                    }
                    Ok(Some(s)) => s as i64 + p,
                }
            }
        };
        self.0.pos = pos as u64;
        Ok(self.pos)
    }
}
<commit_msg>Fix doc test<commit_after>use std::io::{Result, Read, Write, Seek, SeekFrom, Error, ErrorKind};
use std::ops::{Deref, DerefMut};
use super::{ReadAt, WriteAt, Size};

/// Adapts a `ReadAt` or `WriteAt` into a `Read` or `Write`.
///
/// This wraps anything that read and write at offsets, turning into an object that can
/// read or write at a file position. This allows you to use those types with all the many
/// functions that expect a `Read` or `Write`.
///
/// Note that seeking on `Cursor` has limited functionality. We don't know how many bytes are
/// available, so we can't use SeekFrom::End. See [`SizeCursor`][SizeCursor] for another option.
///
/// [SizeCursor]: struct.SizeCursor.html
///
/// # Examples
///
/// ```no_run
/// # use std::io::{self, Result, Read};
/// # use std::fs::File;
/// use positioned_io::{ReadAt, Cursor};
///
/// struct NetworkStorage {
///     // A remote disk that supports random access.
/// }
/// # impl NetworkStorage {
/// #   fn new(i: i32) -> Self { NetworkStorage { } }
/// # }
/// impl ReadAt for NetworkStorage {
///     // ...
/// #   fn read_at(&self, pos: u64, buf: &mut [u8]) -> Result<usize> {
/// #       Ok(0)
/// #   }
/// }
///
/// # const SOME_LOCATION: i32 = 1;
/// # fn foo() -> Result<()> {
/// // Adapt our storage into a Read.
/// let storage = NetworkStorage::new(SOME_LOCATION);
/// let curs = Cursor::new_pos(storage, 1 << 30);
///
/// // Copy a segment to a file.
/// let mut input = curs.take(1 << 20);
/// let mut output = try!(File::create("segment.out"));
/// try!(io::copy(&mut input, &mut output));
/// # Ok(())
/// # }
/// ```
pub struct Cursor<I> {
    io: I,
    pos: u64,
}
impl<I> Cursor<I> {
    /// Create a new `Cursor` which starts reading at a specified offset.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new_pos(io: I, pos: u64) -> Self {
        Cursor { io: io, pos: pos }
    }
    /// Create a new Cursor which starts reading at offset zero.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new(io: I) -> Self {
        Self::new_pos(io, 0)
    }

    /// Consume `self` and yield the inner `ReadAt` or `WriteAt`.
    pub fn into_inner(self) -> I {
        self.io
    }
    /// Borrow the inner `ReadAt` or `WriteAt`.
    pub fn get_ref(&self) -> &I {
        &self.io
    }
    /// Borrow the inner `ReadAt` or `WriteAt` mutably.
    pub fn get_mut(&mut self) -> &mut I {
        &mut self.io
    }

    /// Get the current read/write position.
    pub fn position(&self) -> u64 {
        self.pos
    }
    /// Set the current read/write position.
    pub fn set_position(&mut self, pos: u64) {
        self.pos = pos;
    }
}

impl<I> Seek for Cursor<I> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        match pos {
            SeekFrom::Start(p) => self.pos = p,
            SeekFrom::Current(p) => {
                let pos = self.pos as i64 + p;
                if pos < 0 {
                    return Err(Error::new(ErrorKind::InvalidInput, "seek to a negative position"));
                }
                self.pos = pos as u64;
            }
            SeekFrom::End(_) => {
                return Err(Error::new(ErrorKind::InvalidInput, "seek from unknown end"))
            }
        };
        Ok(self.pos)
    }
}

impl<I> Read for Cursor<I>
    where I: ReadAt
{
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let bytes = try!(self.get_ref().read_at(self.pos, buf));
        self.pos += bytes as u64;
        Ok(bytes)
    }
}
impl<I> Write for Cursor<I>
    where I: WriteAt
{
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let pos = self.pos;
        let bytes = try!(self.get_mut().write_at(pos, buf));
        self.pos += bytes as u64;
        Ok(bytes)
    }
    fn flush(&mut self) -> Result<()> {
        WriteAt::flush(self.get_mut())
    }
}

/// Adapts a `ReadAt` or `WriteAt` into a `Read` or `Write`, with better seeking.
///
/// This is just like [`Cursor`][Cursor], except that it requires an object that implements
/// [`Size`][Size], and that it can seek from the end of the I/O object.
///
/// Eventually it will be legal to specialize `Cursor` for types that implement `Size`, see
/// [RFC 1210][RFC].
///
/// [Cursor]: struct.Cursor.html
/// [Size]: trait.Size.html
/// [RFC]: https://github.com/rust-lang/rfcs/pull/1210
pub struct SizeCursor<I: Size>(Cursor<I>);
impl<I> SizeCursor<I>
    where I: Size
{
    /// Create a new `SizeCursor` which starts reading at a specified offset.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new_pos(io: I, pos: u64) -> Self {
        SizeCursor(Cursor::new_pos(io, pos))
    }
    /// Create a new `SizeCursor` which starts reading at offset zero.
    ///
    /// Pass in a `ReadAt` or `WriteAt` as `io`.
    pub fn new(io: I) -> Self {
        SizeCursor(Cursor::new(io))
    }
}

// Automatically fall back to Cursor.
impl<I> Deref for SizeCursor<I>
    where I: Size
{
    type Target = Cursor<I>;
    fn deref(&self) -> &Cursor<I> {
        &self.0
    }
}
impl<I> DerefMut for SizeCursor<I>
    where I: Size
{
    fn deref_mut(&mut self) -> &mut Cursor<I> {
        &mut self.0
    }
}

// We know how to seek from the end for SizeCursor.
impl<I> Seek for SizeCursor<I>
    where I: Size
{
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        let pos = match pos {
            SeekFrom::Start(p) => p as i64,
            SeekFrom::Current(p) => self.pos as i64 + p,
            SeekFrom::End(p) => {
                match self.get_ref().size() {
                    Err(e) => return Err(e),
                    Ok(None) => {
                        return Err(Error::new(ErrorKind::InvalidData, "seek from unknown end"))
                    }
                    Ok(Some(s)) => s as i64 + p,
                }
            }
        };
        self.0.pos = pos as u64;
        Ok(self.pos)
    }
}
<|endoftext|>


<commit_before>//! Window-wrangling, polygon-pushing and input-grabbing
//!

#[macro_use]
extern crate glium;
extern crate image;
extern crate cgmath;
extern crate calx_alg;
extern crate calx_window;
extern crate calx_color;
extern crate calx_layout;
extern crate calx_cache;

pub use draw_util::DrawUtil;
pub use font::{Font, Fonter, Align};
pub use wall::{Wall, Vertex};

mod draw_util;
mod font;
mod wall;

/// UI Widget static identifier, unique for a specific site in source code.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct WidgetId {
    filename: &'static str,
    line: u32,
    column: u32,
}

impl WidgetId {
    pub fn new(filename: &'static str, line: u32, column: u32) -> WidgetId {
        WidgetId {
            filename: filename,
            line: line,
            column: column,
        }
    }

    pub fn dummy() -> WidgetId {
        WidgetId {
            filename: "n/a",
            line: 666666,
            column: 666666,
        }
    }
}

#[macro_export]
/// Generate a static identifier for the current source code position. Used
/// with imgui API.
macro_rules! widget_id {
    () => {
        ::calx::backend::WidgetId::new(concat!(module_path!(), "/", file!()), line!(), column!())
    }
}
<commit_msg>Fix calx-wall description<commit_after>//! 2D drawing utilities
//!

#[macro_use]
extern crate glium;
extern crate image;
extern crate cgmath;
extern crate calx_alg;
extern crate calx_window;
extern crate calx_color;
extern crate calx_layout;
extern crate calx_cache;

pub use draw_util::DrawUtil;
pub use font::{Font, Fonter, Align};
pub use wall::{Wall, Vertex};

mod draw_util;
mod font;
mod wall;

/// UI Widget static identifier, unique for a specific site in source code.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct WidgetId {
    filename: &'static str,
    line: u32,
    column: u32,
}

impl WidgetId {
    pub fn new(filename: &'static str, line: u32, column: u32) -> WidgetId {
        WidgetId {
            filename: filename,
            line: line,
            column: column,
        }
    }

    pub fn dummy() -> WidgetId {
        WidgetId {
            filename: "n/a",
            line: 666666,
            column: 666666,
        }
    }
}

#[macro_export]
/// Generate a static identifier for the current source code position. Used
/// with imgui API.
macro_rules! widget_id {
    () => {
        ::calx::backend::WidgetId::new(concat!(module_path!(), "/", file!()), line!(), column!())
    }
}
<|endoftext|>


<commit_before>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(tool_lints)]
#![allow(unknown_lints, clippy::missing_docs_in_private_items)]

use rustc_driver::{self, driver::CompileController, Compilation};
use rustc_plugin;
use std::process::{exit, Command};

#[allow(clippy::print_stdout)]
fn show_version() {
    println!(env!("CARGO_PKG_VERSION"));
}

pub fn main() {
    exit(rustc_driver::run(move || {
        use std::env;

        if std::env::args().any(|a| a == "--version" || a == "-V") {
            show_version();
            exit(0);
        }

        let sys_root = option_env!("SYSROOT")
            .map(String::from)
            .or_else(|| std::env::var("SYSROOT").ok())
            .or_else(|| {
                let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
            })
            .or_else(|| {
                Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| s.trim().to_owned())
            })
            .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

        // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
        // We're invoking the compiler programmatically, so we ignore this/
        let mut orig_args: Vec<String> = env::args().collect();
        if orig_args.len() <= 1 {
            std::process::exit(1);
        }
        if orig_args[1] == "rustc" {
            // we still want to be able to invoke it normally though
            orig_args.remove(1);
        }
        // this conditional check for the --sysroot flag is there so users can call
        // `clippy_driver` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
            orig_args.clone()
        } else {
            orig_args
                .clone()
                .into_iter()
                .chain(Some("--sysroot".to_owned()))
                .chain(Some(sys_root))
                .collect()
        };

        // this check ensures that dependencies are built but not linted and the final
        // crate is
        // linted but not built
        let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
            || orig_args.iter().any(|s| s == "--emit=dep-info,metadata");

        if clippy_enabled {
            args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
            if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                args.extend(
                    extra_args
                        .split("__CLIPPY_HACKERY__")
                        .filter(|s| !s.is_empty())
                        .map(str::to_owned),
                );
            }
        }

        let mut controller = CompileController::basic();
        if clippy_enabled {
            controller.after_parse.callback = Box::new(move |state| {
                let mut registry = rustc_plugin::registry::Registry::new(
                    state.session,
                    state
                        .krate
                        .as_ref()
                        .expect(
                            "at this compilation stage \
                            the crate must be parsed",
                        )
                        .span,
                );
                registry.args_hidden = Some(Vec::new());

                let conf = clippy_lints::read_conf(&registry);
                clippy_lints::register_plugins(&mut registry, &conf);

                let rustc_plugin::registry::Registry {
                    early_lint_passes,
                    late_lint_passes,
                    lint_groups,
                    llvm_passes,
                    attributes,
                    ..
                } = registry;
                let sess = &state.session;
                let mut ls = sess.lint_store.borrow_mut();
                for pass in early_lint_passes {
                    ls.register_early_pass(Some(sess), true, pass);
                }
                for pass in late_lint_passes {
                    ls.register_late_pass(Some(sess), true, pass);
                }

                for (name, (to, deprecated_name)) in lint_groups {
                    ls.register_group(Some(sess), true, name, deprecated_name, to);
                }
                clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);

                sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                sess.plugin_attributes.borrow_mut().extend(attributes);
            });
        }
        controller.compilation_done.stop = Compilation::Stop;

        let args = args;
        rustc_driver::run_compiler(&args, Box::new(controller), None, None)
    }) as i32)
}
<commit_msg>driver: Improve check for rustc arg<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(tool_lints)]
#![allow(unknown_lints, clippy::missing_docs_in_private_items)]

use rustc_driver::{self, driver::CompileController, Compilation};
use rustc_plugin;
use std::path::Path;
use std::process::{exit, Command};

#[allow(clippy::print_stdout)]
fn show_version() {
    println!(env!("CARGO_PKG_VERSION"));
}

pub fn main() {
    exit(rustc_driver::run(move || {
        use std::env;

        if std::env::args().any(|a| a == "--version" || a == "-V") {
            show_version();
            exit(0);
        }

        let sys_root = option_env!("SYSROOT")
            .map(String::from)
            .or_else(|| std::env::var("SYSROOT").ok())
            .or_else(|| {
                let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
            })
            .or_else(|| {
                Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| s.trim().to_owned())
            })
            .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

        // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
        // We're invoking the compiler programmatically, so we ignore this/
        let mut orig_args: Vec<String> = env::args().collect();
        if orig_args.len() <= 1 {
            std::process::exit(1);
        }
        if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) {
            // we still want to be able to invoke it normally though
            orig_args.remove(1);
        }
        // this conditional check for the --sysroot flag is there so users can call
        // `clippy_driver` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
            orig_args.clone()
        } else {
            orig_args
                .clone()
                .into_iter()
                .chain(Some("--sysroot".to_owned()))
                .chain(Some(sys_root))
                .collect()
        };

        // this check ensures that dependencies are built but not linted and the final
        // crate is
        // linted but not built
        let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
            || orig_args.iter().any(|s| s == "--emit=dep-info,metadata");

        if clippy_enabled {
            args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
            if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                args.extend(
                    extra_args
                        .split("__CLIPPY_HACKERY__")
                        .filter(|s| !s.is_empty())
                        .map(str::to_owned),
                );
            }
        }

        let mut controller = CompileController::basic();
        if clippy_enabled {
            controller.after_parse.callback = Box::new(move |state| {
                let mut registry = rustc_plugin::registry::Registry::new(
                    state.session,
                    state
                        .krate
                        .as_ref()
                        .expect(
                            "at this compilation stage \
                            the crate must be parsed",
                        )
                        .span,
                );
                registry.args_hidden = Some(Vec::new());

                let conf = clippy_lints::read_conf(&registry);
                clippy_lints::register_plugins(&mut registry, &conf);

                let rustc_plugin::registry::Registry {
                    early_lint_passes,
                    late_lint_passes,
                    lint_groups,
                    llvm_passes,
                    attributes,
                    ..
                } = registry;
                let sess = &state.session;
                let mut ls = sess.lint_store.borrow_mut();
                for pass in early_lint_passes {
                    ls.register_early_pass(Some(sess), true, pass);
                }
                for pass in late_lint_passes {
                    ls.register_late_pass(Some(sess), true, pass);
                }

                for (name, (to, deprecated_name)) in lint_groups {
                    ls.register_group(Some(sess), true, name, deprecated_name, to);
                }
                clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);

                sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                sess.plugin_attributes.borrow_mut().extend(attributes);
            });
        }
        controller.compilation_done.stop = Compilation::Stop;

        let args = args;
        rustc_driver::run_compiler(&args, Box::new(controller), None, None)
    }) as i32)
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::env;
use std::path::Path;
use std::process::Command;

struct Sources {
    files: Vec<&'static str>,
}

impl Sources {
    fn new() -> Sources {
        Sources { files: Vec::new() }
    }

    fn extend(&mut self, sources: &[&'static str]) {
        self.files.extend(sources);
    }
}

fn main() {
    if !Path::new("compiler-rt/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    let target = env::var("TARGET").expect("TARGET was not set");
    let cfg = &mut gcc::Config::new();

    if target.contains("msvc") {
        cfg.define("__func__", Some("__FUNCTION__"));
    } else {
        cfg.flag("-fno-builtin");
        cfg.flag("-fomit-frame-pointer");
        cfg.flag("-ffreestanding");
    }

    let mut sources = Sources::new();

    sources.extend(&[
        "muldi3.c",
        "mulosi4.c",
        "mulodi4.c",
        "divsi3.c",
        "divdi3.c",
        "modsi3.c",
        "moddi3.c",
        "divmodsi4.c",
        "divmoddi4.c",
        "ashldi3.c",
        "ashrdi3.c",
        "lshrdi3.c",
        "udivdi3.c",
        "umoddi3.c",
        "udivmoddi4.c",
        "udivsi3.c",
        "umodsi3.c",
        "udivmodsi4.c",
        "adddf3.c",
        "addsf3.c",
        "powidf2.c",
        "powisf2.c",
    ]);

    for src in sources.files.iter() {
        cfg.file(Path::new("compiler-rt/lib/builtins").join(src));
    }

    cfg.compile("libcompiler-rt.a");
}
<commit_msg>add rebuild logic to compiler-rt-cdylib<commit_after>extern crate gcc;

use std::env;
use std::path::Path;
use std::process::Command;

struct Sources {
    files: Vec<&'static str>,
}

impl Sources {
    fn new() -> Sources {
        Sources { files: Vec::new() }
    }

    fn extend(&mut self, sources: &[&'static str]) {
        self.files.extend(sources);
    }
}

fn main() {
    if !Path::new("compiler-rt/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    let target = env::var("TARGET").expect("TARGET was not set");
    let cfg = &mut gcc::Config::new();

    if target.contains("msvc") {
        cfg.define("__func__", Some("__FUNCTION__"));
    } else {
        cfg.flag("-fno-builtin");
        cfg.flag("-fomit-frame-pointer");
        cfg.flag("-ffreestanding");
    }

    let mut sources = Sources::new();

    sources.extend(&[
        "muldi3.c",
        "mulosi4.c",
        "mulodi4.c",
        "divsi3.c",
        "divdi3.c",
        "modsi3.c",
        "moddi3.c",
        "divmodsi4.c",
        "divmoddi4.c",
        "ashldi3.c",
        "ashrdi3.c",
        "lshrdi3.c",
        "udivdi3.c",
        "umoddi3.c",
        "udivmoddi4.c",
        "udivsi3.c",
        "umodsi3.c",
        "udivmodsi4.c",
        "adddf3.c",
        "addsf3.c",
        "powidf2.c",
        "powisf2.c",
    ]);

    let builtins_dir = Path::new("compiler-rt/lib/builtins");
    for src in sources.files.iter() {
        cfg.file(builtins_dir.join(src));
    }

    cfg.compile("libcompiler-rt.a");

    println!("cargo:rerun-if-changed=build.rs");

    for source in sources.files.iter() {
        println!("cargo:rerun-if-changed={}", builtins_dir.join(source).display());
    }
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::fmt;
use std::io;
use std::str::Utf8Error;
use std::string::FromUtf8Error;

use base64;

use serde::de;

use parse::Position;

/// Deserialization result.
pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    IoError(String),
    Message(String),
    Parser(ParseError, Position),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ParseError {
    Base64Error(base64::DecodeError),
    Eof,
    ExpectedArray,
    ExpectedArrayEnd,
    ExpectedAttribute,
    ExpectedAttributeEnd,
    ExpectedBoolean,
    ExpectedComma,
    ExpectedEnum,
    ExpectedChar,
    ExpectedFloat,
    ExpectedInteger,
    ExpectedOption,
    ExpectedOptionEnd,
    ExpectedMap,
    ExpectedMapColon,
    ExpectedMapEnd,
    ExpectedStruct,
    ExpectedStructEnd,
    ExpectedUnit,
    ExpectedStructName,
    ExpectedString,
    ExpectedStringEnd,
    ExpectedIdentifier,

    InvalidEscape(&'static str),

    NoSuchExtension(String),

    UnclosedBlockComment,
    UnexpectedByte(char),

    Utf8Error(Utf8Error),
    TrailingCharacters,

    #[doc(hidden)] __NonExhaustive,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::IoError(ref s) => write!(f, "{}", s),
            Error::Message(ref s) => write!(f, "{}", s),
            Error::Parser(_, pos) => write!(f, "{}: {}", pos, self.description()),
        }
    }
}

impl de::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IoError(ref s) => s,
            Error::Message(ref e) => e,
            Error::Parser(ref kind, _) => match *kind {
                ParseError::Base64Error(ref e) => e.description(),
                ParseError::Eof => "Unexpected end of file",
                ParseError::ExpectedArray => "Expected array",
                ParseError::ExpectedArrayEnd => "Expected end of array",
                ParseError::ExpectedAttribute => "Expected an enable attribute",
                ParseError::ExpectedAttributeEnd => {
                    "Expected closing `)` and `]` after the attribute"
                }
                ParseError::ExpectedBoolean => "Expected boolean",
                ParseError::ExpectedComma => "Expected comma",
                ParseError::ExpectedEnum => "Expected enum",
                ParseError::ExpectedChar => "Expected char",
                ParseError::ExpectedFloat => "Expected float",
                ParseError::ExpectedInteger => "Expected integer",
                ParseError::ExpectedOption => "Expected option",
                ParseError::ExpectedOptionEnd => "Expected end of option",
                ParseError::ExpectedMap => "Expected map",
                ParseError::ExpectedMapColon => "Expected colon",
                ParseError::ExpectedMapEnd => "Expected end of map",
                ParseError::ExpectedStruct => "Expected struct",
                ParseError::ExpectedStructEnd => "Expected end of struct",
                ParseError::ExpectedUnit => "Expected unit",
                ParseError::ExpectedStructName => "Expected struct name",
                ParseError::ExpectedString => "Expected string",
                ParseError::ExpectedIdentifier => "Expected identifier",

                ParseError::InvalidEscape(_) => "Invalid escape sequence",

                ParseError::Utf8Error(ref e) => e.description(),
                ParseError::UnclosedBlockComment => "Unclosed block comment",
                ParseError::UnexpectedByte(_) => "Unexpected byte",
                ParseError::TrailingCharacters => "Non-whitespace trailing characters",

                _ => unimplemented!(),
            },
        }
    }
}

impl From<Utf8Error> for ParseError {
    fn from(e: Utf8Error) -> Self {
        ParseError::Utf8Error(e)
    }
}

impl From<FromUtf8Error> for ParseError {
    fn from(e: FromUtf8Error) -> Self {
        ParseError::Utf8Error(e.utf8_error())
    }
}

impl From<Utf8Error> for Error {
    fn from(e: Utf8Error) -> Self {
        Error::Parser(ParseError::Utf8Error(e), Position { line: 0, col: 0 })
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::IoError(e.description().to_string())
    }
}
<commit_msg>Match exhaustively and add missing branches<commit_after>use std::error::Error as StdError;
use std::fmt;
use std::io;
use std::str::Utf8Error;
use std::string::FromUtf8Error;

use base64;

use serde::de;

use parse::Position;

/// Deserialization result.
pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    IoError(String),
    Message(String),
    Parser(ParseError, Position),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ParseError {
    Base64Error(base64::DecodeError),
    Eof,
    ExpectedArray,
    ExpectedArrayEnd,
    ExpectedAttribute,
    ExpectedAttributeEnd,
    ExpectedBoolean,
    ExpectedComma,
    ExpectedEnum,
    ExpectedChar,
    ExpectedFloat,
    ExpectedInteger,
    ExpectedOption,
    ExpectedOptionEnd,
    ExpectedMap,
    ExpectedMapColon,
    ExpectedMapEnd,
    ExpectedStruct,
    ExpectedStructEnd,
    ExpectedUnit,
    ExpectedStructName,
    ExpectedString,
    ExpectedStringEnd,
    ExpectedIdentifier,

    InvalidEscape(&'static str),

    NoSuchExtension(String),

    UnclosedBlockComment,
    UnexpectedByte(char),

    Utf8Error(Utf8Error),
    TrailingCharacters,

    #[doc(hidden)] __NonExhaustive,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::IoError(ref s) => write!(f, "{}", s),
            Error::Message(ref s) => write!(f, "{}", s),
            Error::Parser(_, pos) => write!(f, "{}: {}", pos, self.description()),
        }
    }
}

impl de::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IoError(ref s) => s,
            Error::Message(ref e) => e,
            Error::Parser(ref kind, _) => match *kind {
                ParseError::Base64Error(ref e) => e.description(),
                ParseError::Eof => "Unexpected end of file",
                ParseError::ExpectedArray => "Expected array",
                ParseError::ExpectedArrayEnd => "Expected end of array",
                ParseError::ExpectedAttribute => "Expected an enable attribute",
                ParseError::ExpectedAttributeEnd => {
                    "Expected closing `)` and `]` after the attribute"
                }
                ParseError::ExpectedBoolean => "Expected boolean",
                ParseError::ExpectedComma => "Expected comma",
                ParseError::ExpectedEnum => "Expected enum",
                ParseError::ExpectedChar => "Expected char",
                ParseError::ExpectedFloat => "Expected float",
                ParseError::ExpectedInteger => "Expected integer",
                ParseError::ExpectedOption => "Expected option",
                ParseError::ExpectedOptionEnd => "Expected end of option",
                ParseError::ExpectedMap => "Expected map",
                ParseError::ExpectedMapColon => "Expected colon",
                ParseError::ExpectedMapEnd => "Expected end of map",
                ParseError::ExpectedStruct => "Expected struct",
                ParseError::ExpectedStructEnd => "Expected end of struct",
                ParseError::ExpectedUnit => "Expected unit",
                ParseError::ExpectedStructName => "Expected struct name",
                ParseError::ExpectedString => "Expected string",
                ParseError::ExpectedStringEnd => "Expected string end",
                ParseError::ExpectedIdentifier => "Expected identifier",

                ParseError::InvalidEscape(_) => "Invalid escape sequence",

                ParseError::NoSuchExtension(_) => "No such RON extension",

                ParseError::Utf8Error(ref e) => e.description(),
                ParseError::UnclosedBlockComment => "Unclosed block comment",
                ParseError::UnexpectedByte(_) => "Unexpected byte",
                ParseError::TrailingCharacters => "Non-whitespace trailing characters",

                ParseError::__NonExhaustive => unimplemented!(),
            },
        }
    }
}

impl From<Utf8Error> for ParseError {
    fn from(e: Utf8Error) -> Self {
        ParseError::Utf8Error(e)
    }
}

impl From<FromUtf8Error> for ParseError {
    fn from(e: FromUtf8Error) -> Self {
        ParseError::Utf8Error(e.utf8_error())
    }
}

impl From<Utf8Error> for Error {
    fn from(e: Utf8Error) -> Self {
        Error::Parser(ParseError::Utf8Error(e), Position { line: 0, col: 0 })
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::IoError(e.description().to_string())
    }
}
<|endoftext|>


<commit_before>pub use transform::Transform;

/// An entity is anything that has spatial properties (i.e. a `Transform`).
#[derive(Debug)]
pub struct Entity<T> {
  pub object: T,
  pub transform: Transform
}

impl<T> Entity<T> {
  pub fn new(object: T, transform: Transform) -> Self {
    Entity {
      object: object,
      transform: transform
    }
  }
}
<commit_msg>Export more items from transform in entity.<commit_after>pub use transform::*;

/// An entity is anything that has spatial properties (i.e. a `Transform`).
#[derive(Debug)]
pub struct Entity<T> {
  pub object: T,
  pub transform: Transform
}

impl<T> Entity<T> {
  pub fn new(object: T, transform: Transform) -> Self {
    Entity {
      object: object,
      transform: transform
    }
  }
}
<|endoftext|>


<commit_before>//! The errors needletail can return; only when parsing FASTA/FASTQ files

use crate::parser::Format;
use std::error::Error as StdError;
use std::fmt;
use std::io;

/// Represents where we were in a file when an error occurred.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ErrorPosition {
    /// Line number where the error occurred (starting with 1)
    pub line: u64,
    /// ID of record if available
    pub id: Option<String>,
}

impl fmt::Display for ErrorPosition {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(id) = self.id.as_ref() {
            write!(f, "record '{}' at ", id)?;
        }
        write!(f, "line {}", self.line)
    }
}

/// The type of error that occured during file parsing
#[derive(Clone, Debug, PartialEq)]
pub enum ParseErrorKind {
    /// An error happened during file/stream input/output
    Io,
    /// The file didn't start with `@` or `>`
    UnknownFormat,
    /// Invalid start byte encountered (expected `@` in FASTQ and `>` in FASTA)
    InvalidStart,
    /// The separator line in a FASTQ file is not valid (no `+`)
    InvalidSeparator,
    /// Sequence and quality lengths are not equal (in a FASTQ file only)
    UnequalLengths,
    /// Truncated record found
    UnexpectedEnd,
}

/// The only error type that needletail returns
#[derive(Clone, Debug, PartialEq)]
pub struct ParseError {
    /// A description of what went wrong
    pub msg: String,
    /// The type of error that occurred
    pub kind: ParseErrorKind,
    /// Position within file
    pub position: ErrorPosition,
    /// The format of the file we were parsing
    pub format: Option<Format>,
}

impl ParseError {
    pub fn new_invalid_start(byte_found: u8, position: ErrorPosition, format: Format) -> Self {
        let msg = format!(
            "Expected '{}' but found '{}",
            format.start_char(),
            (byte_found as char).escape_default()
        );
        ParseError {
            kind: ParseErrorKind::InvalidStart,
            msg,
            position,
            format: Some(format),
        }
    }

    pub fn new_invalid_separator(byte_found: u8, position: ErrorPosition) -> Self {
        let msg = format!(
            "Expected '+' separator but found '{}",
            (byte_found as char).escape_default()
        );
        ParseError {
            kind: ParseErrorKind::InvalidSeparator,
            msg,
            position,
            format: Some(Format::Fastq),
        }
    }

    pub fn new_unknown_format(byte_found: u8) -> Self {
        let msg = format!(
            "Expected '@' or '>' at the start of the file but found '{}'. Maybe it's compressed?",
            (byte_found as char).escape_default()
        );
        ParseError {
            kind: ParseErrorKind::UnknownFormat,
            msg,
            position: ErrorPosition::default(),
            format: Some(Format::Fastq),
        }
    }

    pub fn new_unequal_length(seq_len: usize, qual_len: usize, position: ErrorPosition) -> Self {
        let msg = format!(
            "Sequence length is {} but quality length is {}",
            seq_len, qual_len
        );
        ParseError {
            kind: ParseErrorKind::UnequalLengths,
            msg,
            position,
            format: Some(Format::Fastq),
        }
    }

    pub fn new_unexpected_end(position: ErrorPosition, format: Format) -> Self {
        ParseError {
            msg: String::new(),
            kind: ParseErrorKind::UnexpectedEnd,
            position,
            format: Some(format),
        }
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ParseErrorKind::Io => write!(f, "I/O error: {}", self.msg),
            ParseErrorKind::UnequalLengths
            | ParseErrorKind::InvalidStart
            | ParseErrorKind::UnknownFormat
            | ParseErrorKind::InvalidSeparator => write!(f, "{} ({})", self.msg, self.position),
            ParseErrorKind::UnexpectedEnd => {
                write!(f, "Unexpected end of input ({}).", self.position)
            }
        }
    }
}

impl From<io::Error> for ParseError {
    fn from(err: io::Error) -> ParseError {
        ParseError {
            msg: err.to_string(),
            kind: ParseErrorKind::Io,
            position: ErrorPosition::default(),
            format: None,
        }
    }
}

impl StdError for ParseError {
    fn cause(&self) -> Option<&dyn StdError> {
        // Ideally we would pass the io::Error but we don't for simplicity sake
        // since we wouldn't be able to `==` on the error kind otherwise.
        // TODO: impl partialeq manually?
        None
    }
}
<commit_msg>Remove misleading text in error<commit_after>//! The errors needletail can return; only when parsing FASTA/FASTQ files

use crate::parser::Format;
use std::error::Error as StdError;
use std::fmt;
use std::io;

/// Represents where we were in a file when an error occurred.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct ErrorPosition {
    /// Line number where the error occurred (starting with 1)
    pub line: u64,
    /// ID of record if available
    pub id: Option<String>,
}

impl fmt::Display for ErrorPosition {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(id) = self.id.as_ref() {
            write!(f, "record '{}' at ", id)?;
        }
        write!(f, "line {}", self.line)
    }
}

/// The type of error that occured during file parsing
#[derive(Clone, Debug, PartialEq)]
pub enum ParseErrorKind {
    /// An error happened during file/stream input/output
    Io,
    /// The file didn't start with `@` or `>` and we didn't know what to expect yet
    UnknownFormat,
    /// Invalid start byte of record encountered (expected `@` in FASTQ and `>` in FASTA)
    InvalidStart,
    /// The separator line in a FASTQ file is not valid (no `+`)
    InvalidSeparator,
    /// Sequence and quality lengths are not equal (in a FASTQ file only)
    UnequalLengths,
    /// Truncated record found
    UnexpectedEnd,
}

/// The only error type that needletail returns
#[derive(Clone, Debug, PartialEq)]
pub struct ParseError {
    /// A description of what went wrong
    pub msg: String,
    /// The type of error that occurred
    pub kind: ParseErrorKind,
    /// Position within file
    pub position: ErrorPosition,
    /// The format of the file we were parsing
    pub format: Option<Format>,
}

impl ParseError {
    pub fn new_invalid_start(byte_found: u8, position: ErrorPosition, format: Format) -> Self {
        let msg = format!(
            "Expected '{}' but found '{}",
            format.start_char(),
            (byte_found as char).escape_default()
        );
        ParseError {
            kind: ParseErrorKind::InvalidStart,
            msg,
            position,
            format: Some(format),
        }
    }

    pub fn new_invalid_separator(byte_found: u8, position: ErrorPosition) -> Self {
        let msg = format!(
            "Expected '+' separator but found '{}",
            (byte_found as char).escape_default()
        );
        ParseError {
            kind: ParseErrorKind::InvalidSeparator,
            msg,
            position,
            format: Some(Format::Fastq),
        }
    }

    pub fn new_unknown_format(byte_found: u8) -> Self {
        let msg = format!(
            "Expected '@' or '>' at the start of the file but found '{}'.",
            (byte_found as char).escape_default()
        );
        ParseError {
            kind: ParseErrorKind::UnknownFormat,
            msg,
            position: ErrorPosition::default(),
            format: Some(Format::Fastq),
        }
    }

    pub fn new_unequal_length(seq_len: usize, qual_len: usize, position: ErrorPosition) -> Self {
        let msg = format!(
            "Sequence length is {} but quality length is {}",
            seq_len, qual_len
        );
        ParseError {
            kind: ParseErrorKind::UnequalLengths,
            msg,
            position,
            format: Some(Format::Fastq),
        }
    }

    pub fn new_unexpected_end(position: ErrorPosition, format: Format) -> Self {
        ParseError {
            msg: String::new(),
            kind: ParseErrorKind::UnexpectedEnd,
            position,
            format: Some(format),
        }
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ParseErrorKind::Io => write!(f, "I/O error: {}", self.msg),
            ParseErrorKind::UnequalLengths
            | ParseErrorKind::InvalidStart
            | ParseErrorKind::UnknownFormat
            | ParseErrorKind::InvalidSeparator => write!(f, "{} ({})", self.msg, self.position),
            ParseErrorKind::UnexpectedEnd => {
                write!(f, "Unexpected end of input ({}).", self.position)
            }
        }
    }
}

impl From<io::Error> for ParseError {
    fn from(err: io::Error) -> ParseError {
        ParseError {
            msg: err.to_string(),
            kind: ParseErrorKind::Io,
            position: ErrorPosition::default(),
            format: None,
        }
    }
}

impl StdError for ParseError {
    fn cause(&self) -> Option<&dyn StdError> {
        // Ideally we would pass the io::Error but we don't for simplicity sake
        // since we wouldn't be able to `==` on the error kind otherwise.
        // TODO: impl partialeq manually?
        None
    }
}
<|endoftext|>