<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use config_builder::{FullNodeConfig, ValidatorConfig};
use libra_config::config::NodeConfig;
use libra_network_address::NetworkAddress;
use std::{convert::TryInto, fs, fs::File, io::Write, net::SocketAddr, path::PathBuf};
use structopt::StructOpt;

const NODE_CONFIG: &str = "node.config.toml";

#[allow(clippy::large_enum_variant)]
#[derive(Debug, StructOpt)]
#[structopt(about = "Tool to create and extend Libra Configs")]
enum Args {
    #[structopt(about = "Generate a Libra faucet key")]
    Faucet(FaucetArgs),
    #[structopt(about = "Create or extend a FullNode network")]
    FullNode(FullNodeCommand),
    #[structopt(about = "Create a new SafetyRules config")]
    SafetyRules(SafetyRulesArgs),
    #[structopt(about = "Create a new validator config")]
    Validator(ValidatorArgs),
}

#[derive(Debug, StructOpt)]
struct FaucetArgs {
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory
    output_dir: PathBuf,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators
    seed: Option<String>,
    #[structopt(short = "n", long)]
    /// Specify the number of nodes coded in genesis blob to produce waypoint.
    nodes_in_genesis: usize,
}

#[derive(Debug, StructOpt)]
enum FullNodeCommand {
    #[structopt(about = "Create a new config")]
    Create(FullNodeArgs),
    #[structopt(about = "Create a new config")]
    Extend(FullNodeArgs),
}

#[derive(Debug, StructOpt)]
struct FullNodeArgs {
    // Describe the validator networrk
    #[structopt(short = "n", long, default_value = "1")]
    /// Specify the number of nodes to configure
    nodes: usize,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators
    seed: Option<String>,

    // Parameters for this full node config
    #[structopt(short = "a", long, parse(from_str = parse_addr))]
    /// Advertised address for this node, if this is null, listen is reused
    advertised: NetworkAddress,
    #[structopt(short = "b", long, parse(from_str = parse_addr))]
    /// Advertised address for the first node in this test net
    bootstrap: NetworkAddress,
    #[structopt(short = "d", long, parse(from_os_str))]
    /// The data directory for the configs (e.g. /opt/libra/data)
    data_dir: PathBuf,
    #[structopt(short = "c", long)]
    /// Use the provided seed for generating keys for each of the FullNodes
    full_node_seed: Option<String>,
    #[structopt(short = "f", long, default_value = "1")]
    /// Total number of full nodes
    full_nodes: usize,
    #[structopt(short = "i", long, default_value = "0")]
    /// Specify the index into the number of nodes to write to output dir
    index: usize,
    #[structopt(short = "l", long, parse(from_str = parse_addr))]
    /// Listening address for this node
    listen: NetworkAddress,
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory, note if a config exists already here, it will be updated to include
    /// this full node network
    output_dir: PathBuf,
    #[structopt(short = "p", long)]
    /// Public network, doesn't use any authentication or encryption
    public: bool,
    #[structopt(short = "t", long, parse(from_os_str))]
    /// Path to a template NodeConfig
    template: Option<PathBuf>,
}

#[derive(Debug, StructOpt)]
struct SafetyRulesArgs {
    #[structopt(flatten)]
    validator_common: ValidatorCommonArgs,
}

#[derive(Debug, StructOpt)]
struct ValidatorArgs {
    #[structopt(short = "a", long, parse(from_str = parse_addr))]
    /// Advertised address for this node, if this is null, listen is reused
    advertised: NetworkAddress,
    #[structopt(short = "b", long, parse(from_str = parse_addr))]
    /// Advertised address for the first node in this test net
    bootstrap: NetworkAddress,
    #[structopt(short = "l", long, parse(from_str = parse_addr))]
    /// Listening address for this node
    listen: NetworkAddress,
    #[structopt(flatten)]
    validator_common: ValidatorCommonArgs,
}

#[derive(Debug, StructOpt)]
struct ValidatorCommonArgs {
    #[structopt(short = "d", long, parse(from_os_str))]
    /// The data directory for the configs (e.g. /opt/libra/etc)
    data_dir: PathBuf,
    #[structopt(short = "i", long, default_value = "0")]
    /// Specify the index into the number of nodes to write to output dir
    index: usize,
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory
    output_dir: PathBuf,
    #[structopt(short = "n", long, default_value = "1")]
    /// Specify the number of nodes to configure
    nodes: usize,
    #[structopt(short = "g", long)]
    /// Specify the number of nodes coded in genesis blob, will use all nodes if unspecified
    nodes_in_genesis: Option<usize>,
    #[structopt(long, parse(from_str = parse_socket_addr))]
    /// Specify the IP:Port for Safety rules. If this is not defined, SafetyRules will run in its
    /// default configuration.
    safety_rules_addr: Option<SocketAddr>,
    /// Specifies the type of backend to use for safety rules: in-memory, on-disk, or vault
    #[structopt(long)]
    safety_rules_backend: Option<String>,
    /// Specifies the host URL for secure storages hosted on remote URLs
    #[structopt(long)]
    safety_rules_host: Option<String>,
    /// Specifies the token for secure storages that use credentials
    #[structopt(long)]
    safety_rules_token: Option<String>,
    /// Specifies a unique namespace for the secure storage
    #[structopt(long)]
    safety_rules_namespace: Option<String>,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators
    seed: Option<String>,
    #[structopt(short = "t", long, parse(from_os_str))]
    /// Path to a template NodeConfig
    template: Option<PathBuf>,
}

fn parse_addr(src: &str) -> NetworkAddress {
    src.parse::<NetworkAddress>().unwrap()
}

fn parse_socket_addr(src: &str) -> SocketAddr {
    src.parse::<SocketAddr>().unwrap()
}

fn main() {
    let args = Args::from_args();

    match args {
        Args::Faucet(faucet_args) => build_faucet(faucet_args),
        Args::FullNode(full_node_args) => build_full_node(full_node_args),
        Args::SafetyRules(safety_rules_args) => build_safety_rules(safety_rules_args),
        Args::Validator(validator_args) => build_validator(validator_args),
    };
}

fn build_faucet(args: FaucetArgs) {
    let mut config_builder = ValidatorConfig::new();
    config_builder.nodes(args.nodes_in_genesis);

    if let Some(seed) = args.seed.as_ref() {
        let seed = hex::decode(seed).expect("Invalid hex in seed.");
        config_builder.seed(seed[..32].try_into().expect("Invalid seed"));
    }

    let (faucet_key, waypoint) = config_builder
        .build_faucet_client()
        .expect("Unable to build faucet");
    let key_path = args.output_dir.join("mint.key");
    fs::create_dir_all(&args.output_dir).expect("Unable to create output directory");
    generate_key::save_key(faucet_key, key_path);

    let waypoint_path = args.output_dir.join("waypoint.txt");
    let mut file =
        File::create(waypoint_path).expect("Unable to create/truncate file at specified path");
    file.write_all(waypoint.to_string().as_bytes())
        .expect("Unable to write waypoint to file at specified path");
}

fn build_full_node(command: FullNodeCommand) {
    let config_builder = match &command {
        FullNodeCommand::Create(args) => build_full_node_config_builder(&args),
        FullNodeCommand::Extend(args) => build_full_node_config_builder(&args),
    };

    match command {
        FullNodeCommand::Create(args) => {
            if node_config_exists(&args.output_dir) {
                eprintln!("Node config already exists in this directory");
                return;
            }
            let mut new_config = config_builder.build().expect("ConfigBuilder failed");
            new_config.set_data_dir(args.data_dir);
            save_config(new_config, &args.output_dir);
        }
        FullNodeCommand::Extend(args) => {
            if !node_config_exists(&args.output_dir) {
                eprintln!("No node config in this directory");
                return;
            }

            let config_file = args.output_dir.join(NODE_CONFIG);
            let mut orig_config =
                NodeConfig::load(&config_file).expect("Unable to load node config");
            if orig_config.base.role.is_validator() {
                config_builder
                    .extend_validator(&mut orig_config)
                    .expect("Unable to add full node network to validator");
            } else {
                config_builder
                    .extend(&mut orig_config)
                    .expect("Unable to append full node network");
            }
            save_config(orig_config, &args.output_dir);
        }
    };
}

fn build_full_node_config_builder(args: &FullNodeArgs) -> FullNodeConfig {
    let mut config_builder = FullNodeConfig::new();
    config_builder
        .advertised(args.advertised.clone())
        .bootstrap(args.bootstrap.clone())
        .full_node_index(args.index)
        .full_nodes(args.full_nodes)
        .listen(args.listen.clone())
        .nodes(args.nodes)
        .template(load_template(args.template.as_ref()));

    if let Some(fn_seed) = args.full_node_seed.as_ref() {
        config_builder.full_node_seed(parse_seed(fn_seed));
    }

    if args.public {
        config_builder.public();
    }

    if let Some(seed) = args.seed.as_ref() {
        config_builder.seed(parse_seed(seed));
    }

    config_builder
}

fn build_safety_rules(args: SafetyRulesArgs) {
    if node_config_exists(&args.validator_common.output_dir) {
        eprintln!("SafetyRules config already exists in this directory");
        return;
    }

    let config_builder = safety_rules_common(&args.validator_common);
    let mut node_config = config_builder.build().expect("ConfigBuilder failed");
    node_config.set_data_dir(args.validator_common.data_dir);
    save_config(node_config, &args.validator_common.output_dir);
}

fn build_validator(args: ValidatorArgs) {
    if node_config_exists(&args.validator_common.output_dir) {
        eprintln!("Node config already exists in this directory");
        return;
    }

    let mut config_builder = safety_rules_common(&args.validator_common);
    config_builder
        .advertised(args.advertised)
        .bootstrap(args.bootstrap)
        .index(args.validator_common.index)
        .listen(args.listen)
        .nodes(args.validator_common.nodes)
        .nodes_in_genesis(args.validator_common.nodes_in_genesis);

    if let Some(seed) = args.validator_common.seed.as_ref() {
        config_builder.seed(parse_seed(seed));
    }

    let mut node_config = config_builder.build().expect("ConfigBuilder failed");
    node_config.set_data_dir(args.validator_common.data_dir);
    save_config(node_config, &args.validator_common.output_dir);
}

