<commit_before>//! # descriptor
//!
//! Loads the tasks descriptor.

//! It will first load the default descriptor which is defined in cargo-make internally and
//! afterwards tries to find the external descriptor and load it as well.

//! If an extenal descriptor exists, it will be loaded and extend the default descriptor.
//!

#[cfg(test)]
#[path = "./descriptor_test.rs"]
mod descriptor_test;

use crate::command;
use crate::types::{Config, ConfigSection, EnvValue, Extend, ExternalConfig, ModifyConfig, Task};
use indexmap::IndexMap;
use std::env;
use std::fs::{canonicalize, File};
use std::io::Read;
use std::path::{Path, PathBuf};
use toml;

fn merge_env(
    base: &mut IndexMap<String, EnvValue>,
    extended: &mut IndexMap<String, EnvValue>,
) -> IndexMap<String, EnvValue> {
    let mut merged = IndexMap::<String, EnvValue>::new();

    for (key, value) in base.iter() {
        let key_str = key.to_string();
        let value_clone = value.clone();
        merged.insert(key_str, value_clone);
    }

    for (key, value) in extended.iter() {
        let key_str = key.to_string();
        let value_clone = value.clone();

        if merged.contains_key(&key_str) {
            let mut base_value = merged.remove(&key_str).unwrap();

            match (base_value, value_clone.clone()) {
                (
                    EnvValue::Profile(ref base_profile_env),
                    EnvValue::Profile(ref extended_profile_env),
                ) => {
                    let mut base_profile_env_mut = base_profile_env.clone();
                    let mut extended_profile_env_mut = extended_profile_env.clone();

                    let merged_sub_env =
                        merge_env(&mut base_profile_env_mut, &mut extended_profile_env_mut);

                    merged.insert(key_str, EnvValue::Profile(merged_sub_env));
                }
                _ => {
                    merged.insert(key_str, value_clone);
                    ()
                }
            };
        } else {
            merged.insert(key_str, value_clone);
        }
    }

    merged
}

fn merge_tasks(
    base: &mut IndexMap<String, Task>,
    extended: &mut IndexMap<String, Task>,
) -> IndexMap<String, Task> {
    let mut merged = IndexMap::<String, Task>::new();

    for (key, value) in base.iter() {
        let key_str = key.to_string();
        merged.insert(key_str, value.clone());
    }

    for (key, value) in extended.iter() {
        let key_str = key.to_string();
        let mut task = value.clone();

        task = match base.get(key) {
            Some(ref value) => {
                let mut merged_task = Task::new();

                merged_task.extend(value);
                merged_task.extend(&task);

                merged_task
            }
            _ => task,
        };

        merged.insert(key_str, task);
    }

    merged
}

fn run_load_script(external_config: &ExternalConfig) -> bool {
    match external_config.config {
        Some(ref config) => {
            let load_script = config.get_load_script();

            match load_script {
                Some(ref script) => {
                    debug!("Load script found.");

                    command::run_script(script, None, &vec![], true);

                    true
                }
                None => {
                    debug!("No load script defined.");
                    false
                }
            }
        }
        None => {
            debug!("No load script defined.");
            false
        }
    }
}

fn merge_external_configs(config: ExternalConfig, parent_config: ExternalConfig) -> ExternalConfig {
    // merge env
    let mut parent_env = match parent_config.env {
        Some(env) => env,
        None => IndexMap::new(),
    };
    let mut extended_env = match config.env {
        Some(env) => env,
        None => IndexMap::new(),
    };
    let all_env = merge_env(&mut parent_env, &mut extended_env);

    // merge tasks
    let mut parent_tasks = match parent_config.tasks {
        Some(tasks) => tasks,
        None => IndexMap::new(),
    };
    let mut extended_tasks = match config.tasks {
        Some(tasks) => tasks,
        None => IndexMap::new(),
    };
    let all_tasks = merge_tasks(&mut parent_tasks, &mut extended_tasks);

    let mut config_section = ConfigSection::new();
    if parent_config.config.is_some() {
        config_section.extend(&mut parent_config.config.unwrap());
    }
    if config.config.is_some() {
        config_section.extend(&mut config.config.unwrap());
    }

    ExternalConfig {
        extend: None,
        config: Some(config_section),
        env: Some(all_env),
        tasks: Some(all_tasks),
    }
}

fn load_descriptor_extended_makefiles(parent_path: &str, extend_struct: &Extend) -> ExternalConfig {
    match extend_struct {
        Extend::Path(base_file) => load_external_descriptor(parent_path, &base_file, true, false),
        Extend::Options(extend_options) => {
            let force = !extend_options.optional.unwrap_or(false);
            load_external_descriptor(parent_path, &extend_options.path, force, false)
        }
        Extend::List(extend_list) => {
            let mut ordered_list_config = ExternalConfig::new();

            for entry in extend_list.iter() {
                let extend_options = entry.clone();
                let entry_config = load_descriptor_extended_makefiles(
                    parent_path,
                    &Extend::Options(extend_options),
                );

                // merge configs
                ordered_list_config = merge_external_configs(entry_config, ordered_list_config);
            }

            ordered_list_config
        }
    }
}

fn load_external_descriptor(
    base_path: &str,
    file_name: &str,
    force: bool,
    set_env: bool,
) -> ExternalConfig {
    debug!(
        "Loading tasks from file: {} base directory: {}",
        &file_name, &base_path
    );

    let file_path = Path::new(base_path).join(file_name);

    if file_path.exists() && file_path.is_file() {
        if set_env {
            let absolute_file_path = match canonicalize(&file_path) {
                Ok(result_path) => result_path,
                _ => file_path.clone(),
            };

            env::set_var("CARGO_MAKE_MAKEFILE_PATH", &absolute_file_path);
        }

        debug!("Opening file: {:#?}", &file_path);
        let mut file = match File::open(&file_path) {
            Ok(value) => value,
            Err(error) => panic!(
                "Unable to open file, base path: {} file name: {} error: {}",
                base_path, file_name, error
            ),
        };
        let mut external_descriptor = String::new();
        file.read_to_string(&mut external_descriptor).unwrap();

        let file_config: ExternalConfig = match toml::from_str(&external_descriptor) {
            Ok(value) => value,
            Err(error) => panic!("Unable to parse external descriptor, {}", error),
        };
        debug!("Loaded external config: {:#?}", &file_config);

        run_load_script(&file_config);

        match file_config.extend {
            Some(ref extend_struct) => {
                let parent_path_buf = Path::new(base_path).join(file_name).join("..");
                let parent_path = file_path
                    .parent()
                    .unwrap_or(&parent_path_buf)
                    .to_str()
                    .unwrap_or(".");
                debug!("External config parent path: {}", &parent_path);

                let base_file_config =
                    load_descriptor_extended_makefiles(&parent_path, extend_struct);

                merge_external_configs(file_config.clone(), base_file_config)
            }
            None => file_config,
        }
    } else if force {
        error!("Descriptor file: {:#?} not found.", &file_path);
        panic!("Descriptor file: {:#?} not found.", &file_path);
    } else {
        info!("External file not found or is not a file, skipping.");

        ExternalConfig::new()
    }
}

pub(crate) fn load_internal_descriptors(
    stable: bool,
    experimental: bool,
    modify_config: Option<ModifyConfig>,
) -> Config {
    debug!("Loading base tasks.");

    let base_descriptor = if stable {
        include_str!("Makefile.stable.toml")
    } else {
        include_str!("Makefile.base.toml")
    };

    let mut base_config: Config = match toml::from_str(base_descriptor) {
        Ok(value) => value,
        Err(error) => panic!("Unable to parse base descriptor, {}", error),
    };
    debug!("Loaded base config: {:#?}", &base_config);

    if experimental {
        debug!("Loading experimental tasks.");
        let experimental_descriptor = include_str!("Makefile.beta.toml");

        let experimental_config: Config = match toml::from_str(experimental_descriptor) {
            Ok(value) => value,
            Err(error) => panic!("Unable to parse experimental descriptor, {}", error),
        };
        debug!("Loaded experimental config: {:#?}", &experimental_config);

        let mut base_tasks = base_config.tasks;
        let mut experimental_tasks = experimental_config.tasks;
        let all_tasks = merge_tasks(&mut base_tasks, &mut experimental_tasks);

        base_config.tasks = all_tasks;
    }

    // reset
    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE", "");
    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE_PREFIX", "");

    match modify_config {
        Some(props) => {
            base_config.apply(&props);

            match props.namespace {
                Some(ref namespace) => {
                    let prefix = props.get_namespace_prefix();

                    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE", &namespace);
                    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE_PREFIX", &prefix);
                }
                None => (),
            };
        }
        None => (),
    };

    base_config
}

