<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Jordi Boggiano <j.boggiano@seld.be>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

/* last synced with: env (GNU coreutils) 8.13 */

// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv posix_spawnp

#[macro_use]
extern crate clap;

#[macro_use]
extern crate uucore;

use clap::{App, AppSettings, Arg};
use ini::Ini;
use std::borrow::Cow;
use std::env;
use std::io::{self, Write};
use std::iter::Iterator;
use std::process::Command;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError, UUsageError};

const USAGE: &str = "env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
const AFTER_HELP: &str = "\
A mere - implies -i. If no COMMAND, print the resulting environment.
";

struct Options<'a> {
    ignore_env: bool,
    null: bool,
    running_directory: Option<&'a str>,
    files: Vec<&'a str>,
    unsets: Vec<&'a str>,
    sets: Vec<(&'a str, &'a str)>,
    program: Vec<&'a str>,
}

// print name=value env pairs on screen
// if null is true, separate pairs with a \0, \n otherwise
fn print_env(null: bool) {
    let stdout_raw = io::stdout();
    let mut stdout = stdout_raw.lock();
    for (n, v) in env::vars() {
        write!(stdout, "{}={}{}", n, v, if null { '\0' } else { '\n' }).unwrap();
    }
}

fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<bool> {
    // is it a NAME=VALUE like opt ?
    if let Some(idx) = opt.find('=') {
        // yes, so push name, value pair
        let (name, value) = opt.split_at(idx);
        opts.sets.push((name, &value['='.len_utf8()..]));

        Ok(false)
    } else {
        // no, it's a program-like opt
        parse_program_opt(opts, opt).map(|_| true)
    }
}

fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<()> {
    if opts.null {
        Err(UUsageError::new(
            125,
            "cannot specify --null (-0) with command".to_string(),
        ))
    } else {
        opts.program.push(opt);
        Ok(())
    }
}

fn load_config_file(opts: &mut Options) -> UResult<()> {
    // NOTE: config files are parsed using an INI parser b/c it's available and compatible with ".env"-style files
    //   ... * but support for actual INI files, although working, is not intended, nor claimed
    for &file in &opts.files {
        let conf = if file == "-" {
            let stdin = io::stdin();
            let mut stdin_locked = stdin.lock();
            Ini::read_from(&mut stdin_locked)
        } else {
            Ini::load_from_file(file)
        };

        let conf =
            conf.map_err(|e| USimpleError::new(1, format!("{}: {}", file.maybe_quote(), e)))?;

        for (_, prop) in &conf {
            // ignore all INI section lines (treat them as comments)
            for (key, value) in prop.iter() {
                env::set_var(key, value);
            }
        }
    }

    Ok(())
}

#[cfg(not(windows))]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    let progname = Cow::from(args[0]);
    (progname, &args[1..])
}

#[cfg(windows)]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    args.insert(0, "/d/c");
    let progname = env::var("ComSpec")
        .map(Cow::from)
        .unwrap_or_else(|_| Cow::from("cmd"));

    (progname, &args[..])
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(crate_name!())
        .version(crate_version!())
        .author(crate_authors!())
        .about(crate_description!())
        .usage(USAGE)
        .after_help(AFTER_HELP)
        .setting(AppSettings::AllowExternalSubcommands)
        .arg(Arg::with_name("ignore-environment")
            .short("i")
            .long("ignore-environment")
            .help("start with an empty environment"))
        .arg(Arg::with_name("chdir")
            .short("C") // GNU env compatibility
            .long("chdir")
            .takes_value(true)
            .number_of_values(1)
            .value_name("DIR")
            .help("change working directory to DIR"))
        .arg(Arg::with_name("null")
            .short("0")
            .long("null")
            .help("end each output line with a 0 byte rather than a newline (only valid when \
                    printing the environment)"))
        .arg(Arg::with_name("file")
            .short("f")
            .long("file")
            .takes_value(true)
            .number_of_values(1)
            .value_name("PATH")
            .multiple(true)
            .help("read and set variables from a \".env\"-style configuration file (prior to any \
                    unset and/or set)"))
        .arg(Arg::with_name("unset")
            .short("u")
            .long("unset")
            .takes_value(true)
            .number_of_values(1)
            .value_name("NAME")
            .multiple(true)
            .help("remove variable from the environment"))
}

fn run_env(args: impl uucore::Args) -> UResult<()> {
    let app = uu_app();
    let matches = app.get_matches_from(args);

    let ignore_env = matches.is_present("ignore-environment");
    let null = matches.is_present("null");
    let running_directory = matches.value_of("chdir");
    let files = matches
        .values_of("file")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));
    let unsets = matches
        .values_of("unset")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));

    let mut opts = Options {
        ignore_env,
        null,
        running_directory,
        files,
        unsets,
        sets: vec![],
        program: vec![],
    };

    // change directory
    if let Some(d) = opts.running_directory {
        match env::set_current_dir(d) {
            Ok(()) => d,
            Err(error) => {
                return Err(USimpleError::new(
                    125,
                    format!("cannot change directory to \"{}\": {}", d, error),
                ));
            }
        };
    }

    // we handle the name, value pairs and the program to be executed by treating them as external
    // subcommands in clap
    if let (external, Some(matches)) = matches.subcommand() {
        let mut begin_prog_opts = false;

        if external == "-" {
            // "-" implies -i and stop parsing opts
            opts.ignore_env = true;
        } else {
            begin_prog_opts = parse_name_value_opt(&mut opts, external)?;
        }

        if let Some(mut iter) = matches.values_of("") {
            // read NAME=VALUE arguments (and up to a single program argument)
            while !begin_prog_opts {
                if let Some(opt) = iter.next() {
                    begin_prog_opts = parse_name_value_opt(&mut opts, opt)?;
                } else {
                    break;
                }
            }

            // read any leftover program arguments
            for opt in iter {
                parse_program_opt(&mut opts, opt)?;
            }
        }
    }

    // GNU env tests this behavior
    if opts.program.is_empty() && running_directory.is_some() {
        return Err(UUsageError::new(
            125,
            "must specify command with --chdir (-C)".to_string(),
        ));
    }

    // NOTE: we manually set and unset the env vars below rather than using Command::env() to more
    //       easily handle the case where no command is given

    // remove all env vars if told to ignore presets
    if opts.ignore_env {
        for (ref name, _) in env::vars() {
            env::remove_var(name);
        }
    }

    // load .env-style config file prior to those given on the command-line
    load_config_file(&mut opts)?;

    // unset specified env vars
    for name in &opts.unsets {
        if name.is_empty() || name.contains(0 as char) || name.contains('=') {
            return Err(USimpleError::new(
                125,
                format!("cannot unset {}: Invalid argument", name.quote()),
            ));
        }

        env::remove_var(name);
    }

    // set specified env vars
    for &(name, val) in &opts.sets {
        /*
         * set_var panics if name is an empty string
         * set_var internally calls setenv (on unix at least), while GNU env calls putenv instead.
         *
         * putenv returns successfully if provided with something like "=a" and modifies the environ
         * variable to contain "=a" inside it, effectively modifying the process' current environment
         * to contain a malformed string in it. Using GNU's implementation, the command `env =a`
         * prints out the malformed string and even invokes the child process with that environment.
         * This can be seen by using `env -i =a env` or `env -i =a cat /proc/self/environ`
         *
         * POSIX.1-2017 doesn't seem to mention what to do if the string is malformed (at least
         * not in "Chapter 8, Environment Variables" or in the definition for environ and various
         * exec*'s or in the description of env in the "Shell & Utilities" volume).
         *
         * It also doesn't specify any checks for putenv before modifying the environ variable, which
         * is likely why glibc doesn't do so. However, setenv's first argument cannot point to
         * an empty string or a string containing '='.
         *
         * There is no benefit in replicating GNU's env behavior, since it will only modify the
         * environment in weird ways
         */

        if name.is_empty() {
            show_warning!("no name specified for value {}", val.quote());
            continue;
        }
        env::set_var(name, val);
    }

    if !opts.program.is_empty() {
        // we need to execute a command
        let (prog, args) = build_command(&mut opts.program);

        /*
         * On Unix-like systems Command::status either ends up calling either fork or posix_spawnp
         * (which ends up calling clone). Keep using the current process would be ideal, but the
         * standard library contains many checks and fail-safes to ensure the process ends up being
         * created. This is much simpler than dealing with the hassles of calling execvp directly.
         */
        match Command::new(&*prog).args(args).status() {
            Ok(exit) if !exit.success() => return Err(exit.code().unwrap().into()),
            Err(ref err) if err.kind() == io::ErrorKind::NotFound => return Err(127.into()),
            Err(_) => return Err(126.into()),
            Ok(_) => (),
        }
    } else {
        // no program provided, so just dump all env vars to stdout
        print_env(opts.null);
    }

    Ok(())
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    run_env(args)
}
<commit_msg>env: add contributor<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Jordi Boggiano <j.boggiano@seld.be>
// (c) Thomas Queiroz <thomasqueirozb@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

/* last synced with: env (GNU coreutils) 8.13 */

// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv posix_spawnp

#[macro_use]
extern crate clap;

#[macro_use]
extern crate uucore;

use clap::{App, AppSettings, Arg};
use ini::Ini;
use std::borrow::Cow;
use std::env;
use std::io::{self, Write};
use std::iter::Iterator;
use std::process::Command;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError, UUsageError};

const USAGE: &str = "env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
const AFTER_HELP: &str = "\
A mere - implies -i. If no COMMAND, print the resulting environment.
";

struct Options<'a> {
    ignore_env: bool,
    null: bool,
    running_directory: Option<&'a str>,
    files: Vec<&'a str>,
    unsets: Vec<&'a str>,
    sets: Vec<(&'a str, &'a str)>,
    program: Vec<&'a str>,
}

// print name=value env pairs on screen
// if null is true, separate pairs with a \0, \n otherwise
fn print_env(null: bool) {
    let stdout_raw = io::stdout();
    let mut stdout = stdout_raw.lock();
    for (n, v) in env::vars() {
        write!(stdout, "{}={}{}", n, v, if null { '\0' } else { '\n' }).unwrap();
    }
}

fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<bool> {
    // is it a NAME=VALUE like opt ?
    if let Some(idx) = opt.find('=') {
        // yes, so push name, value pair
        let (name, value) = opt.split_at(idx);
        opts.sets.push((name, &value['='.len_utf8()..]));

        Ok(false)
    } else {
        // no, it's a program-like opt
        parse_program_opt(opts, opt).map(|_| true)
    }
}

fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<()> {
    if opts.null {
        Err(UUsageError::new(
            125,
            "cannot specify --null (-0) with command".to_string(),
        ))
    } else {
        opts.program.push(opt);
        Ok(())
    }
}

