<commit_before>// DOCS

extern crate tempdir;

use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior) -> Self {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, p.parent().unwrap_or(p))
    }

    pub fn new_with_tmpdir<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior, tmpdir: P) -> Self {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<T, E, F>(&self, f: F) -> Result<T, E> where
        E: From<io::Error>,
        F: FnOnce(&mut fs::File) -> Result<T, E>
    {
        let tmpdir = try!(TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ));

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = try!({
            let mut tmpfile = try!(fs::File::create(&tmppath));
            f(&mut tmpfile)
        });
        try!(self.commit(&tmppath));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    extern crate nix;

    use std::{io,fs,path};
    use std::os::unix::io::AsRawFd;

    fn fsync_dir(x: &path::Path) -> io::Result<()> {
        let f = try!(fs::File::open(x));
        try!(nix::unistd::fsync(f.as_raw_fd()));
        Ok(())
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::rename(src, dst));

        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        Ok(())
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        try!(fs::remove_file(src));

        let src_directory = src.parent().unwrap();
        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        if src_directory != dst_directory { try!(fsync_dir(src_directory)); }
        Ok(())
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32 as win32kernel;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH | winapi::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<commit_msg>Use an enum to differentiate between user and library errors<commit_after>// DOCS

extern crate tempdir;

use std::error::Error;
use std::fmt;
use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

/// Represents an error raised by `AtomicFile.write`.
#[derive(Debug)]
pub enum AtomicWriteError<E> {
    /// The error originated in the library itself, while it was either creating a temporary file
    /// or moving the file into place.
    Internal(io::Error),
    /// The error originated in the user-supplied callback.
    User(E)
}

impl<E: fmt::Display> fmt::Display for AtomicWriteError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            AtomicWriteError::Internal(ref e) => e.fmt(f),
            AtomicWriteError::User(ref e) => e.fmt(f)
        }
    }
}

