<commit_before>use ffi;
use libc;

use AsLua;
use AsMutLua;
use LuaContext;
use LuaRead;
use Push;
use PushGuard;

use std::marker::PhantomData;
use std::fmt::Debug;
use std::mem;
use std::ptr;

/// Wraps a type that implements `FnMut` so that it can be used by hlua.
///
/// This is only needed because of a limitation in Rust's inferrence system.
pub fn function<F, P>(f: F) -> Function<F, P, <F as FnMut<P>>::Output> where F: FnMut<P> {
    Function {
        function: f,
        marker: PhantomData,
    }
}

/// Opaque type containing a Rust function or closure.
pub struct Function<F, P, R> {
    function: F,
    marker: PhantomData<(P, R)>,
}

// this function is the main entry point when Lua wants to call one of our functions
extern fn wrapper1(lua: *mut ffi::lua_State) -> ::libc::c_int {
    // we load the pointer to the wrapper2 function from an upvalue (an upvalue is a value that was pushed alongside our function)
    let wrapper2raw = unsafe { ffi::lua_touserdata(lua, ffi::lua_upvalueindex(2)) };
    let wrapper2: fn(*mut ffi::lua_State)->::libc::c_int = unsafe { ::std::mem::transmute(wrapper2raw) };

    wrapper2(lua)
}

// this function is called when Lua wants to call one of our functions
fn wrapper2<T, P, R>(lua: *mut ffi::lua_State) -> libc::c_int
                     where T: FnMut<P, Output=R>,
                           P: for<'p> LuaRead<&'p mut InsideCallback> + 'static,
                           R: for<'p> Push<&'p mut InsideCallback>
{
    // loading the object that we want to call from the Lua context
    let data_raw = unsafe { ffi::lua_touserdata(lua, ffi::lua_upvalueindex(1)) };
    let data: &mut T = unsafe { mem::transmute(data_raw) };

    // creating a temporary Lua context in order to pass it to push & read functions
    let mut tmp_lua = InsideCallback { lua: LuaContext(lua) };

    // trying to read the arguments
    let arguments_count = unsafe { ffi::lua_gettop(lua) } as i32;
    let args = match LuaRead::lua_read_at_position(&mut tmp_lua, -arguments_count as libc::c_int) {      // TODO: what if the user has the wrong params?
        None => {
            let err_msg = format!("wrong parameter types for callback function");
            err_msg.push_to_lua(&mut tmp_lua).forget();
            unsafe { ffi::lua_error(lua); }
            unreachable!()
        },
        Some(a) => a
    };

    let ret_value = data.call_mut(args);

    // pushing back the result of the function on the stack
    let nb = ret_value.push_to_lua(&mut tmp_lua).forget();
    nb as libc::c_int
}

// this trait should be implemented on objects that are pushed to be callbacks
trait AnyCallable {
    fn load_args_and_call(&mut self, lua: *mut ffi::lua_State) -> ::libc::c_int;
}

/// Opaque type that represents the Lua context when inside a callback.
///
/// Some types (like `Result`) can only be returned from a callback and not written inside a
/// Lua variable. This type is here to enforce this restriction.
pub struct InsideCallback {
    lua: LuaContext,
}

unsafe impl<'a> AsLua for &'a InsideCallback {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a> AsLua for &'a mut InsideCallback {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a> AsMutLua for &'a mut InsideCallback {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.lua
    }
}

impl<L, F, P, R> Push<L> for Function<F, P, R>
        where L: AsMutLua, P: 'static,
              F: FnMut<P, Output=R>,
              P: for<'p> LuaRead<&'p mut InsideCallback>,
              R: for<'a> Push<&'a mut InsideCallback> + 'static
{
    fn push_to_lua(self, mut lua: L) -> PushGuard<L> {
        // pushing the function pointer as a userdata
        let lua_data_raw = unsafe {
            ffi::lua_newuserdata(lua.as_mut_lua().0, mem::size_of::<F>() as libc::size_t)
        };

        let lua_data: *mut F = unsafe { mem::transmute(lua_data_raw) };
        unsafe { ptr::write(lua_data, self.function) };

        // pushing wrapper2 as a lightuserdata
        let wrapper2: fn(*mut ffi::lua_State) -> libc::c_int = wrapper2::<F, P, R>;
        unsafe { ffi::lua_pushlightuserdata(lua.as_mut_lua().0, mem::transmute(wrapper2)) };

        // pushing wrapper1 as a closure
        unsafe { ffi::lua_pushcclosure(lua.as_mut_lua().0, mem::transmute(wrapper1), 2) };

        PushGuard { lua: lua, size: 1 }
    }
}

impl<'a, T, E> Push<&'a mut InsideCallback> for Result<T, E>
                where T: Push<&'a mut InsideCallback> +
                         for<'b> Push<&'b mut &'a mut InsideCallback>,
                      E: Debug
{
    fn push_to_lua(self, mut lua: &'a mut InsideCallback) -> PushGuard<&'a mut InsideCallback> {
        match self {
            Ok(val) => val.push_to_lua(lua),
            Err(val) => {
                let msg = format!("{:?}", val);
                msg.push_to_lua(&mut lua).forget();
                unsafe { ffi::lua_error(lua.as_mut_lua().0); }
                unreachable!();
            }
        }
    }
}
<commit_msg>Cleanup the functions_write module<commit_after>use ffi;
use libc;

use AsLua;
use AsMutLua;
use LuaContext;
use LuaRead;
use Push;
use PushGuard;

use std::marker::PhantomData;
use std::fmt::Debug;
use std::mem;
use std::ptr;

/// Wraps a type that implements `FnMut` so that it can be used by hlua.
///
/// This is only needed because of a limitation in Rust's inferrence system.
pub fn function<F, P>(f: F) -> Function<F, P, <F as FnMut<P>>::Output> where F: FnMut<P> {
    Function {
        function: f,
        marker: PhantomData,
    }
}

/// Opaque type containing a Rust function or closure.
pub struct Function<F, P, R> {
    function: F,
    marker: PhantomData<(P, R)>,
}

/// Opaque type that represents the Lua context when inside a callback.
///
/// Some types (like `Result`) can only be returned from a callback and not written inside a
/// Lua variable. This type is here to enforce this restriction.
pub struct InsideCallback {
    lua: LuaContext,
}

unsafe impl<'a> AsLua for &'a InsideCallback {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a> AsLua for &'a mut InsideCallback {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a> AsMutLua for &'a mut InsideCallback {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.lua
    }
}

impl<L, F, P, R> Push<L> for Function<F, P, R>
        where L: AsMutLua, P: 'static,
              F: FnMut<P, Output=R>,
              P: for<'p> LuaRead<&'p mut InsideCallback>,
              R: for<'a> Push<&'a mut InsideCallback> + 'static
{
    fn push_to_lua(self, mut lua: L) -> PushGuard<L> {
        unsafe {
            // pushing the function pointer as a userdata
            let lua_data = ffi::lua_newuserdata(lua.as_mut_lua().0,
                                                mem::size_of::<F>() as libc::size_t);
            let lua_data: *mut F = mem::transmute(lua_data);
            ptr::write(lua_data, self.function);

            // pushing wrapper as a closure
            let wrapper: extern fn(*mut ffi::lua_State) -> libc::c_int = wrapper::<F, P, R>;
            ffi::lua_pushcclosure(lua.as_mut_lua().0, wrapper, 1);
            PushGuard { lua: lua, size: 1 }
        }
    }
}

impl<'a, T, E> Push<&'a mut InsideCallback> for Result<T, E>
                where T: Push<&'a mut InsideCallback> +
                         for<'b> Push<&'b mut &'a mut InsideCallback>,
                      E: Debug
{
    fn push_to_lua(self, mut lua: &'a mut InsideCallback) -> PushGuard<&'a mut InsideCallback> {
        match self {
            Ok(val) => val.push_to_lua(lua),
            Err(val) => {
                let msg = format!("{:?}", val);
                msg.push_to_lua(&mut lua).forget();
                unsafe { ffi::lua_error(lua.as_mut_lua().0); }
                unreachable!();
            }
        }
    }
}

// this function is called when Lua wants to call one of our functions
extern fn wrapper<T, P, R>(lua: *mut ffi::lua_State) -> libc::c_int
                           where T: FnMut<P, Output=R>,
                                 P: for<'p> LuaRead<&'p mut InsideCallback> + 'static,
                                 R: for<'p> Push<&'p mut InsideCallback>
{
    // loading the object that we want to call from the Lua context
    let data_raw = unsafe { ffi::lua_touserdata(lua, ffi::lua_upvalueindex(1)) };
    let data: &mut T = unsafe { mem::transmute(data_raw) };

    // creating a temporary Lua context in order to pass it to push & read functions
    let mut tmp_lua = InsideCallback { lua: LuaContext(lua) };

    // trying to read the arguments
    let arguments_count = unsafe { ffi::lua_gettop(lua) } as i32;
    let args = match LuaRead::lua_read_at_position(&mut tmp_lua, -arguments_count as libc::c_int) {      // TODO: what if the user has the wrong params?
        None => {
            let err_msg = format!("wrong parameter types for callback function");
            err_msg.push_to_lua(&mut tmp_lua).forget();
            unsafe { ffi::lua_error(lua); }
            unreachable!()
        },
        Some(a) => a
    };

    let ret_value = data.call_mut(args);

    // pushing back the result of the function on the stack
    let nb = ret_value.push_to_lua(&mut tmp_lua).forget();
    nb as libc::c_int
}
<|endoftext|>


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

use core::num::flt2dec::estimator::*;

#[test]
fn test_estimate_scaling_factor() {
    macro_rules! assert_almost_eq {
        ($actual:expr, $expected:expr) => ({
            let actual = $actual;
            let expected = $expected;
            println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual),
                     expected, actual, expected - actual);
            assert!(expected == actual || expected == actual + 1,
                    "expected {}, actual {}", expected, actual);
        })
    }

    assert_almost_eq!(estimate_scaling_factor(1, 0), 0);
    assert_almost_eq!(estimate_scaling_factor(2, 0), 1);
    assert_almost_eq!(estimate_scaling_factor(10, 0), 1);
    assert_almost_eq!(estimate_scaling_factor(11, 0), 2);
    assert_almost_eq!(estimate_scaling_factor(100, 0), 2);
    assert_almost_eq!(estimate_scaling_factor(101, 0), 3);
    assert_almost_eq!(estimate_scaling_factor(10000000000000000000, 0), 19);
    assert_almost_eq!(estimate_scaling_factor(10000000000000000001, 0), 20);

    // 1/2^20 = 0.00000095367...
    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000, -20), -6);
    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000 + 1, -20), -5);
    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000, -20), -5);
    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000 + 1, -20), -4);
    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000, -20), -4);
    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), -3);
    assert_almost_eq!(estimate_scaling_factor(1048575, -20), 0);
    assert_almost_eq!(estimate_scaling_factor(1048576, -20), 0);
    assert_almost_eq!(estimate_scaling_factor(1048577, -20), 1);
    assert_almost_eq!(estimate_scaling_factor(10485759999999999999, -20), 13);
    assert_almost_eq!(estimate_scaling_factor(10485760000000000000, -20), 13);
    assert_almost_eq!(estimate_scaling_factor(10485760000000000001, -20), 14);

    // extreme values:
    // 2^-1074 = 4.94065... * 10^-324
    // (2^53-1) * 2^971 = 1.79763... * 10^308
    assert_almost_eq!(estimate_scaling_factor(1, -1074), -323);
    assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309);

    for i in -1074..972 {
        let expected = super::ldexp_f64(1.0, i).log10().ceil();
        assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16);
    }
}

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

