<commit_before>extern crate icepick;

#[cfg(test)]
mod tests {
    pub use icepick::search::Search;

    pub fn input_times(n: usize) ->Vec<String> {
        let choices = vec!["choice".to_string()];
        let mut result: Vec<String> = Vec::new();
        for choice in choices.iter().cycle().take(n) {
            result.push(choice.clone());
        }
        result
    }

    #[test]
    fn it_selects_the_first_choice_by_default() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.selection(), Some("one".to_string()));
    }

    #[test]
    fn it_selets_the_second_when_down_is_called() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_end_of_list() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().down().down().down().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_top_of_list() {
        let choices = vec!["one".to_string(), "two".to_string(), "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.up().up().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_visible_limit() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().down().down().down().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("t").down().selection(), Some("three".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results_twice() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("t").append_to_search("w").selection(), Some("two".to_string()));
    }

    #[test]
    fn it_handles_not_matching_anything() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("x").selection(), None);
    }

    #[test]
    fn up_match_nothing_after_filtering_all_out() {
        let choices = vec!["one".to_string(), "two".to_string(), "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("x").up().selection(), None);
    }

    #[test]
    fn down_match_nothing_after_filtering_all_out() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("x").down().selection(), None);
    }

    #[test]
    fn backspaces_over_characters() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        search = search.append_to_search("e");

        assert_eq!(search.query, "e");
        assert_eq!(search.backspace().query, "");
    }

    #[test]
    fn resets_the_index_when_removing_char_from_search() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("e").down().backspace().current, 0);
    }

    #[test]
    fn resets_the_index_when_adding_char_to_seach() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().append_to_search("o").current, 0);
    }

    #[test]
    fn previous_results_appear_after_backspace() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("t").backspace().num_matches(), 3);
    }

    #[test]
    fn initial_search_is_not_done() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert!(!search.is_done());
    }

    #[test]
    fn backspace_over_initial_doesnt_crash() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        search.backspace();
    }

    #[test]
    fn done_search_is_done() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert!(search.done().is_done());
    }

    #[test]
    fn done_search_has_selection() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.done().selection(), Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_bottom_of_choices() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("n").down().selection(), Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_top_of_choices() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("n").up().selection(), Some("one".to_string()));
    }

    #[test]
    fn search_is_case_insensitive() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("T").num_matches(), 2);
    }

    #[test]
    fn uses_configs_visible_limit_as_result_size() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let mut search = Search::blank(&choices, None, 20);

        let many_choices = input_times(30);
        let search = Search::blank(&many_choices, None, 20).append_to_search("c");

        assert_eq!(search.result.len(), 20);
    }
}
<commit_msg>Fix warnings about dropping mutability for search<commit_after>extern crate icepick;

#[cfg(test)]
mod tests {
    pub use icepick::search::Search;

    pub fn input_times(n: usize) ->Vec<String> {
        let choices = vec!["choice".to_string()];
        let mut result: Vec<String> = Vec::new();
        for choice in choices.iter().cycle().take(n) {
            result.push(choice.clone());
        }
        result
    }

    #[test]
    fn it_selects_the_first_choice_by_default() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let search = Search::blank(&choices, None, 20);

        assert_eq!(search.selection(), Some("one".to_string()));
    }

    #[test]
    fn it_selets_the_second_when_down_is_called() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_end_of_list() {
        let choices = vec!["one".to_string(),
                           "two".to_string(),
                           "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().down().down().down().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_top_of_list() {
        let choices = vec!["one".to_string(),
                           "two".to_string(),
                           "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.up().up().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_visible_limit() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().down().down().down().selection(), Some("two".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("t").down().selection(), Some("three".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results_twice() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("t").append_to_search("w").selection(), Some("two".to_string()));
    }

    #[test]
    fn it_handles_not_matching_anything() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("x").selection(), None);
    }

    #[test]
    fn up_match_nothing_after_filtering_all_out() {
        let choices = vec!["one".to_string(), "two".to_string(), "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("x").up().selection(), None);
    }

    #[test]
    fn down_match_nothing_after_filtering_all_out() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("x").down().selection(), None);
    }

    #[test]
    fn backspaces_over_characters() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let initial = Search::blank(&choices, None, 20);

        let search = initial.append_to_search("e");

        assert_eq!(search.query, "e");
        assert_eq!(search.backspace().query, "");
    }

    #[test]
    fn resets_the_index_when_removing_char_from_search() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("e").down().backspace().current, 0);
    }

    #[test]
    fn resets_the_index_when_adding_char_to_seach() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.down().append_to_search("o").current, 0);
    }

    #[test]
    fn previous_results_appear_after_backspace() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("t").backspace().num_matches(), 3);
    }

    #[test]
    fn initial_search_is_not_done() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert!(!search.is_done());
    }

    #[test]
    fn backspace_over_initial_doesnt_crash() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        search.backspace();
    }

    #[test]
    fn done_search_is_done() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert!(search.done().is_done());
    }

    #[test]
    fn done_search_has_selection() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.done().selection(), Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_bottom_of_choices() {
        let choices = vec!["one".to_string(), "two".to_string(), "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("n").down().selection(), Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_top_of_choices() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("n").up().selection(), Some("one".to_string()));
    }

    #[test]
    fn search_is_case_insensitive() {
        let choices = vec!["one".to_string(),
        "two".to_string(),
        "three".to_string()];
        let  search = Search::blank(&choices, None, 20);

        assert_eq!(search.append_to_search("T").num_matches(), 2);
    }

    #[test]
    fn uses_configs_visible_limit_as_result_size() {
        let many_choices = input_times(30);
        let search = Search::blank(&many_choices, None, 20).append_to_search("c");

        assert_eq!(search.result.len(), 20);
    }
}
<|endoftext|>


<commit_before>//! Argument passing

use crate::prelude::*;

pub(super) use EmptySinglePair::*;

#[derive(Copy, Clone, Debug)]
pub(super) enum PassMode {
    NoPass,
    ByVal(Type),
    ByValPair(Type, Type),
    ByRef { size: Option<Size> },
}

#[derive(Copy, Clone, Debug)]
pub(super) enum EmptySinglePair<T> {
    Empty,
    Single(T),
    Pair(T, T),
}

impl<T> EmptySinglePair<T> {
    pub(super) fn into_iter(self) -> EmptySinglePairIter<T> {
        EmptySinglePairIter(self)
    }

    pub(super) fn map<U>(self, mut f: impl FnMut(T) -> U) -> EmptySinglePair<U> {
        match self {
            Empty => Empty,
            Single(v) => Single(f(v)),
            Pair(a, b) => Pair(f(a), f(b)),
        }
    }
}

pub(super) struct EmptySinglePairIter<T>(EmptySinglePair<T>);

impl<T> Iterator for EmptySinglePairIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        match std::mem::replace(&mut self.0, Empty) {
            Empty => None,
            Single(v) => Some(v),
            Pair(a, b) => {
                self.0 = Single(b);
                Some(a)
            }
        }
    }
}

impl<T: std::fmt::Debug> EmptySinglePair<T> {
    pub(super) fn assert_single(self) -> T {
        match self {
            Single(v) => v,
            _ => panic!("Called assert_single on {:?}", self),
        }
    }

    pub(super) fn assert_pair(self) -> (T, T) {
        match self {
            Pair(a, b) => (a, b),
            _ => panic!("Called assert_pair on {:?}", self),
        }
    }
}

impl PassMode {
    pub(super) fn get_param_ty(self, tcx: TyCtxt<'_>) -> EmptySinglePair<Type> {
        match self {
            PassMode::NoPass => Empty,
            PassMode::ByVal(clif_type) => Single(clif_type),
            PassMode::ByValPair(a, b) => Pair(a, b),
            PassMode::ByRef { size: Some(_) } => Single(pointer_ty(tcx)),
            PassMode::ByRef { size: None } => Pair(pointer_ty(tcx), pointer_ty(tcx)),
        }
    }
}

pub(super) fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> PassMode {
    if layout.is_zst() {
        // WARNING zst arguments must never be passed, as that will break CastKind::ClosureFnPointer
        PassMode::NoPass
    } else {
        match &layout.abi {
            Abi::Uninhabited => PassMode::NoPass,
            Abi::Scalar(scalar) => PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())),
            Abi::ScalarPair(a, b) => {
                let a = scalar_to_clif_type(tcx, a.clone());
                let b = scalar_to_clif_type(tcx, b.clone());
                if a == types::I128 && b == types::I128 {
                    // Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are
                    // available on x86_64. Cranelift gets confused when too many return params
                    // are used.
                    PassMode::ByRef {
                        size: Some(layout.size),
                    }
                } else {
                    PassMode::ByValPair(a, b)
                }
            }

            // FIXME implement Vector Abi in a cg_llvm compatible way
            Abi::Vector { .. } => {
                if let Some(vector_ty) = crate::intrinsics::clif_vector_type(tcx, layout) {
                    PassMode::ByVal(vector_ty)
                } else {
                    PassMode::ByRef {
                        size: Some(layout.size),
                    }
                }
            }

            Abi::Aggregate { sized: true } => PassMode::ByRef {
                size: Some(layout.size),
            },
            Abi::Aggregate { sized: false } => PassMode::ByRef { size: None },
        }
    }
}

