<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 std::env;
use std::error;
use std::fmt;
use std::io;
use std::path::Path;
use std::process::Command;
use std::str::{from_utf8, Utf8Error};

extern crate tempfile;
use self::tempfile::Builder;

#[derive(Debug)]
/// Possible errors that can occur during `rustc --pretty=expanded`.
pub enum Error {
    /// Error during creation of temporary directory
    Io(io::Error),
    /// Output of `cargo metadata` was not valid utf8
    Utf8(Utf8Error),
    /// Error during execution of `cargo rustc --pretty=expanded`
    Compile(String),
}

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

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Io(ref err) => err.fmt(f),
            Error::Utf8(ref err) => err.fmt(f),
            Error::Compile(ref err) => write!(f, "{}", err),
        }
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::Io(ref err) => Some(err),
            Error::Utf8(ref err) => Some(err),
            Error::Compile(..) => None,
        }
    }
}

/// Use rustc to expand and pretty print the crate into a single file,
/// removing any macros in the process.
pub fn expand(
    manifest_path: &Path,
    crate_name: &str,
    version: &str,
    use_tempdir: bool,
    expand_all_features: bool,
    expand_default_features: bool,
    expand_features: &Option<Vec<String>>,
) -> Result<String, Error> {
    let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
    let mut cmd = Command::new(cargo);

    let mut _temp_dir = None; // drop guard
    if use_tempdir {
        _temp_dir = Some(Builder::new().prefix("cbindgen-expand").tempdir()?);
        cmd.env("CARGO_TARGET_DIR", _temp_dir.unwrap().path());
    } else if let Ok(ref path) = env::var("CARGO_EXPAND_TARGET_DIR") {
        cmd.env("CARGO_TARGET_DIR", path);
    }

    cmd.arg("rustc");
    cmd.arg("--lib");
    cmd.arg("--manifest-path");
    cmd.arg(manifest_path);
    if let Some(features) = expand_features {
        cmd.arg("--features");
        let mut features_str = String::new();
        for (index, feature) in features.iter().enumerate() {
            if index != 0 {
                features_str.push_str(" ");
            }
            features_str.push_str(feature);
        }
        cmd.arg(features_str);
    }
    if expand_all_features {
        cmd.arg("--all-features");
    }
    if !expand_default_features {
        cmd.arg("--no-default-features");
    }
    cmd.arg("-p");
    cmd.arg(&format!("{}:{}", crate_name, version));
    cmd.arg("--");
    cmd.arg("-Z");
    cmd.arg("unstable-options");
    cmd.arg("--pretty=expanded");
    let output = cmd.output()?;

    let src = from_utf8(&output.stdout)?.to_owned();
    let error = from_utf8(&output.stderr)?.to_owned();

    if src.len() == 0 {
        Err(Error::Compile(error))
    } else {
        Ok(src)
    }
}
<commit_msg>Run cargo expand outside the normal target directory<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 std::env;
use std::error;
use std::fmt;
use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::{from_utf8, Utf8Error};

extern crate tempfile;
use self::tempfile::Builder;

#[derive(Debug)]
/// Possible errors that can occur during `rustc --pretty=expanded`.
pub enum Error {
    /// Error during creation of temporary directory
    Io(io::Error),
    /// Output of `cargo metadata` was not valid utf8
    Utf8(Utf8Error),
    /// Error during execution of `cargo rustc --pretty=expanded`
    Compile(String),
}

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

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Io(ref err) => err.fmt(f),
            Error::Utf8(ref err) => err.fmt(f),
            Error::Compile(ref err) => write!(f, "{}", err),
        }
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Error::Io(ref err) => Some(err),
            Error::Utf8(ref err) => Some(err),
            Error::Compile(..) => None,
        }
    }
}

/// Use rustc to expand and pretty print the crate into a single file,
/// removing any macros in the process.
pub fn expand(
    manifest_path: &Path,
    crate_name: &str,
    version: &str,
    use_tempdir: bool,
    expand_all_features: bool,
    expand_default_features: bool,
    expand_features: &Option<Vec<String>>,
) -> Result<String, Error> {
    let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
    let mut cmd = Command::new(cargo);

    let mut _temp_dir = None; // drop guard
    if use_tempdir {
        _temp_dir = Some(Builder::new().prefix("cbindgen-expand").tempdir()?);
        cmd.env("CARGO_TARGET_DIR", _temp_dir.unwrap().path());
    } else if let Ok(ref path) = env::var("CARGO_EXPAND_TARGET_DIR") {
        cmd.env("CARGO_TARGET_DIR", path);
    } else if let Ok(ref path) = env::var("OUT_DIR") {
        // When cbindgen was started programatically from a build.rs file, Cargo is running and
        // locking the default target directory. In this case we need to use another directory,
        // else we would end up in a deadlock. If Cargo is running `OUT_DIR` will be set, so we
        // can use a directory relative to that.
        cmd.env("CARGO_TARGET_DIR", PathBuf::from(path).join("expanded"));
    }

    cmd.arg("rustc");
    cmd.arg("--lib");
    cmd.arg("--manifest-path");
    cmd.arg(manifest_path);
    if let Some(features) = expand_features {
        cmd.arg("--features");
        let mut features_str = String::new();
        for (index, feature) in features.iter().enumerate() {
            if index != 0 {
                features_str.push_str(" ");
            }
            features_str.push_str(feature);
        }
        cmd.arg(features_str);
    }
    if expand_all_features {
        cmd.arg("--all-features");
    }
    if !expand_default_features {
        cmd.arg("--no-default-features");
    }
    cmd.arg("-p");
    cmd.arg(&format!("{}:{}", crate_name, version));
    cmd.arg("--");
    cmd.arg("-Z");
    cmd.arg("unstable-options");
    cmd.arg("--pretty=expanded");
    let output = cmd.output()?;

    let src = from_utf8(&output.stdout)?.to_owned();
    let error = from_utf8(&output.stderr)?.to_owned();

    if src.len() == 0 {
        Err(Error::Compile(error))
    } else {
        Ok(src)
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;
use std::path::Path;

use anyhow::{anyhow, bail, Context, Result};
use procfs::process::Process;
use pueue_lib::network::message::*;
use pueue_lib::settings::*;

use super::*;

/// Send the Shutdown message to the test daemon.
pub async fn shutdown_daemon(shared: &Shared) -> Result<Message> {
    let message = Message::DaemonShutdown(Shutdown::Graceful);

    send_message(shared, message)
        .await
        .context("Failed to send Shutdown message")
}

/// Get a daemon pid from a specific pueue directory.
/// This function gives the daemon a little time to boot up, but ultimately crashes if it takes too
/// long.
pub fn get_pid(pid_path: &Path) -> Result<i32> {
    // Give the daemon about 1 sec to boot and create the pid file.
    let tries = 20;
    let mut current_try = 0;

    while current_try < tries {
        // The daemon didn't create the pid file yet. Wait for 100ms and try again.
        if !pid_path.exists() {
            sleep_ms(50);
            current_try += 1;
            continue;
        }

        let mut file = File::open(&pid_path).context("Couldn't open pid file")?;
        let mut content = String::new();
        file.read_to_string(&mut content)
            .context("Couldn't write to file")?;

        // The file has been created but not yet been written to.
        if content.is_empty() {
            sleep_ms(50);
            current_try += 1;
            continue;
        }

        let pid = content
            .parse::<i32>()
            .map_err(|_| anyhow!("Couldn't parse value: {content}"))?;
        return Ok(pid);
    }

    bail!("Couldn't find pid file after about 1 sec.");
}

/// Waits for a daemon to shut down.
/// This is done by waiting for the pid to disappear.
pub fn wait_for_shutdown(pid: i32) -> Result<()> {
    // Try to read the process. If this fails, the daemon already exited.
    let process = match Process::new(pid) {
        Ok(process) => process,
        Err(_) => return Ok(()),
    };

    // Give the daemon about 1 sec to shutdown.
    let tries = 40;
    let mut current_try = 0;

    while current_try < tries {
        // Process is still alive, wait a little longer
        if process.is_alive() {
            sleep_ms(50);
            current_try += 1;
            continue;
        }

        return Ok(());
    }

    bail!("Couldn't find pid file after about 2 sec.");
}
<commit_msg>fix: Test debug message<commit_after>use std::fs::File;
use std::io::Read;
use std::path::Path;

use anyhow::{anyhow, bail, Context, Result};
use procfs::process::Process;
use pueue_lib::network::message::*;
use pueue_lib::settings::*;

use super::*;

/// Send the Shutdown message to the test daemon.
pub async fn shutdown_daemon(shared: &Shared) -> Result<Message> {
    let message = Message::DaemonShutdown(Shutdown::Graceful);

    send_message(shared, message)
        .await
        .context("Failed to send Shutdown message")
}

/// Get a daemon pid from a specific pueue directory.
/// This function gives the daemon a little time to boot up, but ultimately crashes if it takes too
/// long.
pub fn get_pid(pid_path: &Path) -> Result<i32> {
    // Give the daemon about 1 sec to boot and create the pid file.
    let tries = 20;
    let mut current_try = 0;

    while current_try < tries {
        // The daemon didn't create the pid file yet. Wait for 100ms and try again.
        if !pid_path.exists() {
            sleep_ms(50);
            current_try += 1;
            continue;
        }

        let mut file = File::open(&pid_path).context("Couldn't open pid file")?;
        let mut content = String::new();
        file.read_to_string(&mut content)
            .context("Couldn't write to file")?;

        // The file has been created but not yet been written to.
        if content.is_empty() {
            sleep_ms(50);
            current_try += 1;
            continue;
        }

        let pid = content
            .parse::<i32>()
            .map_err(|_| anyhow!("Couldn't parse value: {content}"))?;
        return Ok(pid);
    }

    bail!("Couldn't find pid file after about 1 sec.");
}

/// Waits for a daemon to shut down.
/// This is done by waiting for the pid to disappear.
pub fn wait_for_shutdown(pid: i32) -> Result<()> {
    // Try to read the process. If this fails, the daemon already exited.
    let process = match Process::new(pid) {
        Ok(process) => process,
        Err(_) => return Ok(()),
    };

    // Give the daemon about 1 sec to shutdown.
    let tries = 40;
    let mut current_try = 0;

    while current_try < tries {
        // Process is still alive, wait a little longer
        if process.is_alive() {
            sleep_ms(50);
            current_try += 1;
            continue;
        }

        return Ok(());
    }

    bail!("Pueued daemon didn't shut down after about 2 sec.");
}
<|endoftext|>


<commit_before>use hir::ModPath;
use ra_ide_db::imports_locator::ImportsLocator;
use ra_syntax::{
    ast::{self, AstNode},
    SyntaxNode,
};

use crate::{
    assist_ctx::{ActionBuilder, Assist, AssistCtx},
    auto_import_text_edit, AssistId,
};

// Assist: auto_import
//
// If the name is unresolved, provides all possible imports for it.
//
// ```
// fn main() {
//     let map = HashMap<|>::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn main() {
//     let map = HashMap::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
    let path_to_import: ast::Path = ctx.find_node_at_offset()?;
    let path_to_import_syntax = path_to_import.syntax();
    if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }
    let name_to_import =
        path_to_import_syntax.descendants().find_map(ast::NameRef::cast)?.syntax().to_string();

    let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast);
    let position = match module.and_then(|it| it.item_list()) {
        Some(item_list) => item_list.syntax().clone(),
        None => {
            let current_file = path_to_import_syntax.ancestors().find_map(ast::SourceFile::cast)?;
            current_file.syntax().clone()
        }
    };
    let source_analyzer = ctx.source_analyzer(&position, None);
    let module_with_name_to_import = source_analyzer.module()?;
    if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() {
        return None;
    }

    let mut imports_locator = ImportsLocator::new(ctx.db);

    let proposed_imports = imports_locator
        .find_imports(&name_to_import)
        .into_iter()
        .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
        .filter(|use_path| !use_path.segments.is_empty())
        .take(20)
        .collect::<std::collections::BTreeSet<_>>();
    if proposed_imports.is_empty() {
        return None;
    }

    ctx.add_assist_group(AssistId("auto_import"), format!("Import {}", name_to_import), || {
        proposed_imports
            .into_iter()
            .map(|import| import_to_action(import, &position, &path_to_import_syntax))
            .collect()
    })
}

fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder {
    let mut action_builder = ActionBuilder::default();
    action_builder.label(format!("Import `{}`", &import));
    auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder());
    action_builder
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::helpers::{check_assist, check_assist_not_applicable};

    #[test]
    fn applicable_when_found_an_import() {
        check_assist(
            auto_import,
            r"
            <|>PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
            r"
            <|>use PubMod::PubStruct;

            PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn auto_imports_are_merged() {
        check_assist(
            auto_import,
            r"
            use PubMod::PubStruct1;

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
            r"
            use PubMod::{PubStruct2, PubStruct1};

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
        );
    }

    #[test]
    fn applicable_when_found_multiple_imports() {
        check_assist(
            auto_import,
            r"
            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
            r"
            use PubMod1::PubStruct;

            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_already_imported_types() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubMod::PubStruct;

            PubStruct<|>

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_types_with_private_paths() {
        check_assist_not_applicable(
            auto_import,
            r"
            PrivateStruct<|>

            pub mod PubMod {
                struct PrivateStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_when_no_imports_found() {
        check_assist_not_applicable(
            auto_import,
            "
            PubStruct<|>",
        );
    }

    #[test]
    fn not_applicable_in_import_statements() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubStruct<|>;

            pub mod PubMod {
                pub struct PubStruct;
            }",
        );
    }

    #[test]
    fn function_import() {
        check_assist(
            auto_import,
            r"
            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
            r"
            use PubMod::test_function;

            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
        );
    }
}
<commit_msg>Cleanups<commit_after>use hir::ModPath;
use ra_ide_db::imports_locator::ImportsLocator;
use ra_syntax::{
    ast::{self, AstNode},
    SyntaxNode,
};

use crate::{
    assist_ctx::{ActionBuilder, Assist, AssistCtx},
    auto_import_text_edit, AssistId,
};
use std::collections::BTreeSet;

// Assist: auto_import
//
// If the name is unresolved, provides all possible imports for it.
//
// ```
// fn main() {
//     let map = HashMap<|>::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn main() {
//     let map = HashMap::new();
// }
// # pub mod std { pub mod collections { pub struct HashMap { } } }
// ```
pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
    let path_to_import: ast::Path = ctx.find_node_at_offset()?;
    let path_to_import_syntax = path_to_import.syntax();
    if path_to_import_syntax.ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }
    let name_to_import =
        path_to_import_syntax.descendants().find_map(ast::NameRef::cast)?.syntax().to_string();

    let module = path_to_import_syntax.ancestors().find_map(ast::Module::cast);
    let position = match module.and_then(|it| it.item_list()) {
        Some(item_list) => item_list.syntax().clone(),
        None => {
            let current_file = path_to_import_syntax.ancestors().find_map(ast::SourceFile::cast)?;
            current_file.syntax().clone()
        }
    };
    let source_analyzer = ctx.source_analyzer(&position, None);
    let module_with_name_to_import = source_analyzer.module()?;
    if source_analyzer.resolve_path(ctx.db, &path_to_import).is_some() {
        return None;
    }

    let mut imports_locator = ImportsLocator::new(ctx.db);

    let proposed_imports = imports_locator
        .find_imports(&name_to_import)
        .into_iter()
        .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
        .filter(|use_path| !use_path.segments.is_empty())
        .take(20)
        .collect::<BTreeSet<_>>();

    if proposed_imports.is_empty() {
        return None;
    }

    ctx.add_assist_group(AssistId("auto_import"), format!("Import {}", name_to_import), || {
        proposed_imports
            .into_iter()
            .map(|import| import_to_action(import, &position, &path_to_import_syntax))
            .collect()
    })
}

fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder {
    let mut action_builder = ActionBuilder::default();
    action_builder.label(format!("Import `{}`", &import));
    auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder());
    action_builder
}

#[cfg(test)]
mod tests {
    use crate::helpers::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn applicable_when_found_an_import() {
        check_assist(
            auto_import,
            r"
            <|>PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
            r"
            <|>use PubMod::PubStruct;

            PubStruct

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn auto_imports_are_merged() {
        check_assist(
            auto_import,
            r"
            use PubMod::PubStruct1;

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
            r"
            use PubMod::{PubStruct2, PubStruct1};

            struct Test {
                test: Pub<|>Struct2<u8>,
            }

            pub mod PubMod {
                pub struct PubStruct1;
                pub struct PubStruct2<T> {
                    _t: T,
                }
            }
            ",
        );
    }

    #[test]
    fn applicable_when_found_multiple_imports() {
        check_assist(
            auto_import,
            r"
            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
            r"
            use PubMod1::PubStruct;

            PubSt<|>ruct

            pub mod PubMod1 {
                pub struct PubStruct;
            }
            pub mod PubMod2 {
                pub struct PubStruct;
            }
            pub mod PubMod3 {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_already_imported_types() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubMod::PubStruct;

            PubStruct<|>

            pub mod PubMod {
                pub struct PubStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_for_types_with_private_paths() {
        check_assist_not_applicable(
            auto_import,
            r"
            PrivateStruct<|>

            pub mod PubMod {
                struct PrivateStruct;
            }
            ",
        );
    }

    #[test]
    fn not_applicable_when_no_imports_found() {
        check_assist_not_applicable(
            auto_import,
            "
            PubStruct<|>",
        );
    }

    #[test]
    fn not_applicable_in_import_statements() {
        check_assist_not_applicable(
            auto_import,
            r"
            use PubStruct<|>;

            pub mod PubMod {
                pub struct PubStruct;
            }",
        );
    }

    #[test]
    fn function_import() {
        check_assist(
            auto_import,
            r"
            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
            r"
            use PubMod::test_function;

            test_function<|>

            pub mod PubMod {
                pub fn test_function() {};
            }
            ",
        );
    }
}
<|endoftext|>


<commit_before>#![no_std]

pub mod buttons;
pub mod console;
pub mod led;
#[cfg(feature = "with_nfc")]
pub mod nfc;
pub mod result;
pub mod rng;
pub mod timer;
pub mod usb_ctap_hid;
pub mod util;
<commit_msg>Revert #cfg change<commit_after>#![no_std]

pub mod buttons;
pub mod console;
pub mod led;
pub mod nfc;
pub mod result;
pub mod rng;
pub mod timer;
pub mod usb_ctap_hid;
pub mod util;
<|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/. */

#[macro_use] extern crate procedural_masquerade;
extern crate phf_codegen;
extern crate proc_macro;
#[macro_use] extern crate quote;
extern crate syn;

use std::ascii::AsciiExt;

define_proc_macros! {
    /// Input: the arms of a `match` expression.
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
    ///
    /// Panic if the arms contain non-string patterns,
    /// or string patterns that contains ASCII uppercase letters.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: &str) -> String {
        let expr = syn::parse_expr(&format!("match x {{ {} }}", input)).unwrap();
        let arms = match expr {
            syn::Expr { node: syn::ExprKind::Match(_, ref arms), .. } => arms,
            _ => panic!("expected a match expression, got {:?}", expr)
        };
        max_len(arms.iter().flat_map(|arm| &arm.pats).filter_map(|pattern| {
            let expr = match *pattern {
                syn::Pat::Lit(ref expr) => expr,
                syn::Pat::Wild |
                syn::Pat::Ident(_, _, None) => return None,
                syn::Pat::Ident(_, _, Some(ref sub_pattern)) => {
                    match **sub_pattern {
                        syn::Pat::Lit(ref expr) => expr,
                        syn::Pat::Wild => return None,
                        _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
                    }
                }
                _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
            };
            match **expr {
                syn::Expr { node: syn::ExprKind::Lit(syn::Lit::Str(ref string, _)), .. } => {
                    assert_eq!(*string, string.to_ascii_lowercase(),
                               "string patterns must be given in ASCII lowercase");
                    Some(string.len())
                }
                _ => panic!("expected string pattern, got {:?}", expr)
            }
        }))
    }

    /// Input: string literals with no separator
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__max_len(input: &str) -> String {
        max_len(syn::parse_token_trees(input).unwrap().iter().map(|tt| string_literal(tt).len()))
    }

    /// Input: parsed as token trees. The first TT is a type. (Can be wrapped in parens.)
    /// following TTs are grouped in pairs, each pair being a key as a string literal
    /// and the corresponding value as a const expression.
    ///
    /// Output: a rust-phf map, with keys ASCII-lowercased:
    /// ```
    /// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
    /// ```
    #[allow(non_snake_case)]
    pub fn cssparser_internal__phf_map(input: &str) -> String {
        let token_trees = syn::parse_token_trees(input).unwrap();
        let value_type = &token_trees[0];
        let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
            let key = string_literal(&chunk[0]);
            let value = &chunk[1];
            (key.to_ascii_lowercase(), quote!(#value).to_string())
        }).collect();

        let mut map = phf_codegen::Map::new();
        map.phf_path("::cssparser::_internal__phf");
        for &(ref key, ref value) in &pairs {
            map.entry(&**key, &**value);
        }

        let mut tokens = quote! {
            static MAP: ::cssparser::_internal__phf::Map<&'static str, #value_type> =
        };
        let mut initializer_bytes = Vec::new();
        map.build(&mut initializer_bytes).unwrap();
        tokens.append(::std::str::from_utf8(&initializer_bytes).unwrap());
        tokens.append(";");
        tokens.into_string()
    }
}

fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
    let max_length = lengths.max().expect("expected at least one string");
    quote!( const MAX_LENGTH: usize = #max_length; ).into_string()
}

fn string_literal(token: &syn::TokenTree) -> &str {
    match *token {
        syn::TokenTree::Token(syn::Token::Literal(syn::Lit::Str(ref string, _))) => string,
        _ => panic!("expected string literal, got {:?}", token)
    }
}
<commit_msg>Mark invalid Rust as text-only documentation.<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/. */

#[macro_use] extern crate procedural_masquerade;
extern crate phf_codegen;
extern crate proc_macro;
#[macro_use] extern crate quote;
extern crate syn;

use std::ascii::AsciiExt;

define_proc_macros! {
    /// Input: the arms of a `match` expression.
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
    ///
    /// Panic if the arms contain non-string patterns,
    /// or string patterns that contains ASCII uppercase letters.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__assert_ascii_lowercase__max_len(input: &str) -> String {
        let expr = syn::parse_expr(&format!("match x {{ {} }}", input)).unwrap();
        let arms = match expr {
            syn::Expr { node: syn::ExprKind::Match(_, ref arms), .. } => arms,
            _ => panic!("expected a match expression, got {:?}", expr)
        };
        max_len(arms.iter().flat_map(|arm| &arm.pats).filter_map(|pattern| {
            let expr = match *pattern {
                syn::Pat::Lit(ref expr) => expr,
                syn::Pat::Wild |
                syn::Pat::Ident(_, _, None) => return None,
                syn::Pat::Ident(_, _, Some(ref sub_pattern)) => {
                    match **sub_pattern {
                        syn::Pat::Lit(ref expr) => expr,
                        syn::Pat::Wild => return None,
                        _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
                    }
                }
                _ => panic!("expected string or wildcard pattern, got {:?}", pattern)
            };
            match **expr {
                syn::Expr { node: syn::ExprKind::Lit(syn::Lit::Str(ref string, _)), .. } => {
                    assert_eq!(*string, string.to_ascii_lowercase(),
                               "string patterns must be given in ASCII lowercase");
                    Some(string.len())
                }
                _ => panic!("expected string pattern, got {:?}", expr)
            }
        }))
    }

    /// Input: string literals with no separator
    ///
    /// Output: a `MAX_LENGTH` constant with the length of the longest string.
    #[allow(non_snake_case)]
    pub fn cssparser_internal__max_len(input: &str) -> String {
        max_len(syn::parse_token_trees(input).unwrap().iter().map(|tt| string_literal(tt).len()))
    }

    /// Input: parsed as token trees. The first TT is a type. (Can be wrapped in parens.)
    /// following TTs are grouped in pairs, each pair being a key as a string literal
    /// and the corresponding value as a const expression.
    ///
    /// Output: a rust-phf map, with keys ASCII-lowercased:
    /// ```text
    /// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
    /// ```
    #[allow(non_snake_case)]
    pub fn cssparser_internal__phf_map(input: &str) -> String {
        let token_trees = syn::parse_token_trees(input).unwrap();
        let value_type = &token_trees[0];
        let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
            let key = string_literal(&chunk[0]);
            let value = &chunk[1];
            (key.to_ascii_lowercase(), quote!(#value).to_string())
        }).collect();

        let mut map = phf_codegen::Map::new();
        map.phf_path("::cssparser::_internal__phf");
        for &(ref key, ref value) in &pairs {
            map.entry(&**key, &**value);
        }

        let mut tokens = quote! {
            static MAP: ::cssparser::_internal__phf::Map<&'static str, #value_type> =
        };
        let mut initializer_bytes = Vec::new();
        map.build(&mut initializer_bytes).unwrap();
        tokens.append(::std::str::from_utf8(&initializer_bytes).unwrap());
        tokens.append(";");
        tokens.into_string()
    }
}

fn max_len<I: Iterator<Item=usize>>(lengths: I) -> String {
    let max_length = lengths.max().expect("expected at least one string");
    quote!( const MAX_LENGTH: usize = #max_length; ).into_string()
}

fn string_literal(token: &syn::TokenTree) -> &str {
    match *token {
        syn::TokenTree::Token(syn::Token::Literal(syn::Lit::Str(ref string, _))) => string,
        _ => panic!("expected string literal, got {:?}", token)
    }
}
<|endoftext|>


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

#![allow(dead_code)]

// very simple test for a 'static static with default lifetime
static STATIC_STR: &str = "&'static str";
const CONST_STR: &str = "&'static str";

// this should be the same as without default:
static EXPLICIT_STATIC_STR: &'static str = "&'static str";
const EXPLICIT_CONST_STR: &'static str = "&'static str";

// a function that elides to an unbound lifetime for both in- and output
fn id_u8_slice(arg: &[u8]) -> &[u8] {
    arg
}

// one with a function, argument elided
static STATIC_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
const CONST_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);

// this should be the same as without elision
static STATIC_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] =
    &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
const CONST_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] =
    &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);

// another function that elides, each to a different unbound lifetime
fn multi_args(a: &u8, b: &u8, c: &u8) {}

static STATIC_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
const CONST_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));

