<commit_before>use std::fmt::Write;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;

use colored::*;
use comments::ErrorMatch;
use crossbeam::queue::SegQueue;
use regex::Regex;

use crate::comments::Comments;

mod comments;
#[cfg(test)]
mod tests;

#[derive(Debug)]
pub struct Config {
    /// Arguments passed to the binary that is executed.
    pub args: Vec<String>,
    /// `None` to run on the host, otherwise a target triple
    pub target: Option<String>,
    /// Filters applied to stderr output before processing it
    pub stderr_filters: Filter,
    /// Filters applied to stdout output before processing it
    pub stdout_filters: Filter,
    /// The folder in which to start searching for .rs files
    pub root_dir: PathBuf,
    pub mode: Mode,
    pub program: PathBuf,
    pub output_conflict_handling: OutputConflictHandling,
    /// Only run tests with one of these strings in their path/name
    pub path_filter: Vec<String>,
}

#[derive(Debug)]
pub enum OutputConflictHandling {
    /// The default: emit a diff of the expected/actual output.
    Error,
    /// Ignore mismatches in the stderr/stdout files.
    Ignore,
    /// Instead of erroring if the stderr/stdout differs from the expected
    /// automatically replace it with the found output (after applying filters).
    Bless,
}

pub type Filter = Vec<(Regex, &'static str)>;

pub fn run_tests(config: Config) {
    eprintln!("   Compiler flags: {:?}", config.args);

    // Get the triple with which to run the tests
    let target = config.target.clone().unwrap_or_else(|| config.get_host());

    // A queue for files or folders to process
    let todo = SegQueue::new();
    todo.push(config.root_dir.clone());

    // Some statistics and failure reports.
    let failures = Mutex::new(vec![]);
    let succeeded = AtomicUsize::default();
    let ignored = AtomicUsize::default();

    crossbeam::scope(|s| {
        for _ in 0..std::thread::available_parallelism().unwrap().get() {
            s.spawn(|_| {
                while let Some(path) = todo.pop() {
                    // Collect everything inside directories
                    if path.is_dir() {
                        for entry in std::fs::read_dir(path).unwrap() {
                            todo.push(entry.unwrap().path());
                        }
                        continue;
                    }
                    // Only look at .rs files
                    if !path.extension().map(|ext| ext == "rs").unwrap_or(false) {
                        continue;
                    }
                    if !config.path_filter.is_empty() {
                        let path_display = path.display().to_string();
                        if !config.path_filter.iter().any(|filter| path_display.contains(filter)) {
                            ignored.fetch_add(1, Ordering::Relaxed);
                            eprintln!(
                                "{} .. {}",
                                path_display,
                                "ignored (command line filter)".yellow()
                            );
                            continue;
                        }
                    }
                    let comments = Comments::parse_file(&path);
                    // Ignore file if only/ignore rules do (not) apply
                    if ignore_file(&comments, &target) {
                        ignored.fetch_add(1, Ordering::Relaxed);
                        eprintln!("{} .. {}", path.display(), "ignored".yellow());
                        continue;
                    }
                    // Run the test for all revisions
                    for revision in
                        comments.revisions.clone().unwrap_or_else(|| vec![String::new()])
                    {
                        let (m, errors) = run_test(&path, &config, &target, &revision, &comments);

                        // Using `format` to prevent messages from threads from getting intermingled.
                        let mut msg = format!("{} ", path.display());
                        if !revision.is_empty() {
                            write!(msg, "(revision `{revision}`) ").unwrap();
                        }
                        write!(msg, "... ").unwrap();
                        if errors.is_empty() {
                            eprintln!("{msg}{}", "ok".green());
                            succeeded.fetch_add(1, Ordering::Relaxed);
                        } else {
                            eprintln!("{msg}{}", "FAILED".red().bold());
                            failures.lock().unwrap().push((path.clone(), m, revision, errors));
                        }
                    }
                }
            });
        }
    })
    .unwrap();

    // Print all errors in a single thread to show reliable output
    let failures = failures.into_inner().unwrap();
    let succeeded = succeeded.load(Ordering::Relaxed);
    let ignored = ignored.load(Ordering::Relaxed);
    if !failures.is_empty() {
        for (path, miri, revision, errors) in &failures {
            eprintln!();
            eprint!("{}", path.display().to_string().underline());
            if !revision.is_empty() {
                eprint!(" (revision `{}`)", revision);
            }
            eprint!(" {}", "FAILED".red());
            eprintln!();
            eprintln!("command: {:?}", miri);
            eprintln!();
            let mut dump_stderr = None;
            for error in errors {
                match error {
                    Error::ExitStatus(mode, exit_status) => eprintln!("{mode:?} got {exit_status}"),
                    Error::PatternNotFound { stderr, pattern, definition_line } => {
                        eprintln!("`{pattern}` {} in stderr output", "not found".red());
                        eprintln!(
                            "expected because of pattern here: {}:{definition_line}",
                            path.display().to_string().bold()
                        );
                        dump_stderr = Some(stderr.clone())
                    }
                    Error::NoPatternsFound =>
                        eprintln!("{}", "no error patterns found in failure test".red()),
                    Error::PatternFoundInPassTest =>
                        eprintln!("{}", "error pattern found in success test".red()),
                    Error::OutputDiffers { path, actual, expected } => {
                        dump_stderr = None;
                        eprintln!("actual output differed from expected {}", path.display());
                        eprintln!("{}", pretty_assertions::StrComparison::new(expected, actual));
                        eprintln!()
                    }
                }
                eprintln!();
            }
            if let Some(stderr) = dump_stderr {
                eprintln!("actual stderr:");
                eprintln!("{}", stderr);
                eprintln!();
            }
        }
        eprintln!(
            "{} tests failed, {} tests passed, {} ignored",
            failures.len().to_string().red().bold(),
            succeeded.to_string().green(),
            ignored.to_string().yellow()
        );
        std::process::exit(1);
    }
    eprintln!();
    eprintln!(
        "test result: {}. {} tests passed, {} ignored",
        "ok".green(),
        succeeded.to_string().green(),
        ignored.to_string().yellow()
    );
    eprintln!();
}

#[derive(Debug)]
enum Error {
    /// Got an invalid exit status for the given mode.
    ExitStatus(Mode, ExitStatus),
    PatternNotFound {
        stderr: String,
        pattern: String,
        definition_line: usize,
    },
    /// A ui test checking for failure does not have any failure patterns
    NoPatternsFound,
    /// A ui test checking for success has failure patterns
    PatternFoundInPassTest,
    /// Stderr/Stdout differed from the `.stderr`/`.stdout` file present.
    OutputDiffers {
        path: PathBuf,
        actual: String,
        expected: String,
    },
}

type Errors = Vec<Error>;

fn run_test(
    path: &Path,
    config: &Config,
    target: &str,
    revision: &str,
    comments: &Comments,
) -> (Command, Errors) {
    // Run miri
    let mut miri = Command::new(&config.program);
    miri.args(config.args.iter());
    miri.arg(path);
    if !revision.is_empty() {
        miri.arg(format!("--cfg={revision}"));
    }
    for arg in &comments.compile_flags {
        miri.arg(arg);
    }
    for (k, v) in &comments.env_vars {
        miri.env(k, v);
    }
    let output = miri.output().expect("could not execute miri");
    let mut errors = config.mode.ok(output.status);
    // Check output files (if any)
    let revised = |extension: &str| {
        if revision.is_empty() {
            extension.to_string()
        } else {
            format!("{}.{}", revision, extension)
        }
    };
    // Check output files against actual output
    check_output(
        &output.stderr,
        path,
        &mut errors,
        revised("stderr"),
        target,
        &config.stderr_filters,
        &config,
        comments,
    );
    check_output(
        &output.stdout,
        path,
        &mut errors,
        revised("stdout"),
        target,
        &config.stdout_filters,
        &config,
        comments,
    );
    // Check error annotations in the source against output
    check_annotations(&output.stderr, &mut errors, config, revision, comments);
    (miri, errors)
}

fn check_annotations(
    unnormalized_stderr: &[u8],
    errors: &mut Errors,
    config: &Config,
    revision: &str,
    comments: &Comments,
) {
    let unnormalized_stderr = std::str::from_utf8(unnormalized_stderr).unwrap();
    // erase annotations from the stderr so they don't match themselves
    let annotations = Regex::new(r"\s*//~.*").unwrap();
    let unnormalized_stderr = annotations.replace(unnormalized_stderr, "");
    let mut found_annotation = false;
    if let Some((ref error_pattern, definition_line)) = comments.error_pattern {
        if !unnormalized_stderr.contains(error_pattern) {
            errors.push(Error::PatternNotFound {
                stderr: unnormalized_stderr.to_string(),
                pattern: error_pattern.to_string(),
                definition_line,
            });
        }
        found_annotation = true;
    }
    for &ErrorMatch { ref matched, revision: ref rev, definition_line } in &comments.error_matches {
        // FIXME: check that the error happens on the marked line

        if let Some(rev) = rev {
            if rev != revision {
                continue;
            }
        }

        if !unnormalized_stderr.contains(matched) {
            errors.push(Error::PatternNotFound {
                stderr: unnormalized_stderr.to_string(),
                pattern: matched.to_string(),
                definition_line,
            });
        }
        found_annotation = true;
    }
    match (config.mode, found_annotation) {
        (Mode::Pass, true) | (Mode::Panic, true) => errors.push(Error::PatternFoundInPassTest),
        (Mode::Fail, false) => errors.push(Error::NoPatternsFound),
        _ => {}
    };
}

fn check_output(
    output: &[u8],
    path: &Path,
    errors: &mut Errors,
    kind: String,
    target: &str,
    filters: &Filter,
    config: &Config,
    comments: &Comments,
) {
    let output = std::str::from_utf8(&output).unwrap();
    let output = normalize(path, output, filters, comments);
    let path = output_path(path, comments, kind, target);
    match config.output_conflict_handling {
        OutputConflictHandling::Bless =>
            if output.is_empty() {
                let _ = std::fs::remove_file(path);
            } else {
                std::fs::write(path, &output).unwrap();
            },
        OutputConflictHandling::Error => {
            let expected_output = std::fs::read_to_string(&path).unwrap_or_default();
            if output != expected_output {
                errors.push(Error::OutputDiffers {
                    path,
                    actual: output,
                    expected: expected_output,
                });
            }
        }
        OutputConflictHandling::Ignore => {}
    }
}

fn output_path(path: &Path, comments: &Comments, kind: String, target: &str) -> PathBuf {
    if comments.stderr_per_bitwidth {
        return path.with_extension(format!("{}.{kind}", get_pointer_width(target)));
    }
    path.with_extension(kind)
}

fn ignore_file(comments: &Comments, target: &str) -> bool {
    for s in &comments.ignore {
        if target.contains(s) {
            return true;
        }
        if get_pointer_width(target) == s {
            return true;
        }
    }
    for s in &comments.only {
        if !target.contains(s) {
            return true;
        }
        if get_pointer_width(target) != s {
            return true;
        }
    }
    false
}

// Taken 1:1 from compiletest-rs
fn get_pointer_width(triple: &str) -> &'static str {
    if (triple.contains("64") && !triple.ends_with("gnux32") && !triple.ends_with("gnu_ilp32"))
        || triple.starts_with("s390x")
    {
        "64bit"
    } else if triple.starts_with("avr") {
        "16bit"
    } else {
        "32bit"
    }
}