use core::num::flt2dec::estimator::*;

#[test]
// FIXME https://github.com/kripken/emscripten/issues/4563
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_estimate_scaling_factor() {
    macro_rules! assert_almost_eq {
        ($actual:expr, $expected:expr) => ({
            let actual = $actual;
            let expected = $expected;
            println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual),
                     expected, actual, expected - actual);
            assert!(expected == actual || expected == actual + 1,
                    "expected {}, actual {}", expected, actual);
        })
    }

    assert_almost_eq!(estimate_scaling_factor(1, 0), 0);
    assert_almost_eq!(estimate_scaling_factor(2, 0), 1);
    assert_almost_eq!(estimate_scaling_factor(10, 0), 1);
    assert_almost_eq!(estimate_scaling_factor(11, 0), 2);
    assert_almost_eq!(estimate_scaling_factor(100, 0), 2);
    assert_almost_eq!(estimate_scaling_factor(101, 0), 3);
    assert_almost_eq!(estimate_scaling_factor(10000000000000000000, 0), 19);
    assert_almost_eq!(estimate_scaling_factor(10000000000000000001, 0), 20);

    // 1/2^20 = 0.00000095367...
    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000, -20), -6);
    assert_almost_eq!(estimate_scaling_factor(1 * 1048576 / 1000000 + 1, -20), -5);
    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000, -20), -5);
    assert_almost_eq!(estimate_scaling_factor(10 * 1048576 / 1000000 + 1, -20), -4);
    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000, -20), -4);
    assert_almost_eq!(estimate_scaling_factor(100 * 1048576 / 1000000 + 1, -20), -3);
    assert_almost_eq!(estimate_scaling_factor(1048575, -20), 0);
    assert_almost_eq!(estimate_scaling_factor(1048576, -20), 0);
    assert_almost_eq!(estimate_scaling_factor(1048577, -20), 1);
    assert_almost_eq!(estimate_scaling_factor(10485759999999999999, -20), 13);
    assert_almost_eq!(estimate_scaling_factor(10485760000000000000, -20), 13);
    assert_almost_eq!(estimate_scaling_factor(10485760000000000001, -20), 14);

    // extreme values:
    // 2^-1074 = 4.94065... * 10^-324
    // (2^53-1) * 2^971 = 1.79763... * 10^308
    assert_almost_eq!(estimate_scaling_factor(1, -1074), -323);
    assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309);

    for i in -1074..972 {
        let expected = super::ldexp_f64(1.0, i).log10().ceil();
        assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16);
    }
}

<|endoftext|>


<commit_before>//! Translation skeletton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use wasmparser::{ParserState, SectionCode, ParserInput, Parser, WasmDecoder, BinaryReaderError};
use sections_translator::{SectionParsingError, parse_function_signatures, parse_import_section,
                          parse_function_section, parse_export_section, parse_memory_section,
                          parse_global_section, parse_table_section, parse_elements_section,
                          parse_data_section};
use translation_utils::{Import, SignatureIndex, FunctionIndex};
use cretonne::ir::{Function, FunctionName};
use func_translator::FuncTranslator;
use std::collections::HashMap;
use std::error::Error;
use runtime::WasmRuntime;

/// Output of the [`translate_module`](fn.translate_module.html) function.
pub struct TranslationResult {
    /// The translated functions.
    pub functions: Vec<Function>,
    /// When present, the index of the function defined as `start` of the module.
    ///
    /// Note that this is a WebAssembly function index and not an index into the `functions` vector
    /// above. The imported functions are numbered before the local functions.
    pub start_index: Option<FunctionIndex>,
}

