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

// FIXME: switch to something more ergonomic here, once available.
// (currently there is no way to opt into sysroot crates w/o `extern crate`)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_plugin;
use self::rustc_driver::{driver::CompileController, Compilation};

use std::convert::TryInto;
use std::path::Path;
use std::process::{exit, Command};

fn show_version() {
    println!(env!("CARGO_PKG_VERSION"));
}

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]
pub fn main() {
    rustc_driver::init_rustc_env_logger();
    exit(
        rustc_driver::run(move || {
            use std::env;

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

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(std::string::ToString::to_string)
                .or_else(|| std::env::var("SYSROOT").ok())
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| s.trim().to_owned())
                })
                .or_else(|| option_env!("SYSROOT").map(String::from))
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

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

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

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

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

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

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

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

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

            let args = args;
            rustc_driver::run_compiler(&args, Box::new(controller), None, None)
        })
        .try_into()
        .expect("exit code too large"),
    )
}
<commit_msg>Auto merge of #3733 - Zoxc:rustc-interface, r=oli-obk<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(clippy::missing_docs_in_private_items)]

// FIXME: switch to something more ergonomic here, once available.
// (currently there is no way to opt into sysroot crates w/o `extern crate`)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_interface;
#[allow(unused_extern_crates)]
extern crate rustc_plugin;

use rustc_interface::interface;
use std::path::Path;
use std::process::{exit, Command};

fn show_version() {
    println!(env!("CARGO_PKG_VERSION"));
}

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]

struct ClippyCallbacks;

impl rustc_driver::Callbacks for ClippyCallbacks {
    fn after_parsing(&mut self, compiler: &interface::Compiler) -> bool {
        let sess = compiler.session();
        let mut registry = rustc_plugin::registry::Registry::new(
            sess,
            compiler
                .parse()
                .expect(
                    "at this compilation stage \
                     the crate must be parsed",
                )
                .peek()
                .span,
        );
        registry.args_hidden = Some(Vec::new());

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

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

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

        sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
        sess.plugin_attributes.borrow_mut().extend(attributes);

        // Continue execution
        true
    }
}

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

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

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(std::string::ToString::to_string)
                .or_else(|| std::env::var("SYSROOT").ok())
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| s.trim().to_owned())
                })
                .or_else(|| option_env!("SYSROOT").map(String::from))
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

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

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

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

            let mut clippy = ClippyCallbacks;
            let mut default = rustc_driver::DefaultCallbacks;
            let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
                if clippy_enabled { &mut clippy } else { &mut default };
            let args = args;
            rustc_driver::run_compiler(&args, callbacks, None, None)
        })
        .and_then(|result| result)
        .is_err() as i32,
    )
}
<|endoftext|>


<commit_before>error_chain!{
    foreign_links {
        Fmt(::std::fmt::Error);
        Io(::std::io::Error) #[cfg(unix)];
    }

    errors {
        TooManyData(desc: &'static str) {
            description("Too many data")
            display("Too many data: '{}'", desc)
        }
        InvalidSlaveID(id: u8) {
            description("Invalid slave ID")
            display("Invalid slave ID: '{}'", id)
        }
    }

}
<commit_msg>New Error for incompatible API errors<commit_after>error_chain!{
    foreign_links {
        Fmt(::std::fmt::Error);
        Io(::std::io::Error) #[cfg(unix)];
    }

    errors {
        IncompatibleAPI {
            description("libmodbus API incompatible response")
            display("libmodbus API incompatible response")
        }
        TooManyData(desc: &'static str) {
            description("Too many data")
            display("Too many data: '{}'", desc)
        }
        InvalidSlaveID(id: u8) {
            description("Invalid slave ID")
            display("Invalid slave ID: '{}'", id)
        }
    }

}
<|endoftext|>


<commit_before>use ape;
use core;
use diesel;
use diesel_migrations;
use getopts;
use hyper;
use id3;
use image;
use iron::status::Status;
use iron::IronError;
use lewton;
use metaflac;
use regex;
use rocket;
use rustfm_scrobble;
use serde_json;
use std;
use toml;

error_chain! {
	foreign_links {
		Ape(ape::Error);
		Diesel(diesel::result::Error);
		DieselConnection(diesel::ConnectionError);
		DieselMigration(diesel_migrations::RunMigrationsError);
		Encoding(core::str::Utf8Error);
		Flac(metaflac::Error);
		GetOpts(getopts::Fail);
		Hyper(hyper::Error);
		Id3(id3::Error);
		Image(image::ImageError);
		Io(std::io::Error);
		Json(serde_json::Error);
		Time(std::time::SystemTimeError);
		Toml(toml::de::Error);
		Regex(regex::Error);
		Scrobbler(rustfm_scrobble::ScrobblerError);
		Vorbis(lewton::VorbisError);
	}

	errors {
		DaemonError {}
		AuthenticationRequired {}
		AdminPrivilegeRequired {}
		MissingConfig {}
		MissingPreferences {}
		MissingUsername {}
		MissingPassword {}
		MissingPlaylist {}
		IncorrectCredentials {}
		CannotServeDirectory {}
		UnsupportedFileType {}
		FileNotFound {}
		MissingIndexVersion {}
		MissingPlaylistName {}
		EncodingError {}
		MissingLastFMCredentials {}
		LastFMAuthError {}
		LastFMDeserializationError {}
		MissingDesiredResponse {}
	}
}

impl<'r> rocket::response::Responder<'r> for Error {
	fn respond_to(self, _: &rocket::request::Request) -> rocket::response::Result<'r> {
        let mut build = rocket::response::Response::build();
        build.status(match self.0 {
			ErrorKind::FileNotFound => rocket::http::Status::NotFound,
			_ => rocket::http::Status::InternalServerError,
		}).ok()
    }
}

impl From<Error> for IronError {
	fn from(err: Error) -> IronError {
		match err {
			e @ Error(ErrorKind::AuthenticationRequired, _) => {
				IronError::new(e, Status::Unauthorized)
			}
			e @ Error(ErrorKind::AdminPrivilegeRequired, _) => IronError::new(e, Status::Forbidden),
			e @ Error(ErrorKind::MissingUsername, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::MissingPassword, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::IncorrectCredentials, _) => {
				IronError::new(e, Status::Unauthorized)
			}
			e @ Error(ErrorKind::CannotServeDirectory, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::UnsupportedFileType, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::MissingLastFMCredentials, _) => {
				IronError::new(e, Status::Unauthorized)
			}
			e => IronError::new(e, Status::InternalServerError),
		}
	}
}
<commit_msg>Formatting<commit_after>use ape;
use core;
use diesel;
use diesel_migrations;
use getopts;
use hyper;
use id3;
use image;
use iron::status::Status;
use iron::IronError;
use lewton;
use metaflac;
use regex;
use rocket;
use rustfm_scrobble;
use serde_json;
use std;
use toml;

error_chain! {
	foreign_links {
		Ape(ape::Error);
		Diesel(diesel::result::Error);
		DieselConnection(diesel::ConnectionError);
		DieselMigration(diesel_migrations::RunMigrationsError);
		Encoding(core::str::Utf8Error);
		Flac(metaflac::Error);
		GetOpts(getopts::Fail);
		Hyper(hyper::Error);
		Id3(id3::Error);
		Image(image::ImageError);
		Io(std::io::Error);
		Json(serde_json::Error);
		Time(std::time::SystemTimeError);
		Toml(toml::de::Error);
		Regex(regex::Error);
		Scrobbler(rustfm_scrobble::ScrobblerError);
		Vorbis(lewton::VorbisError);
	}

	errors {
		DaemonError {}
		AuthenticationRequired {}
		AdminPrivilegeRequired {}
		MissingConfig {}
		MissingPreferences {}
		MissingUsername {}
		MissingPassword {}
		MissingPlaylist {}
		IncorrectCredentials {}
		CannotServeDirectory {}
		UnsupportedFileType {}
		FileNotFound {}
		MissingIndexVersion {}
		MissingPlaylistName {}
		EncodingError {}
		MissingLastFMCredentials {}
		LastFMAuthError {}
		LastFMDeserializationError {}
		MissingDesiredResponse {}
	}
}

impl<'r> rocket::response::Responder<'r> for Error {
	fn respond_to(self, _: &rocket::request::Request) -> rocket::response::Result<'r> {
		let mut build = rocket::response::Response::build();
		build
			.status(match self.0 {
				ErrorKind::FileNotFound => rocket::http::Status::NotFound,
				_ => rocket::http::Status::InternalServerError,
			})
			.ok()
	}
}

impl From<Error> for IronError {
	fn from(err: Error) -> IronError {
		match err {
			e @ Error(ErrorKind::AuthenticationRequired, _) => {
				IronError::new(e, Status::Unauthorized)
			}
			e @ Error(ErrorKind::AdminPrivilegeRequired, _) => IronError::new(e, Status::Forbidden),
			e @ Error(ErrorKind::MissingUsername, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::MissingPassword, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::IncorrectCredentials, _) => {
				IronError::new(e, Status::Unauthorized)
			}
			e @ Error(ErrorKind::CannotServeDirectory, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::UnsupportedFileType, _) => IronError::new(e, Status::BadRequest),
			e @ Error(ErrorKind::MissingLastFMCredentials, _) => {
				IronError::new(e, Status::Unauthorized)
			}
			e => IronError::new(e, Status::InternalServerError),
		}
	}
}
<|endoftext|>