impl<E: Error> Error for AtomicWriteError<E> {
    fn description(&self) -> &str {
        match *self {
            AtomicWriteError::Internal(ref e) => e.description(),
            AtomicWriteError::User(ref e) => e.description()
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            AtomicWriteError::Internal(ref e) => Some(e),
            AtomicWriteError::User(ref e) => Some(e)
        }
    }
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior) -> Self {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, p.parent().unwrap_or(p))
    }

    pub fn new_with_tmpdir<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior, tmpdir: P) -> Self {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<T, E, F>(&self, f: F) -> Result<T, AtomicWriteError<E>> where
        F: FnOnce(&mut fs::File) -> Result<T, E>
    {
        macro_rules! try_internal {
            ($expr:expr) => {
                match $expr {
                    Ok(r) => r,
                    Err(e) => return Err(AtomicWriteError::Internal(e))
                }
            };
        }

        let tmpdir = try_internal!(TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ));

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = {
            let mut tmpfile = try_internal!(fs::File::create(&tmppath));
            try!(f(&mut tmpfile).map_err(AtomicWriteError::User))
        };
        try_internal!(self.commit(&tmppath));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    extern crate nix;

    use std::{io,fs,path};
    use std::os::unix::io::AsRawFd;

    fn fsync_dir(x: &path::Path) -> io::Result<()> {
        let f = try!(fs::File::open(x));
        try!(nix::unistd::fsync(f.as_raw_fd()));
        Ok(())
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::rename(src, dst));

        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        Ok(())
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        try!(fs::remove_file(src));

        let src_directory = src.parent().unwrap();
        let dst_directory = dst.parent().unwrap();
        try!(fsync_dir(dst_directory));
        if src_directory != dst_directory { try!(fsync_dir(src_directory)); }
        Ok(())
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;
    extern crate kernel32 as win32kernel;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH | winapi::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {win32kernel::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<|endoftext|>


<commit_before>//! Modbus implementation in pure Rust.
//!
//! # Examples
//!
//! ```
//! # extern crate modbus;
//! # extern crate test_server;
//! # use test_server::start_dummy_server;
//! # fn main() {
//! use modbus::{Client, Coil};
//! use modbus::tcp;
//! # if cfg!(feature = "modbus-server-tests") {
//! # let (_s, port) = start_dummy_server(Some(22221));
//!
//! let mut cfg = tcp::Config::default();
//! # cfg.tcp_port = port;
//! let mut client = tcp::Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
//! assert!(client.write_single_coil(0, Coil::On).is_ok());
//! # }
//! # }
//! ```

#[macro_use]
extern crate enum_primitive;
extern crate num;
extern crate byteorder;

use std::io;
use std::str::FromStr;

pub mod binary;
mod client;

pub mod scoped;

/// The Modbus TCP backend implements a Modbus variant used for communication over TCP/IPv4 networks.
pub mod tcp;
pub use tcp::Transport;
pub use tcp::Config;
pub use client::Client;

type Address = u16;
type Quantity = u16;
type Value = u16;

enum Function<'a> {
    ReadCoils(Address, Quantity),
    ReadDiscreteInputs(Address, Quantity),
    ReadHoldingRegisters(Address, Quantity),
    ReadInputRegisters(Address, Quantity),
    WriteSingleCoil(Address, Value),
    WriteSingleRegister(Address, Value),
    WriteMultipleCoils(Address, Quantity, &'a [u8]),
    WriteMultipleRegisters(Address, Quantity, &'a [u8]),
}

impl<'a> Function<'a> {
    fn code(&self) -> u8 {
        match *self {
            Function::ReadCoils(_, _) => 0x01,
            Function::ReadDiscreteInputs(_, _) => 0x02,
            Function::ReadHoldingRegisters(_, _) => 0x03,
            Function::ReadInputRegisters(_, _) => 0x04,
            Function::WriteSingleCoil(_, _) => 0x05,
            Function::WriteSingleRegister(_, _) => 0x06,
            Function::WriteMultipleCoils(_, _, _) => 0x0f,
            Function::WriteMultipleRegisters(_, _, _) => 0x10,
        }
        // ReadExceptionStatus     = 0x07,
        // ReportSlaveId           = 0x11,
        // MaskWriteRegister       = 0x16,
        // WriteAndReadRegisters   = 0x17
    }
}

enum_from_primitive! {
#[derive(Debug, PartialEq)]
/// Modbus exception codes returned from the server.
pub enum ExceptionCode {
    IllegalFunction         = 0x01,
    IllegalDataAddress      = 0x02,
    IllegalDataValue        = 0x03,
    SlaveOrServerFailure    = 0x04,
    Acknowledge             = 0x05,
    SlaveOrServerBusy       = 0x06,
    NegativeAcknowledge     = 0x07,
    MemoryParity            = 0x08,
    NotDefined              = 0x09,
    GatewayPath             = 0x0a,
    GatewayTarget           = 0x0b
}
}

/// `InvalidData` reasons
#[derive(Debug)]
pub enum Reason {
    UnexpectedReplySize,
    BytecountNotEven,
    SendBufferEmpty,
    RecvBufferEmpty,
    SendBufferTooBig,
    DecodingError,
    EncodingError,
    InvalidByteorder,
    Custom(String),
}

/// Combination of Modbus, IO and data corruption errors
#[derive(Debug)]
pub enum Error {
    Exception(ExceptionCode),
    Io(io::Error),
    InvalidResponse,
    InvalidData(Reason),
    InvalidFunction,
    ParseCoilError,
}

impl From<ExceptionCode> for Error {
    fn from(err: ExceptionCode) -> Error {
        Error::Exception(err)
    }
}

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

/// Result type used to nofify success or failure in communication
pub type Result<T> = std::result::Result<T, Error>;

/// Single bit status values, used in read or write coil functions
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Coil {
    On,
    Off,
}

impl Coil {
    fn code(&self) -> u16 {
        match *self {
            Coil::On => 0xff00,
            Coil::Off => 0x0000,
        }
    }
}

impl FromStr for Coil {
    type Err = Error;
    fn from_str(s: &str) -> Result<Coil> {
        if s == "On" {
            Ok(Coil::On)
        } else if s == "Off" {
            Ok(Coil::Off)
        } else {
            Err(Error::ParseCoilError)
        }
    }
}
<commit_msg>Implement std::error::Error for Error<commit_after>//! Modbus implementation in pure Rust.
//!
//! # Examples
//!
//! ```
//! # extern crate modbus;
//! # extern crate test_server;
//! # use test_server::start_dummy_server;
//! # fn main() {
//! use modbus::{Client, Coil};
//! use modbus::tcp;
//! # if cfg!(feature = "modbus-server-tests") {
//! # let (_s, port) = start_dummy_server(Some(22221));
//!
//! let mut cfg = tcp::Config::default();
//! # cfg.tcp_port = port;
//! let mut client = tcp::Transport::new_with_cfg("127.0.0.1", cfg).unwrap();
//! assert!(client.write_single_coil(0, Coil::On).is_ok());
//! # }
//! # }
//! ```

#[macro_use]
extern crate enum_primitive;
extern crate num;
extern crate byteorder;

use std::io;
use std::fmt;
use std::str::FromStr;

pub mod binary;
mod client;

pub mod scoped;

/// The Modbus TCP backend implements a Modbus variant used for communication over TCP/IPv4 networks.
pub mod tcp;
pub use tcp::Transport;
pub use tcp::Config;
pub use client::Client;

type Address = u16;
type Quantity = u16;
type Value = u16;

enum Function<'a> {
    ReadCoils(Address, Quantity),
    ReadDiscreteInputs(Address, Quantity),
    ReadHoldingRegisters(Address, Quantity),
    ReadInputRegisters(Address, Quantity),
    WriteSingleCoil(Address, Value),
    WriteSingleRegister(Address, Value),
    WriteMultipleCoils(Address, Quantity, &'a [u8]),
    WriteMultipleRegisters(Address, Quantity, &'a [u8]),
}

impl<'a> Function<'a> {
    fn code(&self) -> u8 {
        match *self {
            Function::ReadCoils(_, _) => 0x01,
            Function::ReadDiscreteInputs(_, _) => 0x02,
            Function::ReadHoldingRegisters(_, _) => 0x03,
            Function::ReadInputRegisters(_, _) => 0x04,
            Function::WriteSingleCoil(_, _) => 0x05,
            Function::WriteSingleRegister(_, _) => 0x06,
            Function::WriteMultipleCoils(_, _, _) => 0x0f,
            Function::WriteMultipleRegisters(_, _, _) => 0x10,
        }
        // ReadExceptionStatus     = 0x07,
        // ReportSlaveId           = 0x11,
        // MaskWriteRegister       = 0x16,
        // WriteAndReadRegisters   = 0x17
    }
}

enum_from_primitive! {
#[derive(Debug, PartialEq)]
/// Modbus exception codes returned from the server.
pub enum ExceptionCode {
    IllegalFunction         = 0x01,
    IllegalDataAddress      = 0x02,
    IllegalDataValue        = 0x03,
    SlaveOrServerFailure    = 0x04,
    Acknowledge             = 0x05,
    SlaveOrServerBusy       = 0x06,
    NegativeAcknowledge     = 0x07,
    MemoryParity            = 0x08,
    NotDefined              = 0x09,
    GatewayPath             = 0x0a,
    GatewayTarget           = 0x0b
}
}

/// `InvalidData` reasons
#[derive(Debug)]
pub enum Reason {
    UnexpectedReplySize,
    BytecountNotEven,
    SendBufferEmpty,
    RecvBufferEmpty,
    SendBufferTooBig,
    DecodingError,
    EncodingError,
    InvalidByteorder,
    Custom(String),
}

/// Combination of Modbus, IO and data corruption errors
#[derive(Debug)]
pub enum Error {
    Exception(ExceptionCode),
    Io(io::Error),
    InvalidResponse,
    InvalidData(Reason),
    InvalidFunction,
    ParseCoilError,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        use Error::*;

        match *self {
            Exception(ref code) => write!(f, "modbus exception: {:?}", code),
            Io(ref err) => write!(f, "I/O error: {}", err),
            InvalidResponse => write!(f, "invalid response"),
            InvalidData(ref reason) => write!(f, "invalid data: {:?}", reason),
            InvalidFunction => write!(f, "invalid modbus function"),
            ParseCoilError => write!(f, "parse coil could not be parsed"),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {

        use Error::*;

        match *self {
            Exception(_) => "modbus exception",
            Io(_) => "I/O error",
            InvalidResponse => "invalid response",
            InvalidData(_) => "invalid data",
            InvalidFunction => "invalid modbus function",
            ParseCoilError => "parse coil could not be parsed",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {

        match *self {
            Error::Io(ref err) => Some(err),
            _ => None,
        }
    }
}

impl From<ExceptionCode> for Error {
    fn from(err: ExceptionCode) -> Error {
        Error::Exception(err)
    }
}

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

/// Result type used to nofify success or failure in communication
pub type Result<T> = std::result::Result<T, Error>;

/// Single bit status values, used in read or write coil functions
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Coil {
    On,
    Off,
}

impl Coil {
    fn code(&self) -> u16 {
        match *self {
            Coil::On => 0xff00,
            Coil::Off => 0x0000,
        }
    }
}

impl FromStr for Coil {
    type Err = Error;
    fn from_str(s: &str) -> Result<Coil> {
        if s == "On" {
            Ok(Coil::On)
        } else if s == "Off" {
            Ok(Coil::Off)
        } else {
            Err(Error::ParseCoilError)
        }
    }
}
<|endoftext|>


<commit_before>#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

#![feature(into_cow)]

extern crate oauth_client as oauth;
extern crate rustc_serialize as rustc_serialize;

use std::borrow::{Cow, IntoCow};
use std::collections::HashMap;
use oauth::Token;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};

mod api_twitter_oauth {
    pub const REQUEST_TOKEN: &'static str   = "https://api.twitter.com/oauth/request_token";
    pub const AUTHORIZE: &'static str       = "https://api.twitter.com/oauth/authorize";
    pub const ACCESS_TOKEN: &'static str    = "https://api.twitter.com/oauth/access_token";
}

mod api_twitter_soft {
    pub const UPDATE_STATUS: &'static str = "https://api.twitter.com/1.1/statuses/update.json";
    pub const HOME_TIMELINE: &'static str = "https://api.twitter.com/1.1/statuses/home_timeline.json";
}

fn split_query<'a>(query: &'a str) -> HashMap<Cow<'a, str>, Cow<'a, str>> {
    let mut param = HashMap::new();
    for q in query.split('&') {
        let mut s = q.splitn(2, '=');
        let k = s.next().unwrap();
        let v = s.next().unwrap();
        let _ = param.insert(k.into_cow(), v.into_cow());
    }
    param
}

pub fn get_request_token(consumer: &Token) -> Token<'static> {
    let resp = oauth::get(api_twitter_oauth::REQUEST_TOKEN, consumer, None, None);
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

pub fn get_authorize_url(request: &Token) -> String {
    format!("{}?oauth_token={}", api_twitter_oauth::AUTHORIZE, request.key)
}

pub fn get_access_token(consumer: &Token, request: &Token, pin: &str) -> Token<'static> {
    let mut param = HashMap::new();
    let _ = param.insert("oauth_verifier".into_cow(), pin.into_cow());
    let resp = oauth::get(api_twitter_oauth::ACCESS_TOKEN, consumer, Some(request), Some(&param));
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

/// function to update the status
/// This function takes as arguments the consumer key, the access key, and the status (obviously)
pub fn update_status(consumer: &Token, access: &Token, status: &str) {
    let mut param = HashMap::new();
    let _ = param.insert("status".into_cow(), status.into_cow());
    let _ = oauth::post(api_twitter_soft::UPDATE_STATUS, consumer, Some(access), Some(&param));
}

pub fn get_last_tweets(consumer: &Token, access: &Token) {
    let mut param = HashMap::new();
    println!("{:?}", oauth::get(api_twitter_soft::HOME_TIMELINE, consumer, Some(access), Some(&param)));
}
<commit_msg>src/lib.rs : Tweet is now a struct<commit_after>#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

#![feature(into_cow)]

extern crate oauth_client as oauth;
extern crate rustc_serialize as rustc_serialize;

use std::borrow::{Cow, IntoCow};
use std::collections::HashMap;
use oauth::Token;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};

mod api_twitter_oauth {
    pub const REQUEST_TOKEN: &'static str   = "https://api.twitter.com/oauth/request_token";
    pub const AUTHORIZE: &'static str       = "https://api.twitter.com/oauth/authorize";
    pub const ACCESS_TOKEN: &'static str    = "https://api.twitter.com/oauth/access_token";
}

mod api_twitter_soft {
    pub const UPDATE_STATUS: &'static str = "https://api.twitter.com/1.1/statuses/update.json";
    pub const HOME_TIMELINE: &'static str = "https://api.twitter.com/1.1/statuses/home_timeline.json";
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Tweet {
    pub created_at: String,
    pub text: String
}

impl Tweet {
    pub fn parse_timeline(json_string: String) -> Option<Tweet> {
        let conf = Json::from_str(&json_string).unwrap();
        let d = Decodable::decode(&mut json::Decoder::new(conf));
        println!("{:?}", d);
        d.ok()
    }
}

fn split_query<'a>(query: &'a str) -> HashMap<Cow<'a, str>, Cow<'a, str>> {
    let mut param = HashMap::new();
    for q in query.split('&') {
        let mut s = q.splitn(2, '=');
        let k = s.next().unwrap();
        let v = s.next().unwrap();
        let _ = param.insert(k.into_cow(), v.into_cow());
    }
    param
}

pub fn get_request_token(consumer: &Token) -> Token<'static> {
    let resp = oauth::get(api_twitter_oauth::REQUEST_TOKEN, consumer, None, None);
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

pub fn get_authorize_url(request: &Token) -> String {
    format!("{}?oauth_token={}", api_twitter_oauth::AUTHORIZE, request.key)
}

pub fn get_access_token(consumer: &Token, request: &Token, pin: &str) -> Token<'static> {
    let mut param = HashMap::new();
    let _ = param.insert("oauth_verifier".into_cow(), pin.into_cow());
    let resp = oauth::get(api_twitter_oauth::ACCESS_TOKEN, consumer, Some(request), Some(&param));
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

/// function to update the status
/// This function takes as arguments the consumer key, the access key, and the status (obviously)
pub fn update_status(consumer: &Token, access: &Token, status: &str) {
    let mut param = HashMap::new();
    let _ = param.insert("status".into_cow(), status.into_cow());
    let _ = oauth::post(api_twitter_soft::UPDATE_STATUS, consumer, Some(access), Some(&param));
}

pub fn get_last_tweets(consumer: &Token, access: &Token) {
    let mut param = HashMap::new();
    println!("{:?}", oauth::get(api_twitter_soft::HOME_TIMELINE, consumer, Some(access), Some(&param)));
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate window;
extern crate shader_version;
extern crate input;
extern crate gl;
extern crate current;

// External crates.
use std::mem::transmute;
use window::{
    Window,
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    CaptureCursor, DrawSize, Title, ExitOnEsc
};
use input::{ keyboard, mouse, InputEvent };
use shader_version::opengl::OpenGL;
use current::{ Get, Modifier, Set };

/// A widow implemented by SDL2 back-end.
pub struct Sdl2Window {
    /// SDL window handle
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
    mouse_relative: Option<(f64, f64)>,
    exit_on_esc: bool,
}

#[test]
fn test_sdl2_window() {
    fn foo<T: Window>() {}

    foo::<Sdl2Window>();
}

impl Sdl2Window {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> Sdl2Window {
        sdl2::init(sdl2::INIT_EVERYTHING);
        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, major);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, minor);
        sdl2::video::gl_set_attribute(
            sdl2::video::GLContextProfileMask,
            sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int
        );
        if settings.samples != 0 {
            sdl2::video::gl_set_attribute(sdl2::video::GLMultiSampleBuffers, 1);
            sdl2::video::gl_set_attribute(
                sdl2::video::GLMultiSampleSamples,
                settings.samples as int
            );
        }

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OPENGL| sdl2::video::RESIZABLE
        ).unwrap();
        if settings.fullscreen {
            window.set_fullscreen(sdl2::video::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        Sdl2Window {
            exit_on_esc: settings.exit_on_esc,
            should_close: false,
            last_pressed_key: None,
            window: window,
            context: context,
            mouse_relative: None,
        }
    }
}

impl Drop for Sdl2Window {
    fn drop(&mut self) {
        self.set_mut(CaptureCursor(false));
    }
}

impl Get<ShouldClose> for Sdl2Window {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.should_close)
    }
}

impl Get<Size> for Sdl2Window {
    fn get(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size([w as u32, h as u32])
    }
}

impl SwapBuffers for Sdl2Window {
    fn swap_buffers(&mut self) {
        self.window.gl_swap_window();
    }
}

impl PollEvent<InputEvent> for Sdl2Window {
    fn poll_event(&mut self) -> Option<InputEvent> {
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(input::Move(input::MouseRelative(x, y)));
            }
            None => {}
        }
        match sdl2::event::poll_event() {
            sdl2::event::Quit_) => { self.should_close = true; }
            sdl2::event::TextInput(_, _, text) => { return Some(input::Text(text)); }
            sdl2::event::KeyDown(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return self.poll_event(),
                    _ => {}
                };
                self.last_pressed_key = Some(key);

                if self.exit_on_esc
                && key == sdl2::keycode::KeyCode::Escape {
                    self.should_close = true;
                } else {
                    return Some(input::Press(input::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::KeyUp(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return Some(input::Release(input::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::MouseButtonDownEvent(_, _, _, button, _, _) => {
                return Some(input::Press(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseButtonUp(_, _, _, button, _, _) => {
                return Some(input::Release(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseMotion(_, _, _, _, x, y, dx, dy) => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(input::Move(input::MouseCursor(x as f64, y as f64)));
            },
            sdl2::event::MouseWheel(_, _, _, x, y) => {
                return Some(input::Move(input::MouseScroll(x as f64, y as f64)));
            }
            sdl2::event::Window(_, _, sdl2::event::WindowEventId::Resized, w, h) => {
                return Some(input::Resize(w as u32, h as u32));
            }
            sdl2::event::Window(_, _, sdl2::event::WindowEventId::FocusGained, _, _) => {
                return Some(input::Focus(true));
            }
            sdl2::event::Window(_, _, sdl2::event::WindowEventId::FocusLost, _, _) => {
                return Some(input::Focus(false));
            }
            _ => {}
        }
        None
    }
}

impl Modifier<Sdl2Window> for CaptureCursor {
    fn modify(self, _window: &mut Sdl2Window) {
        let CaptureCursor(enabled) = self;
        sdl2::mouse::set_relative_mouse_mode(enabled)
    }
}

impl Modifier<Sdl2Window> for ShouldClose {
    fn modify(self, window: &mut Sdl2Window) {
        let ShouldClose(val) = self;
        window.should_close = val;
    }
}

impl Get<DrawSize> for Sdl2Window {
    fn get(&self) -> DrawSize {
        let (w, h) = self.window.get_drawable_size();
        DrawSize([w as u32, h as u32])
    }
}

impl Get<Title> for Sdl2Window {
    fn get(&self) -> Title {
        Title(self.window.get_title())
    }
}

impl Modifier<Sdl2Window> for Title {
    fn modify(self, window: &mut Sdl2Window) {
        let Title(val) = self;
        window.window.set_title(val.as_slice());
    }
}

impl Get<ExitOnEsc> for Sdl2Window {
    fn get(&self) -> ExitOnEsc {
        ExitOnEsc(self.exit_on_esc)
    }
}

impl Modifier<Sdl2Window> for ExitOnEsc {
    fn modify(self, window: &mut Sdl2Window) {
        let ExitOnEsc(val) = self;
        window.exit_on_esc = val;
    }
}

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode as u64).unwrap()
}

/// Maps a SDL2 mouse button to piston-input button.
pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::Mouse::LeftMouse => mouse::Left,
        sdl2::mouse::Mouse::RightMouse => mouse::Right,
        sdl2::mouse::Mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::Mouse::X1Mouse => mouse::X1,
        sdl2::mouse::Mouse::X2Mouse => mouse::X2,
        sdl2::mouse::Mouse::UnknownMouse(_) => mouse::Unknown,
    }
}
<commit_msg>First attempt at fully namespacing enums<commit_after>#![deny(missing_docs)]

//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate window;
extern crate shader_version;
extern crate input;
extern crate gl;
extern crate current;

// External crates.
use std::mem::transmute;
use window::{
    Window,
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    CaptureCursor, DrawSize, Title, ExitOnEsc
};
use input::{ keyboard, mouse, InputEvent };
use shader_version::opengl::OpenGL;
use current::{ Get, Modifier, Set };

/// A widow implemented by SDL2 back-end.
pub struct Sdl2Window {
    /// SDL window handle
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
    mouse_relative: Option<(f64, f64)>,
    exit_on_esc: bool,
}

#[test]
fn test_sdl2_window() {
    fn foo<T: Window>() {}

    foo::<Sdl2Window>();
}

impl Sdl2Window {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> Sdl2Window {
        sdl2::init(sdl2::INIT_EVERYTHING);
        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, major);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, minor);
        sdl2::video::gl_set_attribute(
            sdl2::video::GLContextProfileMask,
            sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int
        );
        if settings.samples != 0 {
            sdl2::video::gl_set_attribute(sdl2::video::GLMultiSampleBuffers, 1);
            sdl2::video::gl_set_attribute(
                sdl2::video::GLMultiSampleSamples,
                settings.samples as int
            );
        }

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OPENGL| sdl2::video::RESIZABLE
        ).unwrap();
        if settings.fullscreen {
            window.set_fullscreen(sdl2::video::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        Sdl2Window {
            exit_on_esc: settings.exit_on_esc,
            should_close: false,
            last_pressed_key: None,
            window: window,
            context: context,
            mouse_relative: None,
        }
    }
}

impl Drop for Sdl2Window {
    fn drop(&mut self) {
        self.set_mut(CaptureCursor(false));
    }
}

impl Get<ShouldClose> for Sdl2Window {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.should_close)
    }
}

impl Get<Size> for Sdl2Window {
    fn get(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size([w as u32, h as u32])
    }
}

impl SwapBuffers for Sdl2Window {
    fn swap_buffers(&mut self) {
        self.window.gl_swap_window();
    }
}

impl PollEvent<InputEvent> for Sdl2Window {
    fn poll_event(&mut self) -> Option<InputEvent> {
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(input::Move(input::MouseRelative(x, y)));
            }
            None => {}
        }
        match sdl2::event::poll_event() {
            sdl2::event::Event::Quit_) => { self.should_close = true; }
            sdl2::event::Event::TextInput(_, _, text) => { return Some(input::Text(text)); }
            sdl2::event::Event::KeyDown(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return self.poll_event(),
                    _ => {}
                };
                self.last_pressed_key = Some(key);

                if self.exit_on_esc
                && key == sdl2::keycode::KeyCode::Escape {
                    self.should_close = true;
                } else {
                    return Some(input::Press(input::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::Event::KeyUp(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return Some(input::Release(input::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::Event::MouseButtonDown(_, _, _, button, _, _) => {
                return Some(input::Press(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::Event::MouseButtonUp(_, _, _, button, _, _) => {
                return Some(input::Release(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::Event::MouseMotion(_, _, _, _, x, y, dx, dy) => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(input::Move(input::MouseCursor(x as f64, y as f64)));
            },
            sdl2::event::Event::MouseWheel(_, _, _, x, y) => {
                return Some(input::Move(input::MouseScroll(x as f64, y as f64)));
            }
            sdl2::event::Event::Window(_, _, sdl2::event::WindowEventId::Resized, w, h) => {
                return Some(input::Resize(w as u32, h as u32));
            }
            sdl2::event::Event::Window(_, _, sdl2::event::WindowEventId::FocusGained, _, _) => {
                return Some(input::Focus(true));
            }
            sdl2::event::Event::Window(_, _, sdl2::event::Event::WindowEventId::FocusLost, _, _) => {
                return Some(input::Focus(false));
            }
            _ => {}
        }
        None
    }
}

impl Modifier<Sdl2Window> for CaptureCursor {
    fn modify(self, _window: &mut Sdl2Window) {
        let CaptureCursor(enabled) = self;
        sdl2::mouse::set_relative_mouse_mode(enabled)
    }
}

impl Modifier<Sdl2Window> for ShouldClose {
    fn modify(self, window: &mut Sdl2Window) {
        let ShouldClose(val) = self;
        window.should_close = val;
    }
}

impl Get<DrawSize> for Sdl2Window {
    fn get(&self) -> DrawSize {
        let (w, h) = self.window.get_drawable_size();
        DrawSize([w as u32, h as u32])
    }
}

impl Get<Title> for Sdl2Window {
    fn get(&self) -> Title {
        Title(self.window.get_title())
    }
}

impl Modifier<Sdl2Window> for Title {
    fn modify(self, window: &mut Sdl2Window) {
        let Title(val) = self;
        window.window.set_title(val.as_slice());
    }
}

impl Get<ExitOnEsc> for Sdl2Window {
    fn get(&self) -> ExitOnEsc {
        ExitOnEsc(self.exit_on_esc)
    }
}

impl Modifier<Sdl2Window> for ExitOnEsc {
    fn modify(self, window: &mut Sdl2Window) {
        let ExitOnEsc(val) = self;
        window.exit_on_esc = val;
    }
}

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode as u64).unwrap()
}

/// Maps a SDL2 mouse button to piston-input button.
pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::Mouse::LeftMouse => mouse::Left,
        sdl2::mouse::Mouse::RightMouse => mouse::Right,
        sdl2::mouse::Mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::Mouse::X1Mouse => mouse::X1,
        sdl2::mouse::Mouse::X2Mouse => mouse::X2,
        sdl2::mouse::Mouse::UnknownMouse(_) => mouse::Unknown,
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://hyperium.github.io/hyper/")]
#![deny(missing_docs)]
#![deny(warnings)]
#![deny(missing_debug_implementations)]
#![cfg_attr(all(test, feature = "nightly"), feature(test))]

//! # Hyper
//!
//! Hyper is a fast, modern HTTP implementation written in and for Rust. It
//! is a low-level typesafe abstraction over raw HTTP, providing an elegant
//! layer over "stringly-typed" HTTP.
//!
//! Hyper provides both a [Client](client/index.html) and a
//! [Server](server/index.html), along with a
//! [typed Headers system](header/index.html).

extern crate bytes;
#[macro_use] extern crate futures;
extern crate futures_cpupool;
extern crate httparse;
extern crate language_tags;
#[macro_use] extern crate log;
pub extern crate mime;
extern crate base64;
extern crate time;
extern crate tokio_core as tokio;
#[macro_use] extern crate tokio_io;
extern crate tokio_proto;
extern crate tokio_service;
extern crate unicase;
#[macro_use] extern crate url;

#[cfg(all(test, feature = "nightly"))]
extern crate test;

pub use uri::Uri;
pub use client::Client;
pub use error::{Result, Error};
pub use header::Headers;
pub use http::{Body, Chunk};
pub use http::request::Request;
pub use http::response::Response;
pub use method::Method::{self, Get, Head, Post, Put, Delete};
pub use status::StatusCode::{self, Ok, BadRequest, NotFound};
pub use server::Server;
pub use version::HttpVersion;

#[cfg(test)]
mod mock;
pub mod client;
pub mod error;
mod method;
pub mod header;
mod http;
pub mod server;
pub mod status;
mod uri;
mod version;
<commit_msg>docs(guides): add a link to guides in doc homepage<commit_after>#![doc(html_root_url = "https://hyperium.github.io/hyper/")]
#![deny(missing_docs)]
#![deny(warnings)]
#![deny(missing_debug_implementations)]
#![cfg_attr(all(test, feature = "nightly"), feature(test))]

//! # Hyper
//!
//! Hyper is a fast, modern HTTP implementation written in and for Rust. It
//! is a low-level typesafe abstraction over raw HTTP, providing an elegant
//! layer over "stringly-typed" HTTP.
//!
//! Hyper provides both a [Client](client/index.html) and a
//! [Server](server/index.html), along with a
//! [typed Headers system](header/index.html).
//!
//! If just starting out, **check out the [Guides](https://hyper.rs/guides)
//! first.**

extern crate bytes;
#[macro_use] extern crate futures;
extern crate futures_cpupool;
extern crate httparse;
extern crate language_tags;
#[macro_use] extern crate log;
pub extern crate mime;
extern crate base64;
extern crate time;
extern crate tokio_core as tokio;
#[macro_use] extern crate tokio_io;
extern crate tokio_proto;
extern crate tokio_service;
extern crate unicase;
#[macro_use] extern crate url;

#[cfg(all(test, feature = "nightly"))]
extern crate test;

pub use uri::Uri;
pub use client::Client;
pub use error::{Result, Error};
pub use header::Headers;
pub use http::{Body, Chunk};
pub use http::request::Request;
pub use http::response::Response;
pub use method::Method::{self, Get, Head, Post, Put, Delete};
pub use status::StatusCode::{self, Ok, BadRequest, NotFound};
pub use server::Server;
pub use version::HttpVersion;

#[cfg(test)]
mod mock;
pub mod client;
pub mod error;
mod method;
pub mod header;
mod http;
pub mod server;
pub mod status;
mod uri;
mod version;
<|endoftext|>


<commit_before>extern crate chrono;
#[macro_use] extern crate log;
extern crate rusqlite;

use rusqlite::Connection;
use rusqlite::types::{ToSql, ToSqlOutput};
use std::fmt;
use std::path::{Path, PathBuf};

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    Sqlite(rusqlite::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Sqlite(e) => write!(f, "SQLite error: {}", e),
            Error::Io(e) => write!(f, "I/O error: {}", e),
        }
    }
}

impl std::error::Error for Error {}

impl From<rusqlite::Error> for Error {
    fn from(e: rusqlite::Error) -> Error {
        Error::Sqlite(e)
    }
}

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

#[derive(Debug, PartialEq, Eq)]
pub struct RollingHash(u32);

impl ToSql for RollingHash {
    fn to_sql(&self) -> Result<ToSqlOutput, rusqlite::Error> {
        unimplemented!()
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct SecureHash([u8; 20]);

impl ToSql for SecureHash {
    fn to_sql(&self) -> Result<ToSqlOutput, rusqlite::Error> {
        unimplemented!()
    }
}

const SCHEMA: &'static str = "
    CREATE TABLE version(
        name VARCHAR(8) NOT NULL,
        version VARCHAR(16) NOT NULL
    );
    INSERT INTO version(name, version) VALUES('rs-sync', '0.1');

    CREATE TABLE files(
        file_id INTEGER NOT NULL PRIMARY KEY,
        name VARCHAR(512) NOT NULL,
        modified DATETIME NOT NULL
    );
    CREATE INDEX idx_files_name ON files(name);

    CREATE TABLE blocks(
        rolling_hash VARCHAR(8) NOT NULL,
        secure_hash VARCHAR(40) NOT NULL,
        file_id INTEGER NOT NULL,
        offset INTEGER NOT NULL,
        PRIMARY KEY(file_id, offset)
    );
    CREATE INDEX idx_blocks_rolling_hash ON blocks(rolling_hash);
    CREATE INDEX idx_blocks_file ON blocks(file_id);
    CREATE INDEX idx_blocks_file_offset ON blocks(file_id, offset);
";

pub struct Index {
    db: Connection,
}

impl Index {
    pub fn open(filename: &Path) -> Result<Index, Error> {
        let exists = filename.exists();
        let db = Connection::open(filename)?;
        if !exists {
            warn!("Database doesn't exist, creating tables...");
            db.execute_batch(SCHEMA)?;
        }
        Ok(Index { db })
    }

    pub fn add_file(
        &mut self,
        name: &Path,
        modified: chrono::NaiveDateTime,
    ) -> Result<u32, Error>
    {
        let modified = modified.format("%Y-%m-%d %H:%M:%S").to_string();
        let mut stmt = self.db.prepare(
            "
            SELECT file_id FROM files
            WHERE name = ?;
            ",
        )?;
        let mut rows = stmt.query(&[name.to_str().expect("encoding")])?;
        if let Some(row) = rows.next() {
            let file_id: u32 = row?.get(0);
            self.db.execute(
                "
                UPDATE files SET modified = ? WHERE file_id = ?;
                ",
                &[&file_id as &dyn ToSql, &modified],
            )?;
            Ok(file_id)
        } else {
            self.db.execute(
                "
                INSERT INTO files(name, modified)
                VALUES(?, ?);
                ",
                &[name.to_str().expect("encoding"), &modified],
            )?;
            let file_id = self.db.last_insert_rowid();
            Ok(file_id as u32)
        }
    }

    pub fn remove_file(
        &mut self,
        name: &Path,
    ) -> Result<(), Error>
    {
        self.db.execute(
            "
            DELETE FROM blocks WHERE file_id = (
                SELECT file_id FROM files
                WHERE name = ?
            );
            ",
            &[name.to_str().expect("encoding")],
        )?;
        self.db.execute(
            "
            DELETE FROM files WHERE name = ?;
            ",
            &[name.to_str().expect("encoding")],
        )?;
        Ok(())
    }

    pub fn add_block(
        &mut self,
        rolling_hash: RollingHash,
        secure_hash: SecureHash,
        file_id: u32,
        offset: usize,
    ) -> Result<(), Error>
    {
        self.db.execute(
            "
            INSERT INTO blocks(rolling_hash, secure_hash, file_id, offset)
            VALUES(?, ?, ?, ?);
            ",
            &[&rolling_hash as &dyn ToSql, &secure_hash, &file_id, &(offset as i64)],
        )?;
        Ok(())
    }

    pub fn get_block(
        &self,
        rolling_hash: RollingHash,
        secure_hash: SecureHash,
    ) -> Result<Option<(PathBuf, usize)>, Error>
    {
        let mut stmt = self.db.prepare(
            "
            SELECT blocks.file_id, blocks.offset
            FROM blocks
            INNER JOIN files ON blocks.file_id = files.file_id
            WHERE blocks.rolling_hash = ? AND blocks.secure_hash = ?;
            ",
        )?;
        let mut rows = stmt.query(&[
            &rolling_hash as &dyn ToSql,
            &secure_hash,
        ])?;
        if let Some(row) = rows.next() {
            let row = row?;
            let path: String = row.get(0);
            let path: PathBuf = path.into();
            let offset: i64 = row.get(1);
            let offset = offset as usize;
            Ok(Some((path, offset)))
        } else {
            Ok(None)
        }
    }
}
<commit_msg>Use a single hash<commit_after>extern crate chrono;
#[macro_use] extern crate log;
extern crate rusqlite;

use rusqlite::Connection;
use rusqlite::types::{ToSql, ToSqlOutput};
use std::fmt;
use std::path::{Path, PathBuf};

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    Sqlite(rusqlite::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Sqlite(e) => write!(f, "SQLite error: {}", e),
            Error::Io(e) => write!(f, "I/O error: {}", e),
        }
    }
}

impl std::error::Error for Error {}

impl From<rusqlite::Error> for Error {
    fn from(e: rusqlite::Error) -> Error {
        Error::Sqlite(e)
    }
}

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

#[derive(Debug, PartialEq, Eq)]
pub struct HashDigest([u8; 20]);

impl ToSql for HashDigest {
    fn to_sql(&self) -> Result<ToSqlOutput, rusqlite::Error> {
        unimplemented!()
    }
}

const SCHEMA: &'static str = "
    CREATE TABLE version(
        name VARCHAR(8) NOT NULL,
        version VARCHAR(16) NOT NULL
    );
    INSERT INTO version(name, version) VALUES('rs-sync', '0.1');

    CREATE TABLE files(
        file_id INTEGER NOT NULL PRIMARY KEY,
        name VARCHAR(512) NOT NULL,
        modified DATETIME NOT NULL
    );
    CREATE INDEX idx_files_name ON files(name);

    CREATE TABLE blocks(
        hash VARCHAR(40) NOT NULL,
        file_id INTEGER NOT NULL,
        offset INTEGER NOT NULL,
        PRIMARY KEY(file_id, offset)
    );
    CREATE INDEX idx_blocks_hash ON blocks(hash);
    CREATE INDEX idx_blocks_file ON blocks(file_id);
    CREATE INDEX idx_blocks_file_offset ON blocks(file_id, offset);
";

pub struct Index {
    db: Connection,
}

impl Index {
    pub fn open(filename: &Path) -> Result<Index, Error> {
        let exists = filename.exists();
        let db = Connection::open(filename)?;
        if !exists {
            warn!("Database doesn't exist, creating tables...");
            db.execute_batch(SCHEMA)?;
        }
        Ok(Index { db })
    }

    pub fn add_file(
        &mut self,
        name: &Path,
        modified: chrono::NaiveDateTime,
    ) -> Result<u32, Error>
    {
        let modified = modified.format("%Y-%m-%d %H:%M:%S").to_string();
        let mut stmt = self.db.prepare(
            "
            SELECT file_id FROM files
            WHERE name = ?;
            ",
        )?;
        let mut rows = stmt.query(&[name.to_str().expect("encoding")])?;
        if let Some(row) = rows.next() {
            let file_id: u32 = row?.get(0);
            self.db.execute(
                "
                UPDATE files SET modified = ? WHERE file_id = ?;
                ",
                &[&file_id as &dyn ToSql, &modified],
            )?;
            Ok(file_id)
        } else {
            self.db.execute(
                "
                INSERT INTO files(name, modified)
                VALUES(?, ?);
                ",
                &[name.to_str().expect("encoding"), &modified],
            )?;
            let file_id = self.db.last_insert_rowid();
            Ok(file_id as u32)
        }
    }

    pub fn remove_file(
        &mut self,
        name: &Path,
    ) -> Result<(), Error>
    {
        self.db.execute(
            "
            DELETE FROM blocks WHERE file_id = (
                SELECT file_id FROM files
                WHERE name = ?
            );
            ",
            &[name.to_str().expect("encoding")],
        )?;
        self.db.execute(
            "
            DELETE FROM files WHERE name = ?;
            ",
            &[name.to_str().expect("encoding")],
        )?;
        Ok(())
    }

    pub fn add_block(
        &mut self,
        hash: HashDigest,
        file_id: u32,
        offset: usize,
    ) -> Result<(), Error>
    {
        self.db.execute(
            "
            INSERT INTO blocks(hash, file_id, offset)
            VALUES(?, ?, ?);
            ",
            &[&hash as &dyn ToSql, &file_id, &(offset as i64)],
        )?;
        Ok(())
    }

    pub fn get_block(
        &self,
        hash: HashDigest,
    ) -> Result<Option<(PathBuf, usize)>, Error>
    {
        let mut stmt = self.db.prepare(
            "
            SELECT blocks.file_id, blocks.offset
            FROM blocks
            INNER JOIN files ON blocks.file_id = files.file_id
            WHERE blocks.hash = ?;
            ",
        )?;
        let mut rows = stmt.query(&[&hash as &dyn ToSql])?;
        if let Some(row) = rows.next() {
            let row = row?;
            let path: String = row.get(0);
            let path: PathBuf = path.into();
            let offset: i64 = row.get(1);
            let offset = offset as usize;
            Ok(Some((path, offset)))
        } else {
            Ok(None)
        }
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![crate_type = "lib"]
#[allow(dead_code)]

extern crate ip;

use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ip::IpAddr;

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    pub fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network {
            addr: addr,
            prefix: prefix,
        }
    }

    pub fn from_cidr(cidr: &str) -> Result<Ipv4Network, String> {
        let (addr_str, prefix_str) = try!(cidr_parts(cidr));
        let addr = try!(Self::parse_addr(addr_str));
        let prefix = try!(parse_prefix(prefix_str, 32));
        Ok(Self::new(addr, prefix))
    }

    pub fn ip(&self) -> Ipv4Addr {
        self.addr
    }

    pub fn prefix(&self) -> u8 {
        self.prefix
    }

    pub fn mask(&self) -> (Ipv4Addr, u32) {
        let prefix = self.prefix;
        let mask = !(0xffffffff >> prefix);
        (Ipv4Addr::from(mask), mask)
    }

    pub fn network(&self) -> (Ipv4Addr, u32) {
        let (_, mask) = self.mask();
        let ip = u32::from(self.addr) & mask;
        (Ipv4Addr::from(ip), ip)
    }

    pub fn broadcast(&self) -> (Ipv4Addr, u32) {
        let (_, network) = self.network();
        let (_, mask) = self.mask();
        let broadcast = network | !mask;
        (Ipv4Addr::from(broadcast), broadcast)
    }

    pub fn contains(&self, ip: Ipv4Addr) -> bool {
        let (_, net) = self.network();
        (u32::from(ip) & net) == net
    }

    fn parse_addr(addr: &str) -> Result<Ipv4Addr, String> {
        let byte_strs = addr.split('.')
                            .map(|b| b.parse::<u8>())
                            .map(|b| b.map_err(|_| format!("Invalid IPv4: {}", addr)));
        let mut bytes = [0; 4];
        for (i, byte) in byte_strs.enumerate() {
            if i >= 4 {
                return Err(format!("Malformed IP: {}", addr));
            }
            bytes[i] = try!(byte);
        }
        Ok(Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]))
    }
}

impl Ipv6Network {
    pub fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network {
            addr: addr,
            prefix: prefix,
        }
    }

    pub fn from_cidr(cidr: &str) -> Result<Ipv6Network, String> {
        let (addr_str, prefix_str) = try!(cidr_parts(cidr));
        let addr = try!(Self::parse_addr(addr_str));
        let prefix = try!(parse_prefix(prefix_str, 128));
        Ok(Self::new(addr, prefix))
    }

    pub fn ip(&self) -> Ipv6Addr {
        self.addr
    }

    pub fn prefix(&self) -> u8 {
        self.prefix
    }

    fn parse_addr(addr: &str) -> Result<Ipv6Addr, String> {
        Ipv6Addr::from_str(addr).map_err(|e| format!("{}", e))
    }
}

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

fn cidr_parts<'a>(cidr: &'a str) -> Result<(&'a str, &'a str), String> {
    let parts = cidr.split('/').collect::<Vec<&str>>();
    if parts.len() == 2 {
        Ok((parts[0], parts[1]))
    } else {
        Err(format!("Malformed cidr: {}", cidr))
    }
}

fn parse_prefix(prefix: &str, max: u8) -> Result<u8, String> {
    let mask = try!(prefix.parse::<u8>().map_err(|_| format!("Prefix is NaN")));
    if mask > max {
        Err(format!("Prefix must be <= {}", max))
    } else {
        Ok(mask)
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn parse_v4() {
        let cidr = Ipv4Network::from_cidr("0/0").unwrap();
        assert_eq!(cidr.ip(), Ipv4Addr::new(0, 0, 0, 0));
        assert_eq!(cidr.prefix(), 0);
    }

    #[test]
    fn parse_v4_2() {
        let cidr = Ipv4Network::from_cidr("127.1.0.0/24").unwrap();
        assert_eq!(cidr.ip(), Ipv4Addr::new(127, 1, 0, 0));
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn parse_v4_fail_addr() {
        let cidr = Ipv4Network::from_cidr("10.a.b/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v4_fail_addr2() {
        let cidr = Ipv4Network::from_cidr("10.1.1.1.0/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v4_fail_addr3() {
        let cidr = Ipv4Network::from_cidr("256/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v4_fail_prefix() {
        let cidr = Ipv4Network::from_cidr("0/39");
        assert!(cidr.is_err());
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn parse_v6() {
        let cidr = Ipv6Network::from_cidr("::1/0").unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
        assert_eq!(cidr.prefix(), 0);
    }

    #[test]
    fn parse_v6_2() {
        let cidr = Ipv6Network::from_cidr("FF01:0:0:17:0:0:0:2/64").unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2));
        assert_eq!(cidr.prefix(), 64);
    }

    #[test]
    fn parse_v6_fail_addr() {
        let cidr = Ipv6Network::from_cidr("2001::1::/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v6_fail_prefix() {
        let cidr = Ipv6Network::from_cidr("::1/129");
        assert!(cidr.is_err());
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        let (ip, int) = cidr.mask();
        assert_eq!(ip, Ipv4Addr::new(255, 255, 255, 248));
        assert_eq!(int, 4294967288);
    }

    #[test]
    fn network_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(10, 10, 1, 97), 23);
        let (ip, int) = cidr.network();
        assert_eq!(ip, Ipv4Addr::new(10, 10, 0, 0));
        assert_eq!(int, 168427520);
    }

    #[test]
    fn broadcast_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(10, 10, 1, 97), 23);
        let (ip, int) = cidr.broadcast();
        assert_eq!(ip, Ipv4Addr::new(10, 10, 1, 255));
        assert_eq!(int, 168428031);
    }

    #[test]
    fn contains_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        let ip = Ipv4Addr::new(74, 125, 227, 4);
        assert!(cidr.contains(ip));
    }
}
<commit_msg>Add check that IP in CIDR is network<commit_after>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![crate_type = "lib"]
#[allow(dead_code)]

extern crate ip;

use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ip::IpAddr;

const IPV4_BITS: u8 = 32;
const IPV6_BITS: u8 = 128;

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    pub fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network {
            addr: addr,
            prefix: prefix,
        }
    }

    pub fn from_cidr(cidr: &str) -> Result<Ipv4Network, String> {
        let (addr_str, prefix_str) = try!(cidr_parts(cidr));
        let addr = try!(Self::parse_addr(addr_str));
        let prefix = try!(parse_prefix(prefix_str, IPV4_BITS));
        let new = Self::new(addr, prefix);
        let (net, _) = new.network();
        if addr != net {
            Err(format!("IP must have zeroes in host part"))
        } else {
            Ok(new)
        }
    }

    pub fn ip(&self) -> Ipv4Addr {
        self.addr
    }

    pub fn prefix(&self) -> u8 {
        self.prefix
    }

    pub fn mask(&self) -> (Ipv4Addr, u32) {
        let prefix = self.prefix;
        let mask = !(0xffffffff >> prefix);
        (Ipv4Addr::from(mask), mask)
    }

    pub fn network(&self) -> (Ipv4Addr, u32) {
        let (_, mask) = self.mask();
        let ip = u32::from(self.addr) & mask;
        (Ipv4Addr::from(ip), ip)
    }

    pub fn broadcast(&self) -> (Ipv4Addr, u32) {
        let (_, network) = self.network();
        let (_, mask) = self.mask();
        let broadcast = network | !mask;
        (Ipv4Addr::from(broadcast), broadcast)
    }

    pub fn contains(&self, ip: Ipv4Addr) -> bool {
        let (_, net) = self.network();
        (u32::from(ip) & net) == net
    }

    fn parse_addr(addr: &str) -> Result<Ipv4Addr, String> {
        let byte_strs = addr.split('.')
                            .map(|b| b.parse::<u8>())
                            .map(|b| b.map_err(|_| format!("Invalid IPv4: {}", addr)));
        let mut bytes = [0; 4];
        for (i, byte) in byte_strs.enumerate() {
            if i >= 4 {
                return Err(format!("Malformed IP: {}", addr));
            }
            bytes[i] = try!(byte);
        }
        Ok(Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]))
    }
}