/// Get a set of values to be passed as function arguments.
pub(super) fn adjust_arg_for_abi<'tcx>(
    fx: &mut FunctionCx<'_, 'tcx, impl Module>,
    arg: CValue<'tcx>,
) -> EmptySinglePair<Value> {
    match get_pass_mode(fx.tcx, arg.layout()) {
        PassMode::NoPass => Empty,
        PassMode::ByVal(_) => Single(arg.load_scalar(fx)),
        PassMode::ByValPair(_, _) => {
            let (a, b) = arg.load_scalar_pair(fx);
            Pair(a, b)
        }
        PassMode::ByRef { size: _ } => match arg.force_stack(fx) {
            (ptr, None) => Single(ptr.get_addr(fx)),
            (ptr, Some(meta)) => Pair(ptr.get_addr(fx), meta),
        },
    }
}

/// Create a [`CValue`] containing the value of a function parameter adding clif function parameters
/// as necessary.
pub(super) fn cvalue_for_param<'tcx>(
    fx: &mut FunctionCx<'_, 'tcx, impl Module>,
    start_block: Block,
    #[cfg_attr(not(debug_assertions), allow(unused_variables))] local: Option<mir::Local>,
    #[cfg_attr(not(debug_assertions), allow(unused_variables))] local_field: Option<usize>,
    arg_ty: Ty<'tcx>,
) -> Option<CValue<'tcx>> {
    let layout = fx.layout_of(arg_ty);
    let pass_mode = get_pass_mode(fx.tcx, layout);

    if let PassMode::NoPass = pass_mode {
        return None;
    }

    let clif_types = pass_mode.get_param_ty(fx.tcx);
    let block_params = clif_types.map(|t| fx.bcx.append_block_param(start_block, t));

    #[cfg(debug_assertions)]
    crate::abi::comments::add_arg_comment(
        fx,
        "arg",
        local,
        local_field,
        block_params,
        pass_mode,
        arg_ty,
    );

    match pass_mode {
        PassMode::NoPass => unreachable!(),
        PassMode::ByVal(_) => Some(CValue::by_val(block_params.assert_single(), layout)),
        PassMode::ByValPair(_, _) => {
            let (a, b) = block_params.assert_pair();
            Some(CValue::by_val_pair(a, b, layout))
        }
        PassMode::ByRef { size: Some(_) } => Some(CValue::by_ref(
            Pointer::new(block_params.assert_single()),
            layout,
        )),
        PassMode::ByRef { size: None } => {
            let (ptr, meta) = block_params.assert_pair();
            Some(CValue::by_ref_unsized(Pointer::new(ptr), meta, layout))
        }
    }
}
<commit_msg>Start using ArgAbi<commit_after>//! Argument passing

use crate::prelude::*;

use rustc_target::abi::call::{ArgAbi, ArgAttributes, PassMode as RustcPassMode};
pub(super) use EmptySinglePair::*;

#[derive(Copy, Clone, Debug)]
pub(super) enum PassMode {
    NoPass,
    ByVal(Type),
    ByValPair(Type, Type),
    ByRef { size: Option<Size> },
}

#[derive(Copy, Clone, Debug)]
pub(super) enum EmptySinglePair<T> {
    Empty,
    Single(T),
    Pair(T, T),
}

impl<T> EmptySinglePair<T> {
    pub(super) fn into_iter(self) -> EmptySinglePairIter<T> {
        EmptySinglePairIter(self)
    }

    pub(super) fn map<U>(self, mut f: impl FnMut(T) -> U) -> EmptySinglePair<U> {
        match self {
            Empty => Empty,
            Single(v) => Single(f(v)),
            Pair(a, b) => Pair(f(a), f(b)),
        }
    }
}

pub(super) struct EmptySinglePairIter<T>(EmptySinglePair<T>);

impl<T> Iterator for EmptySinglePairIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        match std::mem::replace(&mut self.0, Empty) {
            Empty => None,
            Single(v) => Some(v),
            Pair(a, b) => {
                self.0 = Single(b);
                Some(a)
            }
        }
    }
}

impl<T: std::fmt::Debug> EmptySinglePair<T> {
    pub(super) fn assert_single(self) -> T {
        match self {
            Single(v) => v,
            _ => panic!("Called assert_single on {:?}", self),
        }
    }

    pub(super) fn assert_pair(self) -> (T, T) {
        match self {
            Pair(a, b) => (a, b),
            _ => panic!("Called assert_pair on {:?}", self),
        }
    }
}

impl PassMode {
    pub(super) fn get_param_ty(self, tcx: TyCtxt<'_>) -> EmptySinglePair<Type> {
        match self {
            PassMode::NoPass => Empty,
            PassMode::ByVal(clif_type) => Single(clif_type),
            PassMode::ByValPair(a, b) => Pair(a, b),
            PassMode::ByRef { size: Some(_) } => Single(pointer_ty(tcx)),
            PassMode::ByRef { size: None } => Pair(pointer_ty(tcx), pointer_ty(tcx)),
        }
    }
}

pub(super) fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> PassMode {
    if layout.is_zst() {
        // WARNING zst arguments must never be passed, as that will break CastKind::ClosureFnPointer
        PassMode::NoPass
    } else {
        let arg_abi = ArgAbi::new(&tcx, layout, |_, _, _| ArgAttributes::new());
        match arg_abi.mode {
            RustcPassMode::Ignore => PassMode::NoPass,
            RustcPassMode::Direct(_) => match &arg_abi.layout.abi {
                Abi::Scalar(scalar) => PassMode::ByVal(scalar_to_clif_type(tcx, scalar.clone())),
                // FIXME implement Vector Abi in a cg_llvm compatible way
                Abi::Vector { .. } => {
                    if let Some(vector_ty) = crate::intrinsics::clif_vector_type(tcx, arg_abi.layout) {
                        PassMode::ByVal(vector_ty)
                    } else {
                        PassMode::ByRef {
                            size: Some(arg_abi.layout.size),
                        }
                    }
                }
                _ => unreachable!("{:?}", arg_abi.layout.abi)
            },
            RustcPassMode::Pair(_, _) => match &arg_abi.layout.abi {
                Abi::ScalarPair(a, b) => {
                    let a = scalar_to_clif_type(tcx, a.clone());
                    let b = scalar_to_clif_type(tcx, b.clone());
                    if a == types::I128 && b == types::I128 {
                        // Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are
                        // available on x86_64. Cranelift gets confused when too many return params
                        // are used.
                        PassMode::ByRef {
                            size: Some(arg_abi.layout.size),
                        }
                    } else {
                        PassMode::ByValPair(a, b)
                    }
                }
                _ => unreachable!("{:?}", arg_abi.layout.abi)
            },
            RustcPassMode::Cast(_) | RustcPassMode::Indirect {
                attrs: _,
                extra_attrs: None,
                on_stack: false,
            } => PassMode::ByRef {
                size: Some(arg_abi.layout.size),
            },
            RustcPassMode::Indirect {
                attrs: _,
                extra_attrs,
                on_stack: true,
            } => {
                assert!(extra_attrs.is_none());
                PassMode::ByRef {
                    size: Some(arg_abi.layout.size)
                }
            }
            RustcPassMode::Indirect {
                attrs: _,
                extra_attrs: Some(_),
                on_stack: false,
            } => PassMode::ByRef {
                size: None,
            },
        }
    }
}

/// Get a set of values to be passed as function arguments.
pub(super) fn adjust_arg_for_abi<'tcx>(
    fx: &mut FunctionCx<'_, 'tcx, impl Module>,
    arg: CValue<'tcx>,
) -> EmptySinglePair<Value> {
    match get_pass_mode(fx.tcx, arg.layout()) {
        PassMode::NoPass => Empty,
        PassMode::ByVal(_) => Single(arg.load_scalar(fx)),
        PassMode::ByValPair(_, _) => {
            let (a, b) = arg.load_scalar_pair(fx);
            Pair(a, b)
        }
        PassMode::ByRef { size: _ } => match arg.force_stack(fx) {
            (ptr, None) => Single(ptr.get_addr(fx)),
            (ptr, Some(meta)) => Pair(ptr.get_addr(fx), meta),
        },
    }
}