/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
/// [`Function`](../cretonne/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module(
    data: &[u8],
    runtime: &mut WasmRuntime,
) -> Result<TranslationResult, String> {
    let mut parser = Parser::new(data);
    match *parser.read() {
        ParserState::BeginWasm { .. } => {}
        ParserState::Error(BinaryReaderError { message, offset }) => {
            return Err(format!("at offset {}: {}", offset, message));
        }
        ref s => panic!("modules should begin properly: {:?}", s),
    }
    let mut functions: Option<Vec<SignatureIndex>> = None;
    let mut globals = Vec::new();
    let mut exports: Option<HashMap<FunctionIndex, String>> = None;
    let mut next_input = ParserInput::Default;
    let mut function_index: FunctionIndex = 0;
    let mut start_index: Option<FunctionIndex> = None;
    loop {
        match *parser.read_with_input(next_input) {
            ParserState::BeginSection { code: SectionCode::Type, .. } => {
                match parse_function_signatures(&mut parser, runtime) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the type section: {}", s))
                    }
                };
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Import, .. } => {
                match parse_import_section(&mut parser, runtime) {
                    Ok(imps) => {
                        for import in imps {
                            match import {
                                Import::Function { sig_index } => {
                                    functions = match functions {
                                        None => Some(vec![sig_index as SignatureIndex]),
                                        Some(mut funcs) => {
                                            funcs.push(sig_index as SignatureIndex);
                                            Some(funcs)
                                        }
                                    };
                                    function_index += 1;
                                }
                                Import::Memory(mem) => {
                                    runtime.declare_memory(mem);
                                }
                                Import::Global(glob) => {
                                    runtime.declare_global(glob);
                                    globals.push(glob);
                                }
                                Import::Table(tab) => {
                                    runtime.declare_table(tab);
                                }
                            }
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the import section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Function, .. } => {
                match parse_function_section(&mut parser, runtime) {
                    Ok(funcs) => {
                        match functions {
                            None => functions = Some(funcs),
                            Some(ref mut imps) => imps.extend(funcs),
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the function section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Table, .. } => {
                match parse_table_section(&mut parser, runtime) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the table section: {}", s))
                    }
                }
            }
            ParserState::BeginSection { code: SectionCode::Memory, .. } => {
                match parse_memory_section(&mut parser) {
                    Ok(mems) => {
                        for mem in mems {
                            runtime.declare_memory(mem);
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the memory section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Global, .. } => {
                match parse_global_section(&mut parser, runtime) {
                    Ok(mut globs) => globals.append(&mut globs),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the global section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Export, .. } => {
                match parse_export_section(&mut parser) {
                    Ok(exps) => exports = Some(exps),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the export section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Start, .. } => {
                match *parser.read() {
                    ParserState::StartSectionEntry(index) => {
                        start_index = Some(index as FunctionIndex)
                    }
                    _ => return Err(String::from("wrong content in the start section")),
                }
                match *parser.read() {
                    ParserState::EndSection => {}
                    _ => return Err(String::from("wrong content in the start section")),
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Element, .. } => {
                match parse_elements_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the element section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Code, .. } => {
                // The code section begins
                break;
            }
            ParserState::EndSection => {
                next_input = ParserInput::Default;
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: Vec::new(),
                    start_index: None,
                })
            }
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            _ => return Err(String::from("wrong content in the preamble")),
        };
    }
    // At this point we've entered the code section
    // First we check that we have all that is necessary to translate a function.
    let functions = match functions {
        None => return Err(String::from("missing a function section")),
        Some(functions) => functions,
    };
    let mut il_functions: Vec<Function> = Vec::new();
    let mut trans = FuncTranslator::new();
    runtime.begin_translation();
    loop {
        match *parser.read() {
            ParserState::BeginFunctionBody { .. } => {}
            ParserState::EndSection => break,
            _ => return Err(String::from("wrong content in code section")),
        }
        runtime.next_function();
        // First we build the Function object with its name and signature
        let mut func = Function::new();
        func.signature = runtime.get_signature(functions[function_index]).clone();
        if let Some(ref exports) = exports {
            if let Some(name) = exports.get(&function_index) {
                func.name = FunctionName::new(name.clone());
            }
        }
        trans
            .translate_from_reader(parser.create_binary_reader(), &mut func, runtime)
            .map_err(|e| String::from(e.description()))?;
        il_functions.push(func);
        function_index += 1;
    }
    loop {
        match *parser.read() {
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: il_functions,
                    start_index,
                })
            }
            _ => (),
        }
    }
}
<commit_msg>Simplify code by removing unnecessary `Option`s.<commit_after>//! Translation skeletton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use wasmparser::{ParserState, SectionCode, ParserInput, Parser, WasmDecoder, BinaryReaderError};
use sections_translator::{SectionParsingError, parse_function_signatures, parse_import_section,
                          parse_function_section, parse_export_section, parse_memory_section,
                          parse_global_section, parse_table_section, parse_elements_section,
                          parse_data_section};
use translation_utils::{Import, SignatureIndex, FunctionIndex};
use cretonne::ir::{Function, FunctionName};
use func_translator::FuncTranslator;
use std::collections::HashMap;
use std::error::Error;
use runtime::WasmRuntime;

/// Output of the [`translate_module`](fn.translate_module.html) function.
pub struct TranslationResult {
    /// The translated functions.
    pub functions: Vec<Function>,
    /// When present, the index of the function defined as `start` of the module.
    ///
    /// Note that this is a WebAssembly function index and not an index into the `functions` vector
    /// above. The imported functions are numbered before the local functions.
    pub start_index: Option<FunctionIndex>,
}

/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
/// [`Function`](../cretonne/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module(
    data: &[u8],
    runtime: &mut WasmRuntime,
) -> Result<TranslationResult, String> {
    let mut parser = Parser::new(data);
    match *parser.read() {
        ParserState::BeginWasm { .. } => {}
        ParserState::Error(BinaryReaderError { message, offset }) => {
            return Err(format!("at offset {}: {}", offset, message));
        }
        ref s => panic!("modules should begin properly: {:?}", s),
    }
    let mut functions: Vec<SignatureIndex> = Vec::new();
    let mut globals = Vec::new();
    let mut exports: HashMap<FunctionIndex, String> = HashMap::new();
    let mut next_input = ParserInput::Default;
    let mut function_index: FunctionIndex = 0;
    let mut start_index: Option<FunctionIndex> = None;
    loop {
        match *parser.read_with_input(next_input) {
            ParserState::BeginSection { code: SectionCode::Type, .. } => {
                match parse_function_signatures(&mut parser, runtime) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the type section: {}", s))
                    }
                };
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Import, .. } => {
                match parse_import_section(&mut parser, runtime) {
                    Ok(imps) => {
                        for import in imps {
                            match import {
                                Import::Function { sig_index } => {
                                    functions.push(sig_index as SignatureIndex);
                                    function_index += 1;
                                }
                                Import::Memory(mem) => {
                                    runtime.declare_memory(mem);
                                }
                                Import::Global(glob) => {
                                    runtime.declare_global(glob);
                                    globals.push(glob);
                                }
                                Import::Table(tab) => {
                                    runtime.declare_table(tab);
                                }
                            }
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the import section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Function, .. } => {
                match parse_function_section(&mut parser, runtime) {
                    Ok(funcs) => {
                        functions.extend(funcs);
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the function section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Table, .. } => {
                match parse_table_section(&mut parser, runtime) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the table section: {}", s))
                    }
                }
            }
            ParserState::BeginSection { code: SectionCode::Memory, .. } => {
                match parse_memory_section(&mut parser) {
                    Ok(mems) => {
                        for mem in mems {
                            runtime.declare_memory(mem);
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the memory section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Global, .. } => {
                match parse_global_section(&mut parser, runtime) {
                    Ok(mut globs) => globals.append(&mut globs),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the global section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Export, .. } => {
                match parse_export_section(&mut parser) {
                    Ok(exps) => exports = exps,
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the export section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Start, .. } => {
                match *parser.read() {
                    ParserState::StartSectionEntry(index) => {
                        start_index = Some(index as FunctionIndex)
                    }
                    _ => return Err(String::from("wrong content in the start section")),
                }
                match *parser.read() {
                    ParserState::EndSection => {}
                    _ => return Err(String::from("wrong content in the start section")),
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Element, .. } => {
                match parse_elements_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the element section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Code, .. } => {
                // The code section begins
                break;
            }
            ParserState::EndSection => {
                next_input = ParserInput::Default;
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: Vec::new(),
                    start_index: None,
                })
            }
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            _ => return Err(String::from("wrong content in the preamble")),
        };
    }
    // At this point we've entered the code section
    let mut il_functions: Vec<Function> = Vec::new();
    let mut trans = FuncTranslator::new();
    runtime.begin_translation();
    loop {
        match *parser.read() {
            ParserState::BeginFunctionBody { .. } => {}
            ParserState::EndSection => break,
            _ => return Err(String::from("wrong content in code section")),
        }
        runtime.next_function();
        // First we build the Function object with its name and signature
        let mut func = Function::new();
        func.signature = runtime.get_signature(functions[function_index]).clone();
        if let Some(name) = exports.get(&function_index) {
            func.name = FunctionName::new(name.clone());
        }
        trans
            .translate_from_reader(parser.create_binary_reader(), &mut func, runtime)
            .map_err(|e| String::from(e.description()))?;
        il_functions.push(func);
        function_index += 1;
    }
    loop {
        match *parser.read() {
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: il_functions,
                    start_index,
                })
            }
            _ => (),
        }
    }
}
<|endoftext|>


<commit_before>use toml::Value;

/// Check whether the configuration is valid for the store
///
/// The passed `Value` _must be_ the `[store]` sub-tree of the configuration. Otherwise this will
/// fail.
///
/// It checks whether the configuration looks like the store wants it to be:
///
/// ```toml
/// [store]
/// pre-create-hook-aspects = [ "misc", "encryption", "version-control"]
///
/// [[aspects.misc]]
/// parallel = true
/// [[aspects.encryption]]
/// parallel = false
/// [[aspects.version-control]]
/// parallel = false
///
/// [[hooks.gnupg]]
/// aspect = "encryption"
/// key = "0x123456789"
///
/// [[hooks.git]]
/// aspect = "version-control"
/// ```
///
/// It checks:
///  * Whether all the maps are there (whether store, store.aspects, store.aspects.example are all
///  maps)
///  * Whether each aspect configuration has a "parallel = <Boolean>" setting
///  * Whether each hook congfiguration has a "aspect = <String>" setting
///
/// It does NOT check:
///  * Whether all aspects which are used in the hook configuration are also configured
///
/// No configuration is a valid configuration, as the store will use the most conservative settings
/// automatically. This has also performance impact, as all hooks run in no-parallel mode then.
/// You have been warned!
///
///
pub fn config_is_valid(config: &Option<Value>) -> bool {
    use std::collections::BTreeMap;

    if config.is_none() {
        return true;
    }

    fn has_key_with_map(v: &BTreeMap<String, Value>, key: &str) -> bool {
        v.get(key).map(|t| match t { &Value::Table(_) => true, _ => false }).unwrap_or(false)
    }

    fn has_key_with_string_ary(v: &BTreeMap<String, Value>, key: &str) -> bool {
        v.get(key)
            .map(|t| match t {
                &Value::Array(ref a) => a.iter().all(|elem| {
                    match elem {
                        &Value::String(_) => true,
                        _ => false,
                    }
                }),
                _ => false
            }).unwrap_or(false)
    }

    /// Check that
    /// * the top-level configuration
    /// * is a table
    /// * where all entries of a key `section` (eg. "hooks" or "aspects")
    ///     * Are maps
    ///     * where each has a key `key` (eg. "aspect" or "parallel")
    ///     * which fullfills constraint `f` (typecheck)
    fn check_all_inner_maps_have_key_with<F>(store_config: &BTreeMap<String, Value>,
                                             section: &str,
                                             key: &str,
                                             f: F)
        -> bool
        where F: Fn(&Value) -> bool
    {
        store_config.get(section) // The store config has the section `section`
            .map(|section_table| {
                match section_table { // which is
                    &Value::Table(ref section_table) => // a table
                        section_table
                            .values() // which has values,
                            .all(|cfg| { // and all of these values
                                match cfg {
                                    &Value::Table(ref hook_config) => { // are tables
                                        hook_config.get(key) // with a key
                                            // fullfilling this constraint
                                            .map(|hook_aspect| f(&hook_aspect))
                                            .unwrap_or(false)
                                    },
                                    _ => false,
                                }
                            }),
                    _ => false,
                }
            })
            .unwrap_or(false)
    }

    match config {
        &Some(Value::Table(ref t)) => {
            has_key_with_string_ary(t, "pre-read-hook-aspects")        &&
            has_key_with_string_ary(t, "post-read-hook-aspects")       &&
            has_key_with_string_ary(t, "pre-create-hook-aspects")      &&
            has_key_with_string_ary(t, "post-create-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-retrieve-hook-aspects")    &&
            has_key_with_string_ary(t, "post-retrieve-hook-aspects")   &&
            has_key_with_string_ary(t, "pre-update-hook-aspects")      &&
            has_key_with_string_ary(t, "post-update-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-delete-hook-aspects")      &&
            has_key_with_string_ary(t, "post-delete-hook-aspects")     &&

            // The section "hooks" has maps which have a key "aspect" which has a value of type
            // String
            check_all_inner_maps_have_key_with(t, "hooks", "aspect", |asp| {
                match asp { &Value::String(_) => true, _ => false }
            }) &&

            // The section "aspects" has maps which have a key "parllel" which has a value of type
            // Boolean
            check_all_inner_maps_have_key_with(t, "aspects", "parallel", |asp| {
                match asp { &Value::Boolean(_) => true, _ => false, }
            })
        }
        _ => false,
    }
}

pub fn get_pre_read_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-read-hook-aspects", value)
}

pub fn get_post_read_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-read-hook-aspects", value)
}

pub fn get_pre_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-create-hook-aspects", value)
}

pub fn get_post_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-create-hook-aspects", value)
}