impl Ipv6Network {
    pub fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network {
            addr: addr,
            prefix: prefix,
        }
    }

    pub fn from_cidr(cidr: &str) -> Result<Ipv6Network, String> {
        let (addr_str, prefix_str) = try!(cidr_parts(cidr));
        let addr = try!(Self::parse_addr(addr_str));
        let prefix = try!(parse_prefix(prefix_str, IPV6_BITS));
        Ok(Self::new(addr, prefix))
    }

    pub fn ip(&self) -> Ipv6Addr {
        self.addr
    }

    pub fn prefix(&self) -> u8 {
        self.prefix
    }

    fn parse_addr(addr: &str) -> Result<Ipv6Addr, String> {
        Ipv6Addr::from_str(addr).map_err(|e| format!("{}", e))
    }
}

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

fn cidr_parts<'a>(cidr: &'a str) -> Result<(&'a str, &'a str), String> {
    let parts = cidr.split('/').collect::<Vec<&str>>();
    if parts.len() == 2 {
        Ok((parts[0], parts[1]))
    } else {
        Err(format!("Malformed cidr: {}", cidr))
    }
}

fn parse_prefix(prefix: &str, max: u8) -> Result<u8, String> {
    let mask = try!(prefix.parse::<u8>().map_err(|_| format!("Prefix is NaN")));
    if mask > max {
        Err(format!("Prefix must be <= {}", max))
    } else {
        Ok(mask)
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn parse_v4() {
        let cidr = Ipv4Network::from_cidr("0/0").unwrap();
        assert_eq!(cidr.ip(), Ipv4Addr::new(0, 0, 0, 0));
        assert_eq!(cidr.prefix(), 0);
    }

    #[test]
    fn parse_v4_2() {
        let cidr = Ipv4Network::from_cidr("127.1.0.0/24").unwrap();
        assert_eq!(cidr.ip(), Ipv4Addr::new(127, 1, 0, 0));
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn parse_v4_fail_addr() {
        let cidr = Ipv4Network::from_cidr("10.a.b/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v4_fail_addr2() {
        let cidr = Ipv4Network::from_cidr("10.1.1.1.0/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v4_fail_addr3() {
        let cidr = Ipv4Network::from_cidr("256/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v4_fail_prefix() {
        let cidr = Ipv4Network::from_cidr("0/39");
        assert!(cidr.is_err());
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn parse_v6() {
        let cidr = Ipv6Network::from_cidr("::1/0").unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
        assert_eq!(cidr.prefix(), 0);
    }

    #[test]
    fn parse_v6_2() {
        let cidr = Ipv6Network::from_cidr("FF01:0:0:17:0:0:0:2/64").unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2));
        assert_eq!(cidr.prefix(), 64);
    }

    #[test]
    fn parse_v6_fail_addr() {
        let cidr = Ipv6Network::from_cidr("2001::1::/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v6_fail_prefix() {
        let cidr = Ipv6Network::from_cidr("::1/129");
        assert!(cidr.is_err());
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        let (ip, int) = cidr.mask();
        assert_eq!(ip, Ipv4Addr::new(255, 255, 255, 248));
        assert_eq!(int, 4294967288);
    }

    #[test]
    fn network_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(10, 10, 1, 97), 23);
        let (ip, int) = cidr.network();
        assert_eq!(ip, Ipv4Addr::new(10, 10, 0, 0));
        assert_eq!(int, 168427520);
    }

    #[test]
    fn broadcast_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(10, 10, 1, 97), 23);
        let (ip, int) = cidr.broadcast();
        assert_eq!(ip, Ipv4Addr::new(10, 10, 1, 255));
        assert_eq!(int, 168428031);
    }

    #[test]
    fn contains_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        let ip = Ipv4Addr::new(74, 125, 227, 4);
        assert!(cidr.contains(ip));
    }
}
<|endoftext|>


