<commit_before>

extern crate cratesfyi;
extern crate clap;
extern crate log;
extern crate env_logger;
extern crate time;
extern crate rustwide;

use std::env;
use std::path::{Path, PathBuf};

use clap::{Arg, App, SubCommand};
use cratesfyi::{DocBuilder, RustwideBuilder, DocBuilderOptions, db};
use cratesfyi::utils::add_crate_to_queue;
use cratesfyi::start_web_server;
use cratesfyi::db::{add_path_into_database, connect_db};

pub fn main() {
    logger_init();

    let matches = App::new("cratesfyi")
        .version(cratesfyi::BUILD_VERSION)
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .subcommand(SubCommand::with_name("build")
            .about("Builds documentation in a chroot environment")
            .arg(Arg::with_name("PREFIX")
                .short("P")
                .long("prefix")
                .takes_value(true))
            .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
                .long("crates-io-index-path")
                .help("Sets crates.io-index path")
                .takes_value(true))
            .arg(Arg::with_name("SKIP_IF_EXISTS")
                .short("s")
                .long("skip")
                .help("Skips building documentation if \
                                                      documentation exists"))
            .arg(Arg::with_name("SKIP_IF_LOG_EXISTS")
                .long("skip-if-log-exists")
                .help("Skips building documentation if build \
                                                      log exists"))
            .arg(Arg::with_name("KEEP_BUILD_DIRECTORY")
                .short("-k")
                .long("keep-build-directory")
                .help("Keeps build directory after build."))
            .subcommand(SubCommand::with_name("world").about("Builds documentation of every \
                                                              crate"))
            .subcommand(SubCommand::with_name("crate")
                .about("Builds documentation for a crate")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required_unless("LOCAL")
                    .requires("CRATE_VERSION")
                    .help("Crate name"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .help("Version of crate"))
                .arg(Arg::with_name("LOCAL")
                    .short("-l")
                    .long("--local")
                    .takes_value(true)
                    .conflicts_with_all(&["CRATE_NAME", "CRATE_VERSION"])
                    .help("Build a crate at a specific path")))
            .subcommand(SubCommand::with_name("add-essential-files")
                .about("Adds essential files for rustc"))
            .subcommand(SubCommand::with_name("lock").about("Locks cratesfyi daemon to stop \
                                                              building new crates"))
            .subcommand(SubCommand::with_name("unlock")
                .about("Unlocks cratesfyi daemon to continue \
                                                              building new crates"))
            .subcommand(SubCommand::with_name("print-options")))
        .subcommand(SubCommand::with_name("start-web-server")
            .about("Starts web server")
            .arg(Arg::with_name("SOCKET_ADDR")
                .index(1)
                .required(false)
                .help("Socket address to listen to")))
        .subcommand(SubCommand::with_name("daemon").about("Starts cratesfyi daemon")
            .arg(Arg::with_name("FOREGROUND")
                .short("-f")
                .long("foreground")
                .help("run the server in the foreground instead of detaching a child")))
        .subcommand(SubCommand::with_name("database")
            .about("Database operations")
            .subcommand(SubCommand::with_name("move-to-s3"))
            .subcommand(SubCommand::with_name("migrate")
                .about("Run database migrations")
                .arg(Arg::with_name("VERSION")))
            .subcommand(SubCommand::with_name("update-github-fields")
                .about("Updates github stats for crates."))
            .subcommand(SubCommand::with_name("add-directory")
                .about("Adds a directory into database")
                .arg(Arg::with_name("DIRECTORY")
                    .index(1)
                    .required(true)
                    .help("Path of file or \
                                                                      directory"))
                .arg(Arg::with_name("PREFIX")
                    .index(2)
                    .help("Prefix of files in \
                                                                      database")))
            .subcommand(SubCommand::with_name("update-release-activity"))
            .about("Updates montly release activity \
                                                              chart")
            .subcommand(SubCommand::with_name("update-search-index"))
            .about("Updates search index"))
        .subcommand(SubCommand::with_name("queue")
            .about("Interactions with the build queue")
            .subcommand(SubCommand::with_name("add")
                .about("Add a crate to the build queue")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required(true)
                    .help("Name of crate to build"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .required(true)
                    .help("Version of crate to build"))
                .arg(Arg::with_name("BUILD_PRIORITY")
                    .short("p")
                    .long("priority")
                    .help("Priority of build (default: 5) (new crate builds get priority 0)")
                    .takes_value(true))))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("build") {
        let docbuilder_opts = {
            let mut docbuilder_opts = if let Some(prefix) = matches.value_of("PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else if let Ok(prefix) = env::var("CRATESFYI_PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else {
                DocBuilderOptions::default()
            };

            if let Some(crates_io_index_path) = matches.value_of("CRATES_IO_INDEX_PATH") {
                docbuilder_opts.crates_io_index_path = PathBuf::from(crates_io_index_path);
            }

            docbuilder_opts.skip_if_exists = matches.is_present("SKIP_IF_EXISTS");
            docbuilder_opts.skip_if_log_exists = matches.is_present("SKIP_IF_LOG_EXISTS");
            docbuilder_opts.keep_build_directory = matches.is_present("KEEP_BUILD_DIRECTORY");

            docbuilder_opts.check_paths().unwrap();

            docbuilder_opts
        };

        let mut docbuilder = DocBuilder::new(docbuilder_opts);

        if let Some(_) = matches.subcommand_matches("world") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().unwrap();
            builder.build_world(&mut docbuilder).expect("Failed to build world");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(matches) = matches.subcommand_matches("crate") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().unwrap();
            match matches.value_of("LOCAL") {
                Some(path) => builder.build_local_package(&mut docbuilder, Path::new(path)),
                None => builder.build_package(&mut docbuilder,
                    matches.value_of("CRATE_NAME").unwrap(), matches.value_of("CRATE_VERSION").unwrap(), None),
            }.expect("Building documentation failed");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(_) = matches.subcommand_matches("add-essential-files") {
            let mut builder = RustwideBuilder::init().unwrap();
            builder.add_essential_files().expect("failed to add essential files");
        } else if let Some(_) = matches.subcommand_matches("lock") {
            docbuilder.lock().expect("Failed to lock");
        } else if let Some(_) = matches.subcommand_matches("unlock") {
            docbuilder.unlock().expect("Failed to unlock");
        } else if let Some(_) = matches.subcommand_matches("print-options") {
            println!("{:?}", docbuilder.options());
        }

    } else if let Some(matches) = matches.subcommand_matches("database") {
        if let Some(matches) = matches.subcommand_matches("migrate") {
            let version = matches.value_of("VERSION").map(|v| v.parse::<i64>()
                                                          .expect("Version should be an integer"));
            db::migrate(version).expect("Failed to run database migrations");
        } else if let Some(_) = matches.subcommand_matches("update-github-fields") {
            cratesfyi::utils::github_updater().expect("Failed to update github fields");
        } else if let Some(matches) = matches.subcommand_matches("add-directory") {
            add_path_into_database(&db::connect_db().unwrap(),
                                   matches.value_of("PREFIX").unwrap_or(""),
                                   matches.value_of("DIRECTORY").unwrap())
                .expect("Failed to add directory into database");
        } else if let Some(_) = matches.subcommand_matches("update-release-activity") {
            // FIXME: This is actually util command not database
            cratesfyi::utils::update_release_activity().expect("Failed to update release activity");
        } else if let Some(_) = matches.subcommand_matches("update-search-index") {
            let conn = db::connect_db().unwrap();
            db::update_search_index(&conn).expect("Failed to update search index");
        } else if let Some(_) = matches.subcommand_matches("move-to-s3") {
            let conn = db::connect_db().unwrap();
            let mut count = 1;
            let mut total = 0;
            while count != 0 {
                count = db::file::move_to_s3(&conn, 5_000).expect("Failed to upload batch to S3");
                total += count;
                eprintln!(
                    "moved {} rows to s3 in this batch, total moved so far: {}",
                    count, total
                );
            }
        }
    } else if let Some(matches) = matches.subcommand_matches("start-web-server") {
        start_web_server(Some(matches.value_of("SOCKET_ADDR").unwrap_or("0.0.0.0:3000")));
    } else if let Some(_) = matches.subcommand_matches("daemon") {
        let foreground = matches.subcommand_matches("daemon")
            .map_or(false, |opts| opts.is_present("FOREGROUND"));
        cratesfyi::utils::start_daemon(!foreground);
    } else if let Some(matches) = matches.subcommand_matches("queue") {
        if let Some(matches) = matches.subcommand_matches("add") {
            let priority = matches.value_of("BUILD_PRIORITY").unwrap_or("5");
            let priority: i32 = priority.parse().expect("--priority was not a number");
            let conn = connect_db().expect("Could not connect to database");

            add_crate_to_queue(&conn,
                               matches.value_of("CRATE_NAME").unwrap(),
                               matches.value_of("CRATE_VERSION").unwrap(),
                               priority).expect("Could not add crate to queue");
        }
    } else {
        println!("{}", matches.usage());
    }
}

fn logger_init() {
    use std::io::Write;

    let mut builder = env_logger::Builder::new();
    builder.format(|buf, record| {
        writeln!(buf, "{} [{}] {}: {}",
                time::now().strftime("%Y/%m/%d %H:%M:%S").unwrap(),
                record.level(),
                record.target(),
                record.args())
    });
    builder.parse(&env::var("RUST_LOG").unwrap_or("cratesfyi=info".to_owned()));

    rustwide::logging::init_with(builder.build());
}
<commit_msg>give a useful error message when rustwide fails to initialize<commit_after>

extern crate cratesfyi;
extern crate clap;
extern crate log;
extern crate env_logger;
extern crate time;
extern crate rustwide;

use std::env;
use std::path::{Path, PathBuf};

use clap::{Arg, App, SubCommand};
use cratesfyi::{DocBuilder, RustwideBuilder, DocBuilderOptions, db};
use cratesfyi::utils::add_crate_to_queue;
use cratesfyi::start_web_server;
use cratesfyi::db::{add_path_into_database, connect_db};