fn safety_rules_common(args: &ValidatorCommonArgs) -> ValidatorConfig {
    let mut config_builder = ValidatorConfig::new();

    config_builder
        .index(args.index)
        .nodes(args.nodes)
        .safety_rules_addr(args.safety_rules_addr.clone())
        .safety_rules_backend(args.safety_rules_backend.clone())
        .safety_rules_host(args.safety_rules_host.clone())
        .safety_rules_namespace(args.safety_rules_namespace.clone())
        .safety_rules_token(args.safety_rules_token.clone())
        .template(load_template(args.template.as_ref()));

    if let Some(seed) = args.seed.as_ref() {
        config_builder.seed(parse_seed(seed));
    }

    config_builder
}

fn node_config_exists(output_dir: &PathBuf) -> bool {
    output_dir.join(NODE_CONFIG).exists()
}

fn load_template(template: Option<&PathBuf>) -> NodeConfig {
    if let Some(template_path) = template {
        NodeConfig::load(template_path).expect("Unable to load template")
    } else {
        NodeConfig::default()
    }
}

fn parse_seed(seed: &str) -> [u8; 32] {
    let seed = hex::decode(seed).expect("Invalid hex in seed.");
    seed[..32].try_into().expect("Invalid seed")
}

fn save_config(mut node_config: NodeConfig, output_dir: &PathBuf) {
    fs::create_dir_all(output_dir).expect("Unable to create output directory");
    node_config
        .save(output_dir.join(NODE_CONFIG))
        .expect("Unable to save configs");
}
<commit_msg>Clarify cmdln arg comments<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use config_builder::{FullNodeConfig, ValidatorConfig};
use libra_config::config::NodeConfig;
use libra_network_address::NetworkAddress;
use std::{convert::TryInto, fs, fs::File, io::Write, net::SocketAddr, path::PathBuf};
use structopt::StructOpt;

const NODE_CONFIG: &str = "node.config.toml";

#[allow(clippy::large_enum_variant)]
#[derive(Debug, StructOpt)]
#[structopt(about = "Tool to create and extend Libra Configs")]
enum Args {
    #[structopt(about = "Generate a Libra faucet key")]
    Faucet(FaucetArgs),
    #[structopt(about = "Create a new FullNode config XOR extend a Validator config")]
    FullNode(FullNodeCommand),
    #[structopt(about = "Create a new SafetyRules config")]
    SafetyRules(SafetyRulesArgs),
    #[structopt(about = "Create a new Validator config")]
    Validator(ValidatorArgs),
}

#[derive(Debug, StructOpt)]
struct FaucetArgs {
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory
    output_dir: PathBuf,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators.
    seed: Option<String>,
    #[structopt(short = "n", long)]
    /// Specify the number of validators coded in genesis blob to produce waypoint.
    nodes_in_genesis: usize,
}

#[derive(Debug, StructOpt)]
enum FullNodeCommand {
    #[structopt(about = "Create a new FullNode config")]
    Create(FullNodeArgs),
    #[structopt(about = "Extend a Validator config with a FullNode network")]
    Extend(FullNodeArgs),
}

#[derive(Debug, StructOpt)]
struct FullNodeArgs {
    // Describe the validator networrk
    #[structopt(short = "n", long, default_value = "1")]
    /// Specify the number of Validators to configure in the genesis blob.
    nodes: usize,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators.
    seed: Option<String>,

    // Parameters for this full node config
    #[structopt(short = "a", long, parse(from_str = parse_addr))]
    /// Advertised address for this node, if this is null, listen is reused.
    advertised: NetworkAddress,
    #[structopt(short = "b", long, parse(from_str = parse_addr))]
    /// Advertised address for the first node in this FullNode network.
    bootstrap: NetworkAddress,
    #[structopt(short = "d", long, parse(from_os_str))]
    /// The data directory for the configs (e.g. /opt/libra/data).
    data_dir: PathBuf,
    #[structopt(short = "c", long)]
    /// Use the provided seed for generating keys for each of the FullNodes.
    full_node_seed: Option<String>,
    #[structopt(short = "f", long, default_value = "1")]
    /// Total number of FullNodes.
    full_nodes: usize,
    #[structopt(short = "i", long, default_value = "0")]
    /// Specify the index of the FullNode being configured.  Must be in the range 0..f-1.
    index: usize,
    #[structopt(short = "l", long, parse(from_str = parse_addr))]
    /// Listening address for this node.
    listen: NetworkAddress,
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory. Note if a NodeConfig exists already here, 'create' will fail while
    /// 'extend' will update the NodeConfig to include a new FullNode network configuration.
    output_dir: PathBuf,
    #[structopt(short = "p", long)]
    /// Public network, doesn't use any authentication or encryption
    public: bool,
    #[structopt(short = "t", long, parse(from_os_str))]
    /// Path to a template NodeConfig.
    template: Option<PathBuf>,
}

#[derive(Debug, StructOpt)]
struct SafetyRulesArgs {
    #[structopt(flatten)]
    validator_common: ValidatorCommonArgs,
}

#[derive(Debug, StructOpt)]
struct ValidatorArgs {
    #[structopt(short = "a", long, parse(from_str = parse_addr))]
    /// Advertised address for this Validator, if this is null, listen is reused.
    advertised: NetworkAddress,
    #[structopt(short = "b", long, parse(from_str = parse_addr))]
    /// Advertised address for the first Validator in this test net.
    bootstrap: NetworkAddress,
    #[structopt(short = "l", long, parse(from_str = parse_addr))]
    /// Listening address for this Validator.
    listen: NetworkAddress,
    #[structopt(flatten)]
    validator_common: ValidatorCommonArgs,
}

#[derive(Debug, StructOpt)]
struct ValidatorCommonArgs {
    #[structopt(short = "d", long, parse(from_os_str))]
    /// The data directory for the configs (e.g. /opt/libra/etc).
    data_dir: PathBuf,
    #[structopt(short = "i", long, default_value = "0")]
    /// Specify the index of the Validator being configured.  Must be in the range 0..n-1.
    index: usize,
    #[structopt(short = "o", long, parse(from_os_str))]
    /// The output directory.
    output_dir: PathBuf,
    #[structopt(short = "n", long, default_value = "1")]
    /// Specify the potential number of Validators to configure in the genesis blob.
    nodes: usize,
    #[structopt(short = "g", long)]
    /// Specify the number of Validators coded in genesis blob, will use all validators if
    /// unspecified.  Must be in the range 0..n-1.
    nodes_in_genesis: Option<usize>,
    #[structopt(long, parse(from_str = parse_socket_addr))]
    /// Specify the IP:Port for Safety rules. If this is not defined, SafetyRules will run in its
    /// default configuration.
    safety_rules_addr: Option<SocketAddr>,
    /// Specifies the type of backend to use for safety rules: in-memory, on-disk, or vault.
    #[structopt(long)]
    safety_rules_backend: Option<String>,
    /// Specifies the host URL for secure storages hosted on remote URLs
    #[structopt(long)]
    safety_rules_host: Option<String>,
    /// Specifies the token for secure storages that use credentials
    #[structopt(long)]
    safety_rules_token: Option<String>,
    /// Specifies a unique namespace for the secure storage
    #[structopt(long)]
    safety_rules_namespace: Option<String>,
    #[structopt(short = "s", long)]
    /// Use the provided seed for generating keys for each of the validators
    seed: Option<String>,
    #[structopt(short = "t", long, parse(from_os_str))]
    /// Path to a template NodeConfig
    template: Option<PathBuf>,
}

fn parse_addr(src: &str) -> NetworkAddress {
    src.parse::<NetworkAddress>().unwrap()
}

fn parse_socket_addr(src: &str) -> SocketAddr {
    src.parse::<SocketAddr>().unwrap()
}

fn main() {
    let args = Args::from_args();

    match args {
        Args::Faucet(faucet_args) => build_faucet(faucet_args),
        Args::FullNode(full_node_args) => build_full_node(full_node_args),
        Args::SafetyRules(safety_rules_args) => build_safety_rules(safety_rules_args),
        Args::Validator(validator_args) => build_validator(validator_args),
    };
}

fn build_faucet(args: FaucetArgs) {
    let mut config_builder = ValidatorConfig::new();
    config_builder.nodes(args.nodes_in_genesis);

    if let Some(seed) = args.seed.as_ref() {
        let seed = hex::decode(seed).expect("Invalid hex in seed.");
        config_builder.seed(seed[..32].try_into().expect("Invalid seed"));
    }

    let (faucet_key, waypoint) = config_builder
        .build_faucet_client()
        .expect("Unable to build faucet");
    let key_path = args.output_dir.join("mint.key");
    fs::create_dir_all(&args.output_dir).expect("Unable to create output directory");
    generate_key::save_key(faucet_key, key_path);

    let waypoint_path = args.output_dir.join("waypoint.txt");
    let mut file =
        File::create(waypoint_path).expect("Unable to create/truncate file at specified path");
    file.write_all(waypoint.to_string().as_bytes())
        .expect("Unable to write waypoint to file at specified path");
}

fn build_full_node(command: FullNodeCommand) {
    let config_builder = match &command {
        FullNodeCommand::Create(args) => build_full_node_config_builder(&args),
        FullNodeCommand::Extend(args) => build_full_node_config_builder(&args),
    };

    match command {
        FullNodeCommand::Create(args) => {
            if node_config_exists(&args.output_dir) {
                eprintln!("Node config already exists in this directory");
                return;
            }
            let mut new_config = config_builder.build().expect("ConfigBuilder failed");
            new_config.set_data_dir(args.data_dir);
            save_config(new_config, &args.output_dir);
        }
        FullNodeCommand::Extend(args) => {
            if !node_config_exists(&args.output_dir) {
                eprintln!("No node config in this directory");
                return;
            }

            let config_file = args.output_dir.join(NODE_CONFIG);
            let mut orig_config =
                NodeConfig::load(&config_file).expect("Unable to load node config");
            if orig_config.base.role.is_validator() {
                config_builder
                    .extend_validator(&mut orig_config)
                    .expect("Unable to add full node network to validator");
            } else {
                config_builder
                    .extend(&mut orig_config)
                    .expect("Unable to append full node network");
            }
            save_config(orig_config, &args.output_dir);
        }
    };
}