fn load_config_file(opts: &mut Options) -> UResult<()> {
    // NOTE: config files are parsed using an INI parser b/c it's available and compatible with ".env"-style files
    //   ... * but support for actual INI files, although working, is not intended, nor claimed
    for &file in &opts.files {
        let conf = if file == "-" {
            let stdin = io::stdin();
            let mut stdin_locked = stdin.lock();
            Ini::read_from(&mut stdin_locked)
        } else {
            Ini::load_from_file(file)
        };

        let conf =
            conf.map_err(|e| USimpleError::new(1, format!("{}: {}", file.maybe_quote(), e)))?;

        for (_, prop) in &conf {
            // ignore all INI section lines (treat them as comments)
            for (key, value) in prop.iter() {
                env::set_var(key, value);
            }
        }
    }

    Ok(())
}

#[cfg(not(windows))]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    let progname = Cow::from(args[0]);
    (progname, &args[1..])
}

#[cfg(windows)]
fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b str]) {
    args.insert(0, "/d/c");
    let progname = env::var("ComSpec")
        .map(Cow::from)
        .unwrap_or_else(|_| Cow::from("cmd"));

    (progname, &args[..])
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(crate_name!())
        .version(crate_version!())
        .author(crate_authors!())
        .about(crate_description!())
        .usage(USAGE)
        .after_help(AFTER_HELP)
        .setting(AppSettings::AllowExternalSubcommands)
        .arg(Arg::with_name("ignore-environment")
            .short("i")
            .long("ignore-environment")
            .help("start with an empty environment"))
        .arg(Arg::with_name("chdir")
            .short("C") // GNU env compatibility
            .long("chdir")
            .takes_value(true)
            .number_of_values(1)
            .value_name("DIR")
            .help("change working directory to DIR"))
        .arg(Arg::with_name("null")
            .short("0")
            .long("null")
            .help("end each output line with a 0 byte rather than a newline (only valid when \
                    printing the environment)"))
        .arg(Arg::with_name("file")
            .short("f")
            .long("file")
            .takes_value(true)
            .number_of_values(1)
            .value_name("PATH")
            .multiple(true)
            .help("read and set variables from a \".env\"-style configuration file (prior to any \
                    unset and/or set)"))
        .arg(Arg::with_name("unset")
            .short("u")
            .long("unset")
            .takes_value(true)
            .number_of_values(1)
            .value_name("NAME")
            .multiple(true)
            .help("remove variable from the environment"))
}

fn run_env(args: impl uucore::Args) -> UResult<()> {
    let app = uu_app();
    let matches = app.get_matches_from(args);

    let ignore_env = matches.is_present("ignore-environment");
    let null = matches.is_present("null");
    let running_directory = matches.value_of("chdir");
    let files = matches
        .values_of("file")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));
    let unsets = matches
        .values_of("unset")
        .map(Iterator::collect)
        .unwrap_or_else(|| Vec::with_capacity(0));

    let mut opts = Options {
        ignore_env,
        null,
        running_directory,
        files,
        unsets,
        sets: vec![],
        program: vec![],
    };

    // change directory
    if let Some(d) = opts.running_directory {
        match env::set_current_dir(d) {
            Ok(()) => d,
            Err(error) => {
                return Err(USimpleError::new(
                    125,
                    format!("cannot change directory to \"{}\": {}", d, error),
                ));
            }
        };
    }

    // we handle the name, value pairs and the program to be executed by treating them as external
    // subcommands in clap
    if let (external, Some(matches)) = matches.subcommand() {
        let mut begin_prog_opts = false;

        if external == "-" {
            // "-" implies -i and stop parsing opts
            opts.ignore_env = true;
        } else {
            begin_prog_opts = parse_name_value_opt(&mut opts, external)?;
        }

        if let Some(mut iter) = matches.values_of("") {
            // read NAME=VALUE arguments (and up to a single program argument)
            while !begin_prog_opts {
                if let Some(opt) = iter.next() {
                    begin_prog_opts = parse_name_value_opt(&mut opts, opt)?;
                } else {
                    break;
                }
            }

            // read any leftover program arguments
            for opt in iter {
                parse_program_opt(&mut opts, opt)?;
            }
        }
    }

    // GNU env tests this behavior
    if opts.program.is_empty() && running_directory.is_some() {
        return Err(UUsageError::new(
            125,
            "must specify command with --chdir (-C)".to_string(),
        ));
    }

    // NOTE: we manually set and unset the env vars below rather than using Command::env() to more
    //       easily handle the case where no command is given

    // remove all env vars if told to ignore presets
    if opts.ignore_env {
        for (ref name, _) in env::vars() {
            env::remove_var(name);
        }
    }

    // load .env-style config file prior to those given on the command-line
    load_config_file(&mut opts)?;

    // unset specified env vars
    for name in &opts.unsets {
        if name.is_empty() || name.contains(0 as char) || name.contains('=') {
            return Err(USimpleError::new(
                125,
                format!("cannot unset {}: Invalid argument", name.quote()),
            ));
        }

        env::remove_var(name);
    }

    // set specified env vars
    for &(name, val) in &opts.sets {
        /*
         * set_var panics if name is an empty string
         * set_var internally calls setenv (on unix at least), while GNU env calls putenv instead.
         *
         * putenv returns successfully if provided with something like "=a" and modifies the environ
         * variable to contain "=a" inside it, effectively modifying the process' current environment
         * to contain a malformed string in it. Using GNU's implementation, the command `env =a`
         * prints out the malformed string and even invokes the child process with that environment.
         * This can be seen by using `env -i =a env` or `env -i =a cat /proc/self/environ`
         *
         * POSIX.1-2017 doesn't seem to mention what to do if the string is malformed (at least
         * not in "Chapter 8, Environment Variables" or in the definition for environ and various
         * exec*'s or in the description of env in the "Shell & Utilities" volume).
         *
         * It also doesn't specify any checks for putenv before modifying the environ variable, which
         * is likely why glibc doesn't do so. However, setenv's first argument cannot point to
         * an empty string or a string containing '='.
         *
         * There is no benefit in replicating GNU's env behavior, since it will only modify the
         * environment in weird ways
         */

        if name.is_empty() {
            show_warning!("no name specified for value {}", val.quote());
            continue;
        }
        env::set_var(name, val);
    }

    if !opts.program.is_empty() {
        // we need to execute a command
        let (prog, args) = build_command(&mut opts.program);

        /*
         * On Unix-like systems Command::status either ends up calling either fork or posix_spawnp
         * (which ends up calling clone). Keep using the current process would be ideal, but the
         * standard library contains many checks and fail-safes to ensure the process ends up being
         * created. This is much simpler than dealing with the hassles of calling execvp directly.
         */
        match Command::new(&*prog).args(args).status() {
            Ok(exit) if !exit.success() => return Err(exit.code().unwrap().into()),
            Err(ref err) if err.kind() == io::ErrorKind::NotFound => return Err(127.into()),
            Err(_) => return Err(126.into()),
            Ok(_) => (),
        }
    } else {
        // no program provided, so just dump all env vars to stdout
        print_env(opts.null);
    }

    Ok(())
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    run_env(args)
}
<|endoftext|>


<commit_before>use crate::visit::IntoNeighbors;
use crate::visit::{VisitMap, Visitable};

/// Strictly monotonically increasing event time for a depth first search.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default, Hash)]
pub struct Time(pub usize);

/// A depth first search (DFS) visitor event.
#[derive(Copy, Clone, Debug)]
pub enum DfsEvent<N> {
    Discover(N, Time),
    /// An edge of the tree formed by the traversal.
    TreeEdge(N, N),
    /// An edge to an already visited node.
    BackEdge(N, N),
    /// A cross or forward edge.
    ///
    /// For an edge *(u, v)*, if the discover time of *v* is greater than *u*,
    /// then it is a forward edge, else a cross edge.
    CrossForwardEdge(N, N),
    /// All edges from a node have been reported.
    Finish(N, Time),
}

/// Return if the expression is a break value, execute the provided statement
/// if it is a prune value.
macro_rules! try_control {
    ($e:expr, $p:stmt) => {
        match $e {
            x => {
                if x.should_break() {
                    return x;
                } else if x.should_prune() {
                    $p
                }
            }
        }
    };
}

/// Control flow for `depth_first_search` callbacks.
#[derive(Copy, Clone, Debug)]
pub enum Control<B> {
    /// Continue the DFS traversal as normal.
    Continue,
    /// Prune the current node from the DFS traversal. No more edges from this
    /// node will be reported to the callback. A `DfsEvent::Finish` for this
    /// node will still be reported. This can be returned in response to any
    /// `DfsEvent`, except `Finish`, which will panic.
    Prune,
    /// Stop the DFS traversal and return the provided value.
    Break(B),
}

impl<B> Control<B> {
    pub fn breaking() -> Control<()> {
        Control::Break(())
    }
    /// Get the value in `Control::Break(_)`, if present.
    pub fn break_value(self) -> Option<B> {
        match self {
            Control::Continue | Control::Prune => None,
            Control::Break(b) => Some(b),
        }
    }
}

/// Control flow for callbacks.
///
/// The empty return value `()` is equivalent to continue.
pub trait ControlFlow {
    fn continuing() -> Self;
    fn should_break(&self) -> bool;
    fn should_prune(&self) -> bool;
}

impl ControlFlow for () {
    fn continuing() {}
    #[inline]
    fn should_break(&self) -> bool {
        false
    }
    #[inline]
    fn should_prune(&self) -> bool {
        false
    }
}

impl<B> ControlFlow for Control<B> {
    fn continuing() -> Self {
        Control::Continue
    }
    fn should_break(&self) -> bool {
        if let Control::Break(_) = *self {
            true
        } else {
            false
        }
    }
    fn should_prune(&self) -> bool {
        match *self {
            Control::Prune => true,
            Control::Continue | Control::Break(_) => false,
        }
    }
}

impl<C: ControlFlow, E> ControlFlow for Result<C, E> {
    fn continuing() -> Self {
        Ok(C::continuing())
    }
    fn should_break(&self) -> bool {
        if let Ok(ref c) = *self {
            c.should_break()
        } else {
            true
        }
    }
    fn should_prune(&self) -> bool {
        if let Ok(ref c) = *self {
            c.should_prune()
        } else {
            false
        }
    }
}

/// The default is `Continue`.
impl<B> Default for Control<B> {
    fn default() -> Self {
        Control::Continue
    }
}

