<commit_before>//extern crate scaii_core;
//#[macro_use]
//extern crate serde_derive;

use std::process;
use std::env;
use std::error::Error;
use scaii_core::{ScaiiConfig, ScaiiError};
use scaii_core::util;
use scaii_core::scaii_config;

// launch the simple python webserver if python3 installed
pub fn launch_webserver() {
    let python3_command_result = get_python3_command();
    match python3_command_result {
        Some(python_command) => match python_command.as_ref() {
            "python" => {
                let cd_result = change_to_viz_dir();
                match cd_result {
                    Ok(_) => {
                        launch_webserver_using_command("python");
                    }
                    Err(error) => {
                        println!(
                            "failed to cd into viz directory to launch webserver... {:?}",
                            error.description()
                        );
                        process::exit(0);
                    }
                }
            }
            "python3" => {
                let cd_result = change_to_viz_dir();
                match cd_result {
                    Ok(_) => {
                        launch_webserver_using_command("python3");
                    }
                    Err(error) => {
                        println!(
                            "failed to cd into viz directory to launch webserver... {:?}",
                            error.description()
                        );
                        process::exit(0);
                    }
                }
            }
            _ => {
                println!("ERROR - Python3 is required to run SCAII.");
                process::exit(0);
            }
        },
        _ => {
            println!("ERROR - Python3 is required to run SCAII.");
            process::exit(0);
        }
    }
}

fn get_python3_command() -> Option<String> {
    if is_python3_invoked_as_python() {
        return Some("python".to_string());
    }
    if is_python3_invoked_as_python3() {
        return Some("python3".to_string());
    }
    None
}

fn is_python3_invoked_as_python() -> bool {
    let version_option = get_python_version("python".to_string());
    match version_option {
        Some(version) => match version.as_ref() {
            "3" => true,
            _ => false,
        },
        _ => false,
    }
}

fn is_python3_invoked_as_python3() -> bool {
    let version_option = get_python_version("python3".to_string());
    match version_option {
        Some(version) => match version.as_ref() {
            "3" => true,
            _ => false,
        },
        _ => false,
    }
}

#[cfg(windows)]
fn get_python_version(python_command: String) -> Option<String> {
    let mut args: Vec<String> = Vec::new();
    args.push("--version".to_string());
    let command_result = util::run_command_read_stderr(&python_command, args);
    match command_result {
        Ok(result_string) => {
            if result_string.starts_with("Python 3") {
                Some("3".to_string())
            } else {
                println!("no python3 detected");
                None
            }
        }
        Err(_) => None,
    }
}

#[cfg(unix)]
fn get_python_version(python_command: String) -> Option<String> {
    let mut args: Vec<String> = Vec::new();
    args.push("--version".to_string());
    let command_result = util::run_command(&python_command, args); // This is the only line that
    match command_result {
        // changes, potential area for
        Ok(result_string) => {
            // consolidation during refactor.
            if result_string.starts_with("Python 3") {
                Some("3".to_string())
            } else {
                println!("no python3 detected");
                None
            }
        }
        Err(_) => None,
    }
}

fn change_to_viz_dir() -> Result<(), Box<Error>> {
    //cd <SCAII_ROOT>\viz
    let mut root = util::get_scaii_root()?;
    root.push("viz");
    if env::set_current_dir(&root.as_path()).is_ok() {
        Ok(())
    } else {
        Err(Box::new(ScaiiError::new(&format!(
            "could not set_current_dir to {:?}",
            root.as_path()
        ))))
    }
}

fn launch_webserver_using_command(python_command: &str) {
    //python -m http.server <port>
    let mut scaii_config: ScaiiConfig = scaii_config::load_scaii_config();
    let port = scaii_config.get_replay_port();
    let command = python_command.to_string();
    let mut args: Vec<String> = Vec::new();
    args.push("-m".to_string());
    args.push("http.server".to_string());
    args.push(port);
    let run_result = util::run_command(&command, args);
    match run_result {
        Ok(_) => {}
        Err(error) => {
            println!(
                "Error - problem launching SCAII simple web server: {:?}",
                error.description()
            );
        }
    }
}
<commit_msg>Fixes #77, re-wrote get_python_version()<commit_after>//extern crate scaii_core;
//#[macro_use]
//extern crate serde_derive;

use std::process;
use std::env;
use std::error::Error;
use scaii_core::{ScaiiConfig, ScaiiError};
use scaii_core::util;
use scaii_core::scaii_config;

// launch the simple python webserver if python3 installed
pub fn launch_webserver() {
    let python3_command_result = get_python3_command();

    match python3_command_result {
        Some(python_command) => match python_command.as_ref() {
            "python" => {
                let cd_result = change_to_viz_dir();
                match cd_result {
                    Ok(_) => {
                        launch_webserver_using_command("python");
                    }
                    Err(error) => {
                        println!(
                            "failed to cd into viz directory to launch webserver... {:?}",
                            error.description()
                        );
                        process::exit(0);
                    }
                }
            }
            "python3" => {
                let cd_result = change_to_viz_dir();
                match cd_result {
                    Ok(_) => {
                        launch_webserver_using_command("python3");
                    }
                    Err(error) => {
                        println!(
                            "failed to cd into viz directory to launch webserver... {:?}",
                            error.description()
                        );
                        process::exit(0);
                    }
                }
            }
            _ => {
                println!("ERROR - Python3 is required to run SCAII.");
                process::exit(0);
            }
        },
        _ => {
            println!("ERROR - Python3 is required to run SCAII.");
            process::exit(0);
        }
    }
}

fn get_python3_command() -> Option<String> {
    if is_python3_invoked_as_python() {
        return Some("python".to_string());
    }
    if is_python3_invoked_as_python3() {
        return Some("python3".to_string());
    }
    None
}

fn is_python3_invoked_as_python() -> bool {
    let version_option = get_python_version("python".to_string());
    match version_option {
        Some(version) => match version.as_ref() {
            "3" => true,
            _ => false,
        },
        _ => false,
    }
}

fn is_python3_invoked_as_python3() -> bool {
    let version_option = get_python_version("python3".to_string());
    match version_option {
        Some(version) => match version.as_ref() {
            "3" => true,
            _ => false,
        },
        _ => false,
    }
}

fn get_python_version(python_command: String) -> Option<String> {
    use std::process::{Command, Stdio};

    let output_stdout = Command::new(&python_command)
        .arg("--version")
        .stdout(Stdio::piped())
        .output()
        .expect("Failed to execute command");

    let result = String::from_utf8_lossy(&output_stdout.stdout);

    if result.starts_with("Python 3") {
        return Some("3".to_string())
    } else {
        let output_stderr = Command::new(&python_command) // Python 3.4 outputs to stderr
        .arg("--version")
        .stderr(Stdio::piped())
        .output()
        .expect("Failed to execute command");

        let result = String::from_utf8_lossy(&output_stderr.stderr);
        if result.starts_with("Python 3") {
            return Some("3".to_string())
        }
    }
    None
}

fn change_to_viz_dir() -> Result<(), Box<Error>> {
    //cd <SCAII_ROOT>\viz
    let mut root = util::get_scaii_root()?;
    root.push("viz");
    if env::set_current_dir(&root.as_path()).is_ok() {
        Ok(())
    } else {
        Err(Box::new(ScaiiError::new(&format!(
            "could not set_current_dir to {:?}",
            root.as_path()
        ))))
    }
}