pub fn main() {
    logger_init();

    let matches = App::new("cratesfyi")
        .version(cratesfyi::BUILD_VERSION)
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .subcommand(SubCommand::with_name("build")
            .about("Builds documentation in a chroot environment")
            .arg(Arg::with_name("PREFIX")
                .short("P")
                .long("prefix")
                .takes_value(true))
            .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
                .long("crates-io-index-path")
                .help("Sets crates.io-index path")
                .takes_value(true))
            .arg(Arg::with_name("SKIP_IF_EXISTS")
                .short("s")
                .long("skip")
                .help("Skips building documentation if \
                                                      documentation exists"))
            .arg(Arg::with_name("SKIP_IF_LOG_EXISTS")
                .long("skip-if-log-exists")
                .help("Skips building documentation if build \
                                                      log exists"))
            .arg(Arg::with_name("KEEP_BUILD_DIRECTORY")
                .short("-k")
                .long("keep-build-directory")
                .help("Keeps build directory after build."))
            .subcommand(SubCommand::with_name("world").about("Builds documentation of every \
                                                              crate"))
            .subcommand(SubCommand::with_name("crate")
                .about("Builds documentation for a crate")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required_unless("LOCAL")
                    .requires("CRATE_VERSION")
                    .help("Crate name"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .help("Version of crate"))
                .arg(Arg::with_name("LOCAL")
                    .short("-l")
                    .long("--local")
                    .takes_value(true)
                    .conflicts_with_all(&["CRATE_NAME", "CRATE_VERSION"])
                    .help("Build a crate at a specific path")))
            .subcommand(SubCommand::with_name("add-essential-files")
                .about("Adds essential files for rustc"))
            .subcommand(SubCommand::with_name("lock").about("Locks cratesfyi daemon to stop \
                                                              building new crates"))
            .subcommand(SubCommand::with_name("unlock")
                .about("Unlocks cratesfyi daemon to continue \
                                                              building new crates"))
            .subcommand(SubCommand::with_name("print-options")))
        .subcommand(SubCommand::with_name("start-web-server")
            .about("Starts web server")
            .arg(Arg::with_name("SOCKET_ADDR")
                .index(1)
                .required(false)
                .help("Socket address to listen to")))
        .subcommand(SubCommand::with_name("daemon").about("Starts cratesfyi daemon")
            .arg(Arg::with_name("FOREGROUND")
                .short("-f")
                .long("foreground")
                .help("run the server in the foreground instead of detaching a child")))
        .subcommand(SubCommand::with_name("database")
            .about("Database operations")
            .subcommand(SubCommand::with_name("move-to-s3"))
            .subcommand(SubCommand::with_name("migrate")
                .about("Run database migrations")
                .arg(Arg::with_name("VERSION")))
            .subcommand(SubCommand::with_name("update-github-fields")
                .about("Updates github stats for crates."))
            .subcommand(SubCommand::with_name("add-directory")
                .about("Adds a directory into database")
                .arg(Arg::with_name("DIRECTORY")
                    .index(1)
                    .required(true)
                    .help("Path of file or \
                                                                      directory"))
                .arg(Arg::with_name("PREFIX")
                    .index(2)
                    .help("Prefix of files in \
                                                                      database")))
            .subcommand(SubCommand::with_name("update-release-activity"))
            .about("Updates montly release activity \
                                                              chart")
            .subcommand(SubCommand::with_name("update-search-index"))
            .about("Updates search index"))
        .subcommand(SubCommand::with_name("queue")
            .about("Interactions with the build queue")
            .subcommand(SubCommand::with_name("add")
                .about("Add a crate to the build queue")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required(true)
                    .help("Name of crate to build"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .required(true)
                    .help("Version of crate to build"))
                .arg(Arg::with_name("BUILD_PRIORITY")
                    .short("p")
                    .long("priority")
                    .help("Priority of build (default: 5) (new crate builds get priority 0)")
                    .takes_value(true))))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("build") {
        let docbuilder_opts = {
            let mut docbuilder_opts = if let Some(prefix) = matches.value_of("PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else if let Ok(prefix) = env::var("CRATESFYI_PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else {
                DocBuilderOptions::default()
            };

            if let Some(crates_io_index_path) = matches.value_of("CRATES_IO_INDEX_PATH") {
                docbuilder_opts.crates_io_index_path = PathBuf::from(crates_io_index_path);
            }

            docbuilder_opts.skip_if_exists = matches.is_present("SKIP_IF_EXISTS");
            docbuilder_opts.skip_if_log_exists = matches.is_present("SKIP_IF_LOG_EXISTS");
            docbuilder_opts.keep_build_directory = matches.is_present("KEEP_BUILD_DIRECTORY");

            docbuilder_opts.check_paths().unwrap();

            docbuilder_opts
        };

        let mut docbuilder = DocBuilder::new(docbuilder_opts);

        if let Some(_) = matches.subcommand_matches("world") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().unwrap();
            builder.build_world(&mut docbuilder).expect("Failed to build world");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(matches) = matches.subcommand_matches("crate") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().expect("failed to initialize rustwide");
            match matches.value_of("LOCAL") {
                Some(path) => builder.build_local_package(&mut docbuilder, Path::new(path)),
                None => builder.build_package(&mut docbuilder,
                    matches.value_of("CRATE_NAME").unwrap(), matches.value_of("CRATE_VERSION").unwrap(), None),
            }.expect("Building documentation failed");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(_) = matches.subcommand_matches("add-essential-files") {
            let mut builder = RustwideBuilder::init().unwrap();
            builder.add_essential_files().expect("failed to add essential files");
        } else if let Some(_) = matches.subcommand_matches("lock") {
            docbuilder.lock().expect("Failed to lock");
        } else if let Some(_) = matches.subcommand_matches("unlock") {
            docbuilder.unlock().expect("Failed to unlock");
        } else if let Some(_) = matches.subcommand_matches("print-options") {
            println!("{:?}", docbuilder.options());
        }

    } else if let Some(matches) = matches.subcommand_matches("database") {
        if let Some(matches) = matches.subcommand_matches("migrate") {
            let version = matches.value_of("VERSION").map(|v| v.parse::<i64>()
                                                          .expect("Version should be an integer"));
            db::migrate(version).expect("Failed to run database migrations");
        } else if let Some(_) = matches.subcommand_matches("update-github-fields") {
            cratesfyi::utils::github_updater().expect("Failed to update github fields");
        } else if let Some(matches) = matches.subcommand_matches("add-directory") {
            add_path_into_database(&db::connect_db().unwrap(),
                                   matches.value_of("PREFIX").unwrap_or(""),
                                   matches.value_of("DIRECTORY").unwrap())
                .expect("Failed to add directory into database");
        } else if let Some(_) = matches.subcommand_matches("update-release-activity") {
            // FIXME: This is actually util command not database
            cratesfyi::utils::update_release_activity().expect("Failed to update release activity");
        } else if let Some(_) = matches.subcommand_matches("update-search-index") {
            let conn = db::connect_db().unwrap();
            db::update_search_index(&conn).expect("Failed to update search index");
        } else if let Some(_) = matches.subcommand_matches("move-to-s3") {
            let conn = db::connect_db().unwrap();
            let mut count = 1;
            let mut total = 0;
            while count != 0 {
                count = db::file::move_to_s3(&conn, 5_000).expect("Failed to upload batch to S3");
                total += count;
                eprintln!(
                    "moved {} rows to s3 in this batch, total moved so far: {}",
                    count, total
                );
            }
        }
    } else if let Some(matches) = matches.subcommand_matches("start-web-server") {
        start_web_server(Some(matches.value_of("SOCKET_ADDR").unwrap_or("0.0.0.0:3000")));
    } else if let Some(_) = matches.subcommand_matches("daemon") {
        let foreground = matches.subcommand_matches("daemon")
            .map_or(false, |opts| opts.is_present("FOREGROUND"));
        cratesfyi::utils::start_daemon(!foreground);
    } else if let Some(matches) = matches.subcommand_matches("queue") {
        if let Some(matches) = matches.subcommand_matches("add") {
            let priority = matches.value_of("BUILD_PRIORITY").unwrap_or("5");
            let priority: i32 = priority.parse().expect("--priority was not a number");
            let conn = connect_db().expect("Could not connect to database");

            add_crate_to_queue(&conn,
                               matches.value_of("CRATE_NAME").unwrap(),
                               matches.value_of("CRATE_VERSION").unwrap(),
                               priority).expect("Could not add crate to queue");
        }
    } else {
        println!("{}", matches.usage());
    }
}

fn logger_init() {
    use std::io::Write;

    let mut builder = env_logger::Builder::new();
    builder.format(|buf, record| {
        writeln!(buf, "{} [{}] {}: {}",
                time::now().strftime("%Y/%m/%d %H:%M:%S").unwrap(),
                record.level(),
                record.target(),
                record.args())
    });
    builder.parse(&env::var("RUST_LOG").unwrap_or("cratesfyi=info".to_owned()));

    rustwide::logging::init_with(builder.build());
}
<|endoftext|>


<commit_before>use std::io::{Result, Error, Read, Seek, SeekFrom, ErrorKind};

pub trait ReadAll : Read {
    fn read_all(&mut self, buf: &mut [u8]) -> Result<()>;
}

pub trait BinaryRead : ReadAll {
    fn read_u8(&mut self) -> Result<u8>;
    fn read_le_u16(&mut self) -> Result<u16>;
    fn read_le_i32(&mut self) -> Result<i32>;
}

pub struct BinaryReader<R> {
    inner: R
}

impl<R: Read> BinaryReader<R> {
    pub fn new(inner: R) -> BinaryReader<R> {
        BinaryReader { inner: inner }
    }
}

impl<R: Read> Read for BinaryReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.inner.read(buf)
    }
}

impl<R: Seek> Seek for BinaryReader<R> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        self.inner.seek(pos)
    }
}