<commit_before>use std;
use std::thread;
use std::sync::mpsc;
use num_cpus;
// macro_rules! if_any_divides {
//      ( $( $div:tt ),* | $n:ident $if_b:block ) => { if $(($n % $div == 0))|* $if_b};
// }
// macro_rules! if_sm_prime_divides{
//     ( $n:ident $if_b:block ) => {if_any_divides!(
//     2, 3, 5, 7, 11, 13,
//     17, 19, 23, 29, 31,
//     37, 41, 43, 47, 53,
//     59, 61, 67, 71, 73,
//     79, 83, 89, 97, 101,
//     103, 107, 109, 113, 127,
//     131, 137, 139, 149, 151,
//     157, 163, 167, 173, 179,
//     181, 191, 193, 197, 199 | $n $if_b)};
// }
macro_rules! set_true_if_in_range{
    ( $( $i:tt ),* => $filter:ident + $offset:expr, $min:expr, $max:expr) => {
        $(if ($min <= $i) & ($max > $i) {$filter[$i-$offset] = true;})*
    };
    ( $( $i:tt ),* => $filter:ident, $min:expr, $max:expr) => {
        $(if ($min <= $i) & ($max > $i) {$filter[$i] = true;})*
    };
}
// macro_rules! set_sm_primes_true {
//     ($filter:expr, $min:expr, $max:expr) => {
//         set_true_if_in_range!(
//         2, 3, 5, 7, 11, 13,
//         17, 19, 23, 29, 31,
//         37, 41, 43, 47, 53,
//         59, 61, 67, 71, 73,
//         79, 83, 89, 97, 101,
//         103, 107, 109, 113, 127,
//         131, 137, 139, 149, 151,
//         157, 163, 167, 173, 179,
//         181, 191, 193, 197, 199 => $filter + $min, $min, $max)
//     };
// }
pub fn prime_filter_concurrently(iter_size: usize, threads: usize) -> Vec<bool>{
    prime_filter_section_concurrently(0, iter_size, threads)
}
pub fn prime_filter_section_concurrently(min_num:usize, max_num: usize, threads: usize) -> Vec<bool>{
    let mut res_vec: Vec<Vec<bool>> = vec![vec![]; threads];
    let seg_size = (max_num - min_num)/threads;
    let (tx, rx) = mpsc::channel();
    for i in 0..threads{
        let (tx, min, max) = (tx.clone(), min_num + seg_size*i,
                                min_num + seg_size*(i+1));
        thread::spawn( move || {
            let to_send = match max-min {
                0 => vec![],
                _ => prime_filter_section_sequentially(min, max),
            };
            tx.send((i, to_send)).unwrap();
        });
    }
    if (min_num + seg_size*threads) != max_num {
        res_vec.push(vec![]);
        let (tx, min, max) = (tx.clone(), min_num + seg_size*threads, max_num);
        thread::spawn( move || {
            let to_send = match max-min {
                0 => vec![],
                _ => prime_filter_section_sequentially(min, max),
            };
            tx.send((threads, to_send)).unwrap();
        });

        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    };
    for _ in 0..threads{
        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    }
    res_vec.into_iter().flat_map(|x| x).collect()
}

fn int_sqrt(n:usize) -> usize{
    match n {
        0 => 0,
        1 ... 3 => 1,
        4 ... 8 => 2,
        9 ... 15 => 3,
        k => {
        let mut x = k;
            loop{
                x = match (x + n/x) >> 1 {
                    new_x if new_x == x => break,
                    new_x if new_x*new_x == n + 1 => {x = new_x - 1; break},
                    new_x => new_x,
                };
            }
            x
        },
    }

}

fn ceil_sqrt(n:usize) -> usize{
    match int_sqrt(n){
        sqrt if sqrt*sqrt == n => sqrt,
        sqrt => sqrt+1,
    }
}
pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    prime_filter_concurrently(iter_size, num_cpus::get())
}

pub fn prime_filter_section(min_num:usize, max_num: usize) -> Vec<bool>{
    prime_filter_section_concurrently(min_num, max_num, num_cpus::get())
}