struct Foo<'a> {
    bools: &'a [bool],
}

static STATIC_FOO: Foo = Foo { bools: &[true, false] };
const CONST_FOO: Foo = Foo { bools: &[true, false] };

type Bar<'a> = Foo<'a>;

static STATIC_BAR: Bar = Bar { bools: &[true, false] };
const CONST_BAR: Bar = Bar { bools: &[true, false] };

type Baz<'a> = fn(&'a [u8]) -> Option<u8>;

fn baz(e: &[u8]) -> Option<u8> {
    e.first().map(|x| *x)
}

static STATIC_BAZ: &Baz = &(baz as Baz);
const CONST_BAZ: &Baz = &(baz as Baz);

static BYTES: &[u8] = &[1, 2, 3];

fn main() {
    // make sure that the lifetime is actually elided (and not defaulted)
    let x = &[1u8, 2, 3];
    STATIC_SIMPLE_FN(x);
    CONST_SIMPLE_FN(x);

    STATIC_BAZ(BYTES); // neees static lifetime
    CONST_BAZ(BYTES);

    // make sure this works with different lifetimes
    let a = &1;
    {
        let b = &2;
        let c = &3;
        CONST_MULTI_FN(a, b, c);
    }
}
<commit_msg>Fix warnings in unit test<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]