/// Create a [`CValue`] containing the value of a function parameter adding clif function parameters
/// as necessary.
pub(super) fn cvalue_for_param<'tcx>(
    fx: &mut FunctionCx<'_, 'tcx, impl Module>,
    start_block: Block,
    #[cfg_attr(not(debug_assertions), allow(unused_variables))] local: Option<mir::Local>,
    #[cfg_attr(not(debug_assertions), allow(unused_variables))] local_field: Option<usize>,
    arg_ty: Ty<'tcx>,
) -> Option<CValue<'tcx>> {
    let layout = fx.layout_of(arg_ty);
    let pass_mode = get_pass_mode(fx.tcx, layout);

    if let PassMode::NoPass = pass_mode {
        return None;
    }

    let clif_types = pass_mode.get_param_ty(fx.tcx);
    let block_params = clif_types.map(|t| fx.bcx.append_block_param(start_block, t));

    #[cfg(debug_assertions)]
    crate::abi::comments::add_arg_comment(
        fx,
        "arg",
        local,
        local_field,
        block_params,
        pass_mode,
        arg_ty,
    );

    match pass_mode {
        PassMode::NoPass => unreachable!(),
        PassMode::ByVal(_) => Some(CValue::by_val(block_params.assert_single(), layout)),
        PassMode::ByValPair(_, _) => {
            let (a, b) = block_params.assert_pair();
            Some(CValue::by_val_pair(a, b, layout))
        }
        PassMode::ByRef { size: Some(_) } => Some(CValue::by_ref(
            Pointer::new(block_params.assert_single()),
            layout,
        )),
        PassMode::ByRef { size: None } => {
            let (ptr, meta) = block_params.assert_pair();
            Some(CValue::by_ref_unsized(Pointer::new(ptr), meta, layout))
        }
    }
}
<|endoftext|>


<commit_before>#![cfg(thiserror_nightly_testing)]
#![feature(backtrace)]

use std::backtrace::Backtrace;
use thiserror::Error;

#[derive(Error, Debug)]
#[error("...")]
pub struct OptSourceNoBacktraceStruct {
    #[source]
    source: Option<anyhow::Error>,
}

#[derive(Error, Debug)]
#[error("...")]
pub struct OptSourceAlwaysBacktraceStruct {
    #[source]
    source: Option<anyhow::Error>,
    backtrace: Backtrace,
}

#[derive(Error, Debug)]
pub enum OptSourceNoBacktraceEnum {
    #[error("...")]
    Test {
        #[source]
        source: Option<anyhow::Error>,
    },
}

#[derive(Error, Debug)]
pub enum OptSourceAlwaysBacktraceEnum {
    #[error("...")]
    Test {
        #[source]
        source: Option<anyhow::Error>,
        backtrace: Backtrace,
    },
}
<commit_msg>Add test for optional backtrace<commit_after>#![cfg(thiserror_nightly_testing)]
#![feature(backtrace)]

use std::backtrace::Backtrace;
use thiserror::Error;

pub mod structs {
    use super::*;

    #[derive(Error, Debug)]
    #[error("...")]
    pub struct OptSourceNoBacktrace {
        #[source]
        source: Option<anyhow::Error>,
    }

    #[derive(Error, Debug)]
    #[error("...")]
    pub struct OptSourceAlwaysBacktrace {
        #[source]
        source: Option<anyhow::Error>,
        backtrace: Backtrace,
    }

    #[derive(Error, Debug)]
    #[error("...")]
    pub struct NoSourceOptBacktrace {
        #[backtrace]
        backtrace: Option<Backtrace>,
    }

    #[derive(Error, Debug)]
    #[error("...")]
    pub struct AlwaysSourceOptBacktrace {
        source: anyhow::Error,
        #[backtrace]
        backtrace: Option<Backtrace>,
    }

    #[derive(Error, Debug)]
    #[error("...")]
    pub struct OptSourceOptBacktrace {
        #[source]
        source: Option<anyhow::Error>,
        #[backtrace]
        backtrace: Option<Backtrace>,
    }
}

pub mod enums {
    use super::*;

    #[derive(Error, Debug)]
    pub enum OptSourceNoBacktrace {
        #[error("...")]
        Test {
            #[source]
            source: Option<anyhow::Error>,
        },
    }

    #[derive(Error, Debug)]
    pub enum OptSourceAlwaysBacktrace {
        #[error("...")]
        Test {
            #[source]
            source: Option<anyhow::Error>,
            backtrace: Backtrace,
        },
    }

    #[derive(Error, Debug)]
    pub enum NoSourceOptBacktrace {
        #[error("...")]
        Test {
            #[backtrace]
            backtrace: Option<Backtrace>,
        },
    }

    #[derive(Error, Debug)]
    pub enum AlwaysSourceOptBacktrace {
        #[error("...")]
        Test {
            source: anyhow::Error,
            #[backtrace]
            backtrace: Option<Backtrace>,
        },
    }

    #[derive(Error, Debug)]
    pub enum OptSourceOptBacktrace {
        #[error("...")]
        Test {
            #[source]
            source: Option<anyhow::Error>,
            #[backtrace]
            backtrace: Option<Backtrace>,
        },
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Server, Packet, PollEmpty, PacketConnect, PacketMessage, PacketDisconnect, PollDisconnected};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::time::duration::Duration;

mod test_shared;

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, ConnectionConfig<Vec<u8>>) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, Duration::seconds(10), test_shared::deserializer, test_shared::serializer);
    (my_addr, settings)
}

/**
 * Test we can start listening
 */
#[test]
fn create_server() {
    let socket = 64000;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(server) => (), //passed
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we get empty polls when we have no clients
 */
#[test]
fn empty_poll() {
    unimplemented!()
}

/**
 * Test we reject bad connection attempts
 */
#[test]
fn bad_client_attempt() {
    unimplemented!()
}

/**
 * Test we can take multiple clients
 */
#[test]
fn multiple_clients() {
    unimplemented!()
}

/**
 * Test we can cull old clients
 */
#[test]
fn cull() {
    unimplemented!()
}

/**
 * Test we can send to one
 */
#[test]
fn send_to_one() {
    unimplemented!()
}

/**
 * Test we can't send to folks who aren't connected
 */
#[test]
fn send_to_disconnected() {
    unimplemented!()
}

/**
 * Test we can send to multiple folks
 */
#[test]
fn send_to_many() {
    unimplemented!()
}

/**
 * Test we can send to everyone connected
 */
#[test]
fn send_to_all() {
    unimplemented!()
}
<commit_msg>Test for empty poll<commit_after>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Server, Packet, PollEmpty, PacketConnect, PacketMessage, PacketDisconnect, PollDisconnected};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::time::duration::Duration;

mod test_shared;

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, ConnectionConfig<Vec<u8>>) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, Duration::seconds(10), test_shared::deserializer, test_shared::serializer);
    (my_addr, settings)
}

/**
 * Test we can start listening
 */
#[test]
fn create_server() {
    let socket = 64000;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(_) => (), //passed
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we get empty polls when we have no clients
 */
#[test]
fn empty_poll() {
    let socket = 64001;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            assert!(server.poll().is_none())
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we reject bad connection attempts
 */
#[test]
fn bad_client_attempt() {
    unimplemented!()
}

/**
 * Test we can take multiple clients
 */
#[test]
fn multiple_clients() {
    unimplemented!()
}

/**
 * Test we can cull old clients
 */
#[test]
fn cull() {
    unimplemented!()
}

/**
 * Test we can send to one
 */
#[test]
fn send_to_one() {
    unimplemented!()
}

/**
 * Test we can't send to folks who aren't connected
 */
#[test]
fn send_to_disconnected() {
    unimplemented!()
}

/**
 * Test we can send to multiple folks
 */
#[test]
fn send_to_many() {
    unimplemented!()
}

/**
 * Test we can send to everyone connected
 */
#[test]
fn send_to_all() {
    unimplemented!()
}
<|endoftext|>


<commit_before>use syntax_pos::Span;

use crate::print::pprust::token_to_string;
use crate::parse::lexer::{StringReader, UnmatchedBrace};
use crate::parse::{token, PResult};
use crate::tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree, TreeAndJoint};

impl<'a> StringReader<'a> {
    crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
        let mut tt_reader = TokenTreesReader {
            string_reader: self,
            token: token::Eof,
            span: syntax_pos::DUMMY_SP,
            open_braces: Vec::new(),
            unmatched_braces: Vec::new(),
            matching_delim_spans: Vec::new(),
            last_unclosed_found_span: None,
        };
        let res = tt_reader.parse_all_token_trees();
        (res, tt_reader.unmatched_braces)
    }
}

struct TokenTreesReader<'a> {
    string_reader: StringReader<'a>,
    token: token::Token,
    span: Span,
    /// Stack of open delimiters and their spans. Used for error message.
    open_braces: Vec<(token::DelimToken, Span)>,
    unmatched_braces: Vec<UnmatchedBrace>,
    /// The type and spans for all braces
    ///
    /// Used only for error recovery when arriving to EOF with mismatched braces.
    matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
    last_unclosed_found_span: Option<Span>,
}

impl<'a> TokenTreesReader<'a> {
    // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
    fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
        let mut tts = Vec::new();

        self.real_token();
        while self.token != token::Eof {
            tts.push(self.parse_token_tree()?);
        }