/// Loads the tasks descriptor.

/// It will first load the default descriptor which is defined in cargo-make internally and
/// afterwards tries to find the external descriptor and load it as well.

/// If an extenal descriptor exists, it will be loaded and extend the default descriptor.
fn load_descriptors(
    file_name: &str,
    force: bool,
    env_map: Option<Vec<String>>,
    stable: bool,
    experimental: bool,
    modify_core_tasks: Option<ModifyConfig>,
) -> Config {
    let default_config = load_internal_descriptors(stable, experimental, modify_core_tasks);

    let mut external_config: ExternalConfig = load_external_descriptor(".", file_name, force, true);

    external_config = match env::var("CARGO_MAKE_WORKSPACE_MAKEFILE") {
        Ok(workspace_makefile) => {
            let mut pathbuf = PathBuf::from(workspace_makefile);
            match pathbuf.clone().file_name() {
                Some(workspace_file_name) => match workspace_file_name.to_str() {
                    Some(workspace_file_name_str) => {
                        pathbuf.pop();

                        match pathbuf.to_str() {
                            Some(directory) => {
                                let workspace_config = load_external_descriptor(
                                    directory,
                                    workspace_file_name_str,
                                    false,
                                    false,
                                );
                                merge_external_configs(external_config, workspace_config)
                            }
                            _ => external_config,
                        }
                    }
                    _ => external_config,
                },
                _ => external_config,
            }
        }
        _ => external_config,
    };

    let mut external_tasks = match external_config.tasks {
        Some(tasks) => tasks,
        None => IndexMap::new(),
    };
    let mut default_tasks = default_config.tasks;

    let mut external_env = match external_config.env {
        Some(env) => env,
        None => IndexMap::new(),
    };
    let mut default_env = default_config.env;

    // merge configs
    let mut all_env = merge_env(&mut default_env, &mut external_env);
    all_env = match env_map {
        Some(values) => {
            let mut cli_env = IndexMap::new();

            for env_pair in &values {
                let env_part: Vec<&str> = env_pair.split('=').collect();
                debug!("Checking env pair: {}", &env_pair);

                if env_part.len() == 2 {
                    cli_env.insert(
                        env_part[0].to_string(),
                        EnvValue::Value(env_part[1].to_string()),
                    );
                }
            }

            merge_env(&mut all_env, &mut cli_env)
        }
        None => all_env,
    };

    let all_tasks = merge_tasks(&mut default_tasks, &mut external_tasks);

    let mut config_section = default_config.config.clone();
    config_section.extend(&mut external_config.config.unwrap_or(ConfigSection::new()));

    let config = Config {
        config: config_section,
        env: all_env,
        tasks: all_tasks,
    };

    debug!("Loaded merged config: {:#?}", &config);

    config
}

/// Loads the tasks descriptor.

/// It will first load the default descriptor which is defined in cargo-make internally and
/// afterwards tries to find the external descriptor and load it as well.

/// If an extenal descriptor exists, it will be loaded and extend the default descriptor.
pub(crate) fn load(
    file_name: &str,
    force: bool,
    env_map: Option<Vec<String>>,
    experimental: bool,
) -> Config {
    let mut config = load_descriptors(&file_name, force, env_map.clone(), true, experimental, None);

    if config.config.skip_core_tasks.unwrap_or(false) {
        config = load_descriptors(&file_name, force, env_map.clone(), false, false, None);
    } else {
        let modify_core_tasks = config.config.modify_core_tasks.clone();

        match modify_core_tasks {
            Some(modify_config) => {
                if modify_config.is_modifications_defined() {
                    config = load_descriptors(
                        &file_name,
                        force,
                        env_map.clone(),
                        true,
                        experimental,
                        Some(modify_config),
                    );
                }
            }
            None => (),
        };
    }

    config
}
<commit_msg>fix lint error<commit_after>//! # descriptor
//!
//! Loads the tasks descriptor.

//! It will first load the default descriptor which is defined in cargo-make internally and
//! afterwards tries to find the external descriptor and load it as well.

//! If an extenal descriptor exists, it will be loaded and extend the default descriptor.
//!

#[cfg(test)]
#[path = "./descriptor_test.rs"]
mod descriptor_test;

use crate::command;
use crate::types::{Config, ConfigSection, EnvValue, Extend, ExternalConfig, ModifyConfig, Task};
use indexmap::IndexMap;
use std::env;
use std::fs::{canonicalize, File};
use std::io::Read;
use std::path::{Path, PathBuf};
use toml;

fn merge_env(
    base: &mut IndexMap<String, EnvValue>,
    extended: &mut IndexMap<String, EnvValue>,
) -> IndexMap<String, EnvValue> {
    let mut merged = IndexMap::<String, EnvValue>::new();

    for (key, value) in base.iter() {
        let key_str = key.to_string();
        let value_clone = value.clone();
        merged.insert(key_str, value_clone);
    }

    for (key, value) in extended.iter() {
        let key_str = key.to_string();
        let value_clone = value.clone();

        if merged.contains_key(&key_str) {
            let base_value = merged.remove(&key_str).unwrap();

            match (base_value, value_clone.clone()) {
                (
                    EnvValue::Profile(ref base_profile_env),
                    EnvValue::Profile(ref extended_profile_env),
                ) => {
                    let mut base_profile_env_mut = base_profile_env.clone();
                    let mut extended_profile_env_mut = extended_profile_env.clone();

                    let merged_sub_env =
                        merge_env(&mut base_profile_env_mut, &mut extended_profile_env_mut);

                    merged.insert(key_str, EnvValue::Profile(merged_sub_env));
                }
                _ => {
                    merged.insert(key_str, value_clone);
                    ()
                }
            };
        } else {
            merged.insert(key_str, value_clone);
        }
    }

    merged
}

fn merge_tasks(
    base: &mut IndexMap<String, Task>,
    extended: &mut IndexMap<String, Task>,
) -> IndexMap<String, Task> {
    let mut merged = IndexMap::<String, Task>::new();

    for (key, value) in base.iter() {
        let key_str = key.to_string();
        merged.insert(key_str, value.clone());
    }

    for (key, value) in extended.iter() {
        let key_str = key.to_string();
        let mut task = value.clone();

        task = match base.get(key) {
            Some(ref value) => {
                let mut merged_task = Task::new();

                merged_task.extend(value);
                merged_task.extend(&task);

                merged_task
            }
            _ => task,
        };

        merged.insert(key_str, task);
    }

    merged
}

fn run_load_script(external_config: &ExternalConfig) -> bool {
    match external_config.config {
        Some(ref config) => {
            let load_script = config.get_load_script();

            match load_script {
                Some(ref script) => {
                    debug!("Load script found.");

                    command::run_script(script, None, &vec![], true);

                    true
                }
                None => {
                    debug!("No load script defined.");
                    false
                }
            }
        }
        None => {
            debug!("No load script defined.");
            false
        }
    }
}

fn merge_external_configs(config: ExternalConfig, parent_config: ExternalConfig) -> ExternalConfig {
    // merge env
    let mut parent_env = match parent_config.env {
        Some(env) => env,
        None => IndexMap::new(),
    };
    let mut extended_env = match config.env {
        Some(env) => env,
        None => IndexMap::new(),
    };
    let all_env = merge_env(&mut parent_env, &mut extended_env);

    // merge tasks
    let mut parent_tasks = match parent_config.tasks {
        Some(tasks) => tasks,
        None => IndexMap::new(),
    };
    let mut extended_tasks = match config.tasks {
        Some(tasks) => tasks,
        None => IndexMap::new(),
    };
    let all_tasks = merge_tasks(&mut parent_tasks, &mut extended_tasks);

    let mut config_section = ConfigSection::new();
    if parent_config.config.is_some() {
        config_section.extend(&mut parent_config.config.unwrap());
    }
    if config.config.is_some() {
        config_section.extend(&mut config.config.unwrap());
    }

    ExternalConfig {
        extend: None,
        config: Some(config_section),
        env: Some(all_env),
        tasks: Some(all_tasks),
    }
}

fn load_descriptor_extended_makefiles(parent_path: &str, extend_struct: &Extend) -> ExternalConfig {
    match extend_struct {
        Extend::Path(base_file) => load_external_descriptor(parent_path, &base_file, true, false),
        Extend::Options(extend_options) => {
            let force = !extend_options.optional.unwrap_or(false);
            load_external_descriptor(parent_path, &extend_options.path, force, false)
        }
        Extend::List(extend_list) => {
            let mut ordered_list_config = ExternalConfig::new();

            for entry in extend_list.iter() {
                let extend_options = entry.clone();
                let entry_config = load_descriptor_extended_makefiles(
                    parent_path,
                    &Extend::Options(extend_options),
                );

                // merge configs
                ordered_list_config = merge_external_configs(entry_config, ordered_list_config);
            }

            ordered_list_config
        }
    }
}