fn launch_webserver_using_command(python_command: &str) {
    //python -m http.server <port>
    let mut scaii_config: ScaiiConfig = scaii_config::load_scaii_config();
    let port = scaii_config.get_replay_port();
    let command = python_command.to_string();
    let mut args: Vec<String> = Vec::new();
    args.push("-m".to_string());
    args.push("http.server".to_string());
    args.push(port);
    let run_result = util::run_command(&command, args);
    match run_result {
        Ok(_) => {}
        Err(error) => {
            println!(
                "Error - problem launching SCAII simple web server: {:?}",
                error.description()
            );
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::time::Instant;

mod keyed_event;
mod waitaddress;

enum Backend {
    KeyedEvent(keyed_event::KeyedEvent),
    WaitAddress(waitaddress::WaitAddress),
}

impl Backend {
    unsafe fn get() -> &'static Backend {
        static BACKEND: AtomicUsize = ATOMIC_USIZE_INIT;

        // Fast path: use the existing object
        let backend = BACKEND.load(Ordering::Acquire);
        if backend != 0 {
            return &*(backend as *const Backend);
        };

        // Try to create a new Backend
        let backend;
        if let Some(waitaddress) = waitaddress::WaitAddress::create() {
            backend = Backend::WaitAddress(waitaddress);
        } else if let Some(keyed_event) = keyed_event::KeyedEvent::create() {
            backend = Backend::KeyedEvent(keyed_event);
        } else {
            panic!(
                "parking_lot requires either NT Keyed Events (WinXP+) or \
                 WaitOnAddress/WakeByAddress (Win8+)"
            );
        }

        // Try to create a new object
        let backend = Box::into_raw(Box::new(backend));
        match BACKEND.compare_exchange(0, backend as usize, Ordering::Release, Ordering::Relaxed) {
            Ok(_) => &*(backend as *const Backend),
            Err(x) => {
                // We lost the race, free our object and return the global one
                Box::from_raw(backend);
                &*(x as *const Backend)
            }
        }
    }
}

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    key: AtomicUsize,
    backend: &'static Backend,
}

impl ThreadParker {
    pub fn new() -> ThreadParker {
        // Initialize the backend here to ensure we don't get any panics
        // later on, which could leave synchronization primitives in a broken
        // state.
        ThreadParker {
            key: AtomicUsize::new(0),
            backend: unsafe { Backend::get() },
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    pub unsafe fn prepare_park(&self) {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.prepare_park(&self.key),
            Backend::WaitAddress(ref x) => x.prepare_park(&self.key),
        }
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    pub unsafe fn timed_out(&self) -> bool {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.timed_out(&self.key),
            Backend::WaitAddress(ref x) => x.timed_out(&self.key),
        }
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    pub unsafe fn park(&self) {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.park(&self.key),
            Backend::WaitAddress(ref x) => x.park(&self.key),
        }
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    pub unsafe fn park_until(&self, timeout: Instant) -> bool {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.park_until(&self.key, timeout),
            Backend::WaitAddress(ref x) => x.park_until(&self.key, timeout),
        }
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    pub unsafe fn unpark_lock(&self) -> UnparkHandle {
        match *self.backend {
            Backend::KeyedEvent(ref x) => UnparkHandle::KeyedEvent(x.unpark_lock(&self.key)),
            Backend::WaitAddress(ref x) => UnparkHandle::WaitAddress(x.unpark_lock(&self.key)),
        }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub enum UnparkHandle {
    KeyedEvent(keyed_event::UnparkHandle),
    WaitAddress(waitaddress::UnparkHandle),
}

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    pub unsafe fn unpark(self) {
        match self {
            UnparkHandle::KeyedEvent(x) => x.unpark(),
            UnparkHandle::WaitAddress(x) => x.unpark(),
        }
    }
}
<commit_msg>Use AtomicPtr instead of AtomicUsize for pointers<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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::ptr;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use std::time::Instant;

mod keyed_event;
mod waitaddress;

enum Backend {
    KeyedEvent(keyed_event::KeyedEvent),
    WaitAddress(waitaddress::WaitAddress),
}

impl Backend {
    unsafe fn get() -> &'static Backend {
        static BACKEND: AtomicPtr<Backend> = AtomicPtr::new(ptr::null_mut());

        // Fast path: use the existing object
        let backend_ptr = BACKEND.load(Ordering::Acquire);
        if !backend_ptr.is_null() {
            return &*backend_ptr;
        };

        // Try to create a new Backend
        let backend;
        if let Some(waitaddress) = waitaddress::WaitAddress::create() {
            backend = Backend::WaitAddress(waitaddress);
        } else if let Some(keyed_event) = keyed_event::KeyedEvent::create() {
            backend = Backend::KeyedEvent(keyed_event);
        } else {
            panic!(
                "parking_lot requires either NT Keyed Events (WinXP+) or \
                 WaitOnAddress/WakeByAddress (Win8+)"
            );
        }

        // Try to create a new object
        let backend_ptr = Box::into_raw(Box::new(backend));
        match BACKEND.compare_exchange(
            ptr::null_mut(),
            backend_ptr,
            Ordering::Release,
            Ordering::Relaxed,
        ) {
            Ok(_) => &*backend_ptr,
            Err(global_backend_ptr) => {
                // We lost the race, free our object and return the global one
                Box::from_raw(backend_ptr);
                &*global_backend_ptr
            }
        }
    }
}

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    key: AtomicUsize,
    backend: &'static Backend,
}

impl ThreadParker {
    pub fn new() -> ThreadParker {
        // Initialize the backend here to ensure we don't get any panics
        // later on, which could leave synchronization primitives in a broken
        // state.
        ThreadParker {
            key: AtomicUsize::new(0),
            backend: unsafe { Backend::get() },
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    pub unsafe fn prepare_park(&self) {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.prepare_park(&self.key),
            Backend::WaitAddress(ref x) => x.prepare_park(&self.key),
        }
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    pub unsafe fn timed_out(&self) -> bool {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.timed_out(&self.key),
            Backend::WaitAddress(ref x) => x.timed_out(&self.key),
        }
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    pub unsafe fn park(&self) {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.park(&self.key),
            Backend::WaitAddress(ref x) => x.park(&self.key),
        }
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    pub unsafe fn park_until(&self, timeout: Instant) -> bool {
        match *self.backend {
            Backend::KeyedEvent(ref x) => x.park_until(&self.key, timeout),
            Backend::WaitAddress(ref x) => x.park_until(&self.key, timeout),
        }
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    pub unsafe fn unpark_lock(&self) -> UnparkHandle {
        match *self.backend {
            Backend::KeyedEvent(ref x) => UnparkHandle::KeyedEvent(x.unpark_lock(&self.key)),
            Backend::WaitAddress(ref x) => UnparkHandle::WaitAddress(x.unpark_lock(&self.key)),
        }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub enum UnparkHandle {
    KeyedEvent(keyed_event::UnparkHandle),
    WaitAddress(waitaddress::UnparkHandle),
}

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    pub unsafe fn unpark(self) {
        match self {
            UnparkHandle::KeyedEvent(x) => x.unpark(),
            UnparkHandle::WaitAddress(x) => x.unpark(),
        }
    }
}
<|endoftext|>


<commit_before>//! Stand-alone WebAssembly to Cranelift IR translator.
//!
//! This module defines the `FuncTranslator` type which can translate a single WebAssembly
//! function to Cranelift IR guided by a `FuncEnvironment` which provides information about the
//! WebAssembly module and the runtime environment.

use crate::code_translator::translate_operator;
use crate::environ::{FuncEnvironment, ReturnMode, WasmResult};
use crate::state::TranslationState;
use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::{self, Ebb, InstBuilder};
use cranelift_codegen::timing;
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
use log::info;
use wasmparser::{self, BinaryReader};

/// WebAssembly to Cranelift IR function translator.
///
/// A `FuncTranslator` is used to translate a binary WebAssembly function into Cranelift IR guided
/// by a `FuncEnvironment` object. A single translator instance can be reused to translate multiple
/// functions which will reduce heap allocation traffic.
pub struct FuncTranslator {
    func_ctx: FunctionBuilderContext,
    state: TranslationState,
}

impl FuncTranslator {
    /// Create a new translator.
    pub fn new() -> Self {
        Self {
            func_ctx: FunctionBuilderContext::new(),
            state: TranslationState::new(),
        }
    }

    /// Translate a binary WebAssembly function.
    ///
    /// The `code` slice contains the binary WebAssembly *function code* as it appears in the code
    /// section of a WebAssembly module, not including the initial size of the function code. The
    /// slice is expected to contain two parts:
    ///
    /// - The declaration of *locals*, and
    /// - The function *body* as an expression.
    ///
    /// See [the WebAssembly specification][wasm].
    ///
    /// [wasm]: https://webassembly.github.io/spec/binary/modules.html#code-section
    ///
    /// The Cranelift IR function `func` should be completely empty except for the `func.signature`
    /// and `func.name` fields. The signature may contain special-purpose arguments which are not
    /// regarded as WebAssembly local variables. Any signature arguments marked as
    /// `ArgumentPurpose::Normal` are made accessible as WebAssembly local variables.
    ///
    pub fn translate<FE: FuncEnvironment + ?Sized>(
        &mut self,
        code: &[u8],
        code_offset: usize,
        func: &mut ir::Function,
        environ: &mut FE,
    ) -> WasmResult<()> {
        self.translate_from_reader(
            BinaryReader::new_with_offset(code, code_offset),
            func,
            environ,
        )
    }

    /// Translate a binary WebAssembly function from a `BinaryReader`.
    pub fn translate_from_reader<FE: FuncEnvironment + ?Sized>(
        &mut self,
        mut reader: BinaryReader,
        func: &mut ir::Function,
        environ: &mut FE,
    ) -> WasmResult<()> {
        let _tt = timing::wasm_translate_function();
        info!(
            "translate({} bytes, {}{})",
            reader.bytes_remaining(),
            func.name,
            func.signature
        );
        debug_assert_eq!(func.dfg.num_ebbs(), 0, "Function must be empty");
        debug_assert_eq!(func.dfg.num_insts(), 0, "Function must be empty");

        // This clears the `FunctionBuilderContext`.
        let mut builder = FunctionBuilder::new(func, &mut self.func_ctx);
        let entry_block = builder.create_ebb();
        builder.append_ebb_params_for_function_params(entry_block);
        builder.switch_to_block(entry_block); // This also creates values for the arguments.
        builder.seal_block(entry_block);
        // Make sure the entry block is inserted in the layout before we make any callbacks to
        // `environ`. The callback functions may need to insert things in the entry block.
        builder.ensure_inserted_ebb();

        let num_params = declare_wasm_parameters(&mut builder, entry_block);

        // Set up the translation state with a single pushed control block representing the whole
        // function and its return values.
        let exit_block = builder.create_ebb();
        builder.append_ebb_params_for_function_returns(exit_block);
        self.state.initialize(&builder.func.signature, exit_block);

        parse_local_decls(&mut reader, &mut builder, num_params)?;
        parse_function_body(reader, &mut builder, &mut self.state, environ)?;

        builder.finalize();
        Ok(())
    }
}

/// Declare local variables for the signature parameters that correspond to WebAssembly locals.
///
/// Return the number of local variables declared.
fn declare_wasm_parameters(builder: &mut FunctionBuilder, entry_block: Ebb) -> usize {
    let sig_len = builder.func.signature.params.len();
    let mut next_local = 0;
    for i in 0..sig_len {
        let param_type = builder.func.signature.params[i];
        // There may be additional special-purpose parameters following the normal WebAssembly
        // signature parameters. For example, a `vmctx` pointer.
        if param_type.purpose == ir::ArgumentPurpose::Normal {
            // This is a normal WebAssembly signature parameter, so create a local for it.
            let local = Variable::new(next_local);
            builder.declare_var(local, param_type.value_type);
            next_local += 1;

            let param_value = builder.ebb_params(entry_block)[i];
            builder.def_var(local, param_value);
        }
    }

    next_local
}

/// Parse the local variable declarations that precede the function body.
///
/// Declare local variables, starting from `num_params`.
fn parse_local_decls(
    reader: &mut BinaryReader,
    builder: &mut FunctionBuilder,
    num_params: usize,
) -> WasmResult<()> {
    let mut next_local = num_params;
    let local_count = reader.read_local_count()?;

    let mut locals_total = 0;
    for _ in 0..local_count {
        builder.set_srcloc(cur_srcloc(reader));
        let (count, ty) = reader.read_local_decl(&mut locals_total)?;
        declare_locals(builder, count, ty, &mut next_local);
    }

    Ok(())
}

/// Declare `count` local variables of the same type, starting from `next_local`.
///
/// Fail of too many locals are declared in the function, or if the type is not valid for a local.
fn declare_locals(
    builder: &mut FunctionBuilder,
    count: u32,
    wasm_type: wasmparser::Type,
    next_local: &mut usize,
) {
    // All locals are initialized to 0.
    use wasmparser::Type::*;
    let zeroval = match wasm_type {
        I32 => builder.ins().iconst(ir::types::I32, 0),
        I64 => builder.ins().iconst(ir::types::I64, 0),
        F32 => builder.ins().f32const(ir::immediates::Ieee32::with_bits(0)),
        F64 => builder.ins().f64const(ir::immediates::Ieee64::with_bits(0)),
        _ => panic!("invalid local type"),
    };

    let ty = builder.func.dfg.value_type(zeroval);
    for _ in 0..count {
        let local = Variable::new(*next_local);
        builder.declare_var(local, ty);
        builder.def_var(local, zeroval);
        *next_local += 1;
    }
}

/// Parse the function body in `reader`.
///
/// This assumes that the local variable declarations have already been parsed and function
/// arguments and locals are declared in the builder.
fn parse_function_body<FE: FuncEnvironment + ?Sized>(
    mut reader: BinaryReader,
    builder: &mut FunctionBuilder,
    state: &mut TranslationState,
    environ: &mut FE,
) -> WasmResult<()> {
    // The control stack is initialized with a single block representing the whole function.
    debug_assert_eq!(state.control_stack.len(), 1, "State not initialized");

    // Keep going until the final `End` operator which pops the outermost block.
    while !state.control_stack.is_empty() {
        builder.set_srcloc(cur_srcloc(&reader));
        let op = reader.read_operator()?;
        translate_operator(op, builder, state, environ)?;
    }

    // The final `End` operator left us in the exit block where we need to manually add a return
    // instruction.
    //
    // If the exit block is unreachable, it may not have the correct arguments, so we would
    // generate a return instruction that doesn't match the signature.
    if state.reachable {
        debug_assert!(builder.is_pristine());
        if !builder.is_unreachable() {
            match environ.return_mode() {
                ReturnMode::NormalReturns => builder.ins().return_(&state.stack),
                ReturnMode::FallthroughReturn => builder.ins().fallthrough_return(&state.stack),
            };
        }
    }

    // Discard any remaining values on the stack. Either we just returned them,
    // or the end of the function is unreachable.
    state.stack.clear();

    debug_assert!(reader.eof());

    Ok(())
}

/// Get the current source location from a reader.
fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc {
    // We record source locations as byte code offsets relative to the beginning of the file.
    // This will wrap around if byte code is larger than 4 GB.
    ir::SourceLoc::new(reader.original_position() as u32)
}

#[cfg(test)]
mod tests {
    use super::{FuncTranslator, ReturnMode};
    use crate::environ::DummyEnvironment;
    use cranelift_codegen::ir::types::I32;
    use cranelift_codegen::{ir, isa, settings, Context};
    use log::debug;
    use target_lexicon::PointerWidth;

    #[test]
    fn small1() {
        // Implicit return.
        //
        // (func $small1 (param i32) (result i32)
        //     (i32.add (get_local 0) (i32.const 1))
        // )
        const BODY: [u8; 7] = [
            0x00, // local decl count
            0x20, 0x00, // get_local 0
            0x41, 0x01, // i32.const 1
            0x6a, // i32.add
            0x0b, // end
        ];

        let mut trans = FuncTranslator::new();
        let flags = settings::Flags::new(settings::builder());
        let runtime = DummyEnvironment::new(
            isa::TargetFrontendConfig {
                default_call_conv: isa::CallConv::Fast,
                pointer_width: PointerWidth::U64,
            },
            ReturnMode::NormalReturns,
        );

        let mut ctx = Context::new();

        ctx.func.name = ir::ExternalName::testcase("small1");
        ctx.func.signature.params.push(ir::AbiParam::new(I32));
        ctx.func.signature.returns.push(ir::AbiParam::new(I32));

        trans
            .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
            .unwrap();
        debug!("{}", ctx.func.display(None));
        ctx.verify(&flags).unwrap();
    }

    #[test]
    fn small2() {
        // Same as above, but with an explicit return instruction.
        //
        // (func $small2 (param i32) (result i32)
        //     (return (i32.add (get_local 0) (i32.const 1)))
        // )
        const BODY: [u8; 8] = [
            0x00, // local decl count
            0x20, 0x00, // get_local 0
            0x41, 0x01, // i32.const 1
            0x6a, // i32.add
            0x0f, // return
            0x0b, // end
        ];

        let mut trans = FuncTranslator::new();
        let flags = settings::Flags::new(settings::builder());
        let runtime = DummyEnvironment::new(
            isa::TargetFrontendConfig {
                default_call_conv: isa::CallConv::Fast,
                pointer_width: PointerWidth::U64,
            },
            ReturnMode::NormalReturns,
        );
        let mut ctx = Context::new();

        ctx.func.name = ir::ExternalName::testcase("small2");
        ctx.func.signature.params.push(ir::AbiParam::new(I32));
        ctx.func.signature.returns.push(ir::AbiParam::new(I32));

        trans
            .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
            .unwrap();
        debug!("{}", ctx.func.display(None));
        ctx.verify(&flags).unwrap();
    }

    #[test]
    fn infloop() {
        // An infinite loop, no return instructions.
        //
        // (func $infloop (result i32)
        //     (local i32)
        //     (loop (result i32)
        //         (i32.add (get_local 0) (i32.const 1))
        //         (set_local 0)
        //         (br 0)
        //     )
        // )
        const BODY: [u8; 16] = [
            0x01, // 1 local decl.
            0x01, 0x7f, // 1 i32 local.
            0x03, 0x7f, // loop i32
            0x20, 0x00, // get_local 0
            0x41, 0x01, // i32.const 0
            0x6a, // i32.add
            0x21, 0x00, // set_local 0
            0x0c, 0x00, // br 0
            0x0b, // end
            0x0b, // end
        ];

        let mut trans = FuncTranslator::new();
        let flags = settings::Flags::new(settings::builder());
        let runtime = DummyEnvironment::new(
            isa::TargetFrontendConfig {
                default_call_conv: isa::CallConv::Fast,
                pointer_width: PointerWidth::U64,
            },
            ReturnMode::NormalReturns,
        );
        let mut ctx = Context::new();

        ctx.func.name = ir::ExternalName::testcase("infloop");
        ctx.func.signature.returns.push(ir::AbiParam::new(I32));

        trans
            .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
            .unwrap();
        debug!("{}", ctx.func.display(None));
        ctx.verify(&flags).unwrap();
    }
}
<commit_msg>[wasm] Raise an error instead of panicking for unhandled function local types;<commit_after>//! Stand-alone WebAssembly to Cranelift IR translator.
//!
//! This module defines the `FuncTranslator` type which can translate a single WebAssembly
//! function to Cranelift IR guided by a `FuncEnvironment` which provides information about the
//! WebAssembly module and the runtime environment.

use crate::code_translator::translate_operator;
use crate::environ::{FuncEnvironment, ReturnMode, WasmError, WasmResult};
use crate::state::TranslationState;
use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::{self, Ebb, InstBuilder};
use cranelift_codegen::timing;
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
use log::info;
use wasmparser::{self, BinaryReader};

/// WebAssembly to Cranelift IR function translator.
///
/// A `FuncTranslator` is used to translate a binary WebAssembly function into Cranelift IR guided
/// by a `FuncEnvironment` object. A single translator instance can be reused to translate multiple
/// functions which will reduce heap allocation traffic.
pub struct FuncTranslator {
    func_ctx: FunctionBuilderContext,
    state: TranslationState,
}

impl FuncTranslator {
    /// Create a new translator.
    pub fn new() -> Self {
        Self {
            func_ctx: FunctionBuilderContext::new(),
            state: TranslationState::new(),
        }
    }

    /// Translate a binary WebAssembly function.
    ///
    /// The `code` slice contains the binary WebAssembly *function code* as it appears in the code
    /// section of a WebAssembly module, not including the initial size of the function code. The
    /// slice is expected to contain two parts:
    ///
    /// - The declaration of *locals*, and
    /// - The function *body* as an expression.
    ///
    /// See [the WebAssembly specification][wasm].
    ///
    /// [wasm]: https://webassembly.github.io/spec/binary/modules.html#code-section
    ///
    /// The Cranelift IR function `func` should be completely empty except for the `func.signature`
    /// and `func.name` fields. The signature may contain special-purpose arguments which are not
    /// regarded as WebAssembly local variables. Any signature arguments marked as
    /// `ArgumentPurpose::Normal` are made accessible as WebAssembly local variables.
    ///
    pub fn translate<FE: FuncEnvironment + ?Sized>(
        &mut self,
        code: &[u8],
        code_offset: usize,
        func: &mut ir::Function,
        environ: &mut FE,
    ) -> WasmResult<()> {
        self.translate_from_reader(
            BinaryReader::new_with_offset(code, code_offset),
            func,
            environ,
        )
    }

    /// Translate a binary WebAssembly function from a `BinaryReader`.
    pub fn translate_from_reader<FE: FuncEnvironment + ?Sized>(
        &mut self,
        mut reader: BinaryReader,
        func: &mut ir::Function,
        environ: &mut FE,
    ) -> WasmResult<()> {
        let _tt = timing::wasm_translate_function();
        info!(
            "translate({} bytes, {}{})",
            reader.bytes_remaining(),
            func.name,
            func.signature
        );
        debug_assert_eq!(func.dfg.num_ebbs(), 0, "Function must be empty");
        debug_assert_eq!(func.dfg.num_insts(), 0, "Function must be empty");

        // This clears the `FunctionBuilderContext`.
        let mut builder = FunctionBuilder::new(func, &mut self.func_ctx);
        let entry_block = builder.create_ebb();
        builder.append_ebb_params_for_function_params(entry_block);
        builder.switch_to_block(entry_block); // This also creates values for the arguments.
        builder.seal_block(entry_block);
        // Make sure the entry block is inserted in the layout before we make any callbacks to
        // `environ`. The callback functions may need to insert things in the entry block.
        builder.ensure_inserted_ebb();

        let num_params = declare_wasm_parameters(&mut builder, entry_block);

        // Set up the translation state with a single pushed control block representing the whole
        // function and its return values.
        let exit_block = builder.create_ebb();
        builder.append_ebb_params_for_function_returns(exit_block);
        self.state.initialize(&builder.func.signature, exit_block);

        parse_local_decls(&mut reader, &mut builder, num_params)?;
        parse_function_body(reader, &mut builder, &mut self.state, environ)?;

        builder.finalize();
        Ok(())
    }
}

/// Declare local variables for the signature parameters that correspond to WebAssembly locals.
///
/// Return the number of local variables declared.
fn declare_wasm_parameters(builder: &mut FunctionBuilder, entry_block: Ebb) -> usize {
    let sig_len = builder.func.signature.params.len();
    let mut next_local = 0;
    for i in 0..sig_len {
        let param_type = builder.func.signature.params[i];
        // There may be additional special-purpose parameters following the normal WebAssembly
        // signature parameters. For example, a `vmctx` pointer.
        if param_type.purpose == ir::ArgumentPurpose::Normal {
            // This is a normal WebAssembly signature parameter, so create a local for it.
            let local = Variable::new(next_local);
            builder.declare_var(local, param_type.value_type);
            next_local += 1;

            let param_value = builder.ebb_params(entry_block)[i];
            builder.def_var(local, param_value);
        }
    }

    next_local
}

/// Parse the local variable declarations that precede the function body.
///
/// Declare local variables, starting from `num_params`.
fn parse_local_decls(
    reader: &mut BinaryReader,
    builder: &mut FunctionBuilder,
    num_params: usize,
) -> WasmResult<()> {
    let mut next_local = num_params;
    let local_count = reader.read_local_count()?;

    let mut locals_total = 0;
    for _ in 0..local_count {
        builder.set_srcloc(cur_srcloc(reader));
        let (count, ty) = reader.read_local_decl(&mut locals_total)?;
        declare_locals(builder, count, ty, &mut next_local)?;
    }

    Ok(())
}

/// Declare `count` local variables of the same type, starting from `next_local`.
///
/// Fail of too many locals are declared in the function, or if the type is not valid for a local.
fn declare_locals(
    builder: &mut FunctionBuilder,
    count: u32,
    wasm_type: wasmparser::Type,
    next_local: &mut usize,
) -> WasmResult<()> {
    // All locals are initialized to 0.
    use wasmparser::Type::*;
    let zeroval = match wasm_type {
        I32 => builder.ins().iconst(ir::types::I32, 0),
        I64 => builder.ins().iconst(ir::types::I64, 0),
        F32 => builder.ins().f32const(ir::immediates::Ieee32::with_bits(0)),
        F64 => builder.ins().f64const(ir::immediates::Ieee64::with_bits(0)),
        _ => return Err(WasmError::Unsupported("unsupported local type")),
    };

    let ty = builder.func.dfg.value_type(zeroval);
    for _ in 0..count {
        let local = Variable::new(*next_local);
        builder.declare_var(local, ty);
        builder.def_var(local, zeroval);
        *next_local += 1;
    }
    Ok(())
}

/// Parse the function body in `reader`.
///
/// This assumes that the local variable declarations have already been parsed and function
/// arguments and locals are declared in the builder.
fn parse_function_body<FE: FuncEnvironment + ?Sized>(
    mut reader: BinaryReader,
    builder: &mut FunctionBuilder,
    state: &mut TranslationState,
    environ: &mut FE,
) -> WasmResult<()> {
    // The control stack is initialized with a single block representing the whole function.
    debug_assert_eq!(state.control_stack.len(), 1, "State not initialized");

    // Keep going until the final `End` operator which pops the outermost block.
    while !state.control_stack.is_empty() {
        builder.set_srcloc(cur_srcloc(&reader));
        let op = reader.read_operator()?;
        translate_operator(op, builder, state, environ)?;
    }

    // The final `End` operator left us in the exit block where we need to manually add a return
    // instruction.
    //
    // If the exit block is unreachable, it may not have the correct arguments, so we would
    // generate a return instruction that doesn't match the signature.
    if state.reachable {
        debug_assert!(builder.is_pristine());
        if !builder.is_unreachable() {
            match environ.return_mode() {
                ReturnMode::NormalReturns => builder.ins().return_(&state.stack),
                ReturnMode::FallthroughReturn => builder.ins().fallthrough_return(&state.stack),
            };
        }
    }

    // Discard any remaining values on the stack. Either we just returned them,
    // or the end of the function is unreachable.
    state.stack.clear();

    debug_assert!(reader.eof());

    Ok(())
}

/// Get the current source location from a reader.
fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc {
    // We record source locations as byte code offsets relative to the beginning of the file.
    // This will wrap around if byte code is larger than 4 GB.
    ir::SourceLoc::new(reader.original_position() as u32)
}

#[cfg(test)]
mod tests {
    use super::{FuncTranslator, ReturnMode};
    use crate::environ::DummyEnvironment;
    use cranelift_codegen::ir::types::I32;
    use cranelift_codegen::{ir, isa, settings, Context};
    use log::debug;
    use target_lexicon::PointerWidth;

    #[test]
    fn small1() {
        // Implicit return.
        //
        // (func $small1 (param i32) (result i32)
        //     (i32.add (get_local 0) (i32.const 1))
        // )
        const BODY: [u8; 7] = [
            0x00, // local decl count
            0x20, 0x00, // get_local 0
            0x41, 0x01, // i32.const 1
            0x6a, // i32.add
            0x0b, // end
        ];

        let mut trans = FuncTranslator::new();
        let flags = settings::Flags::new(settings::builder());
        let runtime = DummyEnvironment::new(
            isa::TargetFrontendConfig {
                default_call_conv: isa::CallConv::Fast,
                pointer_width: PointerWidth::U64,
            },
            ReturnMode::NormalReturns,
        );

        let mut ctx = Context::new();

        ctx.func.name = ir::ExternalName::testcase("small1");
        ctx.func.signature.params.push(ir::AbiParam::new(I32));
        ctx.func.signature.returns.push(ir::AbiParam::new(I32));

        trans
            .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
            .unwrap();
        debug!("{}", ctx.func.display(None));
        ctx.verify(&flags).unwrap();
    }

    #[test]
    fn small2() {
        // Same as above, but with an explicit return instruction.
        //
        // (func $small2 (param i32) (result i32)
        //     (return (i32.add (get_local 0) (i32.const 1)))
        // )
        const BODY: [u8; 8] = [
            0x00, // local decl count
            0x20, 0x00, // get_local 0
            0x41, 0x01, // i32.const 1
            0x6a, // i32.add
            0x0f, // return
            0x0b, // end
        ];

        let mut trans = FuncTranslator::new();
        let flags = settings::Flags::new(settings::builder());
        let runtime = DummyEnvironment::new(
            isa::TargetFrontendConfig {
                default_call_conv: isa::CallConv::Fast,
                pointer_width: PointerWidth::U64,
            },
            ReturnMode::NormalReturns,
        );
        let mut ctx = Context::new();

        ctx.func.name = ir::ExternalName::testcase("small2");
        ctx.func.signature.params.push(ir::AbiParam::new(I32));
        ctx.func.signature.returns.push(ir::AbiParam::new(I32));

        trans
            .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
            .unwrap();
        debug!("{}", ctx.func.display(None));
        ctx.verify(&flags).unwrap();
    }

    #[test]
    fn infloop() {
        // An infinite loop, no return instructions.
        //
        // (func $infloop (result i32)
        //     (local i32)
        //     (loop (result i32)
        //         (i32.add (get_local 0) (i32.const 1))
        //         (set_local 0)
        //         (br 0)
        //     )
        // )
        const BODY: [u8; 16] = [
            0x01, // 1 local decl.
            0x01, 0x7f, // 1 i32 local.
            0x03, 0x7f, // loop i32
            0x20, 0x00, // get_local 0
            0x41, 0x01, // i32.const 0
            0x6a, // i32.add
            0x21, 0x00, // set_local 0
            0x0c, 0x00, // br 0
            0x0b, // end
            0x0b, // end
        ];

        let mut trans = FuncTranslator::new();
        let flags = settings::Flags::new(settings::builder());
        let runtime = DummyEnvironment::new(
            isa::TargetFrontendConfig {
                default_call_conv: isa::CallConv::Fast,
                pointer_width: PointerWidth::U64,
            },
            ReturnMode::NormalReturns,
        );
        let mut ctx = Context::new();

        ctx.func.name = ir::ExternalName::testcase("infloop");
        ctx.func.signature.returns.push(ir::AbiParam::new(I32));

        trans
            .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env())
            .unwrap();
        debug!("{}", ctx.func.display(None));
        ctx.verify(&flags).unwrap();
    }
}
<|endoftext|>


<commit_before>macro_rules! tx_deref {
    ($ty:ty) => {
        impl ::std::ops::Deref for $ty {
            type Target = Tx;

            #[inline(always)]
            fn deref(&self) -> &Tx {
                &self.base
            }
        }
    };
}

macro_rules! tx_sign {
    ($ty:ty) => {
        impl SignTx for $ty {
            #[inline]
            fn sign(&self, key_pair: &KeyPair) -> SigPair {
                let mut buf = Vec::new();
                self.encode(&mut buf);
                key_pair.sign(&buf)
            }

            #[inline]
            fn append_sign(&mut self, key_pair: &KeyPair) {
                let pair = self.sign(key_pair);
                self.base.signature_pairs.push(pair);
            }
        }
    }
}
<commit_msg>Specify default capacity when encoding during signing<commit_after>macro_rules! tx_deref {
    ($ty:ty) => {
        impl ::std::ops::Deref for $ty {
            type Target = Tx;

            #[inline(always)]
            fn deref(&self) -> &Tx {
                &self.base
            }
        }
    };
}

macro_rules! tx_sign {
    ($ty:ty) => {
        impl SignTx for $ty {
            #[inline]
            fn sign(&self, key_pair: &KeyPair) -> SigPair {
                let mut buf = Vec::with_capacity(4096);
                self.encode(&mut buf);
                key_pair.sign(&buf)
            }

            #[inline]
            fn append_sign(&mut self, key_pair: &KeyPair) {
                let pair = self.sign(key_pair);
                self.base.signature_pairs.push(pair);
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// 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 nom::{ IResult, multispace, not_line_ending } ;

use super::base::* ;
use super::* ;
use term::{
  Sym, StsResult, Factory, ParseSts2
} ;

named!{
  pub comment,
  chain!(
    opt!(multispace) ~
    char!(';') ~
    many0!(not_line_ending),
    || & []
  )
}

named!{
  space_comment<()>,
  map!(
    many0!(
      alt!(
        comment | multispace
      )
    ),
    |_| ()
  )
}

named!{
  pub sig_parser<Sig>,
  chain!(
    char!('(') ~
    opt!(space_comment) ~
    args: separated_list!(
      opt!(space_comment),
      Factory::parse_type
    ) ~
    opt!(space_comment) ~
    char!(')'),
    || Sig::mk(args)
  )
}

pub fn sym_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Sym> {
  f.parse_ident(bytes)
}

pub fn args_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Args> {
  map!(
    bytes,
    separated_list!(
      opt!(space_comment),
      delimited!(
        char!('('),
        chain!(
          opt!(space_comment) ~
          sym: apply!(sym_parser, f) ~
          space_comment ~
          typ: call!(Factory::parse_type) ~
          opt!(space_comment),
          || (sym, typ)
        ),
        char!(')')
      )
    ),
    |args| Args::mk(args)
  )
}

pub fn state_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], State> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-state") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    args: apply!(args_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || State::mk(sym, args)
  )
}

pub fn fun_dec_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], FunDec> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("declare-fun") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    sig: sig_parser ~
    opt!(space_comment) ~
    typ: call!(Factory::parse_type) ~
    opt!(space_comment) ~
    char!(')'),
    || FunDec::mk(sym, sig, typ)
  )
}

pub fn term_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], StsResult> {
  f.parse_expr(bytes)
}

pub fn body_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Body> {
  map!(
    bytes,
    apply!(term_parser, f),
    |term| Body::mk(term)
  )
}

pub fn fun_def_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], FunDef> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-fun") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    args: apply!(args_parser, f) ~
    opt!(space_comment) ~
    typ: call!(Factory::parse_type) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || FunDef::mk(sym, args, typ, body)
  )
}