// very simple test for a 'static static with default lifetime
static STATIC_STR: &str = "&'static str";
const CONST_STR: &str = "&'static str";

// this should be the same as without default:
static EXPLICIT_STATIC_STR: &'static str = "&'static str";
const EXPLICIT_CONST_STR: &'static str = "&'static str";

// a function that elides to an unbound lifetime for both in- and output
fn id_u8_slice(arg: &[u8]) -> &[u8] {
    arg
}

// one with a function, argument elided
static STATIC_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
const CONST_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);

// this should be the same as without elision
static STATIC_NON_ELIDED_FN: &for<'a> fn(&'a [u8]) -> &'a [u8] =
    &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
const CONST_NON_ELIDED_FN: &for<'a> fn(&'a [u8]) -> &'a [u8] =
    &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);

// another function that elides, each to a different unbound lifetime
fn multi_args(_a: &u8, _b: &u8, _c: &u8) {}

static STATIC_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
const CONST_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));

struct Foo<'a> {
    bools: &'a [bool],
}

static STATIC_FOO: Foo = Foo { bools: &[true, false] };
const CONST_FOO: Foo = Foo { bools: &[true, false] };

type Bar<'a> = Foo<'a>;

static STATIC_BAR: Bar = Bar { bools: &[true, false] };
const CONST_BAR: Bar = Bar { bools: &[true, false] };

type Baz<'a> = fn(&'a [u8]) -> Option<u8>;

fn baz(e: &[u8]) -> Option<u8> {
    e.first().map(|x| *x)
}

static STATIC_BAZ: &Baz = &(baz as Baz);
const CONST_BAZ: &Baz = &(baz as Baz);

static BYTES: &[u8] = &[1, 2, 3];

fn main() {
    // make sure that the lifetime is actually elided (and not defaulted)
    let x = &[1u8, 2, 3];
    STATIC_SIMPLE_FN(x);
    CONST_SIMPLE_FN(x);

    STATIC_BAZ(BYTES); // neees static lifetime
    CONST_BAZ(BYTES);

    // make sure this works with different lifetimes
    let a = &1;
    {
        let b = &2;
        let c = &3;
        CONST_MULTI_FN(a, b, c);
    }
}
<|endoftext|>


<commit_before>//! Error handling utilities.

use CL::*;

impl ToStr for CLStatus {
    fn to_str(&self) -> ~str {
        format!("{:?}", *self)
    }
}

macro_rules! convert(
    ($e: expr, $x: ident) => (if $e == $x as cl_int {
        Some($x)
    } else { None });

    ($e: expr, $x: ident, $($xs: ident),+) => (if $e == $x as cl_int {
        Some($x)
    } else { convert!($e, $($xs),+) })
)

pub fn try_convert(status: cl_int) -> Option<CLStatus> {
    convert!(status,
             CL_SUCCESS,
             CL_DEVICE_NOT_FOUND,
             CL_DEVICE_NOT_AVAILABLE,
             CL_COMPILER_NOT_AVAILABLE,
             CL_MEM_OBJECT_ALLOCATION_FAILURE,
             CL_OUT_OF_RESOURCES,
             CL_OUT_OF_HOST_MEMORY,
             CL_PROFILING_INFO_NOT_AVAILABLE,
             CL_MEM_COPY_OVERLAP,
             CL_IMAGE_FORMAT_MISMATCH,
             CL_IMAGE_FORMAT_NOT_SUPPORTED,
             CL_BUILD_PROGRAM_FAILURE,
             CL_MAP_FAILURE,
             CL_MISALIGNED_SUB_BUFFER_OFFSET,
             CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST,
             CL_INVALID_VALUE,
             CL_INVALID_DEVICE_TYPE,
             CL_INVALID_PLATFORM,
             CL_INVALID_DEVICE,
             CL_INVALID_CONTEXT,
             CL_INVALID_QUEUE_PROPERTIES,
             CL_INVALID_COMMAND_QUEUE,
             CL_INVALID_HOST_PTR,
             CL_INVALID_MEM_OBJECT,
             CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
             CL_INVALID_IMAGE_SIZE,
             CL_INVALID_SAMPLER,
             CL_INVALID_BINARY,
             CL_INVALID_BUILD_OPTIONS,
             CL_INVALID_PROGRAM,
             CL_INVALID_PROGRAM_EXECUTABLE,
             CL_INVALID_KERNEL_NAME,
             CL_INVALID_KERNEL_DEFINITION,
             CL_INVALID_KERNEL,
             CL_INVALID_ARG_INDEX,
             CL_INVALID_ARG_VALUE,
             CL_INVALID_ARG_SIZE,
             CL_INVALID_KERNEL_ARGS,
             CL_INVALID_WORK_DIMENSION,
             CL_INVALID_WORK_GROUP_SIZE,
             CL_INVALID_WORK_ITEM_SIZE,
             CL_INVALID_GLOBAL_OFFSET,
             CL_INVALID_EVENT_WAIT_LIST,
             CL_INVALID_EVENT,
             CL_INVALID_OPERATION,
             CL_INVALID_GL_OBJECT,
             CL_INVALID_BUFFER_SIZE,
             CL_INVALID_MIP_LEVEL,
             CL_INVALID_GLOBAL_WORK_SIZE,
             CL_INVALID_PROPERTY)
}

pub fn convert(status: cl_int) -> CLStatus {
    match try_convert(status) {
        Some(s) => s,
        None => fail!(format!("Uknown OpenCL Status Code: {:?}", status))
    }
}

fn error_str(status: cl_int) -> ~str {
    match try_convert(status) {
        Some(s) => s.to_str(),
        None => format!("Unknown Error: {:?}", status)
    }
}

pub fn check(status: cl_int, message: &str) {
    if status != CL_SUCCESS as cl_int {
        fail!(format!("{:?} ({:?})", message, error_str(status)))
    }
}
<commit_msg>fixed Show<commit_after>//! Error handling utilities.

use CL::*;
use std::fmt::{Show, Formatter, Result};

impl Show for CLStatus {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f.buf, "{:?}", *self)
    }
}

macro_rules! convert(
    ($e: expr, $x: ident) => (if $e == $x as cl_int {
        Some($x)
    } else { None });

    ($e: expr, $x: ident, $($xs: ident),+) => (if $e == $x as cl_int {
        Some($x)
    } else { convert!($e, $($xs),+) })
)

pub fn try_convert(status: cl_int) -> Option<CLStatus> {
    convert!(status,
             CL_SUCCESS,
             CL_DEVICE_NOT_FOUND,
             CL_DEVICE_NOT_AVAILABLE,
             CL_COMPILER_NOT_AVAILABLE,
             CL_MEM_OBJECT_ALLOCATION_FAILURE,
             CL_OUT_OF_RESOURCES,
             CL_OUT_OF_HOST_MEMORY,
             CL_PROFILING_INFO_NOT_AVAILABLE,
             CL_MEM_COPY_OVERLAP,
             CL_IMAGE_FORMAT_MISMATCH,
             CL_IMAGE_FORMAT_NOT_SUPPORTED,
             CL_BUILD_PROGRAM_FAILURE,
             CL_MAP_FAILURE,
             CL_MISALIGNED_SUB_BUFFER_OFFSET,
             CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST,
             CL_INVALID_VALUE,
             CL_INVALID_DEVICE_TYPE,
             CL_INVALID_PLATFORM,
             CL_INVALID_DEVICE,
             CL_INVALID_CONTEXT,
             CL_INVALID_QUEUE_PROPERTIES,
             CL_INVALID_COMMAND_QUEUE,
             CL_INVALID_HOST_PTR,
             CL_INVALID_MEM_OBJECT,
             CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
             CL_INVALID_IMAGE_SIZE,
             CL_INVALID_SAMPLER,
             CL_INVALID_BINARY,
             CL_INVALID_BUILD_OPTIONS,
             CL_INVALID_PROGRAM,
             CL_INVALID_PROGRAM_EXECUTABLE,
             CL_INVALID_KERNEL_NAME,
             CL_INVALID_KERNEL_DEFINITION,
             CL_INVALID_KERNEL,
             CL_INVALID_ARG_INDEX,
             CL_INVALID_ARG_VALUE,
             CL_INVALID_ARG_SIZE,
             CL_INVALID_KERNEL_ARGS,
             CL_INVALID_WORK_DIMENSION,
             CL_INVALID_WORK_GROUP_SIZE,
             CL_INVALID_WORK_ITEM_SIZE,
             CL_INVALID_GLOBAL_OFFSET,
             CL_INVALID_EVENT_WAIT_LIST,
             CL_INVALID_EVENT,
             CL_INVALID_OPERATION,
             CL_INVALID_GL_OBJECT,
             CL_INVALID_BUFFER_SIZE,
             CL_INVALID_MIP_LEVEL,
             CL_INVALID_GLOBAL_WORK_SIZE,
             CL_INVALID_PROPERTY)
}