fn load_external_descriptor(
    base_path: &str,
    file_name: &str,
    force: bool,
    set_env: bool,
) -> ExternalConfig {
    debug!(
        "Loading tasks from file: {} base directory: {}",
        &file_name, &base_path
    );

    let file_path = Path::new(base_path).join(file_name);

    if file_path.exists() && file_path.is_file() {
        if set_env {
            let absolute_file_path = match canonicalize(&file_path) {
                Ok(result_path) => result_path,
                _ => file_path.clone(),
            };

            env::set_var("CARGO_MAKE_MAKEFILE_PATH", &absolute_file_path);
        }

        debug!("Opening file: {:#?}", &file_path);
        let mut file = match File::open(&file_path) {
            Ok(value) => value,
            Err(error) => panic!(
                "Unable to open file, base path: {} file name: {} error: {}",
                base_path, file_name, error
            ),
        };
        let mut external_descriptor = String::new();
        file.read_to_string(&mut external_descriptor).unwrap();

        let file_config: ExternalConfig = match toml::from_str(&external_descriptor) {
            Ok(value) => value,
            Err(error) => panic!("Unable to parse external descriptor, {}", error),
        };
        debug!("Loaded external config: {:#?}", &file_config);

        run_load_script(&file_config);

        match file_config.extend {
            Some(ref extend_struct) => {
                let parent_path_buf = Path::new(base_path).join(file_name).join("..");
                let parent_path = file_path
                    .parent()
                    .unwrap_or(&parent_path_buf)
                    .to_str()
                    .unwrap_or(".");
                debug!("External config parent path: {}", &parent_path);

                let base_file_config =
                    load_descriptor_extended_makefiles(&parent_path, extend_struct);

                merge_external_configs(file_config.clone(), base_file_config)
            }
            None => file_config,
        }
    } else if force {
        error!("Descriptor file: {:#?} not found.", &file_path);
        panic!("Descriptor file: {:#?} not found.", &file_path);
    } else {
        info!("External file not found or is not a file, skipping.");

        ExternalConfig::new()
    }
}

pub(crate) fn load_internal_descriptors(
    stable: bool,
    experimental: bool,
    modify_config: Option<ModifyConfig>,
) -> Config {
    debug!("Loading base tasks.");

    let base_descriptor = if stable {
        include_str!("Makefile.stable.toml")
    } else {
        include_str!("Makefile.base.toml")
    };

    let mut base_config: Config = match toml::from_str(base_descriptor) {
        Ok(value) => value,
        Err(error) => panic!("Unable to parse base descriptor, {}", error),
    };
    debug!("Loaded base config: {:#?}", &base_config);

    if experimental {
        debug!("Loading experimental tasks.");
        let experimental_descriptor = include_str!("Makefile.beta.toml");

        let experimental_config: Config = match toml::from_str(experimental_descriptor) {
            Ok(value) => value,
            Err(error) => panic!("Unable to parse experimental descriptor, {}", error),
        };
        debug!("Loaded experimental config: {:#?}", &experimental_config);

        let mut base_tasks = base_config.tasks;
        let mut experimental_tasks = experimental_config.tasks;
        let all_tasks = merge_tasks(&mut base_tasks, &mut experimental_tasks);

        base_config.tasks = all_tasks;
    }

    // reset
    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE", "");
    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE_PREFIX", "");

    match modify_config {
        Some(props) => {
            base_config.apply(&props);

            match props.namespace {
                Some(ref namespace) => {
                    let prefix = props.get_namespace_prefix();

                    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE", &namespace);
                    env::set_var("CARGO_MAKE_CORE_TASK_NAMESPACE_PREFIX", &prefix);
                }
                None => (),
            };
        }
        None => (),
    };

    base_config
}

/// Loads the tasks descriptor.

/// It will first load the default descriptor which is defined in cargo-make internally and
/// afterwards tries to find the external descriptor and load it as well.

/// If an extenal descriptor exists, it will be loaded and extend the default descriptor.
fn load_descriptors(
    file_name: &str,
    force: bool,
    env_map: Option<Vec<String>>,
    stable: bool,
    experimental: bool,
    modify_core_tasks: Option<ModifyConfig>,
) -> Config {
    let default_config = load_internal_descriptors(stable, experimental, modify_core_tasks);

    let mut external_config: ExternalConfig = load_external_descriptor(".", file_name, force, true);

    external_config = match env::var("CARGO_MAKE_WORKSPACE_MAKEFILE") {
        Ok(workspace_makefile) => {
            let mut pathbuf = PathBuf::from(workspace_makefile);
            match pathbuf.clone().file_name() {
                Some(workspace_file_name) => match workspace_file_name.to_str() {
                    Some(workspace_file_name_str) => {
                        pathbuf.pop();

                        match pathbuf.to_str() {
                            Some(directory) => {
                                let workspace_config = load_external_descriptor(
                                    directory,
                                    workspace_file_name_str,
                                    false,
                                    false,
                                );
                                merge_external_configs(external_config, workspace_config)
                            }
                            _ => external_config,
                        }
                    }
                    _ => external_config,
                },
                _ => external_config,
            }
        }
        _ => external_config,
    };

    let mut external_tasks = match external_config.tasks {
        Some(tasks) => tasks,
        None => IndexMap::new(),
    };
    let mut default_tasks = default_config.tasks;

    let mut external_env = match external_config.env {
        Some(env) => env,
        None => IndexMap::new(),
    };
    let mut default_env = default_config.env;

    // merge configs
    let mut all_env = merge_env(&mut default_env, &mut external_env);
    all_env = match env_map {
        Some(values) => {
            let mut cli_env = IndexMap::new();

            for env_pair in &values {
                let env_part: Vec<&str> = env_pair.split('=').collect();
                debug!("Checking env pair: {}", &env_pair);

                if env_part.len() == 2 {
                    cli_env.insert(
                        env_part[0].to_string(),
                        EnvValue::Value(env_part[1].to_string()),
                    );
                }
            }

            merge_env(&mut all_env, &mut cli_env)
        }
        None => all_env,
    };

    let all_tasks = merge_tasks(&mut default_tasks, &mut external_tasks);

    let mut config_section = default_config.config.clone();
    config_section.extend(&mut external_config.config.unwrap_or(ConfigSection::new()));

    let config = Config {
        config: config_section,
        env: all_env,
        tasks: all_tasks,
    };

    debug!("Loaded merged config: {:#?}", &config);

    config
}

/// Loads the tasks descriptor.

/// It will first load the default descriptor which is defined in cargo-make internally and
/// afterwards tries to find the external descriptor and load it as well.

/// If an extenal descriptor exists, it will be loaded and extend the default descriptor.
pub(crate) fn load(
    file_name: &str,
    force: bool,
    env_map: Option<Vec<String>>,
    experimental: bool,
) -> Config {
    let mut config = load_descriptors(&file_name, force, env_map.clone(), true, experimental, None);

    if config.config.skip_core_tasks.unwrap_or(false) {
        config = load_descriptors(&file_name, force, env_map.clone(), false, false, None);
    } else {
        let modify_core_tasks = config.config.modify_core_tasks.clone();

        match modify_core_tasks {
            Some(modify_config) => {
                if modify_config.is_modifications_defined() {
                    config = load_descriptors(
                        &file_name,
                        force,
                        env_map.clone(),
                        true,
                        experimental,
                        Some(modify_config),
                    );
                }
            }
            None => (),
        };
    }

    config
}
<|endoftext|>


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

//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
//! scope.
//!
//! # Examples
//!
//! Creating a box:
//!
//! ```
//! let x = Box::new(5);
//! ```
//!
//! Creating a recursive data structure:
//!
//! ```
//! #[derive(Debug)]
//! enum List<T> {
//!     Cons(T, Box<List<T>>),
//!     Nil,
//! }
//!
//! fn main() {
//!     let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
//!     println!("{:?}", list);
//! }
//! ```
//!
//! This will print `Cons(1, Box(Cons(2, Box(Nil))))`.
//!
//! Recursive structures must be boxed, because if the definition of `Cons` looked like this:
//!
//! ```rust,ignore
//! Cons(T, List<T>),
//! ```
//!
//! It wouldn't work. This is because the size of a `List` depends on how many elements are in the
//! list, and so we don't know how much memory to allocate for a `Cons`. By introducing a `Box`,
//! which has a defined size, we know how big `Cons` needs to be.

#![stable(feature = "rust1", since = "1.0.0")]