pub fn prime_filter_sequentially(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}
pub fn prime_filter_section_sequentially(min_num:usize, max_num: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min_num<max_num);
    let mut prime_filter = vec![false; max_num-min_num];

    set_true_if_in_range!(2, 3, 5 => prime_filter + min_num, min_num, max_num);
    //Macro equivilent:
    // if (min_num <= 2) & (max_num > 2) {prime_filter[2-min_num] = true;}
    // if (min_num <= 3) & (max_num > 3) {prime_filter[3-min_num] = true;}
    // if (min_num <= 5) & (max_num > 5) {prime_filter[5-min_num] = true;}

    let (mut y_sq, mut to_next_y_sq) = (1, 3);

    while y_sq<max_num {
        if y_sq%2 == 1 {
            //CASE 1
            //n_1 = 4x^2 + y^2 === 1 (mod 4)
            let (mut n_1, mut to_next_n_1) = match y_sq < min_num {
                false => (y_sq+4, 12),
                _ => {
                    let min_num_x = (ceil_sqrt(min_num - y_sq) +1)/2;
                    (4*min_num_x*min_num_x + y_sq, 8*min_num_x + 4)
                },
            };
            loop{

                match n_1{
                    n if n >= max_num => break,
                    n => {match n%60{
                        1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => prime_filter[n-min_num] ^= true,
                        _ => (),
                    };},
                };

                n_1 += to_next_n_1;
                to_next_n_1 += 8;
            };
        };
        if y_sq%3 == 1 {
            //CASE 2
            //n_2 = 3x^2 + y^2 === 1 (mod 6)
            let (mut n_2, mut to_next_n_2) = match y_sq < min_num {
                false => (y_sq+3, 9),
                _ => {
                    let min_num_x = (ceil_sqrt((min_num - y_sq)*3)+2)/3;
                    (3*min_num_x*min_num_x + y_sq, 6*min_num_x + 3)
                },
            };
            loop {
                match n_2{
                    n if n >= max_num => break,
                    n => {match n%60{
                            7 | 19 | 31 | 43 => prime_filter[n-min_num] ^= true,
                            _ => (),
                        };}
                };
                n_2 += to_next_n_2;
                to_next_n_2 += 6;
            };
            //CASE 3
            //n_3 = 3x^2 - y^2 === 11 (mod 12)
            //Initially, we set x = y+1 -> n_3 = 3(y+1)^2 - y^2 = 2*y^2 + 6*y + 3
            //Amd then hop x by 2 each iteration.
            let (mut n_3, mut to_next_n_3) = match (y_sq << 1) < min_num {
                false => (2*y_sq+3*to_next_y_sq, 6*to_next_y_sq+18),
                _ => {
                    let min_num_x = match (ceil_sqrt((min_num + y_sq)*3) +2)/3{
                        mx if (mx+y_sq)%2 == 0 => mx + 1,
                        mx => mx,
                    };
                    (3*min_num_x*min_num_x - y_sq, 12*min_num_x + 12)
                },
            };
            loop {
                match n_3{
                    n if n >= max_num => break,
                    n => {match n%60{
                            11 | 23 | 47 | 59 => prime_filter[n-min_num] ^= true,
                            _ => (),
                    };},
                };
                n_3 += to_next_n_3;
                to_next_n_3 += 24;
            };
        };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };

    //Elimin_numate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max_num {
        let mut non_sq_free = n_sq;
        while non_sq_free < max_num {
            if non_sq_free >= min_num {
                prime_filter[non_sq_free - min_num] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}

#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

#[test]
fn private_filter_test(){
    assert_eq!(5, ceil_sqrt(24));
    assert_eq!(2, int_sqrt(4));
    assert_eq!(4, int_sqrt(24));
    assert_eq!(10, int_sqrt(101));
    assert_eq!(1, int_sqrt(1));
    assert_eq!(10, int_sqrt(100));
    assert_eq!(3, int_sqrt(13));
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<commit_msg>make arg names homogenous<commit_after>use std;
use std::thread;
use std::sync::mpsc;
use num_cpus;
// macro_rules! if_any_divides {
//      ( $( $div:tt ),* | $n:ident $if_b:block ) => { if $(($n % $div == 0))|* $if_b};
// }
// macro_rules! if_sm_prime_divides{
//     ( $n:ident $if_b:block ) => {if_any_divides!(
//     2, 3, 5, 7, 11, 13,
//     17, 19, 23, 29, 31,
//     37, 41, 43, 47, 53,
//     59, 61, 67, 71, 73,
//     79, 83, 89, 97, 101,
//     103, 107, 109, 113, 127,
//     131, 137, 139, 149, 151,
//     157, 163, 167, 173, 179,
//     181, 191, 193, 197, 199 | $n $if_b)};
// }
macro_rules! set_true_if_in_range{
    ( $( $i:tt ),* => $filter:ident + $offset:expr, $min:expr, $max:expr) => {
        $(if ($min <= $i) & ($max > $i) {$filter[$i-$offset] = true;})*
    };
    ( $( $i:tt ),* => $filter:ident, $min:expr, $max:expr) => {
        $(if ($min <= $i) & ($max > $i) {$filter[$i] = true;})*
    };
}
// macro_rules! set_sm_primes_true {
//     ($filter:expr, $min:expr, $max:expr) => {
//         set_true_if_in_range!(
//         2, 3, 5, 7, 11, 13,
//         17, 19, 23, 29, 31,
//         37, 41, 43, 47, 53,
//         59, 61, 67, 71, 73,
//         79, 83, 89, 97, 101,
//         103, 107, 109, 113, 127,
//         131, 137, 139, 149, 151,
//         157, 163, 167, 173, 179,
//         181, 191, 193, 197, 199 => $filter + $min, $min, $max)
//     };
// }
pub fn prime_filter_concurrently(max_num: usize, threads: usize) -> Vec<bool>{
    prime_filter_section_concurrently(0, max_num, threads)
}
pub fn prime_filter_section_concurrently(min_num:usize, max_num: usize, threads: usize) -> Vec<bool>{
    let mut res_vec: Vec<Vec<bool>> = vec![vec![]; threads];
    let seg_size = (max_num - min_num)/threads;
    let (tx, rx) = mpsc::channel();
    for i in 0..threads{
        let (tx, min, max) = (tx.clone(), min_num + seg_size*i,
                                min_num + seg_size*(i+1));
        thread::spawn( move || {
            let to_send = match max-min {
                0 => vec![],
                _ => prime_filter_section_sequentially(min, max),
            };
            tx.send((i, to_send)).unwrap();
        });
    }
    if (min_num + seg_size*threads) != max_num {
        res_vec.push(vec![]);
        let (tx, min, max) = (tx.clone(), min_num + seg_size*threads, max_num);
        thread::spawn( move || {
            let to_send = match max-min {
                0 => vec![],
                _ => prime_filter_section_sequentially(min, max),
            };
            tx.send((threads, to_send)).unwrap();
        });

        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    };
    for _ in 0..threads{
        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    }
    res_vec.into_iter().flat_map(|x| x).collect()
}

fn int_sqrt(n:usize) -> usize{
    match n {
        0 => 0,
        1 ... 3 => 1,
        4 ... 8 => 2,
        9 ... 15 => 3,
        k => {
        let mut x = k;
            loop{
                x = match (x + n/x) >> 1 {
                    new_x if new_x == x => break,
                    new_x if new_x*new_x == n + 1 => {x = new_x - 1; break},
                    new_x => new_x,
                };
            }
            x
        },
    }

}

fn ceil_sqrt(n:usize) -> usize{
    match int_sqrt(n){
        sqrt if sqrt*sqrt == n => sqrt,
        sqrt => sqrt+1,
    }
}
pub fn prime_filter(max_num: usize) -> Vec<bool>{
    prime_filter_concurrently(max_num, num_cpus::get())
}

pub fn prime_filter_section(min_num:usize, max_num: usize) -> Vec<bool>{
    prime_filter_section_concurrently(min_num, max_num, num_cpus::get())
}

pub fn prime_filter_sequentially(max_num: usize) -> Vec<bool>{
    if max_num<100{
        slow_prime_filter(max_num)
    }else{
        prime_filter_section(0, max_num)
    }
}
pub fn prime_filter_section_sequentially(min_num:usize, max_num: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min_num<max_num);
    let mut prime_filter = vec![false; max_num-min_num];

    set_true_if_in_range!(2, 3, 5 => prime_filter + min_num, min_num, max_num);
    //Macro equivilent:
    // if (min_num <= 2) & (max_num > 2) {prime_filter[2-min_num] = true;}
    // if (min_num <= 3) & (max_num > 3) {prime_filter[3-min_num] = true;}
    // if (min_num <= 5) & (max_num > 5) {prime_filter[5-min_num] = true;}

    let (mut y_sq, mut to_next_y_sq) = (1, 3);

    while y_sq<max_num {
        if y_sq%2 == 1 {
            //CASE 1
            //n_1 = 4x^2 + y^2 === 1 (mod 4)
            let (mut n_1, mut to_next_n_1) = match y_sq < min_num {
                false => (y_sq+4, 12),
                _ => {
                    let min_num_x = (ceil_sqrt(min_num - y_sq) +1)/2;
                    (4*min_num_x*min_num_x + y_sq, 8*min_num_x + 4)
                },
            };
            loop{

                match n_1{
                    n if n >= max_num => break,
                    n => {match n%60{
                        1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => prime_filter[n-min_num] ^= true,
                        _ => (),
                    };},
                };

                n_1 += to_next_n_1;
                to_next_n_1 += 8;
            };
        };
        if y_sq%3 == 1 {
            //CASE 2
            //n_2 = 3x^2 + y^2 === 1 (mod 6)
            let (mut n_2, mut to_next_n_2) = match y_sq < min_num {
                false => (y_sq+3, 9),
                _ => {
                    let min_num_x = (ceil_sqrt((min_num - y_sq)*3)+2)/3;
                    (3*min_num_x*min_num_x + y_sq, 6*min_num_x + 3)
                },
            };
            loop {
                match n_2{
                    n if n >= max_num => break,
                    n => {match n%60{
                            7 | 19 | 31 | 43 => prime_filter[n-min_num] ^= true,
                            _ => (),
                        };}
                };
                n_2 += to_next_n_2;
                to_next_n_2 += 6;
            };
            //CASE 3
            //n_3 = 3x^2 - y^2 === 11 (mod 12)
            //Initially, we set x = y+1 -> n_3 = 3(y+1)^2 - y^2 = 2*y^2 + 6*y + 3
            //Amd then hop x by 2 each iteration.
            let (mut n_3, mut to_next_n_3) = match (y_sq << 1) < min_num {
                false => (2*y_sq+3*to_next_y_sq, 6*to_next_y_sq+18),
                _ => {
                    let min_num_x = match (ceil_sqrt((min_num + y_sq)*3) +2)/3{
                        mx if (mx+y_sq)%2 == 0 => mx + 1,
                        mx => mx,
                    };
                    (3*min_num_x*min_num_x - y_sq, 12*min_num_x + 12)
                },
            };
            loop {
                match n_3{
                    n if n >= max_num => break,
                    n => {match n%60{
                            11 | 23 | 47 | 59 => prime_filter[n-min_num] ^= true,
                            _ => (),
                    };},
                };
                n_3 += to_next_n_3;
                to_next_n_3 += 24;
            };
        };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };

    //Elimin_numate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max_num {
        let mut non_sq_free = n_sq;
        while non_sq_free < max_num {
            if non_sq_free >= min_num {
                prime_filter[non_sq_free - min_num] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}

#[cfg(test)]
pub fn old_prime_filter(max_num: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(max_num)
}

#[test]
fn private_filter_test(){
    assert_eq!(5, ceil_sqrt(24));
    assert_eq!(2, int_sqrt(4));
    assert_eq!(4, int_sqrt(24));
    assert_eq!(10, int_sqrt(101));
    assert_eq!(1, int_sqrt(1));
    assert_eq!(10, int_sqrt(100));
    assert_eq!(3, int_sqrt(13));
}

fn slow_prime_filter(max_num: usize) -> std::vec::Vec<bool>{
    if max_num < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(max_num);
         return ret
     }
    let mut prime_filter = vec![true; max_num];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..max_num{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > max_num {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<|endoftext|>


<commit_before>use serde::{Serialize, Deserialize};
use serde;
use serde_json;
use algorithm::*;
use std::collections::HashMap;

#[derive(Clone, Debug, PartialEq)]
/// A basic JWT header part, the alg defaults to HS256 and typ is automatically
/// set to `JWT`. All the other fields are optional
pub struct Header {
    typ: Option<String>,
    pub alg: Algorithm,
    pub jku: Option<String>, // jwk key set url
    pub jwk: Option<String>, // json web key
    pub kid: Option<String>, // key id
    pub x5u: Option<String>, // x509 url
    pub x5c: Option<Vec<String>>, // x509 cert chain
    pub x5t: Option<String>, // x509 cert sha1 thumbprint
    pub x5t_s256: Option<String>, // x509 cert sha256 thumbprint
    pub cty: Option<String>, // payload media type
    pub crit: Option<Vec<String>>, // critical extension params list
    pub custom_params: HashMap<String, serde_json::value::Value>,
}

impl Header {
    pub fn new(algorithm: Algorithm) -> Header {
        Header {
            typ: Some("JWT".to_owned()),
            alg: algorithm,
            jku: None,
            jwk: None,
            kid: None,
            x5u: None,
            x5c: None,
            x5t: None,
            x5t_s256: None,
            cty: None,
            crit: None,
            custom_params: HashMap::new(),
        }
    }
}

impl Default for Header {
    fn default() -> Header {
        Header::new(Algorithm::HS256)
    }
}

impl Serialize for Header {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_map(HeaderSerVisitor(&self))
    }
}

struct HeaderSerVisitor<'a>(&'a Header);

impl<'a> serde::ser::MapVisitor for HeaderSerVisitor<'a> {
    fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
        where S: serde::Serializer
    {
        if self.0.typ.is_some() {
            try!(serializer.serialize_struct_elt("typ", &self.0.typ));
        }

        try!(serializer.serialize_struct_elt("alg", &self.0.alg));

        if self.0.jku.is_some() {
            try!(serializer.serialize_struct_elt("jku", &self.0.jku));
        }

        if self.0.jwk.is_some() {
            try!(serializer.serialize_struct_elt("jwk", &self.0.jwk));
        }

        if self.0.kid.is_some() {
            try!(serializer.serialize_struct_elt("kid", &self.0.kid));
        }

        if self.0.x5u.is_some() {
            try!(serializer.serialize_struct_elt("x5u", &self.0.x5u));
        }

        if self.0.x5c.is_some() {
            try!(serializer.serialize_struct_elt("x5c", &self.0.x5c));
        }

        if self.0.x5t.is_some() {
            try!(serializer.serialize_struct_elt("x5t", &self.0.x5t));
        }

        if self.0.x5t_s256.is_some() {
            try!(serializer.serialize_struct_elt("x5t#s256", &self.0.x5t_s256));
        }

        if self.0.cty.is_some() {
            try!(serializer.serialize_struct_elt("cty", &self.0.cty));
        }

        if let Some(crit) = self.0.crit.as_ref() {
            if crit.len() != 0 {
                try!(serializer.serialize_struct_elt("crit", &self.0.crit));
            }
        }

        for (k,v) in &self.0.custom_params {
            try!(serializer.serialize_map_elt(k, v));
        }

        Ok(None)
    }
}

impl Deserialize for Header {
    fn deserialize<D>(deserializer: &mut D) -> Result<Header, D::Error>
        where D: serde::Deserializer,
    {
        deserializer.deserialize(HeaderDeVisitor)
    }
}

struct HeaderDeVisitor;

impl serde::de::Visitor for HeaderDeVisitor {
    type Value = Header;

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<Header, V::Error>
        where V: serde::de::MapVisitor,
    {
        let mut alg = None;
        let mut typ = None;
        let mut jku = None;
        let mut jwk = None;
        let mut kid = None;
        let mut x5u = None;
        let mut x5c = None;
        let mut x5t = None;
        let mut x5t_s256 = None;
        let mut cty = None;
        let mut crit = None;
        let mut custom_params = HashMap::<String, serde_json::value::Value>::new();

        loop {
            if let Some(key) = try!(visitor.visit_key::<String>()) {
                match &key[..] {
                    "alg" => { alg = Some(try!(visitor.visit_value())); }
                    "typ" => { typ = Some(try!(visitor.visit_value())); }
                    "kid" => { kid = Some(try!(visitor.visit_value())); }
                    "jku" => { jku = Some(try!(visitor.visit_value())); }
                    "jwk" => { jwk = Some(try!(visitor.visit_value())); }
                    "x5u" => { x5u = Some(try!(visitor.visit_value())); }
                    "x5c" => { x5c = Some(try!(visitor.visit_value())); }
                    "x5t" => { x5t = Some(try!(visitor.visit_value())); }
                    "x5t#s256" => { x5t_s256 = Some(try!(visitor.visit_value())); }
                    "cty" => { cty = Some(try!(visitor.visit_value())); }
                    "crit" => { crit = Some(try!(visitor.visit_value())); }

                    k => {
                        let v = try!(visitor.visit_value());

                        custom_params.entry(k.to_owned()).or_insert(v);
                    }
                }
            } else {
                break;
            }
        }

        let alg = match alg {
            Some(alg) => alg,
            None => try!(visitor.missing_field("alg")),
        };

        try!(visitor.end());

        Ok(Header{
            alg: alg,
            typ: typ,
            kid: kid,
            jku: jku,
            jwk: jwk,
            x5u: x5u,
            x5c: x5c,
            x5t: x5t,
            x5t_s256: x5t_s256,
            cty: cty,
            crit: crit,
            custom_params: custom_params,
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use serde_json;

    #[test]
    fn test_header_serde() {
        let mut h = Header::default();
        h.jku = Some("https://example.com/jwk".to_owned());
        h.jwk = Some("".to_owned());
        h.kid = Some("one".to_owned());
        h.x5u = Some("https://example.com/x509cert".to_owned());
        h.x5c = Some(vec!["b64 jws cert".to_owned(), "b64 jws cert's CA etc".to_owned()]);
        h.x5t = Some("blah".to_owned());
        h.x5t_s256 = Some("blah256".to_owned());
        h.cty = Some("example".to_owned());
        h.crit = Some(vec!["exp".to_owned()]);
        h.custom_params.insert("exp".to_owned(), serde_json::to_value("soon"));

        let h_js = serde_json::to_string(&h).unwrap();

        let h2: Header = serde_json::from_str(&h_js).unwrap();

        assert_eq!(h, h2);
    }
}<commit_msg>header typ should be public<commit_after>use serde::{Serialize, Deserialize};
use serde;
use serde_json;
use algorithm::*;
use std::collections::HashMap;

#[derive(Clone, Debug, PartialEq)]
/// A basic JWT header part, the alg defaults to HS256 and typ is automatically
/// set to `JWT`. All the other fields are optional
pub struct Header {
    pub typ: Option<String>,
    pub alg: Algorithm,
    pub jku: Option<String>, // jwk key set url
    pub jwk: Option<String>, // json web key
    pub kid: Option<String>, // key id
    pub x5u: Option<String>, // x509 url
    pub x5c: Option<Vec<String>>, // x509 cert chain
    pub x5t: Option<String>, // x509 cert sha1 thumbprint
    pub x5t_s256: Option<String>, // x509 cert sha256 thumbprint
    pub cty: Option<String>, // payload media type
    pub crit: Option<Vec<String>>, // critical extension params list
    pub custom_params: HashMap<String, serde_json::value::Value>,
}

impl Header {
    pub fn new(algorithm: Algorithm) -> Header {
        Header {
            typ: Some("JWT".to_owned()),
            alg: algorithm,
            jku: None,
            jwk: None,
            kid: None,
            x5u: None,
            x5c: None,
            x5t: None,
            x5t_s256: None,
            cty: None,
            crit: None,
            custom_params: HashMap::new(),
        }
    }
}

impl Default for Header {
    fn default() -> Header {
        Header::new(Algorithm::HS256)
    }
}

impl Serialize for Header {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_map(HeaderSerVisitor(&self))
    }
}

struct HeaderSerVisitor<'a>(&'a Header);

impl<'a> serde::ser::MapVisitor for HeaderSerVisitor<'a> {
    fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
        where S: serde::Serializer
    {
        if self.0.typ.is_some() {
            try!(serializer.serialize_struct_elt("typ", &self.0.typ));
        }

        try!(serializer.serialize_struct_elt("alg", &self.0.alg));

        if self.0.jku.is_some() {
            try!(serializer.serialize_struct_elt("jku", &self.0.jku));
        }

        if self.0.jwk.is_some() {
            try!(serializer.serialize_struct_elt("jwk", &self.0.jwk));
        }

        if self.0.kid.is_some() {
            try!(serializer.serialize_struct_elt("kid", &self.0.kid));
        }

        if self.0.x5u.is_some() {
            try!(serializer.serialize_struct_elt("x5u", &self.0.x5u));
        }

        if self.0.x5c.is_some() {
            try!(serializer.serialize_struct_elt("x5c", &self.0.x5c));
        }

        if self.0.x5t.is_some() {
            try!(serializer.serialize_struct_elt("x5t", &self.0.x5t));
        }

        if self.0.x5t_s256.is_some() {
            try!(serializer.serialize_struct_elt("x5t#s256", &self.0.x5t_s256));
        }

        if self.0.cty.is_some() {
            try!(serializer.serialize_struct_elt("cty", &self.0.cty));
        }

        if let Some(crit) = self.0.crit.as_ref() {
            if crit.len() != 0 {
                try!(serializer.serialize_struct_elt("crit", &self.0.crit));
            }
        }

        for (k,v) in &self.0.custom_params {
            try!(serializer.serialize_map_elt(k, v));
        }

        Ok(None)
    }
}

impl Deserialize for Header {
    fn deserialize<D>(deserializer: &mut D) -> Result<Header, D::Error>
        where D: serde::Deserializer,
    {
        deserializer.deserialize(HeaderDeVisitor)
    }
}

struct HeaderDeVisitor;

impl serde::de::Visitor for HeaderDeVisitor {
    type Value = Header;

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<Header, V::Error>
        where V: serde::de::MapVisitor,
    {
        let mut alg = None;
        let mut typ = None;
        let mut jku = None;
        let mut jwk = None;
        let mut kid = None;
        let mut x5u = None;
        let mut x5c = None;
        let mut x5t = None;
        let mut x5t_s256 = None;
        let mut cty = None;
        let mut crit = None;
        let mut custom_params = HashMap::<String, serde_json::value::Value>::new();

        loop {
            if let Some(key) = try!(visitor.visit_key::<String>()) {
                match &key[..] {
                    "alg" => { alg = Some(try!(visitor.visit_value())); }
                    "typ" => { typ = Some(try!(visitor.visit_value())); }
                    "kid" => { kid = Some(try!(visitor.visit_value())); }
                    "jku" => { jku = Some(try!(visitor.visit_value())); }
                    "jwk" => { jwk = Some(try!(visitor.visit_value())); }
                    "x5u" => { x5u = Some(try!(visitor.visit_value())); }
                    "x5c" => { x5c = Some(try!(visitor.visit_value())); }
                    "x5t" => { x5t = Some(try!(visitor.visit_value())); }
                    "x5t#s256" => { x5t_s256 = Some(try!(visitor.visit_value())); }
                    "cty" => { cty = Some(try!(visitor.visit_value())); }
                    "crit" => { crit = Some(try!(visitor.visit_value())); }

                    k => {
                        let v = try!(visitor.visit_value());

                        custom_params.entry(k.to_owned()).or_insert(v);
                    }
                }
            } else {
                break;
            }
        }

        let alg = match alg {
            Some(alg) => alg,
            None => try!(visitor.missing_field("alg")),
        };

        try!(visitor.end());

        Ok(Header{
            alg: alg,
            typ: typ,
            kid: kid,
            jku: jku,
            jwk: jwk,
            x5u: x5u,
            x5c: x5c,
            x5t: x5t,
            x5t_s256: x5t_s256,
            cty: cty,
            crit: crit,
            custom_params: custom_params,
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use serde_json;

    #[test]
    fn test_header_serde() {
        let mut h = Header::default();
        h.jku = Some("https://example.com/jwk".to_owned());
        h.jwk = Some("".to_owned());
        h.kid = Some("one".to_owned());
        h.x5u = Some("https://example.com/x509cert".to_owned());
        h.x5c = Some(vec!["b64 jws cert".to_owned(), "b64 jws cert's CA etc".to_owned()]);
        h.x5t = Some("blah".to_owned());
        h.x5t_s256 = Some("blah256".to_owned());
        h.cty = Some("example".to_owned());
        h.crit = Some(vec!["exp".to_owned()]);
        h.custom_params.insert("exp".to_owned(), serde_json::to_value("soon"));

        let h_js = serde_json::to_string(&h).unwrap();

        let h2: Header = serde_json::from_str(&h_js).unwrap();

        assert_eq!(h, h2);
    }
}<|endoftext|>


<commit_before>use std::collections::HashMap;

use {Client, QueryOptions, QueryMeta};
use errors::Result;
use request::get;

#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct AgentService {
    pub ID: String,
    pub Service: String,
    pub Tags: Vec<String>,
    pub Port: u16,
    pub Address: String,
    pub EnableTagOverride: bool,
    pub CreateIndex: u64,
    pub ModifyIndex: u64,
}
#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct HealthCheck {
    pub Node: String,
    pub CheckID: String,
    pub Name: String,
    pub Status: String,
    pub Notes: String,
    pub Output: String,
    pub ServiceID: String,
    pub ServiceName: String,
    pub ServiceTags: Vec<String>,
}

#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct Node {
    pub ID: String,
    pub Node: String,
    pub Address: String,
    pub Datacenter: String,
    pub TaggedAddresses: HashMap<String, String>,
    pub Meta: HashMap<String, String>,
    pub CreateIndex: u64,
    pub ModifyIndex: u64,
}

#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct ServiceEntry {
    pub Node: Node,
    pub Service: AgentService,
    pub Checks: Vec<HealthCheck>,
}

pub trait Health {
    fn service(
        &self,
        service: &str,
        tag: Option<&str>,
        passing_only: bool,
        options: Option<&QueryOptions>,
    ) -> Result<(ServiceEntry, QueryMeta)>;
}

impl Health for Client {
    fn service(
        &self,
        service: &str,
        tag: Option<&str>,
        passing_only: bool,
        options: Option<&QueryOptions>,
    ) -> Result<(ServiceEntry, QueryMeta)> {
        let mut params = HashMap::new();
        let path = format!("/v1/health/service/{}", service);
        if passing_only {
            params.insert(String::from("passing"), String::from("1"));
        }
        if let Some(tag) = tag {
            params.insert(String::from("tag"), tag.to_owned());
        }
        get(&path, &self.config, params, options)
    }
}
<commit_msg>Update to service call<commit_after>use std::collections::HashMap;

use {Client, QueryOptions, QueryMeta};
use errors::Result;
use request::get;

#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct AgentService {
    pub ID: String,
    pub Service: String,
    pub Tags: Vec<String>,
    pub Port: u16,
    pub Address: String,
    pub EnableTagOverride: bool,
    pub CreateIndex: u64,
    pub ModifyIndex: u64,
}
#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct HealthCheck {
    pub Node: String,
    pub CheckID: String,
    pub Name: String,
    pub Status: String,
    pub Notes: String,
    pub Output: String,
    pub ServiceID: String,
    pub ServiceName: String,
    pub ServiceTags: Vec<String>,
}

#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct Node {
    pub ID: String,
    pub Node: String,
    pub Address: String,
    pub Datacenter: String,
    pub TaggedAddresses: HashMap<String, String>,
    pub Meta: HashMap<String, String>,
    pub CreateIndex: u64,
    pub ModifyIndex: u64,
}