/// A recursive depth first search.
///
/// Starting points are the nodes in the iterator `starts` (specify just one
/// start vertex *x* by using `Some(x)`).
///
/// The traversal emits discovery and finish events for each reachable vertex,
/// and edge classification of each reachable edge. `visitor` is called for each
/// event, see [`DfsEvent`][de] for possible values.
///
/// If the return value of the visitor is simply `()`, the visit runs until it
/// is finished. If the return value is a `Control<B>`, it can be used to
/// change the control flow of the search. `Control::Break` will stop
/// the visit early, returning the contained value from the function.
/// `Control::Prune` will stop traversing any additional edges from the current
/// node and proceed immediately to the `Finish` event.
///
/// ***Panics** if you attempt to prune a node from its `Finish` event.
///
/// [de]: enum.DfsEvent.html
///
/// # Example
///
/// Find a path from vertex 0 to 5, and exit the visit as soon as we reach
/// the goal vertex.
///
/// ```
/// use petgraph::prelude::*;
/// use petgraph::graph::node_index as n;
/// use petgraph::visit::depth_first_search;
/// use petgraph::visit::{DfsEvent, Control};
///
/// let gr: Graph<(), ()> = Graph::from_edges(&[
///     (0, 1), (0, 2), (0, 3),
///     (1, 3),
///     (2, 3), (2, 4),
///     (4, 0), (4, 5),
/// ]);
///
/// // record each predecessor, mapping node → node
/// let mut predecessor = vec![NodeIndex::end(); gr.node_count()];
/// let start = n(0);
/// let goal = n(5);
/// depth_first_search(&gr, Some(start), |event| {
///     if let DfsEvent::TreeEdge(u, v) = event {
///         predecessor[v.index()] = u;
///         if v == goal {
///             return Control::Break(v);
///         }
///     }
///     Control::Continue
/// });
///
/// let mut next = goal;
/// let mut path = vec![next];
/// while next != start {
///     let pred = predecessor[next.index()];
///     path.push(pred);
///     next = pred;
/// }
/// path.reverse();
/// assert_eq!(&path, &[n(0), n(2), n(4), n(5)]);
/// ```
pub fn depth_first_search<G, I, F, C>(graph: G, starts: I, mut visitor: F) -> C
where
    G: IntoNeighbors + Visitable,
    I: IntoIterator<Item = G::NodeId>,
    F: FnMut(DfsEvent<G::NodeId>) -> C,
    C: ControlFlow,
{
    let time = &mut Time(0);
    let discovered = &mut graph.visit_map();
    let finished = &mut graph.visit_map();

    for start in starts {
        try_control!(
            dfs_visitor(graph, start, &mut visitor, discovered, finished, time),
            unreachable!()
        );
    }
    C::continuing()
}

fn dfs_visitor<G, F, C>(
    graph: G,
    u: G::NodeId,
    visitor: &mut F,
    discovered: &mut G::Map,
    finished: &mut G::Map,
    time: &mut Time,
) -> C
where
    G: IntoNeighbors + Visitable,
    F: FnMut(DfsEvent<G::NodeId>) -> C,
    C: ControlFlow,
{
    if !discovered.visit(u) {
        return C::continuing();
    }

    'prune: loop {
        try_control!(
            visitor(DfsEvent::Discover(u, time_post_inc(time))),
            break 'prune
        );
        for v in graph.neighbors(u) {
            if !discovered.is_visited(&v) {
                try_control!(visitor(DfsEvent::TreeEdge(u, v)), continue);
                try_control!(
                    dfs_visitor(graph, v, visitor, discovered, finished, time),
                    unreachable!()
                );
            } else if !finished.is_visited(&v) {
                try_control!(visitor(DfsEvent::BackEdge(u, v)), continue);
            } else {
                try_control!(visitor(DfsEvent::CrossForwardEdge(u, v)), continue);
            }
        }

        break;
    }
    let first_finish = finished.visit(u);
    debug_assert!(first_finish);
    try_control!(
        visitor(DfsEvent::Finish(u, time_post_inc(time))),
        panic!("Pruning on the `DfsEvent::Finish` is not supported!")
    );
    C::continuing()
}

fn time_post_inc(x: &mut Time) -> Time {
    let v = *x;
    x.0 += 1;
    v
}
<commit_msg>docs: note that depth_first_search also works for Result.<commit_after>use crate::visit::IntoNeighbors;
use crate::visit::{VisitMap, Visitable};

/// Strictly monotonically increasing event time for a depth first search.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default, Hash)]
pub struct Time(pub usize);

/// A depth first search (DFS) visitor event.
#[derive(Copy, Clone, Debug)]
pub enum DfsEvent<N> {
    Discover(N, Time),
    /// An edge of the tree formed by the traversal.
    TreeEdge(N, N),
    /// An edge to an already visited node.
    BackEdge(N, N),
    /// A cross or forward edge.
    ///
    /// For an edge *(u, v)*, if the discover time of *v* is greater than *u*,
    /// then it is a forward edge, else a cross edge.
    CrossForwardEdge(N, N),
    /// All edges from a node have been reported.
    Finish(N, Time),
}

/// Return if the expression is a break value, execute the provided statement
/// if it is a prune value.
macro_rules! try_control {
    ($e:expr, $p:stmt) => {
        match $e {
            x => {
                if x.should_break() {
                    return x;
                } else if x.should_prune() {
                    $p
                }
            }
        }
    };
}

/// Control flow for `depth_first_search` callbacks.
#[derive(Copy, Clone, Debug)]
pub enum Control<B> {
    /// Continue the DFS traversal as normal.
    Continue,
    /// Prune the current node from the DFS traversal. No more edges from this
    /// node will be reported to the callback. A `DfsEvent::Finish` for this
    /// node will still be reported. This can be returned in response to any
    /// `DfsEvent`, except `Finish`, which will panic.
    Prune,
    /// Stop the DFS traversal and return the provided value.
    Break(B),
}

impl<B> Control<B> {
    pub fn breaking() -> Control<()> {
        Control::Break(())
    }
    /// Get the value in `Control::Break(_)`, if present.
    pub fn break_value(self) -> Option<B> {
        match self {
            Control::Continue | Control::Prune => None,
            Control::Break(b) => Some(b),
        }
    }
}

/// Control flow for callbacks.
///
/// The empty return value `()` is equivalent to continue.
pub trait ControlFlow {
    fn continuing() -> Self;
    fn should_break(&self) -> bool;
    fn should_prune(&self) -> bool;
}

impl ControlFlow for () {
    fn continuing() {}
    #[inline]
    fn should_break(&self) -> bool {
        false
    }
    #[inline]
    fn should_prune(&self) -> bool {
        false
    }
}

impl<B> ControlFlow for Control<B> {
    fn continuing() -> Self {
        Control::Continue
    }
    fn should_break(&self) -> bool {
        if let Control::Break(_) = *self {
            true
        } else {
            false
        }
    }
    fn should_prune(&self) -> bool {
        match *self {
            Control::Prune => true,
            Control::Continue | Control::Break(_) => false,
        }
    }
}

impl<C: ControlFlow, E> ControlFlow for Result<C, E> {
    fn continuing() -> Self {
        Ok(C::continuing())
    }
    fn should_break(&self) -> bool {
        if let Ok(ref c) = *self {
            c.should_break()
        } else {
            true
        }
    }
    fn should_prune(&self) -> bool {
        if let Ok(ref c) = *self {
            c.should_prune()
        } else {
            false
        }
    }
}

/// The default is `Continue`.
impl<B> Default for Control<B> {
    fn default() -> Self {
        Control::Continue
    }
}

/// A recursive depth first search.
///
/// Starting points are the nodes in the iterator `starts` (specify just one
/// start vertex *x* by using `Some(x)`).
///
/// The traversal emits discovery and finish events for each reachable vertex,
/// and edge classification of each reachable edge. `visitor` is called for each
/// event, see [`DfsEvent`][de] for possible values.
///
/// The return value should implement the trait `ControlFlow`, and can be used to change
/// the control flow of the search.
///
/// `Control` Implements `ControlFlow` such that `Control::Continue` resumes the search.
/// `Control::Break` will stop the visit early, returning the contained value.
/// `Control::Prune` will stop traversing any additional edges from the current
/// node and proceed immediately to the `Finish` event.
///
/// There are implementations of `ControlFlow` for `()`, and `Result<C, E>` where
/// `C: ControlFlow`. The implementation for `()` will continue until finished.
/// For `Result`, upon encountering an `E` it will break, otherwise acting the same as `C`.
///
/// ***Panics** if you attempt to prune a node from its `Finish` event.
///
/// [de]: enum.DfsEvent.html
///
/// # Example returning `Control`.
///
/// Find a path from vertex 0 to 5, and exit the visit as soon as we reach
/// the goal vertex.
///
/// ```
/// use petgraph::prelude::*;
/// use petgraph::graph::node_index as n;
/// use petgraph::visit::depth_first_search;
/// use petgraph::visit::{DfsEvent, Control};
///
/// let gr: Graph<(), ()> = Graph::from_edges(&[
///     (0, 1), (0, 2), (0, 3),
///     (1, 3),
///     (2, 3), (2, 4),
///     (4, 0), (4, 5),
/// ]);
///
/// // record each predecessor, mapping node → node
/// let mut predecessor = vec![NodeIndex::end(); gr.node_count()];
/// let start = n(0);
/// let goal = n(5);
/// depth_first_search(&gr, Some(start), |event| {
///     if let DfsEvent::TreeEdge(u, v) = event {
///         predecessor[v.index()] = u;
///         if v == goal {
///             return Control::Break(v);
///         }
///     }
///     Control::Continue
/// });
///
/// let mut next = goal;
/// let mut path = vec![next];
/// while next != start {
///     let pred = predecessor[next.index()];
///     path.push(pred);
///     next = pred;
/// }
/// path.reverse();
/// assert_eq!(&path, &[n(0), n(2), n(4), n(5)]);
/// ```
///
/// # Example returning a `Result`.
/// ```
/// use petgraph::graph::node_index as n;
/// use petgraph::prelude::*;
/// use petgraph::visit::depth_first_search;
/// use petgraph::visit::{DfsEvent, Time};
///
/// let gr: Graph<(), ()> = Graph::from_edges(&[(0, 1), (1, 2), (1, 1), (2, 1)]);
/// let start = n(0);
/// let mut back_edges = 0;
/// let mut discover_time = 0;
/// // Stop the search, the first time a BackEdge is encountered.
/// let result = depth_first_search(&gr, Some(start), |event| {
///     match event {
///         // In the cases where Ok(()) is returned,
///         // Result falls back to the implementation of Control on the value ().
///         // In the case of (), this is to always return Control::Continue.
///         // continuing the search.
///         DfsEvent::Discover(_, Time(t)) => {
///             discover_time = t;
///             Ok(())
///         }
///         DfsEvent::BackEdge(_, _) => {
///             back_edges += 1;
///             // the implementation of ControlFlow for Result,
///             // treats this Err value as Continue::Break
///             Err(event)
///         }
///         _ => Ok(()),
///     }
/// });
///
/// // Even though the graph has more than one cycle,
/// // The number of back_edges visited by the search should always be 1.
/// assert_eq!(back_edges, 1);
/// println!("discover time:{:?}", discover_time);
/// println!("number of backedges encountered: {}", back_edges);
/// println!("back edge: {:?}", result);
/// ```
pub fn depth_first_search<G, I, F, C>(graph: G, starts: I, mut visitor: F) -> C
where
    G: IntoNeighbors + Visitable,
    I: IntoIterator<Item = G::NodeId>,
    F: FnMut(DfsEvent<G::NodeId>) -> C,
    C: ControlFlow,
{
    let time = &mut Time(0);
    let discovered = &mut graph.visit_map();
    let finished = &mut graph.visit_map();

    for start in starts {
        try_control!(
            dfs_visitor(graph, start, &mut visitor, discovered, finished, time),
            unreachable!()
        );
    }
    C::continuing()
}