<commit_before>//! # `derive_more`
//!
//! [![Build Status](https://api.travis-ci.org/JelteF/derive_more.svg?branch=master)](https://travis-ci.org/JelteF/derive_more)
//! [![Latest Version](https://img.shields.io/crates/v/derive_more.svg)](https://crates.io/crates/derive_more)
//! [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://jeltef.github.io/derive_more/derive_more/)
//! [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/JelteF/derive_more/master/LICENSE)
//!
//! Rust has lots of builtin traits that are implemented for its basic types, such
//! as `Add`, `Not`, `From` or `Display`.
//! However, when wrapping these types inside your own structs or enums you lose the
//! implementations of these traits and are required to recreate them.
//! This is especially annoying when your own structures are very simple, such as
//! when using the commonly advised newtype pattern (e.g. `MyInt(i32)`).
//!
//! This library tries to remove these annoyances and the corresponding boilerplate code.
//! It does this by allowing you to derive lots of commonly used traits for both structs and enums.
//!
//! ## Example code
//!
//! By using this library the following code just works:
//!
//! ```rust
//! extern crate derive_more;
//! use derive_more::{Add, Display, From, Into};
//!
//! #[derive(PartialEq, From, Add)]
//! struct MyInt(i32);
//!
//! #[derive(PartialEq, From, Into)]
//! struct Point2D {
//!     x: i32,
//!     y: i32,
//! }
//!
//! #[derive(PartialEq, From, Add, Display)]
//! enum MyEnum {
//!     #[display(fmt = "int: {}", _0)]
//!     Int(i32),
//!     Uint(u32),
//!     #[display(fmt = "nothing")]
//!     Nothing,
//! }
//!
//! assert!(MyInt(11) == MyInt(5) + 6.into());
//! assert!((5, 6) == Point2D { x: 5, y: 6 }.into());
//! assert!(MyEnum::Int(15) == (MyEnum::Int(8) + 7.into()).unwrap());
//! assert!(MyEnum::Int(15).to_string() == "int: 15");
//! assert!(MyEnum::Uint(42).to_string() == "42");
//! assert!(MyEnum::Nothing.to_string() == "nothing");
//! ```
//!
//! ## The derivable traits
//!
//! Below are all the traits that you can derive using this library.
//! Some trait derivations are so similar that the further documentation will only show a single one
//! of them.
//! You can recognize these by the "-like" suffix in their name.
//! The trait name before that will be the only one that is used throughout the further
//! documentation.
//!
//! It is important to understand what code gets generated when using one of the
//! derives from this crate.
//! That is why the links below explain what code gets generated for a trait for
//! each group from before.
//!
//! You can use the [`cargo-expand`] utility to see the exact code that is generated
//! for your specific type.
//! This will show you your code with all macros and derives expanded.
//!
//! **NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't
//! automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]`
//!
//! ### Conversion traits
//!
//! These are traits that are used to convert automatically between types.
//!
//! 1. [`From`]
//! 2. [`Into`]
//! 3. [`FromStr`]
//! 4. [`TryInto`]
//! 5. [`IntoIterator`]
//! 6. [`AsRef`]
//! 7. [`AsMut`]
//!
//! ### Formatting traits
//!
//! These traits are used for converting a struct to a string in different ways.
//!
//! 1. [`Display`-like], contains `Display`, `Binary`, `Octal`, `LowerHex`,
//!    `UpperHex`, `LowerExp`, `UpperExp`, `Pointer`
//!
//! ### Operators
//!
//! These are traits that can be used for operator overloading.
//!
//! 1. [`Index`]
//! 2. [`Deref`]
//! 3. [`Not`-like], contains `Not` and `Neg`
//! 4. [`Add`-like], contains `Add`, `Sub`, `BitAnd`, `BitOr`, `BitXor`, `MulSelf`,
//!    `DivSelf`, `RemSelf`, `ShrSelf` and `ShlSelf`
//! 5. [`Mul`-like], contains `Mul`, `Div`, `Rem`, `Shr` and `Shl`
//! 3. [`Sum`-like], contains `Sum` and `Product`
//! 6. [`IndexMut`]
//! 7. [`DerefMut`]
//! 8. [`AddAssign`-like], contains `AddAssign`, `SubAssign`, `BitAndAssign`,
//!    `BitOrAssign` and `BitXorAssign`
//! 9. [`MulAssign`-like], contains `MulAssign`, `DivAssign`, `RemAssign`,
//!    `ShrAssign` and `ShlAssign`
//!
//! ### Static methods
//!
//! These don't derive traits, but derive static methods instead.
//!
//! 1. [`Constructor`], this derives a `new` method that can be used as a constructor.
//!    This is very basic if you need more customization for your constructor, check
//!    out the [`derive-new`] crate.
//!
//! ## Generated code
//!
//! ## Installation
//!
//! This library requires Rust 1.32 or higher and it supports `no_std` out of the box.
//! Then add the following to `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! derive_more = "0.99.0"
//! # You can specifiy the types of derives that you need for less time spent
//! # compiling. For the full list of features see this crate its Cargo.toml.
//! default-features = false
//! features = ["from", "add", "iterator"]
//! ```
//!
//! And this to the top of your Rust file for Rust 2018:
//!
//! ```rust
//! extern crate derive_more;
//! // use the derives that you want in the file
//! use derive_more::{Add, Display, From};
//! ```
//! If you're still using Rust 2015 you should add this instead:
//! ```rust
//! extern crate core;
//! #[macro_use]
//! extern crate derive_more;
//! ```
//!
//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
//! [`derive-new`]: https://github.com/nrc/derive-new
//!
//! [`From`]: from.html
//! [`Into`]: into.html
//! [`FromStr`]: from_str.html
//! [`TryInto`]: try_into.html
//! [`IntoIterator`]: into_iterator.html
//! [`AsRef`]: as_ref.html
//! [`AsMut`]: as_mut.html
//!
//! [`Display`-like]: display.html
//!
//! [`Index`]: index_op.html
//! [`Deref`]: deref.html
//! [`Not`-like]: not.html
//! [`Add`-like]: add.html
//! [`Mul`-like]: mul.html
//! [`Sum`-like]: sum.html
//! [`IndexMut`]: index_mut.html
//! [`DerefMut`]: deref_mut.html
//! [`AddAssign`-like]: add_assign.html
//! [`MulAssign`-like]: mul_assign.html
//!
//! [`Constructor`]: constructor.html