pub fn pred_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Pred> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-pred") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Pred::mk(sym, state, body)
  )
}

pub fn init_def_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Init> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-init") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Init::mk(sym, state, body)
  )
}

pub fn trans_def_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Trans> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-trans") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Trans::mk(sym, state, body)
  )
}

pub fn sys_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Sys> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-system") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    space_comment ~
    init: apply!(sym_parser, f) ~
    space_comment ~
    trans: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Sys::mk(sym, state, init, trans)
  )
}

pub fn item_parser<'a>(
  bytes: & 'a [u8], c: & mut Context
) -> IResult<'a, & 'a [u8], Result<(), Error>> {
  use super::base::Item::* ;
  map!(
    bytes,
    preceded!(
      opt!(multispace),
      alt!(
        map!( apply!(state_parser, c.factory()), |out| St(out) ) |
        map!( apply!(fun_dec_parser, c.factory()), |out| FDc(out) ) |
        map!( apply!(fun_def_parser, c.factory()), |out| FDf(out) ) |
        map!( apply!(pred_parser, c.factory()), |out| P(out) ) |
        map!( apply!(init_def_parser, c.factory()), |out| I(out) ) |
        map!( apply!(trans_def_parser, c.factory()), |out| T(out) ) |
        map!( apply!(sys_parser, c.factory()), |out| S(out) )
      )
    ),
    |item| c.add(item)
  )
}