use core::prelude::*;

use core::any::Any;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::{Unique};
use core::raw::{TraitObject};

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```
/// # #![feature(alloc)]
/// #![feature(box_syntax)]
/// use std::boxed::HEAP;
///
/// fn main() {
///     let foo = box(HEAP) 5;
///     let foo = box 5;
/// }
/// ```
#[lang = "exchange_heap"]
#[unstable(feature = "alloc",
           reason = "may be renamed; uncertain about custom allocator design")]
pub static HEAP: () = ();

/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
#[lang = "owned_box"]
#[stable(feature = "rust1", since = "1.0.0")]
#[fundamental]
pub struct Box<T>(Unique<T>);

impl<T> Box<T> {
    /// Allocates memory on the heap and then moves `x` into it.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline(always)]
    pub fn new(x: T) -> Box<T> {
        box x
    }
}

impl<T : ?Sized> Box<T> {
    /// Constructs a box from the raw pointer.
    ///
    /// After this function call, pointer is owned by resulting box.
    /// In particular, it means that `Box` destructor calls destructor
    /// of `T` and releases memory. Since the way `Box` allocates and
    /// releases memory is unspecified, the only valid pointer to pass
    /// to this function is the one taken from another `Box` with
    /// `boxed::into_raw` function.
    ///
    /// Function is unsafe, because improper use of this function may
    /// lead to memory problems like double-free, for example if the
    /// function is called twice on the same raw pointer.
    #[unstable(feature = "alloc",
               reason = "may be renamed or moved out of Box scope")]
    #[inline]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        mem::transmute(raw)
    }
}

/// Consumes the `Box`, returning the wrapped raw pointer.
///
/// After call to this function, caller is responsible for the memory
/// previously managed by `Box`, in particular caller should properly
/// destroy `T` and release memory. The proper way to do it is to
/// convert pointer back to `Box` with `Box::from_raw` function, because
/// `Box` does not specify, how memory is allocated.
///
/// Function is unsafe, because result of this function is no longer
/// automatically managed that may lead to memory or other resource
/// leak.
///
/// # Examples
/// ```
/// # #![feature(alloc)]
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// let raw = unsafe { boxed::into_raw(seventeen) };
/// let boxed_again = unsafe { Box::from_raw(raw) };
/// ```
#[unstable(feature = "alloc",
           reason = "may be renamed")]
#[inline]
pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
    mem::transmute(b)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<T> { box Default::default() }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Box<T> {
    /// Returns a new box with a `clone()` of this box's contents.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let y = x.clone();
    /// ```
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Copies `source`'s contents into `self` without creating a new allocation.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![feature(alloc, core)]
    /// let x = Box::new(5);
    /// let mut y = Box::new(10);
    ///
    /// y.clone_from(&x);
    ///
    /// assert_eq!(*y, 5);
    /// ```
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

impl Box<Any> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let raw = into_raw(self);
                let to: TraitObject =
                    mem::transmute::<*mut Any, TraitObject>(raw);

                // Extract the data pointer
                Ok(Box::from_raw(to.data as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

impl Box<Any + Send> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
        <Box<Any>>::downcast(self).map_err(|s| unsafe {
            // reapply the Send marker
            mem::transmute::<Box<Any>, Box<Any + Send>>(s)
        })
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Pointer for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Uniq directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &**self;
        fmt::Pointer::fmt(&ptr, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
    type Target = T;

    fn deref(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for Box<T> {
    fn deref_mut(&mut self) -> &mut T { &mut **self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for Box<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> { (**self).next() }
    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
    fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}

/// `FnBox` is a version of the `FnOnce` intended for use with boxed
/// closure objects. The idea is that where one would normally store a
/// `Box<FnOnce()>` in a data structure, you should use
/// `Box<FnBox()>`. The two traits behave essentially the same, except
/// that a `FnBox` closure can only be called if it is boxed. (Note
/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
/// closures become directly usable.)
///
/// ### Example
///
/// Here is a snippet of code which creates a hashmap full of boxed
/// once closures and then removes them one by one, calling each
/// closure as it is removed. Note that the type of the closures
/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
/// -> i32>`.
///
/// ```
/// #![feature(core)]
///
/// use std::boxed::FnBox;
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
///     let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
///     map.insert(1, Box::new(|| 22));
///     map.insert(2, Box::new(|| 44));
///     map
/// }
///
/// fn main() {
///     let mut map = make_map();
///     for i in &[1, 2] {
///         let f = map.remove(&i).unwrap();
///         assert_eq!(f(), i * 22);
///     }
/// }
/// ```
#[rustc_paren_sugar]
#[unstable(feature = "core", reason = "Newly introduced")]
pub trait FnBox<A> {
    type Output;

    fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

impl<A,F> FnBox<A> for F
    where F: FnOnce<A>
{
    type Output = F::Output;

    fn call_box(self: Box<F>, args: A) -> F::Output {
        self.call_once(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}
<commit_msg>Rollup merge of #25131 - janne:patch-1, r=alexcrichton<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
//! scope.
//!
//! # Examples
//!
//! Creating a box:
//!
//! ```
//! let x = Box::new(5);
//! ```
//!
//! Creating a recursive data structure:
//!
//! ```
//! #[derive(Debug)]
//! enum List<T> {
//!     Cons(T, Box<List<T>>),
//!     Nil,
//! }
//!
//! fn main() {
//!     let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
//!     println!("{:?}", list);
//! }
//! ```
//!
//! This will print `Cons(1, Cons(2, Nil))`.
//!
//! Recursive structures must be boxed, because if the definition of `Cons` looked like this:
//!
//! ```rust,ignore
//! Cons(T, List<T>),
//! ```
//!
//! It wouldn't work. This is because the size of a `List` depends on how many elements are in the
//! list, and so we don't know how much memory to allocate for a `Cons`. By introducing a `Box`,
//! which has a defined size, we know how big `Cons` needs to be.

#![stable(feature = "rust1", since = "1.0.0")]

use core::prelude::*;

use core::any::Any;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::{Unique};
use core::raw::{TraitObject};

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```
/// # #![feature(alloc)]
/// #![feature(box_syntax)]
/// use std::boxed::HEAP;
///
/// fn main() {
///     let foo = box(HEAP) 5;
///     let foo = box 5;
/// }
/// ```
#[lang = "exchange_heap"]
#[unstable(feature = "alloc",
           reason = "may be renamed; uncertain about custom allocator design")]
pub static HEAP: () = ();

/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
#[lang = "owned_box"]
#[stable(feature = "rust1", since = "1.0.0")]
#[fundamental]
pub struct Box<T>(Unique<T>);

impl<T> Box<T> {
    /// Allocates memory on the heap and then moves `x` into it.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline(always)]
    pub fn new(x: T) -> Box<T> {
        box x
    }
}

impl<T : ?Sized> Box<T> {
    /// Constructs a box from the raw pointer.
    ///
    /// After this function call, pointer is owned by resulting box.
    /// In particular, it means that `Box` destructor calls destructor
    /// of `T` and releases memory. Since the way `Box` allocates and
    /// releases memory is unspecified, the only valid pointer to pass
    /// to this function is the one taken from another `Box` with
    /// `boxed::into_raw` function.
    ///
    /// Function is unsafe, because improper use of this function may
    /// lead to memory problems like double-free, for example if the
    /// function is called twice on the same raw pointer.
    #[unstable(feature = "alloc",
               reason = "may be renamed or moved out of Box scope")]
    #[inline]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        mem::transmute(raw)
    }
}

/// Consumes the `Box`, returning the wrapped raw pointer.
///
/// After call to this function, caller is responsible for the memory
/// previously managed by `Box`, in particular caller should properly
/// destroy `T` and release memory. The proper way to do it is to
/// convert pointer back to `Box` with `Box::from_raw` function, because
/// `Box` does not specify, how memory is allocated.
///
/// Function is unsafe, because result of this function is no longer
/// automatically managed that may lead to memory or other resource
/// leak.
///
/// # Examples
/// ```
/// # #![feature(alloc)]
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// let raw = unsafe { boxed::into_raw(seventeen) };
/// let boxed_again = unsafe { Box::from_raw(raw) };
/// ```
#[unstable(feature = "alloc",
           reason = "may be renamed")]
#[inline]
pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
    mem::transmute(b)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<T> { box Default::default() }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Box<T> {
    /// Returns a new box with a `clone()` of this box's contents.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let y = x.clone();
    /// ```
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Copies `source`'s contents into `self` without creating a new allocation.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![feature(alloc, core)]
    /// let x = Box::new(5);
    /// let mut y = Box::new(10);
    ///
    /// y.clone_from(&x);
    ///
    /// assert_eq!(*y, 5);
    /// ```
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

impl Box<Any> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let raw = into_raw(self);
                let to: TraitObject =
                    mem::transmute::<*mut Any, TraitObject>(raw);

                // Extract the data pointer
                Ok(Box::from_raw(to.data as *mut T))
            }
        } else {
            Err(self)
        }
    }
}