fn dfs_visitor<G, F, C>(
    graph: G,
    u: G::NodeId,
    visitor: &mut F,
    discovered: &mut G::Map,
    finished: &mut G::Map,
    time: &mut Time,
) -> C
where
    G: IntoNeighbors + Visitable,
    F: FnMut(DfsEvent<G::NodeId>) -> C,
    C: ControlFlow,
{
    if !discovered.visit(u) {
        return C::continuing();
    }

    'prune: loop {
        try_control!(
            visitor(DfsEvent::Discover(u, time_post_inc(time))),
            break 'prune
        );
        for v in graph.neighbors(u) {
            if !discovered.is_visited(&v) {
                try_control!(visitor(DfsEvent::TreeEdge(u, v)), continue);
                try_control!(
                    dfs_visitor(graph, v, visitor, discovered, finished, time),
                    unreachable!()
                );
            } else if !finished.is_visited(&v) {
                try_control!(visitor(DfsEvent::BackEdge(u, v)), continue);
            } else {
                try_control!(visitor(DfsEvent::CrossForwardEdge(u, v)), continue);
            }
        }

        break;
    }
    let first_finish = finished.visit(u);
    debug_assert!(first_finish);
    try_control!(
        visitor(DfsEvent::Finish(u, time_post_inc(time))),
        panic!("Pruning on the `DfsEvent::Finish` is not supported!")
    );
    C::continuing()
}

fn time_post_inc(x: &mut Time) -> Time {
    let v = *x;
    x.0 += 1;
    v
}
<|endoftext|>


<commit_before>use std::ffi::OsStr;
use std::fs::File;
use std::io::{self, Write, BufRead, BufReader, Seek, SeekFrom};
use std::process::{self, Command, Stdio};
use std::time::Instant;
use regex::Regex;
use tempfile::tempfile;

use Cfg;
use errors::*;
use notifications::*;
use rustup_utils;
use telemetry::{Telemetry, TelemetryEvent};

pub fn run_command_for_dir<S: AsRef<OsStr>>(cmd: Command,
                                            arg0: &str,
                                            args: &[S],
                                            cfg: &Cfg) -> Result<()> {
    if (arg0 == "rustc" || arg0 == "rustc.exe") && try!(cfg.telemetry_enabled()) {
        return telemetry_rustc(cmd, arg0, args, cfg);
    }

    run_command_for_dir_without_telemetry(cmd, arg0, args)
}

fn telemetry_rustc<S: AsRef<OsStr>>(mut cmd: Command,
                                    arg0: &str,
                                    args: &[S], cfg: &Cfg) -> Result<()> {
    #[cfg(unix)]
    fn file_as_stdio(file: &File) -> Stdio {
        use std::os::unix::io::{AsRawFd, FromRawFd};
        unsafe { Stdio::from_raw_fd(file.as_raw_fd()) }
    }

    #[cfg(windows)]
    fn file_as_stdio(file: &File) -> Stdio {
        use std::os::windows::io::{AsRawHandle, FromRawHandle};
        unsafe { Stdio::from_raw_handle(file.as_raw_handle()) }
    }

    let now = Instant::now();

    cmd.args(args);

    let has_color_args = args.iter().any(|e| {
        let e = e.as_ref().to_str().unwrap_or("");
        e.starts_with("--color")
    });

    if stderr_isatty() && !has_color_args
    {
        cmd.arg("--color");
        cmd.arg("always");
    }

    let mut cmd_err_file = tempfile().unwrap();
    let cmd_err_stdio = file_as_stdio(&cmd_err_file);

    // FIXME rust-lang/rust#32254. It's not clear to me
    // when and why this is needed.
    let mut cmd = cmd.stdin(Stdio::inherit())
                    .stdout(Stdio::inherit())
                    .stderr(cmd_err_stdio)
                    .spawn()
                    .unwrap();

    let status = cmd.wait();

    let duration = now.elapsed();

    let ms = (duration.as_secs() as u64 * 1000) + (duration.subsec_nanos() as u64 / 1000 / 1000);

    let t = Telemetry::new(cfg.multirust_dir.join("telemetry"));

    match status {
        Ok(status) => {
            let exit_code = status.code().unwrap_or(1);

            let re = Regex::new(r"\[(?P<error>E.{4})\]").unwrap();

            let mut buffer = String::new();
            // Chose a HashSet instead of a Vec to avoid calls to sort() and dedup().
            // The HashSet should be faster if there are a lot of errors, too.
            let mut errors: Vec<String> = Vec::new();

            let stderr = io::stderr();
            let mut handle = stderr.lock();

            cmd_err_file.seek(SeekFrom::Start(0)).unwrap();

            let mut buffered_stderr = BufReader::new(cmd_err_file);

            while buffered_stderr.read_line(&mut buffer).unwrap() > 0 {
                let b = buffer.to_owned();
                buffer.clear();
                let _ = handle.write(b.as_bytes());

                if let Some(caps) = re.captures(&b) {
                    if !caps.is_empty() {
                        errors.push(caps.name("error").unwrap_or("").to_owned());
                    }
                };
            }

            let e = if errors.is_empty() { None } else { Some(errors) };

            let te = TelemetryEvent::RustcRun { duration_ms: ms,
                                                exit_code: exit_code,
                                                errors: e };

            let _ = t.log_telemetry(te).map_err(|xe| {
                (cfg.notify_handler)(Notification::TelemetryCleanupError(&xe));
            });

            process::exit(exit_code);
        },
        Err(e) => {
            let exit_code = e.raw_os_error().unwrap_or(1);
            let te = TelemetryEvent::RustcRun { duration_ms: ms,
                                                exit_code: exit_code,
                                                errors: None };

            let _ = t.log_telemetry(te).map_err(|xe| {
                (cfg.notify_handler)(Notification::TelemetryCleanupError(&xe));
            });

            Err(e).chain_err(|| rustup_utils::ErrorKind::RunningCommand {
                name: OsStr::new(arg0).to_owned(),
            })
        },
    }
}

fn run_command_for_dir_without_telemetry<S: AsRef<OsStr>>(
    mut cmd: Command, arg0: &str, args: &[S]) -> Result<()>
{
    cmd.args(&args);

    // FIXME rust-lang/rust#32254. It's not clear to me
    // when and why this is needed.
    cmd.stdin(process::Stdio::inherit());

    match cmd.status() {
        Ok(status) => {
            // Ensure correct exit code is returned
            let code = status.code().unwrap_or(1);
            process::exit(code);
        }
        Err(e) => {
            Err(e).chain_err(|| rustup_utils::ErrorKind::RunningCommand {
                name: OsStr::new(arg0).to_owned(),
            })
        }
    }
}

#[cfg(unix)]
fn stderr_isatty() -> bool {
    use libc;
    unsafe { libc::isatty(libc::STDERR_FILENO) != 0 }
}

#[cfg(windows)]
fn stderr_isatty() -> bool {
    type DWORD = u32;
    type BOOL = i32;
    type HANDLE = *mut u8;
    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
    extern "system" {
        fn GetStdHandle(which: DWORD) -> HANDLE;
        fn GetConsoleMode(hConsoleHandle: HANDLE,
                          lpMode: *mut DWORD) -> BOOL;
    }
    unsafe {
        let handle = GetStdHandle(STD_ERROR_HANDLE);
        let mut out = 0;
        GetConsoleMode(handle, &mut out) != 0
    }
}
<commit_msg>Fix build<commit_after>use std::ffi::OsStr;
use std::fs::File;
use std::io::{self, Write, BufRead, BufReader, Seek, SeekFrom};
use std::process::{self, Command, Stdio};
use std::time::Instant;
use regex::Regex;
use tempfile::tempfile;

use Cfg;
use errors::*;
use notifications::*;
use rustup_utils;
use telemetry::{Telemetry, TelemetryEvent};

pub fn run_command_for_dir<S: AsRef<OsStr>>(cmd: Command,
                                            arg0: &str,
                                            args: &[S],
                                            cfg: &Cfg) -> Result<()> {
    if (arg0 == "rustc" || arg0 == "rustc.exe") && try!(cfg.telemetry_enabled()) {
        return telemetry_rustc(cmd, arg0, args, cfg);
    }

    run_command_for_dir_without_telemetry(cmd, arg0, args)
}