pub fn check_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], (Sym,Vec<Sym>)> {
  chain!(
    bytes,
    opt!(space_comment) ~
    char!('(') ~
    opt!(space_comment) ~
    tag!("check") ~
    space_comment ~
    sys: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    props: delimited!(
      char!('('),
      delimited!(
        opt!(space_comment),
        separated_list!(
          space_comment,
          apply!(sym_parser, f)
        ),
        opt!(space_comment)
      ),
      char!(')')
    ) ~
    opt!(space_comment) ~
    char!(')'),
    || (sys, props)
  )
}

named!{
  pub exit_parser,
  preceded!(
    opt!(space_comment),
    delimited!(
      char!('('),
      delimited!(
        opt!(space_comment),
        tag!("exit"),
        opt!(space_comment)
      ),
      char!(')')
    )
  )
}<commit_msg>documentation for parsers<commit_after>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// 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 nom::{ IResult, multispace, not_line_ending } ;

use super::base::* ;
use super::* ;
use term::{
  Sym, StsResult, Factory, ParseSts2
} ;

/** Parses a multispace and a comment. */
named!{
  pub comment,
  chain!(
    opt!(multispace) ~
    char!(';') ~
    many0!(not_line_ending),
    || & []
  )
}

/** Parses a repetition of multispace/comment. */
named!{
  space_comment<()>,
  map!(
    many0!(
      alt!(
        comment | multispace
      )
    ),
    |_| ()
  )
}