#![recursion_limit = "128"]

extern crate proc_macro;
use proc_macro2;
use syn;

use proc_macro::TokenStream;
use syn::parse::Error as ParseError;

mod utils;

#[cfg(feature = "add_assign")]
mod add_assign_like;
#[cfg(any(
    feature = "add",
    feature = "add_assign",
    feature = "mul"
))]
mod add_helpers;
#[cfg(any(feature = "add", feature = "mul"))]
mod add_like;
#[cfg(feature = "as_mut")]
mod as_mut;
#[cfg(feature = "as_ref")]
mod as_ref;
#[cfg(feature = "constructor")]
mod constructor;
#[cfg(feature = "deref")]
mod deref;
#[cfg(feature = "deref_mut")]
mod deref_mut;
#[cfg(feature = "display")]
mod display;
#[cfg(feature = "from")]
mod from;
#[cfg(feature = "from_str")]
mod from_str;
#[cfg(feature = "index")]
mod index;
#[cfg(feature = "index_mut")]
mod index_mut;
#[cfg(feature = "into")]
mod into;
#[cfg(feature = "into_iterator")]
mod into_iterator;
#[cfg(feature = "iterator")]
mod iterator;
#[cfg(feature = "mul_assign")]
mod mul_assign_like;
#[cfg(any(feature = "mul", feature = "mul_assign"))]
mod mul_helpers;
#[cfg(feature = "mul")]
mod mul_like;
#[cfg(feature = "not")]
mod not_like;
#[cfg(feature = "display")]
#[allow(ellipsis_inclusive_range_patterns)]
#[allow(clippy::all)]
mod parsing;
#[cfg(feature = "sum")]
mod sum_like;
#[cfg(feature = "try_into")]
mod try_into;