        Ok(TokenStream::new(tts))
    }

    // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
    fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
        let mut tts = vec![];
        loop {
            if let token::CloseDelim(..) = self.token {
                return TokenStream::new(tts);
            }

            match self.parse_token_tree() {
                Ok(tree) => tts.push(tree),
                Err(mut e) => {
                    e.emit();
                    return TokenStream::new(tts);
                }
            }
        }
    }

    fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
        let sm = self.string_reader.sess.source_map();
        match self.token {
            token::Eof => {
                let msg = "this file contains an un-closed delimiter";
                let mut err = self.string_reader.sess.span_diagnostic
                    .struct_span_err(self.span, msg);
                for &(_, sp) in &self.open_braces {
                    err.span_label(sp, "un-closed delimiter");
                }

                if let Some((delim, _)) = self.open_braces.last() {
                    if let Some((_, open_sp, close_sp)) = self.matching_delim_spans.iter()
                        .filter(|(d, open_sp, close_sp)| {
                            if let Some(close_padding) = sm.span_to_margin(*close_sp) {
                                if let Some(open_padding) = sm.span_to_margin(*open_sp) {
                                    return delim == d && close_padding != open_padding;
                                }
                            }
                            false
                        }).next()  // these are in reverse order as they get inserted on close, but
                    {              // we want the last open/first close
                        err.span_label(
                            *open_sp,
                            "this delimiter might not be properly closed...",
                        );
                        err.span_label(
                            *close_sp,
                            "...as it matches this but it has different indentation",
                        );
                    }
                }
                Err(err)
            },
            token::OpenDelim(delim) => {
                // The span for beginning of the delimited section
                let pre_span = self.span;

                // Parse the open delimiter.
                self.open_braces.push((delim, self.span));
                self.real_token();

                // Parse the token trees within the delimiters.
                // We stop at any delimiter so we can try to recover if the user
                // uses an incorrect delimiter.
                let tts = self.parse_token_trees_until_close_delim();

                // Expand to cover the entire delimited token tree
                let delim_span = DelimSpan::from_pair(pre_span, self.span);

                match self.token {
                    // Correct delimiter.
                    token::CloseDelim(d) if d == delim => {
                        let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
                        if self.open_braces.len() == 0 {
                            // Clear up these spans to avoid suggesting them as we've found
                            // properly matched delimiters so far for an entire block.
                            self.matching_delim_spans.clear();
                        } else {
                            self.matching_delim_spans.push(
                                (open_brace, open_brace_span, self.span),
                            );
                        }
                        // Parse the close delimiter.
                        self.real_token();
                    }
                    // Incorrect delimiter.
                    token::CloseDelim(other) => {
                        let mut unclosed_delimiter = None;
                        let mut candidate = None;
                        if self.last_unclosed_found_span != Some(self.span) {
                            // do not complain about the same unclosed delimiter multiple times
                            self.last_unclosed_found_span = Some(self.span);
                            // This is a conservative error: only report the last unclosed
                            // delimiter. The previous unclosed delimiters could actually be
                            // closed! The parser just hasn't gotten to them yet.
                            if let Some(&(_, sp)) = self.open_braces.last() {
                                unclosed_delimiter = Some(sp);
                            };
                            if let Some(current_padding) = sm.span_to_margin(self.span) {
                                for (brace, brace_span) in &self.open_braces {
                                    if let Some(padding) = sm.span_to_margin(*brace_span) {
                                        // high likelihood of these two corresponding
                                        if current_padding == padding && brace == &other {
                                            candidate = Some(*brace_span);
                                        }
                                    }
                                }
                            }
                            let (tok, _) = self.open_braces.pop().unwrap();
                            self.unmatched_braces.push(UnmatchedBrace {
                                expected_delim: tok,
                                found_delim: other,
                                found_span: self.span,
                                unclosed_span: unclosed_delimiter,
                                candidate_span: candidate,
                            });
                        } else {
                            self.open_braces.pop();
                        }

                        // If the incorrect delimiter matches an earlier opening
                        // delimiter, then don't consume it (it can be used to
                        // close the earlier one). Otherwise, consume it.
                        // E.g., we try to recover from:
                        // fn foo() {
                        //     bar(baz(
                        // }  // Incorrect delimiter but matches the earlier `{`
                        if !self.open_braces.iter().any(|&(b, _)| b == other) {
                            self.real_token();
                        }
                    }
                    token::Eof => {
                        // Silently recover, the EOF token will be seen again
                        // and an error emitted then. Thus we don't pop from
                        // self.open_braces here.
                    },
                    _ => {}
                }

                Ok(TokenTree::Delimited(
                    delim_span,
                    delim,
                    tts.into()
                ).into())
            },
            token::CloseDelim(_) => {
                // An unexpected closing delimiter (i.e., there is no
                // matching opening delimiter).
                let token_str = token_to_string(&self.token);
                let msg = format!("unexpected close delimiter: `{}`", token_str);
                let mut err = self.string_reader.sess.span_diagnostic
                    .struct_span_err(self.span, &msg);
                err.span_label(self.span, "unexpected close delimiter");
                Err(err)
            },
            _ => {
                let tt = TokenTree::Token(self.span, self.token.clone());
                // Note that testing for joint-ness here is done via the raw
                // source span as the joint-ness is a property of the raw source
                // rather than wanting to take `override_span` into account.
                let raw = self.string_reader.peek_span_src_raw;
                self.real_token();
                let is_joint = raw.hi() == self.string_reader.peek_span_src_raw.lo()
                    && token::is_op(&self.token);
                Ok((tt, if is_joint { Joint } else { NonJoint }))
            }
        }
    }

    fn real_token(&mut self) {
        let t = self.string_reader.real_token();
        self.token = t.tok;
        self.span = t.sp;
    }
}

<commit_msg>move raw span to tt reader<commit_after>use syntax_pos::Span;

use crate::print::pprust::token_to_string;
use crate::parse::lexer::{StringReader, UnmatchedBrace};
use crate::parse::{token, PResult};
use crate::tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree, TreeAndJoint};

impl<'a> StringReader<'a> {
    crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
        let mut tt_reader = TokenTreesReader {
            string_reader: self,
            token: token::Eof,
            span: syntax_pos::DUMMY_SP,
            open_braces: Vec::new(),
            unmatched_braces: Vec::new(),
            matching_delim_spans: Vec::new(),
            last_unclosed_found_span: None,
        };
        let res = tt_reader.parse_all_token_trees();
        (res, tt_reader.unmatched_braces)
    }
}

struct TokenTreesReader<'a> {
    string_reader: StringReader<'a>,
    token: token::Token,
    span: Span,
    /// Stack of open delimiters and their spans. Used for error message.
    open_braces: Vec<(token::DelimToken, Span)>,
    unmatched_braces: Vec<UnmatchedBrace>,
    /// The type and spans for all braces
    ///
    /// Used only for error recovery when arriving to EOF with mismatched braces.
    matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
    last_unclosed_found_span: Option<Span>,
}

impl<'a> TokenTreesReader<'a> {
    // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
    fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
        let mut tts = Vec::new();

        self.real_token();
        while self.token != token::Eof {
            tts.push(self.parse_token_tree()?);
        }