/** Parses a signature. */
named!{
  sig_parser<Sig>,
  chain!(
    char!('(') ~
    opt!(space_comment) ~
    args: separated_list!(
      opt!(space_comment),
      Factory::parse_type
    ) ~
    opt!(space_comment) ~
    char!(')'),
    || Sig::mk(args)
  )
}

/** Parses a symbol. */
fn sym_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Sym> {
  f.parse_ident(bytes)
}

/** Parses some arguments. */
fn args_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Args> {
  map!(
    bytes,
    separated_list!(
      opt!(space_comment),
      delimited!(
        char!('('),
        chain!(
          opt!(space_comment) ~
          sym: apply!(sym_parser, f) ~
          space_comment ~
          typ: call!(Factory::parse_type) ~
          opt!(space_comment),
          || (sym, typ)
        ),
        char!(')')
      )
    ),
    |args| Args::mk(args)
  )
}

/** Parses a state declaration. */
fn state_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], State> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-state") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    args: apply!(args_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || State::mk(sym, args)
  )
}

/** Parses a function declaration. */
fn fun_dec_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], FunDec> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("declare-fun") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    sig: sig_parser ~
    opt!(space_comment) ~
    typ: call!(Factory::parse_type) ~
    opt!(space_comment) ~
    char!(')'),
    || FunDec::mk(sym, sig, typ)
  )
}