fn normalize(path: &Path, text: &str, filters: &Filter, comments: &Comments) -> String {
    // Useless paths
    let mut text = text.replace(&path.parent().unwrap().display().to_string(), "$DIR");
    if let Some(lib_path) = option_env!("RUSTC_LIB_PATH") {
        text = text.replace(lib_path, "RUSTLIB");
    }

    for (regex, replacement) in filters.iter() {
        text = regex.replace_all(&text, *replacement).to_string();
    }

    for (from, to) in &comments.normalize_stderr {
        text = from.replace_all(&text, to).to_string();
    }
    text
}

impl Config {
    fn get_host(&self) -> String {
        rustc_version::VersionMeta::for_command(std::process::Command::new(&self.program))
            .expect("failed to parse rustc version info")
            .host
    }
}

#[derive(Copy, Clone, Debug)]
pub enum Mode {
    // The test passes a full execution of the rustc driver
    Pass,
    // The rustc driver panicked
    Panic,
    // The rustc driver emitted an error
    Fail,
}

impl Mode {
    fn ok(self, status: ExitStatus) -> Errors {
        match (status.code().unwrap(), self) {
            (1, Mode::Fail) | (101, Mode::Panic) | (0, Mode::Pass) => vec![],
            _ => vec![Error::ExitStatus(self, status)],
        }
    }
}
<commit_msg>ui_test: printing more consistent with compiletest<commit_after>use std::fmt::Write;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;

use colored::*;
use comments::ErrorMatch;
use crossbeam::queue::SegQueue;
use regex::Regex;

use crate::comments::Comments;

mod comments;
#[cfg(test)]
mod tests;

#[derive(Debug)]
pub struct Config {
    /// Arguments passed to the binary that is executed.
    pub args: Vec<String>,
    /// `None` to run on the host, otherwise a target triple
    pub target: Option<String>,
    /// Filters applied to stderr output before processing it
    pub stderr_filters: Filter,
    /// Filters applied to stdout output before processing it
    pub stdout_filters: Filter,
    /// The folder in which to start searching for .rs files
    pub root_dir: PathBuf,
    pub mode: Mode,
    pub program: PathBuf,
    pub output_conflict_handling: OutputConflictHandling,
    /// Only run tests with one of these strings in their path/name
    pub path_filter: Vec<String>,
}

#[derive(Debug)]
pub enum OutputConflictHandling {
    /// The default: emit a diff of the expected/actual output.
    Error,
    /// Ignore mismatches in the stderr/stdout files.
    Ignore,
    /// Instead of erroring if the stderr/stdout differs from the expected
    /// automatically replace it with the found output (after applying filters).
    Bless,
}