impl Box<Any + Send> {
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    /// Attempt to downcast the box to a concrete type.
    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
        <Box<Any>>::downcast(self).map_err(|s| unsafe {
            // reapply the Send marker
            mem::transmute::<Box<Any>, Box<Any + Send>>(s)
        })
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Pointer for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Uniq directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &**self;
        fmt::Pointer::fmt(&ptr, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
    type Target = T;

    fn deref(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for Box<T> {
    fn deref_mut(&mut self) -> &mut T { &mut **self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for Box<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> { (**self).next() }
    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
    fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}

/// `FnBox` is a version of the `FnOnce` intended for use with boxed
/// closure objects. The idea is that where one would normally store a
/// `Box<FnOnce()>` in a data structure, you should use
/// `Box<FnBox()>`. The two traits behave essentially the same, except
/// that a `FnBox` closure can only be called if it is boxed. (Note
/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
/// closures become directly usable.)
///
/// ### Example
///
/// Here is a snippet of code which creates a hashmap full of boxed
/// once closures and then removes them one by one, calling each
/// closure as it is removed. Note that the type of the closures
/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
/// -> i32>`.
///
/// ```
/// #![feature(core)]
///
/// use std::boxed::FnBox;
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
///     let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
///     map.insert(1, Box::new(|| 22));
///     map.insert(2, Box::new(|| 44));
///     map
/// }
///
/// fn main() {
///     let mut map = make_map();
///     for i in &[1, 2] {
///         let f = map.remove(&i).unwrap();
///         assert_eq!(f(), i * 22);
///     }
/// }
/// ```
#[rustc_paren_sugar]
#[unstable(feature = "core", reason = "Newly introduced")]
pub trait FnBox<A> {
    type Output;

    fn call_box(self: Box<Self>, args: A) -> Self::Output;
}

impl<A,F> FnBox<A> for F
    where F: FnOnce<A>
{
    type Output = F::Output;

    fn call_box(self: Box<F>, args: A) -> F::Output {
        self.call_once(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}

impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        self.call_box(args)
    }
}
<|endoftext|>


<commit_before>#[doc = "
A type representing values that may be computed concurrently and
operations for working with them.

# Example

~~~
let delayed_fib = future::spawn {|| fib(5000) };
make_a_sandwitch();
io::println(#fmt(\"fib(5000) = %?\", delayed_fib.get()))
~~~
"];

import either::either;

export future;
export future::{};
export from_value;
export from_port;
export from_fn;
export get;
export with;
export spawn;

#[doc = "The future type"]
enum future<A> = {
    mut v: either<@A, fn@() -> A>
};

#[doc = "Methods on the `future` type"]
impl future<A:copy send> for future<A> {

    fn get() -> A {
        #[doc = "Get the value of the future"];

        get(self)
    }

    fn with<B>(blk: fn(A) -> B) -> B {
        #[doc = "Work with the value without copying it"];

        with(self, blk)
    }
}

fn from_value<A>(+val: A) -> future<A> {
    #[doc = "
    Create a future from a value

    The value is immediately available and calling `get` later will
    not block.
    "];

    future({
        mut v: either::left(@val)
    })
}

fn from_port<A:send>(-port: comm::port<A>) -> future<A> {
    #[doc = "
    Create a future from a port

    The first time that the value is requested the task will block
    waiting for the result to be received on the port.
    "];

    from_fn {||
        comm::recv(port)
    }
}

fn from_fn<A>(f: fn@() -> A) -> future<A> {
    #[doc = "
    Create a future from a function.

    The first time that the value is requested it will be retreived by
    calling the function.  Note that this function is a local
    function. It is not spawned into another task.
    "];

    future({
        mut v: either::right(f)
    })
}

fn spawn<A:send>(+blk: fn~() -> A) -> future<A> {
    #[doc = "
    Create a future from a unique closure.

    The closure will be run in a new task and its result used as the
    value of the future.
    "];

    let mut po = comm::port();
    let ch = comm::chan(po);
    task::spawn {||
        comm::send(ch, blk())
    };
    from_port(po)
}

fn get<A:copy>(future: future<A>) -> A {
    #[doc = "Get the value of the future"];

    with(future) {|v| v }
}

fn with<A,B>(future: future<A>, blk: fn(A) -> B) -> B {
    #[doc = "Work with the value without copying it"];

    let v = alt copy future.v {
      either::left(v) { v }
      either::right(f) {
        let v = @f();
        future.v = either::left(v);
        v
      }
    };
    blk(*v)
}

#[test]
fn test_from_value() {
    let f = from_value("snail");
    assert get(f) == "snail";
}

#[test]
fn test_from_port() {
    let po = comm::port();
    let ch = comm::chan(po);
    comm::send(ch, "whale");
    let f = from_port(po);
    assert get(f) == "whale";
}

#[test]
fn test_from_fn() {
    let f = fn@() -> str { "brail" };
    let f = from_fn(f);
    assert get(f) == "brail";
}

#[test]
fn test_iface_get() {
    let f = from_value("fail");
    assert f.get() == "fail";
}

#[test]
fn test_with() {
    let f = from_value("nail");
    assert with(f) {|v| v} == "nail";
}

#[test]
fn test_iface_with() {
    let f = from_value("kale");
    assert f.with {|v| v} == "kale";
}

#[test]
fn test_spawn() {
    let f = spawn {|| "bale" };
    assert get(f) == "bale";
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_futurefail() {
    let f = spawn {|| fail };
    let _x: str = get(f);
}<commit_msg>core: make_a_sandwitch -> make_a_sandwich<commit_after>#[doc = "
A type representing values that may be computed concurrently and
operations for working with them.

# Example

~~~
let delayed_fib = future::spawn {|| fib(5000) };
make_a_sandwich();
io::println(#fmt(\"fib(5000) = %?\", delayed_fib.get()))
~~~
"];

import either::either;

export future;
export future::{};
export from_value;
export from_port;
export from_fn;
export get;
export with;
export spawn;

#[doc = "The future type"]
enum future<A> = {
    mut v: either<@A, fn@() -> A>
};

#[doc = "Methods on the `future` type"]
impl future<A:copy send> for future<A> {

    fn get() -> A {
        #[doc = "Get the value of the future"];

        get(self)
    }

    fn with<B>(blk: fn(A) -> B) -> B {
        #[doc = "Work with the value without copying it"];

        with(self, blk)
    }
}

fn from_value<A>(+val: A) -> future<A> {
    #[doc = "
    Create a future from a value

    The value is immediately available and calling `get` later will
    not block.
    "];

    future({
        mut v: either::left(@val)
    })
}

fn from_port<A:send>(-port: comm::port<A>) -> future<A> {
    #[doc = "
    Create a future from a port

    The first time that the value is requested the task will block
    waiting for the result to be received on the port.
    "];

    from_fn {||
        comm::recv(port)
    }
}

fn from_fn<A>(f: fn@() -> A) -> future<A> {
    #[doc = "
    Create a future from a function.

    The first time that the value is requested it will be retreived by
    calling the function.  Note that this function is a local
    function. It is not spawned into another task.
    "];

    future({
        mut v: either::right(f)
    })
}

fn spawn<A:send>(+blk: fn~() -> A) -> future<A> {
    #[doc = "
    Create a future from a unique closure.

    The closure will be run in a new task and its result used as the
    value of the future.
    "];

    let mut po = comm::port();
    let ch = comm::chan(po);
    task::spawn {||
        comm::send(ch, blk())
    };
    from_port(po)
}

fn get<A:copy>(future: future<A>) -> A {
    #[doc = "Get the value of the future"];

    with(future) {|v| v }
}

fn with<A,B>(future: future<A>, blk: fn(A) -> B) -> B {
    #[doc = "Work with the value without copying it"];

    let v = alt copy future.v {
      either::left(v) { v }
      either::right(f) {
        let v = @f();
        future.v = either::left(v);
        v
      }
    };
    blk(*v)
}

#[test]
fn test_from_value() {
    let f = from_value("snail");
    assert get(f) == "snail";
}

#[test]
fn test_from_port() {
    let po = comm::port();
    let ch = comm::chan(po);
    comm::send(ch, "whale");
    let f = from_port(po);
    assert get(f) == "whale";
}

#[test]
fn test_from_fn() {
    let f = fn@() -> str { "brail" };
    let f = from_fn(f);
    assert get(f) == "brail";
}

#[test]
fn test_iface_get() {
    let f = from_value("fail");
    assert f.get() == "fail";
}

#[test]
fn test_with() {
    let f = from_value("nail");
    assert with(f) {|v| v} == "nail";
}

#[test]
fn test_iface_with() {
    let f = from_value("kale");
    assert f.with {|v| v} == "kale";
}

#[test]
fn test_spawn() {
    let f = spawn {|| "bale" };
    assert get(f) == "bale";
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_futurefail() {
    let f = spawn {|| fail };
    let _x: str = get(f);
}
<|endoftext|>


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

#![allow(missing_copy_implementations)]

use prelude::v1::*;

use io::{self, Read, Write, ErrorKind, BufRead};

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// # fn foo() -> io::Result<()> {
/// let mut reader: &[u8] = b"hello";
/// let mut writer: Vec<u8> = vec![];
///
/// try!(io::copy(&mut reader, &mut writer));
///
/// assert_eq!(reader, &writer[..]);
/// # Ok(())
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: Read, W: Write>(reader: &mut R, writer: &mut W) -> io::Result<u64> {
    let mut buf = [0; super::DEFAULT_BUF_SIZE];
    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        try!(writer.write_all(&buf[..len]));
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty()`][empty]. Please see
/// the documentation of `empty()` for more details.
///
/// [empty]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return `Ok(0)`.
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io;
/// use std::io::Read;
///
/// # fn foo() -> io::Result<String> {
/// let mut buffer = String::new();
/// try!(io::empty().read_to_string(&mut buffer));
/// # Ok(buffer)
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    fn consume(&mut self, _n: usize) {}
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat()`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink()`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;

    use io::prelude::*;
    use io::{sink, empty, repeat};

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }

    #[test]
    fn tee() {
        let mut buf = [0; 10];
        {
            let mut ptr: &mut [u8] = &mut buf;
            assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]).unwrap(), 5);
        }
        assert_eq!(buf, [4, 4, 4, 4, 4, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn broadcast() {
        let mut buf1 = [0; 10];
        let mut buf2 = [0; 10];
        {
            let mut ptr1: &mut [u8] = &mut buf1;
            let mut ptr2: &mut [u8] = &mut buf2;

            assert_eq!((&mut ptr1).broadcast(&mut ptr2)
                                  .write(&[1, 2, 3]).unwrap(), 3);
        }
        assert_eq!(buf1, buf2);
        assert_eq!(buf1, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]);
    }
}
<commit_msg>std: Allow ?Sized parameters in std::io::copy<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(missing_copy_implementations)]

use prelude::v1::*;

use io::{self, Read, Write, ErrorKind, BufRead};

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// # fn foo() -> io::Result<()> {
/// let mut reader: &[u8] = b"hello";
/// let mut writer: Vec<u8> = vec![];
///
/// try!(io::copy(&mut reader, &mut writer));
///
/// assert_eq!(reader, &writer[..]);
/// # Ok(())
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = [0; super::DEFAULT_BUF_SIZE];
    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        try!(writer.write_all(&buf[..len]));
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty()`][empty]. Please see
/// the documentation of `empty()` for more details.
///
/// [empty]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return `Ok(0)`.
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io;
/// use std::io::Read;
///
/// # fn foo() -> io::Result<String> {
/// let mut buffer = String::new();
/// try!(io::empty().read_to_string(&mut buffer));
/// # Ok(buffer)
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    fn consume(&mut self, _n: usize) {}
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat()`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink()`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;

    use io::prelude::*;
    use io::{copy, sink, empty, repeat};

    #[test]
    fn copy_copies() {
        let mut r = repeat(0).take(4);
        let mut w = sink();
        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);

        let mut r = repeat(0).take(1 << 17);
        assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17);
    }

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }

    #[test]
    fn tee() {
        let mut buf = [0; 10];
        {
            let mut ptr: &mut [u8] = &mut buf;
            assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]).unwrap(), 5);
        }
        assert_eq!(buf, [4, 4, 4, 4, 4, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn broadcast() {
        let mut buf1 = [0; 10];
        let mut buf2 = [0; 10];
        {
            let mut ptr1: &mut [u8] = &mut buf1;
            let mut ptr2: &mut [u8] = &mut buf2;

            assert_eq!((&mut ptr1).broadcast(&mut ptr2)
                                  .write(&[1, 2, 3]).unwrap(), 3);
        }
        assert_eq!(buf1, buf2);
        assert_eq!(buf1, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]);
    }
}
<|endoftext|>


<commit_before>//! Render input types and related functions.

use serde_derive::{Deserialize, Serialize};

use crate::render::type_channel::TypeChan;

/// Input type.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan),
  BuiltIn(BuiltIn)
}

/// Associate an input type to a given type.
pub trait InputType {
  const INPUT: Type;
}

/// Render inputs.
pub trait InputTypes {
  /// Get the types of the input.
  fn ty() -> &'static [Type];
}

impl<A> InputTypes for A where A: InputType {
  fn ty() -> &'static [Type] {
    &[A::INPUT]
  }
}

macro_rules! multi_input_type_impl {
  ($($t:tt),*) => {
    impl<$($t),*> InputTypes for ($($t),*) where $($t: InputType),* {
      fn ty() -> &'static [Type] {
        &[$($t::INPUT),*]
      }
    }
  }
}