/** Parses a term. */
fn term_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], StsResult> {
  f.parse_expr(bytes)
}

/** Parses a body (term). */
fn body_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Body> {
  map!(
    bytes,
    apply!(term_parser, f),
    |term| Body::mk(term)
  )
}

/** Parses a function definition. */
fn fun_def_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], FunDef> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-fun") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    args: apply!(args_parser, f) ~
    opt!(space_comment) ~
    typ: call!(Factory::parse_type) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || FunDef::mk(sym, args, typ, body)
  )
}

/** Parses a predicate definition. */
fn pred_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Pred> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-pred") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Pred::mk(sym, state, body)
  )
}

/** Parses an init definition. */
fn init_def_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Init> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-init") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Init::mk(sym, state, body)
  )
}

/** Parses a trans definition. */
fn trans_def_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Trans> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-trans") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    body: apply!(body_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Trans::mk(sym, state, body)
  )
}

/** Parses a system definition. */
fn sys_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], Sys> {
  chain!(
    bytes,
    char!('(') ~
    opt!(space_comment) ~
    tag!("define-system") ~
    space_comment ~
    sym: apply!(sym_parser, f) ~
    space_comment ~
    state: apply!(sym_parser, f) ~
    space_comment ~
    init: apply!(sym_parser, f) ~
    space_comment ~
    trans: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    char!(')'),
    || Sys::mk(sym, state, init, trans)
  )
}

/** Parses an item. */
pub fn item_parser<'a>(
  bytes: & 'a [u8], c: & mut Context
) -> IResult<'a, & 'a [u8], Result<(), Error>> {
  use super::base::Item::* ;
  map!(
    bytes,
    preceded!(
      opt!(multispace),
      alt!(
        map!( apply!(state_parser, c.factory()), |out| St(out) ) |
        map!( apply!(fun_dec_parser, c.factory()), |out| FDc(out) ) |
        map!( apply!(fun_def_parser, c.factory()), |out| FDf(out) ) |
        map!( apply!(pred_parser, c.factory()), |out| P(out) ) |
        map!( apply!(init_def_parser, c.factory()), |out| I(out) ) |
        map!( apply!(trans_def_parser, c.factory()), |out| T(out) ) |
        map!( apply!(sys_parser, c.factory()), |out| S(out) )
      )
    ),
    |item| c.add(item)
  )
}

/** Parses a check. */
pub fn check_parser<'a>(
  bytes: & 'a [u8], f: & Factory
) -> IResult<'a, & 'a [u8], (Sym,Vec<Sym>)> {
  chain!(
    bytes,
    opt!(space_comment) ~
    char!('(') ~
    opt!(space_comment) ~
    tag!("check") ~
    space_comment ~
    sys: apply!(sym_parser, f) ~
    opt!(space_comment) ~
    props: delimited!(
      char!('('),
      delimited!(
        opt!(space_comment),
        separated_list!(
          space_comment,
          apply!(sym_parser, f)
        ),
        opt!(space_comment)
      ),
      char!(')')
    ) ~
    opt!(space_comment) ~
    char!(')'),
    || (sys, props)
  )
}

/** Parses exit. */
named!{
  pub exit_parser,
  preceded!(
    opt!(space_comment),
    delimited!(
      char!('('),
      delimited!(
        opt!(space_comment),
        tag!("exit"),
        opt!(space_comment)
      ),
      char!(')')
    )
  )
}<|endoftext|>


<commit_before>pub fn is_leap_year(x:i16) -> bool {
   let y = handle_centuries(x);

    let reminder = y % 4;
    if reminder==0{

     return   true;
    } else
    {
        println!("old");
        return false;
    }
}

fn handle_centuries(x:i16) ->i16{
    if x%100 == 0{
        x/100
    }else{
        x
    }
}<commit_msg>refactor leap year test<commit_after>pub fn is_leap_year(x:i16) -> bool {
   check_divisibility(x,4) && (
       !check_divisibility(x,100) || check_divisibility(x,400)
       )
}

fn check_divisibility(number:i16,divisor:i16) ->bool{
  number%divisor == 0
}<|endoftext|>


<commit_before>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;
mod util;

use rocksdb::{ColumnFamilyDescriptor, MergeOperands, Options, DB};
use util::DBPath;