pub type Filter = Vec<(Regex, &'static str)>;

pub fn run_tests(config: Config) {
    eprintln!("   Compiler flags: {:?}", config.args);

    // Get the triple with which to run the tests
    let target = config.target.clone().unwrap_or_else(|| config.get_host());

    // A queue for files or folders to process
    let todo = SegQueue::new();
    todo.push(config.root_dir.clone());

    // Some statistics and failure reports.
    let failures = Mutex::new(vec![]);
    let succeeded = AtomicUsize::default();
    let ignored = AtomicUsize::default();
    let filtered = AtomicUsize::default();

    crossbeam::scope(|s| {
        for _ in 0..std::thread::available_parallelism().unwrap().get() {
            s.spawn(|_| {
                while let Some(path) = todo.pop() {
                    // Collect everything inside directories
                    if path.is_dir() {
                        for entry in std::fs::read_dir(path).unwrap() {
                            todo.push(entry.unwrap().path());
                        }
                        continue;
                    }
                    // Only look at .rs files
                    if !path.extension().map(|ext| ext == "rs").unwrap_or(false) {
                        continue;
                    }
                    if !config.path_filter.is_empty() {
                        let path_display = path.display().to_string();
                        if !config.path_filter.iter().any(|filter| path_display.contains(filter)) {
                            filtered.fetch_add(1, Ordering::Relaxed);
                            continue;
                        }
                    }
                    let comments = Comments::parse_file(&path);
                    // Ignore file if only/ignore rules do (not) apply
                    if ignore_file(&comments, &target) {
                        ignored.fetch_add(1, Ordering::Relaxed);
                        eprintln!("{} ... {}", path.display(), "ignored".yellow());
                        continue;
                    }
                    // Run the test for all revisions
                    for revision in
                        comments.revisions.clone().unwrap_or_else(|| vec![String::new()])
                    {
                        let (m, errors) = run_test(&path, &config, &target, &revision, &comments);

                        // Using `format` to prevent messages from threads from getting intermingled.
                        let mut msg = format!("{} ", path.display());
                        if !revision.is_empty() {
                            write!(msg, "(revision `{revision}`) ").unwrap();
                        }
                        write!(msg, "... ").unwrap();
                        if errors.is_empty() {
                            eprintln!("{msg}{}", "ok".green());
                            succeeded.fetch_add(1, Ordering::Relaxed);
                        } else {
                            eprintln!("{msg}{}", "FAILED".red().bold());
                            failures.lock().unwrap().push((path.clone(), m, revision, errors));
                        }
                    }
                }
            });
        }
    })
    .unwrap();

    // Print all errors in a single thread to show reliable output
    let failures = failures.into_inner().unwrap();
    let succeeded = succeeded.load(Ordering::Relaxed);
    let ignored = ignored.load(Ordering::Relaxed);
    let filtered = filtered.load(Ordering::Relaxed);
    if !failures.is_empty() {
        for (path, miri, revision, errors) in &failures {
            eprintln!();
            eprint!("{}", path.display().to_string().underline());
            if !revision.is_empty() {
                eprint!(" (revision `{}`)", revision);
            }
            eprint!(" {}", "FAILED".red());
            eprintln!();
            eprintln!("command: {:?}", miri);
            eprintln!();
            let mut dump_stderr = None;
            for error in errors {
                match error {
                    Error::ExitStatus(mode, exit_status) => eprintln!("{mode:?} got {exit_status}"),
                    Error::PatternNotFound { stderr, pattern, definition_line } => {
                        eprintln!("`{pattern}` {} in stderr output", "not found".red());
                        eprintln!(
                            "expected because of pattern here: {}:{definition_line}",
                            path.display().to_string().bold()
                        );
                        dump_stderr = Some(stderr.clone())
                    }
                    Error::NoPatternsFound =>
                        eprintln!("{}", "no error patterns found in failure test".red()),
                    Error::PatternFoundInPassTest =>
                        eprintln!("{}", "error pattern found in success test".red()),
                    Error::OutputDiffers { path, actual, expected } => {
                        dump_stderr = None;
                        eprintln!("actual output differed from expected {}", path.display());
                        eprintln!("{}", pretty_assertions::StrComparison::new(expected, actual));
                        eprintln!()
                    }
                }
                eprintln!();
            }
            if let Some(stderr) = dump_stderr {
                eprintln!("actual stderr:");
                eprintln!("{}", stderr);
                eprintln!();
            }
        }
        eprintln!(
            "test result: {}. {} tests failed, {} tests passed, {} ignored, {} filtered out",
            "FAIL".red(),
            failures.len().to_string().red().bold(),
            succeeded.to_string().green(),
            ignored.to_string().yellow(),
            filtered.to_string().yellow(),
        );
        std::process::exit(1);
    }
    eprintln!();
    eprintln!(
        "test result: {}. {} tests passed, {} ignored, {} filtered out",
        "ok".green(),
        succeeded.to_string().green(),
        ignored.to_string().yellow(),
        filtered.to_string().yellow(),
    );
    eprintln!();
}

#[derive(Debug)]
enum Error {
    /// Got an invalid exit status for the given mode.
    ExitStatus(Mode, ExitStatus),
    PatternNotFound {
        stderr: String,
        pattern: String,
        definition_line: usize,
    },
    /// A ui test checking for failure does not have any failure patterns
    NoPatternsFound,
    /// A ui test checking for success has failure patterns
    PatternFoundInPassTest,
    /// Stderr/Stdout differed from the `.stderr`/`.stdout` file present.
    OutputDiffers {
        path: PathBuf,
        actual: String,
        expected: String,
    },
}

type Errors = Vec<Error>;

fn run_test(
    path: &Path,
    config: &Config,
    target: &str,
    revision: &str,
    comments: &Comments,
) -> (Command, Errors) {
    // Run miri
    let mut miri = Command::new(&config.program);
    miri.args(config.args.iter());
    miri.arg(path);
    if !revision.is_empty() {
        miri.arg(format!("--cfg={revision}"));
    }
    for arg in &comments.compile_flags {
        miri.arg(arg);
    }
    for (k, v) in &comments.env_vars {
        miri.env(k, v);
    }
    let output = miri.output().expect("could not execute miri");
    let mut errors = config.mode.ok(output.status);
    // Check output files (if any)
    let revised = |extension: &str| {
        if revision.is_empty() {
            extension.to_string()
        } else {
            format!("{}.{}", revision, extension)
        }
    };
    // Check output files against actual output
    check_output(
        &output.stderr,
        path,
        &mut errors,
        revised("stderr"),
        target,
        &config.stderr_filters,
        &config,
        comments,
    );
    check_output(
        &output.stdout,
        path,
        &mut errors,
        revised("stdout"),
        target,
        &config.stdout_filters,
        &config,
        comments,
    );
    // Check error annotations in the source against output
    check_annotations(&output.stderr, &mut errors, config, revision, comments);
    (miri, errors)
}

fn check_annotations(
    unnormalized_stderr: &[u8],
    errors: &mut Errors,
    config: &Config,
    revision: &str,
    comments: &Comments,
) {
    let unnormalized_stderr = std::str::from_utf8(unnormalized_stderr).unwrap();
    // erase annotations from the stderr so they don't match themselves
    let annotations = Regex::new(r"\s*//~.*").unwrap();
    let unnormalized_stderr = annotations.replace(unnormalized_stderr, "");
    let mut found_annotation = false;
    if let Some((ref error_pattern, definition_line)) = comments.error_pattern {
        if !unnormalized_stderr.contains(error_pattern) {
            errors.push(Error::PatternNotFound {
                stderr: unnormalized_stderr.to_string(),
                pattern: error_pattern.to_string(),
                definition_line,
            });
        }
        found_annotation = true;
    }
    for &ErrorMatch { ref matched, revision: ref rev, definition_line } in &comments.error_matches {
        // FIXME: check that the error happens on the marked line

        if let Some(rev) = rev {
            if rev != revision {
                continue;
            }
        }

        if !unnormalized_stderr.contains(matched) {
            errors.push(Error::PatternNotFound {
                stderr: unnormalized_stderr.to_string(),
                pattern: matched.to_string(),
                definition_line,
            });
        }
        found_annotation = true;
    }
    match (config.mode, found_annotation) {
        (Mode::Pass, true) | (Mode::Panic, true) => errors.push(Error::PatternFoundInPassTest),
        (Mode::Fail, false) => errors.push(Error::NoPatternsFound),
        _ => {}
    };
}

fn check_output(
    output: &[u8],
    path: &Path,
    errors: &mut Errors,
    kind: String,
    target: &str,
    filters: &Filter,
    config: &Config,
    comments: &Comments,
) {
    let output = std::str::from_utf8(&output).unwrap();
    let output = normalize(path, output, filters, comments);
    let path = output_path(path, comments, kind, target);
    match config.output_conflict_handling {
        OutputConflictHandling::Bless =>
            if output.is_empty() {
                let _ = std::fs::remove_file(path);
            } else {
                std::fs::write(path, &output).unwrap();
            },
        OutputConflictHandling::Error => {
            let expected_output = std::fs::read_to_string(&path).unwrap_or_default();
            if output != expected_output {
                errors.push(Error::OutputDiffers {
                    path,
                    actual: output,
                    expected: expected_output,
                });
            }
        }
        OutputConflictHandling::Ignore => {}
    }
}

fn output_path(path: &Path, comments: &Comments, kind: String, target: &str) -> PathBuf {
    if comments.stderr_per_bitwidth {
        return path.with_extension(format!("{}.{kind}", get_pointer_width(target)));
    }
    path.with_extension(kind)
}

fn ignore_file(comments: &Comments, target: &str) -> bool {
    for s in &comments.ignore {
        if target.contains(s) {
            return true;
        }
        if get_pointer_width(target) == s {
            return true;
        }
    }
    for s in &comments.only {
        if !target.contains(s) {
            return true;
        }
        if get_pointer_width(target) != s {
            return true;
        }
    }
    false
}

// Taken 1:1 from compiletest-rs
fn get_pointer_width(triple: &str) -> &'static str {
    if (triple.contains("64") && !triple.ends_with("gnux32") && !triple.ends_with("gnu_ilp32"))
        || triple.starts_with("s390x")
    {
        "64bit"
    } else if triple.starts_with("avr") {
        "16bit"
    } else {
        "32bit"
    }
}

fn normalize(path: &Path, text: &str, filters: &Filter, comments: &Comments) -> String {
    // Useless paths
    let mut text = text.replace(&path.parent().unwrap().display().to_string(), "$DIR");
    if let Some(lib_path) = option_env!("RUSTC_LIB_PATH") {
        text = text.replace(lib_path, "RUSTLIB");
    }

    for (regex, replacement) in filters.iter() {
        text = regex.replace_all(&text, *replacement).to_string();
    }

    for (from, to) in &comments.normalize_stderr {
        text = from.replace_all(&text, to).to_string();
    }
    text
}

impl Config {
    fn get_host(&self) -> String {
        rustc_version::VersionMeta::for_command(std::process::Command::new(&self.program))
            .expect("failed to parse rustc version info")
            .host
    }
}

#[derive(Copy, Clone, Debug)]
pub enum Mode {
    // The test passes a full execution of the rustc driver
    Pass,
    // The rustc driver panicked
    Panic,
    // The rustc driver emitted an error
    Fail,
}

impl Mode {
    fn ok(self, status: ExitStatus) -> Errors {
        match (status.code().unwrap(), self) {
            (1, Mode::Fail) | (101, Mode::Panic) | (0, Mode::Pass) => vec![],
            _ => vec![Error::ExitStatus(self, status)],
        }
    }
}
<|endoftext|>


<commit_before>use common::take_cell::TakeCell;
use hil::{AppId,Driver,Callback,AppSlice,Shared,NUM_PROCS};
use hil::uart::{UART, Client};

///
/// Nrf51822Serialization is the kernel-level driver that provides
/// the UART API that the nRF51822 serialization library requires.
///

struct App {
    callback:      Option<Callback>,
    tx_buffer:     Option<AppSlice<Shared, u8>>,
    rx_buffer:     Option<AppSlice<Shared, u8>>,
    rx_recv_so_far: usize,  // How many RX bytes we have currently received.
    rx_recv_total:   usize   // The total number of bytes we expect to receive.
}

// Local buffer for storing data between when the application passes it to
// use
pub static mut WRITE_BUF : [u8; 256] = [0; 256];

// We need two resources: a UART HW driver and driver state for each
// application.
pub struct Nrf51822Serialization<'a, U: UART + 'a> {
    uart: &'a U,
    apps: [TakeCell<App>; NUM_PROCS],
    buffer: TakeCell<&'static mut [u8]>
}

impl<'a, U: UART> Nrf51822Serialization<'a, U> {
    pub const fn new(uart: &'a U, buffer: &'static mut [u8]) -> Nrf51822Serialization<'a, U> {
        Nrf51822Serialization {
            uart: uart,
            apps: [TakeCell::empty()],
            buffer: TakeCell::new(buffer)
        }
    }

    pub fn initialize(&self) {
        self.uart.enable_tx();
        self.uart.enable_rx();
    }
}

impl<'a, U: UART> Driver for Nrf51822Serialization<'a, U> {

    /// Pass application space memory to this driver.
    ///
    /// allow_type: 0 - Provide an RX buffer
    /// allow_type: 1 - Provide an TX buffer
    ///
    fn allow(&self,
             appid: AppId,
             allow_type: usize,
             slice: AppSlice<Shared, u8>) -> isize {
        let app = appid.idx();
        match allow_type {
            0 => {
                let resapp = match self.apps[app].take() {
                    Some(mut app) => {
                        app.rx_buffer = Some(slice);
                        app.rx_recv_so_far = 0;
                        app.rx_recv_total = 0;
                        app
                    },
                    None => App {
                        callback:       None,
                        tx_buffer:      None,
                        rx_buffer:      Some(slice),
                        rx_recv_so_far: 0,
                        rx_recv_total:  0
                    }
                };
                self.apps[app].replace(resapp);
                0
            },
            1 => {
                let resapp = match self.apps[app].take() {
                    Some(mut app) => {
                        app.tx_buffer = Some(slice);
                        app
                    },
                    None => App {
                        callback:       None,
                        tx_buffer:      Some(slice),
                        rx_buffer:      None,
                        rx_recv_so_far: 0,
                        rx_recv_total:  0
                    }
                };
                self.apps[app].replace(resapp);
                0
            },
            _ => -1
        }
    }