pub fn convert(status: cl_int) -> CLStatus {
    match try_convert(status) {
        Some(s) => s,
        None => fail!(format!("Uknown OpenCL Status Code: {:?}", status))
    }
}

fn error_str(status: cl_int) -> ~str {
    match try_convert(status) {
        Some(s) => s.to_str(),
        None => format!("Unknown Error: {:?}", status)
    }
}

pub fn check(status: cl_int, message: &str) {
    if status != CL_SUCCESS as cl_int {
        fail!(format!("{:?} ({:?})", message, error_str(status)))
    }
}
<|endoftext|>


<commit_before>#![crate_name = "helloworld_server"]
#![feature(std_misc, thread_sleep)]

/// Hello World server in Rust
/// Binds REP socket to tcp://*:5555
/// Expects "Hello" from client, replies with "World"

extern crate zmq;

use std::thread;
use std::time::Duration;

fn main() {
    let mut context = zmq::Context::new();
    let mut responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new().unwrap();
    loop {
        responder.recv(&mut msg, 0).unwrap();
        println!("Received {}", msg.as_str().unwrap());
        responder.send_str("World", 0).unwrap();
        thread::sleep(Duration::seconds(1));
    }
}
<commit_msg>thread::sleep() -> thread::sleep_ms()<commit_after>#![crate_name = "helloworld_server"]

/// Hello World server in Rust
/// Binds REP socket to tcp://*:5555
/// Expects "Hello" from client, replies with "World"

extern crate zmq;

use std::thread;

fn main() {
    let mut context = zmq::Context::new();
    let mut responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new().unwrap();
    loop {
        responder.recv(&mut msg, 0).unwrap();
        println!("Received {}", msg.as_str().unwrap());
        responder.send_str("World", 0).unwrap();
        thread::sleep_ms(1000);
    }
}
<|endoftext|>


<commit_before>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! #![feature(async_await)]
//!
//! use futures::{FutureExt, TryStreamExt};
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     let connection = connection.map(|r| {
//!         if let Err(e) = r {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!     tokio::spawn(connection);
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a Stream of Rows which we collect into a Vec.
//!     let rows: Vec<Row> = client
//!         .query(&stmt, &[&"hello world"])
//!         .try_collect()
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! fn pipelined_prepare(
//!     client: &mut Client,
//! ) -> impl Future<Output = Result<(Statement, Statement), Error>>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     )
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.4.0-rc.3")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]
#![feature(async_await)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::row::{Row, SimpleQueryRow};
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::transaction::Transaction;
pub use statement::{Column, Statement};

#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: ./Config.t.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    config.connect(tls).await
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}
<commit_msg>Fix impl ordering<commit_after>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! #![feature(async_await)]
//!
//! use futures::{FutureExt, TryStreamExt};
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     let connection = connection.map(|r| {
//!         if let Err(e) = r {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!     tokio::spawn(connection);
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a Stream of Rows which we collect into a Vec.
//!     let rows: Vec<Row> = client
//!         .query(&stmt, &[&"hello world"])
//!         .try_collect()
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! fn pipelined_prepare(
//!     client: &mut Client,
//! ) -> impl Future<Output = Result<(Statement, Statement), Error>>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     )
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.4.0-rc.3")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]
#![feature(async_await)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::row::{Row, SimpleQueryRow};
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::transaction::Transaction;
pub use statement::{Column, Statement};

#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: ./Config.t.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    config.connect(tls).await
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}
<|endoftext|>


<commit_before>//! TLS support.

use std::error::Error;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::{fmt, io};
use tokio::io::{AsyncRead, AsyncWrite};

pub(crate) mod private {
    pub struct ForcePrivateApi;
}

/// Channel binding information returned from a TLS handshake.
pub struct ChannelBinding {
    pub(crate) tls_server_end_point: Option<Vec<u8>>,
}

impl ChannelBinding {
    /// Creates a `ChannelBinding` containing no information.
    pub fn none() -> ChannelBinding {
        ChannelBinding {
            tls_server_end_point: None,
        }
    }

    /// Creates a `ChannelBinding` containing `tls-server-end-point` channel binding information.
    pub fn tls_server_end_point(tls_server_end_point: Vec<u8>) -> ChannelBinding {
        ChannelBinding {
            tls_server_end_point: Some(tls_server_end_point),
        }
    }
}

/// A constructor of `TlsConnect`ors.
///
/// Requires the `runtime` Cargo feature (enabled by default).
#[cfg(feature = "runtime")]
pub trait MakeTlsConnect<S> {
    /// The stream type created by the `TlsConnect` implementation.
    type Stream: AsyncRead + AsyncWrite + Unpin;
    /// The `TlsConnect` implementation created by this type.
    type TlsConnect: TlsConnect<S, Stream = Self::Stream>;
    /// The error type returned by the `TlsConnect` implementation.
    type Error: Into<Box<dyn Error + Sync + Send>>;

    /// Creates a new `TlsConnect`or.
    ///
    /// The domain name is provided for certificate verification and SNI.
    fn make_tls_connect(&mut self, domain: &str) -> Result<Self::TlsConnect, Self::Error>;
}

/// An asynchronous function wrapping a stream in a TLS session.
pub trait TlsConnect<S> {
    /// The stream returned by the future.
    type Stream: AsyncRead + AsyncWrite + Unpin;
    /// The error returned by the future.
    type Error: Into<Box<dyn Error + Sync + Send>>;
    /// The future returned by the connector.
    type Future: Future<Output = Result<(Self::Stream, ChannelBinding), Self::Error>>;

    /// Returns a future performing a TLS handshake over the stream.
    fn connect(self, stream: S) -> Self::Future;

    #[doc(hidden)]
    fn can_connect(&self, _: private::ForcePrivateApi) -> bool {
        true
    }
}

/// A `MakeTlsConnect` and `TlsConnect` implementation which simply returns an error.
///
/// This can be used when `sslmode` is `none` or `prefer`.
pub struct NoTls;

#[cfg(feature = "runtime")]
impl<S> MakeTlsConnect<S> for NoTls {
    type Stream = NoTlsStream;
    type TlsConnect = NoTls;
    type Error = NoTlsError;

    fn make_tls_connect(&mut self, _: &str) -> Result<NoTls, NoTlsError> {
        Ok(NoTls)
    }
}

impl<S> TlsConnect<S> for NoTls {
    type Stream = NoTlsStream;
    type Error = NoTlsError;
    type Future = NoTlsFuture;

    fn connect(self, _: S) -> NoTlsFuture {
        NoTlsFuture(())
    }

    fn can_connect(&self, _: private::ForcePrivateApi) -> bool {
        false
    }
}

/// The future returned by `NoTls`.
pub struct NoTlsFuture(());

impl Future for NoTlsFuture {
    type Output = Result<(NoTlsStream, ChannelBinding), NoTlsError>;

    fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
        Poll::Ready(Err(NoTlsError(())))
    }
}

/// The TLS "stream" type produced by the `NoTls` connector.
///
/// Since `NoTls` doesn't support TLS, this type is uninhabited.
pub enum NoTlsStream {}

impl AsyncRead for NoTlsStream {
    fn poll_read(
        self: Pin<&mut Self>,
        _: &mut Context<'_>,
        _: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        match *self {}
    }
}

impl AsyncWrite for NoTlsStream {
    fn poll_write(self: Pin<&mut Self>, _: &mut Context<'_>, _: &[u8]) -> Poll<io::Result<usize>> {
        match *self {}
    }

    fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
        match *self {}
    }

    fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
        match *self {}
    }
}

/// The error returned by `NoTls`.
#[derive(Debug)]
pub struct NoTlsError(());

impl fmt::Display for NoTlsError {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.write_str("no TLS implementation configured")
    }
}

impl Error for NoTlsError {}
<commit_msg>Implement traits for NoTls<commit_after>//! TLS support.

use std::error::Error;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::{fmt, io};
use tokio::io::{AsyncRead, AsyncWrite};

pub(crate) mod private {
    pub struct ForcePrivateApi;
}

/// Channel binding information returned from a TLS handshake.
pub struct ChannelBinding {
    pub(crate) tls_server_end_point: Option<Vec<u8>>,
}

impl ChannelBinding {
    /// Creates a `ChannelBinding` containing no information.
    pub fn none() -> ChannelBinding {
        ChannelBinding {
            tls_server_end_point: None,
        }
    }