impl<R: Read> ReadAll for BinaryReader<R> {
    fn read_all(&mut self, buf: &mut [u8]) -> Result<()> {
        match self.inner.read(buf) {
            Ok(len) if len == buf.len() => Ok(()),
            Ok(_) => Err(Error::new(ErrorKind::Other, "Could not read all bytes")),
            Err(e) => Err(e)
        }
    }
}

impl<R: Read> BinaryRead for BinaryReader<R> {
    fn read_u8(&mut self) -> Result<u8> {
        let mut buf = [0; 1];
        try!(self.read_all(&mut buf));
        Ok(buf[0])
    }

    fn read_le_u16(&mut self) -> Result<u16> {
        // TODO: Ensure endian
        let mut buf = [0; 2];
        try!(self.read_all(&mut buf));
        Ok(((buf[1] as u16) << 8) | (buf[0] as u16))
    }

    fn read_le_i32(&mut self) -> Result<i32> {
        // TODO: Ensure endian
        let mut buf = [0; 4];
        try!(self.read_all(&mut buf));
        Ok((
            ((buf[3] as u32) << 24) | ((buf[2] as u32) << 16) |
            ((buf[1] as u32) << 8) | (buf[0] as u32)) as i32)
    }
}
<commit_msg>Removed unnecessary TODO's in binary_reader<commit_after>use std::io::{Result, Error, Read, Seek, SeekFrom, ErrorKind};

pub trait ReadAll : Read {
    fn read_all(&mut self, buf: &mut [u8]) -> Result<()>;
}

pub trait BinaryRead : ReadAll {
    fn read_u8(&mut self) -> Result<u8>;
    fn read_le_u16(&mut self) -> Result<u16>;
    fn read_le_i32(&mut self) -> Result<i32>;
}

pub struct BinaryReader<R> {
    inner: R
}

impl<R: Read> BinaryReader<R> {
    pub fn new(inner: R) -> BinaryReader<R> {
        BinaryReader { inner: inner }
    }
}

impl<R: Read> Read for BinaryReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.inner.read(buf)
    }
}

impl<R: Seek> Seek for BinaryReader<R> {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        self.inner.seek(pos)
    }
}

impl<R: Read> ReadAll for BinaryReader<R> {
    fn read_all(&mut self, buf: &mut [u8]) -> Result<()> {
        match self.inner.read(buf) {
            Ok(len) if len == buf.len() => Ok(()),
            Ok(_) => Err(Error::new(ErrorKind::Other, "Could not read all bytes")),
            Err(e) => Err(e)
        }
    }
}

impl<R: Read> BinaryRead for BinaryReader<R> {
    fn read_u8(&mut self) -> Result<u8> {
        let mut buf = [0; 1];
        try!(self.read_all(&mut buf));
        Ok(buf[0])
    }

    fn read_le_u16(&mut self) -> Result<u16> {
        let mut buf = [0; 2];
        try!(self.read_all(&mut buf));
        Ok(((buf[1] as u16) << 8) | (buf[0] as u16))
    }

    fn read_le_i32(&mut self) -> Result<i32> {
        let mut buf = [0; 4];
        try!(self.read_all(&mut buf));
        Ok((
            ((buf[3] as u32) << 24) | ((buf[2] as u32) << 16) |
            ((buf[1] as u32) << 8) | (buf[0] as u32)) as i32)
    }
}
<|endoftext|>


<commit_before>use mysql::error::Error;
use mysql::{Conn, Opts, OptsBuilder};
use std::result::Result;
use r2d2;
use mysql::prelude::Queryable;

#[derive(Clone, Debug)]
pub struct MysqlConnectionManager {
    params: Opts,
}

impl MysqlConnectionManager {
    pub fn new(params: OptsBuilder) -> MysqlConnectionManager {
        MysqlConnectionManager {
            params: Opts::from(params),
        }
    }
}

impl r2d2::ManageConnection for MysqlConnectionManager {
    type Connection = Conn;
    type Error = Error;

    fn connect(&self) -> Result<Conn, Error> {
        Conn::new(self.params.clone())
    }

    fn is_valid(&self, conn: &mut Conn) -> Result<(), Error> {
        conn.query("SELECT version()").map(|_| ())
    }

    fn has_broken(&self, conn: &mut Conn) -> bool {
        self.is_valid(conn).is_err()
    }
}
<commit_msg>Update pool.rs<commit_after>use mysql::error::Error;
use mysql::{Conn, Opts, OptsBuilder};
use std::result::Result;
use r2d2;
use mysql::prelude::Queryable;

#[derive(Clone, Debug)]
pub struct MysqlConnectionManager {
    params: Opts,
}

impl MysqlConnectionManager {
    pub fn new(params: OptsBuilder) -> MysqlConnectionManager {
        MysqlConnectionManager {
            params: Opts::from(params),
        }
    }
}

impl r2d2::ManageConnection for MysqlConnectionManager {
    type Connection = Conn;
    type Error = Error;

    fn connect(&self) -> Result<Conn, Error> {
        Conn::new(self.params.clone())
    }

    fn is_valid(&self, conn: &mut Conn) -> Result<(), Error> {
        conn.query("SELECT version()").map(|_: String| ())
    }

    fn has_broken(&self, conn: &mut Conn) -> bool {
        self.is_valid(conn).is_err()
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Documentation generation for rustbuild.
//!
//! This module implements generation for all bits and pieces of documentation
//! for the Rust project. This notably includes suites like the rust book, the
//! nomicon, standalone documentation, etc.
//!
//! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`.

use std::fs::{self, File};
use std::io::prelude::*;
use std::process::Command;

use {Build, Compiler, Mode};
use util::{up_to_date, cp_r};

/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
/// `name` into the `out` path.
///
/// This will not actually generate any documentation if the documentation has
/// already been generated.
pub fn rustbook(build: &Build, target: &str, name: &str) {
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));

    let out = out.join(name);
    let compiler = Compiler::new(0, &build.config.build);
    let src = build.src.join("src/doc").join(name);
    let index = out.join("index.html");
    let rustbook = build.tool(&compiler, "rustbook");
    if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
        return
    }
    println!("Rustbook ({}) - {}", target, name);
    let _ = fs::remove_dir_all(&out);
    build.run(build.tool_cmd(&compiler, "rustbook")
                   .arg("build")
                   .arg(&src)
                   .arg(out));
}

/// Generates all standalone documentation as compiled by the rustdoc in `stage`
/// for the `target` into `out`.
///
/// This will list all of `src/doc` looking for markdown files and appropriately
/// perform transformations like substituting `VERSION`, `SHORT_HASH`, and
/// `STAMP` alongw ith providing the various header/footer HTML we've cutomized.
///
/// In the end, this is just a glorified wrapper around rustdoc!
pub fn standalone(build: &Build, target: &str) {
    println!("Documenting standalone ({})", target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));

    let compiler = Compiler::new(0, &build.config.build);

    let favicon = build.src.join("src/doc/favicon.inc");
    let footer = build.src.join("src/doc/footer.inc");
    let full_toc = build.src.join("src/doc/full-toc.inc");
    t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css")));

    let version_input = build.src.join("src/doc/version_info.html.template");
    let version_info = out.join("version_info.html");

    if !up_to_date(&version_input, &version_info) {
        let mut info = String::new();
        t!(t!(File::open(&version_input)).read_to_string(&mut info));
        let blank = String::new();
        let short = build.short_ver_hash.as_ref().unwrap_or(&blank);
        let hash = build.ver_hash.as_ref().unwrap_or(&blank);
        let info = info.replace("VERSION", &build.release)
                       .replace("SHORT_HASH", short)
                       .replace("STAMP", hash);
        t!(t!(File::create(&version_info)).write_all(info.as_bytes()));
    }

    for file in t!(fs::read_dir(build.src.join("src/doc"))) {
        let file = t!(file);
        let path = file.path();
        let filename = path.file_name().unwrap().to_str().unwrap();
        if !filename.ends_with(".md") || filename == "README.md" {
            continue
        }

        let html = out.join(filename).with_extension("html");
        let rustdoc = build.rustdoc(&compiler);
        if up_to_date(&path, &html) &&
           up_to_date(&footer, &html) &&
           up_to_date(&favicon, &html) &&
           up_to_date(&full_toc, &html) &&
           up_to_date(&version_info, &html) &&
           up_to_date(&rustdoc, &html) {
            continue
        }

        let mut cmd = Command::new(&rustdoc);
        build.add_rustc_lib_path(&compiler, &mut cmd);
        cmd.arg("--html-after-content").arg(&footer)
           .arg("--html-before-content").arg(&version_info)
           .arg("--html-in-header").arg(&favicon)
           .arg("--markdown-playground-url")
           .arg("https://play.rust-lang.org/")
           .arg("-o").arg(&out)
           .arg(&path);

        if filename == "reference.md" {
           cmd.arg("--html-in-header").arg(&full_toc);
        }

        if filename == "not_found.md" {
            cmd.arg("--markdown-no-toc")
               .arg("--markdown-css")
               .arg("https://doc.rust-lang.org/rust.css");
        } else {
            cmd.arg("--markdown-css").arg("rust.css");
        }
        build.run(&mut cmd);
    }
}