fn build_full_node_config_builder(args: &FullNodeArgs) -> FullNodeConfig {
    let mut config_builder = FullNodeConfig::new();
    config_builder
        .advertised(args.advertised.clone())
        .bootstrap(args.bootstrap.clone())
        .full_node_index(args.index)
        .full_nodes(args.full_nodes)
        .listen(args.listen.clone())
        .nodes(args.nodes)
        .template(load_template(args.template.as_ref()));

    if let Some(fn_seed) = args.full_node_seed.as_ref() {
        config_builder.full_node_seed(parse_seed(fn_seed));
    }

    if args.public {
        config_builder.public();
    }

    if let Some(seed) = args.seed.as_ref() {
        config_builder.seed(parse_seed(seed));
    }

    config_builder
}

fn build_safety_rules(args: SafetyRulesArgs) {
    if node_config_exists(&args.validator_common.output_dir) {
        eprintln!("SafetyRules config already exists in this directory");
        return;
    }

    let config_builder = safety_rules_common(&args.validator_common);
    let mut node_config = config_builder.build().expect("ConfigBuilder failed");
    node_config.set_data_dir(args.validator_common.data_dir);
    save_config(node_config, &args.validator_common.output_dir);
}

fn build_validator(args: ValidatorArgs) {
    if node_config_exists(&args.validator_common.output_dir) {
        eprintln!("Node config already exists in this directory");
        return;
    }

    let mut config_builder = safety_rules_common(&args.validator_common);
    config_builder
        .advertised(args.advertised)
        .bootstrap(args.bootstrap)
        .index(args.validator_common.index)
        .listen(args.listen)
        .nodes(args.validator_common.nodes)
        .nodes_in_genesis(args.validator_common.nodes_in_genesis);

    if let Some(seed) = args.validator_common.seed.as_ref() {
        config_builder.seed(parse_seed(seed));
    }

    let mut node_config = config_builder.build().expect("ConfigBuilder failed");
    node_config.set_data_dir(args.validator_common.data_dir);
    save_config(node_config, &args.validator_common.output_dir);
}

fn safety_rules_common(args: &ValidatorCommonArgs) -> ValidatorConfig {
    let mut config_builder = ValidatorConfig::new();

    config_builder
        .index(args.index)
        .nodes(args.nodes)
        .safety_rules_addr(args.safety_rules_addr.clone())
        .safety_rules_backend(args.safety_rules_backend.clone())
        .safety_rules_host(args.safety_rules_host.clone())
        .safety_rules_namespace(args.safety_rules_namespace.clone())
        .safety_rules_token(args.safety_rules_token.clone())
        .template(load_template(args.template.as_ref()));

    if let Some(seed) = args.seed.as_ref() {
        config_builder.seed(parse_seed(seed));
    }

    config_builder
}

fn node_config_exists(output_dir: &PathBuf) -> bool {
    output_dir.join(NODE_CONFIG).exists()
}

fn load_template(template: Option<&PathBuf>) -> NodeConfig {
    if let Some(template_path) = template {
        NodeConfig::load(template_path).expect("Unable to load template")
    } else {
        NodeConfig::default()
    }
}

fn parse_seed(seed: &str) -> [u8; 32] {
    let seed = hex::decode(seed).expect("Invalid hex in seed.");
    seed[..32].try_into().expect("Invalid seed")
}

fn save_config(mut node_config: NodeConfig, output_dir: &PathBuf) {
    fs::create_dir_all(output_dir).expect("Unable to create output directory");
    node_config
        .save(output_dir.join(NODE_CONFIG))
        .expect("Unable to save configs");
}
<|endoftext|>


<commit_before>extern crate parity_wasm;

use std::env;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    if args.len() != 2 {
        println!("Usage: {} somefile.wasm", args[0]);
        return;
    }

    let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");

    let data_section = module.data_section().expect("no data section in module");

    println!("Data segments: {}", data_section.entries().len());

    let mut index = 0;
    for entry in data_section.entries() {
        println!("  Entry #{}", index);
        println!("    init: {}", entry.offset().code()[0]);
        println!("    size: {}", entry.value().len());
        index += 1;
    }
}<commit_msg>data.rs comments<commit_after>// This short example provides the utility to inspect
// wasm file data section.

extern crate parity_wasm;

use std::env;

fn main() {

    // Example executable takes one argument which must
    // refernce the existing file with a valid wasm module
    let args = env::args().collect::<Vec<_>>();
    if args.len() != 2 {
        println!("Usage: {} somefile.wasm", args[0]);
        return;
    }

    // Here we load module using dedicated for this purpose
    // `deserialize_file` function (which works only with modules)
    let module = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");

    // We query module for data section. Note that not every valid
    // wasm module must contain a data section. So in case the provided
    // module does not contain data section, we panic with an error
    let data_section = module.data_section().expect("no data section in module");

    // Printing the total count of data segments
    println!("Data segments: {}", data_section.entries().len());

    let mut index = 0;
    for entry in data_section.entries() {
        // Printing the details info of each data segment
        // see `elements::DataSegment` for more properties
        // you can query
        println!("  Entry #{}", index);

        // This shows the initialization member of data segment
        // (expression which must resolve in the linear memory location).
        println!("    init: {}", entry.offset().code()[0]);

        // This shows the total length of the data segment in bytes.
        println!("    size: {}", entry.value().len());

        index += 1;
    }
}<|endoftext|>


<commit_before>extern crate capstone;

static CODE: &'static [u8; 8] = b"\x55\x48\x8b\x05\xb8\x13\x00\x00";

fn main() {
     match capstone::Capstone::new(capstone::Arch::X86) {
         Ok(cs) => {
             cs.detail().unwrap();
             cs.att();
             match cs.disassemble(CODE, 0x1000) {
                 Ok(insns) => {
                     println!("Got {} instructions", insns.len());
                     for i in insns.iter() {
                         println!("{}", i);
                         println!("detail: {:?}", i.detail());
                     }
                 },
                 Err(err) => {
                     println!("Error disassembling: {}", err);
                 }
             }
         },
         Err(err) => {
             println!("Error creating disassembler: {}", err);
         }
     }
}
<commit_msg>static -> const<commit_after>extern crate capstone;

const CODE: &'static [u8; 8] = b"\x55\x48\x8b\x05\xb8\x13\x00\x00";

fn main() {
     match capstone::Capstone::new(capstone::Arch::X86) {
         Ok(cs) => {
             cs.detail().unwrap();
             cs.att();
             match cs.disassemble(CODE, 0x1000) {
                 Ok(insns) => {
                     println!("Got {} instructions", insns.len());
                     for i in insns.iter() {
                         println!("{}", i);
                         println!("detail: {:?}", i.detail());
                     }
                 },
                 Err(err) => {
                     println!("Error disassembling: {}", err);
                 }
             }
         },
         Err(err) => {
             println!("Error creating disassembler: {}", err);
         }
     }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate conrod_core;
extern crate nannou;
extern crate nannou_timeline as timeline;
extern crate pitch_calc;
extern crate time_calc;
// Conditionally compile with or with out serde i.e. serialization and thereby saving and loading.
// To use, run with `cargo run --release --example demo --features "serde"
#[cfg(feature = "serde1")]
#[macro_use]
extern crate serde;
#[cfg(feature = "serde1")]
extern crate serde_json;

use nannou::prelude::*;
use nannou::ui::prelude::*;
use pitch_calc as pitch;
use std::iter::once;
use time_calc as time;
use timeline::track::automation::{BangValue as Bang, Envelope, Point, ToggleValue as Toggle};
use timeline::track::piano_roll;
use timeline::{bars, track};

const BPM: time::calc::Bpm = 140.0;
const ONE_SECOND_MS: time::calc::Ms = 1_000.0;
const PPQN: time::Ppqn = 9600;
const WIDTH: u32 = 800;
const HEIGHT: u32 = 600;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    _window: window::Id,
    ui: Ui,
    ids: Ids,
    timeline_data: TimelineData,
    playing: bool,
}

// Implement the Serialize and Deserialize traits only if the serde feature is enabled.
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
struct TimelineData {
    playhead_ticks: time::Ticks,
    bars: Vec<time::TimeSig>,
    notes: Vec<piano_roll::Note>,
    tempo_envelope: track::automation::numeric::Envelope<f32>,
    octave_envelope: track::automation::numeric::Envelope<i32>,
    toggle_envelope: track::automation::toggle::Envelope,
    bang_envelope: track::automation::bang::Envelope,
}

// Create all of our unique `WidgetId`s with the `widget_ids!` macro.
conrod_core::widget_ids! {
    struct Ids {
        window,
        ruler,
        timeline,
    }
}