fn telemetry_rustc<S: AsRef<OsStr>>(mut cmd: Command,
                                    arg0: &str,
                                    args: &[S], cfg: &Cfg) -> Result<()> {
    #[cfg(unix)]
    fn file_as_stdio(file: &File) -> Stdio {
        use std::os::unix::io::{AsRawFd, FromRawFd};
        unsafe { Stdio::from_raw_fd(file.as_raw_fd()) }
    }

    #[cfg(windows)]
    fn file_as_stdio(file: &File) -> Stdio {
        use std::os::windows::io::{AsRawHandle, FromRawHandle};
        unsafe { Stdio::from_raw_handle(file.as_raw_handle()) }
    }

    let now = Instant::now();

    cmd.args(args);

    let has_color_args = args.iter().any(|e| {
        let e = e.as_ref().to_str().unwrap_or("");
        e.starts_with("--color")
    });

    if stderr_isatty() && !has_color_args
    {
        cmd.arg("--color");
        cmd.arg("always");
    }

    let mut cmd_err_file = tempfile().unwrap();
    let cmd_err_stdio = file_as_stdio(&cmd_err_file);

    // FIXME rust-lang/rust#32254. It's not clear to me
    // when and why this is needed.
    let mut cmd = cmd.stdin(Stdio::inherit())
                    .stdout(Stdio::inherit())
                    .stderr(cmd_err_stdio)
                    .spawn()
                    .unwrap();

    let status = cmd.wait();

    let duration = now.elapsed();

    let ms = (duration.as_secs() as u64 * 1000) + (duration.subsec_nanos() as u64 / 1000 / 1000);

    let t = Telemetry::new(cfg.multirust_dir.join("telemetry"));

    match status {
        Ok(status) => {
            let exit_code = status.code().unwrap_or(1);

            let re = Regex::new(r"\[(?P<error>E.{4})\]").unwrap();

            let mut buffer = String::new();
            // Chose a HashSet instead of a Vec to avoid calls to sort() and dedup().
            // The HashSet should be faster if there are a lot of errors, too.
            let mut errors: Vec<String> = Vec::new();

            let stderr = io::stderr();
            let mut handle = stderr.lock();

            cmd_err_file.seek(SeekFrom::Start(0)).unwrap();

            let mut buffered_stderr = BufReader::new(cmd_err_file);

            while buffered_stderr.read_line(&mut buffer).unwrap() > 0 {
                let b = buffer.to_owned();
                buffer.clear();
                let _ = handle.write(b.as_bytes());

                if let Some(caps) = re.captures(&b) {
                    if !caps.is_empty() {
                        errors.push(caps.name("error").unwrap_or("").to_owned());
                    }
                };
            }

            let e = if errors.is_empty() { None } else { Some(errors) };

            let te = TelemetryEvent::RustcRun { duration_ms: ms,
                                                exit_code: exit_code,
                                                errors: e };

            let _ = t.log_telemetry(te).map_err(|xe| {
                (cfg.notify_handler)(Notification::TelemetryCleanupError(&xe));
            });

            process::exit(exit_code);
        },
        Err(e) => {
            let exit_code = e.raw_os_error().unwrap_or(1);
            let te = TelemetryEvent::RustcRun { duration_ms: ms,
                                                exit_code: exit_code,
                                                errors: None };

            let _ = t.log_telemetry(te).map_err(|xe| {
                (cfg.notify_handler)(Notification::TelemetryCleanupError(&xe));
            });

            Err(e).chain_err(|| rustup_utils::ErrorKind::RunningCommand {
                name: OsStr::new(arg0).to_owned(),
            })
        },
    }
}

fn run_command_for_dir_without_telemetry<S: AsRef<OsStr>>(
    mut cmd: Command, arg0: &str, args: &[S]) -> Result<()>
{
    cmd.args(args);

    // FIXME rust-lang/rust#32254. It's not clear to me
    // when and why this is needed.
    cmd.stdin(process::Stdio::inherit());

    match cmd.status() {
        Ok(status) => {
            // Ensure correct exit code is returned
            let code = status.code().unwrap_or(1);
            process::exit(code);
        }
        Err(e) => {
            Err(e).chain_err(|| rustup_utils::ErrorKind::RunningCommand {
                name: OsStr::new(arg0).to_owned(),
            })
        }
    }
}

#[cfg(unix)]
fn stderr_isatty() -> bool {
    use libc;
    unsafe { libc::isatty(libc::STDERR_FILENO) != 0 }
}

#[cfg(windows)]
fn stderr_isatty() -> bool {
    type DWORD = u32;
    type BOOL = i32;
    type HANDLE = *mut u8;
    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
    extern "system" {
        fn GetStdHandle(which: DWORD) -> HANDLE;
        fn GetConsoleMode(hConsoleHandle: HANDLE,
                          lpMode: *mut DWORD) -> BOOL;
    }
    unsafe {
        let handle = GetStdHandle(STD_ERROR_HANDLE);
        let mut out = 0;
        GetConsoleMode(handle, &mut out) != 0
    }
}
<|endoftext|>


<commit_before>use std::iter::IntoIterator;
use std::str::FromStr;

use crate::error::Result;
use crate::map::Map;
use crate::source::AsyncSource;
use crate::{config::Config, path::Expression, source::Source, value::Value};

/// A configuration builder
///
/// It registers ordered sources of configuration to later build consistent [`Config`] from them.
/// Configuration sources it defines are defaults, [`Source`]s and overrides.
///
/// Defaults are alaways loaded first and can be overwritten by any of two other sources.
/// Overrides are always loaded last, thus cannot be overridden.
/// Both can be only set explicitly key by key in code
/// using [`set_default`](Self::set_default) or [`set_override`](Self::set_override).
///
/// An intermediate category, [`Source`], set groups of keys at once implicitly using data coming from external sources
/// like files, environment variables or others that one implements. Defining a [`Source`] is as simple as implementing
/// a trait for a struct.
///
/// Adding sources, setting defaults and overrides does not invoke any I/O nor builds a config.
/// It happens on demand when [`build`](Self::build) (or its alternative) is called.
/// Therefore all errors, related to any of the [`Source`] will only show up then.
///
/// # Sync and async builder
///
/// [`ConfigBuilder`] uses type parameter to keep track of builder state.
///
/// In [`DefaultState`] builder only supports [`Source`]s
///
/// In [`AsyncState`] it supports both [`Source`]s and [`AsyncSource`]s at the price of building using `async fn`.
///
/// # Examples
///
/// ```rust
/// # use config::*;
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = Config::builder()
///     .set_default("default", "1")?
///     .add_source(File::new("config/settings", FileFormat::Json))
/// //  .add_async_source(...)
///     .set_override("override", "1")?;
///
/// match builder.build() {
///     Ok(config) => {
///         // use your config
///     },
///     Err(e) => {
///         // something went wrong
///     }
/// }
/// # Ok(())
/// # }
/// ```
///
/// If any [`AsyncSource`] is used, the builder will transition to [`AsyncState`].
/// In such case, it is required to _await_ calls to [`build`](Self::build) and its non-consuming sibling.
///
/// Calls can be not chained as well
/// ```rust
/// # use std::error::Error;
/// # use config::*;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = Config::builder();
/// builder = builder.set_default("default", "1")?;
/// builder = builder.add_source(File::new("config/settings", FileFormat::Json));
/// builder = builder.add_source(File::new("config/settings.prod", FileFormat::Json));
/// builder = builder.set_override("override", "1")?;
/// # Ok(())
/// # }
/// ```
///
/// Calling [`Config::builder`](Config::builder) yields builder in the default state.
/// If having an asynchronous state as the initial state is desired, _turbofish_ notation needs to be used.
/// ```rust
/// # use config::{*, builder::AsyncState};
/// let mut builder = ConfigBuilder::<AsyncState>::default();
/// ```
///
/// If for some reason acquiring builder in default state is required without calling [`Config::builder`](Config::builder)
/// it can also be achieved.
/// ```rust
/// # use config::{*, builder::DefaultState};
/// let mut builder = ConfigBuilder::<DefaultState>::default();
/// ```
#[derive(Debug, Clone, Default)]
pub struct ConfigBuilder<St: BuilderState> {
    defaults: Map<Expression, Value>,
    overrides: Map<Expression, Value>,
    state: St,
}

/// Represents [`ConfigBuilder`] state.
pub trait BuilderState {}

/// Represents data specific to builder in default, sychronous state, without support for async.
#[derive(Debug, Default)]
pub struct DefaultState {
    sources: Vec<Box<dyn Source + Send + Sync>>,
}

/// The asynchronous configuration builder.
///
/// Similar to a [`ConfigBuilder`] it maintains a set of defaults, a set of sources, and overrides.
///
/// Defaults do not override anything, sources override defaults, and overrides override anything else.
/// Within those three groups order of adding them at call site matters - entities added later take precedence.
///
/// For more detailed description and examples see [`ConfigBuilder`].
/// [`AsyncConfigBuilder`] is just an extension of it that takes async functions into account.
///
/// To obtain a [`Config`] call [`build`](AsyncConfigBuilder::build) or [`build_cloned`](AsyncConfigBuilder::build_cloned)
///
/// # Example
/// Since this library does not implement any [`AsyncSource`] an example in rustdocs cannot be given.
/// Detailed explanation about why such a source is not implemented is in [`AsyncSource`]'s documentation.
///
/// Refer to [`ConfigBuilder`] for similar API sample usage or to the examples folder of the crate, where such a source is implemented.
#[derive(Debug, Clone, Default)]
pub struct AsyncConfigBuilder {}

/// Represents data specific to builder in asychronous state, with support for async.
#[derive(Debug, Default)]
pub struct AsyncState {
    sources: Vec<SourceType>,
}

#[derive(Debug, Clone)]
enum SourceType {
    Sync(Box<dyn Source + Send + Sync>),
    Async(Box<dyn AsyncSource + Send + Sync>),
}

impl BuilderState for DefaultState {}
impl BuilderState for AsyncState {}

impl<St: BuilderState> ConfigBuilder<St> {
    // operations allowed in any state

    /// Set a default `value` at `key`
    ///
    /// This value can be overwritten by any [`Source`], [`AsyncSource`] or override.
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_default<S, T>(mut self, key: S, value: T) -> Result<Self>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.defaults
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }

    /// Set an override
    ///
    /// This function sets an overwrite value. It will not be altered by any default, [`Source`] nor [`AsyncSource`]
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_override<S, T>(mut self, key: S, value: T) -> Result<Self>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.overrides
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }
}

impl ConfigBuilder<DefaultState> {
    // operations allowed in sync state

    /// Registers new [`Source`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`Source`] is only saved in internal register for later use.
    #[must_use]
    pub fn add_source<T>(mut self, source: T) -> Self
    where
        T: Source + Send + Sync + 'static,
    {
        self.state.sources.push(Box::new(source));
        self
    }