    /// Creates a `ChannelBinding` containing `tls-server-end-point` channel binding information.
    pub fn tls_server_end_point(tls_server_end_point: Vec<u8>) -> ChannelBinding {
        ChannelBinding {
            tls_server_end_point: Some(tls_server_end_point),
        }
    }
}

/// A constructor of `TlsConnect`ors.
///
/// Requires the `runtime` Cargo feature (enabled by default).
#[cfg(feature = "runtime")]
pub trait MakeTlsConnect<S> {
    /// The stream type created by the `TlsConnect` implementation.
    type Stream: AsyncRead + AsyncWrite + Unpin;
    /// The `TlsConnect` implementation created by this type.
    type TlsConnect: TlsConnect<S, Stream = Self::Stream>;
    /// The error type returned by the `TlsConnect` implementation.
    type Error: Into<Box<dyn Error + Sync + Send>>;

    /// Creates a new `TlsConnect`or.
    ///
    /// The domain name is provided for certificate verification and SNI.
    fn make_tls_connect(&mut self, domain: &str) -> Result<Self::TlsConnect, Self::Error>;
}

/// An asynchronous function wrapping a stream in a TLS session.
pub trait TlsConnect<S> {
    /// The stream returned by the future.
    type Stream: AsyncRead + AsyncWrite + Unpin;
    /// The error returned by the future.
    type Error: Into<Box<dyn Error + Sync + Send>>;
    /// The future returned by the connector.
    type Future: Future<Output = Result<(Self::Stream, ChannelBinding), Self::Error>>;

    /// Returns a future performing a TLS handshake over the stream.
    fn connect(self, stream: S) -> Self::Future;

    #[doc(hidden)]
    fn can_connect(&self, _: private::ForcePrivateApi) -> bool {
        true
    }
}

/// A `MakeTlsConnect` and `TlsConnect` implementation which simply returns an error.
///
/// This can be used when `sslmode` is `none` or `prefer`.
#[derive(Debug, Copy, Clone)]
pub struct NoTls;

#[cfg(feature = "runtime")]
impl<S> MakeTlsConnect<S> for NoTls {
    type Stream = NoTlsStream;
    type TlsConnect = NoTls;
    type Error = NoTlsError;

    fn make_tls_connect(&mut self, _: &str) -> Result<NoTls, NoTlsError> {
        Ok(NoTls)
    }
}

impl<S> TlsConnect<S> for NoTls {
    type Stream = NoTlsStream;
    type Error = NoTlsError;
    type Future = NoTlsFuture;

    fn connect(self, _: S) -> NoTlsFuture {
        NoTlsFuture(())
    }

    fn can_connect(&self, _: private::ForcePrivateApi) -> bool {
        false
    }
}

/// The future returned by `NoTls`.
pub struct NoTlsFuture(());

impl Future for NoTlsFuture {
    type Output = Result<(NoTlsStream, ChannelBinding), NoTlsError>;

    fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
        Poll::Ready(Err(NoTlsError(())))
    }
}

/// The TLS "stream" type produced by the `NoTls` connector.
///
/// Since `NoTls` doesn't support TLS, this type is uninhabited.
pub enum NoTlsStream {}

impl AsyncRead for NoTlsStream {
    fn poll_read(
        self: Pin<&mut Self>,
        _: &mut Context<'_>,
        _: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        match *self {}
    }
}

impl AsyncWrite for NoTlsStream {
    fn poll_write(self: Pin<&mut Self>, _: &mut Context<'_>, _: &[u8]) -> Poll<io::Result<usize>> {
        match *self {}
    }

    fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
        match *self {}
    }

    fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
        match *self {}
    }
}

/// The error returned by `NoTls`.
#[derive(Debug)]
pub struct NoTlsError(());

impl fmt::Display for NoTlsError {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.write_str("no TLS implementation configured")
    }
}

impl Error for NoTlsError {}
<|endoftext|>


<commit_before>extern crate itertools;

use std::collections::{HashSet,HashMap};
use self::itertools::Itertools;
use std::fmt;
use std::error;
use std::io;
use std::num;
use std::fs::File;
use std::path::Path;
use std::io::Read;

// TODO "readm.mk"
// TODO documentation
// TODO read from an iterator
// TODO error for duplicated transitions
#[derive(Debug)]
pub enum DFAError {
    MissingStartingState,
    MissingFinalStates,
    IncompleteTransition(usize),
    IllformedTransition(usize),
    Io(io::Error),
    Parse(num::ParseIntError,Option<usize>),
}

impl fmt::Display for DFAError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DFAError::Io(ref err) => write!(f, "IO error: {}", err),
            DFAError::MissingStartingState => write!(f, "The file is empty or only contains white characters."),
            DFAError::MissingFinalStates => write!(f, "The file does not specify the list of final states."),
            DFAError::IncompleteTransition(ref line) => write!(f, "Line {}: missing the src or the dest state.", line),
            DFAError::IllformedTransition(ref line) => write!(f, "Line {}: too much elements.", line),
            DFAError::Parse(ref err,ref line) => write!(f, "Parse error on line {:?}: {}", line, err),
        }
    }
}

impl error::Error for DFAError {
    fn description(&self) -> &str {
        match *self {
            DFAError::Io(ref err) => err.description(),
            DFAError::MissingStartingState => "The file is empty or only contains white characters.",
            DFAError::MissingFinalStates => "The file does not specify the list of final states.",
            DFAError::IncompleteTransition(_) => "Missing the src or the dest state.",
            DFAError::IllformedTransition(_) => "Too much elements",
            DFAError::Parse(ref err,_) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            DFAError::Io(ref err) => Some(err),
            DFAError::Parse(ref err,_) => Some(err),
            _ => None,
        }
    }
}

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

impl From<num::ParseIntError> for DFAError {
    fn from(err: num::ParseIntError) -> DFAError {
        DFAError::Parse(err,None)
    }
}

#[derive(Debug)]
pub struct DFA {
    transitions : HashMap<(char,usize),usize>,
    start       : usize,
    finals      : HashSet<usize>,
}

impl DFA {
    pub fn new() -> DFA {
        DFA{transitions: HashMap::new(), start: 0, finals: HashSet::new()}
    }

    fn parse_dfa_error(contents: &str, line: usize) -> Result<usize, DFAError> {
            contents.parse::<usize>()
                    .map_err(|e| DFAError::Parse(e,Some(line)))
    }

    pub fn new_from_file<P: AsRef<Path>>(file_path: P) -> Result<DFA, DFAError> {
        let mut file = try!(File::open(file_path));
        let mut contents = String::new();
        try!(file.read_to_string(&mut contents));
        DFA::new_from_string(&*contents)
    }

    // TODO test if the tranisiton start with two symbols instead of one
    pub fn new_from_string(file: &str) -> Result<DFA, DFAError> {
        let mut dfa = DFA::new();
        // lines iterates over the non-empty lines.
        let mut lines = file
            .lines()
            .enumerate()
            // split always return one element even if it's an empty string
            .map(|(nline,line)| (nline+1,line.split('#').nth(0).unwrap().trim()))
            .filter(|&(_,line)| !line.is_empty());
        dfa.start = try!(lines
            .next()
            .ok_or(DFAError::MissingStartingState)
            .and_then(|(nline,contents)| DFA::parse_dfa_error(contents,nline)));
        dfa.finals = try!(lines
            .next()
            .ok_or(DFAError::MissingFinalStates)
            .and_then(|(nline,contents)| Ok((nline,contents.split_whitespace())))
            // need to move the closure inside the make to create a copy of nline for
            // th closure stack frame, otherwise the compiler can't guarantee that the
            // lifetime of the closure won't exceed the lifetime of nline.
            .and_then(|(nline,contents)| Ok((nline,contents.map(move |token| DFA::parse_dfa_error(token,nline)))))
            .and_then(|(_, mut contents)| {
                contents.fold_results(HashSet::new(),|mut acc,elt| {
                    acc.insert(elt);
                    acc
                })
            }));
        for (nline,line) in lines {
            let mut tokens = line.split_whitespace();
            // can't fail because lines iterates over the non-empty line
            let symb = tokens.next().unwrap().chars().nth(0).unwrap();
            let src = try!(tokens
                .next()
                .ok_or(DFAError::IncompleteTransition(nline))
                .and_then(|contents| DFA::parse_dfa_error(contents,nline)));
            let dest = try!(tokens
                .next()
                .ok_or(DFAError::IncompleteTransition(nline))
                .and_then(|contents| DFA::parse_dfa_error(contents,nline)));
            if tokens.next().is_some() {
                return Err(DFAError::IllformedTransition(nline));
            }
            dfa.transitions.insert((symb,src), dest);
        }
        Ok(dfa)
    }

    // TODO return the position of the first match
    //      maybe create an another function to do that
    pub fn run(&self, input: &str) -> bool {
        let f = input
            .chars()
            .fold(Some(self.start), |state,c| {
                match state {
                    Some(n) => self.transitions.get(&(c,n)).map(|v| *v),
                    None => None,
                }
            });
        match f {
            Some(n) => self.finals.contains(&n),
            None => false
        }
    }
}