fn model(app: &App) -> Model {
    let _window = app
        .new_window()
        .key_pressed(key_pressed)
        .size(WIDTH, HEIGHT)
        .title("Timeline Demo")
        .view(view)
        .build()
        .unwrap();

    // Create the UI.
    let mut ui = app.new_ui().build().unwrap();
    let ids = Ids::new(ui.widget_id_generator());

    // Start the playhead at the beginning.
    let playhead_ticks = time::Ticks::from(0);

    // A sequence of bars with varying time signatures.
    let bars = vec![
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 6, bottom: 8 },
        time::TimeSig { top: 6, bottom: 8 },
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 7, bottom: 8 },
        time::TimeSig { top: 7, bottom: 8 },
    ];

    let notes = bars::WithStarts::new(bars.iter().cloned(), PPQN)
        .enumerate()
        .map(|(i, (time_sig, start))| {
            let end = start + time_sig.ticks_per_bar(PPQN);
            let period = timeline::Period { start, end };
            let pitch = pitch::Step((24 + (i * 5) % 12) as f32).to_letter_octave();
            piano_roll::Note { period, pitch }
        })
        .collect();

    let tempo_envelope = {
        let start = Point {
            ticks: time::Ticks(0),
            value: 20.0,
        };
        let points = bars::Periods::new(bars.iter().cloned(), PPQN)
            .enumerate()
            .map(|(i, period)| Point {
                ticks: period.end,
                value: 20.0 + (i + 1) as f32 * 60.0 % 220.0,
            });
        Envelope::from_points(once(start).chain(points), 20.0, 240.0)
    };

    let octave_envelope = {
        let start = Point {
            ticks: time::Ticks(0),
            value: 0,
        };
        let points = bars::WithStarts::new(bars.iter().cloned(), PPQN)
            .enumerate()
            .flat_map(|(i, (ts, mut start))| {
                let bar_end = start + ts.ticks_per_bar(PPQN);
                let mut j = 0;
                std::iter::from_fn(move || {
                    if start >= bar_end {
                        return None;
                    }

                    let end = start + time::Ticks(PPQN as _);
                    let end = if end > bar_end { bar_end } else { end };
                    let point = Point {
                        ticks: end,
                        value: 1 + ((i as i32 + j as i32) * 3) % 12,
                    };
                    start = end;
                    j += 1;
                    Some(point)
                })
            });
        Envelope::from_points(once(start).chain(points), 0, 12)
    };

    let toggle_envelope = {
        let start = Point {
            ticks: time::Ticks(0),
            value: Toggle(random()),
        };
        let points = bars::Periods::new(bars.iter().cloned(), PPQN).map(|period| Point {
            ticks: period.end,
            value: Toggle(random()),
        });
        Envelope::from_points(once(start).chain(points), Toggle(false), Toggle(true))
    };

    let bang_envelope = {
        let points = bars::Periods::new(bars.iter().cloned(), PPQN).map(|period| Point {
            ticks: period.start,
            value: Bang,
        });
        Envelope::from_points(points, Bang, Bang)
    };

    let timeline_data = TimelineData {
        playhead_ticks,
        bars,
        notes,
        tempo_envelope,
        octave_envelope,
        toggle_envelope,
        bang_envelope,
    };

    Model {
        _window,
        ui,
        ids,
        timeline_data,
        playing: false,
    }
}

fn update(_app: &App, model: &mut Model, update: Update) {
    let Model {
        ids,
        ui,
        timeline_data,
        playing,
        ..
    } = model;

    // Update the user interface.
    set_widgets(&mut ui.set_widgets(), ids, timeline_data);

    // Get the current bpm from the tempo_envelope automation track.
    use timeline::track::automation::EnvelopeTrait; // needed to use the .y(Ticks) method on the envelope
    let tempo_value = timeline_data.tempo_envelope.y(timeline_data.playhead_ticks);
    let current_bpm = tempo_value.unwrap_or(BPM as f32) as f64;

    // Update the playhead.
    let delta_secs = if *playing {
        update.since_last.secs()
    } else {
        0.0
    };
    let delta_ticks = time::Ms(delta_secs * ONE_SECOND_MS).to_ticks(current_bpm, PPQN);
    let total_duration_ticks =
        timeline::bars_duration_ticks(timeline_data.bars.iter().cloned(), PPQN);
    let previous_playhead_ticks = timeline_data.playhead_ticks.clone();
    timeline_data.playhead_ticks =
        (timeline_data.playhead_ticks + delta_ticks) % total_duration_ticks;

    // Check if a bang in the bang_envelope has banged.
    for bang_point in timeline_data.bang_envelope.points() {
        if bang_point.ticks > previous_playhead_ticks
            && bang_point.ticks <= timeline_data.playhead_ticks
        {
            println!("BANG!");
        }
    }

    // Check if a note is playing
    for note in &timeline_data.notes {
        if timeline_data.playhead_ticks >= note.period.start
            && timeline_data.playhead_ticks < note.period.end
        {
            println!("Note playing: {:?}", note.pitch);
        }
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    model.ui.draw_to_frame(app, &frame).unwrap();
}

// Update / draw the Ui.
fn set_widgets(ui: &mut UiCell, ids: &Ids, data: &mut TimelineData) {
    use timeline::Timeline;

    // Main window canvas.
    widget::Canvas::new()
        .border(0.0)
        .color(ui::color::DARK_CHARCOAL.alpha(0.5))
        .set(ids.window, ui);

    let TimelineData {
        playhead_ticks,
        bars,
        notes,
        tempo_envelope,
        octave_envelope,
        toggle_envelope,
        bang_envelope,
    } = data;

    let ticks = playhead_ticks.clone();
    let color = ui::color::LIGHT_BLUE;

    ////////////////////
    ///// TIMELINE /////
    ////////////////////
    //
    // Set the `Timeline` widget.
    //
    // This returns a context on which we can begin setting our tracks, playhead and scrollbar.
    //
    // The context is used in three stages:
    //
    // 1. `PinnedTracks` for setting tracks that should be pinned to the top of the timeline.
    // 2. `Tracks` for setting regular tracks.
    // 3. `Final` for setting the `Playhead` and `Scrollbar` widgets after all tracks are set.

    let context = Timeline::new(bars.iter().cloned(), PPQN)
        .playhead(ticks)
        .color(color)
        .wh_of(ids.window)
        .middle_of(ids.window)
        .border(1.0)
        .border_color(ui::color::CHARCOAL)
        .set(ids.timeline, ui);

    /////////////////////////
    ///// PINNED TRACKS /////
    /////////////////////////
    //
    // Pin the ruler track to the top of the timeline.
    //
    // All pinned tracks must be `set` prior to non-pinned tracks.
    {
        let ruler = track::Ruler::new(context.ruler, &context.bars, PPQN).color(color);
        let track = context.set_next_pinned_track(ruler, ui);
        for triggered in track.event {
            *playhead_ticks = triggered.ticks;
        }
    }

    //////////////////
    ///// TRACKS /////
    //////////////////

    // Now that we've finished setting the pinned tracks, move on to the `Tracks` context.
    let context = context.start_tracks(ui);

    {
        // Piano roll.
        let piano_roll = track::PianoRoll::new(&context.bars, PPQN, &notes[..]).color(color);
        let track = context.set_next_track(piano_roll, ui);
        for event in track.event {
            use timeline::track::piano_roll::Event;
            match event {
                Event::NoteOn(_note_idx) => (),
                Event::NoteOff(_note_idx) => (),
                Event::NotePlayed(_note_idx) => (),
            }
        }

        // A macro for common logic between tempo and octave "numeric" envelopes.
        macro_rules! numeric_automation {
            ($envelope:expr) => {
                let track = {
                    let automation =
                        track::automation::Numeric::new(&context.bars, PPQN, $envelope)
                            .color(color);
                    context.set_next_track(automation, ui)
                };
                for event in track.event {
                    use timeline::track::automation::numeric::Event;
                    match event {
                        Event::Interpolate(number) => println!("{}", number),
                        Event::Mutate(mutate) => mutate.apply($envelope),
                    }
                }
            };
        }

        // Tempo automation.
        numeric_automation!(tempo_envelope);
        // Octave automation.
        numeric_automation!(octave_envelope);

        // Toggle automation.
        let track = {
            let automation =
                track::automation::Toggle::new(&context.bars, PPQN, toggle_envelope).color(color);
            context.set_next_track(automation, ui)
        };
        for event in track.event {
            use timeline::track::automation::toggle::Event;
            match event {
                Event::Interpolate(_toggle) => (),
                Event::SwitchTo(_toggle) => (),
                Event::Mutate(mutate) => mutate.apply(toggle_envelope),
            }
        }

        // Bang automation.
        let track = {
            let automation =
                track::automation::Bang::new(&context.bars, PPQN, bang_envelope).color(color);
            context.set_next_track(automation, ui)
        };
        for event in track.event {
            use timeline::track::automation::bang::Event;
            match event {
                Event::Mutate(mutate) => mutate.apply(bang_envelope),
                _ => (),
            }
        }
    }

    ////////////////////////////////
    ///// PLAYHEAD & SCROLLBAR /////
    ////////////////////////////////

    // Now that all tracks have been set, finish up and set the `Playhead` and `Scrollbar`.
    let context = context.end_tracks();

    // Set the playhead after all tracks have been set.
    for event in context.set_playhead(ui) {
        use timeline::playhead::Event;
        match event {
            Event::Pressed => println!("Playhead pressed!"),
            Event::DraggedTo(ticks) => *playhead_ticks = ticks,
            Event::Released => println!("Playhead released!"),
        }
    }

    // Set the scrollbar if it is visible.
    context.set_scrollbar(ui);
}

fn key_pressed(_app: &App, model: &mut Model, key: Key) {
    match key {
        // Toggle play when space is pressed.
        Key::Space => {
            model.playing = !model.playing;
        }
        Key::R => {
            let bars = model.timeline_data.bars.clone();
            model.timeline_data.notes = bars::WithStarts::new(bars.iter().cloned(), PPQN)
                .enumerate()
                .map(|(i, (time_sig, start))| {
                    let end = start + time_sig.ticks_per_bar(PPQN);
                    let period = timeline::Period { start, end };
                    let pitch = pitch::Step((24 + (i * (random::<usize>() % 11)) % 12) as f32)
                        .to_letter_octave();
                    piano_roll::Note { period, pitch }
                })
                .collect();
        }
        Key::S => {
            // Save model.timeline_data to a JSON file.
            // This part is only included if you compile with the serde feature enabled.
            #[cfg(feature = "serde1")] {
                nannou::io::save_to_json("./saved_timeline_data.json", &model.timeline_data).expect("Error saving file");
            }
        }
        Key::L => {
            // Load the model.timeline_data from a JSON file.
            // This part is only included if you compile with the serde feature enabled.
            #[cfg(feature = "serde1")] {
                model.timeline_data = nannou::io::load_from_json("./saved_timeline_data.json").expect("Error loading timeline data");
            }
        }
        _ => {}
    }
}
<commit_msg>Avoid panicking if saved timeline data does not yet exist<commit_after>#[macro_use]
extern crate conrod_core;
extern crate nannou;
extern crate nannou_timeline as timeline;
extern crate pitch_calc;
extern crate time_calc;
// Conditionally compile with or with out serde i.e. serialization and thereby saving and loading.
// To use, run with `cargo run --release --example demo --features "serde"
#[cfg(feature = "serde1")]
#[macro_use]
extern crate serde;
#[cfg(feature = "serde1")]
extern crate serde_json;

use nannou::prelude::*;
use nannou::ui::prelude::*;
use pitch_calc as pitch;
use std::iter::once;
use time_calc as time;
use timeline::track::automation::{BangValue as Bang, Envelope, Point, ToggleValue as Toggle};
use timeline::track::piano_roll;
use timeline::{bars, track};