pub fn get_pre_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-retrieve-hook-aspects", value)
}

pub fn get_post_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-retrieve-hook-aspects", value)
}

pub fn get_pre_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-update-hook-aspects", value)
}

pub fn get_post_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-update-hook-aspects", value)
}

pub fn get_pre_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-delete-hook-aspects", value)
}

pub fn get_post_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-delete-hook-aspects", value)
}

#[derive(Debug)]
pub struct AspectConfig {
    parallel: bool,
    config: Value,
}

impl AspectConfig {

    pub fn new(init: Value) -> AspectConfig {
        let parallel = AspectConfig::is_parallel(&init);
        AspectConfig {
            config: init,
            parallel: parallel,
        }
    }

    pub fn config(&self) -> &Value {
        &self.config
    }

    fn is_parallel(init: &Value) -> bool {
        match init {
            &Value::Table(ref t) =>
                t.get("parallel")
                    .map(|value| {
                        match value {
                            &Value::Boolean(b) => b,
                            _ => false,
                        }
                    })
                    .unwrap_or(false),
            _ => false,
        }
    }

    /// Get the aspect configuration for an aspect.
    ///
    /// Pass the store configuration object, this searches in `[aspects][<aspect_name>]`.
    ///
    /// Returns `None` if one of the keys in the chain is not available
    pub fn get_for(v: &Option<Value>, a_name: String) -> Option<AspectConfig> {
        match v {
            &Some(Value::Table(ref tabl)) => tabl.get(&a_name[..])
                .map(|asp| AspectConfig::new(asp.clone())),
            _ => None,
        }
    }

}

fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Option<Value>) -> Vec<String> {
    let mut v = vec![];

    match value {
        &Some(Value::Table(ref t)) => {
            match t.get(config_name) {
                Some(&Value::Array(ref a)) => {
                    for elem in a {
                        match elem {
                            &Value::String(ref s) => v.push(s.clone()),
                            _ => warn!("Non-String in configuration, inside '{}'", config_name),
                        }
                    }
                },
                _ => warn!("'{}' configuration key should contain Array, does not", config_name),
            };
        },
        &None => warn!("No store configuration"),
        _ => warn!("Configuration is not a table"),
    }
    v
}

<commit_msg>Remove dead code in configuration.rs<commit_after>use toml::Value;

/// Check whether the configuration is valid for the store
///
/// The passed `Value` _must be_ the `[store]` sub-tree of the configuration. Otherwise this will
/// fail.
///
/// It checks whether the configuration looks like the store wants it to be:
///
/// ```toml
/// [store]
/// pre-create-hook-aspects = [ "misc", "encryption", "version-control"]
///
/// [[aspects.misc]]
/// parallel = true
/// [[aspects.encryption]]
/// parallel = false
/// [[aspects.version-control]]
/// parallel = false
///
/// [[hooks.gnupg]]
/// aspect = "encryption"
/// key = "0x123456789"
///
/// [[hooks.git]]
/// aspect = "version-control"
/// ```
///
/// It checks:
///  * Whether all the maps are there (whether store, store.aspects, store.aspects.example are all
///  maps)
///  * Whether each aspect configuration has a "parallel = <Boolean>" setting
///  * Whether each hook congfiguration has a "aspect = <String>" setting
///
/// It does NOT check:
///  * Whether all aspects which are used in the hook configuration are also configured
///
/// No configuration is a valid configuration, as the store will use the most conservative settings
/// automatically. This has also performance impact, as all hooks run in no-parallel mode then.
/// You have been warned!
///
///
pub fn config_is_valid(config: &Option<Value>) -> bool {
    use std::collections::BTreeMap;

    if config.is_none() {
        return true;
    }

    fn has_key_with_string_ary(v: &BTreeMap<String, Value>, key: &str) -> bool {
        v.get(key)
            .map(|t| match t {
                &Value::Array(ref a) => a.iter().all(|elem| {
                    match elem {
                        &Value::String(_) => true,
                        _ => false,
                    }
                }),
                _ => false
            }).unwrap_or(false)
    }

    /// Check that
    /// * the top-level configuration
    /// * is a table
    /// * where all entries of a key `section` (eg. "hooks" or "aspects")
    ///     * Are maps
    ///     * where each has a key `key` (eg. "aspect" or "parallel")
    ///     * which fullfills constraint `f` (typecheck)
    fn check_all_inner_maps_have_key_with<F>(store_config: &BTreeMap<String, Value>,
                                             section: &str,
                                             key: &str,
                                             f: F)
        -> bool
        where F: Fn(&Value) -> bool
    {
        store_config.get(section) // The store config has the section `section`
            .map(|section_table| {
                match section_table { // which is
                    &Value::Table(ref section_table) => // a table
                        section_table
                            .values() // which has values,
                            .all(|cfg| { // and all of these values
                                match cfg {
                                    &Value::Table(ref hook_config) => { // are tables
                                        hook_config.get(key) // with a key
                                            // fullfilling this constraint
                                            .map(|hook_aspect| f(&hook_aspect))
                                            .unwrap_or(false)
                                    },
                                    _ => false,
                                }
                            }),
                    _ => false,
                }
            })
            .unwrap_or(false)
    }

    match config {
        &Some(Value::Table(ref t)) => {
            has_key_with_string_ary(t, "pre-read-hook-aspects")        &&
            has_key_with_string_ary(t, "post-read-hook-aspects")       &&
            has_key_with_string_ary(t, "pre-create-hook-aspects")      &&
            has_key_with_string_ary(t, "post-create-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-retrieve-hook-aspects")    &&
            has_key_with_string_ary(t, "post-retrieve-hook-aspects")   &&
            has_key_with_string_ary(t, "pre-update-hook-aspects")      &&
            has_key_with_string_ary(t, "post-update-hook-aspects")     &&
            has_key_with_string_ary(t, "pre-delete-hook-aspects")      &&
            has_key_with_string_ary(t, "post-delete-hook-aspects")     &&

            // The section "hooks" has maps which have a key "aspect" which has a value of type
            // String
            check_all_inner_maps_have_key_with(t, "hooks", "aspect", |asp| {
                match asp { &Value::String(_) => true, _ => false }
            }) &&

            // The section "aspects" has maps which have a key "parllel" which has a value of type
            // Boolean
            check_all_inner_maps_have_key_with(t, "aspects", "parallel", |asp| {
                match asp { &Value::Boolean(_) => true, _ => false, }
            })
        }
        _ => false,
    }
}

pub fn get_pre_read_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-read-hook-aspects", value)
}

pub fn get_post_read_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-read-hook-aspects", value)
}

pub fn get_pre_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-create-hook-aspects", value)
}

pub fn get_post_create_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-create-hook-aspects", value)
}

pub fn get_pre_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-retrieve-hook-aspects", value)
}

pub fn get_post_retrieve_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-retrieve-hook-aspects", value)
}

pub fn get_pre_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-update-hook-aspects", value)
}

pub fn get_post_update_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-update-hook-aspects", value)
}

pub fn get_pre_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("pre-delete-hook-aspects", value)
}

pub fn get_post_delete_aspect_names(value: &Option<Value>) -> Vec<String> {
    get_aspect_names_for_aspect_position("post-delete-hook-aspects", value)
}

#[derive(Debug)]
pub struct AspectConfig {
    parallel: bool,
    config: Value,
}

impl AspectConfig {

    pub fn new(init: Value) -> AspectConfig {
        let parallel = AspectConfig::is_parallel(&init);
        AspectConfig {
            config: init,
            parallel: parallel,
        }
    }