    /// Registers new [`AsyncSource`] in this builder and forces transition to [`AsyncState`].
    ///
    /// Calling this method does not invoke any I/O. [`AsyncSource`] is only saved in internal register for later use.
    pub fn add_async_source<T>(self, source: T) -> ConfigBuilder<AsyncState>
    where
        T: AsyncSource + Send + Sync + 'static,
    {
        let async_state = ConfigBuilder {
            state: AsyncState {
                sources: self
                    .state
                    .sources
                    .into_iter()
                    .map(|s| SourceType::Sync(s))
                    .collect(),
            },
            defaults: self.defaults,
            overrides: self.overrides,
        };

        async_state.add_async_source(source)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// This is the method that invokes all I/O operations.
    /// For a non consuming alternative see [`build_cloned`](Self::build_cloned)
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build(self) -> Result<Config> {
        Self::build_internal(self.defaults, self.overrides, &self.state.sources)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// Similar to [`build`](Self::build), but it does not take ownership of `ConfigBuilder` to allow later reuse.
    /// Internally it clones data to achieve it.
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build_cloned(&self) -> Result<Config> {
        Self::build_internal(
            self.defaults.clone(),
            self.overrides.clone(),
            &self.state.sources,
        )
    }

    fn build_internal(
        defaults: Map<Expression, Value>,
        overrides: Map<Expression, Value>,
        sources: &[Box<dyn Source + Send + Sync>],
    ) -> Result<Config> {
        let mut cache: Value = Map::<String, Value>::new().into();

        // Add defaults
        for (key, val) in defaults {
            key.set(&mut cache, val);
        }

        // Add sources
        sources.collect_to(&mut cache)?;

        // Add overrides
        for (key, val) in overrides {
            key.set(&mut cache, val);
        }

        Ok(Config::new(cache))
    }
}

impl ConfigBuilder<AsyncState> {
    // operations allowed in async state

    /// Registers new [`Source`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`Source`] is only saved in internal register for later use.
    #[must_use]
    pub fn add_source<T>(mut self, source: T) -> Self
    where
        T: Source + Send + Sync + 'static,
    {
        self.state.sources.push(SourceType::Sync(Box::new(source)));
        self
    }

    /// Registers new [`AsyncSource`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`AsyncSource`] is only saved in internal register for later use.
    #[must_use]
    pub fn add_async_source<T>(mut self, source: T) -> Self
    where
        T: AsyncSource + Send + Sync + 'static,
    {
        self.state.sources.push(SourceType::Async(Box::new(source)));
        self
    }

    /// Reads all registered defaults, [`Source`]s, [`AsyncSource`]s and overrides.
    ///
    /// This is the method that invokes all I/O operations.
    /// For a non consuming alternative see [`build_cloned`](Self::build_cloned)
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub async fn build(self) -> Result<Config> {
        Self::build_internal(self.defaults, self.overrides, &self.state.sources).await
    }

    /// Reads all registered defaults, [`Source`]s, [`AsyncSource`]s and overrides.
    ///
    /// Similar to [`build`](Self::build), but it does not take ownership of `ConfigBuilder` to allow later reuse.
    /// Internally it clones data to achieve it.
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub async fn build_cloned(&self) -> Result<Config> {
        Self::build_internal(
            self.defaults.clone(),
            self.overrides.clone(),
            &self.state.sources,
        )
        .await
    }

    async fn build_internal(
        defaults: Map<Expression, Value>,
        overrides: Map<Expression, Value>,
        sources: &[SourceType],
    ) -> Result<Config> {
        let mut cache: Value = Map::<String, Value>::new().into();

        // Add defaults
        for (key, val) in defaults {
            key.set(&mut cache, val);
        }

        for source in sources.iter() {
            match source {
                SourceType::Sync(source) => source.collect_to(&mut cache)?,
                SourceType::Async(source) => source.collect_to(&mut cache).await?,
            }
        }

        // Add overrides
        for (key, val) in overrides {
            key.set(&mut cache, val);
        }

        Ok(Config::new(cache))
    }
}
<commit_msg>Add ConfigBuilder::set_override_option()<commit_after>use std::iter::IntoIterator;
use std::str::FromStr;

use crate::error::Result;
use crate::map::Map;
use crate::source::AsyncSource;
use crate::{config::Config, path::Expression, source::Source, value::Value};

/// A configuration builder
///
/// It registers ordered sources of configuration to later build consistent [`Config`] from them.
/// Configuration sources it defines are defaults, [`Source`]s and overrides.
///
/// Defaults are alaways loaded first and can be overwritten by any of two other sources.
/// Overrides are always loaded last, thus cannot be overridden.
/// Both can be only set explicitly key by key in code
/// using [`set_default`](Self::set_default) or [`set_override`](Self::set_override).
///
/// An intermediate category, [`Source`], set groups of keys at once implicitly using data coming from external sources
/// like files, environment variables or others that one implements. Defining a [`Source`] is as simple as implementing
/// a trait for a struct.
///
/// Adding sources, setting defaults and overrides does not invoke any I/O nor builds a config.
/// It happens on demand when [`build`](Self::build) (or its alternative) is called.
/// Therefore all errors, related to any of the [`Source`] will only show up then.
///
/// # Sync and async builder
///
/// [`ConfigBuilder`] uses type parameter to keep track of builder state.
///
/// In [`DefaultState`] builder only supports [`Source`]s
///
/// In [`AsyncState`] it supports both [`Source`]s and [`AsyncSource`]s at the price of building using `async fn`.
///
/// # Examples
///
/// ```rust
/// # use config::*;
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = Config::builder()
///     .set_default("default", "1")?
///     .add_source(File::new("config/settings", FileFormat::Json))
/// //  .add_async_source(...)
///     .set_override("override", "1")?;
///
/// match builder.build() {
///     Ok(config) => {
///         // use your config
///     },
///     Err(e) => {
///         // something went wrong
///     }
/// }
/// # Ok(())
/// # }
/// ```
///
/// If any [`AsyncSource`] is used, the builder will transition to [`AsyncState`].
/// In such case, it is required to _await_ calls to [`build`](Self::build) and its non-consuming sibling.
///
/// Calls can be not chained as well
/// ```rust
/// # use std::error::Error;
/// # use config::*;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = Config::builder();
/// builder = builder.set_default("default", "1")?;
/// builder = builder.add_source(File::new("config/settings", FileFormat::Json));
/// builder = builder.add_source(File::new("config/settings.prod", FileFormat::Json));
/// builder = builder.set_override("override", "1")?;
/// # Ok(())
/// # }
/// ```
///
/// Calling [`Config::builder`](Config::builder) yields builder in the default state.
/// If having an asynchronous state as the initial state is desired, _turbofish_ notation needs to be used.
/// ```rust
/// # use config::{*, builder::AsyncState};
/// let mut builder = ConfigBuilder::<AsyncState>::default();
/// ```
///
/// If for some reason acquiring builder in default state is required without calling [`Config::builder`](Config::builder)
/// it can also be achieved.
/// ```rust
/// # use config::{*, builder::DefaultState};
/// let mut builder = ConfigBuilder::<DefaultState>::default();
/// ```
#[derive(Debug, Clone, Default)]
pub struct ConfigBuilder<St: BuilderState> {
    defaults: Map<Expression, Value>,
    overrides: Map<Expression, Value>,
    state: St,
}

/// Represents [`ConfigBuilder`] state.
pub trait BuilderState {}

/// Represents data specific to builder in default, sychronous state, without support for async.
#[derive(Debug, Default)]
pub struct DefaultState {
    sources: Vec<Box<dyn Source + Send + Sync>>,
}

/// The asynchronous configuration builder.
///
/// Similar to a [`ConfigBuilder`] it maintains a set of defaults, a set of sources, and overrides.
///
/// Defaults do not override anything, sources override defaults, and overrides override anything else.
/// Within those three groups order of adding them at call site matters - entities added later take precedence.
///
/// For more detailed description and examples see [`ConfigBuilder`].
/// [`AsyncConfigBuilder`] is just an extension of it that takes async functions into account.
///
/// To obtain a [`Config`] call [`build`](AsyncConfigBuilder::build) or [`build_cloned`](AsyncConfigBuilder::build_cloned)
///
/// # Example
/// Since this library does not implement any [`AsyncSource`] an example in rustdocs cannot be given.
/// Detailed explanation about why such a source is not implemented is in [`AsyncSource`]'s documentation.
///
/// Refer to [`ConfigBuilder`] for similar API sample usage or to the examples folder of the crate, where such a source is implemented.
#[derive(Debug, Clone, Default)]
pub struct AsyncConfigBuilder {}

/// Represents data specific to builder in asychronous state, with support for async.
#[derive(Debug, Default)]
pub struct AsyncState {
    sources: Vec<SourceType>,
}

#[derive(Debug, Clone)]
enum SourceType {
    Sync(Box<dyn Source + Send + Sync>),
    Async(Box<dyn AsyncSource + Send + Sync>),
}

impl BuilderState for DefaultState {}
impl BuilderState for AsyncState {}

impl<St: BuilderState> ConfigBuilder<St> {
    // operations allowed in any state

    /// Set a default `value` at `key`
    ///
    /// This value can be overwritten by any [`Source`], [`AsyncSource`] or override.
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_default<S, T>(mut self, key: S, value: T) -> Result<Self>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.defaults
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }

    /// Set an override
    ///
    /// This function sets an overwrite value. It will not be altered by any default, [`Source`] nor [`AsyncSource`]
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_override<S, T>(mut self, key: S, value: T) -> Result<Self>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.overrides
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }

    /// Sets an override if value is Some(_)
    ///
    /// This function sets an overwrite value if Some(_) is passed. If None is passed, this function does nothing.
    /// It will not be altered by any default, [`Source`] nor [`AsyncSource`]
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_override_option<S, T>(mut self, key: S, value: Option<T>) -> Result<Self>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        if let Some(value) = value {
            self.overrides
                .insert(Expression::from_str(key.as_ref())?, value.into());
        }
        Ok(self)
    }
}

impl ConfigBuilder<DefaultState> {
    // operations allowed in sync state

    /// Registers new [`Source`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`Source`] is only saved in internal register for later use.
    #[must_use]
    pub fn add_source<T>(mut self, source: T) -> Self
    where
        T: Source + Send + Sync + 'static,
    {
        self.state.sources.push(Box::new(source));
        self
    }