#[derive(Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct ServiceEntry {
    pub Node: Node,
    pub Service: AgentService,
    pub Checks: Vec<HealthCheck>,
}

pub trait Health {
    fn service(
        &self,
        service: &str,
        tag: Option<&str>,
        passing_only: bool,
        options: Option<&QueryOptions>,
    ) -> Result<(Vec<ServiceEntry>, QueryMeta)>;
}

impl Health for Client {
    fn service(
        &self,
        service: &str,
        tag: Option<&str>,
        passing_only: bool,
        options: Option<&QueryOptions>,
    ) -> Result<(Vec<ServiceEntry>, QueryMeta)> {
        let mut params = HashMap::new();
        let path = format!("/v1/health/service/{}", service);
        if passing_only {
            params.insert(String::from("passing"), String::from("1"));
        }
        if let Some(tag) = tag {
            params.insert(String::from("tag"), tag.to_owned());
        }
        get(&path, &self.config, params, options)
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::sync::atomic::AtomicBool;

use self::reader::LogReader;
use super::*;

#[doc(hidden)]
pub const MSG_HEADER_LEN: usize = 15;

#[doc(hidden)]
pub const SEG_HEADER_LEN: usize = 18;

#[doc(hidden)]
pub const SEG_TRAILER_LEN: usize = 10;

/// A sequential store which allows users to create
/// reservations placed at known log offsets, used
/// for writing persistent data structures that need
/// to know where to find persisted bits in the future.
///
/// # Working with `Log`
///
/// ```
/// let log = sled::Config::default().log();
/// let (first_lsn, _first_offset) = log.write(b"1".to_vec());
/// log.write(b"22".to_vec());
/// log.write(b"333".to_vec());
///
/// // stick an abort in the middle, which should not be returned
/// let res = log.reserve(b"never_gonna_hit_disk".to_vec());
/// res.abort();
///
/// log.write(b"4444".to_vec());
/// let (last_lsn, _last_offset) = log.write(b"55555".to_vec());
/// log.make_stable(last_lsn);
/// let mut iter = log.iter_from(first_lsn);
/// assert_eq!(iter.next().unwrap().2, b"1".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"22".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"333".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"4444".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"55555".to_vec());
/// assert_eq!(iter.next(), None);
/// ```
pub struct Log {
    /// iobufs is the underlying lock-free IO write buffer.
    iobufs: Arc<IoBufs>,
    config: FinalConfig,
    flusher_shutdown: Arc<AtomicBool>,
    flusher_handle: Option<std::thread::JoinHandle<()>>,
}

unsafe impl Send for Log {}
unsafe impl Sync for Log {}

impl Drop for Log {
    fn drop(&mut self) {
        self.flusher_shutdown.store(
            true,
            std::sync::atomic::Ordering::SeqCst,
        );
        if let Some(join_handle) = self.flusher_handle.take() {
            join_handle.join().unwrap();
        }

        #[cfg(feature = "cpuprofiler")]
        {
            cpuprofiler::PROFILER.lock().unwrap().stop().unwrap();
        }
    }
}

impl Log {
    /// Start the log, open or create the configured file,
    /// and optionally start the periodic buffer flush thread.
    pub fn start<R>(config: FinalConfig, snapshot: Snapshot<R>) -> Log {
        let iobufs = Arc::new(IoBufs::start(config.clone(), snapshot));

        let flusher_shutdown = Arc::new(AtomicBool::new(false));

        let flusher_handle =
            config.get_flush_every_ms().map(|flush_every_ms| {
                periodic_flusher::flusher(
                    "log flusher".to_owned(),
                    Arc::clone(&iobufs),
                    Arc::clone(&flusher_shutdown),
                    flush_every_ms,
                ).unwrap()
            });

        Log {
            iobufs: iobufs,
            config: config,
            flusher_shutdown: flusher_shutdown,
            flusher_handle: flusher_handle,
        }
    }

    /// Starts a log for use without a materializer.
    pub fn start_raw_log(config: FinalConfig) -> Log {
        let log_iter = raw_segment_iter(&config);

        let snapshot = advance_snapshot::<NullMaterializer, (), ()>(
            log_iter,
            Snapshot::default(),
            &config,
        );

        Log::start::<()>(config, snapshot)
    }

    /// Flush the next io buffer.
    pub fn flush(&self) {
        self.iobufs.flush();
    }

    /// Reserve space in the log for a pending linearized operation.
    pub fn reserve(&self, buf: Vec<u8>) -> Reservation {
        self.iobufs.reserve(buf)
    }

    /// Write a buffer into the log. Returns the log sequence
    /// number and the file offset of the write.
    pub fn write(&self, buf: Vec<u8>) -> (Lsn, LogID) {
        self.iobufs.reserve(buf).complete()
    }

    /// Return an iterator over the log, starting with
    /// a specified offset.
    pub fn iter_from(&self, lsn: Lsn) -> LogIter {
        trace!("iterating from lsn {}", lsn);
        let io_buf_size = self.config.get_io_buf_size();
        let segment_base_lsn = lsn / io_buf_size as Lsn * io_buf_size as Lsn;
        let min_lsn = segment_base_lsn + SEG_HEADER_LEN as Lsn;

        // corrected_lsn accounts for the segment header length
        let corrected_lsn = std::cmp::max(lsn, min_lsn);

        let segment_iter =
            self.with_sa(|sa| sa.segment_snapshot_iter_from(corrected_lsn));

        LogIter {
            config: self.config.clone(),
            max_lsn: self.stable_offset(),
            cur_lsn: corrected_lsn,
            segment_base: None,
            segment_iter: segment_iter,
            segment_len: io_buf_size,
            use_compression: self.config.get_use_compression(),
            trailer: None,
        }
    }

    /// read a buffer from the disk
    pub fn read(&self, lsn: Lsn, lid: LogID) -> io::Result<LogRead> {
        trace!("reading log lsn {} lid {}", lsn, lid);
        self.make_stable(lsn);
        let f = self.config.file();

        let read = f.read_message(
            lid,
            self.config.get_io_buf_size(),
            self.config.get_use_compression(),
        );

        read.and_then(|log_read| match log_read {
            LogRead::Flush(read_lsn, _, _) => {
                assert_eq!(lsn, read_lsn);
                Ok(log_read)
            }
            _ => Ok(log_read),
        })
    }

    /// returns the current stable offset written to disk
    pub fn stable_offset(&self) -> Lsn {
        self.iobufs.stable()
    }

    /// blocks until the specified log sequence number has
    /// been made stable on disk
    pub fn make_stable(&self, lsn: Lsn) {
        let start = clock();

        // NB before we write the 0th byte of the file, stable  is -1
        while self.iobufs.stable() < lsn {
            self.iobufs.flush();

            // block until another thread updates the stable lsn
            let waiter = self.iobufs.intervals.lock().unwrap();

            if self.iobufs.stable() < lsn {
                trace!("waiting on cond var for make_stable({})", lsn);
                let _waiter =
                    self.iobufs.interval_updated.wait(waiter).unwrap();
            } else {
                trace!("make_stable({}) returning", lsn);
                break;
            }
        }

        M.make_stable.measure(clock() - start);
    }

    // SegmentAccountant access for coordination with the `PageCache`
    pub(in io) fn with_sa<B, F>(&self, f: F) -> B
        where F: FnOnce(&mut SegmentAccountant) -> B
    {
        self.iobufs.with_sa(f)
    }
}

/// All log messages are prepended with this header
#[derive(Debug, Copy, Clone, PartialEq)]
pub(super) struct MessageHeader {
    pub successful_flush: bool,
    pub lsn: Lsn,
    pub len: usize,
    pub crc16: [u8; 2],
}

/// A segment's header contains the new base LSN and a reference
/// to the previous log segment.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SegmentHeader {
    pub lsn: Lsn,
    pub prev: LogID,
    pub ok: bool,
}

/// A segment's trailer contains the base Lsn for the segment.
/// It is written after the rest of the segment has been fsync'd,
/// and helps us indicate if a segment has been torn.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SegmentTrailer {
    pub lsn: Lsn,
    pub ok: bool,
}