/// Compile all standard library documentation.
///
/// This will generate all documentation for the standard library and its
/// dependencies. This is largely just a wrapper around `cargo doc`.
pub fn std(build: &Build, stage: u32, target: &str) {
    println!("Documenting stage{} std ({})", stage, target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(stage, &build.config.build);
    let compiler = if build.force_use_stage1(&compiler, target) {
        Compiler::new(1, compiler.host)
    } else {
        compiler
    };
    let out_dir = build.stage_out(&compiler, Mode::Libstd)
                       .join(target).join("doc");
    let rustdoc = build.rustdoc(&compiler);

    build.clear_if_dirty(&out_dir, &rustdoc);

    let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc");
    cargo.arg("--manifest-path")
         .arg(build.src.join("src/rustc/std_shim/Cargo.toml"))
         .arg("--features").arg(build.std_features())
         .arg("--no-deps");

    for krate in &["alloc", "collections", "core", "std", "std_unicode"] {
        cargo.arg("-p").arg(krate);
        // Create all crate output directories first to make sure rustdoc uses
        // relative links.
        // FIXME: Cargo should probably do this itself.
        t!(fs::create_dir_all(out_dir.join(krate)));
    }

    build.run(&mut cargo);
    cp_r(&out_dir, &out)
}

/// Compile all libtest documentation.
///
/// This will generate all documentation for libtest and its dependencies. This
/// is largely just a wrapper around `cargo doc`.
pub fn test(build: &Build, stage: u32, target: &str) {
    println!("Documenting stage{} test ({})", stage, target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(stage, &build.config.build);
    let compiler = if build.force_use_stage1(&compiler, target) {
        Compiler::new(1, compiler.host)
    } else {
        compiler
    };
    let out_dir = build.stage_out(&compiler, Mode::Libtest)
                       .join(target).join("doc");
    let rustdoc = build.rustdoc(&compiler);

    build.clear_if_dirty(&out_dir, &rustdoc);

    let mut cargo = build.cargo(&compiler, Mode::Libtest, target, "doc");
    cargo.arg("--manifest-path")
         .arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
    build.run(&mut cargo);
    cp_r(&out_dir, &out)
}

/// Generate all compiler documentation.
///
/// This will generate all documentation for the compiler libraries and their
/// dependencies. This is largely just a wrapper around `cargo doc`.
pub fn rustc(build: &Build, stage: u32, target: &str) {
    println!("Documenting stage{} compiler ({})", stage, target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(stage, &build.config.build);
    let compiler = if build.force_use_stage1(&compiler, target) {
        Compiler::new(1, compiler.host)
    } else {
        compiler
    };
    let out_dir = build.stage_out(&compiler, Mode::Librustc)
                       .join(target).join("doc");
    let rustdoc = build.rustdoc(&compiler);
    if !up_to_date(&rustdoc, &out_dir.join("rustc/index.html")) && out_dir.exists() {
        t!(fs::remove_dir_all(&out_dir));
    }
    let mut cargo = build.cargo(&compiler, Mode::Librustc, target, "doc");
    cargo.arg("--manifest-path")
         .arg(build.src.join("src/rustc/Cargo.toml"))
         .arg("--features").arg(build.rustc_features());
    build.run(&mut cargo);
    cp_r(&out_dir, &out)
}

/// Generates the HTML rendered error-index by running the
/// `error_index_generator` tool.
pub fn error_index(build: &Build, target: &str) {
    println!("Documenting error index ({})", target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(0, &build.config.build);
    let mut index = build.tool_cmd(&compiler, "error_index_generator");
    index.arg("html");
    index.arg(out.join("error-index.html"));

    // FIXME: shouldn't have to pass this env var
    index.env("CFG_BUILD", &build.config.build);

    build.run(&mut index);
}
<commit_msg>Don't restrict docs in compiler-docs mode<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Documentation generation for rustbuild.
//!
//! This module implements generation for all bits and pieces of documentation
//! for the Rust project. This notably includes suites like the rust book, the
//! nomicon, standalone documentation, etc.
//!
//! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`.

use std::fs::{self, File};
use std::io::prelude::*;
use std::process::Command;

use {Build, Compiler, Mode};
use util::{up_to_date, cp_r};

/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
/// `name` into the `out` path.
///
/// This will not actually generate any documentation if the documentation has
/// already been generated.
pub fn rustbook(build: &Build, target: &str, name: &str) {
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));

    let out = out.join(name);
    let compiler = Compiler::new(0, &build.config.build);
    let src = build.src.join("src/doc").join(name);
    let index = out.join("index.html");
    let rustbook = build.tool(&compiler, "rustbook");
    if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
        return
    }
    println!("Rustbook ({}) - {}", target, name);
    let _ = fs::remove_dir_all(&out);
    build.run(build.tool_cmd(&compiler, "rustbook")
                   .arg("build")
                   .arg(&src)
                   .arg(out));
}

/// Generates all standalone documentation as compiled by the rustdoc in `stage`
/// for the `target` into `out`.
///
/// This will list all of `src/doc` looking for markdown files and appropriately
/// perform transformations like substituting `VERSION`, `SHORT_HASH`, and
/// `STAMP` alongw ith providing the various header/footer HTML we've cutomized.
///
/// In the end, this is just a glorified wrapper around rustdoc!
pub fn standalone(build: &Build, target: &str) {
    println!("Documenting standalone ({})", target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));

    let compiler = Compiler::new(0, &build.config.build);

    let favicon = build.src.join("src/doc/favicon.inc");
    let footer = build.src.join("src/doc/footer.inc");
    let full_toc = build.src.join("src/doc/full-toc.inc");
    t!(fs::copy(build.src.join("src/doc/rust.css"), out.join("rust.css")));

    let version_input = build.src.join("src/doc/version_info.html.template");
    let version_info = out.join("version_info.html");

    if !up_to_date(&version_input, &version_info) {
        let mut info = String::new();
        t!(t!(File::open(&version_input)).read_to_string(&mut info));
        let blank = String::new();
        let short = build.short_ver_hash.as_ref().unwrap_or(&blank);
        let hash = build.ver_hash.as_ref().unwrap_or(&blank);
        let info = info.replace("VERSION", &build.release)
                       .replace("SHORT_HASH", short)
                       .replace("STAMP", hash);
        t!(t!(File::create(&version_info)).write_all(info.as_bytes()));
    }

    for file in t!(fs::read_dir(build.src.join("src/doc"))) {
        let file = t!(file);
        let path = file.path();
        let filename = path.file_name().unwrap().to_str().unwrap();
        if !filename.ends_with(".md") || filename == "README.md" {
            continue
        }

        let html = out.join(filename).with_extension("html");
        let rustdoc = build.rustdoc(&compiler);
        if up_to_date(&path, &html) &&
           up_to_date(&footer, &html) &&
           up_to_date(&favicon, &html) &&
           up_to_date(&full_toc, &html) &&
           up_to_date(&version_info, &html) &&
           up_to_date(&rustdoc, &html) {
            continue
        }

        let mut cmd = Command::new(&rustdoc);
        build.add_rustc_lib_path(&compiler, &mut cmd);
        cmd.arg("--html-after-content").arg(&footer)
           .arg("--html-before-content").arg(&version_info)
           .arg("--html-in-header").arg(&favicon)
           .arg("--markdown-playground-url")
           .arg("https://play.rust-lang.org/")
           .arg("-o").arg(&out)
           .arg(&path);

        if filename == "reference.md" {
           cmd.arg("--html-in-header").arg(&full_toc);
        }

        if filename == "not_found.md" {
            cmd.arg("--markdown-no-toc")
               .arg("--markdown-css")
               .arg("https://doc.rust-lang.org/rust.css");
        } else {
            cmd.arg("--markdown-css").arg("rust.css");
        }
        build.run(&mut cmd);
    }
}