    /// Registers new [`AsyncSource`] in this builder and forces transition to [`AsyncState`].
    ///
    /// Calling this method does not invoke any I/O. [`AsyncSource`] is only saved in internal register for later use.
    pub fn add_async_source<T>(self, source: T) -> ConfigBuilder<AsyncState>
    where
        T: AsyncSource + Send + Sync + 'static,
    {
        let async_state = ConfigBuilder {
            state: AsyncState {
                sources: self
                    .state
                    .sources
                    .into_iter()
                    .map(|s| SourceType::Sync(s))
                    .collect(),
            },
            defaults: self.defaults,
            overrides: self.overrides,
        };

        async_state.add_async_source(source)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// This is the method that invokes all I/O operations.
    /// For a non consuming alternative see [`build_cloned`](Self::build_cloned)
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build(self) -> Result<Config> {
        Self::build_internal(self.defaults, self.overrides, &self.state.sources)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// Similar to [`build`](Self::build), but it does not take ownership of `ConfigBuilder` to allow later reuse.
    /// Internally it clones data to achieve it.
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build_cloned(&self) -> Result<Config> {
        Self::build_internal(
            self.defaults.clone(),
            self.overrides.clone(),
            &self.state.sources,
        )
    }

    fn build_internal(
        defaults: Map<Expression, Value>,
        overrides: Map<Expression, Value>,
        sources: &[Box<dyn Source + Send + Sync>],
    ) -> Result<Config> {
        let mut cache: Value = Map::<String, Value>::new().into();

        // Add defaults
        for (key, val) in defaults {
            key.set(&mut cache, val);
        }

        // Add sources
        sources.collect_to(&mut cache)?;

        // Add overrides
        for (key, val) in overrides {
            key.set(&mut cache, val);
        }

        Ok(Config::new(cache))
    }
}

impl ConfigBuilder<AsyncState> {
    // operations allowed in async state

    /// Registers new [`Source`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`Source`] is only saved in internal register for later use.
    #[must_use]
    pub fn add_source<T>(mut self, source: T) -> Self
    where
        T: Source + Send + Sync + 'static,
    {
        self.state.sources.push(SourceType::Sync(Box::new(source)));
        self
    }

    /// Registers new [`AsyncSource`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`AsyncSource`] is only saved in internal register for later use.
    #[must_use]
    pub fn add_async_source<T>(mut self, source: T) -> Self
    where
        T: AsyncSource + Send + Sync + 'static,
    {
        self.state.sources.push(SourceType::Async(Box::new(source)));
        self
    }

    /// Reads all registered defaults, [`Source`]s, [`AsyncSource`]s and overrides.
    ///
    /// This is the method that invokes all I/O operations.
    /// For a non consuming alternative see [`build_cloned`](Self::build_cloned)
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub async fn build(self) -> Result<Config> {
        Self::build_internal(self.defaults, self.overrides, &self.state.sources).await
    }

    /// Reads all registered defaults, [`Source`]s, [`AsyncSource`]s and overrides.
    ///
    /// Similar to [`build`](Self::build), but it does not take ownership of `ConfigBuilder` to allow later reuse.
    /// Internally it clones data to achieve it.
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub async fn build_cloned(&self) -> Result<Config> {
        Self::build_internal(
            self.defaults.clone(),
            self.overrides.clone(),
            &self.state.sources,
        )
        .await
    }

    async fn build_internal(
        defaults: Map<Expression, Value>,
        overrides: Map<Expression, Value>,
        sources: &[SourceType],
    ) -> Result<Config> {
        let mut cache: Value = Map::<String, Value>::new().into();

        // Add defaults
        for (key, val) in defaults {
            key.set(&mut cache, val);
        }

        for source in sources.iter() {
            match source {
                SourceType::Sync(source) => source.collect_to(&mut cache)?,
                SourceType::Async(source) => source.collect_to(&mut cache).await?,
            }
        }

        // Add overrides
        for (key, val) in overrides {
            key.set(&mut cache, val);
        }

        Ok(Config::new(cache))
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use std::{collections::HashMap, iter::IntoIterator};

use crate::{config::Config, error, path::Expression, source::Source, value::Value};

/// A configuration builder
///
/// It registers ordered sources of configuration to later build consistent [`Config`] from them.
/// Configuration sources it defines are defaults, [`Source`]s and overrides.
///
/// Defaults are alaways loaded first and can be overwritten by any of two other sources.
/// Overrides are always loaded last, thus cannot be overridden.
/// Both can be only set explicitly key by key in code
/// using [`set_default`](Self::set_default) or [`set_override`](Self::set_override).
///
/// An intermediate category, [`Source`], set groups of keys at once implicitly using data coming from external sources
/// like files, environment variables or others that one implements. Defining a [`Source`] is as simple as implementing
/// a trait for a struct.
///
/// Adding sources, setting defaults and overrides does not invoke any I/O nor builds a config.
/// It happens on demand when [`build`](Self::build) (or its alternative) is called.
/// Therefore all errors, related to any of the [`Source`] will only show up then.
///
/// # Examples
///
/// ```rust
/// # use config::*;
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = ConfigBuilder::default()
///     .set_default("default", "1")?
///     .add_source(File::new("config/settings", FileFormat::Json))
///     .set_override("override", "1")?;
///
/// match builder.build() {
///     Ok(config) => {
///         // use your config
///     },
///     Err(e) => {
///         // something went wrong
///     }
/// }
/// # Ok(())
/// # }
/// ```
///
/// Calls can be not chained as well
/// ```rust
/// # use std::error::Error;
/// # use config::*;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = ConfigBuilder::default();
/// builder = builder.set_default("default", "1")?;
/// builder = builder.add_source(File::new("config/settings", FileFormat::Json));
/// builder = builder.add_source(File::new("config/settings.prod", FileFormat::Json));
/// builder = builder.set_override("override", "1")?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug, Clone, Default)]
pub struct ConfigBuilder {
    defaults: HashMap<Expression, Value>,
    overrides: HashMap<Expression, Value>,
    sources: Vec<Box<dyn Source + Send + Sync>>,
}

impl ConfigBuilder {
    /// Set a default `value` at `key`
    ///
    /// This value can be overwritten by any [`Source`] or override.
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_default<S, T>(mut self, key: S, value: T) -> error::Result<ConfigBuilder>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.defaults
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }

    /// Registers new [`Source`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`Source`] is only saved in internal register for later use.
    pub fn add_source<T>(mut self, source: T) -> Self
    where
        T: Source + Send + Sync + 'static,
    {
        self.sources.push(Box::new(source));
        self
    }

    /// Set an override
    ///
    /// This function sets an overwrite value. It will not be altered by any default or [`Source`]
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_override<S, T>(mut self, key: S, value: T) -> error::Result<ConfigBuilder>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.overrides
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// This is the method that invokes all I/O operations.
    /// For a non consuming alternative see [`build_cloned`](Self::build_cloned)
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build(self) -> error::Result<Config> {
        Self::build_internal(self.defaults, self.overrides, &self.sources)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// Similar to [`build`](Self::build), but it does not take ownership of `ConfigBuilder` to allow later reuse.
    /// Internally it clones data to achieve it.
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build_cloned(&self) -> error::Result<Config> {
        Self::build_internal(self.defaults.clone(), self.overrides.clone(), &self.sources)
    }

    fn build_internal(
        defaults: HashMap<Expression, Value>,
        overrides: HashMap<Expression, Value>,
        sources: &[Box<dyn Source + Send + Sync>],
    ) -> error::Result<Config> {
        let mut cache: Value = HashMap::<String, Value>::new().into();

        // Add defaults
        for (key, val) in defaults.into_iter() {
            key.set(&mut cache, val);
        }

        // Add sources
        sources.collect_to(&mut cache)?;

        // Add overrides
        for (key, val) in overrides.into_iter() {
            key.set(&mut cache, val);
        }

        Ok(Config::new(cache))
    }
}
<commit_msg>Refactor: Import Result and use it instead of specifying full type path<commit_after>use std::str::FromStr;
use std::{collections::HashMap, iter::IntoIterator};

use crate::error::Result;
use crate::{config::Config, path::Expression, source::Source, value::Value};

/// A configuration builder
///
/// It registers ordered sources of configuration to later build consistent [`Config`] from them.
/// Configuration sources it defines are defaults, [`Source`]s and overrides.
///
/// Defaults are alaways loaded first and can be overwritten by any of two other sources.
/// Overrides are always loaded last, thus cannot be overridden.
/// Both can be only set explicitly key by key in code
/// using [`set_default`](Self::set_default) or [`set_override`](Self::set_override).
///
/// An intermediate category, [`Source`], set groups of keys at once implicitly using data coming from external sources
/// like files, environment variables or others that one implements. Defining a [`Source`] is as simple as implementing
/// a trait for a struct.
///
/// Adding sources, setting defaults and overrides does not invoke any I/O nor builds a config.
/// It happens on demand when [`build`](Self::build) (or its alternative) is called.
/// Therefore all errors, related to any of the [`Source`] will only show up then.
///
/// # Examples
///
/// ```rust
/// # use config::*;
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = ConfigBuilder::default()
///     .set_default("default", "1")?
///     .add_source(File::new("config/settings", FileFormat::Json))
///     .set_override("override", "1")?;
///
/// match builder.build() {
///     Ok(config) => {
///         // use your config
///     },
///     Err(e) => {
///         // something went wrong
///     }
/// }
/// # Ok(())
/// # }
/// ```
///
/// Calls can be not chained as well
/// ```rust
/// # use std::error::Error;
/// # use config::*;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut builder = ConfigBuilder::default();
/// builder = builder.set_default("default", "1")?;
/// builder = builder.add_source(File::new("config/settings", FileFormat::Json));
/// builder = builder.add_source(File::new("config/settings.prod", FileFormat::Json));
/// builder = builder.set_override("override", "1")?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug, Clone, Default)]
pub struct ConfigBuilder {
    defaults: HashMap<Expression, Value>,
    overrides: HashMap<Expression, Value>,
    sources: Vec<Box<dyn Source + Send + Sync>>,
}

impl ConfigBuilder {
    /// Set a default `value` at `key`
    ///
    /// This value can be overwritten by any [`Source`] or override.
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_default<S, T>(mut self, key: S, value: T) -> Result<ConfigBuilder>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.defaults
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }

    /// Registers new [`Source`] in this builder.
    ///
    /// Calling this method does not invoke any I/O. [`Source`] is only saved in internal register for later use.
    pub fn add_source<T>(mut self, source: T) -> Self
    where
        T: Source + Send + Sync + 'static,
    {
        self.sources.push(Box::new(source));
        self
    }

    /// Set an override
    ///
    /// This function sets an overwrite value. It will not be altered by any default or [`Source`]
    ///
    /// # Errors
    ///
    /// Fails if `Expression::from_str(key)` fails.
    pub fn set_override<S, T>(mut self, key: S, value: T) -> Result<ConfigBuilder>
    where
        S: AsRef<str>,
        T: Into<Value>,
    {
        self.overrides
            .insert(Expression::from_str(key.as_ref())?, value.into());
        Ok(self)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// This is the method that invokes all I/O operations.
    /// For a non consuming alternative see [`build_cloned`](Self::build_cloned)
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build(self) -> Result<Config> {
        Self::build_internal(self.defaults, self.overrides, &self.sources)
    }

    /// Reads all registered [`Source`]s.
    ///
    /// Similar to [`build`](Self::build), but it does not take ownership of `ConfigBuilder` to allow later reuse.
    /// Internally it clones data to achieve it.
    ///
    /// # Errors
    /// If source collection fails, be it technical reasons or related to inability to read data as `Config` for different reasons,
    /// this method returns error.
    pub fn build_cloned(&self) -> Result<Config> {
        Self::build_internal(self.defaults.clone(), self.overrides.clone(), &self.sources)
    }

    fn build_internal(
        defaults: HashMap<Expression, Value>,
        overrides: HashMap<Expression, Value>,
        sources: &[Box<dyn Source + Send + Sync>],
    ) -> Result<Config> {
        let mut cache: Value = HashMap::<String, Value>::new().into();

        // Add defaults
        for (key, val) in defaults.into_iter() {
            key.set(&mut cache, val);
        }

        // Add sources
        sources.collect_to(&mut cache)?;

        // Add overrides
        for (key, val) in overrides.into_iter() {
            key.set(&mut cache, val);
        }

        Ok(Config::new(cache))
    }
}
<|endoftext|>


<commit_before>#[crate_type = "rlib"];
#[crate_id="github.com/xsleonard/sdl2_image-rs#sdl2_image:0.1"];
#[desc = "SDL2_image bindings and wrappers"];
#[comment = "SDL2_image bindings and wrappers"];
#[license = "MIT"];

extern mod sdl2;

use std::libc::{c_int, c_char};
use std::ptr;
use std::cast;
use std::io;
use sdl2::surface::Surface;
use sdl2::render::{Texture, Renderer};
use sdl2::get_error;

mod ffi;

#[deriving(Clone, Eq, IterBytes, ToStr)]
pub enum InitFlag {
    InitJpg = ffi::IMG_INIT_JPG as int,
    InitPng = ffi::IMG_INIT_PNG as int,
    InitTif = ffi::IMG_INIT_TIF as int,
    InitWebp = ffi::IMG_INIT_WEBP as int,
}

pub struct ImageVersion {
    major: int,
    minor: int,
    patch: int,
}

impl ToStr for ImageVersion {
    fn to_str(&self) -> ~str {
        format!("{}.{}.{}", self.major, self.minor, self.patch)
    }
}

impl ImageVersion {
    fn from_sdl_version(sv: *ffi::SDL_version) -> ImageVersion {
        unsafe {
            let v = *sv;
            ImageVersion{ major: v.major, minor: v.minor, patch: v.patch }
        }
    }
}

// TODO -- this should be in rust-sdl2
// Most of the sdl2_image API relies on SDL_RWops.

// #[deriving(Eq)]
// pub struct RWops {
//     raw: *SDL_RWops;
//     owned: bool;
// }

// impl Drop for RWops {
//     fn drop(&mut self) {
//         if self.owned {
//             unsafe {
//                 // TODO -- close() returns a c_int error status.
//                 // How do we deal with errors in the destructor?
//                 // Probably either kill the task, or don't implement this
//                 // as a destructor
//                 self.raw.close()
//             }
//         }
//     }
// }

pub trait ImageLoader<T> {
    fn from_file(filename: &str) -> Result<~T, ~str>;
    fn from_xpm_array(xpm: **i8) -> Result<~T, ~str>;
}

pub trait ImageSaver {
    fn save(&self, filename: &str) -> Result<(), ~str>;
}

// TODO -- does this need to be pub'd?
impl ImageLoader<Surface> for Surface {
    fn from_file(filename: &str) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_Load(filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    fn from_xpm_array(xpm: **i8) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_ReadXPMFromArray(xpm as **c_char);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }
}

impl ImageSaver for Surface {
    fn save(&self, filename: &str) -> Result<(), ~str> {
        unsafe {
            let status = ffi::IMG_SavePNG(self.raw,
                                          filename.to_c_str().unwrap());
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

pub trait TextureLoader {
    fn load_texture_from_file(&self, filename: &str) -> Result<~Texture, ~str>;
}

impl TextureLoader for Renderer {
    fn load_texture_from_file(&self,
                              filename: &str) -> Result<~Texture, ~str> {
        unsafe {
            let raw = ffi::IMG_LoadTexture(self.raw,
                                           filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Texture{ raw: raw, owned: true })
            }
        }
    }
}

pub fn init(flags: &[InitFlag]) -> ~[InitFlag] {
    //! Initializes SDL2_image with InitFlags and returns which
    //! InitFlags were actually used.
    let mut used = ~[];
    unsafe {
        let used_flags = ffi::IMG_Init(
            flags.iter().fold(0, |flags, &flag| {
                flags | flag as ffi::IMG_InitFlags
            })
        );
        for flag in flags.iter() {
            if used_flags & *flag as c_int != 0 {
                used.push(*flag)
            }
        }
    }
    used
}

pub fn quit() {
    unsafe { ffi::IMG_Quit(); }
}

pub fn get_linked_version() -> ImageVersion {
    //! Returns the version of the dynamically linked SDL_image library
    unsafe {
        ImageVersion::from_sdl_version(ffi::IMG_Linked_Version())
    }
}
<commit_msg>link to SDL2_image library<commit_after>#[crate_type = "rlib"];
#[crate_id="github.com/xsleonard/sdl2_image-rs#sdl2_image:0.1"];
#[desc = "SDL2_image bindings and wrappers"];
#[comment = "SDL2_image bindings and wrappers"];
#[license = "MIT"];

extern mod sdl2;

use std::libc::{c_int, c_char};
use std::ptr;
use std::cast;
use std::io;
use sdl2::surface::Surface;
use sdl2::render::{Texture, Renderer};
use sdl2::get_error;

// Setup linking for all targets.
#[cfg(target_os="macos")]
mod mac {
    #[cfg(mac_framework)]
    #[link(kind="framework", name="SDL2_image")]
    extern {}

    #[cfg(not(mac_framework))]
    #[link(name="SDL2_image")]
    extern {}
}

#[cfg(target_os="win32")]
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
mod others {
    #[link(name="SDL2_image")]
    extern {}
}

mod ffi;

#[deriving(Clone, Eq, IterBytes, ToStr)]
pub enum InitFlag {
    InitJpg = ffi::IMG_INIT_JPG as int,
    InitPng = ffi::IMG_INIT_PNG as int,
    InitTif = ffi::IMG_INIT_TIF as int,
    InitWebp = ffi::IMG_INIT_WEBP as int,
}

pub struct ImageVersion {
    major: int,
    minor: int,
    patch: int,
}

impl ToStr for ImageVersion {
    fn to_str(&self) -> ~str {
        format!("{}.{}.{}", self.major, self.minor, self.patch)
    }
}

impl ImageVersion {
    fn from_sdl_version(sv: *ffi::SDL_version) -> ImageVersion {
        unsafe {
            let v = *sv;
            ImageVersion{ major: v.major, minor: v.minor, patch: v.patch }
        }
    }
}

// TODO -- this should be in rust-sdl2
// Most of the sdl2_image API relies on SDL_RWops.

// #[deriving(Eq)]
// pub struct RWops {
//     raw: *SDL_RWops;
//     owned: bool;
// }

// impl Drop for RWops {
//     fn drop(&mut self) {
//         if self.owned {
//             unsafe {
//                 // TODO -- close() returns a c_int error status.
//                 // How do we deal with errors in the destructor?
//                 // Probably either kill the task, or don't implement this
//                 // as a destructor
//                 self.raw.close()
//             }
//         }
//     }
// }

pub trait ImageLoader<T> {
    fn from_file(filename: &str) -> Result<~T, ~str>;
    fn from_xpm_array(xpm: **i8) -> Result<~T, ~str>;
}

pub trait ImageSaver {
    fn save(&self, filename: &str) -> Result<(), ~str>;
}

// TODO -- does this need to be pub'd?
impl ImageLoader<Surface> for Surface {
    fn from_file(filename: &str) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_Load(filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    fn from_xpm_array(xpm: **i8) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_ReadXPMFromArray(xpm as **c_char);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }
}

impl ImageSaver for Surface {
    fn save(&self, filename: &str) -> Result<(), ~str> {
        unsafe {
            let status = ffi::IMG_SavePNG(self.raw,
                                          filename.to_c_str().unwrap());
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

pub trait TextureLoader {
    fn load_texture_from_file(&self, filename: &str) -> Result<~Texture, ~str>;
}

impl TextureLoader for Renderer {
    fn load_texture_from_file(&self,
                              filename: &str) -> Result<~Texture, ~str> {
        unsafe {
            let raw = ffi::IMG_LoadTexture(self.raw,
                                           filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Texture{ raw: raw, owned: true })
            }
        }
    }
}

pub fn init(flags: &[InitFlag]) -> ~[InitFlag] {
    //! Initializes SDL2_image with InitFlags and returns which
    //! InitFlags were actually used.
    let mut used = ~[];
    unsafe {
        let used_flags = ffi::IMG_Init(
            flags.iter().fold(0, |flags, &flag| {
                flags | flag as ffi::IMG_InitFlags
            })
        );
        for flag in flags.iter() {
            if used_flags & *flag as c_int != 0 {
                used.push(*flag)
            }
        }
    }
    used
}

pub fn quit() {
    unsafe { ffi::IMG_Quit(); }
}

pub fn get_linked_version() -> ImageVersion {
    //! Returns the version of the dynamically linked SDL_image library
    unsafe {
        ImageVersion::from_sdl_version(ffi::IMG_Linked_Version())
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::boxed::Box;
use std::result;

pub type Error = Box<error::Error + Send + Sync>;

pub type Result<T> = result::Result<T, Error>;

pub fn other<T>(err: T) -> Error
    where T: Into<Box<error::Error + Sync + Send + 'static>>
{
    err.into()
}
<commit_msg>raftserver: use quick error for raft server error.<commit_after>use std::error;
use std::boxed::Box;
use std::result;
use std::io;
use std::net;
use std::vec::Vec;

use protobuf::ProtobufError;

use util::codec;
use pd;
use raft;
use proto::metapb;

quick_error!{
    #[derive(Debug)]
    pub enum Error {
        RegionNotFound(region_id:u64) {
            description("region is not found")
            display("region {} not found", region_id)
        }
        NotLeader(region_id: u64, leader:Option<metapb::Peer>) {
            description("peer is not leader")
            display("peer is not leader for region {}, leader may {:?}", region_id, leader)
        }
        KeyNotInRegion(key: Vec<u8>, region: metapb::Region) {
            description("key is not in region")
            display("key {:?} is not in region key range [{:?}, {:?}) for region {}",
                key, region.get_start_key(), region.get_end_key(), region.get_region_id())
        }
        Other(err: Box<error::Error + Sync + Send>) {
            cause(err.as_ref())
            description(err.description())
            display("{:?}", err)
        }

        // Following is for From other errors.
        Io(err: io::Error) {
            from()
            cause(err)
            description(err.description())
        }
        // RocksDB uses plain string as the error.
        // Maybe other libs use this too?
        RocksDB(msg: String) {
            from()
            description("RocksDB error")
            display("{}", msg)
        }
        Protobuf(err: ProtobufError) {
            from()
            cause(err)
            description(err.description())
        }
        Codec(err: codec::Error) {
            from()
            cause(err)
            description(err.description())
        }
        AddrParse(err: net::AddrParseError) {
            from()
            cause(err)
            description(err.description())
        }
        Pd(err: pd::Error) {
            from()
            cause(err)
            description(err.description())
        }
        Raft(err: raft::Error) {
            from()
            cause(err)
            description(err.description())
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

pub fn other<T>(err: T) -> Error
    where T: Into<Box<error::Error + Sync + Send + 'static>>
{
    Error::Other(err.into())
}
<|endoftext|>