        Ok(TokenStream::new(tts))
    }

    // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
    fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
        let mut tts = vec![];
        loop {
            if let token::CloseDelim(..) = self.token {
                return TokenStream::new(tts);
            }

            match self.parse_token_tree() {
                Ok(tree) => tts.push(tree),
                Err(mut e) => {
                    e.emit();
                    return TokenStream::new(tts);
                }
            }
        }
    }

    fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
        let sm = self.string_reader.sess.source_map();
        match self.token {
            token::Eof => {
                let msg = "this file contains an un-closed delimiter";
                let mut err = self.string_reader.sess.span_diagnostic
                    .struct_span_err(self.span, msg);
                for &(_, sp) in &self.open_braces {
                    err.span_label(sp, "un-closed delimiter");
                }

                if let Some((delim, _)) = self.open_braces.last() {
                    if let Some((_, open_sp, close_sp)) = self.matching_delim_spans.iter()
                        .filter(|(d, open_sp, close_sp)| {
                            if let Some(close_padding) = sm.span_to_margin(*close_sp) {
                                if let Some(open_padding) = sm.span_to_margin(*open_sp) {
                                    return delim == d && close_padding != open_padding;
                                }
                            }
                            false
                        }).next()  // these are in reverse order as they get inserted on close, but
                    {              // we want the last open/first close
                        err.span_label(
                            *open_sp,
                            "this delimiter might not be properly closed...",
                        );
                        err.span_label(
                            *close_sp,
                            "...as it matches this but it has different indentation",
                        );
                    }
                }
                Err(err)
            },
            token::OpenDelim(delim) => {
                // The span for beginning of the delimited section
                let pre_span = self.span;

                // Parse the open delimiter.
                self.open_braces.push((delim, self.span));
                self.real_token();

                // Parse the token trees within the delimiters.
                // We stop at any delimiter so we can try to recover if the user
                // uses an incorrect delimiter.
                let tts = self.parse_token_trees_until_close_delim();

                // Expand to cover the entire delimited token tree
                let delim_span = DelimSpan::from_pair(pre_span, self.span);

                match self.token {
                    // Correct delimiter.
                    token::CloseDelim(d) if d == delim => {
                        let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
                        if self.open_braces.len() == 0 {
                            // Clear up these spans to avoid suggesting them as we've found
                            // properly matched delimiters so far for an entire block.
                            self.matching_delim_spans.clear();
                        } else {
                            self.matching_delim_spans.push(
                                (open_brace, open_brace_span, self.span),
                            );
                        }
                        // Parse the close delimiter.
                        self.real_token();
                    }
                    // Incorrect delimiter.
                    token::CloseDelim(other) => {
                        let mut unclosed_delimiter = None;
                        let mut candidate = None;
                        if self.last_unclosed_found_span != Some(self.span) {
                            // do not complain about the same unclosed delimiter multiple times
                            self.last_unclosed_found_span = Some(self.span);
                            // This is a conservative error: only report the last unclosed
                            // delimiter. The previous unclosed delimiters could actually be
                            // closed! The parser just hasn't gotten to them yet.
                            if let Some(&(_, sp)) = self.open_braces.last() {
                                unclosed_delimiter = Some(sp);
                            };
                            if let Some(current_padding) = sm.span_to_margin(self.span) {
                                for (brace, brace_span) in &self.open_braces {
                                    if let Some(padding) = sm.span_to_margin(*brace_span) {
                                        // high likelihood of these two corresponding
                                        if current_padding == padding && brace == &other {
                                            candidate = Some(*brace_span);
                                        }
                                    }
                                }
                            }
                            let (tok, _) = self.open_braces.pop().unwrap();
                            self.unmatched_braces.push(UnmatchedBrace {
                                expected_delim: tok,
                                found_delim: other,
                                found_span: self.span,
                                unclosed_span: unclosed_delimiter,
                                candidate_span: candidate,
                            });
                        } else {
                            self.open_braces.pop();
                        }

                        // If the incorrect delimiter matches an earlier opening
                        // delimiter, then don't consume it (it can be used to
                        // close the earlier one). Otherwise, consume it.
                        // E.g., we try to recover from:
                        // fn foo() {
                        //     bar(baz(
                        // }  // Incorrect delimiter but matches the earlier `{`
                        if !self.open_braces.iter().any(|&(b, _)| b == other) {
                            self.real_token();
                        }
                    }
                    token::Eof => {
                        // Silently recover, the EOF token will be seen again
                        // and an error emitted then. Thus we don't pop from
                        // self.open_braces here.
                    },
                    _ => {}
                }

                Ok(TokenTree::Delimited(
                    delim_span,
                    delim,
                    tts.into()
                ).into())
            },
            token::CloseDelim(_) => {
                // An unexpected closing delimiter (i.e., there is no
                // matching opening delimiter).
                let token_str = token_to_string(&self.token);
                let msg = format!("unexpected close delimiter: `{}`", token_str);
                let mut err = self.string_reader.sess.span_diagnostic
                    .struct_span_err(self.span, &msg);
                err.span_label(self.span, "unexpected close delimiter");
                Err(err)
            },
            _ => {
                let tt = TokenTree::Token(self.span, self.token.clone());
                // Note that testing for joint-ness here is done via the raw
                // source span as the joint-ness is a property of the raw source
                // rather than wanting to take `override_span` into account.
                // Additionally, we actually check if the *next* pair of tokens
                // is joint, but this is equivalent to checking the current pair.
                let raw = self.string_reader.peek_span_src_raw;
                self.real_token();
                let is_joint = raw.hi() == self.string_reader.peek_span_src_raw.lo()
                    && token::is_op(&self.token);
                Ok((tt, if is_joint { Joint } else { NonJoint }))
            }
        }
    }

    fn real_token(&mut self) {
        let t = self.string_reader.real_token();
        self.token = t.tok;
        self.span = t.sp;
    }
}
<|endoftext|>


<commit_before>use neb::server::*;
use neb::ram::schema::*;
use neb::server::transactions;
use neb::ram::types::*;
use neb::server::transactions::*;
use neb::ram::cell::*;
use super::*;
use std::rc::Rc;
use std::sync::Arc;
use std::thread;
use env_logger;