#[doc(hidden)]
#[derive(Debug)]
pub enum LogRead {
    Flush(Lsn, Vec<u8>, usize),
    Zeroed(usize),
    Corrupted(usize),
}

impl LogRead {
    /// Optionally return successfully read bytes, or None if
    /// the data was corrupt or this log entry was aborted.
    pub fn flush(self) -> Option<(Lsn, Vec<u8>, usize)> {
        match self {
            LogRead::Flush(lsn, bytes, len) => Some((lsn, bytes, len)),
            _ => None,
        }
    }

    /// Return true if we read a completed write successfully.
    pub fn is_flush(&self) -> bool {
        match *self {
            LogRead::Flush(_, _, _) => true,
            _ => false,
        }
    }

    /// Return true if we read an aborted flush.
    pub fn is_zeroed(&self) -> bool {
        match *self {
            LogRead::Zeroed(_) => true,
            _ => false,
        }
    }

    /// Return true if we read a corrupted log entry.
    pub fn is_corrupt(&self) -> bool {
        match *self {
            LogRead::Corrupted(_) => true,
            _ => false,
        }
    }

    /// Retrieve the read bytes from a completed, successful write.
    ///
    /// # Panics
    ///
    /// panics if `is_flush()` is false.
    pub fn unwrap(self) -> (Lsn, Vec<u8>, usize) {
        match self {
            LogRead::Flush(lsn, bytes, len) => (lsn, bytes, len),
            _ => panic!("called unwrap on a non-flush LogRead"),
        }
    }
}