const BPM: time::calc::Bpm = 140.0;
const ONE_SECOND_MS: time::calc::Ms = 1_000.0;
const PPQN: time::Ppqn = 9600;
const WIDTH: u32 = 800;
const HEIGHT: u32 = 600;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    _window: window::Id,
    ui: Ui,
    ids: Ids,
    timeline_data: TimelineData,
    playing: bool,
}

// Implement the Serialize and Deserialize traits only if the serde feature is enabled.
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
struct TimelineData {
    playhead_ticks: time::Ticks,
    bars: Vec<time::TimeSig>,
    notes: Vec<piano_roll::Note>,
    tempo_envelope: track::automation::numeric::Envelope<f32>,
    octave_envelope: track::automation::numeric::Envelope<i32>,
    toggle_envelope: track::automation::toggle::Envelope,
    bang_envelope: track::automation::bang::Envelope,
}

// Create all of our unique `WidgetId`s with the `widget_ids!` macro.
conrod_core::widget_ids! {
    struct Ids {
        window,
        ruler,
        timeline,
    }
}

fn model(app: &App) -> Model {
    let _window = app
        .new_window()
        .key_pressed(key_pressed)
        .size(WIDTH, HEIGHT)
        .title("Timeline Demo")
        .view(view)
        .build()
        .unwrap();

    // Create the UI.
    let mut ui = app.new_ui().build().unwrap();
    let ids = Ids::new(ui.widget_id_generator());

    // Start the playhead at the beginning.
    let playhead_ticks = time::Ticks::from(0);

    // A sequence of bars with varying time signatures.
    let bars = vec![
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 6, bottom: 8 },
        time::TimeSig { top: 6, bottom: 8 },
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 4, bottom: 4 },
        time::TimeSig { top: 7, bottom: 8 },
        time::TimeSig { top: 7, bottom: 8 },
    ];

    let notes = bars::WithStarts::new(bars.iter().cloned(), PPQN)
        .enumerate()
        .map(|(i, (time_sig, start))| {
            let end = start + time_sig.ticks_per_bar(PPQN);
            let period = timeline::Period { start, end };
            let pitch = pitch::Step((24 + (i * 5) % 12) as f32).to_letter_octave();
            piano_roll::Note { period, pitch }
        })
        .collect();

    let tempo_envelope = {
        let start = Point {
            ticks: time::Ticks(0),
            value: 20.0,
        };
        let points = bars::Periods::new(bars.iter().cloned(), PPQN)
            .enumerate()
            .map(|(i, period)| Point {
                ticks: period.end,
                value: 20.0 + (i + 1) as f32 * 60.0 % 220.0,
            });
        Envelope::from_points(once(start).chain(points), 20.0, 240.0)
    };

    let octave_envelope = {
        let start = Point {
            ticks: time::Ticks(0),
            value: 0,
        };
        let points = bars::WithStarts::new(bars.iter().cloned(), PPQN)
            .enumerate()
            .flat_map(|(i, (ts, mut start))| {
                let bar_end = start + ts.ticks_per_bar(PPQN);
                let mut j = 0;
                std::iter::from_fn(move || {
                    if start >= bar_end {
                        return None;
                    }

                    let end = start + time::Ticks(PPQN as _);
                    let end = if end > bar_end { bar_end } else { end };
                    let point = Point {
                        ticks: end,
                        value: 1 + ((i as i32 + j as i32) * 3) % 12,
                    };
                    start = end;
                    j += 1;
                    Some(point)
                })
            });
        Envelope::from_points(once(start).chain(points), 0, 12)
    };

    let toggle_envelope = {
        let start = Point {
            ticks: time::Ticks(0),
            value: Toggle(random()),
        };
        let points = bars::Periods::new(bars.iter().cloned(), PPQN).map(|period| Point {
            ticks: period.end,
            value: Toggle(random()),
        });
        Envelope::from_points(once(start).chain(points), Toggle(false), Toggle(true))
    };

    let bang_envelope = {
        let points = bars::Periods::new(bars.iter().cloned(), PPQN).map(|period| Point {
            ticks: period.start,
            value: Bang,
        });
        Envelope::from_points(points, Bang, Bang)
    };

    let timeline_data = TimelineData {
        playhead_ticks,
        bars,
        notes,
        tempo_envelope,
        octave_envelope,
        toggle_envelope,
        bang_envelope,
    };

    Model {
        _window,
        ui,
        ids,
        timeline_data,
        playing: false,
    }
}