#[test]
pub fn test_column_family() {
    let n = DBPath::new("_rust_rocksdb_cftest");

    // should be able to create column families
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_merge_operator("test operator", test_provided_merge, None);
        let db = DB::open(&opts, &n).unwrap();
        let opts = Options::default();
        match db.create_cf("cf1", &opts) {
            Ok(_db) => println!("cf1 created successfully"),
            Err(e) => {
                panic!("could not create column family: {}", e);
            }
        }
    }

    // should fail to open db without specifying same column families
    {
        let mut opts = Options::default();
        opts.set_merge_operator("test operator", test_provided_merge, None);
        match DB::open(&opts, &n) {
            Ok(_db) => panic!(
                "should not have opened DB successfully without \
                        specifying column
            families"
            ),
            Err(e) => assert!(e.to_string().starts_with(
                "Invalid argument: You have to open all \
                 column families."
            )),
        }
    }

    // should properly open db when specyfing all column families
    {
        let mut opts = Options::default();
        opts.set_merge_operator("test operator", test_provided_merge, None);
        match DB::open_cf(&opts, &n, &["cf1"]) {
            Ok(_db) => println!("successfully opened db with column family"),
            Err(e) => panic!("failed to open db with column family: {}", e),
        }
    }

    // should be able to list a cf
    {
        let opts = Options::default();
        let vec = DB::list_cf(&opts, &n);
        match vec {
            Ok(vec) => assert_eq!(vec, vec!["default", "cf1"]),
            Err(e) => panic!("failed to drop column family: {}", e),
        }
    }

    // TODO should be able to use writebatch ops with a cf
    {}
    // TODO should be able to iterate over a cf
    {}
    // should b able to drop a cf
    {
        let db = DB::open_cf(&Options::default(), &n, &["cf1"]).unwrap();
        match db.drop_cf("cf1") {
            Ok(_) => println!("cf1 successfully dropped."),
            Err(e) => panic!("failed to drop column family: {}", e),
        }
    }
}

#[test]
fn test_create_missing_column_family() {
    let n = DBPath::new("_rust_rocksdb_missing_cftest");

    // should be able to create new column families when opening a new database
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.create_missing_column_families(true);

        match DB::open_cf(&opts, &n, &["cf1"]) {
            Ok(_db) => println!("successfully created new column family"),
            Err(e) => panic!("failed to create new column family: {}", e),
        }
    }
}

#[test]
#[ignore]
fn test_merge_operator() {
    let n = DBPath::new("_rust_rocksdb_cftest_merge");
    // TODO should be able to write, read, merge, batch, and iterate over a cf
    {
        let mut opts = Options::default();
        opts.set_merge_operator("test operator", test_provided_merge, None);
        let db = match DB::open_cf(&opts, &n, &["cf1"]) {
            Ok(db) => {
                println!("successfully opened db with column family");
                db
            }
            Err(e) => panic!("failed to open db with column family: {}", e),
        };
        let cf1 = db.cf_handle("cf1").unwrap();
        assert!(db.put_cf(cf1, b"k1", b"v1").is_ok());
        assert!(db.get_cf(cf1, b"k1").unwrap().unwrap().to_utf8().unwrap() == "v1");
        let p = db.put_cf(cf1, b"k1", b"a");
        assert!(p.is_ok());
        db.merge_cf(cf1, b"k1", b"b").unwrap();
        db.merge_cf(cf1, b"k1", b"c").unwrap();
        db.merge_cf(cf1, b"k1", b"d").unwrap();
        db.merge_cf(cf1, b"k1", b"efg").unwrap();
        let m = db.merge_cf(cf1, b"k1", b"h");
        println!("m is {:?}", m);
        // TODO assert!(m.is_ok());
        match db.get(b"k1") {
            Ok(Some(value)) => match value.to_utf8() {
                Some(v) => println!("retrieved utf8 value: {}", v),
                None => println!("did not read valid utf-8 out of the db"),
            },
            Err(_) => println!("error reading value"),
            _ => panic!("value not present!"),
        }

        let _ = db.get_cf(cf1, b"k1");
        // TODO assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh");
        assert!(db.delete(b"k1").is_ok());
        assert!(db.get(b"k1").unwrap().is_none());
    }
}

fn test_provided_merge(
    _: &[u8],
    existing_val: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let nops = operands.size_hint().0;
    let mut result: Vec<u8> = Vec::with_capacity(nops);
    match existing_val {
        Some(v) => {
            for e in v {
                result.push(*e);
            }
        }
        None => (),
    }
    for op in operands {
        for e in op {
            result.push(*e);
        }
    }
    Some(result)
}

#[test]
pub fn test_column_family_with_options() {
    let n = DBPath::new("_rust_rocksdb_cf_with_optionstest");
    {
        let mut cfopts = Options::default();
        cfopts.set_max_write_buffer_number(16);
        let cf_descriptor = ColumnFamilyDescriptor::new("cf1", cfopts);

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.create_missing_column_families(true);

        let cfs = vec![cf_descriptor];
        match DB::open_cf_descriptors(&opts, &n, cfs) {
            Ok(_db) => println!("created db with column family descriptors succesfully"),
            Err(e) => {
                panic!(
                    "could not create new database with column family descriptors: {}",
                    e
                );
            }
        }
    }

    {
        let mut cfopts = Options::default();
        cfopts.set_max_write_buffer_number(16);
        let cf_descriptor = ColumnFamilyDescriptor::new("cf1", cfopts);

        let opts = Options::default();
        let cfs = vec![cf_descriptor];

        match DB::open_cf_descriptors(&opts, &n, cfs) {
            Ok(_db) => println!("succesfully re-opened database with column family descriptors"),
            Err(e) => {
                panic!(
                    "unable to re-open database with column family descriptors: {}",
                    e
                );
            }
        }
    }
}
<commit_msg>Fixing spelling typos...<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;
mod util;

use rocksdb::{ColumnFamilyDescriptor, MergeOperands, Options, DB};
use util::DBPath;

#[test]
pub fn test_column_family() {
    let n = DBPath::new("_rust_rocksdb_cftest");

    // should be able to create column families
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_merge_operator("test operator", test_provided_merge, None);
        let db = DB::open(&opts, &n).unwrap();
        let opts = Options::default();
        match db.create_cf("cf1", &opts) {
            Ok(_db) => println!("cf1 created successfully"),
            Err(e) => {
                panic!("could not create column family: {}", e);
            }
        }
    }

    // should fail to open db without specifying same column families
    {
        let mut opts = Options::default();
        opts.set_merge_operator("test operator", test_provided_merge, None);
        match DB::open(&opts, &n) {
            Ok(_db) => panic!(
                "should not have opened DB successfully without \
                        specifying column
            families"
            ),
            Err(e) => assert!(e.to_string().starts_with(
                "Invalid argument: You have to open all \
                 column families."
            )),
        }
    }

    // should properly open db when specyfing all column families
    {
        let mut opts = Options::default();
        opts.set_merge_operator("test operator", test_provided_merge, None);
        match DB::open_cf(&opts, &n, &["cf1"]) {
            Ok(_db) => println!("successfully opened db with column family"),
            Err(e) => panic!("failed to open db with column family: {}", e),
        }
    }

    // should be able to list a cf
    {
        let opts = Options::default();
        let vec = DB::list_cf(&opts, &n);
        match vec {
            Ok(vec) => assert_eq!(vec, vec!["default", "cf1"]),
            Err(e) => panic!("failed to drop column family: {}", e),
        }
    }

    // TODO should be able to use writebatch ops with a cf
    {}
    // TODO should be able to iterate over a cf
    {}
    // should b able to drop a cf
    {
        let db = DB::open_cf(&Options::default(), &n, &["cf1"]).unwrap();
        match db.drop_cf("cf1") {
            Ok(_) => println!("cf1 successfully dropped."),
            Err(e) => panic!("failed to drop column family: {}", e),
        }
    }
}

#[test]
fn test_create_missing_column_family() {
    let n = DBPath::new("_rust_rocksdb_missing_cftest");

    // should be able to create new column families when opening a new database
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.create_missing_column_families(true);

        match DB::open_cf(&opts, &n, &["cf1"]) {
            Ok(_db) => println!("successfully created new column family"),
            Err(e) => panic!("failed to create new column family: {}", e),
        }
    }
}

#[test]
#[ignore]
fn test_merge_operator() {
    let n = DBPath::new("_rust_rocksdb_cftest_merge");
    // TODO should be able to write, read, merge, batch, and iterate over a cf
    {
        let mut opts = Options::default();
        opts.set_merge_operator("test operator", test_provided_merge, None);
        let db = match DB::open_cf(&opts, &n, &["cf1"]) {
            Ok(db) => {
                println!("successfully opened db with column family");
                db
            }
            Err(e) => panic!("failed to open db with column family: {}", e),
        };
        let cf1 = db.cf_handle("cf1").unwrap();
        assert!(db.put_cf(cf1, b"k1", b"v1").is_ok());
        assert!(db.get_cf(cf1, b"k1").unwrap().unwrap().to_utf8().unwrap() == "v1");
        let p = db.put_cf(cf1, b"k1", b"a");
        assert!(p.is_ok());
        db.merge_cf(cf1, b"k1", b"b").unwrap();
        db.merge_cf(cf1, b"k1", b"c").unwrap();
        db.merge_cf(cf1, b"k1", b"d").unwrap();
        db.merge_cf(cf1, b"k1", b"efg").unwrap();
        let m = db.merge_cf(cf1, b"k1", b"h");
        println!("m is {:?}", m);
        // TODO assert!(m.is_ok());
        match db.get(b"k1") {
            Ok(Some(value)) => match value.to_utf8() {
                Some(v) => println!("retrieved utf8 value: {}", v),
                None => println!("did not read valid utf-8 out of the db"),
            },
            Err(_) => println!("error reading value"),
            _ => panic!("value not present!"),
        }

        let _ = db.get_cf(cf1, b"k1");
        // TODO assert!(r.unwrap().to_utf8().unwrap() == "abcdefgh");
        assert!(db.delete(b"k1").is_ok());
        assert!(db.get(b"k1").unwrap().is_none());
    }
}