#[test]
pub fn workspace_wr() {
    let server_addr = String::from("127.0.0.1:5200");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_id = txn.begin().unwrap().unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(70));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1).unwrap().unwrap();
    match cell_1_w_res {
        TxnExecResult::Accepted(()) => {},
        _ => {panic!("write cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
            assert_eq!(cell.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    data_map.insert(String::from("score"), Value::U64(90));
    let cell_1_w2 = Cell::new(schema.id, &cell_1.id(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_w_res {
        TxnExecResult::Accepted(()) => {panic!("Write existed cell should fail")}
        TxnExecResult::Error(WriteError::CellAlreadyExisted) => {}
        _ => {panic!("Wrong feedback {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    let cell_1_u_res = txn.update(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_u_res {
        TxnExecResult::Accepted(()) => {},
        _ => {panic!("update cell 1 not accepted")}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 90);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    let cell_1_rm_res = txn.remove(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_rm_res {
        TxnExecResult::Accepted(()) => {},
        _ => {panic!("remove cell 1 not accepted {:?}", cell_1_rm_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Error(ReadError::CellDoesNotExisted) => {},
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    assert_eq!(txn.prepare(&txn_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_id).unwrap().unwrap(), EndResult::Success);
    assert_eq!(txn.commit(&txn_id).unwrap(), Err(TMError::TransactionNotFound));
    // committed transaction should have been disposed
}

#[test]
pub fn data_site_wr() {
    let server_addr = String::from("127.0.0.1:5201");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_id = txn.begin().unwrap().unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(70));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    let cell_1_non_exists_read = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_non_exists_read {
        TxnExecResult::Error(ReadError::CellDoesNotExisted) => {},
        _ => {panic!("read non-existed cell should fail but got {:?}", cell_1_non_exists_read)}
    }
    let cell_1_write = txn.write(&txn_id, &cell_1).unwrap().unwrap();
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
            assert_eq!(cell.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    data_map.insert(String::from("score"), Value::U64(90));
    let cell_1_w2 = Cell::new(schema.id, &cell_1.id(), data_map.clone());
    let cell_1_w_res = txn.update(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_w_res {
        TxnExecResult::Accepted(()) => {}
        _ => {panic!("Wrong feedback {:?}", cell_1_w_res)}
    }
    assert!(server.chunks.read_cell(&cell_1.id()).is_err()); // isolation test
    assert_eq!(txn.prepare(&txn_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_id).unwrap().unwrap(), EndResult::Success);
    let cell_r2 = server.chunks.read_cell(&cell_1.id()).unwrap();
    assert_eq!(cell_r2.id(), cell_1.id());
    assert_eq!(cell_r2.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
    assert_eq!(cell_r2.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
    assert_eq!(cell_r2.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 90);
}

#[test]
pub fn multi_transaction() {
    let server_addr = String::from("127.0.0.1:5202");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_1_id = txn.begin().unwrap().unwrap();
    let txn_2_id = txn.begin().unwrap().unwrap();
    let mut data_map_1 = Map::<String, Value>::new();
    data_map_1.insert(String::from("id"), Value::I64(100));
    data_map_1.insert(String::from("score"), Value::U64(70));
    data_map_1.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map_1.clone());
    let cell_1_t1_write = txn.update(&txn_1_id, &cell_1).unwrap().unwrap();
    let data_map_2 = data_map_1.clone();
    data_map_1.insert(String::from("score"), Value::U64(90));
    let cell_2 = Cell::new(schema.id, &cell_1.id(), data_map_2.clone());
    let cell_1_t2_write = txn.write(&txn_2_id, &cell_2).unwrap().unwrap();
    txn.prepare(&txn_2_id).unwrap().unwrap();
    txn.commit(&txn_2_id).unwrap().unwrap();
    assert_eq!(txn.prepare(&txn_1_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_1_id).unwrap().unwrap(), EndResult::Success);
    ///////////////// PHASE 2 //////////////////
    let txn_1_id = txn.begin().unwrap().unwrap();
    let txn_2_id = txn.begin().unwrap().unwrap();
    match txn.read(&txn_2_id, &cell_1.id()).unwrap().unwrap() {
        TxnExecResult::Accepted(_) => {},
        _ => {panic!("Cannot read cell 1 for txn 2");}
    }
    txn.update(&txn_1_id, &cell_1).unwrap().unwrap();
    assert_eq!(txn.prepare(&txn_1_id).unwrap().unwrap(), // write too late
    TMPrepareResult::DMPrepareError(DMPrepareResult::NotRealizable));
    assert_eq!(txn.commit(&txn_1_id).unwrap().err().unwrap(), TMError::TransactionNotFound);
    let txn_1_id = txn.begin().unwrap().unwrap();
    txn.update(&txn_1_id, &cell_1).unwrap().unwrap(); // txn_1_id > txn_2_id, realizable
    assert_eq!(txn.prepare(&txn_1_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_1_id).unwrap().unwrap(), EndResult::Success);
}

#[test]
pub fn smoke_rw() {
    env_logger::init();
    // this test is likely to have unrealizable transactions and
    // should not cause any deadlock even if they failed
    let server_addr = String::from("127.0.0.1:5203");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let mut data_map_1 = Map::<String, Value>::new();
    data_map_1.insert(String::from("id"), Value::I64(100));
    data_map_1.insert(String::from("score"), Value::U64(0));
    data_map_1.insert(String::from("name"), Value::String(String::from("Jack")));
    let mut cell_1 = Cell::new(schema.id, &Id::rand(), data_map_1.clone());
    server.chunks.write_cell(&mut cell_1);
    let cell_id = cell_1.id();
    let thread_count = 500;
    let mut threads: Vec<thread::JoinHandle<()>> = Vec::with_capacity(thread_count);
    for _ in 0..thread_count {
        // observed deadlock under 100 threads, Waiting check seems okay
        let txn = txn.clone();
        threads.push(thread::spawn(move || {
            let txn_id = txn.begin().unwrap().unwrap();
            let read_result = txn.read(&txn_id, &cell_id).unwrap();
            if let Ok(TxnExecResult::Accepted(mut cell)) = read_result {
                let mut score = cell.data.Map().unwrap().get("score").unwrap().U64().unwrap();
                score += 1;
                let mut data = cell.data.Map().unwrap().clone();
                data.insert(String::from("score"), Value::U64(score));
                cell.data = Value::Map(data);
                txn.update(&txn_id, &cell);
            } else {
                // println!("Failed read, {:?}", read_result);
            }
            if txn.prepare(&txn_id).unwrap() == Ok(TMPrepareResult::Success) {
                assert_eq!(txn.commit(&txn_id).unwrap().unwrap(), EndResult::Success);
            }
        }));
    }
    for handle in threads {
        handle.join();
    }
}<commit_msg>remove  comment<commit_after>use neb::server::*;
use neb::ram::schema::*;
use neb::server::transactions;
use neb::ram::types::*;
use neb::server::transactions::*;
use neb::ram::cell::*;
use super::*;
use std::rc::Rc;
use std::sync::Arc;
use std::thread;
use env_logger;

#[test]
pub fn workspace_wr() {
    let server_addr = String::from("127.0.0.1:5200");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_id = txn.begin().unwrap().unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(70));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1).unwrap().unwrap();
    match cell_1_w_res {
        TxnExecResult::Accepted(()) => {},
        _ => {panic!("write cell 1 not accepted {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
            assert_eq!(cell.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    data_map.insert(String::from("score"), Value::U64(90));
    let cell_1_w2 = Cell::new(schema.id, &cell_1.id(), data_map.clone());
    let cell_1_w_res = txn.write(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_w_res {
        TxnExecResult::Accepted(()) => {panic!("Write existed cell should fail")}
        TxnExecResult::Error(WriteError::CellAlreadyExisted) => {}
        _ => {panic!("Wrong feedback {:?}", cell_1_w_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    let cell_1_u_res = txn.update(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_u_res {
        TxnExecResult::Accepted(()) => {},
        _ => {panic!("update cell 1 not accepted")}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 90);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    let cell_1_rm_res = txn.remove(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_rm_res {
        TxnExecResult::Accepted(()) => {},
        _ => {panic!("remove cell 1 not accepted {:?}", cell_1_rm_res)}
    }
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Error(ReadError::CellDoesNotExisted) => {},
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    assert_eq!(txn.prepare(&txn_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_id).unwrap().unwrap(), EndResult::Success);
    assert_eq!(txn.commit(&txn_id).unwrap(), Err(TMError::TransactionNotFound));
    // committed transaction should have been disposed
}

#[test]
pub fn data_site_wr() {
    let server_addr = String::from("127.0.0.1:5201");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_id = txn.begin().unwrap().unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(70));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    let cell_1_non_exists_read = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_non_exists_read {
        TxnExecResult::Error(ReadError::CellDoesNotExisted) => {},
        _ => {panic!("read non-existed cell should fail but got {:?}", cell_1_non_exists_read)}
    }
    let cell_1_write = txn.write(&txn_id, &cell_1).unwrap().unwrap();
    let cell_1_r_res = txn.read(&txn_id, &cell_1.id()).unwrap().unwrap();
    match cell_1_r_res {
        TxnExecResult::Accepted(cell) => {
            assert_eq!(cell.id(), cell_1.id());
            assert_eq!(cell.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
            assert_eq!(cell.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
            assert_eq!(cell.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 70);
        },
        _ => {panic!("read cell 1 not accepted {:?}", cell_1_r_res)}
    }
    data_map.insert(String::from("score"), Value::U64(90));
    let cell_1_w2 = Cell::new(schema.id, &cell_1.id(), data_map.clone());
    let cell_1_w_res = txn.update(&txn_id, &cell_1_w2).unwrap().unwrap();
    match cell_1_w_res {
        TxnExecResult::Accepted(()) => {}
        _ => {panic!("Wrong feedback {:?}", cell_1_w_res)}
    }
    assert!(server.chunks.read_cell(&cell_1.id()).is_err()); // isolation test
    assert_eq!(txn.prepare(&txn_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_id).unwrap().unwrap(), EndResult::Success);
    let cell_r2 = server.chunks.read_cell(&cell_1.id()).unwrap();
    assert_eq!(cell_r2.id(), cell_1.id());
    assert_eq!(cell_r2.data.Map().unwrap().get("id").unwrap().I64().unwrap(), 100);
    assert_eq!(cell_r2.data.Map().unwrap().get("name").unwrap().String().unwrap(), "Jack");
    assert_eq!(cell_r2.data.Map().unwrap().get("score").unwrap().U64().unwrap(), 90);
}

#[test]
pub fn multi_transaction() {
    let server_addr = String::from("127.0.0.1:5202");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let txn_1_id = txn.begin().unwrap().unwrap();
    let txn_2_id = txn.begin().unwrap().unwrap();
    let mut data_map_1 = Map::<String, Value>::new();
    data_map_1.insert(String::from("id"), Value::I64(100));
    data_map_1.insert(String::from("score"), Value::U64(70));
    data_map_1.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map_1.clone());
    let cell_1_t1_write = txn.update(&txn_1_id, &cell_1).unwrap().unwrap();
    let data_map_2 = data_map_1.clone();
    data_map_1.insert(String::from("score"), Value::U64(90));
    let cell_2 = Cell::new(schema.id, &cell_1.id(), data_map_2.clone());
    let cell_1_t2_write = txn.write(&txn_2_id, &cell_2).unwrap().unwrap();
    txn.prepare(&txn_2_id).unwrap().unwrap();
    txn.commit(&txn_2_id).unwrap().unwrap();
    assert_eq!(txn.prepare(&txn_1_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_1_id).unwrap().unwrap(), EndResult::Success);
    ///////////////// PHASE 2 //////////////////
    let txn_1_id = txn.begin().unwrap().unwrap();
    let txn_2_id = txn.begin().unwrap().unwrap();
    match txn.read(&txn_2_id, &cell_1.id()).unwrap().unwrap() {
        TxnExecResult::Accepted(_) => {},
        _ => {panic!("Cannot read cell 1 for txn 2");}
    }
    txn.update(&txn_1_id, &cell_1).unwrap().unwrap();
    assert_eq!(txn.prepare(&txn_1_id).unwrap().unwrap(), // write too late
    TMPrepareResult::DMPrepareError(DMPrepareResult::NotRealizable));
    assert_eq!(txn.commit(&txn_1_id).unwrap().err().unwrap(), TMError::TransactionNotFound);
    let txn_1_id = txn.begin().unwrap().unwrap();
    txn.update(&txn_1_id, &cell_1).unwrap().unwrap(); // txn_1_id > txn_2_id, realizable
    assert_eq!(txn.prepare(&txn_1_id).unwrap().unwrap(), TMPrepareResult::Success);
    assert_eq!(txn.commit(&txn_1_id).unwrap().unwrap(), EndResult::Success);
}

#[test]
pub fn smoke_rw() {
    env_logger::init();
    // this test is likely to have unrealizable transactions and
    // should not cause any deadlock even if they failed
    let server_addr = String::from("127.0.0.1:5203");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    server.meta.schemas.new_schema(&mut schema);
    let txn = transactions::new_client(&server_addr).unwrap();
    let mut data_map_1 = Map::<String, Value>::new();
    data_map_1.insert(String::from("id"), Value::I64(100));
    data_map_1.insert(String::from("score"), Value::U64(0));
    data_map_1.insert(String::from("name"), Value::String(String::from("Jack")));
    let mut cell_1 = Cell::new(schema.id, &Id::rand(), data_map_1.clone());
    server.chunks.write_cell(&mut cell_1);
    let cell_id = cell_1.id();
    let thread_count = 500;
    let mut threads: Vec<thread::JoinHandle<()>> = Vec::with_capacity(thread_count);
    for _ in 0..thread_count {
        let txn = txn.clone();
        threads.push(thread::spawn(move || {
            let txn_id = txn.begin().unwrap().unwrap();
            let read_result = txn.read(&txn_id, &cell_id).unwrap();
            if let Ok(TxnExecResult::Accepted(mut cell)) = read_result {
                let mut score = cell.data.Map().unwrap().get("score").unwrap().U64().unwrap();
                score += 1;
                let mut data = cell.data.Map().unwrap().clone();
                data.insert(String::from("score"), Value::U64(score));
                cell.data = Value::Map(data);
                txn.update(&txn_id, &cell);
            } else {
                // println!("Failed read, {:?}", read_result);
            }
            if txn.prepare(&txn_id).unwrap() == Ok(TMPrepareResult::Success) {
                assert_eq!(txn.commit(&txn_id).unwrap().unwrap(), EndResult::Success);
            }
        }));
    }
    for handle in threads {
        handle.join();
    }
}<|endoftext|>


<commit_before>use super::InteractiveShell;
use ion_shell::{
    expansion::{self, Expander},
    IonError, PipelineError,
};
use liner::Prompt;

impl<'a> InteractiveShell<'a> {
    /// Generates the prompt that will be used by Liner.
    pub fn prompt(&self) -> Prompt {
        let mut shell = self.shell.borrow_mut();
        let previous_status = shell.previous_status();
        let blocks = if self.terminated.get() { shell.block_len() } else { shell.block_len() + 1 };

        if blocks == 0 {
            let out = shell.command("PROMPT").map(|res| res.to_string()).unwrap_or_else(|err| {
                if let expansion::Error::Subprocess(err) = err {
                    if let IonError::PipelineExecutionError(PipelineError::CommandNotFound(_)) =
                        *err
                    {
                        match shell
                            .variables()
                            .get_str("PROMPT")
                            .and_then(|prompt| shell.get_string(&prompt))
                        {
                            Ok(prompt) => prompt.to_string(),
                            Err(err) => {
                                eprintln!("ion: prompt expansion failed: {}", err);
                                ">>> ".into()
                            }
                        }
                    } else {
                        eprintln!("ion: prompt expansion failed: {}", err);
                        ">>> ".into()
                    }
                } else {
                    panic!("Only a subprocess error should happen inside the pipeline");
                }
            });
            shell.set_previous_status(previous_status); // Set the previous exit code again
            Prompt::from(out)
        } else {
            Prompt::from("    ".repeat(blocks))
        }
    }
}
<commit_msg>feat: Add a default Vi prompt<commit_after>use super::InteractiveShell;
use ion_shell::{
    expansion::{self, Expander},
    IonError, PipelineError, Shell,
};
use liner::{KeyBindings::*, Prompt, ViPromptMode, ViStatus};

impl<'a> InteractiveShell<'a> {
    /// Generates the prompt that will be used by Liner.
    pub fn prompt(&self) -> Prompt {
        let mut shell = self.shell.borrow_mut();
        let previous_status = shell.previous_status();
        let blocks = if self.terminated.get() { shell.block_len() } else { shell.block_len() + 1 };

        if blocks == 0 {
            let out = shell.command("PROMPT").map(|res| res.to_string()).unwrap_or_else(|err| {
                if let expansion::Error::Subprocess(err) = err {
                    if let IonError::PipelineExecutionError(PipelineError::CommandNotFound(_)) =
                        *err
                    {
                        match shell
                            .variables()
                            .get_str("PROMPT")
                            .and_then(|prompt| shell.get_string(&prompt))
                        {
                            Ok(prompt) => prompt.to_string(),
                            Err(err) => {
                                eprintln!("ion: prompt expansion failed: {}", err);
                                ">>> ".into()
                            }
                        }
                    } else {
                        eprintln!("ion: prompt expansion failed: {}", err);
                        ">>> ".into()
                    }
                } else {
                    panic!("Only a subprocess error should happen inside the pipeline");
                }
            });
            shell.set_previous_status(previous_status); // Set the previous exit code again
            let key_bindings = self.context.borrow().key_bindings;
            match key_bindings {
                Emacs => Prompt::from(out),
                Vi => {
                    let normal = vi_prompt_indicator(&mut shell, ViPromptMode::Normal);
                    let insert = vi_prompt_indicator(&mut shell, ViPromptMode::Insert);
                    Prompt {
                        prompt:    out,
                        vi_status: Some(ViStatus::new(ViPromptMode::Insert, normal, insert)),
                    }
                }
            }
        } else {
            Prompt::from("    ".repeat(blocks))
        }
    }
}

/// Returns the default indicators for a given mode in absence of a configuration.
///
/// NOTE: This should be made `const` once this functionality is stabilized:
/// https://github.com/rust-lang/rust/issues/49146
fn default_vi_indicator(mode: ViPromptMode) -> &'static str {
    match mode {
        ViPromptMode::Insert => "${c::dim}${c::greenbg}${c::black} I ${c::reset} ",
        ViPromptMode::Normal => "${c::dim}${c::light_graybg}${c::black} N ${c::reset} ",
    }
}

/// Returns the configuration variable for a given mode.
///
/// NOTE: This should be made `const` once this functionality is stabilized:
/// https://github.com/rust-lang/rust/issues/49146
fn vi_indicator_variable(mode: ViPromptMode) -> &'static str {
    match mode {
        ViPromptMode::Insert => "VI_INSERT",
        ViPromptMode::Normal => "VI_NORMAL",
    }
}

fn vi_prompt_indicator<'a>(shell: &mut Shell<'a>, mode: ViPromptMode) -> String {
    shell
        .variables()
        .get_str(vi_indicator_variable(mode))
        .or_else(|_| Ok(small::String::from(default_vi_indicator(mode))))
        .and_then(|prompt| shell.get_string(&prompt))
        .map(|expanded| expanded.to_string())
        .unwrap_or_else(|e| {
            eprintln!("{:?}", e);
            String::new()
        })
}
<|endoftext|>


<commit_before>#![feature(phase)]

#![allow(uppercase_variables)]

#[phase(syntax,link)]
extern crate lua;
extern crate libc;

mod common;

fn main() {
    let mut L = lua::State::new();
    L.openlibs();
    L.register("sin", my_sin);
    L.register("cos", my_cos);
    L.register("tan", my_tan);
    common::repl(&mut L);
}

lua_extern! {
    unsafe fn my_sin(L: &mut lua::ExternState) -> i32 {
        let input = L.checknumber(1);
        let output = input.sin();
        L.pushnumber(output);
        1
    }

    unsafe fn my_cos(L: &mut lua::ExternState) -> i32 {
        let input = L.checknumber(1);
        let output = input.cos();
        L.pushnumber(output);
        1
    }
}

lua_extern_pub! {
    // this function is marked public
    unsafe fn my_tan(L: &mut lua::ExternState) -> i32 {
        let input = L.checknumber(1);
        let output = input.tan();
        L.pushnumber(output);
        1
    }
}
<commit_msg>Switch from #[phase(syntax)] to #[phase(plugin)]<commit_after>#![feature(phase)]

#![allow(uppercase_variables)]

#[phase(plugin,link)]
extern crate lua;
extern crate libc;

mod common;

fn main() {
    let mut L = lua::State::new();
    L.openlibs();
    L.register("sin", my_sin);
    L.register("cos", my_cos);
    L.register("tan", my_tan);
    common::repl(&mut L);
}

lua_extern! {
    unsafe fn my_sin(L: &mut lua::ExternState) -> i32 {
        let input = L.checknumber(1);
        let output = input.sin();
        L.pushnumber(output);
        1
    }

    unsafe fn my_cos(L: &mut lua::ExternState) -> i32 {
        let input = L.checknumber(1);
        let output = input.cos();
        L.pushnumber(output);
        1
    }
}

lua_extern_pub! {
    // this function is marked public
    unsafe fn my_tan(L: &mut lua::ExternState) -> i32 {
        let input = L.checknumber(1);
        let output = input.tan();
        L.pushnumber(output);
        1
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf};
use syn::*;

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BranchContext {
    files: HashMap<PathBuf, BranchAnalysis>,
}

impl BranchContext {
    pub fn is_branch<P: AsRef<Path>>(&self, path: P, line: usize) -> bool {
        if let Some(file) = self.files.get(path.as_ref()) {
            file.is_branch(line)
        } else {
            false
        }
    }
}

/// Coverage context for all the branches
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BranchAnalysis {
    /// Each key is `LineRange` showing a region of the code containing a set of branches with the
    /// value being a `LineRange` for each branch in the code
    /// TODO consider BTreeMap then can order on line range start
    branches: BTreeMap<LineRange, Branches>,
}

impl BranchAnalysis {
    /// Returns true if the line is part of a branch
    pub fn is_branch(&self, line: usize) -> bool {
        self.branches.iter().any(|(k, _)| k.contains(line))
    }

    pub fn register_expr(&mut self, expr: &Expr) {
        let range = LineRange::from(expr);
        match *expr {
            Expr::If(ref e) => {
                self.branches.insert(range, e.into());
            }
            Expr::Match(ref e) => {
                self.branches.insert(range, e.into());
            }
            Expr::ForLoop(ref e) => {
                self.branches.insert(range, e.into());
            }
            Expr::While(ref e) => {
                self.branches.insert(range, e.into());
            }
            _ => {}
        }
    }
}

/// Represents possible branches through an execution
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Branches {
    /// Line ranges for each branch
    ranges: Vec<LineRange>,
    /// Whether there is an implicit or empty default branch i.e. missing or empty `else` in an
    /// `if` statement
    implicit_default: bool,
}

impl From<&ExprIf> for Branches {
    fn from(expr: &ExprIf) -> Self {
        todo!()
    }
}

impl From<&ExprMatch> for Branches {
    fn from(expr: &ExprMatch) -> Self {
        todo!()
    }
}

impl From<&ExprForLoop> for Branches {
    fn from(expr: &ExprForLoop) -> Self {
        Self {
            implicit_default: true,
            ranges: vec![expr.body.clone().into()],
        }
    }
}

impl From<&ExprWhile> for Branches {
    fn from(expr: &ExprWhile) -> Self {
        Self {
            implicit_default: true,
            ranges: vec![expr.body.clone().into()],
        }
    }
}

/// The start and end of contiguous range of lines. The range is contained within
/// `start..end`
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct LineRange {
    /// Start of the line range (inclusive)
    start: usize,
    /// End of the line range (exclusive)
    end: usize,
}

impl<T> From<T> for LineRange
where
    T: spanned::Spanned,
{
    fn from(t: T) -> Self {
        Self {
            start: t.span().start().line,
            end: t.span().end().line + 1,
        }
    }
}

impl LineRange {
    /// Returns true if the line is contained within the line range
    pub fn contains(&self, line: usize) -> bool {
        line >= self.start && line < self.end
    }
}
<commit_msg>Add branch calculation for if and match<commit_after>use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf};
use syn::*;

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BranchContext {
    files: HashMap<PathBuf, BranchAnalysis>,
}

impl BranchContext {
    pub fn is_branch<P: AsRef<Path>>(&self, path: P, line: usize) -> bool {
        if let Some(file) = self.files.get(path.as_ref()) {
            file.is_branch(line)
        } else {
            false
        }
    }
}

/// Coverage context for all the branches
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BranchAnalysis {
    /// Each key is `LineRange` showing a region of the code containing a set of branches with the
    /// value being a `LineRange` for each branch in the code
    /// TODO consider BTreeMap then can order on line range start
    branches: BTreeMap<LineRange, Branches>,
}

impl BranchAnalysis {
    /// Returns true if the line is part of a branch
    pub fn is_branch(&self, line: usize) -> bool {
        self.branches.iter().any(|(k, _)| k.contains(line))
    }

    pub fn register_expr(&mut self, expr: &Expr) {
        let range = LineRange::from(expr);
        match *expr {
            Expr::If(ref e) => {
                self.branches.insert(range, e.into());
            }
            Expr::Match(ref e) => {
                self.branches.insert(range, e.into());
            }
            Expr::ForLoop(ref e) => {
                self.branches.insert(range, e.into());
            }
            Expr::While(ref e) => {
                self.branches.insert(range, e.into());
            }
            _ => {}
        }
    }
}

/// Represents possible branches through an execution
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Branches {
    /// Line ranges for each branch
    ranges: Vec<LineRange>,
    /// Whether there is an implicit or empty default branch i.e. missing or empty `else` in an
    /// `if` statement
    implicit_default: bool,
}

impl From<&ExprIf> for Branches {
    fn from(expr: &ExprIf) -> Self {
        let mut ranges = vec![];
        let mut else_block = expr.else_branch.as_ref().map(|x| x.1.clone());
        let mut implicit_default = else_block.is_none();
        while let Some(el) = else_block {
            let mut lr = LineRange::from(&el);
            if let Expr::If(ref i) = *el {
                else_block = i.else_branch.as_ref().map(|x| x.1.clone());
                implicit_default = else_block.is_none();
                if let Some(s) = &else_block {
                    let lr2 = LineRange::from(s);
                    if lr2.start < lr.end {
                        lr.end = lr2.start - 1;
                    }
                    ranges.push(lr);
                }
            } else {
                else_block = None;
                ranges.push(lr);
            }
        }
        Self {
            ranges,
            implicit_default,
        }
    }
}

impl From<&ExprMatch> for Branches {
    fn from(expr: &ExprMatch) -> Self {
        let ranges = expr
            .arms
            .iter()
            .map(|x| LineRange::from(x))
            .collect::<Vec<_>>();
        Self {
            implicit_default: false,
            ranges,
        }
    }
}

impl From<&ExprForLoop> for Branches {
    fn from(expr: &ExprForLoop) -> Self {
        Self {
            implicit_default: true,
            ranges: vec![expr.body.clone().into()],
        }
    }
}

impl From<&ExprWhile> for Branches {
    fn from(expr: &ExprWhile) -> Self {
        Self {
            implicit_default: true,
            ranges: vec![expr.body.clone().into()],
        }
    }
}

/// The start and end of contiguous range of lines. The range is contained within
/// `start..end`
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct LineRange {
    /// Start of the line range (inclusive)
    start: usize,
    /// End of the line range (exclusive)
    end: usize,
}

impl<T> From<T> for LineRange
where
    T: spanned::Spanned,
{
    fn from(t: T) -> Self {
        Self {
            start: t.span().start().line,
            end: t.span().end().line + 1,
        }
    }
}

impl LineRange {
    /// Returns true if the line is contained within the line range
    pub fn contains(&self, line: usize) -> bool {
        line >= self.start && line < self.end
    }
}
<|endoftext|>


<commit_before>extern crate vr;

fn main() {
    let ivr = vr::IVRSystem::init().unwrap();
    println!("bounds: {:?}", ivr.bounds());
    println!("recommended size: {:?}", ivr.recommended_render_target_size());
    println!("eye output: {:?} {:?}", ivr.eye_viewport(vr::Eye::Left), ivr.eye_viewport(vr::Eye::Right));
    println!("projection matrix left {:?}", ivr.projection_matrix(vr::Eye::Left, 0.1, 100.));
    println!("projection matrix right {:?}", ivr.projection_matrix(vr::Eye::Right, 0.1, 100.));

    for u in 0..4 {
        for v in 0..4 {
            let pos = ivr.compute_distortion(
                vr::Eye::Left,
                u as f32 / 4.,
                v as f32 / 4.,
            );
            print!("({:2.4}, {:2.4}) ", pos.red[0], pos.red[1]);
        }
        println!("");
    }

    println!("eye_to_head: {:?}", ivr.eye_to_head_transform(vr::Eye::Left));
    println!("vsync: {:?}", ivr.time_since_last_vsync());
    println!("poses {:?}", ivr.tracked_devices(0.).as_slice());

    println!("Trying to create a compositor");
    match ivr.compositor() {
        Err(err) => println!("Could not create compositor {:?}", err),
        Ok(comp) => {
            println!("\tCreated one!");
            println!("\tis fullscreen    ={}", comp.is_fullscreen());
            println!("\tis vsync         ={}", comp.get_vsync());
            println!("\tcan render scene ={}", comp.can_render_scene());
        }
    }

    println!("Done! \\o/");

}<commit_msg>ade the test app print a prettier output<commit_after>extern crate vr;

fn print_matrix_4x4(offset: u32, mat: [[f32; 4]; 4]) {
    let off: String = (0..offset).map(|_| ' ').collect();
    println!("{:?}",        mat[0]);
    println!("{}{:?}", off, mat[1]);
    println!("{}{:?}", off, mat[2]);
    println!("{}{:?}", off, mat[3]);
}

fn print_matrix_4x3(offset: u32, mat: [[f32; 4]; 3]) {
    let off: String = (0..offset).map(|_| ' ').collect();
    println!("{:?}",        mat[0]);
    println!("{}{:?}", off, mat[1]);
    println!("{}{:?}", off, mat[2]);
}

fn main() {
    let ivr = match vr::IVRSystem::init() {
        Ok(ivr) => ivr,
        Err(err) => {
            println!("Failed to create IVR subsystem {:?}", err);
            return;
        }
    };

    println!("IVR was created");
    println!("\tbounds: {:?}", ivr.bounds());
    println!("\trecommended size: {:?}", ivr.recommended_render_target_size());
    println!("\teye output: {:?} {:?}", ivr.eye_viewport(vr::Eye::Left), ivr.eye_viewport(vr::Eye::Right));
    println!("\tvsync: {:?}", ivr.time_since_last_vsync());

    print!("\tprojection matrix left  ");
    print_matrix_4x4(31, ivr.projection_matrix(vr::Eye::Left, 0.1, 100.));
    print!("\tprojection matrix right ");
    print_matrix_4x4(31, ivr.projection_matrix(vr::Eye::Right, 0.1, 100.));

    print!("\teye_to_head ");
    print_matrix_4x3(8+12, ivr.eye_to_head_transform(vr::Eye::Left));

    print!("\tposes ");
    print_matrix_4x3(8+6, ivr.tracked_devices(0.).as_slice()[0].to_device);

    println!("Distortion example");
    for u in 0..2 {
        for v in 0..2 {
            let pos = ivr.compute_distortion(
                vr::Eye::Left,
                u as f32 / 4.,
                v as f32 / 4.,
            );
            print!("\t({:2.4}, {:2.4}) ", pos.red[0], pos.red[1]);
        }
        println!("");
    }

    println!("Trying to create a compositor");
    match ivr.compositor() {
        Err(err) => println!("Could not create compositor {:?}", err),
        Ok(comp) => {
            println!("\tCreated one!");
            println!("\tis fullscreen    ={}", comp.is_fullscreen());
            println!("\tis vsync         ={}", comp.get_vsync());
            println!("\tcan render scene ={}", comp.can_render_scene());
        }
    }

    println!("Done! \\o/");

}<|endoftext|>