// This trait describes the possible return types of
// the derives. A derive can generally be infallible and
// return a TokenStream, or it can be fallible and return
// a Result<TokenStream, syn::parse::Error>.
trait Output {
    fn process(self) -> TokenStream;
}

impl Output for proc_macro2::TokenStream {
    fn process(self) -> TokenStream {
        self.into()
    }
}

impl Output for Result<proc_macro2::TokenStream, ParseError> {
    fn process(self) -> TokenStream {
        match self {
            Ok(ts) => ts.into(),
            Err(e) => e.to_compile_error().into(),
        }
    }
}

macro_rules! create_derive(
    ($feature:literal, $mod_:ident, $trait_:ident, $fn_name: ident $(,$attribute:ident)* $(,)?) => {
        #[cfg(feature = $feature)]
        #[proc_macro_derive($trait_, attributes($($attribute),*))]
        #[doc(hidden)]
        pub fn $fn_name(input: TokenStream) -> TokenStream {
            let ast = syn::parse(input).unwrap();
            Output::process($mod_::expand(&ast, stringify!($trait_)))
        }
    }
);

create_derive!("from", from, From, from_derive, from);

create_derive!("into", into, Into, into_derive, into);

create_derive!("constructor", constructor, Constructor, constructor_derive);

create_derive!("not", not_like, Not, not_derive);
create_derive!("not", not_like, Neg, neg_derive);