impl From<[u8; MSG_HEADER_LEN]> for MessageHeader {
    fn from(buf: [u8; MSG_HEADER_LEN]) -> MessageHeader {
        let valid = buf[0] == 1;

        let lsn_buf = &buf[1..9];
        let mut lsn_arr = [0u8; 8];
        lsn_arr.copy_from_slice(&*lsn_buf);
        let lsn: Lsn = unsafe { std::mem::transmute(lsn_arr) };

        let len_buf = &buf[9..13];
        let mut len_arr = [0u8; 4];
        len_arr.copy_from_slice(&*len_buf);
        let len: u32 = unsafe { std::mem::transmute(len_arr) };

        let crc16 = [buf[13], buf[14]];

        MessageHeader {
            successful_flush: valid,
            lsn: lsn,
            len: len as usize,
            crc16: crc16,
        }
    }
}

impl Into<[u8; MSG_HEADER_LEN]> for MessageHeader {
    fn into(self) -> [u8; MSG_HEADER_LEN] {
        let mut buf = [0u8; MSG_HEADER_LEN];
        if self.successful_flush {
            buf[0] = 1;
        }

        // NB LSN actually gets written after the reservation
        // for the item is claimed, when we actually know the lsn,
        // in PageCache::reserve.
        let lsn_arr: [u8; 8] = unsafe { std::mem::transmute(self.lsn) };
        buf[1..9].copy_from_slice(&lsn_arr);

        let len_arr: [u8; 4] = unsafe { std::mem::transmute(self.len as u32) };
        buf[9..13].copy_from_slice(&len_arr);

        buf[13] = self.crc16[0];
        buf[14] = self.crc16[1];

        buf
    }
}

impl From<[u8; SEG_HEADER_LEN]> for SegmentHeader {
    fn from(buf: [u8; SEG_HEADER_LEN]) -> SegmentHeader {
        let crc16 = [buf[0], buf[1]];

        let lsn_buf = &buf[2..10];
        let mut lsn_arr = [0u8; 8];
        lsn_arr.copy_from_slice(&*lsn_buf);
        let lsn: Lsn = unsafe { std::mem::transmute(lsn_arr) };

        let prev_lid_buf = &buf[10..18];
        let mut prev_lid_arr = [0u8; 8];
        prev_lid_arr.copy_from_slice(&*prev_lid_buf);
        let prev_lid: LogID = unsafe { std::mem::transmute(prev_lid_arr) };

        let crc16_tested = crc16_arr(&prev_lid_arr);

        SegmentHeader {
            lsn: lsn,
            prev: prev_lid,
            ok: crc16_tested == crc16,
        }
    }
}

impl Into<[u8; SEG_HEADER_LEN]> for SegmentHeader {
    fn into(self) -> [u8; SEG_HEADER_LEN] {
        let mut buf = [0u8; SEG_HEADER_LEN];

        let lsn_arr: [u8; 8] = unsafe { std::mem::transmute(self.lsn) };
        buf[2..10].copy_from_slice(&lsn_arr);

        let prev_lid_arr: [u8; 8] = unsafe { std::mem::transmute(self.prev) };
        buf[10..18].copy_from_slice(&prev_lid_arr);

        let crc16 = crc16_arr(&prev_lid_arr);
        buf[0] = crc16[0];
        buf[1] = crc16[1];

        buf
    }
}

impl From<[u8; SEG_TRAILER_LEN]> for SegmentTrailer {
    fn from(buf: [u8; SEG_TRAILER_LEN]) -> SegmentTrailer {
        let crc16 = [buf[0], buf[1]];

        let lsn_buf = &buf[2..10];
        let mut lsn_arr = [0u8; 8];
        lsn_arr.copy_from_slice(&*lsn_buf);
        let lsn: Lsn = unsafe { std::mem::transmute(lsn_arr) };

        let crc16_tested = crc16_arr(&lsn_arr);

        SegmentTrailer {
            lsn: lsn,
            ok: crc16_tested == crc16,
        }
    }
}

impl Into<[u8; SEG_TRAILER_LEN]> for SegmentTrailer {
    fn into(self) -> [u8; SEG_TRAILER_LEN] {
        let mut buf = [0u8; SEG_TRAILER_LEN];

        let lsn_arr: [u8; 8] = unsafe { std::mem::transmute(self.lsn) };
        buf[2..10].copy_from_slice(&lsn_arr);

        let crc16 = crc16_arr(&lsn_arr);
        buf[0] = crc16[0];
        buf[1] = crc16[1];

        buf
    }
}
<commit_msg>XOR lsn and crc16 data to make more clear when there's a misinterpretation of zeroed out buffers<commit_after>use std::sync::Arc;
use std::sync::atomic::AtomicBool;

use self::reader::LogReader;
use super::*;

#[doc(hidden)]
pub const MSG_HEADER_LEN: usize = 15;

#[doc(hidden)]
pub const SEG_HEADER_LEN: usize = 18;

#[doc(hidden)]
pub const SEG_TRAILER_LEN: usize = 10;

/// A sequential store which allows users to create
/// reservations placed at known log offsets, used
/// for writing persistent data structures that need
/// to know where to find persisted bits in the future.
///
/// # Working with `Log`
///
/// ```
/// let log = sled::Config::default().log();
/// let (first_lsn, _first_offset) = log.write(b"1".to_vec());
/// log.write(b"22".to_vec());
/// log.write(b"333".to_vec());
///
/// // stick an abort in the middle, which should not be returned
/// let res = log.reserve(b"never_gonna_hit_disk".to_vec());
/// res.abort();
///
/// log.write(b"4444".to_vec());
/// let (last_lsn, _last_offset) = log.write(b"55555".to_vec());
/// log.make_stable(last_lsn);
/// let mut iter = log.iter_from(first_lsn);
/// assert_eq!(iter.next().unwrap().2, b"1".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"22".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"333".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"4444".to_vec());
/// assert_eq!(iter.next().unwrap().2, b"55555".to_vec());
/// assert_eq!(iter.next(), None);
/// ```
pub struct Log {
    /// iobufs is the underlying lock-free IO write buffer.
    iobufs: Arc<IoBufs>,
    config: FinalConfig,
    flusher_shutdown: Arc<AtomicBool>,
    flusher_handle: Option<std::thread::JoinHandle<()>>,
}

unsafe impl Send for Log {}
unsafe impl Sync for Log {}

impl Drop for Log {
    fn drop(&mut self) {
        self.flusher_shutdown.store(
            true,
            std::sync::atomic::Ordering::SeqCst,
        );
        if let Some(join_handle) = self.flusher_handle.take() {
            join_handle.join().unwrap();
        }

        #[cfg(feature = "cpuprofiler")]
        {
            cpuprofiler::PROFILER.lock().unwrap().stop().unwrap();
        }
    }
}

impl Log {
    /// Start the log, open or create the configured file,
    /// and optionally start the periodic buffer flush thread.
    pub fn start<R>(config: FinalConfig, snapshot: Snapshot<R>) -> Log {
        let iobufs = Arc::new(IoBufs::start(config.clone(), snapshot));

        let flusher_shutdown = Arc::new(AtomicBool::new(false));

        let flusher_handle =
            config.get_flush_every_ms().map(|flush_every_ms| {
                periodic_flusher::flusher(
                    "log flusher".to_owned(),
                    Arc::clone(&iobufs),
                    Arc::clone(&flusher_shutdown),
                    flush_every_ms,
                ).unwrap()
            });

        Log {
            iobufs: iobufs,
            config: config,
            flusher_shutdown: flusher_shutdown,
            flusher_handle: flusher_handle,
        }
    }