    pub fn config(&self) -> &Value {
        &self.config
    }

    fn is_parallel(init: &Value) -> bool {
        match init {
            &Value::Table(ref t) =>
                t.get("parallel")
                    .map(|value| {
                        match value {
                            &Value::Boolean(b) => b,
                            _ => false,
                        }
                    })
                    .unwrap_or(false),
            _ => false,
        }
    }

    /// Get the aspect configuration for an aspect.
    ///
    /// Pass the store configuration object, this searches in `[aspects][<aspect_name>]`.
    ///
    /// Returns `None` if one of the keys in the chain is not available
    pub fn get_for(v: &Option<Value>, a_name: String) -> Option<AspectConfig> {
        match v {
            &Some(Value::Table(ref tabl)) => tabl.get(&a_name[..])
                .map(|asp| AspectConfig::new(asp.clone())),
            _ => None,
        }
    }

}

fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Option<Value>) -> Vec<String> {
    let mut v = vec![];

    match value {
        &Some(Value::Table(ref t)) => {
            match t.get(config_name) {
                Some(&Value::Array(ref a)) => {
                    for elem in a {
                        match elem {
                            &Value::String(ref s) => v.push(s.clone()),
                            _ => warn!("Non-String in configuration, inside '{}'", config_name),
                        }
                    }
                },
                _ => warn!("'{}' configuration key should contain Array, does not", config_name),
            };
        },
        &None => warn!("No store configuration"),
        _ => warn!("Configuration is not a table"),
    }
    v
}

<|endoftext|>


<commit_before>#[doc(hidden)]
#[macro_export]
macro_rules! as_item { ($i:item) => {$i} }