impl fmt::Display for DFA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "START: {}", self.start));
        try!(writeln!(f, "FINALS:"));
        for fi in self.finals.iter() {
            try!(writeln!(f,"  {}", fi));
        }
        try!(writeln!(f, "TRANSITIONS:"));
        for (tr,d) in self.transitions.iter() {
            let (c,s) = *tr;
            try!(writeln!(f, "  ({},{}) => {}", c, s, d));
        }
        write!(f, "")
    }
}

// TODO add specific error analysis
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_dfa() {
        let model =
            "0\n\
             3\n\
             a 0 1\n\
             c 0 3\n\
             b 1 2\n\
             a 2 1\n\
             c 2 3";
        let dfa = DFA::new_from_string(&model).unwrap();
        let samples =
            vec![("ababac", false),
                 ("ababc", true),
                 ("", false),
                 ("abc", true),
                 ("c", true),
                 ("ac", false),
                 ("ababababababababababababababababababababc", true),];

        for (input,expected_result) in samples {
            assert!(dfa.run(input) == expected_result, "input false for: \"{}\"", input);
        }
    }

    #[test]
    fn test_empty_file() {
        let model =
            "";
        match DFA::new_from_string(model) {
            Err(DFAError::MissingStartingState) => assert!(true),
            _ => assert!(false, "Missing state expected."),
        }
    }

    #[test]
    fn test_start_not_a_number() {
        let model =
            "a";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 1),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_many_starts() {
        let model =
            "0 1\n\
             3\n\
             a 0 1\n\
             c 0 3\n\
             b 1 2\n\
             a 2 1\n\
             c 2 3";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 1),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_no_finals() {
        let model =
            "1\n\
            ";
        match DFA::new_from_string(model) {
            Err(DFAError::MissingFinalStates) => assert!(true),
            _ => assert!(false, "Missing final states expected."),
        }
    }

    #[test]
    fn test_finals_not_a_number() {
        let model =
            "1\n\
             2 a 3";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 2),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_no_transistions() {
        let model =
            "0\n\
             3";
        let _dfa = DFA::new_from_string(&model).unwrap();
    }

    #[test]
    fn test_transitions_with_at_least_four_elements() {
        let model =
            "0\n\
             3\n\
             a 0 1 8";
        match DFA::new_from_string(model) {
            Err(DFAError::IllformedTransition(line)) => assert!(line == 3),
            _ => assert!(false, "IllformedTransition expected."),
        }
    }

    #[test]
    #[should_panic]
    fn test_transitions_start_with_at_least_two_chars() {
        let model =
            "0\n\
             3\n\
             ab 2 3";
        let _dfa = DFA::new_from_string(&model).unwrap();
    }

    #[test]
    fn test_transitions_with_src_not_a_number() {
        let model =
            "0\n\
             3\n\
             c b 3";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 3),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_transitions_with_dest_not_a_number() {
        let model =
            "0\n\
             3\n\
             c 2 b";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 3),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_read_from_fake_file() {
        let file = "fake.txt";
        match DFA::new_from_file(file) {
            Err(DFAError::Io(_)) => assert!(true),
            _ => assert!(false, "Io::Error expected."),
        }
    }
}
<commit_msg>Add BuferReading from file.<commit_after>extern crate itertools;

use std::collections::{HashSet,HashMap};
use self::itertools::Itertools;        // fold_results
use std::io;                           // Error
use std::io::{Read,BufReader,BufRead}; // read_to_string
use std::path::Path;
use std::num;                          // ParseIntError
use std::fmt;                          // Formatter, format!, Display, Debug, write!
use std::error;
use std::fs::File;                     // File, open

// TODO "readm.mk"
// TODO documentation
// TODO read from an iterator
// TODO error for duplicated transitions
#[derive(Debug)]
pub enum DFAError {
    MissingStartingState,
    MissingFinalStates,
    IncompleteTransition(usize),
    IllformedTransition(usize),
    Io(io::Error),
    Parse(num::ParseIntError,Option<usize>),
}

impl fmt::Display for DFAError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DFAError::Io(ref err) => write!(f, "IO error: {}", err),
            DFAError::MissingStartingState => write!(f, "The file is empty or only contains white characters."),
            DFAError::MissingFinalStates => write!(f, "The file does not specify the list of final states."),
            DFAError::IncompleteTransition(ref line) => write!(f, "Line {}: missing the src or the dest state.", line),
            DFAError::IllformedTransition(ref line) => write!(f, "Line {}: too much elements.", line),
            DFAError::Parse(ref err,ref line) => write!(f, "Parse error on line {:?}: {}", line, err),
        }
    }
}

impl error::Error for DFAError {
    fn description(&self) -> &str {
        match *self {
            DFAError::Io(ref err) => err.description(),
            DFAError::MissingStartingState => "The file is empty or only contains white characters.",
            DFAError::MissingFinalStates => "The file does not specify the list of final states.",
            DFAError::IncompleteTransition(_) => "Missing the src or the dest state.",
            DFAError::IllformedTransition(_) => "Too much elements",
            DFAError::Parse(ref err,_) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            DFAError::Io(ref err) => Some(err),
            DFAError::Parse(ref err,_) => Some(err),
            _ => None,
        }
    }
}

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

impl From<num::ParseIntError> for DFAError {
    fn from(err: num::ParseIntError) -> DFAError {
        DFAError::Parse(err,None)
    }
}

#[derive(Debug)]
pub struct DFA {
    transitions : HashMap<(char,usize),usize>,
    start       : usize,
    finals      : HashSet<usize>,
}

impl DFA {
    pub fn new() -> DFA {
        DFA{transitions: HashMap::new(), start: 0, finals: HashSet::new()}
    }

    fn parse_dfa_error(contents: &str, line: usize) -> Result<usize, DFAError> {
            contents.parse::<usize>()
                    .map_err(|e| DFAError::Parse(e,Some(line)))
    }

    pub fn new_from_file<P: AsRef<Path>>(file_path: P) -> Result<DFA, DFAError> {
        let file = try!(File::open(file_path));
        let file = BufReader::new(file);
        DFA::new_from_lines(&mut file.lines())
    }

    pub fn new_from_lines(lines : &mut Iterator<Item=io::Result<String>>) -> Result<DFA, DFAError> {
        let lines = lines.map(|line| line.unwrap());
        let mut dfa = DFA::new();
        let mut lines = lines
            .enumerate()
            // split always return one element even if it's an empty string
            .map(|(nline,line)| (nline+1,line.split('#').nth(0).unwrap().trim().to_owned()))
            .filter(|&(_,ref line)| !line.is_empty());
        dfa.start = try!(lines
            .next()
            .ok_or(DFAError::MissingStartingState)
            .and_then(|(nline,contents)| DFA::parse_dfa_error(&&contents,nline)));
        let (nline,contents) = try!(lines.next().ok_or(DFAError::MissingFinalStates));
        dfa.finals = try!(contents
            .split_whitespace()
            .map(|token| DFA::parse_dfa_error(token,nline))
            .fold_results(HashSet::new(), |mut acc, elt| {
                acc.insert(elt);
                acc
            }));
        for (nline,line) in lines {
            let mut tokens = line.split_whitespace();
            // can't fail because lines iterates over the non-empty line
            let symb = tokens.next().unwrap().chars().nth(0).unwrap();
            let src = try!(tokens
                .next()
                .ok_or(DFAError::IncompleteTransition(nline))
                .and_then(|contents| DFA::parse_dfa_error(contents,nline)));
            let dest = try!(tokens
                .next()
                .ok_or(DFAError::IncompleteTransition(nline))
                .and_then(|contents| DFA::parse_dfa_error(contents,nline)));
            if tokens.next().is_some() {
                return Err(DFAError::IllformedTransition(nline));
            }
            dfa.transitions.insert((symb,src), dest);
        }
        Ok(dfa)
    }

    // TODO test if the tranisiton start with two symbols instead of one
    pub fn new_from_string(file: &str) -> Result<DFA, DFAError> {
        DFA::new_from_lines(&mut file.lines().map(|line| Ok(line.to_string())))
    }

    // TODO return the position of the first match
    //      maybe create an another function to do that
    pub fn run(&self, input: &str) -> bool {
        let f = input
            .chars()
            .fold(Some(self.start), |state,c| {
                match state {
                    Some(n) => self.transitions.get(&(c,n)).map(|v| *v),
                    None => None,
                }
            });
        match f {
            Some(n) => self.finals.contains(&n),
            None => false
        }
    }
}

impl fmt::Display for DFA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "START: {}", self.start));
        try!(writeln!(f, "FINALS:"));
        for fi in self.finals.iter() {
            try!(writeln!(f,"  {}", fi));
        }
        try!(writeln!(f, "TRANSITIONS:"));
        for (tr,d) in self.transitions.iter() {
            let (c,s) = *tr;
            try!(writeln!(f, "  ({},{}) => {}", c, s, d));
        }
        write!(f, "")
    }
}