    /// Starts a log for use without a materializer.
    pub fn start_raw_log(config: FinalConfig) -> Log {
        let log_iter = raw_segment_iter(&config);

        let snapshot = advance_snapshot::<NullMaterializer, (), ()>(
            log_iter,
            Snapshot::default(),
            &config,
        );

        Log::start::<()>(config, snapshot)
    }

    /// Flush the next io buffer.
    pub fn flush(&self) {
        self.iobufs.flush();
    }

    /// Reserve space in the log for a pending linearized operation.
    pub fn reserve(&self, buf: Vec<u8>) -> Reservation {
        self.iobufs.reserve(buf)
    }

    /// Write a buffer into the log. Returns the log sequence
    /// number and the file offset of the write.
    pub fn write(&self, buf: Vec<u8>) -> (Lsn, LogID) {
        self.iobufs.reserve(buf).complete()
    }

    /// Return an iterator over the log, starting with
    /// a specified offset.
    pub fn iter_from(&self, lsn: Lsn) -> LogIter {
        trace!("iterating from lsn {}", lsn);
        let io_buf_size = self.config.get_io_buf_size();
        let segment_base_lsn = lsn / io_buf_size as Lsn * io_buf_size as Lsn;
        let min_lsn = segment_base_lsn + SEG_HEADER_LEN as Lsn;

        // corrected_lsn accounts for the segment header length
        let corrected_lsn = std::cmp::max(lsn, min_lsn);

        let segment_iter =
            self.with_sa(|sa| sa.segment_snapshot_iter_from(corrected_lsn));

        LogIter {
            config: self.config.clone(),
            max_lsn: self.stable_offset(),
            cur_lsn: corrected_lsn,
            segment_base: None,
            segment_iter: segment_iter,
            segment_len: io_buf_size,
            use_compression: self.config.get_use_compression(),
            trailer: None,
        }
    }

    /// read a buffer from the disk
    pub fn read(&self, lsn: Lsn, lid: LogID) -> io::Result<LogRead> {
        trace!("reading log lsn {} lid {}", lsn, lid);
        self.make_stable(lsn);
        let f = self.config.file();

        let read = f.read_message(
            lid,
            self.config.get_io_buf_size(),
            self.config.get_use_compression(),
        );

        read.and_then(|log_read| match log_read {
            LogRead::Flush(read_lsn, _, _) => {
                assert_eq!(lsn, read_lsn);
                Ok(log_read)
            }
            _ => Ok(log_read),
        })
    }

    /// returns the current stable offset written to disk
    pub fn stable_offset(&self) -> Lsn {
        self.iobufs.stable()
    }

    /// blocks until the specified log sequence number has
    /// been made stable on disk
    pub fn make_stable(&self, lsn: Lsn) {
        let start = clock();

        // NB before we write the 0th byte of the file, stable  is -1
        while self.iobufs.stable() < lsn {
            self.iobufs.flush();

            // block until another thread updates the stable lsn
            let waiter = self.iobufs.intervals.lock().unwrap();

            if self.iobufs.stable() < lsn {
                trace!("waiting on cond var for make_stable({})", lsn);
                let _waiter =
                    self.iobufs.interval_updated.wait(waiter).unwrap();
            } else {
                trace!("make_stable({}) returning", lsn);
                break;
            }
        }

        M.make_stable.measure(clock() - start);
    }

    // SegmentAccountant access for coordination with the `PageCache`
    pub(in io) fn with_sa<B, F>(&self, f: F) -> B
        where F: FnOnce(&mut SegmentAccountant) -> B
    {
        self.iobufs.with_sa(f)
    }
}

/// All log messages are prepended with this header
#[derive(Debug, Copy, Clone, PartialEq)]
pub(super) struct MessageHeader {
    pub successful_flush: bool,
    pub lsn: Lsn,
    pub len: usize,
    pub crc16: [u8; 2],
}

/// A segment's header contains the new base LSN and a reference
/// to the previous log segment.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SegmentHeader {
    pub lsn: Lsn,
    pub prev: LogID,
    pub ok: bool,
}

/// A segment's trailer contains the base Lsn for the segment.
/// It is written after the rest of the segment has been fsync'd,
/// and helps us indicate if a segment has been torn.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SegmentTrailer {
    pub lsn: Lsn,
    pub ok: bool,
}

#[doc(hidden)]
#[derive(Debug)]
pub enum LogRead {
    Flush(Lsn, Vec<u8>, usize),
    Zeroed(usize),
    Corrupted(usize),
}

impl LogRead {
    /// Optionally return successfully read bytes, or None if
    /// the data was corrupt or this log entry was aborted.
    pub fn flush(self) -> Option<(Lsn, Vec<u8>, usize)> {
        match self {
            LogRead::Flush(lsn, bytes, len) => Some((lsn, bytes, len)),
            _ => None,
        }
    }

    /// Return true if we read a completed write successfully.
    pub fn is_flush(&self) -> bool {
        match *self {
            LogRead::Flush(_, _, _) => true,
            _ => false,
        }
    }

    /// Return true if we read an aborted flush.
    pub fn is_zeroed(&self) -> bool {
        match *self {
            LogRead::Zeroed(_) => true,
            _ => false,
        }
    }

    /// Return true if we read a corrupted log entry.
    pub fn is_corrupt(&self) -> bool {
        match *self {
            LogRead::Corrupted(_) => true,
            _ => false,
        }
    }

    /// Retrieve the read bytes from a completed, successful write.
    ///
    /// # Panics
    ///
    /// panics if `is_flush()` is false.
    pub fn unwrap(self) -> (Lsn, Vec<u8>, usize) {
        match self {
            LogRead::Flush(lsn, bytes, len) => (lsn, bytes, len),
            _ => panic!("called unwrap on a non-flush LogRead"),
        }
    }
}

// NB we use a lot of xors below to differentiate between zeroed out
// data on disk and an lsn or crc16 of 0

impl From<[u8; MSG_HEADER_LEN]> for MessageHeader {
    fn from(buf: [u8; MSG_HEADER_LEN]) -> MessageHeader {
        let valid = buf[0] == 1;

        let lsn_buf = &buf[1..9];
        let mut lsn_arr = [0u8; 8];
        lsn_arr.copy_from_slice(&*lsn_buf);
        let lsn: Lsn = unsafe { std::mem::transmute(lsn_arr) };

        let len_buf = &buf[9..13];
        let mut len_arr = [0u8; 4];
        len_arr.copy_from_slice(&*len_buf);
        let len: u32 = unsafe { std::mem::transmute(len_arr) };

        let crc16 = [buf[13] ^ 0xFF, buf[14] ^ 0xFF];

        MessageHeader {
            successful_flush: valid,
            lsn: lsn,
            len: len as usize,
            crc16: crc16,
        }
    }
}

impl Into<[u8; MSG_HEADER_LEN]> for MessageHeader {
    fn into(self) -> [u8; MSG_HEADER_LEN] {
        let mut buf = [0u8; MSG_HEADER_LEN];
        if self.successful_flush {
            buf[0] = 1;
        }

        // NB LSN actually gets written after the reservation
        // for the item is claimed, when we actually know the lsn,
        // in PageCache::reserve.
        let lsn_arr: [u8; 8] = unsafe { std::mem::transmute(self.lsn) };
        buf[1..9].copy_from_slice(&lsn_arr);

        let len_arr: [u8; 4] = unsafe { std::mem::transmute(self.len as u32) };
        buf[9..13].copy_from_slice(&len_arr);

        buf[13] = self.crc16[0] ^ 0xFF;
        buf[14] = self.crc16[1] ^ 0xFF;

        buf
    }
}

impl From<[u8; SEG_HEADER_LEN]> for SegmentHeader {
    fn from(buf: [u8; SEG_HEADER_LEN]) -> SegmentHeader {
        let crc16 = [buf[0] ^ 0xFF, buf[1] ^ 0xFF];

        let lsn_buf = &buf[2..10];
        let mut lsn_arr = [0u8; 8];
        lsn_arr.copy_from_slice(&*lsn_buf);
        let xor_lsn: Lsn = unsafe { std::mem::transmute(lsn_arr) };
        let lsn = xor_lsn ^ 0xFFFF_FFFF;

        let prev_lid_buf = &buf[10..18];
        let mut prev_lid_arr = [0u8; 8];
        prev_lid_arr.copy_from_slice(&*prev_lid_buf);
        let prev_lid: LogID = unsafe { std::mem::transmute(prev_lid_arr) };

        let crc16_tested = crc16_arr(&prev_lid_arr);

        SegmentHeader {
            lsn: lsn,
            prev: prev_lid,
            ok: crc16_tested == crc16,
        }
    }
}

impl Into<[u8; SEG_HEADER_LEN]> for SegmentHeader {
    fn into(self) -> [u8; SEG_HEADER_LEN] {
        let mut buf = [0u8; SEG_HEADER_LEN];

        let xor_lsn = self.lsn ^ 0xFFFF_FFFF;
        let lsn_arr: [u8; 8] = unsafe { std::mem::transmute(xor_lsn) };
        buf[2..10].copy_from_slice(&lsn_arr);

        let prev_lid_arr: [u8; 8] = unsafe { std::mem::transmute(self.prev) };
        buf[10..18].copy_from_slice(&prev_lid_arr);

        let crc16 = crc16_arr(&prev_lid_arr);

        buf[0] = crc16[0] ^ 0xFF;
        buf[1] = crc16[1] ^ 0xFF;

        buf
    }
}

impl From<[u8; SEG_TRAILER_LEN]> for SegmentTrailer {
    fn from(buf: [u8; SEG_TRAILER_LEN]) -> SegmentTrailer {
        let crc16 = [buf[0] ^ 0xFF, buf[1] ^ 0xFF];

        let lsn_buf = &buf[2..10];
        let mut lsn_arr = [0u8; 8];
        lsn_arr.copy_from_slice(&*lsn_buf);
        let xor_lsn: Lsn = unsafe { std::mem::transmute(lsn_arr) };
        let lsn = xor_lsn ^ 0xFFFF_FFFF;

        let crc16_tested = crc16_arr(&lsn_arr);

        SegmentTrailer {
            lsn: lsn,
            ok: crc16_tested == crc16,
        }
    }
}