/// Compile all standard library documentation.
///
/// This will generate all documentation for the standard library and its
/// dependencies. This is largely just a wrapper around `cargo doc`.
pub fn std(build: &Build, stage: u32, target: &str) {
    println!("Documenting stage{} std ({})", stage, target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(stage, &build.config.build);
    let compiler = if build.force_use_stage1(&compiler, target) {
        Compiler::new(1, compiler.host)
    } else {
        compiler
    };
    let out_dir = build.stage_out(&compiler, Mode::Libstd)
                       .join(target).join("doc");
    let rustdoc = build.rustdoc(&compiler);

    build.clear_if_dirty(&out_dir, &rustdoc);

    let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc");
    cargo.arg("--manifest-path")
         .arg(build.src.join("src/rustc/std_shim/Cargo.toml"))
         .arg("--features").arg(build.std_features());

    // We don't want to build docs for internal std dependencies unless
    // in compiler-docs mode. When not in that mode, we whitelist the crates
    // for which docs must be built.
    if build.config.compiler_docs {
        cargo.arg("-p").arg("std");
    } else {
        cargo.arg("--no-deps");
        for krate in &["alloc", "collections", "core", "std", "std_unicode"] {
            cargo.arg("-p").arg(krate);
            // Create all crate output directories first to make sure rustdoc uses
            // relative links.
            // FIXME: Cargo should probably do this itself.
            t!(fs::create_dir_all(out_dir.join(krate)));
        }
    }

    build.run(&mut cargo);
    cp_r(&out_dir, &out)
}

/// Compile all libtest documentation.
///
/// This will generate all documentation for libtest and its dependencies. This
/// is largely just a wrapper around `cargo doc`.
pub fn test(build: &Build, stage: u32, target: &str) {
    println!("Documenting stage{} test ({})", stage, target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(stage, &build.config.build);
    let compiler = if build.force_use_stage1(&compiler, target) {
        Compiler::new(1, compiler.host)
    } else {
        compiler
    };
    let out_dir = build.stage_out(&compiler, Mode::Libtest)
                       .join(target).join("doc");
    let rustdoc = build.rustdoc(&compiler);

    build.clear_if_dirty(&out_dir, &rustdoc);

    let mut cargo = build.cargo(&compiler, Mode::Libtest, target, "doc");
    cargo.arg("--manifest-path")
         .arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
    build.run(&mut cargo);
    cp_r(&out_dir, &out)
}

/// Generate all compiler documentation.
///
/// This will generate all documentation for the compiler libraries and their
/// dependencies. This is largely just a wrapper around `cargo doc`.
pub fn rustc(build: &Build, stage: u32, target: &str) {
    println!("Documenting stage{} compiler ({})", stage, target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(stage, &build.config.build);
    let compiler = if build.force_use_stage1(&compiler, target) {
        Compiler::new(1, compiler.host)
    } else {
        compiler
    };
    let out_dir = build.stage_out(&compiler, Mode::Librustc)
                       .join(target).join("doc");
    let rustdoc = build.rustdoc(&compiler);
    if !up_to_date(&rustdoc, &out_dir.join("rustc/index.html")) && out_dir.exists() {
        t!(fs::remove_dir_all(&out_dir));
    }
    let mut cargo = build.cargo(&compiler, Mode::Librustc, target, "doc");
    cargo.arg("--manifest-path")
         .arg(build.src.join("src/rustc/Cargo.toml"))
         .arg("--features").arg(build.rustc_features());
    build.run(&mut cargo);
    cp_r(&out_dir, &out)
}

/// Generates the HTML rendered error-index by running the
/// `error_index_generator` tool.
pub fn error_index(build: &Build, target: &str) {
    println!("Documenting error index ({})", target);
    let out = build.doc_out(target);
    t!(fs::create_dir_all(&out));
    let compiler = Compiler::new(0, &build.config.build);
    let mut index = build.tool_cmd(&compiler, "error_index_generator");
    index.arg("html");
    index.arg(out.join("error-index.html"));

    // FIXME: shouldn't have to pass this env var
    index.env("CFG_BUILD", &build.config.build);

    build.run(&mut index);
}
<|endoftext|>


<commit_before>use serde_json;
use serde_json::Value;

use bot::parse_mode::{get_parse_mode, ParseMode};
use error::Error::{JsonNotFound};
use error::{Result, check_for_error};
use objects::{Update, Message};
use bot::Bot;

impl Bot {
    /// API call which will send a message to a chat which your bot participates in.
    pub fn send_message(&self,
                        chat_id: &i64,
                        text: &str,
                        parse_mode: Option<&ParseMode>,
                        disable_web_page_preview: Option<&bool>,
                        disable_notification: Option<&bool>,
                        reply_to_message_id: Option<&i64>)
                        -> Result<Message> {
        let chat_id: &str = &chat_id.to_string();
        let parse_mode = &get_parse_mode(parse_mode.unwrap_or(&ParseMode::Text));
        let disable_web_page_preview: &str = &disable_web_page_preview.unwrap_or(&false)
            .to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let reply_to_message_id: &str = &reply_to_message_id.map(|i| i.to_string())
            .unwrap_or("None".to_string());
        let path = ["sendMessage"];
        let params = [("chat_id", chat_id),
                      ("text", text),
                      ("parse_mode", parse_mode),
                      ("disable_web_page_preview", disable_web_page_preview),
                      ("disable_notification", disable_notification),
                      ("reply_to_message_id", reply_to_message_id)];
        self.post_message(&path, &params)
    }

    /// API call which will reply to a message directed to your bot.
    pub fn reply_to_message(&self, update: &Update, text: &str) -> Result<Message> {
        let message = update.clone().message.unwrap();
        let message_id = message.message_id;
        let chat_id = message.chat.id;
        self.send_message(&chat_id, text, None, None, None, Some(&message_id))
    }

    /// API call which will forward a message.
    pub fn forward_messge(&self,
                          update: &Update,
                          chat_id: &i32,
                          disable_notification: Option<&bool>)
                          -> Result<Message> {
        let message = update.clone().message.unwrap();
        let chat_id: &str = &chat_id.to_string();
        let from_chat_id: &str = &message.chat.id.to_string();
        let message_id: &str = &message.message_id.to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let path = ["forwardMessage"];
        let params = [("chat_id", chat_id),
                      ("from_chat_id", from_chat_id),
                      ("disable_notification", disable_notification),
                      ("message_id", message_id)];
        self.post_message(&path, &params)
    }

    /// The actual networking done for sending messages.
    fn post_message(&self, path: &[&str], params: &[(&str, &str)]) -> Result<Message> {
        let url = ::construct_api_url(&self.bot_url, path);
        let mut data = self.client.post(&url).form(&params).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let message_json = rjson.get("result").ok_or(JsonNotFound)?;
        let message: Message = serde_json::from_value(message_json.clone())?;
        Ok(message)
    }
}
<commit_msg>Removing brackets around single import<commit_after>use serde_json;
use serde_json::Value;

use bot::parse_mode::{get_parse_mode, ParseMode};
use error::Error::JsonNotFound;
use error::{Result, check_for_error};
use objects::{Update, Message};
use bot::Bot;

impl Bot {
    /// API call which will send a message to a chat which your bot participates in.
    pub fn send_message(&self,
                        chat_id: &i64,
                        text: &str,
                        parse_mode: Option<&ParseMode>,
                        disable_web_page_preview: Option<&bool>,
                        disable_notification: Option<&bool>,
                        reply_to_message_id: Option<&i64>)
                        -> Result<Message> {
        let chat_id: &str = &chat_id.to_string();
        let parse_mode = &get_parse_mode(parse_mode.unwrap_or(&ParseMode::Text));
        let disable_web_page_preview: &str = &disable_web_page_preview.unwrap_or(&false)
            .to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let reply_to_message_id: &str = &reply_to_message_id.map(|i| i.to_string())
            .unwrap_or("None".to_string());
        let path = ["sendMessage"];
        let params = [("chat_id", chat_id),
                      ("text", text),
                      ("parse_mode", parse_mode),
                      ("disable_web_page_preview", disable_web_page_preview),
                      ("disable_notification", disable_notification),
                      ("reply_to_message_id", reply_to_message_id)];
        self.post_message(&path, &params)
    }

    /// API call which will reply to a message directed to your bot.
    pub fn reply_to_message(&self, update: &Update, text: &str) -> Result<Message> {
        let message = update.clone().message.unwrap();
        let message_id = message.message_id;
        let chat_id = message.chat.id;
        self.send_message(&chat_id, text, None, None, None, Some(&message_id))
    }

    /// API call which will forward a message.
    pub fn forward_messge(&self,
                          update: &Update,
                          chat_id: &i32,
                          disable_notification: Option<&bool>)
                          -> Result<Message> {
        let message = update.clone().message.unwrap();
        let chat_id: &str = &chat_id.to_string();
        let from_chat_id: &str = &message.chat.id.to_string();
        let message_id: &str = &message.message_id.to_string();
        let disable_notification: &str = &disable_notification.unwrap_or(&false).to_string();
        let path = ["forwardMessage"];
        let params = [("chat_id", chat_id),
                      ("from_chat_id", from_chat_id),
                      ("disable_notification", disable_notification),
                      ("message_id", message_id)];
        self.post_message(&path, &params)
    }

    /// The actual networking done for sending messages.
    fn post_message(&self, path: &[&str], params: &[(&str, &str)]) -> Result<Message> {
        let url = ::construct_api_url(&self.bot_url, path);
        let mut data = self.client.post(&url).form(&params).send()?;
        let rjson: Value = check_for_error(data.json()?)?;
        let message_json = rjson.get("result").ok_or(JsonNotFound)?;
        let message: Message = serde_json::from_value(message_json.clone())?;
        Ok(message)
    }
}
<|endoftext|>


<commit_before>use image::RgbaImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;

pub fn encode_rgba<R: Rng>(source: &mut RgbaImage, payload: &[u8], mode: RgbaMode, mut rng: R)
{
    // number of pixels per byte
    let ppb = match mode
    {
        // 1 values per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // 4 values per pixel = 2 pixels per byte
        RgbaMode::Each => 2,
    };

    for (mut pixels, byte) in source.pixels_mut() // iterate pixels mutably
        .chunks(ppb).into_iter()              // split them into ppb-size chunks
        .map(|ch| ch.collect::<Vec<_>>())     // make them vectors so we can check their lengths later
        .zip(payload.iter().map(|x| *x))      // give each chunk a byte
    {
        // if the pixels don't fit exactly into their chunks,
        // the last chunk will be short. we won't use that chunk
        // (making sure the payload fits into the image is not
        // this functions job!)
        if pixels.len() != ppb
        {
            return;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                for (i, px) in pixels.into_iter().enumerate()
                {
                    // a true, or 1 bit
                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if px.data[3] % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if px.data[3] == 0
                            {
                                px.data[3] = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if px.data[3] % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if px.data[3] == 255
                            {
                                px.data[3] = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                }
            },
            RgbaMode::Each =>
            {
                for i in 0..8
                {
                    let val = if i < 4
                    {
                        &mut pixels[0].data[i]
                    }
                    else
                    {
                        &mut pixels[1].data[i - 4]
                    };

                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if *val % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if *val == 0
                            {
                                *val = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if *val % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if *val == 255
                            {
                                *val = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                }
            },
        }
    }
}

pub fn decode_rgba(source: &RgbaImage, mode: RgbaMode) -> Vec<u8>
{
    // pixels per byte
    let ppb: usize = match mode
    {
        // one value per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // four values per pixel = 2 pixels per byte
        RgbaMode::Each => 2,
    };

    let mut buf = Vec::with_capacity(source.width() as usize* source.height() as usize/ ppb);

    for pixels in source.pixels()         // iterate pixels
        .chunks(ppb).into_iter()          // split into ppb-sized chunks
        .map(|ch| ch.collect::<Vec<_>>()) // make them vectors so we can check their lengths
    {
        // only decode while we have enough data
        if pixels.len() != ppb
        {
            break;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                let mut byte = 0u8;

                for (i, px) in pixels.into_iter().enumerate()
                {
                    byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                }

                buf.push(byte)
            },
            RgbaMode::Each =>
            {
                let mut byte = 0u8;

                for i in 0..8
                {
                    let val = if i < 4
                    {
                        pixels[0].data[i]
                    }
                    else
                    {
                        pixels[1].data[i - 4]
                    };

                    set_bit(byte, i as u8, val % 2 == 1);
                }
            }
        }
    }

    buf

}

/// The encoding/decoding mode
#[derive(Copy, Clone)]
pub enum RgbaMode
{
    /// encode in alpha even/odd
    Alpha,
    /// encode in each field even/odd
    Each,
}

use std::default::Default;

impl Default for RgbaMode
{
    fn default() -> RgbaMode
    {
        RgbaMode::Alpha
    }
}

#[cfg(test)]
mod test
{
    use image::{ImageBuffer, Rgba};
    use rand::StdRng;

    use super::*;

    #[test]
    fn alpha()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            8,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::Alpha, rng);

        let dec = decode_rgba(&image, RgbaMode::Alpha);

        assert_eq!(payload, dec);
    }
}
<commit_msg>Added tests for each encoding/decoding for rgba<commit_after>use image::RgbaImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;

pub fn encode_rgba<R: Rng>(source: &mut RgbaImage, payload: &[u8], mode: RgbaMode, mut rng: R)
{
    // number of pixels per byte
    let ppb = match mode
    {
        // 1 values per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // 4 values per pixel = 2 pixels per byte
        RgbaMode::Each => 2,
    };

    for (mut pixels, byte) in source.pixels_mut() // iterate pixels mutably
        .chunks(ppb).into_iter()              // split them into ppb-size chunks
        .map(|ch| ch.collect::<Vec<_>>())     // make them vectors so we can check their lengths later
        .zip(payload.iter().map(|x| *x))      // give each chunk a byte
    {
        // if the pixels don't fit exactly into their chunks,
        // the last chunk will be short. we won't use that chunk
        // (making sure the payload fits into the image is not
        // this functions job!)
        if pixels.len() != ppb
        {
            return;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                for (i, px) in pixels.into_iter().enumerate()
                {
                    // a true, or 1 bit
                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if px.data[3] % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if px.data[3] == 0
                            {
                                px.data[3] = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if px.data[3] % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if px.data[3] == 255
                            {
                                px.data[3] = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                }
            },
            RgbaMode::Each =>
            {
                for i in 0..8
                {
                    let val = if i < 4
                    {
                        &mut pixels[0].data[i]
                    }
                    else
                    {
                        &mut pixels[1].data[i - 4]
                    };

                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if *val % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if *val == 0
                            {
                                *val = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if *val % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if *val == 255
                            {
                                *val = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                }
            },
        }
    }
}

pub fn decode_rgba(source: &RgbaImage, mode: RgbaMode) -> Vec<u8>
{
    // pixels per byte
    let ppb: usize = match mode
    {
        // one value per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // four values per pixel = 2 pixels per byte
        RgbaMode::Each => 2,
    };

    let mut buf = Vec::with_capacity(source.width() as usize* source.height() as usize/ ppb);

    for pixels in source.pixels()         // iterate pixels
        .chunks(ppb).into_iter()          // split into ppb-sized chunks
        .map(|ch| ch.collect::<Vec<_>>()) // make them vectors so we can check their lengths
    {
        // only decode while we have enough data
        if pixels.len() != ppb
        {
            break;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                let mut byte = 0u8;

                for (i, px) in pixels.into_iter().enumerate()
                {
                    byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                }

                buf.push(byte)
            },
            RgbaMode::Each =>
            {
                let mut byte = 0u8;

                for i in 0..8
                {
                    let val = if i < 4
                    {
                        pixels[0].data[i]
                    }
                    else
                    {
                        pixels[1].data[i - 4]
                    };

                    byte = set_bit(byte, i as u8, val % 2 == 1);
                }

                buf.push(byte);
            }
        }
    }

    buf

}

/// The encoding/decoding mode
#[derive(Copy, Clone)]
pub enum RgbaMode
{
    /// encode in alpha even/odd
    Alpha,
    /// encode in each field even/odd
    Each,
}

use std::default::Default;

impl Default for RgbaMode
{
    fn default() -> RgbaMode
    {
        RgbaMode::Alpha
    }
}

#[cfg(test)]
mod test
{
    use image::{ImageBuffer, Rgba};
    use rand::StdRng;

    use super::*;

    #[test]
    fn alpha()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            8,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::Alpha, rng);

        let dec = decode_rgba(&image, RgbaMode::Alpha);

        assert_eq!(payload, dec);
    }

    #[test]
    fn each()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            2,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::Each, rng);

        let dec = decode_rgba(&image, RgbaMode::Each);

        assert_eq!(payload, dec);
    }
}
<|endoftext|>


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

use std::rand::{Rand, Rng, SeedableRng, XorShiftRng};
use std::num::SignedInt;

use math;

const TABLE_SIZE: usize = 256;

/// A noise seed, required by all noise functions. In most circumstances, you'll
/// only want to create one of these and use it everywhere.
#[allow(missing_copy_implementations)]
pub struct Seed {
    values: [u8; TABLE_SIZE],
}

impl Rand for Seed {
    fn rand<R: Rng>(rng: &mut R) -> Seed {
        let mut seq: Vec<u8> = ::std::iter::range_inclusive(0, (TABLE_SIZE - 1) as u8).collect();
        rng.shuffle(&mut *seq);

        // It's unfortunate that this double-initializes the array, but Rust doesn't currently provide a
        // clean way to do this in one pass. Hopefully won't matter, as Seed creation will usually be a
        // one-time event.
        let mut seed = Seed { values: [0; TABLE_SIZE] };
        let seq_it = seq.iter();
        for (x, y) in seed.values.iter_mut().zip(seq_it) { *x = *y }
        seed
    }
}

impl Seed {
    pub fn new(seed: u32) -> Seed {
        let mut rng: XorShiftRng = SeedableRng::from_seed([1, seed, seed, seed]);
        rng.gen()
    }

    #[inline(always)]
    pub fn get1<T: SignedInt>(&self, x: T) -> usize {
        let x: usize = math::cast(x & math::cast(0xff));
        self.values[x] as usize
    }

    #[inline(always)]
    pub fn get2<T: SignedInt>(&self, pos: math::Point2<T>) -> usize {
        let y: usize = math::cast(pos[1] & math::cast(0xff));
        self.values[self.get1(pos[0]) ^ y] as usize
    }

    #[inline(always)]
    pub fn get3<T: SignedInt>(&self, pos: math::Point3<T>) -> usize {
        let z: usize = math::cast(pos[2] & math::cast(0xff));
        self.values[self.get2([pos[0], pos[1]]) ^ z] as usize
    }

    #[inline(always)]
    pub fn get4<T: SignedInt>(&self, pos: math::Point4<T>) -> usize {
        let w: usize = math::cast(pos[3] & math::cast(0xff));
        self.values[self.get3([pos[0], pos[1], pos[2]]) ^ w] as usize
    }
}

#[cfg(test)]
mod tests {
    use std::rand::random;
    use perlin::perlin3;
    use super::Seed;

    #[test]
    fn test_random_seed() {
        let _ = perlin3::<f32>(&random(), &[1.0, 2.0, 3.0]);
    }

    #[test]
    fn test_negative_params() {
        let _ = perlin3::<f32>(&Seed::new(0), &[-1.0, 2.0, 3.0]);
    }
}
<commit_msg>Expand documentation for Seed type and methods<commit_after>// Copyright 2015 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rand::{Rand, Rng, SeedableRng, XorShiftRng};
use std::num::SignedInt;

use math;

const TABLE_SIZE: usize = 256;

/// A seed table, required by all noise functions.
///
/// Table creation is expensive, so in most circumstances you'll only want to
/// create one of these and reuse it everywhere.
#[allow(missing_copy_implementations)]
pub struct Seed {
    values: [u8; TABLE_SIZE],
}

impl Rand for Seed {
    /// Generates a random seed.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use noise::Seed;
    /// use std::rand;
    ///
    /// let seed = rand::random::<Seed>();
    /// ```
    ///
    /// ```rust
    /// use noise::Seed;
    /// use std::rand::{SeedableRng, Rng, XorShiftRng};
    ///
    /// let mut rng: XorShiftRng = SeedableRng::from_seed([1, 2, 3, 4]);
    /// let seed = rng.gen::<Seed>();
    /// ```
    fn rand<R: Rng>(rng: &mut R) -> Seed {
        let mut seq: Vec<u8> = ::std::iter::range_inclusive(0, (TABLE_SIZE - 1) as u8).collect();
        rng.shuffle(&mut *seq);

        // It's unfortunate that this double-initializes the array, but Rust doesn't currently provide a
        // clean way to do this in one pass. Hopefully won't matter, as Seed creation will usually be a
        // one-time event.
        let mut seed = Seed { values: [0; TABLE_SIZE] };
        let seq_it = seq.iter();
        for (x, y) in seed.values.iter_mut().zip(seq_it) { *x = *y }
        seed
    }
}

impl Seed {
    /// Deterministically generates a new seed table based on a `u32` value.
    ///
    /// Internally this uses a `XorShiftRng`, but we don't really need to worry
    /// about cryptographic security when working with procedural noise.
    ///
    /// # Example
    ///
    /// ```rust
    /// use noise::Seed;
    ///
    /// let seed = Seed::new(12);
    /// ```
    pub fn new(seed: u32) -> Seed {
        let mut rng: XorShiftRng = SeedableRng::from_seed([1, seed, seed, seed]);
        rng.gen()
    }

    #[inline(always)]
    pub fn get1<T: SignedInt>(&self, x: T) -> usize {
        let x: usize = math::cast(x & math::cast(0xff));
        self.values[x] as usize
    }

    #[inline(always)]
    pub fn get2<T: SignedInt>(&self, pos: math::Point2<T>) -> usize {
        let y: usize = math::cast(pos[1] & math::cast(0xff));
        self.values[self.get1(pos[0]) ^ y] as usize
    }

    #[inline(always)]
    pub fn get3<T: SignedInt>(&self, pos: math::Point3<T>) -> usize {
        let z: usize = math::cast(pos[2] & math::cast(0xff));
        self.values[self.get2([pos[0], pos[1]]) ^ z] as usize
    }

    #[inline(always)]
    pub fn get4<T: SignedInt>(&self, pos: math::Point4<T>) -> usize {
        let w: usize = math::cast(pos[3] & math::cast(0xff));
        self.values[self.get3([pos[0], pos[1], pos[2]]) ^ w] as usize
    }
}

#[cfg(test)]
mod tests {
    use std::rand::random;
    use perlin::perlin3;
    use super::Seed;

    #[test]
    fn test_random_seed() {
        let _ = perlin3::<f32>(&random(), &[1.0, 2.0, 3.0]);
    }

    #[test]
    fn test_negative_params() {
        let _ = perlin3::<f32>(&Seed::new(0), &[-1.0, 2.0, 3.0]);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use super::atom::Atom;
use super::parser;
use super::token::{Token, Tokenizer, CurlyAroundTokenizer};
use std::collections::BTreeMap;

#[derive(Debug, PartialEq, Clone)]
pub enum Sexp {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Sexp>),

    // [ ... ]
    Array(Vec<Sexp>),

    // { key val ... }
    Map(Vec<(Sexp, Sexp)>),
}

impl Sexp {
    pub fn is_atom(&self) -> bool {
        match self {
            &Sexp::Atom(..) => true,
            _ => false,
        }
    }

    pub fn is_flat(&self) -> bool {
        match self {
            &Sexp::Atom(..) => true,
            &Sexp::Tuple(ref vec) => vec.iter().all(Sexp::is_atom),
            &Sexp::Array(ref vec) => vec.iter().all(Sexp::is_atom),
            &Sexp::Map(ref vec) => vec.iter().all(|e| e.0.is_atom() && e.1.is_atom()),
        }
    }

    /// Converts a Sexp::Map into a BTreeMap<String, Sexp> if possible.
    pub fn into_map(self) -> Result<BTreeMap<String, Sexp>, &'static str> {
        match self {
            Sexp::Map(pairs) => {
                let mut map = BTreeMap::new();
                for (key, val) in pairs {
                    match key {
                        Sexp::Atom(Atom::Str(s)) => {
                            if map.insert(s, val).is_some() {
                                return Err("duplicate key");
                            }
                        }
                        _ => return Err("key has to be a string"),
                    }
                }
                return Ok(map);
            }
            _ => Err("expr is not a Sexp::Map"),
        }
    }

    pub fn get_uint(&self) -> Option<u64> {
        match self {
            &Sexp::Atom(Atom::UInt(u)) => Some(u),
            _ => None,
        }
    }

    pub fn get_int(&self) -> Option<i64> {
        match self {
            &Sexp::Atom(Atom::SInt(s)) => Some(s),
            _ => None,
        }
    }

    pub fn get_float(&self) -> Option<f64> {
        match self {
            &Sexp::Atom(Atom::Float(f)) => Some(f),
            _ => None,
        }
    }

    pub fn get_str(&self) -> Option<&str> {
        match self {
            &Sexp::Atom(Atom::Str(ref s)) => Some(s),
            _ => None,
        }
    }

    pub fn get_vec<'a, F, R>(&'a self, f: F) -> Option<Vec<R>>
        where F: Fn(&'a Sexp) -> Option<R>
    {
        match self {
            &Sexp::Array(ref ary) => {
                let mut a = Vec::new();
                for elm in ary.iter() {
                    if let Some(u) = f(elm) {
                        a.push(u);
                    } else {
                        return None;
                    }
                }
                Some(a)
            }
            _ => None,
        }
    }

    pub fn get_uint_vec(&self) -> Option<Vec<u64>> {
        self.get_vec(|elm| elm.get_uint())
    }

    pub fn parse_iter<'a, I>(mut iter: I) -> Result<Sexp, ()>
        where I: Iterator<Item = Token<'a>>
    {
        if let Ok(expr) = parser::parse_sexp(&mut iter) {
            if parser::at_end(&mut iter) {
                return Ok(expr);
            }
        }
        Err(())
    }

    pub fn parse(s: &str) -> Result<Sexp, ()> {
        Sexp::parse_iter(Tokenizer::new(s, true))
    }

    pub fn parse_toplevel(s: &str) -> Result<Sexp, ()> {
        Sexp::parse_iter(CurlyAroundTokenizer::new(Tokenizer::new(s, true)))
    }
}

impl<T> From<T> for Sexp where T: Into<Atom>
{
    fn from(t: T) -> Sexp {
        Sexp::Atom(t.into())
    }
}

impl From<()> for Sexp {
    fn from(_e: ()) -> Sexp {
        Sexp::Tuple(vec![])
    }
}

impl<A> From<(A,)> for Sexp where A: Into<Sexp>
{
    fn from(e: (A,)) -> Sexp {
        Sexp::Tuple(vec![e.0.into()])
    }
}

impl<A, B> From<(A, B)> for Sexp
    where A: Into<Sexp>,
          B: Into<Sexp>
{
    fn from(e: (A, B)) -> Sexp {
        Sexp::Tuple(vec![e.0.into(), e.1.into()])
    }
}

impl<A, B, C> From<(A, B, C)> for Sexp
    where A: Into<Sexp>,
          B: Into<Sexp>,
          C: Into<Sexp>
{
    fn from(e: (A, B, C)) -> Sexp {
        Sexp::Tuple(vec![e.0.into(), e.1.into(), e.2.into()])
    }
}

impl<A, B, C, D> From<(A, B, C, D)> for Sexp
    where A: Into<Sexp>,
          B: Into<Sexp>,
          C: Into<Sexp>,
          D: Into<Sexp>
{
    fn from(e: (A, B, C, D)) -> Sexp {
        Sexp::Tuple(vec![e.0.into(), e.1.into(), e.2.into(), e.3.into()])
    }
}

impl<A> From<Vec<A>> for Sexp where A: Into<Sexp>
{
    fn from(arr: Vec<A>) -> Sexp {
        Sexp::Array(arr.into_iter().map(|e| e.into()).collect())
    }
}

pub fn prettyprint<W: fmt::Write>(sexp: &Sexp,
                                  f: &mut W,
                                  indent: usize,
                                  newline: bool)
                                  -> Result<(), fmt::Error> {
    use std::cmp;

    if newline {
        try!(write!(f, "\n"));
        for _ in 0..cmp::min(4, indent) {
            try!(write!(f, "{:>4}", ""));
        }
    }

    match *sexp {
        Sexp::Atom(ref a) => write!(f, "{}", a),
        Sexp::Tuple(ref t) => {
            try!(write!(f, "("));
            for (i, expr) in t.iter().enumerate() {
                if i > 0 {
                    try!(write!(f, " "));
                }
                try!(prettyprint(expr, f, indent, false));
            }
            write!(f, ")")
        }
        Sexp::Array(ref t) => {
            if sexp.is_flat() && t.len() < 5 {
                write!(f, "{}", sexp)
            } else {
                try!(write!(f, "["));
                for (_, expr) in t.iter().enumerate() {
                    try!(prettyprint(expr, f, indent + 1, true));
                }
                write!(f, "]")
            }
        }
        Sexp::Map(ref t) => {
            try!(write!(f, "{}", "{"));
            for (i, expr) in t.iter().enumerate() {
                if i > 0 {
                    try!(write!(f, " "));
                }
                try!(prettyprint(&expr.0, f, indent, false));
                try!(write!(f, " "));
                try!(prettyprint(&expr.1, f, indent, false));
            }
            write!(f, "{}", "}")
        }
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Sexp::Atom(ref a) => write!(f, "{}", a),
            Sexp::Tuple(ref t) => {
                try!(write!(f, "("));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, ")")
            }
            Sexp::Array(ref t) => {
                try!(write!(f, "["));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, "]")
            }
            Sexp::Map(ref t) => {
                try!(write!(f, "{}", "{"));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{} {}", space, expr.0, expr.1));
                }
                write!(f, "{}", "}")
            }
        }
    }
}