multi_input_type_impl!(A, B);
multi_input_type_impl!(A, B, C);
multi_input_type_impl!(A, B, C, D);
multi_input_type_impl!(A, B, C, D, E);
multi_input_type_impl!(A, B, C, D, E, F);
multi_input_type_impl!(A, B, C, D, E, F, G);
multi_input_type_impl!(A, B, C, D, E, F, G, H);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// The time built-in.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct Time;

impl InputType for Time {
  const INPUT: Type = Type::BuiltIn(BuiltIn::Time);
}

/// The framebuffer resolution built-in.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct FramebufferResolution;

impl InputType for FramebufferResolution {
  const INPUT: Type = Type::BuiltIn(BuiltIn::FramebufferResolution);
}

/// One-dimensional integral output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RI;

impl InputType for RI {
  const INPUT: Type = Type::Int(TypeChan::One);
}

/// Two dimensional integral output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGI;

impl InputType for RGI {
  const INPUT: Type = Type::Int(TypeChan::Two);
}

/// Three dimensional integral output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBI;

impl InputType for RGBI {
  const INPUT: Type = Type::Int(TypeChan::Three);
}

/// Four dimensional integral output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAI;

impl InputType for RGBAI {
  const INPUT: Type = Type::Int(TypeChan::Four);
}

/// One-dimensional unigned integral output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RU;

impl InputType for RU {
  const INPUT: Type = Type::UInt(TypeChan::One);
}

/// Two dimensional unsigned integral output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGU;

impl InputType for RGU {
  const INPUT: Type = Type::UInt(TypeChan::Two);
}

/// Three dimensional unsigned integral output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBU;

impl InputType for RGBU {
  const INPUT: Type = Type::UInt(TypeChan::Three);
}

/// Four dimensional unsigned integral output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAU;

impl InputType for RGBAU {
  const INPUT: Type = Type::UInt(TypeChan::Four);
}

/// One-dimensional floating output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RF;

impl InputType for RF {
  const INPUT: Type = Type::Float(TypeChan::One);
}

/// Two dimensional floating output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGF;

impl InputType for RGF {
  const INPUT: Type = Type::Float(TypeChan::Two);
}

/// Three dimensional floating output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBF;

impl InputType for RGBF {
  const INPUT: Type = Type::Float(TypeChan::Three);
}

/// Four dimensional floating output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAF;

impl InputType for RGBAF {
  const INPUT: Type = Type::Float(TypeChan::Four);
}

/// One-dimensional boolean output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RZ;

impl InputType for RZ {
  const INPUT: Type = Type::Bool(TypeChan::One);
}

/// Two dimensional boolean output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGZ;

impl InputType for RGZ {
  const INPUT: Type = Type::Bool(TypeChan::Two);
}

/// Three dimensional boolean output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBZ;

impl InputType for RGBZ {
  const INPUT: Type = Type::Bool(TypeChan::Three);
}

/// Four dimensional boolean output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAZ;

impl InputType for RGBAZ {
  const INPUT: Type = Type::Bool(TypeChan::Four);
}

/// Built-ins.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum BuiltIn {
  Time,
  FramebufferResolution
}

/// An input.
#[derive(Clone, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct Input {
  /// Name of the input.
  name: String,
  /// Type of the input.
  #[serde(rename = "type")]
  ty: Type
}