    /// Register a callback to the Nrf51822Serialization driver.
    ///
    /// The callback will be called when a TX finishes and when
    /// RX data is available.
    ///
    /// subscribe_type: 0 - add the callback
    ///
    #[inline(never)]
    fn subscribe(&self, subscribe_type: usize, callback: Callback) -> isize {
        let app = callback.app_id().idx();
        match subscribe_type {
            0 => {
                let resapp = match self.apps[app].take() {
                    Some(mut app) => {
                        app.callback = Some(callback);
                        app
                    },
                    None => App {
                        callback:       Some(callback),
                        tx_buffer:      None,
                        rx_buffer:      None,
                        rx_recv_so_far: 0,
                        rx_recv_total:  0
                    }
                };
                self.apps[app].replace(resapp);
                0
            },
            _ => -1
        }
    }

    /// Issue a command to the Nrf51822Serialization driver.
    ///
    /// command_type: 0 - Write a byte to the UART.
    ///
    fn command(&self, command_type: usize, arg1: usize) -> isize {

        match command_type {
            0 => {
                // On a TX, send the first byte of the TX buffer.
                // TODO(bradjc): Need to match this to the correct app!
                //               Can't just use 0!
                let result = self.apps[0].map(|appst| {

                    match appst.tx_buffer.take() {
                        Some(slice) => {
                            let write_len = slice.len();
                            self.buffer.take().map(|buffer| {
                                for (i, c) in slice.as_ref().iter().enumerate() {
                                    buffer[i] = *c;
                                }
                                self.uart.send_bytes(buffer, write_len);
                            });
                            0
                        },
                        None => -2
                    }
                });
                result.unwrap_or(-1)
            },
            _ => -1
        }
    }
}

fn each_some<'a, T, I, F>(lst: I, mut f: F)
        where T: 'a, I: Iterator<Item=&'a TakeCell<T>>, F: FnMut(&mut T) {
    for item in lst {
        item.map(|i| f(i));
    }
}

// Callbacks from the underlying UART driver.
impl<'a, U: UART> Client for Nrf51822Serialization<'a, U> {

    // Called when the UART TX has finished
    fn write_done(&self, buffer: &'static mut [u8]) {
        self.buffer.replace(buffer);
        // TODO(bradjc): Need to match this to the correct app!
        //               Can't just use 0!
        self.apps[0].map(|appst| {
            // Call the callback after TX has finished
            appst.callback.as_mut().map(|mut cb| {
                cb.schedule(1, 0, 0);
            });
        });
    }

    // Called when a byte is received on the UART
    fn read_done(&self, c: u8) {
        each_some(self.apps.iter(), |appst| {
            // The PHY layer of the serialization protocol calls for a 16 byte
            // length field to start the packet. After we receive the first two
            // bytes we then know how long to wait for to get the rest of
            // the packet.

            // Save a local copy of this so we can use it after we have a borrow
            let rx_count = appst.rx_recv_so_far;

            if appst.rx_buffer.is_some() &&
               rx_count < appst.rx_buffer.as_ref().unwrap().len() {

                // This is just some rust magic that only gets a mutable
                // reference to the RX buffer and adds the byte if the buffer
                // actually exists.
                // Yes, we did already check that the buffer exists above,
                // but I don't know what to do about that....
                appst.rx_buffer.as_mut().map(|buf| {
                    // Record the received byte
                    buf.as_mut()[rx_count] = c;

                });

                // Increment our counter since we got another byte.
                appst.rx_recv_so_far += 1;

                // Check if this was the second byte. If so, we can now
                // compute how many total bytes we expect to receive.
                if appst.rx_recv_so_far == 2 {
                    appst.rx_recv_total = appst.rx_buffer.as_ref().unwrap().as_ref()[0] as usize |
                                          ((appst.rx_buffer.as_ref().unwrap().as_ref()[1] as usize) << 8);

                    // After first byte let app know that a packet is inbound!
                    let rx_recv_total = appst.rx_recv_total;
                    appst.callback.as_mut().map(|mut cb| {
                        cb.schedule(2, rx_recv_total, 0);
                    });

                } else if appst.rx_recv_so_far > 2 {
                    // Check to see if we have gotten all of the data
                    // we want.
                    if appst.rx_recv_so_far == appst.rx_recv_total + 2 {
                        // we did!

                        // Callback the app with an RX done signal
                        let rx_recv_so_far = appst.rx_recv_so_far;
                        appst.callback.as_mut().map(|mut cb| {
                            cb.schedule(3, rx_recv_so_far, 0);
                        });

                        // Reset this for the next RX
                        appst.rx_recv_so_far = 0;
                    }
                }
            }
        });
    }
}
<commit_msg>Fix unused variable warning in driver<commit_after>use common::take_cell::TakeCell;
use hil::{AppId,Driver,Callback,AppSlice,Shared,NUM_PROCS};
use hil::uart::{UART, Client};

///
/// Nrf51822Serialization is the kernel-level driver that provides
/// the UART API that the nRF51822 serialization library requires.
///

struct App {
    callback:      Option<Callback>,
    tx_buffer:     Option<AppSlice<Shared, u8>>,
    rx_buffer:     Option<AppSlice<Shared, u8>>,
    rx_recv_so_far: usize,  // How many RX bytes we have currently received.
    rx_recv_total:   usize   // The total number of bytes we expect to receive.
}

// Local buffer for storing data between when the application passes it to
// use
pub static mut WRITE_BUF : [u8; 256] = [0; 256];

// We need two resources: a UART HW driver and driver state for each
// application.
pub struct Nrf51822Serialization<'a, U: UART + 'a> {
    uart: &'a U,
    apps: [TakeCell<App>; NUM_PROCS],
    buffer: TakeCell<&'static mut [u8]>
}

impl<'a, U: UART> Nrf51822Serialization<'a, U> {
    pub const fn new(uart: &'a U, buffer: &'static mut [u8]) -> Nrf51822Serialization<'a, U> {
        Nrf51822Serialization {
            uart: uart,
            apps: [TakeCell::empty()],
            buffer: TakeCell::new(buffer)
        }
    }

    pub fn initialize(&self) {
        self.uart.enable_tx();
        self.uart.enable_rx();
    }
}

impl<'a, U: UART> Driver for Nrf51822Serialization<'a, U> {

    /// Pass application space memory to this driver.
    ///
    /// allow_type: 0 - Provide an RX buffer
    /// allow_type: 1 - Provide an TX buffer
    ///
    fn allow(&self,
             appid: AppId,
             allow_type: usize,
             slice: AppSlice<Shared, u8>) -> isize {
        let app = appid.idx();
        match allow_type {
            0 => {
                let resapp = match self.apps[app].take() {
                    Some(mut app) => {
                        app.rx_buffer = Some(slice);
                        app.rx_recv_so_far = 0;
                        app.rx_recv_total = 0;
                        app
                    },
                    None => App {
                        callback:       None,
                        tx_buffer:      None,
                        rx_buffer:      Some(slice),
                        rx_recv_so_far: 0,
                        rx_recv_total:  0
                    }
                };
                self.apps[app].replace(resapp);
                0
            },
            1 => {
                let resapp = match self.apps[app].take() {
                    Some(mut app) => {
                        app.tx_buffer = Some(slice);
                        app
                    },
                    None => App {
                        callback:       None,
                        tx_buffer:      Some(slice),
                        rx_buffer:      None,
                        rx_recv_so_far: 0,
                        rx_recv_total:  0
                    }
                };
                self.apps[app].replace(resapp);
                0
            },
            _ => -1
        }
    }

    /// Register a callback to the Nrf51822Serialization driver.
    ///
    /// The callback will be called when a TX finishes and when
    /// RX data is available.
    ///
    /// subscribe_type: 0 - add the callback
    ///
    #[inline(never)]
    fn subscribe(&self, subscribe_type: usize, callback: Callback) -> isize {
        let app = callback.app_id().idx();
        match subscribe_type {
            0 => {
                let resapp = match self.apps[app].take() {
                    Some(mut app) => {
                        app.callback = Some(callback);
                        app
                    },
                    None => App {
                        callback:       Some(callback),
                        tx_buffer:      None,
                        rx_buffer:      None,
                        rx_recv_so_far: 0,
                        rx_recv_total:  0
                    }
                };
                self.apps[app].replace(resapp);
                0
            },
            _ => -1
        }
    }

    /// Issue a command to the Nrf51822Serialization driver.
    ///
    /// command_type: 0 - Write a byte to the UART.
    ///
    fn command(&self, command_type: usize, _: usize) -> isize {

        match command_type {
            0 => {
                // On a TX, send the first byte of the TX buffer.
                // TODO(bradjc): Need to match this to the correct app!
                //               Can't just use 0!
                let result = self.apps[0].map(|appst| {

                    match appst.tx_buffer.take() {
                        Some(slice) => {
                            let write_len = slice.len();
                            self.buffer.take().map(|buffer| {
                                for (i, c) in slice.as_ref().iter().enumerate() {
                                    buffer[i] = *c;
                                }
                                self.uart.send_bytes(buffer, write_len);
                            });
                            0
                        },
                        None => -2
                    }
                });
                result.unwrap_or(-1)
            },
            _ => -1
        }
    }
}

fn each_some<'a, T, I, F>(lst: I, mut f: F)
        where T: 'a, I: Iterator<Item=&'a TakeCell<T>>, F: FnMut(&mut T) {
    for item in lst {
        item.map(|i| f(i));
    }
}

// Callbacks from the underlying UART driver.
impl<'a, U: UART> Client for Nrf51822Serialization<'a, U> {

    // Called when the UART TX has finished
    fn write_done(&self, buffer: &'static mut [u8]) {
        self.buffer.replace(buffer);
        // TODO(bradjc): Need to match this to the correct app!
        //               Can't just use 0!
        self.apps[0].map(|appst| {
            // Call the callback after TX has finished
            appst.callback.as_mut().map(|mut cb| {
                cb.schedule(1, 0, 0);
            });
        });
    }