#[test]
fn test_display() {
    assert_eq!("12345", &format!("{}", Sexp::Atom(Atom::UInt(12345))));
    assert_eq!("1.0", &format!("{}", Sexp::Atom(Atom::Float(1.0))));

    assert_eq!("(12345)",
               &format!("{}", Sexp::Tuple(vec![Sexp::Atom(Atom::UInt(12345))])));
    assert_eq!("(12345 abc)",
               &format!("{}",
                        Sexp::Tuple(vec![Sexp::Atom(Atom::UInt(12345)),
                                         Sexp::Atom(Atom::Str("abc".to_string()))])));
    assert_eq!("(12345 (abc))",
               &format!("{}",
                        Sexp::Tuple(vec![Sexp::Atom(Atom::UInt(12345)),
                                         Sexp::Tuple(vec![
                                         Sexp::Atom(Atom::Str("abc".to_string()))
                                         ])])));

}

#[test]
fn test_from() {
    assert_eq!(Sexp::Atom(Atom::UInt(123)), Sexp::from(123u64));
    assert_eq!(Sexp::Atom(Atom::SInt(123)), Sexp::from(123i64));
    assert_eq!(Sexp::Atom(Atom::Str("test".to_string())),
               Sexp::from("test"));
    assert_eq!(Sexp::Atom(Atom::Float(123.45)), Sexp::from(123.45));
    assert_eq!(Sexp::Tuple(vec![Sexp::Atom(Atom::Float(123.45))]),
               Sexp::from((123.45,)));
    assert_eq!(Sexp::Array(vec![Sexp::Atom(Atom::Float(123.45))]),
               Sexp::from(vec![123.45]));

}