impl Input {
  /// Create a new input.
  fn new<T, N>(name: N) -> Self
  where T: InputType,
        N: Into<String> {
    Input {
      name: name.into(),
      ty: T::INPUT
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use serde_json::{from_str, to_string};

  #[test]
  fn serialize_type() {
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RGF::INPUT).unwrap(), r#"{"float":2}"#);
    assert_eq!(to_string(&RGBF::INPUT).unwrap(), r#"{"float":3}"#);
    assert_eq!(to_string(&RGBAF::INPUT).unwrap(), r#"{"float":4}"#);
    assert_eq!(to_string(&RI::INPUT).unwrap(), r#"{"int":1}"#);
    assert_eq!(to_string(&RGI::INPUT).unwrap(), r#"{"int":2}"#);
    assert_eq!(to_string(&RGBI::INPUT).unwrap(), r#"{"int":3}"#);
    assert_eq!(to_string(&RGBAI::INPUT).unwrap(), r#"{"int":4}"#);
    assert_eq!(to_string(&RU::INPUT).unwrap(), r#"{"uint":1}"#);
    assert_eq!(to_string(&RGU::INPUT).unwrap(), r#"{"uint":2}"#);
    assert_eq!(to_string(&RGBU::INPUT).unwrap(), r#"{"uint":3}"#);
    assert_eq!(to_string(&RGBAU::INPUT).unwrap(), r#"{"uint":4}"#);
    assert_eq!(to_string(&RZ::INPUT).unwrap(), r#"{"bool":1}"#);
    assert_eq!(to_string(&RGZ::INPUT).unwrap(), r#"{"bool":2}"#);
    assert_eq!(to_string(&RGBZ::INPUT).unwrap(), r#"{"bool":3}"#);
    assert_eq!(to_string(&RGBAZ::INPUT).unwrap(), r#"{"bool":4}"#);
    assert_eq!(to_string(&Type::BuiltIn(BuiltIn::Time)).unwrap(), r#"{"built_in":"time"}"#);
    assert_eq!(to_string(&Type::BuiltIn(BuiltIn::FramebufferResolution)).unwrap(), r#"{"built_in":"framebuffer_resolution"}"#);
  }

  #[test]
  fn deserialize_type() {
    assert_eq!(from_str::<Type>(r#"{"float":1}"#).unwrap(), RF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":2}"#).unwrap(), RGF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":3}"#).unwrap(), RGBF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":4}"#).unwrap(), RGBAF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":1}"#).unwrap(), RI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":2}"#).unwrap(), RGI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":3}"#).unwrap(), RGBI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":4}"#).unwrap(), RGBAI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":1}"#).unwrap(), RU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":2}"#).unwrap(), RGU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":3}"#).unwrap(), RGBU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":4}"#).unwrap(), RGBAU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":1}"#).unwrap(), RZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":2}"#).unwrap(), RGZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":3}"#).unwrap(), RGBZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":4}"#).unwrap(), RGBAZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"built_in":"time"}"#).unwrap(), Type::BuiltIn(BuiltIn::Time));
    assert_eq!(from_str::<Type>(r#"{"built_in":"framebuffer_resolution"}"#).unwrap(), Type::BuiltIn(BuiltIn::FramebufferResolution));
  }

  #[test]
  fn serialize_builtin() {
    assert_eq!(&to_string(&BuiltIn::Time).unwrap(), r#""time""#);
    assert_eq!(&to_string(&BuiltIn::FramebufferResolution).unwrap(), r#""framebuffer_resolution""#);
  }

  #[test]
  fn deserialize_builtin() {
    assert_eq!(from_str::<BuiltIn>(r#""time""#).unwrap(), BuiltIn::Time);
    assert_eq!(from_str::<BuiltIn>(r#""framebuffer_resolution""#).unwrap(), BuiltIn::FramebufferResolution);
  }

  #[test]
  fn input_construction() {
    let time = Input::new::<Time, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&time.name, "t");
    assert_eq!(time.ty, Time::INPUT);
    assert_eq!(&jitter.name, "jitter");
    assert_eq!(jitter.ty, RGBF::INPUT);
  }

  #[test]
  fn serialize_input() {
    let time = Input::new::<Time, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&to_string(&time).unwrap(), r#"{"name":"t","type":{"built_in":"time"}}"#);
    assert_eq!(&to_string(&jitter).unwrap(), r#"{"name":"jitter","type":{"float":3}}"#);
  }
}
<commit_msg>Enhance tests.<commit_after>//! Render input types and related functions.

use serde_derive::{Deserialize, Serialize};

use crate::render::type_channel::TypeChan;

/// Input type.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan),
  #[serde(rename = "built-in")]
  BuiltIn(BuiltIn)
}

/// Associate an input type to a given type.
pub trait InputType {
  const INPUT: Type;
}

/// Render inputs.
pub trait InputTypes {
  /// Get the types of the input.
  fn ty() -> &'static [Type];
}

impl<A> InputTypes for A where A: InputType {
  fn ty() -> &'static [Type] {
    &[A::INPUT]
  }
}

macro_rules! multi_input_type_impl {
  ($($t:tt),*) => {
    impl<$($t),*> InputTypes for ($($t),*) where $($t: InputType),* {
      fn ty() -> &'static [Type] {
        &[$($t::INPUT),*]
      }
    }
  }
}

multi_input_type_impl!(A, B);
multi_input_type_impl!(A, B, C);
multi_input_type_impl!(A, B, C, D);
multi_input_type_impl!(A, B, C, D, E);
multi_input_type_impl!(A, B, C, D, E, F);
multi_input_type_impl!(A, B, C, D, E, F, G);
multi_input_type_impl!(A, B, C, D, E, F, G, H);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// The time built-in.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct Time;

impl InputType for Time {
  const INPUT: Type = Type::BuiltIn(BuiltIn::Time);
}

/// The framebuffer resolution built-in.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct FramebufferResolution;

impl InputType for FramebufferResolution {
  const INPUT: Type = Type::BuiltIn(BuiltIn::FramebufferResolution);
}

/// One-dimensional integral output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RI;

impl InputType for RI {
  const INPUT: Type = Type::Int(TypeChan::One);
}

/// Two dimensional integral output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGI;

impl InputType for RGI {
  const INPUT: Type = Type::Int(TypeChan::Two);
}

/// Three dimensional integral output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBI;

impl InputType for RGBI {
  const INPUT: Type = Type::Int(TypeChan::Three);
}

/// Four dimensional integral output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAI;

impl InputType for RGBAI {
  const INPUT: Type = Type::Int(TypeChan::Four);
}

/// One-dimensional unigned integral output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RU;

impl InputType for RU {
  const INPUT: Type = Type::UInt(TypeChan::One);
}

/// Two dimensional unsigned integral output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGU;

impl InputType for RGU {
  const INPUT: Type = Type::UInt(TypeChan::Two);
}

/// Three dimensional unsigned integral output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBU;

impl InputType for RGBU {
  const INPUT: Type = Type::UInt(TypeChan::Three);
}

/// Four dimensional unsigned integral output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAU;

impl InputType for RGBAU {
  const INPUT: Type = Type::UInt(TypeChan::Four);
}

/// One-dimensional floating output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RF;

impl InputType for RF {
  const INPUT: Type = Type::Float(TypeChan::One);
}

/// Two dimensional floating output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGF;

impl InputType for RGF {
  const INPUT: Type = Type::Float(TypeChan::Two);
}

/// Three dimensional floating output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBF;

impl InputType for RGBF {
  const INPUT: Type = Type::Float(TypeChan::Three);
}

/// Four dimensional floating output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAF;

impl InputType for RGBAF {
  const INPUT: Type = Type::Float(TypeChan::Four);
}

/// One-dimensional boolean output a.k.a. red channel.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RZ;

impl InputType for RZ {
  const INPUT: Type = Type::Bool(TypeChan::One);
}

/// Two dimensional boolean output a.k.a. red-green channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGZ;

impl InputType for RGZ {
  const INPUT: Type = Type::Bool(TypeChan::Two);
}

/// Three dimensional boolean output a.k.a. red-green-blue channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBZ;

impl InputType for RGBZ {
  const INPUT: Type = Type::Bool(TypeChan::Three);
}

/// Four dimensional boolean output a.k.a. red-green-blue-alpha channels.
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct RGBAZ;

impl InputType for RGBAZ {
  const INPUT: Type = Type::Bool(TypeChan::Four);
}

/// Built-ins.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum BuiltIn {
  Time,
  FramebufferResolution
}

/// An input.
#[derive(Clone, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct Input {
  /// Name of the input.
  name: String,
  /// Type of the input.
  #[serde(rename = "type")]
  ty: Type
}

impl Input {
  /// Create a new input.
  fn new<T, N>(name: N) -> Self
  where T: InputType,
        N: Into<String> {
    Input {
      name: name.into(),
      ty: T::INPUT
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use serde_json::{from_str, to_string};

  #[test]
  fn serialize_type() {
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RGF::INPUT).unwrap(), r#"{"float":2}"#);
    assert_eq!(to_string(&RGBF::INPUT).unwrap(), r#"{"float":3}"#);
    assert_eq!(to_string(&RGBAF::INPUT).unwrap(), r#"{"float":4}"#);
    assert_eq!(to_string(&RI::INPUT).unwrap(), r#"{"int":1}"#);
    assert_eq!(to_string(&RGI::INPUT).unwrap(), r#"{"int":2}"#);
    assert_eq!(to_string(&RGBI::INPUT).unwrap(), r#"{"int":3}"#);
    assert_eq!(to_string(&RGBAI::INPUT).unwrap(), r#"{"int":4}"#);
    assert_eq!(to_string(&RU::INPUT).unwrap(), r#"{"uint":1}"#);
    assert_eq!(to_string(&RGU::INPUT).unwrap(), r#"{"uint":2}"#);
    assert_eq!(to_string(&RGBU::INPUT).unwrap(), r#"{"uint":3}"#);
    assert_eq!(to_string(&RGBAU::INPUT).unwrap(), r#"{"uint":4}"#);
    assert_eq!(to_string(&RZ::INPUT).unwrap(), r#"{"bool":1}"#);
    assert_eq!(to_string(&RGZ::INPUT).unwrap(), r#"{"bool":2}"#);
    assert_eq!(to_string(&RGBZ::INPUT).unwrap(), r#"{"bool":3}"#);
    assert_eq!(to_string(&RGBAZ::INPUT).unwrap(), r#"{"bool":4}"#);
    assert_eq!(to_string(&Type::BuiltIn(BuiltIn::Time)).unwrap(), r#"{"built-in":"time"}"#);
    assert_eq!(to_string(&Type::BuiltIn(BuiltIn::FramebufferResolution)).unwrap(), r#"{"built-in":"framebuffer_resolution"}"#);
  }

  #[test]
  fn deserialize_type() {
    assert_eq!(from_str::<Type>(r#"{"float":1}"#).unwrap(), RF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":2}"#).unwrap(), RGF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":3}"#).unwrap(), RGBF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":4}"#).unwrap(), RGBAF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":1}"#).unwrap(), RI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":2}"#).unwrap(), RGI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":3}"#).unwrap(), RGBI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":4}"#).unwrap(), RGBAI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":1}"#).unwrap(), RU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":2}"#).unwrap(), RGU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":3}"#).unwrap(), RGBU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":4}"#).unwrap(), RGBAU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":1}"#).unwrap(), RZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":2}"#).unwrap(), RGZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":3}"#).unwrap(), RGBZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":4}"#).unwrap(), RGBAZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"built-in":"time"}"#).unwrap(), Type::BuiltIn(BuiltIn::Time));
    assert_eq!(from_str::<Type>(r#"{"built-in":"framebuffer_resolution"}"#).unwrap(), Type::BuiltIn(BuiltIn::FramebufferResolution));
  }

  #[test]
  fn serialize_builtin() {
    assert_eq!(&to_string(&BuiltIn::Time).unwrap(), r#""time""#);
    assert_eq!(&to_string(&BuiltIn::FramebufferResolution).unwrap(), r#""framebuffer_resolution""#);
  }

  #[test]
  fn deserialize_builtin() {
    assert_eq!(from_str::<BuiltIn>(r#""time""#).unwrap(), BuiltIn::Time);
    assert_eq!(from_str::<BuiltIn>(r#""framebuffer_resolution""#).unwrap(), BuiltIn::FramebufferResolution);
  }

  #[test]
  fn input_construction() {
    let time = Input::new::<Time, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&time.name, "t");
    assert_eq!(time.ty, Time::INPUT);
    assert_eq!(&jitter.name, "jitter");
    assert_eq!(jitter.ty, RGBF::INPUT);
  }

  #[test]
  fn serialize_input() {
    let time = Input::new::<Time, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&to_string(&time).unwrap(), r#"{"name":"t","type":{"built-in":"time"}}"#);
    assert_eq!(&to_string(&jitter).unwrap(), r#"{"name":"jitter","type":{"float":3}}"#);
  }

  #[test]
  fn deserialize_input() {
    let time = Input::new::<Time, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(from_str::<Input>(r#"{"name":"t","type":{"built-in":"time"}}"#).unwrap(), time);
    assert_eq!(from_str::<Input>(r#"{"name":"jitter","type":{"float":3}}"#).unwrap(), jitter);
  }
}
<|endoftext|>


<commit_before>use crate::{fmt_list, UnicodeData};
use std::fmt;

pub(crate) fn generate_case_mapping(data: &UnicodeData) -> String {
    let mut file = String::new();

    file.push_str(HEADER.trim_start());

    let decl_type = "&[(char, [char; 3])]";

    file.push_str(&format!(
        "static LOWERCASE_TABLE: {} = &[{}];",
        decl_type,
        fmt_list(data.to_lower.iter().map(to_mapping))
    ));
    file.push_str("\n\n");
    file.push_str(&format!(
        "static UPPERCASE_TABLE: {} = &[{}];",
        decl_type,
        fmt_list(data.to_upper.iter().map(to_mapping))
    ));
    file
}

fn to_mapping((key, (a, b, c)): (&u32, &(u32, u32, u32))) -> (CharEscape, [CharEscape; 3]) {
    (
        CharEscape(std::char::from_u32(*key).unwrap()),
        [
            CharEscape(std::char::from_u32(*a).unwrap()),
            CharEscape(std::char::from_u32(*b).unwrap()),
            CharEscape(std::char::from_u32(*c).unwrap()),
        ],
    )
}

struct CharEscape(char);

impl fmt::Debug for CharEscape {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "'{}'", self.0.escape_default())
    }
}

static HEADER: &str = "
pub fn to_lower(c: char) -> [char; 3] {
    match bsearch_case_table(c, LOWERCASE_TABLE) {
        None => [c, '\\0', '\\0'],
        Some(index) => LOWERCASE_TABLE[index].1,
    }
}

pub fn to_upper(c: char) -> [char; 3] {
    match bsearch_case_table(c, UPPERCASE_TABLE) {
        None => [c, '\\0', '\\0'],
        Some(index) => UPPERCASE_TABLE[index].1,
    }
}

fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
    table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
}
";
<commit_msg>Redo #81358 in unicode-table-generator<commit_after>use crate::{fmt_list, UnicodeData};
use std::fmt;

pub(crate) fn generate_case_mapping(data: &UnicodeData) -> String {
    let mut file = String::new();

    file.push_str(HEADER.trim_start());

    let decl_type = "&[(char, [char; 3])]";

    file.push_str(&format!(
        "static LOWERCASE_TABLE: {} = &[{}];",
        decl_type,
        fmt_list(data.to_lower.iter().map(to_mapping))
    ));
    file.push_str("\n\n");
    file.push_str(&format!(
        "static UPPERCASE_TABLE: {} = &[{}];",
        decl_type,
        fmt_list(data.to_upper.iter().map(to_mapping))
    ));
    file
}

fn to_mapping((key, (a, b, c)): (&u32, &(u32, u32, u32))) -> (CharEscape, [CharEscape; 3]) {
    (
        CharEscape(std::char::from_u32(*key).unwrap()),
        [
            CharEscape(std::char::from_u32(*a).unwrap()),
            CharEscape(std::char::from_u32(*b).unwrap()),
            CharEscape(std::char::from_u32(*c).unwrap()),
        ],
    )
}

struct CharEscape(char);

impl fmt::Debug for CharEscape {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "'{}'", self.0.escape_default())
    }
}

static HEADER: &str = r"
pub fn to_lower(c: char) -> [char; 3] {
    if c.is_ascii() {
        [(c as u8).to_ascii_lowercase() as char, '\0', '\0']
    } else {
        match bsearch_case_table(c, LOWERCASE_TABLE) {
            None => [c, '\0', '\0'],
            Some(index) => LOWERCASE_TABLE[index].1,
        }
    }
}

pub fn to_upper(c: char) -> [char; 3] {
    if c.is_ascii() {
        [(c as u8).to_ascii_uppercase() as char, '\0', '\0']
    } else {
        match bsearch_case_table(c, UPPERCASE_TABLE) {
            None => [c, '\0', '\0'],
            Some(index) => UPPERCASE_TABLE[index].1,
        }
    }
}

fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
    table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
}
";
<|endoftext|>