impl Into<[u8; SEG_TRAILER_LEN]> for SegmentTrailer {
    fn into(self) -> [u8; SEG_TRAILER_LEN] {
        let mut buf = [0u8; SEG_TRAILER_LEN];

        let xor_lsn = self.lsn ^ 0xFFFF_FFFF;
        let lsn_arr: [u8; 8] = unsafe { std::mem::transmute(xor_lsn) };
        buf[2..10].copy_from_slice(&lsn_arr);

        let crc16 = crc16_arr(&lsn_arr);
        buf[0] = crc16[0] ^ 0xFF;
        buf[1] = crc16[1] ^ 0xFF;

        buf
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::ops::{DerefMut, Deref};
use std::result::Result;
use handle_table::{Handle};
use ::io::{AsyncRead, AsyncWrite, try_read_internal, write_internal,
           FdObserver, HasHandle, register_new_handle,
           Error};
use {Promise};
use private::{with_current_event_loop};

pub struct Stream {
    stream: ::mio::tcp::TcpStream,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Stream
}

pub struct Listener {
    listener: ::mio::tcp::TcpListener,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Listener
}

impl Drop for Listener {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Listener {
    pub fn bind(addr: ::std::net::SocketAddr) -> Result<Listener, ::std::io::Error> {
        let listener = try!(::mio::tcp::TcpListener::bind(&addr));
        let handle = FdObserver::new();

        with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register(&listener, ::mio::Token(handle.val),
                                                                     ::mio::EventSet::readable(),
                                                                     ::mio::PollOpt::edge()));
            Ok(Listener { listener: listener, handle: handle, no_send: ::std::marker::PhantomData })
        })
    }

    fn accept_internal(self) -> Result<Promise<(Listener, Stream), Error<Listener>>, Error<Listener>> {
        let accept_result = match self.listener.accept() {
            Err(e) => return Err(Error::new(self, e)),
            Ok(v) => v,
        };
        match accept_result {
            Some(stream) => {
                let handle = match register_new_handle(&stream) {
                    Err(e) => return Err(Error::new(self, e)),
                    Ok(v) => v,
                };
                Ok(Promise::fulfilled((self, Stream::new(stream, handle))))
            }
            None => {
                with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    Ok(promise.then_else(move |r| match r {
                        Ok(()) => self.accept_internal(),
                        Err(e) => Err(Error::new(self, e))
                    }))
                })
            }
        }
    }

    pub fn accept(self) -> Promise<(Listener, Stream), Error<Listener>> {
        Promise::fulfilled(()).then(move |()| self.accept_internal())
    }
}

impl ::mio::TryRead for Stream {
    fn try_read(&mut self, buf: &mut [u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryRead;
        self.stream.try_read(buf)
    }
}

impl ::mio::TryWrite for Stream {
    fn try_write(&mut self, buf: &[u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryWrite;
        self.stream.try_write(buf)
    }
}

impl HasHandle for Stream {
    fn get_handle(&self) -> Handle { self.handle }
}

impl Drop for Stream {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Stream {
    fn new(stream: ::mio::tcp::TcpStream, handle: Handle) -> Stream {
        Stream { stream: stream, handle: handle, no_send: ::std::marker::PhantomData }
    }

    pub fn connect(addr: ::std::net::SocketAddr) -> Promise<Stream, ::std::io::Error> {
        Promise::fulfilled(()).then(move |()| {
            let stream = try!(::mio::tcp::TcpStream::connect(&addr));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let handle = try!(register_new_handle(&stream));

            with_current_event_loop(move |event_loop| {
                let promise =
                    event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
                Ok(promise.map(move |()| {
                    // TODO how to test for error?
                    //try!(stream.take_socket_error());
                    Ok(Stream::new(stream, handle))
                }))
            })
        })
    }

    pub fn try_clone(&self) -> Result<Stream, ::std::io::Error> {
        let stream = try!(self.stream.try_clone());
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }

    #[cfg(unix)]
    pub unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Result<Stream, ::std::io::Error> {
        let stream = ::std::os::unix::io::FromRawFd::from_raw_fd(fd);
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }
}

impl AsyncRead for Stream {
    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: DerefMut<Target=[u8]>
    {
        Promise::fulfilled(()).then(move |()| {
            try_read_internal(self, buf, 0, min_bytes)
        })
    }
}

impl AsyncWrite for Stream {
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>> where T: Deref<Target=[u8]> {
        Promise::fulfilled(()).then(move |()| {
            write_internal(self, buf, 0)
        })
    }
}
<commit_msg>Update for new signature of mio::TcpListener::accept().<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::ops::{DerefMut, Deref};
use std::result::Result;
use handle_table::{Handle};
use ::io::{AsyncRead, AsyncWrite, try_read_internal, write_internal,
           FdObserver, HasHandle, register_new_handle,
           Error};
use {Promise};
use private::{with_current_event_loop};

pub struct Stream {
    stream: ::mio::tcp::TcpStream,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Stream
}

pub struct Listener {
    listener: ::mio::tcp::TcpListener,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Listener
}

impl Drop for Listener {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Listener {
    pub fn bind(addr: ::std::net::SocketAddr) -> Result<Listener, ::std::io::Error> {
        let listener = try!(::mio::tcp::TcpListener::bind(&addr));
        let handle = FdObserver::new();

        with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register(&listener, ::mio::Token(handle.val),
                                                                     ::mio::EventSet::readable(),
                                                                     ::mio::PollOpt::edge()));
            Ok(Listener { listener: listener, handle: handle, no_send: ::std::marker::PhantomData })
        })
    }

    fn accept_internal(self) -> Result<Promise<(Listener, Stream), Error<Listener>>, Error<Listener>> {
        let accept_result = match self.listener.accept() {
            Err(e) => return Err(Error::new(self, e)),
            Ok(v) => v,
        };
        match accept_result {
            Some((stream, _)) => {
                let handle = match register_new_handle(&stream) {
                    Err(e) => return Err(Error::new(self, e)),
                    Ok(v) => v,
                };
                Ok(Promise::fulfilled((self, Stream::new(stream, handle))))
            }
            None => {
                with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    Ok(promise.then_else(move |r| match r {
                        Ok(()) => self.accept_internal(),
                        Err(e) => Err(Error::new(self, e))
                    }))
                })
            }
        }
    }

    pub fn accept(self) -> Promise<(Listener, Stream), Error<Listener>> {
        Promise::fulfilled(()).then(move |()| self.accept_internal())
    }
}

impl ::mio::TryRead for Stream {
    fn try_read(&mut self, buf: &mut [u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryRead;
        self.stream.try_read(buf)
    }
}

impl ::mio::TryWrite for Stream {
    fn try_write(&mut self, buf: &[u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryWrite;
        self.stream.try_write(buf)
    }
}

impl HasHandle for Stream {
    fn get_handle(&self) -> Handle { self.handle }
}

impl Drop for Stream {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Stream {
    fn new(stream: ::mio::tcp::TcpStream, handle: Handle) -> Stream {
        Stream { stream: stream, handle: handle, no_send: ::std::marker::PhantomData }
    }

    pub fn connect(addr: ::std::net::SocketAddr) -> Promise<Stream, ::std::io::Error> {
        Promise::fulfilled(()).then(move |()| {
            let stream = try!(::mio::tcp::TcpStream::connect(&addr));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let handle = try!(register_new_handle(&stream));

            with_current_event_loop(move |event_loop| {
                let promise =
                    event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
                Ok(promise.map(move |()| {
                    // TODO how to test for error?
                    //try!(stream.take_socket_error());
                    Ok(Stream::new(stream, handle))
                }))
            })
        })
    }

    pub fn try_clone(&self) -> Result<Stream, ::std::io::Error> {
        let stream = try!(self.stream.try_clone());
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }

    #[cfg(unix)]
    pub unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Result<Stream, ::std::io::Error> {
        let stream = ::std::os::unix::io::FromRawFd::from_raw_fd(fd);
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }
}

impl AsyncRead for Stream {
    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: DerefMut<Target=[u8]>
    {
        Promise::fulfilled(()).then(move |()| {
            try_read_internal(self, buf, 0, min_bytes)
        })
    }
}

impl AsyncWrite for Stream {
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>> where T: Deref<Target=[u8]> {
        Promise::fulfilled(()).then(move |()| {
            write_internal(self, buf, 0)
        })
    }
}
<|endoftext|>


<commit_before>#![crate_name = "uu_arch"]

// This file is part of the uutils coreutils package.
//
// (c) Smigle00 <smigle00@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

extern crate platform_info;
#[macro_use]
extern crate uucore;

use platform_info::*;

static SYNTAX: &str = "Print machine architecture";
static SUMMARY: &str = "Determine architecture name for current machine.";
static LONG_HELP: &str = "";

pub fn uumain(args: Vec<String>) -> i32 {
    new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);
    let uts = return_if_err!(1, PlatformInfo::new());
    println!("{}", uts.machine().trim());
    0
}
<commit_msg>Update src/uu/arch/src/arch.rs<commit_after>#![crate_name = "uu_arch"]

// This file is part of the uutils coreutils package.
//
// (c) Smigle00 <smigle00@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

extern crate platform_info;
#[macro_use]
extern crate uucore;

use platform_info::*;

static SYNTAX: &str = "Display machine architecture";
static SUMMARY: &str = "Determine architecture name for current machine.";
static LONG_HELP: &str = "";

pub fn uumain(args: Vec<String>) -> i32 {
    new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);
    let uts = return_if_err!(1, PlatformInfo::new());
    println!("{}", uts.machine().trim());
    0
}
<|endoftext|>