#[test]
fn test_parse() {
    assert_eq!(Ok(Sexp::from(("abc", 123u64, ("-", 123.43, 11.0)))),
               Sexp::parse("(abc 123 (- 123.43 11.0))"));
}

#[test]
fn test_parse_toplevel() {
    assert_eq!(Sexp::parse("{a 1 b 2}"), Sexp::parse_toplevel("a 1 b 2"));
}

#[test]
fn test_map() {
    let map = Sexp::parse("{a 1 b 2}").unwrap().into_map().unwrap();
    assert_eq!(true, map.contains_key("a"));
    assert_eq!(true, map.contains_key("b"));
    assert_eq!(false, map.contains_key("c"));

    assert_eq!(Err("duplicate key"),
               Sexp::parse("{a 1 b 2 a 1}").unwrap().into_map());
    assert_eq!(Err("key has to be a string"),
               Sexp::parse("{1 1 b 2 a 1}").unwrap().into_map());

}
<commit_msg>Prettyprint: Allow deeper neesting. Display each key/value pair of a map on new line.<commit_after>use std::fmt;
use super::atom::Atom;
use super::parser;
use super::token::{Token, Tokenizer, CurlyAroundTokenizer};
use std::collections::BTreeMap;

#[derive(Debug, PartialEq, Clone)]
pub enum Sexp {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Sexp>),

    // [ ... ]
    Array(Vec<Sexp>),

    // { key val ... }
    Map(Vec<(Sexp, Sexp)>),
}