fn test_provided_merge(
    _: &[u8],
    existing_val: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let nops = operands.size_hint().0;
    let mut result: Vec<u8> = Vec::with_capacity(nops);
    match existing_val {
        Some(v) => {
            for e in v {
                result.push(*e);
            }
        }
        None => (),
    }
    for op in operands {
        for e in op {
            result.push(*e);
        }
    }
    Some(result)
}

#[test]
pub fn test_column_family_with_options() {
    let n = DBPath::new("_rust_rocksdb_cf_with_optionstest");
    {
        let mut cfopts = Options::default();
        cfopts.set_max_write_buffer_number(16);
        let cf_descriptor = ColumnFamilyDescriptor::new("cf1", cfopts);

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.create_missing_column_families(true);

        let cfs = vec![cf_descriptor];
        match DB::open_cf_descriptors(&opts, &n, cfs) {
            Ok(_db) => println!("created db with column family descriptors successfully"),
            Err(e) => {
                panic!(
                    "could not create new database with column family descriptors: {}",
                    e
                );
            }
        }
    }

    {
        let mut cfopts = Options::default();
        cfopts.set_max_write_buffer_number(16);
        let cf_descriptor = ColumnFamilyDescriptor::new("cf1", cfopts);

        let opts = Options::default();
        let cfs = vec![cf_descriptor];

        match DB::open_cf_descriptors(&opts, &n, cfs) {
            Ok(_db) => println!("successfully re-opened database with column family descriptors"),
            Err(e) => {
                panic!(
                    "unable to re-open database with column family descriptors: {}",
                    e
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate regex;

#[cfg(test)]
mod tests {
    include!("../clap-test.rs");
    use clap;
    use clap::{App, Arg, SubCommand, AppSettings};

    fn setup_app_with_globals_and_subcommands<'a, 'b>() -> clap::App<'a, 'b> {
        let global_arg = Arg::with_name("GLOBAL_ARG")
            .long("global-arg")
            .help(
                "Specifies something needed by the subcommands",
            )
            .global(true)
            .takes_value(true);

        let double_sub_command = SubCommand::with_name("outer")
            .subcommand(SubCommand::with_name("inner"));

        App::new("myprog")
            .setting(AppSettings::PropagateGlobalValuesDown)
            .arg(global_arg)
            .subcommand(double_sub_command)
    }

    fn first_subcommand_can_access_global(arg_vector : Vec<&str>) {
        let matches = setup_app_with_globals_and_subcommands().get_matches_from(
            arg_vector
        );

        let sub_match = matches.subcommand_matches("outer").expect("could not access subcommand");

        assert_eq!(sub_match.value_of("GLOBAL_ARG").expect("subcommand could not access global arg"),
                    "some_value", "subcommand did not have expected value for global arg");

    }

    fn second_subcommand_can_access_global(arg_vector : Vec<&str>) {
        let matches = setup_app_with_globals_and_subcommands().get_matches_from(
            arg_vector
        );

        let sub_match = matches.subcommand_matches("outer").expect("could not access subcommand");
        let sub_sub_match = sub_match.subcommand_matches("inner").expect("could not access inner sub");

        assert_eq!(sub_sub_match.value_of("GLOBAL_ARG").expect("inner subcommand could not access global arg"),
                "some_value", "inner subcommand did not have expected value for global arg");
    }

    #[test]
    fn subcommand_can_access_global_arg_if_global_arg_is_first() {
        // currently passes
        first_subcommand_can_access_global(vec!["myprog", "--global-arg", "some_value", "outer", "inner"]);
    }

    #[test]
    fn subcommand_can_access_global_arg_if_global_arg_is_in_the_middle() {
        // currently passes
        first_subcommand_can_access_global(vec!["myprog", "outer",  "--global-arg", "some_value" ,"inner"]);
    }

    #[test]
    fn first_subcommand_can_access_global_arg_if_global_arg_is_last() {
        // currently fails - hypothesis - nothing propagates global args back up
        first_subcommand_can_access_global(vec!["myprog", "outer", "inner", "--global-arg", "some_value"]);
    }

    #[test]
    fn second_subcommand_can_access_global_arg_if_global_arg_is_first() {
        // currently passes
        second_subcommand_can_access_global(vec!["myprog", "--global-arg", "some_value", "outer", "inner"]);
    }

    #[test]
    fn second_subcommand_can_access_global_arg_if_global_arg_is_in_the_middle() {
        // currently fails - hypothesis: subcommands do not recursively propagate global args
        second_subcommand_can_access_global(vec!["myprog", "outer",  "--global-arg", "some_value" ,"inner"]);
    }

    #[test]
    fn second_subcommand_can_access_global_arg_if_global_arg_is_last() {
        // currently passes
        second_subcommand_can_access_global(vec!["myprog", "outer", "inner", "--global-arg", "some_value"]);
    }
}

<commit_msg>use global setting in test<commit_after>extern crate clap;
extern crate regex;

#[cfg(test)]
mod tests {
    include!("../clap-test.rs");
    use clap;
    use clap::{App, Arg, SubCommand, AppSettings};

    fn setup_app_with_globals_and_subcommands<'a, 'b>() -> clap::App<'a, 'b> {
        let global_arg = Arg::with_name("GLOBAL_ARG")
            .long("global-arg")
            .help(
                "Specifies something needed by the subcommands",
            )
            .global(true)
            .takes_value(true);

        let double_sub_command = SubCommand::with_name("outer")
            .setting(AppSettings::PropagateGlobalValuesDown)
            .subcommand(SubCommand::with_name("inner"));

        App::new("myprog")
            .global_setting(AppSettings::PropagateGlobalValuesDown)
            .arg(global_arg)
            .subcommand(double_sub_command)
    }

    fn first_subcommand_can_access_global(arg_vector : Vec<&str>) {
        let matches = setup_app_with_globals_and_subcommands().get_matches_from(
            arg_vector
        );

        let sub_match = matches.subcommand_matches("outer").expect("could not access subcommand");

        assert_eq!(sub_match.value_of("GLOBAL_ARG").expect("subcommand could not access global arg"),
                    "some_value", "subcommand did not have expected value for global arg");

    }

    fn second_subcommand_can_access_global(arg_vector : Vec<&str>) {
        let matches = setup_app_with_globals_and_subcommands().get_matches_from(
            arg_vector
        );

        let sub_match = matches.subcommand_matches("outer").expect("could not access subcommand");
        let sub_sub_match = sub_match.subcommand_matches("inner").expect("could not access inner sub");

        assert_eq!(sub_sub_match.value_of("GLOBAL_ARG").expect("inner subcommand could not access global arg"),
                "some_value", "inner subcommand did not have expected value for global arg");
    }

    #[test]
    fn subcommand_can_access_global_arg_if_global_arg_is_first() {
        // currently passes
        first_subcommand_can_access_global(vec!["myprog", "--global-arg", "some_value", "outer", "inner"]);
    }

    #[test]
    fn subcommand_can_access_global_arg_if_global_arg_is_in_the_middle() {
        // currently passes
        first_subcommand_can_access_global(vec!["myprog", "outer",  "--global-arg", "some_value" ,"inner"]);
    }

    #[test]
    fn first_subcommand_can_access_global_arg_if_global_arg_is_last() {
        // currently fails - hypothesis - nothing propagates global args back up
        first_subcommand_can_access_global(vec!["myprog", "outer", "inner", "--global-arg", "some_value"]);
    }

    #[test]
    fn second_subcommand_can_access_global_arg_if_global_arg_is_first() {
        // currently passes
        second_subcommand_can_access_global(vec!["myprog", "--global-arg", "some_value", "outer", "inner"]);
    }

    #[test]
    fn second_subcommand_can_access_global_arg_if_global_arg_is_in_the_middle() {
        // currently fails - hypothesis: subcommands do not recursively propagate global args
        second_subcommand_can_access_global(vec!["myprog", "outer",  "--global-arg", "some_value" ,"inner"]);
    }

    #[test]
    fn second_subcommand_can_access_global_arg_if_global_arg_is_last() {
        // currently passes
        second_subcommand_can_access_global(vec!["myprog", "outer", "inner", "--global-arg", "some_value"]);
    }
}

<|endoftext|>