    // Called when a byte is received on the UART
    fn read_done(&self, c: u8) {
        each_some(self.apps.iter(), |appst| {
            // The PHY layer of the serialization protocol calls for a 16 byte
            // length field to start the packet. After we receive the first two
            // bytes we then know how long to wait for to get the rest of
            // the packet.

            // Save a local copy of this so we can use it after we have a borrow
            let rx_count = appst.rx_recv_so_far;

            if appst.rx_buffer.is_some() &&
               rx_count < appst.rx_buffer.as_ref().unwrap().len() {

                // This is just some rust magic that only gets a mutable
                // reference to the RX buffer and adds the byte if the buffer
                // actually exists.
                // Yes, we did already check that the buffer exists above,
                // but I don't know what to do about that....
                appst.rx_buffer.as_mut().map(|buf| {
                    // Record the received byte
                    buf.as_mut()[rx_count] = c;

                });

                // Increment our counter since we got another byte.
                appst.rx_recv_so_far += 1;

                // Check if this was the second byte. If so, we can now
                // compute how many total bytes we expect to receive.
                if appst.rx_recv_so_far == 2 {
                    appst.rx_recv_total = appst.rx_buffer.as_ref().unwrap().as_ref()[0] as usize |
                                          ((appst.rx_buffer.as_ref().unwrap().as_ref()[1] as usize) << 8);

                    // After first byte let app know that a packet is inbound!
                    let rx_recv_total = appst.rx_recv_total;
                    appst.callback.as_mut().map(|mut cb| {
                        cb.schedule(2, rx_recv_total, 0);
                    });

                } else if appst.rx_recv_so_far > 2 {
                    // Check to see if we have gotten all of the data
                    // we want.
                    if appst.rx_recv_so_far == appst.rx_recv_total + 2 {
                        // we did!

                        // Callback the app with an RX done signal
                        let rx_recv_so_far = appst.rx_recv_so_far;
                        appst.callback.as_mut().map(|mut cb| {
                            cb.schedule(3, rx_recv_so_far, 0);
                        });

                        // Reset this for the next RX
                        appst.rx_recv_so_far = 0;
                    }
                }
            }
        });
    }
}
<|endoftext|>


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

use dom::bindings::refcounted::Trusted;
use dom::event::{EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use script_thread::{MainThreadRunnable, MainThreadScriptMsg, Runnable, ScriptThread};
use std::result::Result;
use std::sync::mpsc::Sender;
use string_cache::Atom;
use task_source::TaskSource;

#[derive(JSTraceable, Clone)]
pub struct DOMManipulationTaskSource(pub Sender<MainThreadScriptMsg>);

impl TaskSource<DOMManipulationTask> for DOMManipulationTaskSource {
    fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> {
        self.0.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ())
    }
}

impl DOMManipulationTaskSource {
    pub fn queue_event(&self,
                       target: &EventTarget,
                       name: Atom,
                       bubbles: EventBubbles,
                       cancelable: EventCancelable) {
        let target = Trusted::new(target);
        let _ = self.0.send(MainThreadScriptMsg::DOMManipulation(DOMManipulationTask::FireEvent(
            target, name, bubbles, cancelable)));
    }

    pub fn queue_simple_event(&self, target: &EventTarget, name: Atom) {
        let target = Trusted::new(target);
        let _ = self.0.send(MainThreadScriptMsg::DOMManipulation(DOMManipulationTask::FireSimpleEvent(
            target, name)));
    }
}

pub enum DOMManipulationTask {
    // https://html.spec.whatwg.org/multipage/#the-end step 7
    DocumentProgress(Box<Runnable + Send>),
    // https://dom.spec.whatwg.org/#concept-event-fire
    FireEvent(Trusted<EventTarget>, Atom, EventBubbles, EventCancelable),
    // https://html.spec.whatwg.org/multipage/#fire-a-simple-event
    FireSimpleEvent(Trusted<EventTarget>, Atom),
    // https://html.spec.whatwg.org/multipage/#details-notification-task-steps
    FireToggleEvent(Box<Runnable + Send>),
    // Placeholder until there's a real media element task queue implementation
    MediaTask(Box<Runnable + Send>),
    // https://html.spec.whatwg.org/multipage/#planned-navigation
    PlannedNavigation(Box<Runnable + Send>),
    // https://html.spec.whatwg.org/multipage/#send-a-storage-notification
    SendStorageNotification(Box<MainThreadRunnable + Send>)
}

impl DOMManipulationTask {
    pub fn handle_task(self, script_thread: &ScriptThread) {
        use self::DOMManipulationTask::*;

        match self {
            DocumentProgress(runnable) => runnable.handler(),
            FireEvent(element, name, bubbles, cancelable) => {
                let target = element.root();
                target.fire_event(&*name, bubbles, cancelable);
            }
            FireSimpleEvent(element, name) => {
                let target = element.root();
                target.fire_simple_event(&*name);
            }
            FireToggleEvent(runnable) => runnable.handler(),
            MediaTask(runnable) => runnable.handler(),
            PlannedNavigation(runnable) => runnable.handler(),
            SendStorageNotification(runnable) => runnable.handler(script_thread)
        }
    }
}
<commit_msg>Add Miscellaneous event type to DOM task source<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::refcounted::Trusted;
use dom::event::{EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use script_thread::{MainThreadRunnable, MainThreadScriptMsg, Runnable, ScriptThread};
use std::result::Result;
use std::sync::mpsc::Sender;
use string_cache::Atom;
use task_source::TaskSource;

#[derive(JSTraceable, Clone)]
pub struct DOMManipulationTaskSource(pub Sender<MainThreadScriptMsg>);

impl TaskSource<DOMManipulationTask> for DOMManipulationTaskSource {
    fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> {
        self.0.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ())
    }
}

impl DOMManipulationTaskSource {
    pub fn queue_event(&self,
                       target: &EventTarget,
                       name: Atom,
                       bubbles: EventBubbles,
                       cancelable: EventCancelable) {
        let target = Trusted::new(target);
        let _ = self.0.send(MainThreadScriptMsg::DOMManipulation(DOMManipulationTask::FireEvent(
            target, name, bubbles, cancelable)));
    }

    pub fn queue_simple_event(&self, target: &EventTarget, name: Atom) {
        let target = Trusted::new(target);
        let _ = self.0.send(MainThreadScriptMsg::DOMManipulation(DOMManipulationTask::FireSimpleEvent(
            target, name)));
    }
}

pub enum DOMManipulationTask {
    // https://html.spec.whatwg.org/multipage/#the-end step 7
    DocumentProgress(Box<Runnable + Send>),
    // https://dom.spec.whatwg.org/#concept-event-fire
    FireEvent(Trusted<EventTarget>, Atom, EventBubbles, EventCancelable),
    // https://html.spec.whatwg.org/multipage/#fire-a-simple-event
    FireSimpleEvent(Trusted<EventTarget>, Atom),
    // https://html.spec.whatwg.org/multipage/#details-notification-task-steps
    FireToggleEvent(Box<Runnable + Send>),
    // Placeholder until there's a real media element task queue implementation
    MediaTask(Box<Runnable + Send>),
    // https://html.spec.whatwg.org/multipage/#planned-navigation
    PlannedNavigation(Box<Runnable + Send>),
    // https://html.spec.whatwg.org/multipage/#send-a-storage-notification
    SendStorageNotification(Box<MainThreadRunnable + Send>),
    Miscellaneous(Box<Runnable + Send>),
}

impl DOMManipulationTask {
    pub fn handle_task(self, script_thread: &ScriptThread) {
        use self::DOMManipulationTask::*;

        match self {
            DocumentProgress(runnable) => runnable.handler(),
            FireEvent(element, name, bubbles, cancelable) => {
                let target = element.root();
                target.fire_event(&*name, bubbles, cancelable);
            }
            FireSimpleEvent(element, name) => {
                let target = element.root();
                target.fire_simple_event(&*name);
            }
            FireToggleEvent(runnable) => runnable.handler(),
            MediaTask(runnable) => runnable.handler(),
            PlannedNavigation(runnable) => runnable.handler(),
            SendStorageNotification(runnable) => runnable.handler(script_thread),
            Miscellaneous(runnable) => runnable.handler(),
        }
    }
}
<|endoftext|>


<commit_before>use crate::validators::num::*;
use clap::{App, AppSettings, Arg, Shell, SubCommand};