fn update(_app: &App, model: &mut Model, update: Update) {
    let Model {
        ids,
        ui,
        timeline_data,
        playing,
        ..
    } = model;

    // Update the user interface.
    set_widgets(&mut ui.set_widgets(), ids, timeline_data);

    // Get the current bpm from the tempo_envelope automation track.
    use timeline::track::automation::EnvelopeTrait; // needed to use the .y(Ticks) method on the envelope
    let tempo_value = timeline_data.tempo_envelope.y(timeline_data.playhead_ticks);
    let current_bpm = tempo_value.unwrap_or(BPM as f32) as f64;

    // Update the playhead.
    let delta_secs = if *playing {
        update.since_last.secs()
    } else {
        0.0
    };
    let delta_ticks = time::Ms(delta_secs * ONE_SECOND_MS).to_ticks(current_bpm, PPQN);
    let total_duration_ticks =
        timeline::bars_duration_ticks(timeline_data.bars.iter().cloned(), PPQN);
    let previous_playhead_ticks = timeline_data.playhead_ticks.clone();
    timeline_data.playhead_ticks =
        (timeline_data.playhead_ticks + delta_ticks) % total_duration_ticks;

    // Check if a bang in the bang_envelope has banged.
    for bang_point in timeline_data.bang_envelope.points() {
        if bang_point.ticks > previous_playhead_ticks
            && bang_point.ticks <= timeline_data.playhead_ticks
        {
            println!("BANG!");
        }
    }

    // Check if a note is playing
    for note in &timeline_data.notes {
        if timeline_data.playhead_ticks >= note.period.start
            && timeline_data.playhead_ticks < note.period.end
        {
            println!("Note playing: {:?}", note.pitch);
        }
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    model.ui.draw_to_frame(app, &frame).unwrap();
}

// Update / draw the Ui.
fn set_widgets(ui: &mut UiCell, ids: &Ids, data: &mut TimelineData) {
    use timeline::Timeline;

    // Main window canvas.
    widget::Canvas::new()
        .border(0.0)
        .color(ui::color::DARK_CHARCOAL.alpha(0.5))
        .set(ids.window, ui);

    let TimelineData {
        playhead_ticks,
        bars,
        notes,
        tempo_envelope,
        octave_envelope,
        toggle_envelope,
        bang_envelope,
    } = data;

    let ticks = playhead_ticks.clone();
    let color = ui::color::LIGHT_BLUE;

    ////////////////////
    ///// TIMELINE /////
    ////////////////////
    //
    // Set the `Timeline` widget.
    //
    // This returns a context on which we can begin setting our tracks, playhead and scrollbar.
    //
    // The context is used in three stages:
    //
    // 1. `PinnedTracks` for setting tracks that should be pinned to the top of the timeline.
    // 2. `Tracks` for setting regular tracks.
    // 3. `Final` for setting the `Playhead` and `Scrollbar` widgets after all tracks are set.

    let context = Timeline::new(bars.iter().cloned(), PPQN)
        .playhead(ticks)
        .color(color)
        .wh_of(ids.window)
        .middle_of(ids.window)
        .border(1.0)
        .border_color(ui::color::CHARCOAL)
        .set(ids.timeline, ui);

    /////////////////////////
    ///// PINNED TRACKS /////
    /////////////////////////
    //
    // Pin the ruler track to the top of the timeline.
    //
    // All pinned tracks must be `set` prior to non-pinned tracks.
    {
        let ruler = track::Ruler::new(context.ruler, &context.bars, PPQN).color(color);
        let track = context.set_next_pinned_track(ruler, ui);
        for triggered in track.event {
            *playhead_ticks = triggered.ticks;
        }
    }

    //////////////////
    ///// TRACKS /////
    //////////////////

    // Now that we've finished setting the pinned tracks, move on to the `Tracks` context.
    let context = context.start_tracks(ui);

    {
        // Piano roll.
        let piano_roll = track::PianoRoll::new(&context.bars, PPQN, &notes[..]).color(color);
        let track = context.set_next_track(piano_roll, ui);
        for event in track.event {
            use timeline::track::piano_roll::Event;
            match event {
                Event::NoteOn(_note_idx) => (),
                Event::NoteOff(_note_idx) => (),
                Event::NotePlayed(_note_idx) => (),
            }
        }

        // A macro for common logic between tempo and octave "numeric" envelopes.
        macro_rules! numeric_automation {
            ($envelope:expr) => {
                let track = {
                    let automation =
                        track::automation::Numeric::new(&context.bars, PPQN, $envelope)
                            .color(color);
                    context.set_next_track(automation, ui)
                };
                for event in track.event {
                    use timeline::track::automation::numeric::Event;
                    match event {
                        Event::Interpolate(number) => println!("{}", number),
                        Event::Mutate(mutate) => mutate.apply($envelope),
                    }
                }
            };
        }

        // Tempo automation.
        numeric_automation!(tempo_envelope);
        // Octave automation.
        numeric_automation!(octave_envelope);

        // Toggle automation.
        let track = {
            let automation =
                track::automation::Toggle::new(&context.bars, PPQN, toggle_envelope).color(color);
            context.set_next_track(automation, ui)
        };
        for event in track.event {
            use timeline::track::automation::toggle::Event;
            match event {
                Event::Interpolate(_toggle) => (),
                Event::SwitchTo(_toggle) => (),
                Event::Mutate(mutate) => mutate.apply(toggle_envelope),
            }
        }

        // Bang automation.
        let track = {
            let automation =
                track::automation::Bang::new(&context.bars, PPQN, bang_envelope).color(color);
            context.set_next_track(automation, ui)
        };
        for event in track.event {
            use timeline::track::automation::bang::Event;
            match event {
                Event::Mutate(mutate) => mutate.apply(bang_envelope),
                _ => (),
            }
        }
    }

    ////////////////////////////////
    ///// PLAYHEAD & SCROLLBAR /////
    ////////////////////////////////

    // Now that all tracks have been set, finish up and set the `Playhead` and `Scrollbar`.
    let context = context.end_tracks();

    // Set the playhead after all tracks have been set.
    for event in context.set_playhead(ui) {
        use timeline::playhead::Event;
        match event {
            Event::Pressed => println!("Playhead pressed!"),
            Event::DraggedTo(ticks) => *playhead_ticks = ticks,
            Event::Released => println!("Playhead released!"),
        }
    }

    // Set the scrollbar if it is visible.
    context.set_scrollbar(ui);
}

fn key_pressed(_app: &App, model: &mut Model, key: Key) {
    match key {
        // Toggle play when space is pressed.
        Key::Space => {
            model.playing = !model.playing;
        }
        Key::R => {
            let bars = model.timeline_data.bars.clone();
            model.timeline_data.notes = bars::WithStarts::new(bars.iter().cloned(), PPQN)
                .enumerate()
                .map(|(i, (time_sig, start))| {
                    let end = start + time_sig.ticks_per_bar(PPQN);
                    let period = timeline::Period { start, end };
                    let pitch = pitch::Step((24 + (i * (random::<usize>() % 11)) % 12) as f32)
                        .to_letter_octave();
                    piano_roll::Note { period, pitch }
                })
                .collect();
        }
        Key::S => {
            // Save model.timeline_data to a JSON file.
            // This part is only included if you compile with the serde feature enabled.
            #[cfg(feature = "serde1")] {
                nannou::io::save_to_json("./saved_timeline_data.json", &model.timeline_data).expect("Error saving file");
            }
        }
        Key::L => {
            // Load the model.timeline_data from a JSON file.
            // This part is only included if you compile with the serde feature enabled.
            #[cfg(feature = "serde1")] {
                if let Ok(new_data) = nannou::io::load_from_json("./saved_timeline_data.json") {
                    model.timeline_data = new_data;
                }
            }
        }
        _ => {}
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

use std::net::SocketAddr;

use hyper::server::conn::Http;
use hyper::service::service_fn;
use hyper::{Body, Method, Request, Response, StatusCode};
use tokio::net::TcpListener;

/// This is our service handler. It receives a Request, routes on its
/// path, and returns a Future of a Response.
async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    match (req.method(), req.uri().path()) {
        // Serve some instructions at /
        (&Method::GET, "/") => Ok(Response::new(Body::from(
            "Try POSTing data to /echo such as: `curl localhost:3000/echo -XPOST -d 'hello world'`",
        ))),

        // Simply echo the body back to the client.
        (&Method::POST, "/echo") => Ok(Response::new(req.into_body())),

        // TODO: Fix this, broken in PR #2896
        // Convert to uppercase before sending back to client using a stream.
        // (&Method::POST, "/echo/uppercase") => {
        // let chunk_stream = req.into_body().map_ok(|chunk| {
        //     chunk
        //         .iter()
        //         .map(|byte| byte.to_ascii_uppercase())
        //         .collect::<Vec<u8>>()
        // });
        // Ok(Response::new(Body::wrap_stream(chunk_stream)))
        // }

        // Reverse the entire body before sending back to the client.
        //
        // Since we don't know the end yet, we can't simply stream
        // the chunks as they arrive as we did with the above uppercase endpoint.
        // So here we do `.await` on the future, waiting on concatenating the full body,
        // then afterwards the content can be reversed. Only then can we return a `Response`.
        (&Method::POST, "/echo/reversed") => {
            let whole_body = hyper::body::to_bytes(req.into_body()).await?;

            let reversed_body = whole_body.iter().rev().cloned().collect::<Vec<u8>>();
            Ok(Response::new(Body::from(reversed_body)))
        }

        // Return the 404 Not Found for other routes.
        _ => {
            let mut not_found = Response::default();
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            Ok(not_found)
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    let listener = TcpListener::bind(addr).await?;
    println!("Listening on http://{}", addr);
    loop {
        let (stream, _) = listener.accept().await?;

        tokio::task::spawn(async move {
            if let Err(err) = Http::new().serve_connection(stream, service_fn(echo)).await {
                println!("Error serving connection: {:?}", err);
            }
        });
    }
}
<commit_msg>docs(examples): add a length check to reversed echo route (#2952)<commit_after>#![deny(warnings)]

use std::net::SocketAddr;

use hyper::body::HttpBody as _;
use hyper::server::conn::Http;
use hyper::service::service_fn;
use hyper::{Body, Method, Request, Response, StatusCode};
use tokio::net::TcpListener;

/// This is our service handler. It receives a Request, routes on its
/// path, and returns a Future of a Response.
async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
    match (req.method(), req.uri().path()) {
        // Serve some instructions at /
        (&Method::GET, "/") => Ok(Response::new(Body::from(
            "Try POSTing data to /echo such as: `curl localhost:3000/echo -XPOST -d 'hello world'`",
        ))),

        // Simply echo the body back to the client.
        (&Method::POST, "/echo") => Ok(Response::new(req.into_body())),

        // TODO: Fix this, broken in PR #2896
        // Convert to uppercase before sending back to client using a stream.
        // (&Method::POST, "/echo/uppercase") => {
        // let chunk_stream = req.into_body().map_ok(|chunk| {
        //     chunk
        //         .iter()
        //         .map(|byte| byte.to_ascii_uppercase())
        //         .collect::<Vec<u8>>()
        // });
        // Ok(Response::new(Body::wrap_stream(chunk_stream)))
        // }

        // Reverse the entire body before sending back to the client.
        //
        // Since we don't know the end yet, we can't simply stream
        // the chunks as they arrive as we did with the above uppercase endpoint.
        // So here we do `.await` on the future, waiting on concatenating the full body,
        // then afterwards the content can be reversed. Only then can we return a `Response`.
        (&Method::POST, "/echo/reversed") => {
            // To protect our server, reject requests with bodies larger than
            // 64kbs of data.
            let max = req.body().size_hint().upper().unwrap_or(u64::MAX);
            if max > 1024 * 64 {
                let mut resp = Response::new(Body::from("Body too big"));
                *resp.status_mut() = hyper::StatusCode::PAYLOAD_TOO_LARGE;
                return Ok(resp);
            }

            let whole_body = hyper::body::to_bytes(req.into_body()).await?;

            let reversed_body = whole_body.iter().rev().cloned().collect::<Vec<u8>>();
            Ok(Response::new(Body::from(reversed_body)))
        }

        // Return the 404 Not Found for other routes.
        _ => {
            let mut not_found = Response::default();
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            Ok(not_found)
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    let listener = TcpListener::bind(addr).await?;
    println!("Listening on http://{}", addr);
    loop {
        let (stream, _) = listener.accept().await?;

        tokio::task::spawn(async move {
            if let Err(err) = Http::new().serve_connection(stream, service_fn(echo)).await {
                println!("Error serving connection: {:?}", err);
            }
        });
    }
}
<|endoftext|>


<commit_before>extern crate ruroonga;
use ruroonga::*;
use std::ffi::CStr;
use std::str;

fn main() {
    unsafe {
        let rc = grn_init();
        let ctx = grn_ctx_open(rc);
        println!("Hello in Ruroonga with Groonga: {}", get_groonga_version());

        let rc = grn_ctx_close(ctx);
        let _ = grn_fin();
    }
}
<commit_msg>Remove a needless newline<commit_after>extern crate ruroonga;
use ruroonga::*;
use std::ffi::CStr;
use std::str;

fn main() {
    unsafe {
        let rc = grn_init();
        let ctx = grn_ctx_open(rc);
        println!("Hello in Ruroonga with Groonga: {}", get_groonga_version());
        let rc = grn_ctx_close(ctx);
        let _ = grn_fin();
    }
}
<|endoftext|>


<commit_before>extern crate rsoundio;

use std::f32::consts::PI;
use std::thread;
use std::time::Duration;

fn main() {
    let f = 440f32;
    let cycle_len = (48_000 as f32 / f) as usize;
    let phi = 2.0 * f * PI / 48_000 as f32;
    let mut pos = 0;
    let samples: Vec<f32> = (pos..cycle_len)
                                .map(|i| (phi * i as f32).sin())
                                .collect();
    // create an audio context
    let sio = rsoundio::SoundIo::new();
    sio.set_app_name("rsoundio").unwrap();
    // connect to the default audio backend
    sio.connect().unwrap();
    println!("Connected to backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    // get default output device
    let dev = sio.default_output_device().unwrap();
    assert!(dev.probe_error().is_none());
    println!("Using output device: {}", dev);
    // create output stream
    let mut out = dev.create_outstream().unwrap();
    assert!(out.set_name("rsoundio-example-sine").is_ok());
    out.set_format(rsoundio::SioFormat::Float32LE).unwrap();
    println!("Output format: {}", out.format().unwrap());

    // register callbacks
    out.register_write_callback(Box::new(|out: rsoundio::OutStream,
                                          min_frame_count: i32,
                                          max_frame_count: i32| {
        let l: Vec<f32> = samples.iter()
                                 .cycle()
                                 .take(max_frame_count as usize + pos)
                                 .skip(pos)
                                 .map(|s| *s)
                                 .collect();
        pos = (max_frame_count as usize + pos) % cycle_len;
        let r = l.clone();
        let frames = vec![l, r];
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    }));
    out.register_underflow_callback(Box::new(|out: rsoundio::OutStream| {
        println!("Underflow in {} occured!", out.name().unwrap())
    }));
    out.register_error_callback(Box::new(|out: rsoundio::OutStream,
                                          err: rsoundio::SioError| {
        println!("{} error: {}", out.name().unwrap(), err)
    }));

    // open output stream
    out.open().unwrap();
    let sr = out.sample_rate();
    println!("Sample rate: {}", sr);

    let layout = out.layout();
    println!("Output channel layout: {}", layout);
    // start audio output (now the `write_callback` will be called periodically)
    out.start().unwrap();
    thread::sleep(Duration::new(3, 0));
    println!("Pause for 1s");
    out.pause();
    thread::sleep(Duration::new(1, 0));
    println!("Unpausing");
    out.unpause();
    thread::sleep(Duration::new(3, 0));
    out.destroy()
}
<commit_msg>Change applicaiton and stream<commit_after>extern crate rsoundio;

use std::f32::consts::PI;
use std::thread;
use std::time::Duration;

fn main() {
    let f = 440f32;
    let cycle_len = (48_000 as f32 / f) as usize;
    let phi = 2.0 * f * PI / 48_000 as f32;
    let mut pos = 0;
    let samples: Vec<f32> = (pos..cycle_len)
                                .map(|i| (phi * i as f32).sin())
                                .collect();
    // create an audio context
    let mut sio = rsoundio::SoundIo::new();
    sio.set_app_name("rsoundio-example").unwrap();
    // connect to the default audio backend
    sio.connect().unwrap();
    println!("Connected to backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    // get default output device
    let dev = sio.default_output_device().unwrap();
    assert!(dev.probe_error().is_none());
    println!("Using output device: {}", dev);
    // create output stream
    let mut out = dev.create_outstream().unwrap();
    assert!(out.set_name("sine").is_ok());
    out.set_format(rsoundio::SioFormat::Float32LE).unwrap();
    println!("Output format: {}", out.format().unwrap());

    // register callbacks
    out.register_write_callback(Box::new(|out: rsoundio::OutStream,
                                          min_frame_count: i32,
                                          max_frame_count: i32| {
        let l: Vec<f32> = samples.iter()
                                 .cycle()
                                 .take(max_frame_count as usize + pos)
                                 .skip(pos)
                                 .map(|s| *s)
                                 .collect();
        pos = (max_frame_count as usize + pos) % cycle_len;
        let r = l.clone();
        let frames = vec![l, r];
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    }));
    out.register_underflow_callback(Box::new(|out: rsoundio::OutStream| {
        println!("Underflow in {} occured!", out.name().unwrap())
    }));
    out.register_error_callback(Box::new(|out: rsoundio::OutStream,
                                          err: rsoundio::SioError| {
        println!("{} error: {}", out.name().unwrap(), err)
    }));

    // open output stream
    out.open().unwrap();
    let sr = out.sample_rate();
    println!("Sample rate: {}", sr);

    let layout = out.layout();
    println!("Output channel layout: {}", layout);
    // start audio output (now the `write_callback` will be called periodically)
    out.start().unwrap();
    thread::sleep(Duration::new(3, 0));
    println!("Pause for 1s");
    out.pause();
    thread::sleep(Duration::new(1, 0));
    println!("Unpausing");
    out.unpause();
    thread::sleep(Duration::new(3, 0));
    out.destroy()
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

use std::iter;

use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy};

pub fn target() -> Result<Target, String> {
    const PRE_LINK_ARGS: &[&str] = &[
        "-Wl,--as-needed",
        "-Wl,-z,noexecstack",
        "-m64",
         "-fuse-ld=gold",
         "-nostdlib",
         "-shared",
         "-Wl,-e,sgx_entry",
         "-Wl,-Bstatic",
         "-Wl,--gc-sections",
         "-Wl,-z,text",
         "-Wl,-z,norelro",
         "-Wl,--rosegment",
         "-Wl,--no-undefined",
         "-Wl,--error-unresolved-symbols",
         "-Wl,--no-undefined-version",
         "-Wl,-Bsymbolic",
         "-Wl,--export-dynamic",
    ];
    const EXPORT_SYMBOLS: &[&str] = &[
        "sgx_entry",
        "HEAP_BASE",
        "HEAP_SIZE",
        "RELA",
        "RELACOUNT",
        "ENCLAVE_SIZE",
        "CFGDATA_BASE",
        "DEBUG",
    ];
    let opts = TargetOptions {
        dynamic_linking: false,
        executables: true,
        linker_is_gnu: true,
        max_atomic_width: Some(64),
        panic_strategy: PanicStrategy::Abort,
        cpu: "x86-64".into(),
        position_independent_executables: true,
        pre_link_args: iter::once(
                (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect())
        ).collect(),
        override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
        ..Default::default()
    };
    Ok(Target {
        llvm_target: "x86_64-unknown-linux-gnu".into(),
        target_endian: "little".into(),
        target_pointer_width: "64".into(),
        target_c_int_width: "32".into(),
        target_os: "unknown".into(),
        target_env: "sgx".into(),
        target_vendor: "fortanix".into(),
        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".into(),
        arch: "x86_64".into(),
        linker_flavor: LinkerFlavor::Gcc,
        options: opts,
    })
}
<commit_msg>Always set the RDRAND and RDSEED features on SGX<commit_after>// Copyright 2018 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.

use std::iter;

use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy};

pub fn target() -> Result<Target, String> {
    const PRE_LINK_ARGS: &[&str] = &[
        "-Wl,--as-needed",
        "-Wl,-z,noexecstack",
        "-m64",
         "-fuse-ld=gold",
         "-nostdlib",
         "-shared",
         "-Wl,-e,sgx_entry",
         "-Wl,-Bstatic",
         "-Wl,--gc-sections",
         "-Wl,-z,text",
         "-Wl,-z,norelro",
         "-Wl,--rosegment",
         "-Wl,--no-undefined",
         "-Wl,--error-unresolved-symbols",
         "-Wl,--no-undefined-version",
         "-Wl,-Bsymbolic",
         "-Wl,--export-dynamic",
    ];
    const EXPORT_SYMBOLS: &[&str] = &[
        "sgx_entry",
        "HEAP_BASE",
        "HEAP_SIZE",
        "RELA",
        "RELACOUNT",
        "ENCLAVE_SIZE",
        "CFGDATA_BASE",
        "DEBUG",
    ];
    let opts = TargetOptions {
        dynamic_linking: false,
        executables: true,
        linker_is_gnu: true,
        max_atomic_width: Some(64),
        panic_strategy: PanicStrategy::Abort,
        cpu: "x86-64".into(),
        features: "+rdrnd,+rdseed".into(),
        position_independent_executables: true,
        pre_link_args: iter::once(
                (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect())
        ).collect(),
        override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
        ..Default::default()
    };
    Ok(Target {
        llvm_target: "x86_64-unknown-linux-gnu".into(),
        target_endian: "little".into(),
        target_pointer_width: "64".into(),
        target_c_int_width: "32".into(),
        target_os: "unknown".into(),
        target_env: "sgx".into(),
        target_vendor: "fortanix".into(),
        data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".into(),
        arch: "x86_64".into(),
        linker_flavor: LinkerFlavor::Gcc,
        options: opts,
    })
}
<|endoftext|>


<commit_before>// Copyright 2020 The Propverify authors
//
// 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.

/////////////////////////////////////////////////////////////////
// FFI wrapper for KLEE symbolic execution tool
/////////////////////////////////////////////////////////////////

use std::default::Default;
use std::os::raw;

#[link(name = "kleeRuntest")]
extern "C" {
    fn klee_make_symbolic(data: *mut raw::c_void, length: usize, name: *const raw::c_char);
    fn klee_assume(cond: usize);
    fn klee_abort() -> !;
    fn klee_silent_exit(_ignored: u32) -> !;
    fn klee_is_replay() -> i32;
}

// Create an abstract value of type <T>
//
// This should only be used on types that occupy contiguous memory
// and where all possible bit-patterns are legal.
// e.g., u8/i8, ... u128/i128, f32/f64
pub fn abstract_value<T: Default>() -> T {
    let mut r = T::default();
    unsafe {
        let data = std::mem::transmute(&mut r);
        let length = std::mem::size_of::<T>();
        let null = 0 as *const i8;
        klee_make_symbolic(data, length, null)
    }
    return r;
}

// Add an assumption
pub fn assume(cond: bool) {
    unsafe { klee_assume(if cond { 1 } else { 0 }) }
}

// Reject the current execution with a verification failure.
//
// In almost all circumstances, report_error should
// be used instead because it generates an error message.
pub fn abort() -> ! {
    unsafe { klee_abort() }
}

// Reject the current execution path with a verification success.
// This is equivalent to assume(false)
// and the opposite of report_error.
//
// Typical usage is in generating symbolic values when the value
// does not meet some criteria.
pub fn reject() -> ! {
    unsafe { klee_silent_exit(0) }
}

// Detect whether the program is being run symbolically in KLEE
// or being replayed using the kleeRuntest runtime.
//
// This is used to decide whether to display the values of
// variables that may be either symbolic or concrete.
pub fn is_replay() -> bool {
    unsafe { klee_is_replay() != 0 }
}

// Reject the current execution with a verification failure
// and an error message.
pub fn report_error(message: &str) -> ! {
    // Mimic the format of klee_report_error
    // (We don't use klee_report_error because it is not
    // supported by the kleeRuntest library.)
    eprintln!("KLEE: ERROR:{}", message);
    abort();
}

// Check an assertion
pub fn verify(cond: bool) {
    if !cond {
        report_error("verification failed");
    }
}

// Declare that failure is the expected behaviour
pub fn expect_raw(msg: &str) {
    eprintln!("VERIFIER_EXPECT: {}", msg)
}

// Declare that failure is the expected behaviour
pub fn expect(msg: Option<&str>) {
    match msg {
        None => eprintln!("VERIFIER_EXPECT: should_panic"),
        Some(msg) => eprintln!("VERIFIER_EXPECT: should_panic(expected = \"{}\")", msg)
    }
}

#[macro_export]
macro_rules! assert {
    ($cond:expr) => {
        if ! $cond {
            eprintln!("VERIFIER: assertion failed: {}", stringify!($cond));
            abort();
        }
    };
    // ($cond:expr,) => { ... };
    // ($cond:expr, $($arg:tt)+) => { ... };
}

#[macro_export]
macro_rules! assert_eq {
    ($left:expr, $right:expr) => { $crate::assert!(($left) == ($right)); };
    // ($left:expr, $right:expr,) => { ... };
    // ($left:expr, $right:expr, $($arg:tt)+) => { ... };
}

#[macro_export]
macro_rules! assert_ne {
    ($left:expr, $right:expr) => { $crate::assert!(($left) != ($right)); };
    // ($left:expr, $right:expr,) => { ... };
    // ($left:expr, $right:expr, $($arg:tt)+) => { ... };
}

/////////////////////////////////////////////////////////////////
// End
/////////////////////////////////////////////////////////////////
<commit_msg>Fix klee assert macro<commit_after>// Copyright 2020 The Propverify authors
//
// 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.

/////////////////////////////////////////////////////////////////
// FFI wrapper for KLEE symbolic execution tool
/////////////////////////////////////////////////////////////////

use std::default::Default;
use std::os::raw;

#[link(name = "kleeRuntest")]
extern "C" {
    fn klee_make_symbolic(data: *mut raw::c_void, length: usize, name: *const raw::c_char);
    fn klee_assume(cond: usize);
    fn klee_abort() -> !;
    fn klee_silent_exit(_ignored: u32) -> !;
    fn klee_is_replay() -> i32;
}

// Create an abstract value of type <T>
//
// This should only be used on types that occupy contiguous memory
// and where all possible bit-patterns are legal.
// e.g., u8/i8, ... u128/i128, f32/f64
pub fn abstract_value<T: Default>() -> T {
    let mut r = T::default();
    unsafe {
        let data = std::mem::transmute(&mut r);
        let length = std::mem::size_of::<T>();
        let null = 0 as *const i8;
        klee_make_symbolic(data, length, null)
    }
    return r;
}

// Add an assumption
pub fn assume(cond: bool) {
    unsafe { klee_assume(if cond { 1 } else { 0 }) }
}

// Reject the current execution with a verification failure.
//
// In almost all circumstances, report_error should
// be used instead because it generates an error message.
pub fn abort() -> ! {
    unsafe { klee_abort() }
}

// Reject the current execution path with a verification success.
// This is equivalent to assume(false)
// and the opposite of report_error.
//
// Typical usage is in generating symbolic values when the value
// does not meet some criteria.
pub fn reject() -> ! {
    unsafe { klee_silent_exit(0) }
}

// Detect whether the program is being run symbolically in KLEE
// or being replayed using the kleeRuntest runtime.
//
// This is used to decide whether to display the values of
// variables that may be either symbolic or concrete.
pub fn is_replay() -> bool {
    unsafe { klee_is_replay() != 0 }
}

// Reject the current execution with a verification failure
// and an error message.
pub fn report_error(message: &str) -> ! {
    // Mimic the format of klee_report_error
    // (We don't use klee_report_error because it is not
    // supported by the kleeRuntest library.)
    eprintln!("KLEE: ERROR:{}", message);
    abort();
}

// Check an assertion
pub fn verify(cond: bool) {
    if !cond {
        report_error("verification failed");
    }
}

// Declare that failure is the expected behaviour
pub fn expect_raw(msg: &str) {
    eprintln!("VERIFIER_EXPECT: {}", msg)
}

// Declare that failure is the expected behaviour
pub fn expect(msg: Option<&str>) {
    match msg {
        None => eprintln!("VERIFIER_EXPECT: should_panic"),
        Some(msg) => eprintln!("VERIFIER_EXPECT: should_panic(expected = \"{}\")", msg)
    }
}

#[macro_export]
macro_rules! assert {
    ($cond:expr) => {
        if ! $cond {
            eprintln!("VERIFIER: assertion failed: {}", stringify!($cond));
            $crate::abort();
        }
    };
    // ($cond:expr,) => { ... };
    // ($cond:expr, $($arg:tt)+) => { ... };
}

#[macro_export]
macro_rules! assert_eq {
    ($left:expr, $right:expr) => { $crate::assert!(($left) == ($right)); };
    // ($left:expr, $right:expr,) => { ... };
    // ($left:expr, $right:expr, $($arg:tt)+) => { ... };
}

#[macro_export]
macro_rules! assert_ne {
    ($left:expr, $right:expr) => { $crate::assert!(($left) != ($right)); };
    // ($left:expr, $right:expr,) => { ... };
    // ($left:expr, $right:expr, $($arg:tt)+) => { ... };
}

/////////////////////////////////////////////////////////////////
// End
/////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>//! Tests individual commands via `reply`

use std::collections::HashSet;

use rustc_serialize::json::Json;

use super::*;

use super::super::channel;

const PING: &'static str = r#"{ "type":"ping" }"#;
const COMMANDS: &'static str = r#"{ "type":"commands" }"#;
const VERSION: &'static str = r#"{ "type":"ping" }"#;
const RUN_COMMAND: &'static str = r#"{ "type":"ping" }"#;
const RUN_PROP_GET: &'static str = r#"{ "type":"ping" }"#;
const RUN_OBJECT: &'static str = r#"{ "type":"ping" }"#;
const RUN_NO_KEY: &'static str = r#"{ "type":"ping" }"#;
const GET_OBJECT: &'static str = r#"{ "type":"ping" }"#;

macro_rules! reply {
    ($json:expr) => {
        match super::super::command::reply(
            Json::from_str($json).expect("Couldn't parse json")) {
            Ok(json) => json,
            Err(json) => {
                panic!(format!("Bad reply(): got {}", json.to_string()))
            }
        }
    }
}

#[test]
fn ping() {
    let reply = reply!(PING);
    assert_eq!(reply, channel::success_json());
}

#[test]
fn commands() {
    let mut reply = reply!(COMMANDS);

    let mut obj = reply.as_object_mut().expect("reply not object");
    let mut value = obj.remove("value").expect("reply: no 'value'");
    let val_arr = value.as_array_mut().expect("reply: 'value' not array");
    let mut set = HashSet::new();
    for val in val_arr {
        set.insert(val.as_string().expect("reply: 'value' not string array"));
    }
    assert_eq!(set.len(), 7);
    let desired = &["get", "set", "exists", "run", "version", "commands", "ping"];
    for com in desired.iter() {
        assert!(set.contains(com), "Missing command {}", com);
    }
}
<commit_msg>Add Json strs for future tests, warnings galore<commit_after>//! Tests individual commands via `reply`

use std::collections::HashSet;

use rustc_serialize::json::Json;

use super::*;

use super::super::channel;

const PING: &'static str = r#"{ "type":"ping" }"#;
const COMMANDS: &'static str = r#"{ "type":"commands" }"#;
const VERSION: &'static str = r#"{ "type":"version" }"#;

const RUN_COMMAND: &'static str = r#"{ "type":"ping" }"#;
const RUN_PROP_GET: &'static str = r#"{ "type":"ping" }"#;
const RUN_OBJECT: &'static str = r#"{ "type":"ping" }"#;
const RUN_NO_KEY: &'static str = r#"{ "type":"ping" }"#;

const GET_OBJECT: &'static str = r#"{ "type":"ping" }"#;
const GET_PROP: &'static str = r#"{ "type":"ping" }"#;
const GET_READONLY: &'static str = r#"{ "type":"ping" }"#;
const GET_WRITEONLY: &'static str = r#"{ "type":"ping" }"#;
const GET_PROP_WRITE: &'static str = r#"{ "type":"ping" }"#;
const GET_NO_KEY: &'static str = r#"{ "type":"ping" }"#;
const GET_NO_PERMS: &'static str = "";

const SET_OBJECT: &'static str = r#"{ "type":"ping" }"#;
const SET_PROP: &'static str = r#"{ "type":"ping" }"#;
const SET_READONLY: &'static str = r#"{ "type":"ping" }"#;
const SET_WRITEONLY: &'static str = r#"{ "type":"ping" }"#;
const SET_PROP_READ: &'static str = r#"{ "type":"ping" }"#;
const SET_NEW_KEY: &'static str = r#"{ "type":"ping" }"#;
const SET_NO_PERMS: &'static str = "";

const EXISTS_OBJECT_RW: &'static str = r#"{}"#;
const EXISTS_PROP: &'static str = r#"{}"#;
const EXISTS_PROP_READ: &'static str = r#"{}"#;
const EXISTS_PROP_WRITE: &'static str = r#"{}"#;
const EXISTS_OBJECT_READ: &'static str = r#"{}"#;
const EXISTS_OBJECT_WRITE: &'static str = r#"{}"#;
const EXISTS_NO_KEY: &'static str =
    r#"{ "type": "exists", "key": "test.no_key"}"#;

const BAD_NO_REQUEST: &'static str = r#"{}"#;
const BAD_INVALID_REQUEST: &'static str = r#"{}"#;
const BAD_GET_NO_KEY: &'static str = r#"{}"#;
const BAD_SET_NO_KEY: &'static str = r#"{}"#;
const BAD_SET_NO_VALUE: &'static str = r#"{}"#;
const BAD_RUN_NO_COMMAND: &'static str = r#"{}"#;
const BAD_RUN_EXTRA_FIELDS: &'static str = r#"{}"#;
const BAD_RUN_U64_COMMAND: &'static str = r#"{}"#;
const BAD_GET_OBJECT_KEY: &'static str = r#"{}"#;
const BAD_REQUEST_IS_A_NUMBER: &'static str = r#"23"#;

macro_rules! reply {
    ($json:expr) => {
        match super::super::command::reply(
            Json::from_str($json).expect("Couldn't parse json")) {
            Ok(json) => json,
            Err(json) => {
                panic!(format!("Bad reply(): got {}", json.to_string()))
            }
        }
    }
}

#[test]
fn ping() {
    let reply = reply!(PING);
    assert_eq!(reply, channel::success_json());
}

#[test]
fn commands() {
    let mut reply = reply!(COMMANDS);

    let mut obj = reply.as_object_mut()
        .expect("commands: reply not object");
    let mut value = obj.remove("value")
        .expect("commands: reply: no 'value'");
    let val_arr = value.as_array_mut()
        .expect("commands: reply: 'value' not array");
    let mut set = HashSet::new();
    for val in val_arr {
        set.insert(val.as_string()
                   .expect("commands: reply: 'value' not string array"));
    }
    assert_eq!(set.len(), 7);
    let desired = &["get", "set", "exists", "run", "version", "commands", "ping"];
    for com in desired.iter() {
        assert!(set.contains(com), "Missing command {}", com);
    }
}

#[test]
fn version() {
    let mut reply = reply!(VERSION);
    let version = reply.as_object_mut().expect("version: reply not object")
        .remove("value").expect("version: reply: no 'value'")
        .as_u64().expect("version: reply not u64");

    assert_eq!(version, super::super::VERSION);
}
<|endoftext|>