create_derive!("add", add_like, Add, add_derive);
create_derive!("add", add_like, Sub, sub_derive);
create_derive!("add", add_like, BitAnd, bit_and_derive);
create_derive!("add", add_like, BitOr, bit_or_derive);
create_derive!("add", add_like, BitXor, bit_xor_derive);

create_derive!("mul", mul_like, Mul, mul_derive, mul);
create_derive!("mul", mul_like, Div, div_derive, div);
create_derive!("mul", mul_like, Rem, rem_derive, rem);
create_derive!("mul", mul_like, Shr, shr_derive, shr);
create_derive!("mul", mul_like, Shl, shl_derive, shl);

create_derive!(
    "add_assign",
    add_assign_like,
    AddAssign,
    add_assign_derive,
);
create_derive!(
    "add_assign",
    add_assign_like,
    SubAssign,
    sub_assign_derive,
);
create_derive!(
    "add_assign",
    add_assign_like,
    BitAndAssign,
    bit_and_assign_derive,
);
create_derive!(
    "add_assign",
    add_assign_like,
    BitOrAssign,
    bit_or_assign_derive,
);
create_derive!(
    "add_assign",
    add_assign_like,
    BitXorAssign,
    bit_xor_assign_derive,
);

create_derive!(
    "mul_assign",
    mul_assign_like,
    MulAssign,
    mul_assign_derive,
    mul_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    DivAssign,
    div_assign_derive,
    div_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    RemAssign,
    rem_assign_derive,
    rem_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    ShrAssign,
    shr_assign_derive,
    shr_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    ShlAssign,
    shl_assign_derive,
    shl_assign,
);

create_derive!("sum", sum_like, Sum, sum_derive);
create_derive!("sum", sum_like, Product, product_derive);

create_derive!("from_str", from_str, FromStr, from_str_derive);

create_derive!("display", display, Display, display_derive, display);
create_derive!("display", display, Binary, binary_derive, binary);
create_derive!("display", display, Octal, octal_derive, octal);
create_derive!("display", display, LowerHex, lower_hex_derive, lower_hex);
create_derive!("display", display, UpperHex, upper_hex_derive, upper_hex);
create_derive!("display", display, LowerExp, lower_exp_derive, lower_exp);
create_derive!("display", display, UpperExp, upper_exp_derive, upper_exp);
create_derive!("display", display, Pointer, pointer_derive, pointer);
create_derive!("display", display, DebugCustom, debug_custom_derive, debug);

create_derive!("index", index, Index, index_derive, index);
create_derive!(
    "index_mut",
    index_mut,
    IndexMut,
    index_mut_derive,
    index_mut,
);

create_derive!(
    "into_iterator",
    into_iterator,
    IntoIterator,
    into_iterator_derive,
    into_iterator,
);
create_derive!("iterator", iterator, Iterator, iterator_derive, iterator);

create_derive!("try_into", try_into, TryInto, try_into_derive, try_into);

create_derive!("deref", deref, Deref, deref_derive, deref);
create_derive!(
    "deref_mut",
    deref_mut,
    DerefMut,
    deref_mut_derive,
    deref_mut,
);