pub fn build_cli() -> App<'static, 'static> {
    let database_arg = Arg::with_name("DATABASE_URL")
        .long("database-url")
        .help(
            "Specifies the database URL to connect to. Falls back to \
             the DATABASE_URL environment variable if unspecified.",
        )
        .global(true)
        .takes_value(true);

    let migration_subcommand = SubCommand::with_name("migration")
        .about(
            "A group of commands for generating, running, and reverting \
             migrations.",
        )
        .setting(AppSettings::VersionlessSubcommands)
        .arg(migration_dir_arg())
        .subcommand(SubCommand::with_name("run").about("Runs all pending migrations"))
        .subcommand(
            SubCommand::with_name("revert")
                .about("Reverts the specified migrations")
                .arg(
                    Arg::with_name("REVERT_ALL")
                        .long("all")
                        .short("a")
                        .help("Reverts previously run migration files.")
                        .takes_value(false)
                        .conflicts_with("REVERT_NUMBER"),
                )
                .arg(
                    Arg::with_name("REVERT_NUMBER")
                        .long("number")
                        .short("n")
                        .help("Reverts the last `n` migration files")
                        .long_help(
                            "When this option is specified the last `n` migration files \
                             will be reverted. By default revert the last one.",
                        )
                        // TODO : when upgrading to clap 3.0 add default_value("1").
                        // Then update code in main.rs for the revert subcommand.
                        // See https://github.com/clap-rs/clap/issues/1605
                        .takes_value(true)
                        .validator(is_positive_int)
                        .conflicts_with("REVERT_ALL"),
                ),
        )
        .subcommand(
            SubCommand::with_name("redo")
                .about(
                    "Reverts and re-runs the latest migration. Useful \
                     for testing that a migration can in fact be reverted.",
                )
                .arg(
                    Arg::with_name("REDO_ALL")
                        .long("all")
                        .short("a")
                        .help("Reverts and re-runs all migrations.")
                        .long_help(
                            "When this option is specified all migrations \
                             will be reverted and re-runs. Useful for testing \
                             that your migrations can be reverted and applied.",
                        )
                        .takes_value(false)
                        .conflicts_with("REDO_NUMBER"),
                )
                .arg(
                    Arg::with_name("REDO_NUMBER")
                        .long("number")
                        .short("n")
                        .help("Redo the last `n` migration files")
                        .long_help(
                            "When this option is specified the last `n` migration files \
                             will be reverted and re-runs. By default redo the last migration.",
                        )
                        // TODO : when upgrading to clap 3.0 add default_value("1").
                        // Then update code in main.rs for the revert subcommand.
                        // See https://github.com/clap-rs/clap/issues/1605
                        .takes_value(true)
                        .validator(is_positive_int)
                        .conflicts_with("REDO_ALL"),
                ),
        )
        .subcommand(
            SubCommand::with_name("list")
                .about("Lists all available migrations, marking those that have been applied."),
        )
        .subcommand(
            SubCommand::with_name("pending")
                .about("Returns true if there are any pending migrations."),
        )
        .subcommand(
            SubCommand::with_name("generate")
                .about(
                    "Generate a new migration with the given name, and \
                     the current timestamp as the version",
                )
                .arg(
                    Arg::with_name("MIGRATION_NAME")
                        .help("The name of the migration to create")
                        .required(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_VERSION")
                        .long("version")
                        .help(
                            "The version number to use when generating the migration. \
                             Defaults to the current timestamp, which should suffice \
                             for most use cases.",
                        )
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_FORMAT")
                        .long("format")
                        .possible_values(&["sql", "barrel"])
                        .default_value("sql")
                        .takes_value(true)
                        .help("The format of the migration to be generated."),
                ),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let setup_subcommand = SubCommand::with_name("setup")
        .arg(migration_dir_arg())
        .about(
            "Creates the migrations directory, creates the database \
             specified in your DATABASE_URL, and runs existing migrations.",
        );

    let database_subcommand = SubCommand::with_name("database")
        .alias("db")
        .arg(migration_dir_arg())
        .about("A group of commands for setting up and resetting your database.")
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(SubCommand::with_name("setup").about(
            "Creates the database specified in your DATABASE_URL, \
             and then runs any existing migrations.",
        ))
        .subcommand(SubCommand::with_name("reset").about(
            "Resets your database by dropping the database specified \
             in your DATABASE_URL and then running `diesel database setup`.",
        ))
        .subcommand(
            SubCommand::with_name("drop")
                .about("Drops the database specified in your DATABASE_URL.")
                .setting(AppSettings::Hidden),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let generate_bash_completion_subcommand = SubCommand::with_name("bash-completion")
        .about("DEPRECATED: Generate bash completion script for the diesel command.");

    let generate_completions_subcommand = SubCommand::with_name("completions")
        .about("Generate shell completion scripts for the diesel command.")
        .arg(
            Arg::with_name("SHELL")
                .index(1)
                .required(true)
                .possible_values(&Shell::variants()),
        );

    let infer_schema_subcommand = SubCommand::with_name("print-schema")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Print table definitions for database schema.")
        .arg(
            Arg::with_name("schema")
                .long("schema")
                .short("s")
                .takes_value(true)
                .help("The name of the schema."),
        )
        .arg(
            Arg::with_name("table-name")
                .index(1)
                .takes_value(true)
                .multiple(true)
                .help("Table names to filter (default only-tables if not empty)"),
        )
        .arg(
            Arg::with_name("only-tables")
                .short("o")
                .long("only-tables")
                .help("Only include tables from table-name that matches regexp")
                .conflicts_with("except-tables"),
        )
        .arg(
            Arg::with_name("except-tables")
                .short("e")
                .long("except-tables")
                .help("Exclude tables from table-name that matches regex")
                .conflicts_with("only-tables"),
        )
        .arg(
            Arg::with_name("with-docs")
                .long("with-docs")
                .help("Render documentation comments for tables and columns"),
        )
        .arg(
            Arg::with_name("column-sorting")
                .long("column-sorting")
                .help("Sort order for table columns")
                .takes_value(true)
                .possible_values(&["ordinal_position", "name"]),
        )
        .arg(
            Arg::with_name("patch-file")
                .long("patch-file")
                .takes_value(true)
                .help("A unified diff file to be applied to the final schema"),
        )
        .arg(
            Arg::with_name("import-types")
                .long("import-types")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1)
                .help("A list of types to import for every table, separated by commas"),
        );

    let config_arg = Arg::with_name("CONFIG_FILE")
        .long("config-file")
        .help(
            "The location of the configuration file to use. Falls back to the \
             `DIESEL_CONFIG_FILE` environment variable if unspecified. Defaults \
             to `diesel.toml` in your project root. See \
             diesel.rs/guides/configuring-diesel-cli for documentation on this file.",
        )
        .global(true)
        .takes_value(true);

    let locked_schema_arg = Arg::with_name("LOCKED_SCHEMA")
        .long("locked-schema")
        .help("Require that the schema file is up to date")
        .long_help(
            "When `print_schema.file` is specified in your config file, this \
             flag will cause Diesel CLI to error if any command would result in \
             changes to that file. It is recommended that you use this flag when \
             running migrations in CI or production.",
        )
        .global(true);

    App::new("diesel")
        .version(env!("CARGO_PKG_VERSION"))
        .setting(AppSettings::VersionlessSubcommands)
        .after_help(
            "You can also run `diesel SUBCOMMAND -h` to get more information about that subcommand.",
        )
        .arg(database_arg)
        .arg(config_arg)
        .arg(locked_schema_arg)
        .subcommand(migration_subcommand)
        .subcommand(setup_subcommand)
        .subcommand(database_subcommand)
        .subcommand(generate_bash_completion_subcommand)
        .subcommand(generate_completions_subcommand)
        .subcommand(infer_schema_subcommand)
        .setting(AppSettings::SubcommandRequiredElseHelp)
}

fn migration_dir_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name("MIGRATION_DIRECTORY")
        .long("migration-dir")
        .help(
            "The location of your migration directory. By default this \
             will look for a directory called `migrations` in the \
             current directory and its parents.",
        )
        .takes_value(true)
        .global(true)
}
<commit_msg>Uniformly add periods to all help and about.<commit_after>use crate::validators::num::*;
use clap::{App, AppSettings, Arg, Shell, SubCommand};

pub fn build_cli() -> App<'static, 'static> {
    let database_arg = Arg::with_name("DATABASE_URL")
        .long("database-url")
        .help(
            "Specifies the database URL to connect to. Falls back to \
             the DATABASE_URL environment variable if unspecified.",
        )
        .global(true)
        .takes_value(true);

    let migration_subcommand = SubCommand::with_name("migration")
        .about(
            "A group of commands for generating, running, and reverting \
             migrations.",
        )
        .setting(AppSettings::VersionlessSubcommands)
        .arg(migration_dir_arg())
        .subcommand(SubCommand::with_name("run").about("Runs all pending migrations."))
        .subcommand(
            SubCommand::with_name("revert")
                .about("Reverts the specified migrations.")
                .arg(
                    Arg::with_name("REVERT_ALL")
                        .long("all")
                        .short("a")
                        .help("Reverts previously run migration files.")
                        .takes_value(false)
                        .conflicts_with("REVERT_NUMBER"),
                )
                .arg(
                    Arg::with_name("REVERT_NUMBER")
                        .long("number")
                        .short("n")
                        .help("Reverts the last `n` migration files.")
                        .long_help(
                            "When this option is specified the last `n` migration files \
                             will be reverted. By default revert the last one.",
                        )
                        // TODO : when upgrading to clap 3.0 add default_value("1").
                        // Then update code in main.rs for the revert subcommand.
                        // See https://github.com/clap-rs/clap/issues/1605
                        .takes_value(true)
                        .validator(is_positive_int)
                        .conflicts_with("REVERT_ALL"),
                ),
        )
        .subcommand(
            SubCommand::with_name("redo")
                .about(
                    "Reverts and re-runs the latest migration. Useful \
                     for testing that a migration can in fact be reverted.",
                )
                .arg(
                    Arg::with_name("REDO_ALL")
                        .long("all")
                        .short("a")
                        .help("Reverts and re-runs all migrations.")
                        .long_help(
                            "When this option is specified all migrations \
                             will be reverted and re-runs. Useful for testing \
                             that your migrations can be reverted and applied.",
                        )
                        .takes_value(false)
                        .conflicts_with("REDO_NUMBER"),
                )
                .arg(
                    Arg::with_name("REDO_NUMBER")
                        .long("number")
                        .short("n")
                        .help("Redo the last `n` migration files.")
                        .long_help(
                            "When this option is specified the last `n` migration files \
                             will be reverted and re-runs. By default redo the last migration.",
                        )
                        // TODO : when upgrading to clap 3.0 add default_value("1").
                        // Then update code in main.rs for the revert subcommand.
                        // See https://github.com/clap-rs/clap/issues/1605
                        .takes_value(true)
                        .validator(is_positive_int)
                        .conflicts_with("REDO_ALL"),
                ),
        )
        .subcommand(
            SubCommand::with_name("list")
                .about("Lists all available migrations, marking those that have been applied."),
        )
        .subcommand(
            SubCommand::with_name("pending")
                .about("Returns true if there are any pending migrations."),
        )
        .subcommand(
            SubCommand::with_name("generate")
                .about(
                    "Generate a new migration with the given name, and \
                     the current timestamp as the version.",
                )
                .arg(
                    Arg::with_name("MIGRATION_NAME")
                        .help("The name of the migration to create.")
                        .required(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_VERSION")
                        .long("version")
                        .help(
                            "The version number to use when generating the migration. \
                             Defaults to the current timestamp, which should suffice \
                             for most use cases.",
                        )
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("MIGRATION_FORMAT")
                        .long("format")
                        .possible_values(&["sql", "barrel"])
                        .default_value("sql")
                        .takes_value(true)
                        .help("The format of the migration to be generated."),
                ),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let setup_subcommand = SubCommand::with_name("setup")
        .arg(migration_dir_arg())
        .about(
            "Creates the migrations directory, creates the database \
             specified in your DATABASE_URL, and runs existing migrations.",
        );

    let database_subcommand = SubCommand::with_name("database")
        .alias("db")
        .arg(migration_dir_arg())
        .about("A group of commands for setting up and resetting your database.")
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(SubCommand::with_name("setup").about(
            "Creates the database specified in your DATABASE_URL, \
             and then runs any existing migrations.",
        ))
        .subcommand(SubCommand::with_name("reset").about(
            "Resets your database by dropping the database specified \
             in your DATABASE_URL and then running `diesel database setup`.",
        ))
        .subcommand(
            SubCommand::with_name("drop")
                .about("Drops the database specified in your DATABASE_URL.")
                .setting(AppSettings::Hidden),
        )
        .setting(AppSettings::SubcommandRequiredElseHelp);

    let generate_bash_completion_subcommand = SubCommand::with_name("bash-completion")
        .about("DEPRECATED: Generate bash completion script for the diesel command.");

    let generate_completions_subcommand = SubCommand::with_name("completions")
        .about("Generate shell completion scripts for the diesel command.")
        .arg(
            Arg::with_name("SHELL")
                .index(1)
                .required(true)
                .possible_values(&Shell::variants()),
        );

    let infer_schema_subcommand = SubCommand::with_name("print-schema")
        .setting(AppSettings::VersionlessSubcommands)
        .about("Print table definitions for database schema.")
        .arg(
            Arg::with_name("schema")
                .long("schema")
                .short("s")
                .takes_value(true)
                .help("The name of the schema."),
        )
        .arg(
            Arg::with_name("table-name")
                .index(1)
                .takes_value(true)
                .multiple(true)
                .help("Table names to filter (default only-tables if not empty)."),
        )
        .arg(
            Arg::with_name("only-tables")
                .short("o")
                .long("only-tables")
                .help("Only include tables from table-name that matches regexp.")
                .conflicts_with("except-tables"),
        )
        .arg(
            Arg::with_name("except-tables")
                .short("e")
                .long("except-tables")
                .help("Exclude tables from table-name that matches regex.")
                .conflicts_with("only-tables"),
        )
        .arg(
            Arg::with_name("with-docs")
                .long("with-docs")
                .help("Render documentation comments for tables and columns."),
        )
        .arg(
            Arg::with_name("column-sorting")
                .long("column-sorting")
                .help("Sort order for table columns.")
                .takes_value(true)
                .possible_values(&["ordinal_position", "name"]),
        )
        .arg(
            Arg::with_name("patch-file")
                .long("patch-file")
                .takes_value(true)
                .help("A unified diff file to be applied to the final schema."),
        )
        .arg(
            Arg::with_name("import-types")
                .long("import-types")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1)
                .help("A list of types to import for every table, separated by commas."),
        );

    let config_arg = Arg::with_name("CONFIG_FILE")
        .long("config-file")
        .help(
            "The location of the configuration file to use. Falls back to the \
             `DIESEL_CONFIG_FILE` environment variable if unspecified. Defaults \
             to `diesel.toml` in your project root. See \
             diesel.rs/guides/configuring-diesel-cli for documentation on this file.",
        )
        .global(true)
        .takes_value(true);

    let locked_schema_arg = Arg::with_name("LOCKED_SCHEMA")
        .long("locked-schema")
        .help("Require that the schema file is up to date.")
        .long_help(
            "When `print_schema.file` is specified in your config file, this \
             flag will cause Diesel CLI to error if any command would result in \
             changes to that file. It is recommended that you use this flag when \
             running migrations in CI or production.",
        )
        .global(true);

    App::new("diesel")
        .version(env!("CARGO_PKG_VERSION"))
        .setting(AppSettings::VersionlessSubcommands)
        .after_help(
            "You can also run `diesel SUBCOMMAND -h` to get more information about that subcommand.",
        )
        .arg(database_arg)
        .arg(config_arg)
        .arg(locked_schema_arg)
        .subcommand(migration_subcommand)
        .subcommand(setup_subcommand)
        .subcommand(database_subcommand)
        .subcommand(generate_bash_completion_subcommand)
        .subcommand(generate_completions_subcommand)
        .subcommand(infer_schema_subcommand)
        .setting(AppSettings::SubcommandRequiredElseHelp)
}

fn migration_dir_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name("MIGRATION_DIRECTORY")
        .long("migration-dir")
        .help(
            "The location of your migration directory. By default this \
             will look for a directory called `migrations` in the \
             current directory and its parents.",
        )
        .takes_value(true)
        .global(true)
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::net::ToSocketAddrs;

use futures::stream;

use http2::server::Http2Server;
use http2::http_common::*;
use http2::Header;
use http2::StaticHeader;
use http2::futures_misc::*;

pub struct HttpServerEcho {
    server: Http2Server,
    pub port: u16,
}

struct EchoService {
}

impl HttpService for EchoService {
    fn new_request(&self, headers: Vec<StaticHeader>, req: HttpStreamStreamSend) -> HttpStreamStreamSend {
        Box::new(stream_concat(
            stream::once(Ok(HttpStreamPart::intermediate_headers(vec![
                Header::new(":status", "200"),
            ]))),
            req,
        ))
    }
}

impl HttpServerEcho {
    pub fn new() -> HttpServerEcho {
        let http_server = Http2Server::new(0, EchoService {});
        let port = http_server.local_addr().port();
        HttpServerEcho {
            server: http_server,
            port: port,
        }
    }
}
<commit_msg>warnings<commit_after>#![allow(dead_code)]

use futures::stream;

use http2::server::Http2Server;
use http2::http_common::*;
use http2::Header;
use http2::StaticHeader;
use http2::futures_misc::*;

pub struct HttpServerEcho {
    server: Http2Server,
    pub port: u16,
}

struct EchoService {
}

impl HttpService for EchoService {
    fn new_request(&self, _headers: Vec<StaticHeader>, req: HttpStreamStreamSend) -> HttpStreamStreamSend {
        Box::new(stream_concat(
            stream::once(Ok(HttpStreamPart::intermediate_headers(vec![
                Header::new(":status", "200"),
            ]))),
            req,
        ))
    }
}

impl HttpServerEcho {
    pub fn new() -> HttpServerEcho {
        let http_server = Http2Server::new(0, EchoService {});
        let port = http_server.local_addr().port();
        HttpServerEcho {
            server: http_server,
            port: port,
        }
    }
}
<|endoftext|>


<commit_before>/* automatically generated by rust-bindgen */

#[repr(C)]
pub struct Struct_zmq_msg_t {
    pub unnamed_field1: [::libc::c_uchar, ..32u],
}
pub type zmq_msg_t = Struct_zmq_msg_t;
pub type zmq_free_fn = ::libc::c_void;
#[repr(C)]
pub struct Struct_Unnamed1 {
    pub event: uint16_t,
    pub value: int32_t,
}
pub type zmq_event_t = Struct_Unnamed1;
pub enum Struct_iovec { }
#[repr(C)]
pub struct Struct_Unnamed2 {
    pub socket: *mut ::libc::c_void,
    pub fd: ::libc::c_int,
    pub events: ::libc::c_short,
    pub revents: ::libc::c_short,
}
pub type zmq_pollitem_t = Struct_Unnamed2;
extern "C" { }
extern "C" {
    pub fn zmq_version(major: *mut ::libc::c_int, minor: *mut ::libc::c_int,
                       patch: *mut ::libc::c_int);
    pub fn zmq_errno() -> ::libc::c_int;
    pub fn zmq_strerror(errnum: ::libc::c_int) -> *const ::libc::c_char;
    pub fn zmq_ctx_new() -> *mut ::libc::c_void;
    pub fn zmq_ctx_term(context: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_ctx_shutdown(ctx_: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_ctx_set(context: *mut ::libc::c_void, option: ::libc::c_int,
                       optval: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_ctx_get(context: *mut ::libc::c_void, option: ::libc::c_int)
     -> ::libc::c_int;
    pub fn zmq_init(io_threads: ::libc::c_int) -> *mut ::libc::c_void;
    pub fn zmq_term(context: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_ctx_destroy(context: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_msg_init(msg: *mut zmq_msg_t) -> ::libc::c_int;
    pub fn zmq_msg_init_size(msg: *mut zmq_msg_t, size: size_t)
     -> ::libc::c_int;
    pub fn zmq_msg_init_data(msg: *mut zmq_msg_t, data: *mut ::libc::c_void,
                             size: size_t, ffn: *mut zmq_free_fn,
                             hint: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_msg_send(msg: *mut zmq_msg_t, s: *mut ::libc::c_void,
                        flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_msg_recv(msg: *mut zmq_msg_t, s: *mut ::libc::c_void,
                        flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_msg_close(msg: *mut zmq_msg_t) -> ::libc::c_int;
    pub fn zmq_msg_move(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> ::libc::c_int;
    pub fn zmq_msg_copy(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> ::libc::c_int;
    pub fn zmq_msg_data(msg: *mut zmq_msg_t) -> *mut ::libc::c_void;
    pub fn zmq_msg_size(msg: *mut zmq_msg_t) -> size_t;
    pub fn zmq_msg_more(msg: *mut zmq_msg_t) -> ::libc::c_int;
    pub fn zmq_msg_get(msg: *mut zmq_msg_t, option: ::libc::c_int)
     -> ::libc::c_int;
    pub fn zmq_msg_set(msg: *mut zmq_msg_t, option: ::libc::c_int,
                       optval: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_socket(arg1: *mut ::libc::c_void, _type: ::libc::c_int)
     -> *mut ::libc::c_void;
    pub fn zmq_close(s: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_setsockopt(s: *mut ::libc::c_void, option: ::libc::c_int,
                          optval: *const ::libc::c_void, optvallen: size_t)
     -> ::libc::c_int;
    pub fn zmq_getsockopt(s: *mut ::libc::c_void, option: ::libc::c_int,
                          optval: *mut ::libc::c_void, optvallen: *mut size_t)
     -> ::libc::c_int;
    pub fn zmq_bind(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_connect(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_unbind(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_disconnect(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_send(s: *mut ::libc::c_void, buf: *const ::libc::c_void,
                    len: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_send_const(s: *mut ::libc::c_void, buf: *const ::libc::c_void,
                          len: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_recv(s: *mut ::libc::c_void, buf: *mut ::libc::c_void,
                    len: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_socket_monitor(s: *mut ::libc::c_void,
                              addr: *const ::libc::c_char,
                              events: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_sendmsg(s: *mut ::libc::c_void, msg: *mut zmq_msg_t,
                       flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_recvmsg(s: *mut ::libc::c_void, msg: *mut zmq_msg_t,
                       flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_sendiov(s: *mut ::libc::c_void, iov: *mut Struct_iovec,
                       count: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_recviov(s: *mut ::libc::c_void, iov: *mut Struct_iovec,
                       count: *mut size_t, flags: ::libc::c_int)
     -> ::libc::c_int;
    pub fn zmq_poll(items: *mut zmq_pollitem_t, nitems: ::libc::c_int,
                    timeout: ::libc::c_long) -> ::libc::c_int;
    pub fn zmq_proxy(frontend: *mut ::libc::c_void,
                     backend: *mut ::libc::c_void,
                     capture: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_proxy_steerable(frontend: *mut ::libc::c_void,
                               backend: *mut ::libc::c_void,
                               capture: *mut ::libc::c_void,
                               control: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_z85_encode(dest: *mut ::libc::c_char, data: *mut uint8_t,
                          size: size_t) -> *mut ::libc::c_char;
    pub fn zmq_z85_decode(dest: *mut uint8_t, string: *mut ::libc::c_char)
     -> *mut uint8_t;
    pub fn zmq_device(_type: ::libc::c_int, frontend: *mut ::libc::c_void,
                      backend: *mut ::libc::c_void) -> ::libc::c_int;
}
<commit_msg>link zmq-sys with zmq<commit_after>/* automatically generated by rust-bindgen */

#[repr(C)]
pub struct Struct_zmq_msg_t {
    pub unnamed_field1: [::libc::c_uchar, ..32u],
}
pub type zmq_msg_t = Struct_zmq_msg_t;
pub type zmq_free_fn = ::libc::c_void;
#[repr(C)]
pub struct Struct_Unnamed1 {
    pub event: uint16_t,
    pub value: int32_t,
}
pub type zmq_event_t = Struct_Unnamed1;
pub enum Struct_iovec { }
#[repr(C)]
pub struct Struct_Unnamed2 {
    pub socket: *mut ::libc::c_void,
    pub fd: ::libc::c_int,
    pub events: ::libc::c_short,
    pub revents: ::libc::c_short,
}
pub type zmq_pollitem_t = Struct_Unnamed2;
#[link(name = "zmq")]
extern "C" { }
#[link(name = "zmq")]
extern "C" {
    pub fn zmq_version(major: *mut ::libc::c_int, minor: *mut ::libc::c_int,
                       patch: *mut ::libc::c_int);
    pub fn zmq_errno() -> ::libc::c_int;
    pub fn zmq_strerror(errnum: ::libc::c_int) -> *const ::libc::c_char;
    pub fn zmq_ctx_new() -> *mut ::libc::c_void;
    pub fn zmq_ctx_term(context: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_ctx_shutdown(ctx_: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_ctx_set(context: *mut ::libc::c_void, option: ::libc::c_int,
                       optval: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_ctx_get(context: *mut ::libc::c_void, option: ::libc::c_int)
     -> ::libc::c_int;
    pub fn zmq_init(io_threads: ::libc::c_int) -> *mut ::libc::c_void;
    pub fn zmq_term(context: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_ctx_destroy(context: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_msg_init(msg: *mut zmq_msg_t) -> ::libc::c_int;
    pub fn zmq_msg_init_size(msg: *mut zmq_msg_t, size: size_t)
     -> ::libc::c_int;
    pub fn zmq_msg_init_data(msg: *mut zmq_msg_t, data: *mut ::libc::c_void,
                             size: size_t, ffn: *mut zmq_free_fn,
                             hint: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_msg_send(msg: *mut zmq_msg_t, s: *mut ::libc::c_void,
                        flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_msg_recv(msg: *mut zmq_msg_t, s: *mut ::libc::c_void,
                        flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_msg_close(msg: *mut zmq_msg_t) -> ::libc::c_int;
    pub fn zmq_msg_move(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> ::libc::c_int;
    pub fn zmq_msg_copy(dest: *mut zmq_msg_t, src: *mut zmq_msg_t)
     -> ::libc::c_int;
    pub fn zmq_msg_data(msg: *mut zmq_msg_t) -> *mut ::libc::c_void;
    pub fn zmq_msg_size(msg: *mut zmq_msg_t) -> size_t;
    pub fn zmq_msg_more(msg: *mut zmq_msg_t) -> ::libc::c_int;
    pub fn zmq_msg_get(msg: *mut zmq_msg_t, option: ::libc::c_int)
     -> ::libc::c_int;
    pub fn zmq_msg_set(msg: *mut zmq_msg_t, option: ::libc::c_int,
                       optval: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_socket(arg1: *mut ::libc::c_void, _type: ::libc::c_int)
     -> *mut ::libc::c_void;
    pub fn zmq_close(s: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_setsockopt(s: *mut ::libc::c_void, option: ::libc::c_int,
                          optval: *const ::libc::c_void, optvallen: size_t)
     -> ::libc::c_int;
    pub fn zmq_getsockopt(s: *mut ::libc::c_void, option: ::libc::c_int,
                          optval: *mut ::libc::c_void, optvallen: *mut size_t)
     -> ::libc::c_int;
    pub fn zmq_bind(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_connect(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_unbind(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_disconnect(s: *mut ::libc::c_void, addr: *const ::libc::c_char)
     -> ::libc::c_int;
    pub fn zmq_send(s: *mut ::libc::c_void, buf: *const ::libc::c_void,
                    len: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_send_const(s: *mut ::libc::c_void, buf: *const ::libc::c_void,
                          len: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_recv(s: *mut ::libc::c_void, buf: *mut ::libc::c_void,
                    len: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_socket_monitor(s: *mut ::libc::c_void,
                              addr: *const ::libc::c_char,
                              events: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_sendmsg(s: *mut ::libc::c_void, msg: *mut zmq_msg_t,
                       flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_recvmsg(s: *mut ::libc::c_void, msg: *mut zmq_msg_t,
                       flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_sendiov(s: *mut ::libc::c_void, iov: *mut Struct_iovec,
                       count: size_t, flags: ::libc::c_int) -> ::libc::c_int;
    pub fn zmq_recviov(s: *mut ::libc::c_void, iov: *mut Struct_iovec,
                       count: *mut size_t, flags: ::libc::c_int)
     -> ::libc::c_int;
    pub fn zmq_poll(items: *mut zmq_pollitem_t, nitems: ::libc::c_int,
                    timeout: ::libc::c_long) -> ::libc::c_int;
    pub fn zmq_proxy(frontend: *mut ::libc::c_void,
                     backend: *mut ::libc::c_void,
                     capture: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_proxy_steerable(frontend: *mut ::libc::c_void,
                               backend: *mut ::libc::c_void,
                               capture: *mut ::libc::c_void,
                               control: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn zmq_z85_encode(dest: *mut ::libc::c_char, data: *mut uint8_t,
                          size: size_t) -> *mut ::libc::c_char;
    pub fn zmq_z85_decode(dest: *mut uint8_t, string: *mut ::libc::c_char)
     -> *mut uint8_t;
    pub fn zmq_device(_type: ::libc::c_int, frontend: *mut ::libc::c_void,
                      backend: *mut ::libc::c_void) -> ::libc::c_int;
}
<|endoftext|>