// TODO add specific error analysis
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_dfa() {
        let model =
            "0\n\
             3\n\
             a 0 1\n\
             c 0 3\n\
             b 1 2\n\
             a 2 1\n\
             c 2 3";
        let dfa = DFA::new_from_string(&model).unwrap();
        let samples =
            vec![("ababac", false),
                 ("ababc", true),
                 ("", false),
                 ("abc", true),
                 ("c", true),
                 ("ac", false),
                 ("ababababababababababababababababababababc", true),];

        for (input,expected_result) in samples {
            assert!(dfa.run(input) == expected_result, "input false for: \"{}\"", input);
        }
    }

    #[test]
    fn test_empty_file() {
        let model =
            "";
        match DFA::new_from_string(model) {
            Err(DFAError::MissingStartingState) => assert!(true),
            _ => assert!(false, "Missing state expected."),
        }
    }

    #[test]
    fn test_start_not_a_number() {
        let model =
            "a";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 1),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_many_starts() {
        let model =
            "0 1\n\
             3\n\
             a 0 1\n\
             c 0 3\n\
             b 1 2\n\
             a 2 1\n\
             c 2 3";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 1),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_no_finals() {
        let model =
            "1\n\
            ";
        match DFA::new_from_string(model) {
            Err(DFAError::MissingFinalStates) => assert!(true),
            _ => assert!(false, "Missing final states expected."),
        }
    }

    #[test]
    fn test_finals_not_a_number() {
        let model =
            "1\n\
             2 a 3";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 2),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_no_transistions() {
        let model =
            "0\n\
             3";
        let _dfa = DFA::new_from_string(&model).unwrap();
    }

    #[test]
    fn test_transitions_with_at_least_four_elements() {
        let model =
            "0\n\
             3\n\
             a 0 1 8";
        match DFA::new_from_string(model) {
            Err(DFAError::IllformedTransition(line)) => assert!(line == 3),
            _ => assert!(false, "IllformedTransition expected."),
        }
    }

    #[test]
    #[should_panic]
    fn test_transitions_start_with_at_least_two_chars() {
        let model =
            "0\n\
             3\n\
             ab 2 3";
        let _dfa = DFA::new_from_string(&model).unwrap();
    }

    #[test]
    fn test_transitions_with_src_not_a_number() {
        let model =
            "0\n\
             3\n\
             c b 3";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 3),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_transitions_with_dest_not_a_number() {
        let model =
            "0\n\
             3\n\
             c 2 b";
        match DFA::new_from_string(model) {
            Err(DFAError::Parse(_,line)) => assert!(line.unwrap() == 3),
            _ => assert!(false, "Parsing error."),
        }
    }

    #[test]
    fn test_read_from_fake_file() {
        let file = "fake.txt";
        match DFA::new_from_file(file) {
            Err(DFAError::Io(_)) => assert!(true),
            _ => assert!(false, "Io::Error expected."),
        }
    }
}
<|endoftext|>


<commit_before>//! VM errors

use utils::address::Address;
use utils::bigint::M256;

#[derive(Debug, Clone)]
pub enum MemoryError {
    IndexNotSupported,
}

impl From<MemoryError> for MachineError {
    fn from(val: MemoryError) -> MachineError {
        MachineError::Memory(val)
    }
}

impl From<MemoryError> for EvalError {
    fn from(val: MemoryError) -> EvalError {
        EvalError::Machine(MachineError::Memory(val))
    }
}

#[derive(Debug, Clone)]
pub enum StackError {
    Overflow,
    Underflow,
}

impl From<StackError> for EvalError {
    fn from(val: StackError) -> EvalError {
        EvalError::Machine(MachineError::Stack(val))
    }
}

#[derive(Debug, Clone)]
pub enum PCError {
    InvalidOpcode,
    IndexNotSupported,
    BadJumpDest,
    Overflow,
}

impl From<PCError> for EvalError {
    fn from(val: PCError) -> EvalError {
        EvalError::Machine(MachineError::PC(val))
    }
}

#[derive(Debug, Clone)]
pub enum StorageError {
    IndexNotSupported,
}

impl From<StorageError> for EvalError {
    fn from(val: StorageError) -> EvalError {
        EvalError::Machine(MachineError::Storage(val))
    }
}

#[derive(Debug, Clone)]
pub enum EvalError {
    Machine(MachineError),
    Require(RequireError),
}

#[derive(Debug, Clone)]
pub enum MachineError {
    Memory(MemoryError),
    Stack(StackError),
    PC(PCError),
    Storage(StorageError),

    CallstackOverflow,
    InvalidRange,
    EmptyGas,
}

impl From<MachineError> for EvalError {
    fn from(val: MachineError) -> EvalError {
        EvalError::Machine(val)
    }
}

#[derive(Debug, Clone)]
pub enum VMError {
    Machine(MachineError),
}

impl From<MachineError> for VMError {
    fn from(val: MachineError) -> VMError {
        VMError::Machine(val)
    }
}

#[derive(Debug, Clone)]
pub enum RequireError {
    Account(Address),
    AccountCode(Address),
    Blockhash(M256),
}

impl From<RequireError> for EvalError {
    fn from(val: RequireError) -> EvalError {
        EvalError::Require(val)
    }
}

#[derive(Debug, Clone)]
pub enum CommitError {
    AlreadyCommitted,
}
<commit_msg>Problem: no docs for errors.rs Solution: add it<commit_after>//! VM errors

use utils::address::Address;
use utils::bigint::M256;

#[derive(Debug, Clone)]
/// Errors returned by an EVM memory.
pub enum MemoryError {
    /// The index is too large for the implementation of the VM to
    /// handle.
    IndexNotSupported,
}

impl From<MemoryError> for MachineError {
    fn from(val: MemoryError) -> MachineError {
        MachineError::Memory(val)
    }
}

impl From<MemoryError> for EvalError {
    fn from(val: MemoryError) -> EvalError {
        EvalError::Machine(MachineError::Memory(val))
    }
}

#[derive(Debug, Clone)]
/// Errors returned by an EVM stack.
pub enum StackError {
    /// Stack is overflowed (pushed more than 1024 items to the
    /// stack).
    Overflow,
    /// Stack is underflowed (poped an empty stack).
    Underflow,
}

impl From<StackError> for EvalError {
    fn from(val: StackError) -> EvalError {
        EvalError::Machine(MachineError::Stack(val))
    }
}

#[derive(Debug, Clone)]
/// Errors returned by an EVM PC.
pub enum PCError {
    /// The opcode is invalid and the PC is not able to convert it to
    /// an instruction.
    InvalidOpcode,
    /// The index is too large for the implementation of the VM to
    /// handle.
    IndexNotSupported,
    /// PC jumped to an invalid jump destination.
    BadJumpDest,
    /// PC overflowed (tries to read the next opcode which is already
    /// the end of the code).
    Overflow,
}

impl From<PCError> for EvalError {
    fn from(val: PCError) -> EvalError {
        EvalError::Machine(MachineError::PC(val))
    }
}

#[derive(Debug, Clone)]
/// Errors returned by an EVM account storage.
pub enum StorageError {
    /// The index is too large for the implementation of the VM to
    /// handle.
    IndexNotSupported,
}

impl From<StorageError> for EvalError {
    fn from(val: StorageError) -> EvalError {
        EvalError::Machine(MachineError::Storage(val))
    }
}

#[derive(Debug, Clone)]
/// Errors returned when trying to step the instruction.
pub enum EvalError {
    /// A runtime error. Non-recoverable.
    Machine(MachineError),
    /// The VM requires account of blockhash information to be
    /// committed. Recoverable after the required information is
    /// committed.
    Require(RequireError),
}

#[derive(Debug, Clone)]
/// Errors returned by the a single machine of the VM.
pub enum MachineError {
    /// VM memory error.
    Memory(MemoryError),
    /// VM stack error.
    Stack(StackError),
    /// VM PC error.
    PC(PCError),
    /// VM account storage error.
    Storage(StorageError),

    /// Call stack is too large that it exceeds the limit.
    CallstackOverflow,
    /// For instruction that requires reading a range, it is invalid.
    InvalidRange,
    /// Not enough gas to continue.
    EmptyGas,
}

impl From<MachineError> for EvalError {
    fn from(val: MachineError) -> EvalError {
        EvalError::Machine(val)
    }
}

#[derive(Debug, Clone)]
/// Errors returned by the VM.
pub enum VMError {
    /// VM runtime error.
    Machine(MachineError),
}

impl From<MachineError> for VMError {
    fn from(val: MachineError) -> VMError {
        VMError::Machine(val)
    }
}

#[derive(Debug, Clone)]
/// Errors stating that the VM requires additional information to
/// continue running.
pub enum RequireError {
    Account(Address),
    AccountCode(Address),
    Blockhash(M256),
}

impl From<RequireError> for EvalError {
    fn from(val: RequireError) -> EvalError {
        EvalError::Require(val)
    }
}

#[derive(Debug, Clone)]
/// Errors returned when committing a new information.
pub enum CommitError {
    AlreadyCommitted,
}
<|endoftext|>