// Inserts a placeholder doc comment for the module if it's missing
#[doc(hidden)]
#[macro_export]
macro_rules! add_mod_doc {
    // If nothing left, return
    (
        @rec
        { $(#[$done:meta])* }
        { }
        $i:item
    ) => {
        $(#[$done])*
        #[doc="A module containing an rpc service and client stub."]
        $i
    };

    // If we find a doc attribute, return
    (
        @rec
        { $(#[$done:meta])* }
        {
            #[doc=$doc:expr]
            $(#[$rest:meta])*
        }
        $i:item
    ) => {
        $(#[$done])*
        #[doc=$doc]
        $(#[$rest])*
        $i
    };

    // If we don't find a doc attribute, keep going
    (
        @rec
        { $(#[$($done:tt)*])* }
        {
            #[$($attr:tt)*]
            $($rest:tt)*
        }
        $i:item
    ) => {
        add_mod_doc! {
            @rec
            { $(#[$($done)*])* #[$($attr)*] }
            { $($rest)* }
            $i
        }
    };

    // Entry
    (
        { $(#[$($attr:tt)*])* }
        $i:item
    ) => {
        add_mod_doc! {
            @rec
            {}
            { $(#[$($attr)*])* }
            $i
        }
    };
}

// Required because if-let can't be used with irrefutable patterns, so it needs
// to be special cased.
#[doc(hidden)]
#[macro_export]
macro_rules! client_methods {
    (
        { $(#[$attr:meta])* }
        $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty
    ) => (
        $(#[$attr])*
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            let __Reply::$fn_name(reply) = reply;
            Ok(reply)
        }
    );
    ($(
            { $(#[$attr:meta])* }
            $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty
    )*) => ( $(
        $(#[$attr])*
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            if let __Reply::$fn_name(reply) = reply {
                Ok(reply)
            } else {
                panic!("Incorrect reply variant returned from protocol::Clientrpc; expected `{}`, but got {:?}", stringify!($fn_name), reply);
            }
        }
    )*);
}

// Required because enum variants with no fields can't be suffixed by parens
#[doc(hidden)]
#[macro_export]
macro_rules! define_request {
    ($(@($($finished:tt)*))* --) => (as_item!(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum __Request { $($($finished)*),* }
    ););
    ($(@$finished:tt)* -- $name:ident() $($req:tt)*) =>
        (define_request!($(@$finished)* @($name) -- $($req)*););
    ($(@$finished:tt)* -- $name:ident $args: tt $($req:tt)*) =>
        (define_request!($(@$finished)* @($name $args) -- $($req)*););
    ($($started:tt)*) => (define_request!(-- $($started)*););
}

// Required because enum variants with no fields can't be suffixed by parens
#[doc(hidden)]
#[macro_export]
macro_rules! request_variant {
    ($x:ident) => (__Request::$x);
    ($x:ident $($y:ident),+) => (__Request::$x($($y),+));
}

// The main macro that creates RPC services.
#[macro_export]
macro_rules! rpc {
    (
        $(#[$($service_attr:tt)*])*
        mod $server:ident {

            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {
        rpc! {
            $(#[$($service_attr)*])*
            mod $server {

                items { }

                service {
                    $(
                        $(#[$attr])*
                        rpc $fn_name($($arg: $in_),*) -> $out;
                    )*
                }
            }
        }
    };

    (
        // Names the service
        $(#[$($service_attr:tt)*])*
        mod $server:ident {

            // Include any desired or required items. Conflicts can arise with the following names:
            // 1. Service
            // 2. Client
            // 3. serve
            // 4. __Reply
            // 5. __Request
            items { $($i:item)* }

            // List any rpc methods: rpc foo(arg1: Arg1, ..., argN: ArgN) -> Out
            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {

        add_mod_doc! {
            { $(#[$($service_attr)*])* }
            pub mod $server {

                $($i)*

                #[doc="The provided RPC service."]
                pub trait Service: Send + Sync {
                    $(
                        $(#[$attr])*
                        fn $fn_name(&self, $($arg:$in_),*) -> $out;
                    )*
                }

                define_request!($($fn_name($($in_),*))*);

                #[allow(non_camel_case_types)]
                #[derive(Debug, Serialize, Deserialize)]
                enum __Reply {
                    $(
                        $fn_name($out),
                    )*
                }

                #[doc="The client stub that makes RPC calls to the server."]
                pub struct Client($crate::protocol::Client<__Request, __Reply>);

                impl Client {
                    #[doc="Create a new client that connects to the given address."]
                    pub fn new<A>(addr: A, timeout: ::std::option::Option<::std::time::Duration>)
                        -> $crate::Result<Self>
                        where A: ::std::net::ToSocketAddrs,
                    {
                        let inner = try!($crate::protocol::Client::new(addr, timeout));
                        Ok(Client(inner))
                    }

                    client_methods!(
                        $(
                            { $(#[$attr])* }
                            $fn_name($($arg: $in_),*) -> $out
                        )*
                    );
                }

                struct __Server<S: 'static + Service>(S);

                impl<S> $crate::protocol::Serve for __Server<S>
                    where S: 'static + Service
                {
                    type Request = __Request;
                    type Reply = __Reply;
                    fn serve(&self, request: __Request) -> __Reply {
                        match request {
                            $(
                                request_variant!($fn_name $($arg),*) =>
                                    __Reply::$fn_name((self.0).$fn_name($($arg),*)),
                             )*
                        }
                    }
                }

                #[doc="Start a running service."]
                pub fn serve<A, S>(addr: A,
                                   service: S,
                                   read_timeout: ::std::option::Option<::std::time::Duration>)
                    -> $crate::Result<$crate::protocol::ServeHandle>
                    where A: ::std::net::ToSocketAddrs,
                          S: 'static + Service
                {
                    let server = ::std::sync::Arc::new(__Server(service));
                    Ok(try!($crate::protocol::serve_async(addr, server, read_timeout)))
                }
            }
        }
    }
}

#[cfg(test)]
#[allow(dead_code)]
mod test {
    use std::time::Duration;

    fn test_timeout() -> Option<Duration> {
        Some(Duration::from_secs(5))
    }

    rpc! {
        #[deny(missing_docs)]
        #[doc="Hello"]
        mod my_server {
            items {
                #[derive(PartialEq, Debug, Serialize, Deserialize)]
                pub struct Foo {
                    pub message: String
                }
            }

            service {
                rpc hello(foo: Foo) -> Foo;
                rpc add(x: i32, y: i32) -> i32;
            }
        }
    }

    use self::my_server::*;

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo { message: format!("Hello, {}", &s.message) }
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, (), test_timeout()).unwrap();
        let client = Client::new(addr, None).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo { message: "Adam".into() };
        let want = Foo { message: format!("Hello, {}", &foo.message) };
        assert_eq!(want, client.hello(Foo { message: "Adam".into() }).unwrap());
        drop(client);
        shutdown.shutdown();
    }

    // Tests a service definition with a fn that takes no args
    rpc! {
        mod qux {
            service {
                rpc hello() -> String;
            }
        }
    }

    // Tests a service definition with an import
    rpc! {
        mod foo {
            items {
                use std::collections::HashMap;
            }

            service {
                #[doc="Hello bob"]
                #[inline(always)]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }

    // Tests a service definition with an attribute but no doc comment
    rpc! {
        #[deny(missing_docs)]
        mod bar {
            items {
                use std::collections::HashMap;
            }

            service {
                #[doc="Hello bob"]
                #[inline(always)]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }

    // Tests a service definition with an attribute and a doc comment
    rpc! {
        #[deny(missing_docs)]
        #[doc="Hello bob"]
        #[allow(unused)]
        mod baz {
            items {
                use std::collections::HashMap;
            }

            service {
                #[doc="Hello bob"]
                #[inline(always)]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }
}
<commit_msg>Expand macro invocation test for attributes on items in the items { } block<commit_after>#[doc(hidden)]
#[macro_export]
macro_rules! as_item { ($i:item) => {$i} }

// Inserts a placeholder doc comment for the module if it's missing
#[doc(hidden)]
#[macro_export]
macro_rules! add_mod_doc {
    // If nothing left, return
    (
        @rec
        { $(#[$done:meta])* }
        { }
        $i:item
    ) => {
        $(#[$done])*
        #[doc="A module containing an rpc service and client stub."]
        $i
    };

    // If we find a doc attribute, return
    (
        @rec
        { $(#[$done:meta])* }
        {
            #[doc=$doc:expr]
            $(#[$rest:meta])*
        }
        $i:item
    ) => {
        $(#[$done])*
        #[doc=$doc]
        $(#[$rest])*
        $i
    };

    // If we don't find a doc attribute, keep going
    (
        @rec
        { $(#[$($done:tt)*])* }
        {
            #[$($attr:tt)*]
            $($rest:tt)*
        }
        $i:item
    ) => {
        add_mod_doc! {
            @rec
            { $(#[$($done)*])* #[$($attr)*] }
            { $($rest)* }
            $i
        }
    };

    // Entry
    (
        { $(#[$($attr:tt)*])* }
        $i:item
    ) => {
        add_mod_doc! {
            @rec
            {}
            { $(#[$($attr)*])* }
            $i
        }
    };
}

// Required because if-let can't be used with irrefutable patterns, so it needs
// to be special cased.
#[doc(hidden)]
#[macro_export]
macro_rules! client_methods {
    (
        { $(#[$attr:meta])* }
        $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty
    ) => (
        $(#[$attr])*
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            let __Reply::$fn_name(reply) = reply;
            Ok(reply)
        }
    );
    ($(
            { $(#[$attr:meta])* }
            $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty
    )*) => ( $(
        $(#[$attr])*
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            if let __Reply::$fn_name(reply) = reply {
                Ok(reply)
            } else {
                panic!("Incorrect reply variant returned from protocol::Clientrpc; expected `{}`, but got {:?}", stringify!($fn_name), reply);
            }
        }
    )*);
}

// Required because enum variants with no fields can't be suffixed by parens
#[doc(hidden)]
#[macro_export]
macro_rules! define_request {
    ($(@($($finished:tt)*))* --) => (as_item!(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum __Request { $($($finished)*),* }
    ););
    ($(@$finished:tt)* -- $name:ident() $($req:tt)*) =>
        (define_request!($(@$finished)* @($name) -- $($req)*););
    ($(@$finished:tt)* -- $name:ident $args: tt $($req:tt)*) =>
        (define_request!($(@$finished)* @($name $args) -- $($req)*););
    ($($started:tt)*) => (define_request!(-- $($started)*););
}

// Required because enum variants with no fields can't be suffixed by parens
#[doc(hidden)]
#[macro_export]
macro_rules! request_variant {
    ($x:ident) => (__Request::$x);
    ($x:ident $($y:ident),+) => (__Request::$x($($y),+));
}

// The main macro that creates RPC services.
#[macro_export]
macro_rules! rpc {
    (
        $(#[$($service_attr:tt)*])*
        mod $server:ident {

            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {
        rpc! {
            $(#[$($service_attr)*])*
            mod $server {

                items { }

                service {
                    $(
                        $(#[$attr])*
                        rpc $fn_name($($arg: $in_),*) -> $out;
                    )*
                }
            }
        }
    };

    (
        // Names the service
        $(#[$($service_attr:tt)*])*
        mod $server:ident {

            // Include any desired or required items. Conflicts can arise with the following names:
            // 1. Service
            // 2. Client
            // 3. serve
            // 4. __Reply
            // 5. __Request
            items { $($i:item)* }

            // List any rpc methods: rpc foo(arg1: Arg1, ..., argN: ArgN) -> Out
            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {

        add_mod_doc! {
            { $(#[$($service_attr)*])* }
            pub mod $server {

                $($i)*

                #[doc="The provided RPC service."]
                pub trait Service: Send + Sync {
                    $(
                        $(#[$attr])*
                        fn $fn_name(&self, $($arg:$in_),*) -> $out;
                    )*
                }

                define_request!($($fn_name($($in_),*))*);

                #[allow(non_camel_case_types)]
                #[derive(Debug, Serialize, Deserialize)]
                enum __Reply {
                    $(
                        $fn_name($out),
                    )*
                }

                #[doc="The client stub that makes RPC calls to the server."]
                pub struct Client($crate::protocol::Client<__Request, __Reply>);

                impl Client {
                    #[doc="Create a new client that connects to the given address."]
                    pub fn new<A>(addr: A, timeout: ::std::option::Option<::std::time::Duration>)
                        -> $crate::Result<Self>
                        where A: ::std::net::ToSocketAddrs,
                    {
                        let inner = try!($crate::protocol::Client::new(addr, timeout));
                        Ok(Client(inner))
                    }

                    client_methods!(
                        $(
                            { $(#[$attr])* }
                            $fn_name($($arg: $in_),*) -> $out
                        )*
                    );
                }

                struct __Server<S: 'static + Service>(S);

                impl<S> $crate::protocol::Serve for __Server<S>
                    where S: 'static + Service
                {
                    type Request = __Request;
                    type Reply = __Reply;
                    fn serve(&self, request: __Request) -> __Reply {
                        match request {
                            $(
                                request_variant!($fn_name $($arg),*) =>
                                    __Reply::$fn_name((self.0).$fn_name($($arg),*)),
                             )*
                        }
                    }
                }

                #[doc="Start a running service."]
                pub fn serve<A, S>(addr: A,
                                   service: S,
                                   read_timeout: ::std::option::Option<::std::time::Duration>)
                    -> $crate::Result<$crate::protocol::ServeHandle>
                    where A: ::std::net::ToSocketAddrs,
                          S: 'static + Service
                {
                    let server = ::std::sync::Arc::new(__Server(service));
                    Ok(try!($crate::protocol::serve_async(addr, server, read_timeout)))
                }
            }
        }
    }
}

#[cfg(test)]
#[allow(dead_code)]
mod test {
    use std::time::Duration;

    fn test_timeout() -> Option<Duration> {
        Some(Duration::from_secs(5))
    }

    rpc! {
        #[deny(missing_docs)]
        #[doc="Hello"]
        mod my_server {
            items {
                #[derive(PartialEq, Debug, Serialize, Deserialize)]
                pub struct Foo {
                    pub message: String
                }
            }

            service {
                rpc hello(foo: Foo) -> Foo;
                rpc add(x: i32, y: i32) -> i32;
            }
        }
    }

    use self::my_server::*;

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo { message: format!("Hello, {}", &s.message) }
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, (), test_timeout()).unwrap();
        let client = Client::new(addr, None).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo { message: "Adam".into() };
        let want = Foo { message: format!("Hello, {}", &foo.message) };
        assert_eq!(want, client.hello(Foo { message: "Adam".into() }).unwrap());
        drop(client);
        shutdown.shutdown();
    }

    // Tests a service definition with a fn that takes no args
    rpc! {
        mod qux {
            service {
                rpc hello() -> String;
            }
        }
    }

    // Tests a service definition with an import
    rpc! {
        mod foo {
            items {
                use std::collections::HashMap;
            }

            service {
                #[doc="Hello bob"]
                #[inline(always)]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }

    // Tests a service definition with an attribute but no doc comment
    rpc! {
        #[deny(missing_docs)]
        mod bar {
            items {
                use std::collections::HashMap;
            }

            service {
                #[doc="Hello bob"]
                #[inline(always)]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }

    // Tests a service definition with an attribute and a doc comment
    rpc! {
        #[deny(missing_docs)]
        #[doc="Hello bob"]
        #[allow(unused)]
        mod baz {
            items {
                use std::collections::HashMap;

                #[derive(Debug)]
                pub struct Debuggable;
            }

            service {
                #[doc="Hello bob"]
                #[inline(always)]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }

    #[test]
    fn debug() {
        println!("{:?}", baz::Debuggable);
    }
}
<|endoftext|>


<commit_before>use common::util::*;

#[test]
fn test_symlink_existing_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_existing_file";
    let link = "test_symlink_existing_file_link";

    at.touch(file);

    ucmd.args(&["-s", file, link]).succeeds().no_stderr();

    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);
}

#[test]
fn test_symlink_dangling_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_dangling_file";
    let link = "test_symlink_dangling_file_link";

    ucmd.args(&["-s", file, link]).succeeds().no_stderr();
    assert!(!at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);
}

#[test]
fn test_symlink_existing_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_existing_dir";
    let link = "test_symlink_existing_dir_link";

    at.mkdir(dir);

    ucmd.args(&["-s", dir, link]).succeeds().no_stderr();
    assert!(at.dir_exists(dir));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), dir);
}

#[test]
fn test_symlink_dangling_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_dangling_dir";
    let link = "test_symlink_dangling_dir_link";

    ucmd.args(&["-s", dir, link]).succeeds().no_stderr();
    assert!(!at.dir_exists(dir));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), dir);
}

#[test]
fn test_symlink_circular() {
    let (at, mut ucmd) = at_and_ucmd!();
    let link = "test_symlink_circular";

    ucmd.args(&["-s", link]).succeeds().no_stderr();
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), link);
}

#[test]
fn test_symlink_dont_overwrite() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_dont_overwrite";
    let link = "test_symlink_dont_overwrite_link";

    at.touch(file);
    at.touch(link);

    ucmd.args(&["-s", file, link]).fails();
    assert!(at.file_exists(file));
    assert!(at.file_exists(link));
    assert!(!at.is_symlink(link));
}

#[test]
fn test_symlink_overwrite_force() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_symlink_overwrite_force_a";
    let file_b = "test_symlink_overwrite_force_b";
    let link = "test_symlink_overwrite_force_link";

    // Create symlink
    at.symlink(file_a, link);
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file_a);

    // Force overwrite of existing symlink
    ucmd.args(&["--force", "-s", file_b, link]).succeeds();
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file_b);
}

#[test]
fn test_symlink_interactive() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let file = "test_symlink_interactive_file";
    let link = "test_symlink_interactive_file_link";

    at.touch(file);
    at.touch(link);

    scene.ucmd()
        .args(&["-i", "-s", file, link])
        .pipe_in("n").succeeds().no_stderr();

    assert!(at.file_exists(file));
    assert!(!at.is_symlink(link));

    scene.ucmd()
        .args(&["-i", "-s", file, link])
        .pipe_in("Yesh").succeeds().no_stderr();

    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);
}

#[test]
fn test_symlink_simple_backup() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_simple_backup";
    let link = "test_symlink_simple_backup_link";

    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    ucmd.args(&["-b", "-s", file, link]).succeeds().no_stderr();

    assert!(at.file_exists(file));

    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let backup = &format!("{}~", link);
    assert!(at.is_symlink(backup));
    assert_eq!(at.resolve_link(backup), file);
}

#[test]
fn test_symlink_custom_backup_suffix() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_custom_backup_suffix";
    let link = "test_symlink_custom_backup_suffix_link";
    let suffix = "super-suffix-of-the-century";

    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let arg = &format!("--suffix={}", suffix);
    ucmd.args(&["-b", arg, "-s", file, link]).succeeds().no_stderr();
    assert!(at.file_exists(file));

    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let backup = &format!("{}{}", link, suffix);
    assert!(at.is_symlink(backup));
    assert_eq!(at.resolve_link(backup), file);
}

#[test]
fn test_symlink_backup_numbering() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_backup_numbering";
    let link = "test_symlink_backup_numbering_link";

    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    ucmd.args(&["-s", "--backup=t", file, link]).succeeds().no_stderr();
    assert!(at.file_exists(file));

    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let backup = &format!("{}.~1~", link);
    assert!(at.is_symlink(backup));
    assert_eq!(at.resolve_link(backup), file);
}

#[test]
fn test_symlink_existing_backup() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_existing_backup";
    let link = "test_symlink_existing_backup_link";
    let link_backup = "test_symlink_existing_backup_link.~1~";
    let resulting_backup = "test_symlink_existing_backup_link.~2~";

    // Create symlink and verify
    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    // Create backup symlink and verify
    at.symlink(file, link_backup);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link_backup));
    assert_eq!(at.resolve_link(link_backup), file);

    ucmd.args(&["-s", "--backup=nil", file, link]).succeeds().no_stderr();
    assert!(at.file_exists(file));

    assert!(at.is_symlink(link_backup));
    assert_eq!(at.resolve_link(link_backup), file);

    assert!(at.is_symlink(resulting_backup));
    assert_eq!(at.resolve_link(resulting_backup), file);
}

#[test]
fn test_symlink_target_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_ln_target_dir_dir";
    let file_a = "test_ln_target_dir_file_a";
    let file_b = "test_ln_target_dir_file_b";

    at.touch(file_a);
    at.touch(file_b);
    at.mkdir(dir);

    ucmd.args(&["-s", "-t", dir, file_a, file_b]).succeeds().no_stderr();

    let file_a_link = &format!("{}/{}", dir, file_a);
    assert!(at.is_symlink(file_a_link));
    assert_eq!(at.resolve_link(file_a_link), file_a);

    let file_b_link = &format!("{}/{}", dir, file_b);
    assert!(at.is_symlink(file_b_link));
    assert_eq!(at.resolve_link(file_b_link), file_b);
}

#[test]
fn test_symlink_target_dir_from_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_ln_target_dir_dir";
    let from_dir = "test_ln_target_dir_from_dir";
    let filename_a = "test_ln_target_dir_file_a";
    let filename_b = "test_ln_target_dir_file_b";
    let file_a = &format!("{}/{}", from_dir, filename_a);
    let file_b = &format!("{}/{}", from_dir, filename_b);

    at.mkdir(from_dir);
    at.touch(file_a);
    at.touch(file_b);
    at.mkdir(dir);

    ucmd.args(&["-s", "-t", dir, file_a, file_b]).succeeds().no_stderr();

    let file_a_link = &format!("{}/{}", dir, filename_a);
    assert!(at.is_symlink(file_a_link));
    assert_eq!(&at.resolve_link(file_a_link), file_a);

    let file_b_link = &format!("{}/{}", dir, filename_b);
    assert!(at.is_symlink(file_b_link));
    assert_eq!(&at.resolve_link(file_b_link), file_b);
}

#[test]
fn test_symlink_overwrite_dir_fail() {
    let (at, mut ucmd) = at_and_ucmd!();
    let path_a = "test_symlink_overwrite_dir_a";
    let path_b = "test_symlink_overwrite_dir_b";

    at.touch(path_a);
    at.mkdir(path_b);

    assert!(ucmd.args(&["-s", "-T", path_a, path_b]).fails().stderr.len() > 0);
}

#[test]
fn test_symlink_errors() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_errors_dir";
    let file_a = "test_symlink_errors_file_a";
    let file_b = "test_symlink_errors_file_b";

    at.mkdir(dir);
    at.touch(file_a);
    at.touch(file_b);

    // $ ln -T -t a b
    // ln: cannot combine --target-directory (-t) and --no-target-directory (-T)
    ucmd.args(&["-T", "-t", dir, file_a, file_b]).fails()
        .stderr_is("ln: error: cannot combine --target-directory (-t) and --no-target-directory \
                (-T)\n");
}

#[test]
fn test_symlink_verbose() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let file_a = "test_symlink_verbose_file_a";
    let file_b = "test_symlink_verbose_file_b";

    at.touch(file_a);

    scene.ucmd().args(&["-v", file_a, file_b])
        .succeeds().stdout_only(format!("'{}' -> '{}'\n", file_b, file_a));

    at.touch(file_b);

    scene.ucmd().args(&["-v", "-b", file_a, file_b])
        .succeeds().stdout_only(format!("'{}' -> '{}' (backup: '{}~')\n", file_b, file_a, file_b));
}

#[test]
fn test_symlink_target_only() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_target_only";

    at.mkdir(dir);

    assert!(ucmd.args(&["-s", "-t", dir]).fails().stderr.len() > 0);
}

#[test]
fn test_symlink_implicit_target_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_implicit_target_dir";
    let file = "test_symlink_implicit_target_dir/file";

    at.mkdir(dir);
    at.touch(file);

    ucmd.args(&["-s", file]).succeeds().no_stderr();

    assert!(at.file_exists("file"));
    assert!(at.is_symlink("file"));
    assert_eq!(at.resolve_link("file"), file);
}

#[test]
fn test_symlink_to_dir_2args() {
    let (at, mut ucmd) = at_and_ucmd!();
    let filename = "test_symlink_to_dir_2args_file";
    let from_file = &format!("{}/{}", at.as_string(), filename);
    let to_dir = "test_symlink_to_dir_2args_to_dir";
    let to_file = &format!("{}/{}", to_dir, filename);

    at.mkdir(to_dir);
    at.touch(from_file);

    ucmd.args(&["-s", from_file, to_dir]).succeeds().no_stderr();

    assert!(at.file_exists(to_file));
    assert!(at.is_symlink(to_file));
    assert_eq!(at.resolve_link(to_file), filename);
}

#[test]
fn test_symlink_missing_destination() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_missing_destination";

    at.touch(file);

    ucmd.args(&["-s", "-T", file]).fails()
        .stderr_is(format!("ln: error: missing destination file operand after '{}'", file));
}
<commit_msg>Fix the windows failure<commit_after>use common::util::*;
use std::path::PathBuf;

#[test]
fn test_symlink_existing_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_existing_file";
    let link = "test_symlink_existing_file_link";

    at.touch(file);

    ucmd.args(&["-s", file, link]).succeeds().no_stderr();

    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);
}

#[test]
fn test_symlink_dangling_file() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_dangling_file";
    let link = "test_symlink_dangling_file_link";

    ucmd.args(&["-s", file, link]).succeeds().no_stderr();
    assert!(!at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);
}

#[test]
fn test_symlink_existing_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_existing_dir";
    let link = "test_symlink_existing_dir_link";

    at.mkdir(dir);

    ucmd.args(&["-s", dir, link]).succeeds().no_stderr();
    assert!(at.dir_exists(dir));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), dir);
}

#[test]
fn test_symlink_dangling_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_dangling_dir";
    let link = "test_symlink_dangling_dir_link";

    ucmd.args(&["-s", dir, link]).succeeds().no_stderr();
    assert!(!at.dir_exists(dir));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), dir);
}

#[test]
fn test_symlink_circular() {
    let (at, mut ucmd) = at_and_ucmd!();
    let link = "test_symlink_circular";

    ucmd.args(&["-s", link]).succeeds().no_stderr();
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), link);
}

#[test]
fn test_symlink_dont_overwrite() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_dont_overwrite";
    let link = "test_symlink_dont_overwrite_link";

    at.touch(file);
    at.touch(link);

    ucmd.args(&["-s", file, link]).fails();
    assert!(at.file_exists(file));
    assert!(at.file_exists(link));
    assert!(!at.is_symlink(link));
}

#[test]
fn test_symlink_overwrite_force() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file_a = "test_symlink_overwrite_force_a";
    let file_b = "test_symlink_overwrite_force_b";
    let link = "test_symlink_overwrite_force_link";

    // Create symlink
    at.symlink(file_a, link);
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file_a);

    // Force overwrite of existing symlink
    ucmd.args(&["--force", "-s", file_b, link]).succeeds();
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file_b);
}

#[test]
fn test_symlink_interactive() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let file = "test_symlink_interactive_file";
    let link = "test_symlink_interactive_file_link";

    at.touch(file);
    at.touch(link);

    scene.ucmd()
        .args(&["-i", "-s", file, link])
        .pipe_in("n").succeeds().no_stderr();

    assert!(at.file_exists(file));
    assert!(!at.is_symlink(link));

    scene.ucmd()
        .args(&["-i", "-s", file, link])
        .pipe_in("Yesh").succeeds().no_stderr();

    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);
}

#[test]
fn test_symlink_simple_backup() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_simple_backup";
    let link = "test_symlink_simple_backup_link";

    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    ucmd.args(&["-b", "-s", file, link]).succeeds().no_stderr();

    assert!(at.file_exists(file));

    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let backup = &format!("{}~", link);
    assert!(at.is_symlink(backup));
    assert_eq!(at.resolve_link(backup), file);
}

#[test]
fn test_symlink_custom_backup_suffix() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_custom_backup_suffix";
    let link = "test_symlink_custom_backup_suffix_link";
    let suffix = "super-suffix-of-the-century";

    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let arg = &format!("--suffix={}", suffix);
    ucmd.args(&["-b", arg, "-s", file, link]).succeeds().no_stderr();
    assert!(at.file_exists(file));

    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let backup = &format!("{}{}", link, suffix);
    assert!(at.is_symlink(backup));
    assert_eq!(at.resolve_link(backup), file);
}

#[test]
fn test_symlink_backup_numbering() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_backup_numbering";
    let link = "test_symlink_backup_numbering_link";

    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    ucmd.args(&["-s", "--backup=t", file, link]).succeeds().no_stderr();
    assert!(at.file_exists(file));

    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    let backup = &format!("{}.~1~", link);
    assert!(at.is_symlink(backup));
    assert_eq!(at.resolve_link(backup), file);
}

#[test]
fn test_symlink_existing_backup() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_existing_backup";
    let link = "test_symlink_existing_backup_link";
    let link_backup = "test_symlink_existing_backup_link.~1~";
    let resulting_backup = "test_symlink_existing_backup_link.~2~";

    // Create symlink and verify
    at.touch(file);
    at.symlink(file, link);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link));
    assert_eq!(at.resolve_link(link), file);

    // Create backup symlink and verify
    at.symlink(file, link_backup);
    assert!(at.file_exists(file));
    assert!(at.is_symlink(link_backup));
    assert_eq!(at.resolve_link(link_backup), file);

    ucmd.args(&["-s", "--backup=nil", file, link]).succeeds().no_stderr();
    assert!(at.file_exists(file));

    assert!(at.is_symlink(link_backup));
    assert_eq!(at.resolve_link(link_backup), file);

    assert!(at.is_symlink(resulting_backup));
    assert_eq!(at.resolve_link(resulting_backup), file);
}

#[test]
fn test_symlink_target_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_ln_target_dir_dir";
    let file_a = "test_ln_target_dir_file_a";
    let file_b = "test_ln_target_dir_file_b";

    at.touch(file_a);
    at.touch(file_b);
    at.mkdir(dir);

    ucmd.args(&["-s", "-t", dir, file_a, file_b]).succeeds().no_stderr();

    let file_a_link = &format!("{}/{}", dir, file_a);
    assert!(at.is_symlink(file_a_link));
    assert_eq!(at.resolve_link(file_a_link), file_a);

    let file_b_link = &format!("{}/{}", dir, file_b);
    assert!(at.is_symlink(file_b_link));
    assert_eq!(at.resolve_link(file_b_link), file_b);
}

#[test]
fn test_symlink_target_dir_from_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_ln_target_dir_dir";
    let from_dir = "test_ln_target_dir_from_dir";
    let filename_a = "test_ln_target_dir_file_a";
    let filename_b = "test_ln_target_dir_file_b";
    let file_a = &format!("{}/{}", from_dir, filename_a);
    let file_b = &format!("{}/{}", from_dir, filename_b);

    at.mkdir(from_dir);
    at.touch(file_a);
    at.touch(file_b);
    at.mkdir(dir);

    ucmd.args(&["-s", "-t", dir, file_a, file_b]).succeeds().no_stderr();

    let file_a_link = &format!("{}/{}", dir, filename_a);
    assert!(at.is_symlink(file_a_link));
    assert_eq!(&at.resolve_link(file_a_link), file_a);

    let file_b_link = &format!("{}/{}", dir, filename_b);
    assert!(at.is_symlink(file_b_link));
    assert_eq!(&at.resolve_link(file_b_link), file_b);
}

#[test]
fn test_symlink_overwrite_dir_fail() {
    let (at, mut ucmd) = at_and_ucmd!();
    let path_a = "test_symlink_overwrite_dir_a";
    let path_b = "test_symlink_overwrite_dir_b";

    at.touch(path_a);
    at.mkdir(path_b);

    assert!(ucmd.args(&["-s", "-T", path_a, path_b]).fails().stderr.len() > 0);
}

#[test]
fn test_symlink_errors() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_errors_dir";
    let file_a = "test_symlink_errors_file_a";
    let file_b = "test_symlink_errors_file_b";

    at.mkdir(dir);
    at.touch(file_a);
    at.touch(file_b);

    // $ ln -T -t a b
    // ln: cannot combine --target-directory (-t) and --no-target-directory (-T)
    ucmd.args(&["-T", "-t", dir, file_a, file_b]).fails()
        .stderr_is("ln: error: cannot combine --target-directory (-t) and --no-target-directory \
                (-T)\n");
}

#[test]
fn test_symlink_verbose() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;
    let file_a = "test_symlink_verbose_file_a";
    let file_b = "test_symlink_verbose_file_b";

    at.touch(file_a);

    scene.ucmd().args(&["-v", file_a, file_b])
        .succeeds().stdout_only(format!("'{}' -> '{}'\n", file_b, file_a));

    at.touch(file_b);

    scene.ucmd().args(&["-v", "-b", file_a, file_b])
        .succeeds().stdout_only(format!("'{}' -> '{}' (backup: '{}~')\n", file_b, file_a, file_b));
}

#[test]
fn test_symlink_target_only() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_target_only";

    at.mkdir(dir);

    assert!(ucmd.args(&["-s", "-t", dir]).fails().stderr.len() > 0);
}

#[test]
fn test_symlink_implicit_target_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    let dir = "test_symlink_implicit_target_dir";
    // On windows, slashes aren't allowed in symlink targets, so use
    // PathBuf to construct `file` instead of simple "dir/file".
    let filename = "test_symlink_implicit_target_file";
    let path = PathBuf::from(dir).join(filename);
    let file = &path.to_string_lossy();

    at.mkdir(dir);
    at.touch(file);

    ucmd.args(&["-s", file]).succeeds().no_stderr();

    assert!(at.file_exists(filename));
    assert!(at.is_symlink(filename));
    assert_eq!(at.resolve_link(filename), *file);
}

#[test]
fn test_symlink_to_dir_2args() {
    let (at, mut ucmd) = at_and_ucmd!();
    let filename = "test_symlink_to_dir_2args_file";
    let from_file = &format!("{}/{}", at.as_string(), filename);
    let to_dir = "test_symlink_to_dir_2args_to_dir";
    let to_file = &format!("{}/{}", to_dir, filename);

    at.mkdir(to_dir);
    at.touch(from_file);

    ucmd.args(&["-s", from_file, to_dir]).succeeds().no_stderr();

    assert!(at.file_exists(to_file));
    assert!(at.is_symlink(to_file));
    assert_eq!(at.resolve_link(to_file), filename);
}

#[test]
fn test_symlink_missing_destination() {
    let (at, mut ucmd) = at_and_ucmd!();
    let file = "test_symlink_missing_destination";

    at.touch(file);

    ucmd.args(&["-s", "-T", file]).fails()
        .stderr_is(format!("ln: error: missing destination file operand after '{}'", file));
}
<|endoftext|>