impl Sexp {
    pub fn is_atom(&self) -> bool {
        match self {
            &Sexp::Atom(..) => true,
            _ => false,
        }
    }

    pub fn is_flat(&self) -> bool {
        match self {
            &Sexp::Atom(..) => true,
            &Sexp::Tuple(ref vec) => vec.iter().all(Sexp::is_atom),
            &Sexp::Array(ref vec) => vec.iter().all(Sexp::is_atom),
            &Sexp::Map(ref vec) => vec.iter().all(|e| e.0.is_atom() && e.1.is_atom()),
        }
    }

    /// Converts a Sexp::Map into a BTreeMap<String, Sexp> if possible.
    pub fn into_map(self) -> Result<BTreeMap<String, Sexp>, &'static str> {
        match self {
            Sexp::Map(pairs) => {
                let mut map = BTreeMap::new();
                for (key, val) in pairs {
                    match key {
                        Sexp::Atom(Atom::Str(s)) => {
                            if map.insert(s, val).is_some() {
                                return Err("duplicate key");
                            }
                        }
                        _ => return Err("key has to be a string"),
                    }
                }
                return Ok(map);
            }
            _ => Err("expr is not a Sexp::Map"),
        }
    }

    pub fn get_uint(&self) -> Option<u64> {
        match self {
            &Sexp::Atom(Atom::UInt(u)) => Some(u),
            _ => None,
        }
    }

    pub fn get_int(&self) -> Option<i64> {
        match self {
            &Sexp::Atom(Atom::SInt(s)) => Some(s),
            _ => None,
        }
    }

    pub fn get_float(&self) -> Option<f64> {
        match self {
            &Sexp::Atom(Atom::Float(f)) => Some(f),
            _ => None,
        }
    }

    pub fn get_str(&self) -> Option<&str> {
        match self {
            &Sexp::Atom(Atom::Str(ref s)) => Some(s),
            _ => None,
        }
    }

    pub fn get_vec<'a, F, R>(&'a self, f: F) -> Option<Vec<R>>
        where F: Fn(&'a Sexp) -> Option<R>
    {
        match self {
            &Sexp::Array(ref ary) => {
                let mut a = Vec::new();
                for elm in ary.iter() {
                    if let Some(u) = f(elm) {
                        a.push(u);
                    } else {
                        return None;
                    }
                }
                Some(a)
            }
            _ => None,
        }
    }

    pub fn get_uint_vec(&self) -> Option<Vec<u64>> {
        self.get_vec(|elm| elm.get_uint())
    }

    pub fn parse_iter<'a, I>(mut iter: I) -> Result<Sexp, ()>
        where I: Iterator<Item = Token<'a>>
    {
        if let Ok(expr) = parser::parse_sexp(&mut iter) {
            if parser::at_end(&mut iter) {
                return Ok(expr);
            }
        }
        Err(())
    }

    pub fn parse(s: &str) -> Result<Sexp, ()> {
        Sexp::parse_iter(Tokenizer::new(s, true))
    }

    pub fn parse_toplevel(s: &str) -> Result<Sexp, ()> {
        Sexp::parse_iter(CurlyAroundTokenizer::new(Tokenizer::new(s, true)))
    }
}

impl<T> From<T> for Sexp where T: Into<Atom>
{
    fn from(t: T) -> Sexp {
        Sexp::Atom(t.into())
    }
}

impl From<()> for Sexp {
    fn from(_e: ()) -> Sexp {
        Sexp::Tuple(vec![])
    }
}

impl<A> From<(A,)> for Sexp where A: Into<Sexp>
{
    fn from(e: (A,)) -> Sexp {
        Sexp::Tuple(vec![e.0.into()])
    }
}

impl<A, B> From<(A, B)> for Sexp
    where A: Into<Sexp>,
          B: Into<Sexp>
{
    fn from(e: (A, B)) -> Sexp {
        Sexp::Tuple(vec![e.0.into(), e.1.into()])
    }
}

impl<A, B, C> From<(A, B, C)> for Sexp
    where A: Into<Sexp>,
          B: Into<Sexp>,
          C: Into<Sexp>
{
    fn from(e: (A, B, C)) -> Sexp {
        Sexp::Tuple(vec![e.0.into(), e.1.into(), e.2.into()])
    }
}

impl<A, B, C, D> From<(A, B, C, D)> for Sexp
    where A: Into<Sexp>,
          B: Into<Sexp>,
          C: Into<Sexp>,
          D: Into<Sexp>
{
    fn from(e: (A, B, C, D)) -> Sexp {
        Sexp::Tuple(vec![e.0.into(), e.1.into(), e.2.into(), e.3.into()])
    }
}

impl<A> From<Vec<A>> for Sexp where A: Into<Sexp>
{
    fn from(arr: Vec<A>) -> Sexp {
        Sexp::Array(arr.into_iter().map(|e| e.into()).collect())
    }
}

pub fn prettyprint<W: fmt::Write>(sexp: &Sexp,
                                  f: &mut W,
                                  indent: usize,
                                  newline: bool)
                                  -> Result<(), fmt::Error> {
    use std::cmp;

    if newline {
        try!(write!(f, "\n"));
        for _ in 0..cmp::min(8, indent) {
            try!(write!(f, "{:>4}", ""));
        }
    }

    match *sexp {
        Sexp::Atom(ref a) => write!(f, "{}", a),
        Sexp::Tuple(ref t) => {
            try!(write!(f, "("));
            for (i, expr) in t.iter().enumerate() {
                if i > 0 {
                    try!(write!(f, " "));
                }
                try!(prettyprint(expr, f, indent, false));
            }
            write!(f, ")")
        }
        Sexp::Array(ref t) => {
            if sexp.is_flat() && t.len() < 5 {
                write!(f, "{}", sexp)
            } else {
                try!(write!(f, "["));
                for (_, expr) in t.iter().enumerate() {
                    try!(prettyprint(expr, f, indent + 1, true));
                }
                write!(f, "]")
            }
        }
        Sexp::Map(ref t) => {
            try!(write!(f, "{}", "{"));
            for (_, expr) in t.iter().enumerate() {
                try!(prettyprint(&expr.0, f, indent + 1, true));
                try!(write!(f, " "));
                try!(prettyprint(&expr.1, f, indent + 1, false));
            }
            try!(write!(f, "\n"));
            for _ in 0..cmp::min(8, indent) {
                try!(write!(f, "{:>4}", ""));
            }
            write!(f, "{}", "}")
        }
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Sexp::Atom(ref a) => write!(f, "{}", a),
            Sexp::Tuple(ref t) => {
                try!(write!(f, "("));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, ")")
            }
            Sexp::Array(ref t) => {
                try!(write!(f, "["));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, "]")
            }
            Sexp::Map(ref t) => {
                try!(write!(f, "{}", "{"));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{} {}", space, expr.0, expr.1));
                }
                write!(f, "{}", "}")
            }
        }
    }
}

#[test]
fn test_display() {
    assert_eq!("12345", &format!("{}", Sexp::Atom(Atom::UInt(12345))));
    assert_eq!("1.0", &format!("{}", Sexp::Atom(Atom::Float(1.0))));

    assert_eq!("(12345)",
               &format!("{}", Sexp::Tuple(vec![Sexp::Atom(Atom::UInt(12345))])));
    assert_eq!("(12345 abc)",
               &format!("{}",
                        Sexp::Tuple(vec![Sexp::Atom(Atom::UInt(12345)),
                                         Sexp::Atom(Atom::Str("abc".to_string()))])));
    assert_eq!("(12345 (abc))",
               &format!("{}",
                        Sexp::Tuple(vec![Sexp::Atom(Atom::UInt(12345)),
                                         Sexp::Tuple(vec![
                                         Sexp::Atom(Atom::Str("abc".to_string()))
                                         ])])));

}

#[test]
fn test_from() {
    assert_eq!(Sexp::Atom(Atom::UInt(123)), Sexp::from(123u64));
    assert_eq!(Sexp::Atom(Atom::SInt(123)), Sexp::from(123i64));
    assert_eq!(Sexp::Atom(Atom::Str("test".to_string())),
               Sexp::from("test"));
    assert_eq!(Sexp::Atom(Atom::Float(123.45)), Sexp::from(123.45));
    assert_eq!(Sexp::Tuple(vec![Sexp::Atom(Atom::Float(123.45))]),
               Sexp::from((123.45,)));
    assert_eq!(Sexp::Array(vec![Sexp::Atom(Atom::Float(123.45))]),
               Sexp::from(vec![123.45]));

}

#[test]
fn test_parse() {
    assert_eq!(Ok(Sexp::from(("abc", 123u64, ("-", 123.43, 11.0)))),
               Sexp::parse("(abc 123 (- 123.43 11.0))"));
}

#[test]
fn test_parse_toplevel() {
    assert_eq!(Sexp::parse("{a 1 b 2}"), Sexp::parse_toplevel("a 1 b 2"));
}

#[test]
fn test_map() {
    let map = Sexp::parse("{a 1 b 2}").unwrap().into_map().unwrap();
    assert_eq!(true, map.contains_key("a"));
    assert_eq!(true, map.contains_key("b"));
    assert_eq!(false, map.contains_key("c"));

    assert_eq!(Err("duplicate key"),
               Sexp::parse("{a 1 b 2 a 1}").unwrap().into_map());
    assert_eq!(Err("key has to be a string"),
               Sexp::parse("{1 1 b 2 a 1}").unwrap().into_map());

}
<|endoftext|>