create_derive!("as_ref", as_ref, AsRef, as_ref_derive, as_ref);
create_derive!("as_mut", as_mut, AsMut, as_mut_derive, as_mut);
<commit_msg>Fix test failures<commit_after>//! # `derive_more`
//!
//! [![Build Status](https://api.travis-ci.org/JelteF/derive_more.svg?branch=master)](https://travis-ci.org/JelteF/derive_more)
//! [![Latest Version](https://img.shields.io/crates/v/derive_more.svg)](https://crates.io/crates/derive_more)
//! [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://jeltef.github.io/derive_more/derive_more/)
//! [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/JelteF/derive_more/master/LICENSE)
//!
//! Rust has lots of builtin traits that are implemented for its basic types, such
//! as `Add`, `Not`, `From` or `Display`.
//! However, when wrapping these types inside your own structs or enums you lose the
//! implementations of these traits and are required to recreate them.
//! This is especially annoying when your own structures are very simple, such as
//! when using the commonly advised newtype pattern (e.g. `MyInt(i32)`).
//!
//! This library tries to remove these annoyances and the corresponding boilerplate code.
//! It does this by allowing you to derive lots of commonly used traits for both structs and enums.
//!
//! ## Example code
//!
//! By using this library the following code just works:
//!
//! ```rust
//! extern crate derive_more;
//! use derive_more::{Add, Display, From, Into};
//!
//! #[derive(PartialEq, From, Add)]
//! struct MyInt(i32);
//!
//! #[derive(PartialEq, From, Into)]
//! struct Point2D {
//!     x: i32,
//!     y: i32,
//! }
//!
//! #[derive(PartialEq, From, Add, Display)]
//! enum MyEnum {
//!     #[display(fmt = "int: {}", _0)]
//!     Int(i32),
//!     Uint(u32),
//!     #[display(fmt = "nothing")]
//!     Nothing,
//! }
//!
//! assert!(MyInt(11) == MyInt(5) + 6.into());
//! assert!((5, 6) == Point2D { x: 5, y: 6 }.into());
//! assert!(MyEnum::Int(15) == (MyEnum::Int(8) + 7.into()).unwrap());
//! assert!(MyEnum::Int(15).to_string() == "int: 15");
//! assert!(MyEnum::Uint(42).to_string() == "42");
//! assert!(MyEnum::Nothing.to_string() == "nothing");
//! ```
//!
//! ## The derivable traits
//!
//! Below are all the traits that you can derive using this library.
//! Some trait derivations are so similar that the further documentation will only show a single one
//! of them.
//! You can recognize these by the "-like" suffix in their name.
//! The trait name before that will be the only one that is used throughout the further
//! documentation.
//!
//! It is important to understand what code gets generated when using one of the
//! derives from this crate.
//! That is why the links below explain what code gets generated for a trait for
//! each group from before.
//!
//! You can use the [`cargo-expand`] utility to see the exact code that is generated
//! for your specific type.
//! This will show you your code with all macros and derives expanded.
//!
//! **NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't
//! automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]`
//!
//! ### Conversion traits
//!
//! These are traits that are used to convert automatically between types.
//!
//! 1. [`From`]
//! 2. [`Into`]
//! 3. [`FromStr`]
//! 4. [`TryInto`]
//! 5. [`IntoIterator`]
//! 6. [`AsRef`]
//! 7. [`AsMut`]
//!
//! ### Formatting traits
//!
//! These traits are used for converting a struct to a string in different ways.
//!
//! 1. [`Display`-like], contains `Display`, `Binary`, `Octal`, `LowerHex`,
//!    `UpperHex`, `LowerExp`, `UpperExp`, `Pointer`
//!
//! ### Operators
//!
//! These are traits that can be used for operator overloading.
//!
//! 1. [`Index`]
//! 2. [`Deref`]
//! 3. [`Not`-like], contains `Not` and `Neg`
//! 4. [`Add`-like], contains `Add`, `Sub`, `BitAnd`, `BitOr`, `BitXor`, `MulSelf`,
//!    `DivSelf`, `RemSelf`, `ShrSelf` and `ShlSelf`
//! 5. [`Mul`-like], contains `Mul`, `Div`, `Rem`, `Shr` and `Shl`
//! 3. [`Sum`-like], contains `Sum` and `Product`
//! 6. [`IndexMut`]
//! 7. [`DerefMut`]
//! 8. [`AddAssign`-like], contains `AddAssign`, `SubAssign`, `BitAndAssign`,
//!    `BitOrAssign` and `BitXorAssign`
//! 9. [`MulAssign`-like], contains `MulAssign`, `DivAssign`, `RemAssign`,
//!    `ShrAssign` and `ShlAssign`
//!
//! ### Static methods
//!
//! These don't derive traits, but derive static methods instead.
//!
//! 1. [`Constructor`], this derives a `new` method that can be used as a constructor.
//!    This is very basic if you need more customization for your constructor, check
//!    out the [`derive-new`] crate.
//!
//! ## Generated code
//!
//! ## Installation
//!
//! This library requires Rust 1.32 or higher and it supports `no_std` out of the box.
//! Then add the following to `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! derive_more = "0.99.0"
//! # You can specifiy the types of derives that you need for less time spent
//! # compiling. For the full list of features see this crate its Cargo.toml.
//! default-features = false
//! features = ["from", "add", "iterator"]
//! ```
//!
//! And this to the top of your Rust file for Rust 2018:
//!
//! ```rust
//! extern crate derive_more;
//! // use the derives that you want in the file
//! use derive_more::{Add, Display, From};
//! ```
//! If you're still using Rust 2015 you should add this instead:
//! ```rust
//! extern crate core;
//! #[macro_use]
//! extern crate derive_more;
//! # fn main(){}
//! ```
//!
//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
//! [`derive-new`]: https://github.com/nrc/derive-new
//!
//! [`From`]: from.html
//! [`Into`]: into.html
//! [`FromStr`]: from_str.html
//! [`TryInto`]: try_into.html
//! [`IntoIterator`]: into_iterator.html
//! [`AsRef`]: as_ref.html
//! [`AsMut`]: as_mut.html
//!
//! [`Display`-like]: display.html
//!
//! [`Index`]: index_op.html
//! [`Deref`]: deref.html
//! [`Not`-like]: not.html
//! [`Add`-like]: add.html
//! [`Mul`-like]: mul.html
//! [`Sum`-like]: sum.html
//! [`IndexMut`]: index_mut.html
//! [`DerefMut`]: deref_mut.html
//! [`AddAssign`-like]: add_assign.html
//! [`MulAssign`-like]: mul_assign.html
//!
//! [`Constructor`]: constructor.html

#![recursion_limit = "128"]

extern crate proc_macro;
use proc_macro2;
use syn;

use proc_macro::TokenStream;
use syn::parse::Error as ParseError;

mod utils;

#[cfg(feature = "add_assign")]
mod add_assign_like;
#[cfg(any(feature = "add", feature = "add_assign", feature = "mul"))]
mod add_helpers;
#[cfg(any(feature = "add", feature = "mul"))]
mod add_like;
#[cfg(feature = "as_mut")]
mod as_mut;
#[cfg(feature = "as_ref")]
mod as_ref;
#[cfg(feature = "constructor")]
mod constructor;
#[cfg(feature = "deref")]
mod deref;
#[cfg(feature = "deref_mut")]
mod deref_mut;
#[cfg(feature = "display")]
mod display;
#[cfg(feature = "from")]
mod from;
#[cfg(feature = "from_str")]
mod from_str;
#[cfg(feature = "index")]
mod index;
#[cfg(feature = "index_mut")]
mod index_mut;
#[cfg(feature = "into")]
mod into;
#[cfg(feature = "into_iterator")]
mod into_iterator;
#[cfg(feature = "iterator")]
mod iterator;
#[cfg(feature = "mul_assign")]
mod mul_assign_like;
#[cfg(any(feature = "mul", feature = "mul_assign"))]
mod mul_helpers;
#[cfg(feature = "mul")]
mod mul_like;
#[cfg(feature = "not")]
mod not_like;
#[cfg(feature = "display")]
#[allow(ellipsis_inclusive_range_patterns)]
#[allow(clippy::all)]
mod parsing;
#[cfg(feature = "sum")]
mod sum_like;
#[cfg(feature = "try_into")]
mod try_into;

// This trait describes the possible return types of
// the derives. A derive can generally be infallible and
// return a TokenStream, or it can be fallible and return
// a Result<TokenStream, syn::parse::Error>.
trait Output {
    fn process(self) -> TokenStream;
}

impl Output for proc_macro2::TokenStream {
    fn process(self) -> TokenStream {
        self.into()
    }
}

impl Output for Result<proc_macro2::TokenStream, ParseError> {
    fn process(self) -> TokenStream {
        match self {
            Ok(ts) => ts.into(),
            Err(e) => e.to_compile_error().into(),
        }
    }
}

macro_rules! create_derive(
    ($feature:literal, $mod_:ident, $trait_:ident, $fn_name: ident $(,$attribute:ident)* $(,)?) => {
        #[cfg(feature = $feature)]
        #[proc_macro_derive($trait_, attributes($($attribute),*))]
        #[doc(hidden)]
        pub fn $fn_name(input: TokenStream) -> TokenStream {
            let ast = syn::parse(input).unwrap();
            Output::process($mod_::expand(&ast, stringify!($trait_)))
        }
    }
);

create_derive!("from", from, From, from_derive, from);

create_derive!("into", into, Into, into_derive, into);

create_derive!("constructor", constructor, Constructor, constructor_derive);

create_derive!("not", not_like, Not, not_derive);
create_derive!("not", not_like, Neg, neg_derive);

create_derive!("add", add_like, Add, add_derive);
create_derive!("add", add_like, Sub, sub_derive);
create_derive!("add", add_like, BitAnd, bit_and_derive);
create_derive!("add", add_like, BitOr, bit_or_derive);
create_derive!("add", add_like, BitXor, bit_xor_derive);

create_derive!("mul", mul_like, Mul, mul_derive, mul);
create_derive!("mul", mul_like, Div, div_derive, div);
create_derive!("mul", mul_like, Rem, rem_derive, rem);
create_derive!("mul", mul_like, Shr, shr_derive, shr);
create_derive!("mul", mul_like, Shl, shl_derive, shl);

create_derive!("add_assign", add_assign_like, AddAssign, add_assign_derive,);
create_derive!("add_assign", add_assign_like, SubAssign, sub_assign_derive,);
create_derive!(
    "add_assign",
    add_assign_like,
    BitAndAssign,
    bit_and_assign_derive,
);
create_derive!(
    "add_assign",
    add_assign_like,
    BitOrAssign,
    bit_or_assign_derive,
);
create_derive!(
    "add_assign",
    add_assign_like,
    BitXorAssign,
    bit_xor_assign_derive,
);

create_derive!(
    "mul_assign",
    mul_assign_like,
    MulAssign,
    mul_assign_derive,
    mul_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    DivAssign,
    div_assign_derive,
    div_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    RemAssign,
    rem_assign_derive,
    rem_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    ShrAssign,
    shr_assign_derive,
    shr_assign,
);
create_derive!(
    "mul_assign",
    mul_assign_like,
    ShlAssign,
    shl_assign_derive,
    shl_assign,
);

create_derive!("sum", sum_like, Sum, sum_derive);
create_derive!("sum", sum_like, Product, product_derive);

create_derive!("from_str", from_str, FromStr, from_str_derive);

create_derive!("display", display, Display, display_derive, display);
create_derive!("display", display, Binary, binary_derive, binary);
create_derive!("display", display, Octal, octal_derive, octal);
create_derive!("display", display, LowerHex, lower_hex_derive, lower_hex);
create_derive!("display", display, UpperHex, upper_hex_derive, upper_hex);
create_derive!("display", display, LowerExp, lower_exp_derive, lower_exp);
create_derive!("display", display, UpperExp, upper_exp_derive, upper_exp);
create_derive!("display", display, Pointer, pointer_derive, pointer);
create_derive!("display", display, DebugCustom, debug_custom_derive, debug);

create_derive!("index", index, Index, index_derive, index);
create_derive!(
    "index_mut",
    index_mut,
    IndexMut,
    index_mut_derive,
    index_mut,
);

create_derive!(
    "into_iterator",
    into_iterator,
    IntoIterator,
    into_iterator_derive,
    into_iterator,
);
create_derive!("iterator", iterator, Iterator, iterator_derive, iterator);

create_derive!("try_into", try_into, TryInto, try_into_derive, try_into);

create_derive!("deref", deref, Deref, deref_derive, deref);
create_derive!(
    "deref_mut",
    deref_mut,
    DerefMut,
    deref_mut_derive,
    deref_mut,
);

create_derive!("as_ref", as_ref, AsRef, as_ref_derive, as_ref);
create_derive!("as_mut", as_mut, AsMut, as_mut_derive, as_mut);
<|endoftext|>