<commit_before>// Translation of vector operations to LLVM IR, in destination-passing style.

import back::abi;
import lib::llvm::llvm;
import llvm::ValueRef;
import middle::trans;
import middle::trans_common;
import middle::trans_dps;
import middle::ty;
import syntax::ast;
import syntax::codemap::span;
import trans::alloca;
import trans::block_ctxt;
import trans::load_inbounds;
import trans::new_sub_block_ctxt;
import trans::struct_elt;
import trans::type_of_or_i8;
import trans_common::C_int;
import trans_common::C_null;
import trans_common::C_uint;
import trans_common::T_int;
import trans_common::T_ivec_heap;
import trans_common::T_ivec_heap_part;
import trans_common::T_opaque_ivec;
import trans_common::T_ptr;
import trans_dps::bcx_ccx;
import trans_dps::bcx_tcx;
import trans_dps::dest;
import trans_dps::llsize_of;
import trans_dps::mk_temp;

import std::option::none;
import std::option::some;
import tc = middle::trans_common;

// Returns the length of an interior vector and a pointer to its first
// element, in that order.
//
// TODO: We can optimize this in the cases in which we statically know the
// vector must be on the stack.
fn get_len_and_data(&@block_ctxt cx, ty::t t, ValueRef llvecptr)
        -> tup(@block_ctxt, ValueRef, ValueRef) {
    auto bcx = cx;

    // If this interior vector has dynamic size, we can't assume anything
    // about the LLVM type of the value passed in, so we cast it to an
    // opaque vector type.
    auto unit_ty = ty::sequence_element_type(bcx_tcx(bcx), t);
    auto v;
    if (ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty)) {
        v = bcx.build.PointerCast(llvecptr, T_ptr(T_opaque_ivec()));
    } else {
        v = llvecptr;
    }

    auto llunitty = type_of_or_i8(bcx, unit_ty);
    auto stack_len = load_inbounds(bcx, v, ~[C_int(0),
                                             C_uint(abi::ivec_elt_len)]);
    auto stack_elem =
        bcx.build.InBoundsGEP(v,
                              ~[C_int(0), C_uint(abi::ivec_elt_elems),
                                C_int(0)]);
    auto on_heap =
        bcx.build.ICmp(lib::llvm::LLVMIntEQ, stack_len, C_int(0));
    auto on_heap_cx = new_sub_block_ctxt(bcx, "on_heap");
    auto next_cx = new_sub_block_ctxt(bcx, "next");
    bcx.build.CondBr(on_heap, on_heap_cx.llbb, next_cx.llbb);
    auto heap_stub =
        on_heap_cx.build.PointerCast(v, T_ptr(T_ivec_heap(llunitty)));
    auto heap_ptr = load_inbounds(on_heap_cx, heap_stub,
                                  ~[C_int(0),
                                    C_uint(abi::ivec_heap_stub_elt_ptr)]);

    // Check whether the heap pointer is null. If it is, the vector length
    // is truly zero.

    auto llstubty = T_ivec_heap(llunitty);
    auto llheapptrty = struct_elt(llstubty, abi::ivec_heap_stub_elt_ptr);
    auto heap_ptr_is_null =
        on_heap_cx.build.ICmp(lib::llvm::LLVMIntEQ, heap_ptr,
                              C_null(T_ptr(llheapptrty)));
    auto zero_len_cx = new_sub_block_ctxt(bcx, "zero_len");
    auto nonzero_len_cx = new_sub_block_ctxt(bcx, "nonzero_len");
    on_heap_cx.build.CondBr(heap_ptr_is_null, zero_len_cx.llbb,
                            nonzero_len_cx.llbb);
    // Technically this context is unnecessary, but it makes this function
    // clearer.

    auto zero_len = C_int(0);
    auto zero_elem = C_null(T_ptr(llunitty));
    zero_len_cx.build.Br(next_cx.llbb);
    // If we're here, then we actually have a heapified vector.

    auto heap_len = load_inbounds(nonzero_len_cx, heap_ptr,
                                  ~[C_int(0),
                                    C_uint(abi::ivec_heap_elt_len)]);
    auto heap_elem =
        {
            auto v = ~[C_int(0), C_uint(abi::ivec_heap_elt_elems),
                       C_int(0)];
            nonzero_len_cx.build.InBoundsGEP(heap_ptr,v)
        };

    nonzero_len_cx.build.Br(next_cx.llbb);

    // Now we can figure out the length of |v| and get a pointer to its
    // first element.

    auto len =
        next_cx.build.Phi(T_int(), ~[stack_len, zero_len, heap_len],
                          ~[bcx.llbb, zero_len_cx.llbb,
                            nonzero_len_cx.llbb]);
    auto elem =
        next_cx.build.Phi(T_ptr(llunitty),
                          ~[stack_elem, zero_elem, heap_elem],
                          ~[bcx.llbb, zero_len_cx.llbb,
                            nonzero_len_cx.llbb]);
    ret tup(next_cx, len, elem);
}

fn trans_concat(&@block_ctxt cx, &dest in_dest, &span sp, ty::t t,
                &@ast::expr lhs, &@ast::expr rhs) -> @block_ctxt {
    auto bcx = cx;

    // TODO: Skip null if copying strings.
    // TODO: Detect "a = a + b" and promote to trans_append.
    // TODO: Detect "a + [ literal ]" and optimize to copying the literal
    //       elements in directly.

    auto t = ty::expr_ty(bcx_tcx(bcx), lhs);
    auto skip_null = ty::type_is_str(bcx_tcx(bcx), t);

    // Translate the LHS and RHS. Pull out their length and data.
    auto lhs_tmp = trans_dps::dest_alias(bcx_tcx(bcx), t);
    bcx = trans_dps::trans_expr(bcx, lhs_tmp, lhs);
    auto lllhsptr = trans_dps::dest_ptr(lhs_tmp);

    auto rhs_tmp = trans_dps::dest_alias(bcx_tcx(bcx), t);
    bcx = trans_dps::trans_expr(bcx, rhs_tmp, rhs);
    auto llrhsptr = trans_dps::dest_ptr(rhs_tmp);

    auto r0 = get_len_and_data(bcx, t, lllhsptr);
    bcx = r0._0; auto lllhslen = r0._1; auto lllhsdata = r0._2;
    r0 = get_len_and_data(bcx, t, llrhsptr);
    bcx = r0._0; auto llrhslen = r0._1; auto llrhsdata = r0._2;

    if skip_null { lllhslen = bcx.build.Sub(lllhslen, C_int(1)); }

    // Allocate the destination.
    auto r1 = trans_dps::spill_alias(bcx, in_dest, t);
    bcx = r1._0; auto dest = r1._1;

    auto unit_t = ty::sequence_element_type(bcx_tcx(bcx), t);
    auto unit_sz = trans_dps::size_of(bcx_ccx(bcx), sp, unit_t);

    auto stack_elems_sz = unit_sz * abi::ivec_default_length;
    auto lldestptr = trans_dps::dest_ptr(dest);
    auto llunitty = trans::type_of(bcx_ccx(bcx), sp, unit_t);

    // Decide whether to allocate the result on the stack or on the heap.
    auto llnewlen = bcx.build.Add(lllhslen, llrhslen);
    auto llonstack = bcx.build.ICmp(lib::llvm::LLVMIntULE, llnewlen,
                                    C_uint(stack_elems_sz));
    auto on_stack_bcx = new_sub_block_ctxt(bcx, "on_stack");
    auto on_heap_bcx = new_sub_block_ctxt(bcx, "on_heap");
    bcx.build.CondBr(llonstack, on_stack_bcx.llbb, on_heap_bcx.llbb);

    // On-stack case.
    auto next_bcx = new_sub_block_ctxt(bcx, "next");
    trans::store_inbounds(on_stack_bcx, llnewlen, lldestptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_len)]);
    trans::store_inbounds(on_stack_bcx, C_uint(stack_elems_sz), lldestptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_alen)]);
    auto llonstackdataptr =
        on_stack_bcx.build.InBoundsGEP(lldestptr,
                                       ~[C_int(0),
                                         C_uint(abi::ivec_elt_elems),
                                         C_int(0)]);
    on_stack_bcx.build.Br(next_bcx.llbb);

    // On-heap case.
    auto llheappartty = tc::T_ivec_heap(llunitty);
    auto lldeststubptr =
        on_heap_bcx.build.PointerCast(lldestptr, tc::T_ptr(llheappartty));
    trans::store_inbounds(on_heap_bcx, C_int(0), lldeststubptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_len)]);
    trans::store_inbounds(on_heap_bcx, llnewlen, lldeststubptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_alen)]);

    auto llheappartptrptr =
        on_heap_bcx.build.InBoundsGEP(lldeststubptr,
                                      ~[C_int(0),
                                        C_uint(abi::ivec_elt_elems)]);
    auto llsizeofint = C_uint(llsize_of(bcx_ccx(bcx), tc::T_int()));
    on_heap_bcx = trans_dps::malloc(on_heap_bcx, llheappartptrptr,
                                    trans_dps::hp_shared,
                                    some(on_heap_bcx.build.Add(llnewlen,
                                                               llsizeofint)));
    auto llheappartptr = on_heap_bcx.build.Load(llheappartptrptr);
    trans::store_inbounds(on_heap_bcx, llnewlen, llheappartptr,
                          ~[C_int(0), C_uint(abi::ivec_heap_elt_len)]);
    auto llheapdataptr =
        on_heap_bcx.build.InBoundsGEP(llheappartptr,
                                      ~[C_int(0),
                                        C_uint(abi::ivec_heap_elt_elems),
                                        C_int(0)]);
    on_heap_bcx.build.Br(next_bcx.llbb);

    // Perform the memmove.
    auto lldataptr =
        next_bcx.build.Phi(T_ptr(llunitty),
                           ~[llonstackdataptr, llheapdataptr],
                           ~[on_stack_bcx.llbb, on_heap_bcx.llbb]);
    trans_dps::memmove(next_bcx, lldataptr, lllhsdata, lllhslen);
    trans_dps::memmove(next_bcx,
                       next_bcx.build.InBoundsGEP(lldataptr, ~[lllhslen]),
                       llrhsdata, llrhslen);

    ret next_bcx;
}

<commit_msg>rustc: Remove obsolete TODO<commit_after>// Translation of vector operations to LLVM IR, in destination-passing style.

import back::abi;
import lib::llvm::llvm;
import llvm::ValueRef;
import middle::trans;
import middle::trans_common;
import middle::trans_dps;
import middle::ty;
import syntax::ast;
import syntax::codemap::span;
import trans::alloca;
import trans::block_ctxt;
import trans::load_inbounds;
import trans::new_sub_block_ctxt;
import trans::struct_elt;
import trans::type_of_or_i8;
import trans_common::C_int;
import trans_common::C_null;
import trans_common::C_uint;
import trans_common::T_int;
import trans_common::T_ivec_heap;
import trans_common::T_ivec_heap_part;
import trans_common::T_opaque_ivec;
import trans_common::T_ptr;
import trans_dps::bcx_ccx;
import trans_dps::bcx_tcx;
import trans_dps::dest;
import trans_dps::llsize_of;
import trans_dps::mk_temp;

import std::option::none;
import std::option::some;
import tc = middle::trans_common;

// Returns the length of an interior vector and a pointer to its first
// element, in that order.
//
// TODO: We can optimize this in the cases in which we statically know the
// vector must be on the stack.
fn get_len_and_data(&@block_ctxt cx, ty::t t, ValueRef llvecptr)
        -> tup(@block_ctxt, ValueRef, ValueRef) {
    auto bcx = cx;

    // If this interior vector has dynamic size, we can't assume anything
    // about the LLVM type of the value passed in, so we cast it to an
    // opaque vector type.
    auto unit_ty = ty::sequence_element_type(bcx_tcx(bcx), t);
    auto v;
    if (ty::type_has_dynamic_size(bcx_tcx(bcx), unit_ty)) {
        v = bcx.build.PointerCast(llvecptr, T_ptr(T_opaque_ivec()));
    } else {
        v = llvecptr;
    }

    auto llunitty = type_of_or_i8(bcx, unit_ty);
    auto stack_len = load_inbounds(bcx, v, ~[C_int(0),
                                             C_uint(abi::ivec_elt_len)]);
    auto stack_elem =
        bcx.build.InBoundsGEP(v,
                              ~[C_int(0), C_uint(abi::ivec_elt_elems),
                                C_int(0)]);
    auto on_heap =
        bcx.build.ICmp(lib::llvm::LLVMIntEQ, stack_len, C_int(0));
    auto on_heap_cx = new_sub_block_ctxt(bcx, "on_heap");
    auto next_cx = new_sub_block_ctxt(bcx, "next");
    bcx.build.CondBr(on_heap, on_heap_cx.llbb, next_cx.llbb);
    auto heap_stub =
        on_heap_cx.build.PointerCast(v, T_ptr(T_ivec_heap(llunitty)));
    auto heap_ptr = load_inbounds(on_heap_cx, heap_stub,
                                  ~[C_int(0),
                                    C_uint(abi::ivec_heap_stub_elt_ptr)]);

    // Check whether the heap pointer is null. If it is, the vector length
    // is truly zero.

    auto llstubty = T_ivec_heap(llunitty);
    auto llheapptrty = struct_elt(llstubty, abi::ivec_heap_stub_elt_ptr);
    auto heap_ptr_is_null =
        on_heap_cx.build.ICmp(lib::llvm::LLVMIntEQ, heap_ptr,
                              C_null(T_ptr(llheapptrty)));
    auto zero_len_cx = new_sub_block_ctxt(bcx, "zero_len");
    auto nonzero_len_cx = new_sub_block_ctxt(bcx, "nonzero_len");
    on_heap_cx.build.CondBr(heap_ptr_is_null, zero_len_cx.llbb,
                            nonzero_len_cx.llbb);
    // Technically this context is unnecessary, but it makes this function
    // clearer.

    auto zero_len = C_int(0);
    auto zero_elem = C_null(T_ptr(llunitty));
    zero_len_cx.build.Br(next_cx.llbb);
    // If we're here, then we actually have a heapified vector.

    auto heap_len = load_inbounds(nonzero_len_cx, heap_ptr,
                                  ~[C_int(0),
                                    C_uint(abi::ivec_heap_elt_len)]);
    auto heap_elem =
        {
            auto v = ~[C_int(0), C_uint(abi::ivec_heap_elt_elems),
                       C_int(0)];
            nonzero_len_cx.build.InBoundsGEP(heap_ptr,v)
        };

    nonzero_len_cx.build.Br(next_cx.llbb);

    // Now we can figure out the length of |v| and get a pointer to its
    // first element.

    auto len =
        next_cx.build.Phi(T_int(), ~[stack_len, zero_len, heap_len],
                          ~[bcx.llbb, zero_len_cx.llbb,
                            nonzero_len_cx.llbb]);
    auto elem =
        next_cx.build.Phi(T_ptr(llunitty),
                          ~[stack_elem, zero_elem, heap_elem],
                          ~[bcx.llbb, zero_len_cx.llbb,
                            nonzero_len_cx.llbb]);
    ret tup(next_cx, len, elem);
}

fn trans_concat(&@block_ctxt cx, &dest in_dest, &span sp, ty::t t,
                &@ast::expr lhs, &@ast::expr rhs) -> @block_ctxt {
    auto bcx = cx;

    // TODO: Detect "a = a + b" and promote to trans_append.
    // TODO: Detect "a + [ literal ]" and optimize to copying the literal
    //       elements in directly.

    auto t = ty::expr_ty(bcx_tcx(bcx), lhs);
    auto skip_null = ty::type_is_str(bcx_tcx(bcx), t);

    // Translate the LHS and RHS. Pull out their length and data.
    auto lhs_tmp = trans_dps::dest_alias(bcx_tcx(bcx), t);
    bcx = trans_dps::trans_expr(bcx, lhs_tmp, lhs);
    auto lllhsptr = trans_dps::dest_ptr(lhs_tmp);

    auto rhs_tmp = trans_dps::dest_alias(bcx_tcx(bcx), t);
    bcx = trans_dps::trans_expr(bcx, rhs_tmp, rhs);
    auto llrhsptr = trans_dps::dest_ptr(rhs_tmp);

    auto r0 = get_len_and_data(bcx, t, lllhsptr);
    bcx = r0._0; auto lllhslen = r0._1; auto lllhsdata = r0._2;
    r0 = get_len_and_data(bcx, t, llrhsptr);
    bcx = r0._0; auto llrhslen = r0._1; auto llrhsdata = r0._2;

    if skip_null { lllhslen = bcx.build.Sub(lllhslen, C_int(1)); }

    // Allocate the destination.
    auto r1 = trans_dps::spill_alias(bcx, in_dest, t);
    bcx = r1._0; auto dest = r1._1;

    auto unit_t = ty::sequence_element_type(bcx_tcx(bcx), t);
    auto unit_sz = trans_dps::size_of(bcx_ccx(bcx), sp, unit_t);

    auto stack_elems_sz = unit_sz * abi::ivec_default_length;
    auto lldestptr = trans_dps::dest_ptr(dest);
    auto llunitty = trans::type_of(bcx_ccx(bcx), sp, unit_t);

    // Decide whether to allocate the result on the stack or on the heap.
    auto llnewlen = bcx.build.Add(lllhslen, llrhslen);
    auto llonstack = bcx.build.ICmp(lib::llvm::LLVMIntULE, llnewlen,
                                    C_uint(stack_elems_sz));
    auto on_stack_bcx = new_sub_block_ctxt(bcx, "on_stack");
    auto on_heap_bcx = new_sub_block_ctxt(bcx, "on_heap");
    bcx.build.CondBr(llonstack, on_stack_bcx.llbb, on_heap_bcx.llbb);

    // On-stack case.
    auto next_bcx = new_sub_block_ctxt(bcx, "next");
    trans::store_inbounds(on_stack_bcx, llnewlen, lldestptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_len)]);
    trans::store_inbounds(on_stack_bcx, C_uint(stack_elems_sz), lldestptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_alen)]);
    auto llonstackdataptr =
        on_stack_bcx.build.InBoundsGEP(lldestptr,
                                       ~[C_int(0),
                                         C_uint(abi::ivec_elt_elems),
                                         C_int(0)]);
    on_stack_bcx.build.Br(next_bcx.llbb);

    // On-heap case.
    auto llheappartty = tc::T_ivec_heap(llunitty);
    auto lldeststubptr =
        on_heap_bcx.build.PointerCast(lldestptr, tc::T_ptr(llheappartty));
    trans::store_inbounds(on_heap_bcx, C_int(0), lldeststubptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_len)]);
    trans::store_inbounds(on_heap_bcx, llnewlen, lldeststubptr,
                          ~[C_int(0), C_uint(abi::ivec_elt_alen)]);

    auto llheappartptrptr =
        on_heap_bcx.build.InBoundsGEP(lldeststubptr,
                                      ~[C_int(0),
                                        C_uint(abi::ivec_elt_elems)]);
    auto llsizeofint = C_uint(llsize_of(bcx_ccx(bcx), tc::T_int()));
    on_heap_bcx = trans_dps::malloc(on_heap_bcx, llheappartptrptr,
                                    trans_dps::hp_shared,
                                    some(on_heap_bcx.build.Add(llnewlen,
                                                               llsizeofint)));
    auto llheappartptr = on_heap_bcx.build.Load(llheappartptrptr);
    trans::store_inbounds(on_heap_bcx, llnewlen, llheappartptr,
                          ~[C_int(0), C_uint(abi::ivec_heap_elt_len)]);
    auto llheapdataptr =
        on_heap_bcx.build.InBoundsGEP(llheappartptr,
                                      ~[C_int(0),
                                        C_uint(abi::ivec_heap_elt_elems),
                                        C_int(0)]);
    on_heap_bcx.build.Br(next_bcx.llbb);

    // Perform the memmove.
    auto lldataptr =
        next_bcx.build.Phi(T_ptr(llunitty),
                           ~[llonstackdataptr, llheapdataptr],
                           ~[on_stack_bcx.llbb, on_heap_bcx.llbb]);
    trans_dps::memmove(next_bcx, lldataptr, lllhsdata, lllhslen);
    trans_dps::memmove(next_bcx,
                       next_bcx.build.InBoundsGEP(lldataptr, ~[lllhslen]),
                       llrhsdata, llrhslen);

    ret next_bcx;
}

<|endoftext|>


<commit_before><commit_msg>Add Figure 1.5<commit_after>extern crate libc;
extern crate apue;

use libc::{c_int, c_char, FILE, STDIN_FILENO, STDOUT_FILENO, fdopen, ferror};
use apue::LibcResult;

extern "C" {
    pub fn putc(arg1:c_int, arg2: *mut FILE) -> c_int;
    pub fn getc(arg1: *mut FILE) -> c_int;
}

fn main() {
	unsafe {
	    let stdin = fdopen(STDIN_FILENO, &('r' as c_char));
	    let stdout = fdopen(STDOUT_FILENO, &('w' as c_char));
	    while let Some(c) = getc(stdin).to_option() {
	    	assert!(putc(c, stdout) >= 0, "output error");
	    }
	    assert!(ferror(stdin) == 0, "input error");
	}
}<|endoftext|>


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

//! Runtime calls emitted by the compiler.

use cast::transmute;
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
use managed::raw::BoxRepr;
use str;
use sys;
use unstable::exchange_alloc;
use cast::transmute;

#[allow(non_camel_case_types)]
pub type rust_task = c_void;

#[cfg(target_word_size = "32")]
pub static FROZEN_BIT: uint = 0x80000000;
#[cfg(target_word_size = "64")]
pub static FROZEN_BIT: uint = 0x8000000000000000;

pub mod rustrt {
    use libc::{c_char, uintptr_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;

        #[rust_stack]
        unsafe fn rust_upcall_free(ptr: *c_char);
    }
}

#[lang="fail_"]
pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
    sys::begin_unwind_(expr, file, line);
}

#[lang="fail_bounds_check"]
pub unsafe fn fail_bounds_check(file: *c_char, line: size_t,
                                index: size_t, len: size_t) {
    let msg = fmt!("index out of bounds: the len is %d but the index is %d",
                    len as int, index as int);
    do str::as_buf(msg) |p, _len| {
        fail_(p as *c_char, file, line);
    }
}

pub unsafe fn fail_borrowed() {
    let msg = "borrowed";
    do str::as_buf(msg) |msg_p, _| {
        do str::as_buf("???") |file_p, _| {
            fail_(msg_p as *c_char, file_p as *c_char, 0);
        }
    }
}

// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
#[lang="exchange_malloc"]
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    transmute(exchange_alloc::malloc(transmute(td), transmute(size)))
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="exchange_free"]
pub unsafe fn exchange_free(ptr: *c_char) {
    exchange_alloc::free(transmute(ptr))
}

#[lang="malloc"]
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    return rustrt::rust_upcall_malloc(td, size);
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="free"]
pub unsafe fn local_free(ptr: *c_char) {
    rustrt::rust_upcall_free(ptr);
}

#[lang="borrow_as_imm"]
#[inline(always)]
pub unsafe fn borrow_as_imm(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    (*a).header.ref_count |= FROZEN_BIT;
}

#[lang="return_to_mut"]
#[inline(always)]
pub unsafe fn return_to_mut(a: *u8) {
    // Sometimes the box is null, if it is conditionally frozen.
    // See e.g. #4904.
    if !a.is_null() {
        let a: *mut BoxRepr = transmute(a);
        (*a).header.ref_count &= !FROZEN_BIT;
    }
}

#[lang="check_not_borrowed"]
#[inline(always)]
pub unsafe fn check_not_borrowed(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    if ((*a).header.ref_count & FROZEN_BIT) != 0 {
        fail_borrowed();
    }
}

#[lang="strdup_uniq"]
pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
    str::raw::from_buf_len(ptr, len)
}

#[lang="start"]
pub fn start(main: *u8, argc: int, argv: *c_char,
             crate_map: *u8) -> int {
    use libc::getenv;
    use rt::start;

    unsafe {
        let use_new_rt = do str::as_c_str("RUST_NEWRT") |s| {
            getenv(s).is_null()
        };
        if use_new_rt {
            return rust_start(main as *c_void, argc as c_int, argv,
                              crate_map as *c_void) as int;
        } else {
            return start(main, argc, argv, crate_map);
        }
    }

    extern {
        fn rust_start(main: *c_void, argc: c_int, argv: *c_char,
                      crate_map: *c_void) -> c_int;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>core: Inline mallocing wrapper functions<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Runtime calls emitted by the compiler.

use cast::transmute;
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
use managed::raw::BoxRepr;
use str;
use sys;
use unstable::exchange_alloc;
use cast::transmute;

#[allow(non_camel_case_types)]
pub type rust_task = c_void;

#[cfg(target_word_size = "32")]
pub static FROZEN_BIT: uint = 0x80000000;
#[cfg(target_word_size = "64")]
pub static FROZEN_BIT: uint = 0x8000000000000000;

pub mod rustrt {
    use libc::{c_char, uintptr_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;

        #[rust_stack]
        unsafe fn rust_upcall_free(ptr: *c_char);
    }
}

#[lang="fail_"]
pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
    sys::begin_unwind_(expr, file, line);
}

#[lang="fail_bounds_check"]
pub unsafe fn fail_bounds_check(file: *c_char, line: size_t,
                                index: size_t, len: size_t) {
    let msg = fmt!("index out of bounds: the len is %d but the index is %d",
                    len as int, index as int);
    do str::as_buf(msg) |p, _len| {
        fail_(p as *c_char, file, line);
    }
}

pub unsafe fn fail_borrowed() {
    let msg = "borrowed";
    do str::as_buf(msg) |msg_p, _| {
        do str::as_buf("???") |file_p, _| {
            fail_(msg_p as *c_char, file_p as *c_char, 0);
        }
    }
}

// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
#[lang="exchange_malloc"]
#[inline(always)]
pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    transmute(exchange_alloc::malloc(transmute(td), transmute(size)))
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="exchange_free"]
#[inline(always)]
pub unsafe fn exchange_free(ptr: *c_char) {
    exchange_alloc::free(transmute(ptr))
}

#[lang="malloc"]
#[inline(always)]
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
    return rustrt::rust_upcall_malloc(td, size);
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[lang="free"]
#[inline(always)]
pub unsafe fn local_free(ptr: *c_char) {
    rustrt::rust_upcall_free(ptr);
}

#[lang="borrow_as_imm"]
#[inline(always)]
pub unsafe fn borrow_as_imm(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    (*a).header.ref_count |= FROZEN_BIT;
}

#[lang="return_to_mut"]
#[inline(always)]
pub unsafe fn return_to_mut(a: *u8) {
    // Sometimes the box is null, if it is conditionally frozen.
    // See e.g. #4904.
    if !a.is_null() {
        let a: *mut BoxRepr = transmute(a);
        (*a).header.ref_count &= !FROZEN_BIT;
    }
}

#[lang="check_not_borrowed"]
#[inline(always)]
pub unsafe fn check_not_borrowed(a: *u8) {
    let a: *mut BoxRepr = transmute(a);
    if ((*a).header.ref_count & FROZEN_BIT) != 0 {
        fail_borrowed();
    }
}

#[lang="strdup_uniq"]
#[inline(always)]
pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
    str::raw::from_buf_len(ptr, len)
}

#[lang="start"]
pub fn start(main: *u8, argc: int, argv: *c_char,
             crate_map: *u8) -> int {
    use libc::getenv;
    use rt::start;

    unsafe {
        let use_new_rt = do str::as_c_str("RUST_NEWRT") |s| {
            getenv(s).is_null()
        };
        if use_new_rt {
            return rust_start(main as *c_void, argc as c_int, argv,
                              crate_map as *c_void) as int;
        } else {
            return start(main, argc, argv, crate_map);
        }
    }

    extern {
        fn rust_start(main: *c_void, argc: c_int, argv: *c_char,
                      crate_map: *c_void) -> c_int;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before><commit_msg>Add example sending a message to a parent widget<commit_after>/*
 * Copyright (c) 2021 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

use gtk::{
    ButtonExt,
    EditableSignals,
    EntryExt,
    Inhibit,
    LabelExt,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::{Relm, StreamHandle, Widget};
use relm_derive::{Msg, widget};

use self::CounterMsg::*;
use self::Msg::*;
use self::TextMsg::*;

pub struct TextModel {
    content: String,
    win_stream: StreamHandle<Msg>,
}

#[derive(Msg)]
pub enum TextMsg {
    Change(glib::GString),
}

#[widget]
impl Widget for Text {
    fn model(win_stream: StreamHandle<Msg>) -> TextModel {
        TextModel {
            content: String::new(),
            win_stream,
        }
    }

    fn update(&mut self, event: TextMsg) {
        match event {
            Change(text) => {
                self.model.content = text.chars().rev().collect();
                self.model.win_stream.emit(TextChange(text.to_string()));
            },
        }
    }

    view! {
        gtk::Box {
            orientation: Vertical,
            gtk::Entry {
                changed(entry) => Change(entry.get_text()),
                widget_name: "entry",
            },
            gtk::Label {
                text: &self.model.content,
                widget_name: "text_label",
            },
        }
    }
}

pub struct CounterModel {
    counter: i32,
}

#[derive(Msg)]
pub enum CounterMsg {
    Decrement,
    Increment,
}

#[widget]
impl Widget for Counter {
    fn model() -> CounterModel {
        CounterModel {
            counter: 0,
        }
    }

    fn update(&mut self, event: CounterMsg) {
        match event {
            Decrement => self.model.counter -= 1,
            Increment => self.increment(),
        }
    }

    view! {
        gtk::Box {
            orientation: Vertical,
            gtk::Button {
                label: "+",
                widget_name: "inc_button",
                clicked => Increment,
            },
            gtk::Label {
                widget_name: "label",
                text: &self.model.counter.to_string(),
            },
            gtk::Button {
                label: "-",
                widget_name: "dec_button",
                clicked => Decrement,
            },
        }
    }

    fn increment(&mut self) {
        self.model.counter += 1;
    }
}

pub struct Model {
    counter: i32,
    relm: Relm<Win>,
}

#[derive(Msg)]
pub enum Msg {
    TextChange(String),
    Quit,
}

#[widget]
impl Widget for Win {
    fn model(relm: &Relm<Self>, _: ()) -> Model {
        Model {
            counter: 0,
            relm: relm.clone(),
        }
    }

    fn update(&mut self, event: Msg) {
        match event {
            TextChange(text) => {
                println!("{}", text);
                self.model.counter += 1
            },
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Box {
                #[name="dec_button"]
                gtk::Button {
                    label: "Decrement",
                    clicked => counter1@Decrement,
                },
                #[name="counter1"]
                Counter {
                    Increment => counter2@Decrement,
                    Increment => log_increment(),
                },
                #[name="counter2"]
                Counter,
                #[name="text"]
                Text(self.model.relm.stream().clone()) {
                    Change(_) => counter1@Increment,
                },
                #[name="label"]
                gtk::Label {
                    text: &self.model.counter.to_string(),
                }
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

fn log_increment() {
    println!("Increment");
}

fn main() {
    Win::run(()).expect("Win::run failed");
}

#[cfg(test)]
mod tests {
    use gtk::{Button, Entry, Label, LabelExt};

    use gtk_test::{assert_text, find_child_by_name};
    use relm_test::{click, enter_keys};

    use crate::Win;

    #[test]
    fn label_change() {
        let (_component, _, widgets) = relm::init_test::<Win>(()).expect("init_test failed");
        let dec_button = &widgets.dec_button;
        let label1: Label = find_child_by_name(&widgets.counter1, "label").expect("label1");
        let inc_button1: Button = find_child_by_name(&widgets.counter1, "inc_button").expect("button1");
        let dec_button1: Button = find_child_by_name(&widgets.counter1, "dec_button").expect("button1");
        let label2: Label = find_child_by_name(&widgets.counter2, "label").expect("label2");
        let label = &widgets.label;
        let entry: Entry = find_child_by_name(&widgets.text, "entry").expect("entry");
        let text_label: Label = find_child_by_name(&widgets.text, "text_label").expect("label");

        assert_text!(label1, 0);

        click(dec_button);
        assert_text!(label1, -1);

        click(dec_button);
        assert_text!(label1, -2);

        assert_text!(label2, 0);

        click(&inc_button1);
        assert_text!(label1, -1);
        assert_text!(label2, -1);

        click(&inc_button1);
        assert_text!(label1, 0);
        assert_text!(label2, -2);

        click(&dec_button1);
        assert_text!(label1, -1);
        assert_text!(label2, -2);

        click(&dec_button1);
        assert_text!(label1, -2);
        assert_text!(label2, -2);

        assert_text!(label, 0);

        enter_keys(&entry, "t");
        assert_text!(label, 1);
        assert_text!(label1, -1);
        assert_text!(text_label, "t");

        enter_keys(&entry, "e");
        assert_text!(label, 2);
        assert_text!(label1, 0);
        assert_text!(text_label, "et");
    }
}
<|endoftext|>


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

// Check that one cannot subvert Drop Check rule via a user-defined
// Clone implementation.

#![allow(unused_variables, unused_assignments)]

struct D<T:Copy>(T, &'static str);

#[derive(Copy)]
struct S<'a>(&'a D<i32>, &'static str);
impl<'a> Clone for S<'a> {
    fn clone(&self) -> S<'a> {
        println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0);
        S(self.0, self.1)
    }
}

impl<T:Copy> Drop for D<T> {
    fn drop(&mut self) {
        println!("calling Drop for {}", self.1);
        let _call = self.0.clone();
    }
}

fn main() {
    let (d2, d1);
    d1 = D(34, "d1");
    d2 = D(S(&d1, "inner"), "d2"); //~ ERROR `d1` does not live long enough
}
<|endoftext|>


<commit_before><commit_msg>add bench<commit_after>#![feature(test)]

extern crate test;
extern crate hc256;

use test::Bencher;
use hc256::HC256;

#[bench]
fn hc128_bench(b: &mut Bencher) {
    let key = [0; 32];
    let iv = [0; 32];
    let input = [0; 64];
    let mut output = [0; 64];
    let mut cipher = HC256::new(&key, &iv);

    b.bytes = input.len() as u64;
    b.iter(|| cipher.process(&input, &mut output))
}
<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) Nathan Zadoks <nathan@nathan7.eu>,
//               whitequark <whitequark@whitequark.org>
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

// To understand the machine code in this file, keep in mind these facts:
// * OR1K C ABI has a "red zone": 128 bytes under the top of the stack
//   that is defined to be unmolested by signal handlers, interrupts, etc.
//   Leaf functions can use the red zone without adjusting r1 or r2.
// * OR1K C ABI passes the first argument in r3. We also use r3 to pass a value
//   while swapping context; this is an arbitrary choice
//   (we clobber all registers and could use any of them) but this allows us
//   to reuse the swap function to perform the initial call.
//
// To understand the DWARF CFI code in this file, keep in mind these facts:
// * CFI is "call frame information"; a set of instructions to a debugger or
//   an unwinder that allow it to simulate returning from functions. This implies
//   restoring every register to its pre-call state, as well as the stack pointer.
// * CFA is "call frame address"; the value of stack pointer right before the call
//   instruction in the caller. Everything strictly below CFA (and inclusive until
//   the next CFA) is the call frame of the callee. This implies that the return
//   address is the part of callee's call frame.
// * Logically, DWARF CFI is a table where rows are instruction pointer values and
//   columns describe where registers are spilled (mostly using expressions that
//   compute a memory location as CFA+n). A .cfi_offset pseudoinstruction changes
//   the state of a column for all IP numerically larger than the one it's placed
//   after. A .cfi_def_* pseudoinstruction changes the CFA value similarly.
// * Simulating return is as easy as restoring register values from the CFI table
//   and then setting stack pointer to CFA.
//
// A high-level overview of the function of the trampolines is:
// * The 2nd init trampoline puts a controlled value (written in swap to `new_cfa`)
//   into r13.
// * The 1st init trampoline tells the unwinder to set r1 to r13, thus continuing
//   unwinding at the swap call site instead of falling off the end of context stack.
// * The 1st init trampoline together with the swap trampoline also restore r2
//   when unwinding as well as returning normally, because LLVM does not do it for us.
use stack::Stack;

#[derive(Debug, Clone)]
pub struct StackPointer(*mut usize);

pub unsafe fn init(stack: &Stack, f: unsafe extern "C" fn(usize) -> !) -> StackPointer {
  #[naked]
  unsafe extern "C" fn trampoline_1() {
    asm!(
      r#"
        # gdb has a hardcoded check that rejects backtraces where frame addresses
        # do not monotonically decrease. It is turned off if the function is called
        # "__morestack" and that is hardcoded. So, to make gdb backtraces match
        # the actual unwinder behavior, we call ourselves "__morestack" and mark
        # the symbol as local; it shouldn't interfere with anything.
      __morestack:
      .local __morestack

        # Set up the first part of our DWARF CFI linking stacks together.
        # When unwinding the frame corresponding to this function, a DWARF unwinder
        # will use r13 as the next call frame address, restore return address (r9)
        # from CFA-4 and restore stack pointer (r2) from CFA-8.
        # This mirrors what the second half of `swap_trampoline` does.
        .cfi_def_cfa r13, 0
        .cfi_offset r2, -8
        .cfi_offset r9, -4
        # Call the next trampoline.
        l.j     ${0}
        l.nop

      .Lend:
      .size __morestack, .Lend-__morestack
      "#
      : : "s" (trampoline_2 as usize) : "memory" : "volatile")
  }

  #[naked]
  unsafe extern "C" fn trampoline_2() {
    asm!(
      r#"
        # Set up the second part of our DWARF CFI.
        # When unwinding the frame corresponding to this function, a DWARF unwinder
        # will restore r13 (and thus CFA of the first trampoline) from the stack slot.
        .cfi_offset r13, 4
        # Call the provided function.
        l.lwz   r9, 0(r1)
        l.jr    r9
        l.nop
      "#
      : : : "memory" : "volatile")
  }

  unsafe fn push(sp: &mut StackPointer, val: usize) {
    sp.0 = sp.0.offset(-1);
    *sp.0 = val
  }

  let mut sp = StackPointer(stack.base() as *mut usize);
  push(&mut sp, 0xdead0cfa);            // CFA slot
  push(&mut sp, f as usize);            // function
  let rsp = sp.clone();
  push(&mut sp, trampoline_1 as usize); // saved r9
  push(&mut sp, 0xdeadbbbb);            // saved r2
  rsp
}

#[inline(always)]
pub unsafe fn swap(arg: usize, old_sp: &mut StackPointer, new_sp: &StackPointer,
                   new_stack: &Stack) -> usize {
  // Address of the topmost CFA stack slot.
  let new_cfa = (new_stack.base() as *mut usize).offset(-1);

  #[naked]
  unsafe extern "C" fn trampoline() {
    asm!(
      r#"
        # Save instruction pointer of the old context.
        l.sw    -4(r1), r9

        # Save frame pointer explicitly; the unwinder uses it to find CFA of
        # the caller, and so it has to have the correct value immediately after
        # the call instruction that invoked the trampoline.
        l.sw    -8(r1), r2

        # Remember stack pointer of the old context, in case r5==r4.
        l.or    r13, r0, r1
        # Load stack pointer of the new context.
        l.lwz   r1, 0(r5)
        # Save stack pointer of the old context.
        l.sw    0(r4), r13

        # Restore frame pointer of the new context.
        l.lwz   r2, -8(r1)

        # Return into the new context.
        l.lwz   r9, -4(r1)
        l.jr    r9
        l.nop
      "#
      : : : "memory" : "volatile")
  }

  let ret: usize;
  asm!(
    r#"
      # Link the call stacks together.
      l.sw    0(r6), r1
      # Put instruction pointer of the old context into r9 and switch to
      # the new context.
      l.jal   ${1}
      l.nop
    "#
    : "={r3}" (ret)
    : "s" (trampoline as usize)
      "{r3}" (arg)
      "{r4}" (old_sp)
      "{r5}" (new_sp)
      "{r6}" (new_cfa)
    :/*"r0", "r1",  "r2",  "r3",  "r4",  "r5",  "r6",*/"r7",
      "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
      "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
      "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
      "flags", "memory"
    : "volatile");
  ret
}
<commit_msg>arch/or1k: fix typo.<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) Nathan Zadoks <nathan@nathan7.eu>,
//               whitequark <whitequark@whitequark.org>
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

// To understand the machine code in this file, keep in mind these facts:
// * OR1K C ABI has a "red zone": 128 bytes under the top of the stack
//   that is defined to be unmolested by signal handlers, interrupts, etc.
//   Leaf functions can use the red zone without adjusting r1 or r2.
// * OR1K C ABI passes the first argument in r3. We also use r3 to pass a value
//   while swapping context; this is an arbitrary choice
//   (we clobber all registers and could use any of them) but this allows us
//   to reuse the swap function to perform the initial call.
//
// To understand the DWARF CFI code in this file, keep in mind these facts:
// * CFI is "call frame information"; a set of instructions to a debugger or
//   an unwinder that allow it to simulate returning from functions. This implies
//   restoring every register to its pre-call state, as well as the stack pointer.
// * CFA is "call frame address"; the value of stack pointer right before the call
//   instruction in the caller. Everything strictly below CFA (and inclusive until
//   the next CFA) is the call frame of the callee. This implies that the return
//   address is the part of callee's call frame.
// * Logically, DWARF CFI is a table where rows are instruction pointer values and
//   columns describe where registers are spilled (mostly using expressions that
//   compute a memory location as CFA+n). A .cfi_offset pseudoinstruction changes
//   the state of a column for all IP numerically larger than the one it's placed
//   after. A .cfi_def_* pseudoinstruction changes the CFA value similarly.
// * Simulating return is as easy as restoring register values from the CFI table
//   and then setting stack pointer to CFA.
//
// A high-level overview of the function of the trampolines is:
// * The 2nd init trampoline puts a controlled value (written in swap to `new_cfa`)
//   into r13.
// * The 1st init trampoline tells the unwinder to set r1 to r13, thus continuing
//   unwinding at the swap call site instead of falling off the end of context stack.
// * The 1st init trampoline together with the swap trampoline also restore r2
//   when unwinding as well as returning normally, because LLVM does not do it for us.
use stack::Stack;

#[derive(Debug, Clone)]
pub struct StackPointer(*mut usize);

pub unsafe fn init(stack: &Stack, f: unsafe extern "C" fn(usize) -> !) -> StackPointer {
  #[naked]
  unsafe extern "C" fn trampoline_1() {
    asm!(
      r#"
        # gdb has a hardcoded check that rejects backtraces where frame addresses
        # do not monotonically decrease. It is turned off if the function is called
        # "__morestack" and that is hardcoded. So, to make gdb backtraces match
        # the actual unwinder behavior, we call ourselves "__morestack" and mark
        # the symbol as local; it shouldn't interfere with anything.
      __morestack:
      .local __morestack

        # Set up the first part of our DWARF CFI linking stacks together.
        # When unwinding the frame corresponding to this function, a DWARF unwinder
        # will use r13 as the next call frame address, restore return address (r9)
        # from CFA-4 and restore frame pointer (r2) from CFA-8.
        # This mirrors what the second half of `swap_trampoline` does.
        .cfi_def_cfa r13, 0
        .cfi_offset r2, -8
        .cfi_offset r9, -4
        # Call the next trampoline.
        l.j     ${0}
        l.nop

      .Lend:
      .size __morestack, .Lend-__morestack
      "#
      : : "s" (trampoline_2 as usize) : "memory" : "volatile")
  }

  #[naked]
  unsafe extern "C" fn trampoline_2() {
    asm!(
      r#"
        # Set up the second part of our DWARF CFI.
        # When unwinding the frame corresponding to this function, a DWARF unwinder
        # will restore r13 (and thus CFA of the first trampoline) from the stack slot.
        .cfi_offset r13, 4
        # Call the provided function.
        l.lwz   r9, 0(r1)
        l.jr    r9
        l.nop
      "#
      : : : "memory" : "volatile")
  }

  unsafe fn push(sp: &mut StackPointer, val: usize) {
    sp.0 = sp.0.offset(-1);
    *sp.0 = val
  }

  let mut sp = StackPointer(stack.base() as *mut usize);
  push(&mut sp, 0xdead0cfa);            // CFA slot
  push(&mut sp, f as usize);            // function
  let rsp = sp.clone();
  push(&mut sp, trampoline_1 as usize); // saved r9
  push(&mut sp, 0xdeadbbbb);            // saved r2
  rsp
}

#[inline(always)]
pub unsafe fn swap(arg: usize, old_sp: &mut StackPointer, new_sp: &StackPointer,
                   new_stack: &Stack) -> usize {
  // Address of the topmost CFA stack slot.
  let new_cfa = (new_stack.base() as *mut usize).offset(-1);

  #[naked]
  unsafe extern "C" fn trampoline() {
    asm!(
      r#"
        # Save instruction pointer of the old context.
        l.sw    -4(r1), r9

        # Save frame pointer explicitly; the unwinder uses it to find CFA of
        # the caller, and so it has to have the correct value immediately after
        # the call instruction that invoked the trampoline.
        l.sw    -8(r1), r2

        # Remember stack pointer of the old context, in case r5==r4.
        l.or    r13, r0, r1
        # Load stack pointer of the new context.
        l.lwz   r1, 0(r5)
        # Save stack pointer of the old context.
        l.sw    0(r4), r13

        # Restore frame pointer of the new context.
        l.lwz   r2, -8(r1)

        # Return into the new context.
        l.lwz   r9, -4(r1)
        l.jr    r9
        l.nop
      "#
      : : : "memory" : "volatile")
  }

  let ret: usize;
  asm!(
    r#"
      # Link the call stacks together.
      l.sw    0(r6), r1
      # Put instruction pointer of the old context into r9 and switch to
      # the new context.
      l.jal   ${1}
      l.nop
    "#
    : "={r3}" (ret)
    : "s" (trampoline as usize)
      "{r3}" (arg)
      "{r4}" (old_sp)
      "{r5}" (new_sp)
      "{r6}" (new_cfa)
    :/*"r0", "r1",  "r2",  "r3",  "r4",  "r5",  "r6",*/"r7",
      "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
      "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
      "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
      "flags", "memory"
    : "volatile");
  ret
}
<|endoftext|>


<commit_before><commit_msg>Solve Salary with Bonus in rust<commit_after>use std::io;

fn main() {
    let mut input_a = String::new();
    let mut input_b = String::new();
    let mut input_c = String::new();

    if let Err(_e) = io::stdin().read_line(&mut input_a){}
    let _a: String = input_a.trim().parse().unwrap();

    if let Err(_e) = io::stdin().read_line(&mut input_b){}
    let b: f64 = input_b.trim().parse().unwrap();

    if let Err(_e) = io::stdin().read_line(&mut input_c){}
    let c: f64 = input_c.trim().parse().unwrap();

    println!("TOTAL = R$ {:.2}", b + c * 0.15);
}
<|endoftext|>


<commit_before><commit_msg>scaffolding for raindrops<commit_after>
pub fn raindrops(_: i32) -> String {
    String::from("")
}
<|endoftext|>


<commit_before><commit_msg>change folder structure<commit_after>// clap used as argument handler
extern crate clap;

use clap::{App, Arg};

// This Struct is later given to our main program,
// it contains all the needed information to make suggestions of films
#[derive(Debug, Clone)]
struct SearchParams {
    genre: Vec<String>,
    movies: Vec<String>,
    actors: Vec<String>,
}

impl SearchParams {
    // initialize a SearchParams type with empty fields
    fn init() -> Self {
        SearchParams {
            genre: Vec::new(),
            movies: Vec::new(),
            actors: Vec::new(),
        }
    }
}

// Creates struct SearchParams in which all given parameters are included.
fn get_search_params() -> SearchParams {
    // later given to main program, contains all arguments given in
    // command line
    let mut search_params = SearchParams::init();

    // our matches, we can later use those to handle our commandline input
    let matches = App::new("FOM")
        .arg(Arg::with_name("genre")
            .short("g")
            .takes_value(true))
        .arg(Arg::with_name("actor")
            .short("a")
            .takes_value(true))
        .arg(Arg::with_name("movie")
            .short("m")
            .takes_value(true)
            .multiple(true))
        .get_matches();

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("genre"){
        let genre =
            match matches.value_of("genre") {
                Some(genre) => genre,
                None => panic!(),
        };
        search_params.genre.push(genre.into());
        // Debug
        // println!("Genre: {}", genre);
    }

    // If an actor was given, save it in our SearchParams Type
    if matches.is_present("actor"){
        let actor =
            match matches.value_of("actor") {
                Some(actor) => actor,
                None => panic!(),
        };
        search_params.actors.push(actor.into());
        // Debug
        // println!("Actor: {}", actor);
    }

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("movie"){
        let movies:Vec<String> =
            match matches.values_of("movie") {
                Some(vals) => vals
                    .map(|x| x.to_string())
                    .collect(),
                None => panic!(),
        };
        search_params.movies = movies;
        // Debug
        // println!("Movies: {:?}", search_params.genre);
    }
    // Debug
    // println!("{:?}", search_params);

    // return struct with all needed search_params
    search_params
}

// fn main() {
    // Test
    // possible test_input could be
    // cargo run -- -a Name -m Lieblingsfilm1 Lieblingsfilm2 -g horror

    // let args = get_search_params();
    // println!("{:?}", args);
// }
<|endoftext|>


<commit_before><commit_msg>Refactor Script Execution<commit_after><|endoftext|>


<commit_before><commit_msg>parse new usernotice resub and fix some tests in parse.rs<commit_after><|endoftext|>


<commit_before><commit_msg>Implemented calculation of LanManager and NT responses.<commit_after><|endoftext|>


<commit_before><commit_msg>basic match added<commit_after><|endoftext|>


<commit_before><commit_msg>Fixing build.rs for travis<commit_after><|endoftext|>


<commit_before><commit_msg>rust version<commit_after>use std::collections::{HashMap, HashSet};

pub fn max_sum_range_query(nums: Vec<i32>, requests: Vec<Vec<i32>>) -> i32 {
    let mut record: HashMap<usize, usize> = HashMap::new(); // ind -> count
    for v in &requests {
        for ind in v[0]..=v[1] {
            let a = record.entry(ind as usize).or_insert(0);
            *a += 1
        }
    }

    let mut count_set = HashSet::new();
    let mut count_ind: HashMap<usize, Vec<usize>> = HashMap::new(); // count -> vec<ind>
    for (k, v) in record.iter() {
        let a = count_ind.entry(*v).or_insert(vec![]);
        a.push(*k);
        count_set.insert(v);
    }

    let mut count_set = count_set.into_iter().map(|a| *a).collect::<Vec<usize>>();
    count_set.sort();
    count_set.reverse();
    //dbg!(&count_ind);
    //dbg!(&count_set);

    // sort nums
    let mut sort_nums = nums.clone();
    sort_nums.sort();
    sort_nums.reverse(); // larger to smaller
                         //dbg!(&sort_nums);
    let mut sort_nums_iter = sort_nums.iter();

    let mut whole_vec = vec![0; 100000];
    for v in count_set {
        for ind in count_ind.get(&v).unwrap() {
            whole_vec[*ind] = *sort_nums_iter.next().unwrap()
        }
    }

    //dbg!(&whole_vec[0..10]);

    // get result
    let mut result = 0;
    for ind_range in requests {
        result = result % 1000000007
            + (ind_range[0]..=ind_range[1])
                .map(|ind| whole_vec[ind as usize] % 1000000007)
                .sum::<i32>()
                % 1000000007;
    }

    result
}

// first one is too slow, obiviously
pub fn max_sum_range_query2(nums: Vec<i32>, requests: Vec<Vec<i32>>) -> i32 {
    let mut record: HashMap<usize, usize> = HashMap::new(); // ind -> count
    for v in &requests {
        for ind in v[0]..=v[1] {
            let a = record.entry(ind as usize).or_insert(0);
            *a += 1
        }
    }

    let mut count_set = HashSet::new();
    let mut count_ind: HashMap<usize, usize> = HashMap::new(); // count -> number of ind has this count
    for (_, v) in record.iter() {
        let a = count_ind.entry(*v).or_insert(0);
        *a += 1;
        count_set.insert(v);
    }

    let mut count_set = count_set.into_iter().map(|a| *a).collect::<Vec<usize>>();
    count_set.sort();
    count_set.reverse();

    // sort nums
    let mut sort_nums = nums.clone();
    sort_nums.sort();
    sort_nums.reverse(); // larger to smaller
    let mut sort_nums_iter = sort_nums.iter();

    let mut result = 0;
    for count in count_set {
        for _ in 0_usize..*count_ind.get(&count).unwrap() {
            result = result % 1000000007
                + (count as i32 * sort_nums_iter.next().unwrap() % 1000000007) % 1000000007
        }
    }
    result
}

pub fn max_sum_range_query3(nums: Vec<i32>, requests: Vec<Vec<i32>>) -> i32 {
    let mut ind_count = vec![0; 100000];
    for v in &requests {
        for ind in v[0]..=v[1] {
            ind_count[ind as usize] += 1
        }
    }

    ind_count.sort();
    ind_count.reverse();

    let mut sort_nums = nums.clone();
    sort_nums.sort();
    sort_nums.reverse(); // larger to smaller

    let mut module_table: HashMap<i32, i32> = HashMap::new();

    let mut result = 0;
    for ind in 0..nums.len() {
        //result = result % 1000000007 + (ind_count[ind] * sort_nums[ind]) % 1000000007;
        result = result % 1000000007
            + get_big_module(&mut module_table, ind_count[ind] * sort_nums[ind]);
    }

    result
}

fn get_big_module(table: &mut HashMap<i32, i32>, num: i32) -> i32 {
    if num < 1000000007 {
        return num;
    }

    match table.get(&num).as_ref() {
        Some(n) => {
            return **n;
        }
        None => {
            let aa = (1 + get_big_module(table, num - 1)) % 1000000007;
            table.insert(num, aa);
        }
    }

    *table.get(&num).unwrap()
}

fn main() {
    assert_eq!(
        max_sum_range_query3(
            vec![1, 2, 3, 4, 5, 10],
            vec![vec![0, 2], vec![1, 3], vec![1, 1]]
        ),
        47
    );

    assert_eq!(
        max_sum_range_query3(vec![1, 2, 3, 4, 5, 6], vec![vec![0, 1]]),
        11
    );

    assert_eq!(
        max_sum_range_query3(vec![1, 2, 3, 4, 5], vec![vec![1, 3], vec![0, 1]]),
        19
    );
}
<|endoftext|>


<commit_before><commit_msg>[Rust] created issue_435_test.rs<commit_after>use ::issue435::*;

fn create_encoder(buffer: &mut Vec<u8>) -> Issue435Encoder {
    let issue_435 = Issue435Encoder::default().wrap(
        WriteBuf::new(buffer.as_mut_slice()),
        message_header::ENCODED_LENGTH,
    );
    let mut header = issue_435.header(0);
    header.s(*SetRef::default().set_one(true));
    header.parent().unwrap()
}

#[test]
fn issue_435_ref_test() -> SbeResult<()> {
    assert_eq!(9, message_header::ENCODED_LENGTH);
    assert_eq!(1, issue435::SBE_BLOCK_LENGTH);
    assert_eq!(0, issue435::SBE_SCHEMA_VERSION);

    // encode...
    let mut buffer = vec![0u8; 256];
    let encoder = create_encoder(&mut buffer);
    encoder.example_encoder().e(EnumRef::Two);

    // decode...
    let buf = ReadBuf::new(buffer.as_slice());
    let header = MessageHeaderDecoder::default().wrap(buf, 0);
    assert_eq!(issue435::SBE_BLOCK_LENGTH, header.block_length());
    assert_eq!(issue435::SBE_SCHEMA_VERSION, header.version());
    assert_eq!(issue435::SBE_TEMPLATE_ID, header.template_id());
    assert_eq!(issue435::SBE_SCHEMA_ID, header.schema_id());
    assert_eq!(*SetRef::default().set_one(true), header.s());

    let decoder = Issue435Decoder::default().header(header);
    assert_eq!(EnumRef::Two, decoder.example_decoder().e());

    Ok(())
}
<|endoftext|>


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

use build::{Location, ScopeAuxiliaryVec};
use rustc::hir;
use rustc::mir::repr::*;
use rustc::mir::transform::MirSource;
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fnv::FnvHashMap;
use std::fmt::Display;
use std::fs;
use std::io::{self, Write};
use syntax::ast::NodeId;
use syntax::codemap::Span;

const INDENT: &'static str = "    ";
/// Alignment for lining up comments following MIR statements
const ALIGN: usize = 40;

/// If the session is properly configured, dumps a human-readable
/// representation of the mir into:
///
/// ```text
/// rustc.node<node_id>.<pass_name>.<disambiguator>
/// ```
///
/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
/// where `<filter>` takes the following forms:
///
/// - `all` -- dump MIR for all fns, all passes, all everything
/// - `substring1&substring2,...` -- `&`-separated list of substrings
///   that can appear in the pass-name or the `item_path_str` for the given
///   node-id. If any one of the substrings match, the data is dumped out.
pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          pass_name: &str,
                          disambiguator: &Display,
                          src: MirSource,
                          mir: &Mir<'tcx>,
                          auxiliary: Option<&ScopeAuxiliaryVec>) {
    let filters = match tcx.sess.opts.debugging_opts.dump_mir {
        None => return,
        Some(ref filters) => filters,
    };
    let node_id = src.item_id();
    let node_path = tcx.item_path_str(tcx.map.local_def_id(node_id));
    let is_matched =
        filters.split("&")
               .any(|filter| {
                   filter == "all" ||
                       pass_name.contains(filter) ||
                       node_path.contains(filter)
               });
    if !is_matched {
        return;
    }

    let file_name = format!("rustc.node{}.{}.{}.mir",
                            node_id, pass_name, disambiguator);
    let _ = fs::File::create(&file_name).and_then(|mut file| {
        try!(writeln!(file, "// MIR for `{}`", node_path));
        try!(writeln!(file, "// node_id = {}", node_id));
        try!(writeln!(file, "// pass_name = {}", pass_name));
        try!(writeln!(file, "// disambiguator = {}", disambiguator));
        try!(writeln!(file, ""));
        try!(write_mir_fn(tcx, src, mir, &mut file, auxiliary));
        Ok(())
    });
}

/// Write out a human-readable textual representation for the given MIR.
pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                                         iter: I,
                                         w: &mut Write)
                                         -> io::Result<()>
    where I: Iterator<Item=(&'a NodeId, &'a Mir<'tcx>)>, 'tcx: 'a
{
    let mut first = true;
    for (&id, mir) in iter {
        if first {
            first = false;
        } else {
            // Put empty lines between all items
            writeln!(w, "")?;
        }

        let src = MirSource::from_node(tcx, id);
        write_mir_fn(tcx, src, mir, w, None)?;

        for (i, mir) in mir.promoted.iter().enumerate() {
            writeln!(w, "")?;
            write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w, None)?;
        }
    }
    Ok(())
}

enum Annotation {
    EnterScope(ScopeId),
    ExitScope(ScopeId),
}

fn scope_entry_exit_annotations(auxiliary: Option<&ScopeAuxiliaryVec>)
                                -> FnvHashMap<Location, Vec<Annotation>>
{
    // compute scope/entry exit annotations
    let mut annotations = FnvHashMap();
    if let Some(auxiliary) = auxiliary {
        for (index, auxiliary) in auxiliary.vec.iter().enumerate() {
            let scope_id = ScopeId::new(index);

            annotations.entry(auxiliary.dom)
                       .or_insert(vec![])
                       .push(Annotation::EnterScope(scope_id));

            for &loc in &auxiliary.postdoms {
                annotations.entry(loc)
                           .or_insert(vec![])
                           .push(Annotation::ExitScope(scope_id));
            }
        }
    }
    return annotations;
}

pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              src: MirSource,
                              mir: &Mir<'tcx>,
                              w: &mut Write,
                              auxiliary: Option<&ScopeAuxiliaryVec>)
                              -> io::Result<()> {
    let annotations = scope_entry_exit_annotations(auxiliary);
    write_mir_intro(tcx, src, mir, w)?;
    for block in mir.all_basic_blocks() {
        write_basic_block(tcx, block, mir, w, &annotations)?;
    }

    // construct a scope tree and write it out
    let mut scope_tree: FnvHashMap<Option<ScopeId>, Vec<ScopeId>> = FnvHashMap();
    for (index, scope_data) in mir.scopes.iter().enumerate() {
        scope_tree.entry(scope_data.parent_scope)
                  .or_insert(vec![])
                  .push(ScopeId::new(index));
    }

    writeln!(w, "{}scope tree:", INDENT)?;
    write_scope_tree(tcx, mir, auxiliary, &scope_tree, w, None, 1, false)?;
    writeln!(w, "")?;

    writeln!(w, "}}")?;
    Ok(())
}

/// Write out a human-readable textual representation for the given basic block.
fn write_basic_block(tcx: TyCtxt,
                     block: BasicBlock,
                     mir: &Mir,
                     w: &mut Write,
                     annotations: &FnvHashMap<Location, Vec<Annotation>>)
                     -> io::Result<()> {
    let data = mir.basic_block_data(block);

    // Basic block label at the top.
    writeln!(w, "{}{:?}: {{", INDENT, block)?;

    // List of statements in the middle.
    let mut current_location = Location { block: block, statement_index: 0 };
    for statement in &data.statements {
        if let Some(ref annotations) = annotations.get(&current_location) {
            for annotation in annotations.iter() {
                match *annotation {
                    Annotation::EnterScope(id) =>
                        writeln!(w, "{0}{0}// Enter Scope({1})",
                                 INDENT, id.index())?,
                    Annotation::ExitScope(id) =>
                        writeln!(w, "{0}{0}// Exit Scope({1})",
                                 INDENT, id.index())?,
                }
            }
        }

        let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
        writeln!(w, "{0:1$} // {2}",
                 indented_mir,
                 ALIGN,
                 comment(tcx, statement.scope, statement.span))?;

        current_location.statement_index += 1;
    }

    // Terminator at the bottom.
    let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
    writeln!(w, "{0:1$} // {2}",
             indented_terminator,
             ALIGN,
             comment(tcx, data.terminator().scope, data.terminator().span))?;

    writeln!(w, "{}}}\n", INDENT)
}

fn comment(tcx: TyCtxt, scope: ScopeId, span: Span) -> String {
    format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
}

fn write_scope_tree(tcx: TyCtxt,
                    mir: &Mir,
                    auxiliary: Option<&ScopeAuxiliaryVec>,
                    scope_tree: &FnvHashMap<Option<ScopeId>, Vec<ScopeId>>,
                    w: &mut Write,
                    parent: Option<ScopeId>,
                    depth: usize,
                    same_line: bool)
                    -> io::Result<()> {
    let indent = if same_line {
        0
    } else {
        depth * INDENT.len()
    };

    let children = match scope_tree.get(&parent) {
        Some(childs) => childs,
        None => return Ok(()),
    };

    for (index, &child) in children.iter().enumerate() {
        if index == 0 && same_line {
            // We know we're going to output a scope, so prefix it with a space to separate it from
            // the previous scopes on this line
            write!(w, " ")?;
        }

        let data = &mir.scopes[child];
        assert_eq!(data.parent_scope, parent);
        write!(w, "{0:1$}{2}", "", indent, child.index())?;

        let indent = indent + INDENT.len();

        if let Some(auxiliary) = auxiliary {
            let extent = auxiliary[child].extent;
            let data = tcx.region_maps.code_extent_data(extent);
            writeln!(w, "{0:1$}Extent: {2:?}", "", indent, data)?;
        }

        let child_count = scope_tree.get(&Some(child)).map(Vec::len).unwrap_or(0);
        if child_count < 2 {
            // Skip the braces when there's no or only a single subscope
            write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
                             Some(child), depth, true)?;
        } else {
            // 2 or more child scopes? Put them in braces and on new lines.
            writeln!(w, " {{")?;
            write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
                             Some(child), depth + 1, false)?;

            write!(w, "\n{0:1$}}}", "", depth * INDENT.len())?;
        }

        if !same_line && index + 1 < children.len() {
            writeln!(w, "")?;
        }
    }

    Ok(())
}

/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
/// local variables (both user-defined bindings and compiler temporaries).
fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             src: MirSource,
                             mir: &Mir,
                             w: &mut Write)
                             -> io::Result<()> {
    match src {
        MirSource::Fn(_) => write!(w, "fn")?,
        MirSource::Const(_) => write!(w, "const")?,
        MirSource::Static(_, hir::MutImmutable) => write!(w, "static")?,
        MirSource::Static(_, hir::MutMutable) => write!(w, "static mut")?,
        MirSource::Promoted(_, i) => write!(w, "promoted{} in", i)?
    }

    write!(w, " {}", tcx.node_path_str(src.item_id()))?;

    if let MirSource::Fn(_) = src {
        write!(w, "(")?;

        // fn argument types.
        for (i, arg) in mir.arg_decls.iter().enumerate() {
            if i > 0 {
                write!(w, ", ")?;
            }
            write!(w, "{:?}: {}", Lvalue::Arg(i as u32), arg.ty)?;
        }

        write!(w, ") -> ")?;

        // fn return type.
        match mir.return_ty {
            ty::FnOutput::FnConverging(ty) => write!(w, "{}", ty)?,
            ty::FnOutput::FnDiverging => write!(w, "!")?,
        }
    } else {
        assert!(mir.arg_decls.is_empty());
        write!(w, ": {} =", mir.return_ty.unwrap())?;
    }

    writeln!(w, " {{")?;

    // User variable types (including the user's name in a comment).
    for (i, var) in mir.var_decls.iter().enumerate() {
        let mut_str = if var.mutability == Mutability::Mut {
            "mut "
        } else {
            ""
        };

        let indented_var = format!("{}let {}{:?}: {};",
                                   INDENT,
                                   mut_str,
                                   Lvalue::Var(i as u32),
                                   var.ty);
        writeln!(w, "{0:1$} // \"{2}\" in {3}",
                 indented_var,
                 ALIGN,
                 var.name,
                 comment(tcx, var.scope, var.span))?;
    }

    // Compiler-introduced temporary types.
    for (i, temp) in mir.temp_decls.iter().enumerate() {
        writeln!(w, "{}let mut {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty)?;
    }

    // Wrote any declaration? Add an empty line before the first block is printed.
    if !mir.var_decls.is_empty() || !mir.temp_decls.is_empty() {
        writeln!(w, "")?;
    }

    Ok(())
}
<commit_msg>`rustc_mir::pretty` refactoring: break `fn write_fn_intro` into two routines.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use build::{Location, ScopeAuxiliaryVec};
use rustc::hir;
use rustc::mir::repr::*;
use rustc::mir::transform::MirSource;
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fnv::FnvHashMap;
use std::fmt::Display;
use std::fs;
use std::io::{self, Write};
use syntax::ast::NodeId;
use syntax::codemap::Span;

const INDENT: &'static str = "    ";
/// Alignment for lining up comments following MIR statements
const ALIGN: usize = 40;

/// If the session is properly configured, dumps a human-readable
/// representation of the mir into:
///
/// ```text
/// rustc.node<node_id>.<pass_name>.<disambiguator>
/// ```
///
/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
/// where `<filter>` takes the following forms:
///
/// - `all` -- dump MIR for all fns, all passes, all everything
/// - `substring1&substring2,...` -- `&`-separated list of substrings
///   that can appear in the pass-name or the `item_path_str` for the given
///   node-id. If any one of the substrings match, the data is dumped out.
pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          pass_name: &str,
                          disambiguator: &Display,
                          src: MirSource,
                          mir: &Mir<'tcx>,
                          auxiliary: Option<&ScopeAuxiliaryVec>) {
    let filters = match tcx.sess.opts.debugging_opts.dump_mir {
        None => return,
        Some(ref filters) => filters,
    };
    let node_id = src.item_id();
    let node_path = tcx.item_path_str(tcx.map.local_def_id(node_id));
    let is_matched =
        filters.split("&")
               .any(|filter| {
                   filter == "all" ||
                       pass_name.contains(filter) ||
                       node_path.contains(filter)
               });
    if !is_matched {
        return;
    }

    let file_name = format!("rustc.node{}.{}.{}.mir",
                            node_id, pass_name, disambiguator);
    let _ = fs::File::create(&file_name).and_then(|mut file| {
        try!(writeln!(file, "// MIR for `{}`", node_path));
        try!(writeln!(file, "// node_id = {}", node_id));
        try!(writeln!(file, "// pass_name = {}", pass_name));
        try!(writeln!(file, "// disambiguator = {}", disambiguator));
        try!(writeln!(file, ""));
        try!(write_mir_fn(tcx, src, mir, &mut file, auxiliary));
        Ok(())
    });
}

/// Write out a human-readable textual representation for the given MIR.
pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                                         iter: I,
                                         w: &mut Write)
                                         -> io::Result<()>
    where I: Iterator<Item=(&'a NodeId, &'a Mir<'tcx>)>, 'tcx: 'a
{
    let mut first = true;
    for (&id, mir) in iter {
        if first {
            first = false;
        } else {
            // Put empty lines between all items
            writeln!(w, "")?;
        }

        let src = MirSource::from_node(tcx, id);
        write_mir_fn(tcx, src, mir, w, None)?;

        for (i, mir) in mir.promoted.iter().enumerate() {
            writeln!(w, "")?;
            write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w, None)?;
        }
    }
    Ok(())
}

enum Annotation {
    EnterScope(ScopeId),
    ExitScope(ScopeId),
}

fn scope_entry_exit_annotations(auxiliary: Option<&ScopeAuxiliaryVec>)
                                -> FnvHashMap<Location, Vec<Annotation>>
{
    // compute scope/entry exit annotations
    let mut annotations = FnvHashMap();
    if let Some(auxiliary) = auxiliary {
        for (index, auxiliary) in auxiliary.vec.iter().enumerate() {
            let scope_id = ScopeId::new(index);

            annotations.entry(auxiliary.dom)
                       .or_insert(vec![])
                       .push(Annotation::EnterScope(scope_id));

            for &loc in &auxiliary.postdoms {
                annotations.entry(loc)
                           .or_insert(vec![])
                           .push(Annotation::ExitScope(scope_id));
            }
        }
    }
    return annotations;
}

pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              src: MirSource,
                              mir: &Mir<'tcx>,
                              w: &mut Write,
                              auxiliary: Option<&ScopeAuxiliaryVec>)
                              -> io::Result<()> {
    let annotations = scope_entry_exit_annotations(auxiliary);
    write_mir_intro(tcx, src, mir, w)?;
    for block in mir.all_basic_blocks() {
        write_basic_block(tcx, block, mir, w, &annotations)?;
    }

    // construct a scope tree and write it out
    let mut scope_tree: FnvHashMap<Option<ScopeId>, Vec<ScopeId>> = FnvHashMap();
    for (index, scope_data) in mir.scopes.iter().enumerate() {
        scope_tree.entry(scope_data.parent_scope)
                  .or_insert(vec![])
                  .push(ScopeId::new(index));
    }

    writeln!(w, "{}scope tree:", INDENT)?;
    write_scope_tree(tcx, mir, auxiliary, &scope_tree, w, None, 1, false)?;
    writeln!(w, "")?;

    writeln!(w, "}}")?;
    Ok(())
}

/// Write out a human-readable textual representation for the given basic block.
fn write_basic_block(tcx: TyCtxt,
                     block: BasicBlock,
                     mir: &Mir,
                     w: &mut Write,
                     annotations: &FnvHashMap<Location, Vec<Annotation>>)
                     -> io::Result<()> {
    let data = mir.basic_block_data(block);

    // Basic block label at the top.
    writeln!(w, "{}{:?}: {{", INDENT, block)?;

    // List of statements in the middle.
    let mut current_location = Location { block: block, statement_index: 0 };
    for statement in &data.statements {
        if let Some(ref annotations) = annotations.get(&current_location) {
            for annotation in annotations.iter() {
                match *annotation {
                    Annotation::EnterScope(id) =>
                        writeln!(w, "{0}{0}// Enter Scope({1})",
                                 INDENT, id.index())?,
                    Annotation::ExitScope(id) =>
                        writeln!(w, "{0}{0}// Exit Scope({1})",
                                 INDENT, id.index())?,
                }
            }
        }

        let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
        writeln!(w, "{0:1$} // {2}",
                 indented_mir,
                 ALIGN,
                 comment(tcx, statement.scope, statement.span))?;

        current_location.statement_index += 1;
    }

    // Terminator at the bottom.
    let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
    writeln!(w, "{0:1$} // {2}",
             indented_terminator,
             ALIGN,
             comment(tcx, data.terminator().scope, data.terminator().span))?;

    writeln!(w, "{}}}\n", INDENT)
}

fn comment(tcx: TyCtxt, scope: ScopeId, span: Span) -> String {
    format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
}

fn write_scope_tree(tcx: TyCtxt,
                    mir: &Mir,
                    auxiliary: Option<&ScopeAuxiliaryVec>,
                    scope_tree: &FnvHashMap<Option<ScopeId>, Vec<ScopeId>>,
                    w: &mut Write,
                    parent: Option<ScopeId>,
                    depth: usize,
                    same_line: bool)
                    -> io::Result<()> {
    let indent = if same_line {
        0
    } else {
        depth * INDENT.len()
    };

    let children = match scope_tree.get(&parent) {
        Some(childs) => childs,
        None => return Ok(()),
    };

    for (index, &child) in children.iter().enumerate() {
        if index == 0 && same_line {
            // We know we're going to output a scope, so prefix it with a space to separate it from
            // the previous scopes on this line
            write!(w, " ")?;
        }

        let data = &mir.scopes[child];
        assert_eq!(data.parent_scope, parent);
        write!(w, "{0:1$}{2}", "", indent, child.index())?;

        let indent = indent + INDENT.len();

        if let Some(auxiliary) = auxiliary {
            let extent = auxiliary[child].extent;
            let data = tcx.region_maps.code_extent_data(extent);
            writeln!(w, "{0:1$}Extent: {2:?}", "", indent, data)?;
        }

        let child_count = scope_tree.get(&Some(child)).map(Vec::len).unwrap_or(0);
        if child_count < 2 {
            // Skip the braces when there's no or only a single subscope
            write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
                             Some(child), depth, true)?;
        } else {
            // 2 or more child scopes? Put them in braces and on new lines.
            writeln!(w, " {{")?;
            write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
                             Some(child), depth + 1, false)?;

            write!(w, "\n{0:1$}}}", "", depth * INDENT.len())?;
        }

        if !same_line && index + 1 < children.len() {
            writeln!(w, "")?;
        }
    }

    Ok(())
}

/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
/// local variables (both user-defined bindings and compiler temporaries).
fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             src: MirSource,
                             mir: &Mir,
                             w: &mut Write)
                             -> io::Result<()> {
    write_mir_sig(tcx, src, mir, w)?;
    writeln!(w, " {{")?;
    write_mir_decls(tcx, mir, w)
}

fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
                 -> io::Result<()>
{
    match src {
        MirSource::Fn(_) => write!(w, "fn")?,
        MirSource::Const(_) => write!(w, "const")?,
        MirSource::Static(_, hir::MutImmutable) => write!(w, "static")?,
        MirSource::Static(_, hir::MutMutable) => write!(w, "static mut")?,
        MirSource::Promoted(_, i) => write!(w, "promoted{} in", i)?
    }

    write!(w, " {}", tcx.node_path_str(src.item_id()))?;

    if let MirSource::Fn(_) = src {
        write!(w, "(")?;

        // fn argument types.
        for (i, arg) in mir.arg_decls.iter().enumerate() {
            if i > 0 {
                write!(w, ", ")?;
            }
            write!(w, "{:?}: {}", Lvalue::Arg(i as u32), arg.ty)?;
        }

        write!(w, ") -> ")?;

        // fn return type.
        match mir.return_ty {
            ty::FnOutput::FnConverging(ty) => write!(w, "{}", ty),
            ty::FnOutput::FnDiverging => write!(w, "!"),
        }
    } else {
        assert!(mir.arg_decls.is_empty());
        write!(w, ": {} =", mir.return_ty.unwrap())
    }
}

fn write_mir_decls(tcx: TyCtxt, mir: &Mir, w: &mut Write)
                   -> io::Result<()>
{
    // User variable types (including the user's name in a comment).
    for (i, var) in mir.var_decls.iter().enumerate() {
        let mut_str = if var.mutability == Mutability::Mut {
            "mut "
        } else {
            ""
        };

        let indented_var = format!("{}let {}{:?}: {};",
                                   INDENT,
                                   mut_str,
                                   Lvalue::Var(i as u32),
                                   var.ty);
        writeln!(w, "{0:1$} // \"{2}\" in {3}",
                 indented_var,
                 ALIGN,
                 var.name,
                 comment(tcx, var.scope, var.span))?;
    }

    // Compiler-introduced temporary types.
    for (i, temp) in mir.temp_decls.iter().enumerate() {
        writeln!(w, "{}let mut {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty)?;
    }

    // Wrote any declaration? Add an empty line before the first block is printed.
    if !mir.var_decls.is_empty() || !mir.temp_decls.is_empty() {
        writeln!(w, "")?;
    }

    Ok(())
}
<|endoftext|>


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

//! System bindings for the wasm/web platform
//!
//! This module contains the facade (aka platform-specific) implementations of
//! OS level functionality for wasm. Note that this wasm is *not* the emscripten
//! wasm, so we have no runtime here.
//!
//! This is all super highly experimental and not actually intended for
//! wide/production use yet, it's still all in the experimental category. This
//! will likely change over time.
//!
//! Currently all functions here are basically stubs that immediately return
//! errors. The hope is that with a portability lint we can turn actually just
//! remove all this and just omit parts of the standard library if we're
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!

use io;
use os::raw::c_char;

// Right now the wasm backend doesn't even have the ability to print to the
// console by default. Wasm can't import anything from JS! (you have to
// explicitly provide it).
//
// Sometimes that's a real bummer, though, so this flag can be set to `true` to
// enable calling various shims defined in `src/etc/wasm32-shim.js` which should
// help receive debug output and see what's going on. In general this flag
// currently controls "will we call out to our own defined shims in node.js",
// and this flag should always be `false` for release builds.
const DEBUG: bool = false;

pub mod args;
pub mod backtrace;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod fs;
pub mod memchr;
pub mod mutex;
pub mod net;
pub mod os;
pub mod os_str;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rwlock;
pub mod stack_overflow;
pub mod thread;
pub mod thread_local;
pub mod time;
pub mod stdio;

#[cfg(not(test))]
pub fn init() {
}

pub fn unsupported<T>() -> io::Result<T> {
    Err(unsupported_err())
}

pub fn unsupported_err() -> io::Error {
    io::Error::new(io::ErrorKind::Other,
                   "operation not supported on wasm yet")
}

pub fn decode_error_kind(_code: i32) -> io::ErrorKind {
    io::ErrorKind::Other
}

// This enum is used as the storage for a bunch of types which can't actually
// exist.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Void {}

pub unsafe fn strlen(mut s: *const c_char) -> usize {
    let mut n = 0;
    while *s != 0 {
        n += 1;
        s = s.offset(1);
    }
    return n
}

pub unsafe fn abort_internal() -> ! {
    ::intrinsics::abort();
}

// We don't have randomness yet, but I totally used a random number generator to
// generate these numbers.
//
// More seriously though this is just for DOS protection in hash maps. It's ok
// if we don't do that on wasm just yet.
pub fn hashmap_random_keys() -> (u64, u64) {
    (1, 2)
}
<commit_msg>Make wasm obey backtrace feature, like other targets<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! System bindings for the wasm/web platform
//!
//! This module contains the facade (aka platform-specific) implementations of
//! OS level functionality for wasm. Note that this wasm is *not* the emscripten
//! wasm, so we have no runtime here.
//!
//! This is all super highly experimental and not actually intended for
//! wide/production use yet, it's still all in the experimental category. This
//! will likely change over time.
//!
//! Currently all functions here are basically stubs that immediately return
//! errors. The hope is that with a portability lint we can turn actually just
//! remove all this and just omit parts of the standard library if we're
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!

use io;
use os::raw::c_char;

// Right now the wasm backend doesn't even have the ability to print to the
// console by default. Wasm can't import anything from JS! (you have to
// explicitly provide it).
//
// Sometimes that's a real bummer, though, so this flag can be set to `true` to
// enable calling various shims defined in `src/etc/wasm32-shim.js` which should
// help receive debug output and see what's going on. In general this flag
// currently controls "will we call out to our own defined shims in node.js",
// and this flag should always be `false` for release builds.
const DEBUG: bool = false;

pub mod args;
#[cfg(feature = "backtrace")]
pub mod backtrace;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod fs;
pub mod memchr;
pub mod mutex;
pub mod net;
pub mod os;
pub mod os_str;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rwlock;
pub mod stack_overflow;
pub mod thread;
pub mod thread_local;
pub mod time;
pub mod stdio;

#[cfg(not(test))]
pub fn init() {
}

pub fn unsupported<T>() -> io::Result<T> {
    Err(unsupported_err())
}

pub fn unsupported_err() -> io::Error {
    io::Error::new(io::ErrorKind::Other,
                   "operation not supported on wasm yet")
}

pub fn decode_error_kind(_code: i32) -> io::ErrorKind {
    io::ErrorKind::Other
}

// This enum is used as the storage for a bunch of types which can't actually
// exist.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Void {}

pub unsafe fn strlen(mut s: *const c_char) -> usize {
    let mut n = 0;
    while *s != 0 {
        n += 1;
        s = s.offset(1);
    }
    return n
}

pub unsafe fn abort_internal() -> ! {
    ::intrinsics::abort();
}

// We don't have randomness yet, but I totally used a random number generator to
// generate these numbers.
//
// More seriously though this is just for DOS protection in hash maps. It's ok
// if we don't do that on wasm just yet.
pub fn hashmap_random_keys() -> (u64, u64) {
    (1, 2)
}
<|endoftext|>


<commit_before><commit_msg>(doc) Added example of bidirectional middleware.<commit_after><|endoftext|>


<commit_before><commit_msg>https://pt.stackoverflow.com/q/486353/101<commit_after>enum Optional<T> {
    None,
    Some(T)
}

resultado : Optional<i32> = TentaObterResultado();
match resultado {
    Some(valor) => println!("O valor é {}", valor),
    None => println!("Não deu certo")
}

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

//https://pt.stackoverflow.com/q/486353/101
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::error::Error;

use dbus;
use dbus::MessageItem;
use dbus::arg::{ArgType, Iter, IterAppend};
use dbus::tree::{MethodErr, MTFn, PropInfo};

use engine::{EngineError, ErrorEnum};

use super::types::{DbusErrorEnum, TData};

pub const STRATIS_BASE_PATH: &'static str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &'static str = "org.storage.stratis1";

/// Convert a tuple as option to an Option type
pub fn tuple_to_option<T>(value: (bool, T)) -> Option<T> {
    if value.0 { Some(value.1) } else { None }
}

/// Get the next argument off the bus
pub fn get_next_arg<'a, T>(iter: &mut Iter<'a>, loc: u16) -> Result<T, MethodErr>
    where T: dbus::arg::Get<'a> + dbus::arg::Arg
{
    if iter.arg_type() == ArgType::Invalid {
        return Err(MethodErr::no_arg());
    };
    let value: T = iter.read::<T>()
        .map_err(|_| MethodErr::invalid_arg(&loc))?;
    Ok(value)
}

/// Translates an engine error to a dbus error.
pub fn engine_to_dbus_err(err: &EngineError) -> (DbusErrorEnum, String) {
    let error = match *err {
        EngineError::Engine(ref e, _) => {
            match *e {
                ErrorEnum::Error => DbusErrorEnum::ERROR,
                ErrorEnum::AlreadyExists => DbusErrorEnum::ALREADY_EXISTS,
                ErrorEnum::Busy => DbusErrorEnum::BUSY,
                ErrorEnum::Invalid => DbusErrorEnum::ERROR,
                ErrorEnum::NotFound => DbusErrorEnum::NOTFOUND,
            }
        }
        EngineError::Io(_) => DbusErrorEnum::IO_ERROR,
        EngineError::Nix(_) => DbusErrorEnum::NIX_ERROR,
        EngineError::Uuid(_) => DbusErrorEnum::INTERNAL_ERROR,
        EngineError::Utf8(_) => DbusErrorEnum::INTERNAL_ERROR,
        EngineError::Serde(_) => DbusErrorEnum::INTERNAL_ERROR,
        EngineError::DM(_) => DbusErrorEnum::INTERNAL_ERROR,
    };
    (error, err.description().to_owned())
}

/// Convenience function to convert a return code and a string to
/// appropriately typed MessageItems.
pub fn code_to_message_items(code: DbusErrorEnum, mes: String) -> (MessageItem, MessageItem) {
    (MessageItem::UInt16(code.into()), MessageItem::Str(mes))
}

/// Convenience function to directly yield MessageItems for OK code and message.
pub fn ok_message_items() -> (MessageItem, MessageItem) {
    let code = DbusErrorEnum::OK;
    code_to_message_items(code, code.get_error_string().into())
}

pub fn default_object_path<'a>() -> dbus::Path<'a> {
    dbus::Path::new("/").expect("'/' is guaranteed to be a valid Path")
}

/// Get the UUID for an object path.
pub fn get_uuid(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data =
        path.get_data()
            .as_ref()
            .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(MessageItem::Str(format!("{}", data.uuid.simple())));
    Ok(())
}

/// Get the parent object path for an object path.
pub fn get_parent(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data =
        path.get_data()
            .as_ref()
            .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(MessageItem::ObjectPath(data.parent.clone()));
    Ok(())
}
<commit_msg>Allow same arms in match<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::error::Error;

use dbus;
use dbus::MessageItem;
use dbus::arg::{ArgType, Iter, IterAppend};
use dbus::tree::{MethodErr, MTFn, PropInfo};

use engine::{EngineError, ErrorEnum};

use super::types::{DbusErrorEnum, TData};

pub const STRATIS_BASE_PATH: &'static str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &'static str = "org.storage.stratis1";

/// Convert a tuple as option to an Option type
pub fn tuple_to_option<T>(value: (bool, T)) -> Option<T> {
    if value.0 { Some(value.1) } else { None }
}

/// Get the next argument off the bus
pub fn get_next_arg<'a, T>(iter: &mut Iter<'a>, loc: u16) -> Result<T, MethodErr>
    where T: dbus::arg::Get<'a> + dbus::arg::Arg
{
    if iter.arg_type() == ArgType::Invalid {
        return Err(MethodErr::no_arg());
    };
    let value: T = iter.read::<T>()
        .map_err(|_| MethodErr::invalid_arg(&loc))?;
    Ok(value)
}

/// Translates an engine error to a dbus error.
pub fn engine_to_dbus_err(err: &EngineError) -> (DbusErrorEnum, String) {
    #![allow(match_same_arms)]
    let error = match *err {
        EngineError::Engine(ref e, _) => {
            match *e {
                ErrorEnum::Error => DbusErrorEnum::ERROR,
                ErrorEnum::AlreadyExists => DbusErrorEnum::ALREADY_EXISTS,
                ErrorEnum::Busy => DbusErrorEnum::BUSY,
                ErrorEnum::Invalid => DbusErrorEnum::ERROR,
                ErrorEnum::NotFound => DbusErrorEnum::NOTFOUND,
            }
        }
        EngineError::Io(_) => DbusErrorEnum::IO_ERROR,
        EngineError::Nix(_) => DbusErrorEnum::NIX_ERROR,
        EngineError::Uuid(_) => DbusErrorEnum::INTERNAL_ERROR,
        EngineError::Utf8(_) => DbusErrorEnum::INTERNAL_ERROR,
        EngineError::Serde(_) => DbusErrorEnum::INTERNAL_ERROR,
        EngineError::DM(_) => DbusErrorEnum::INTERNAL_ERROR,
    };
    (error, err.description().to_owned())
}

/// Convenience function to convert a return code and a string to
/// appropriately typed MessageItems.
pub fn code_to_message_items(code: DbusErrorEnum, mes: String) -> (MessageItem, MessageItem) {
    (MessageItem::UInt16(code.into()), MessageItem::Str(mes))
}

/// Convenience function to directly yield MessageItems for OK code and message.
pub fn ok_message_items() -> (MessageItem, MessageItem) {
    let code = DbusErrorEnum::OK;
    code_to_message_items(code, code.get_error_string().into())
}

pub fn default_object_path<'a>() -> dbus::Path<'a> {
    dbus::Path::new("/").expect("'/' is guaranteed to be a valid Path")
}

/// Get the UUID for an object path.
pub fn get_uuid(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data =
        path.get_data()
            .as_ref()
            .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(MessageItem::Str(format!("{}", data.uuid.simple())));
    Ok(())
}

/// Get the parent object path for an object path.
pub fn get_parent(i: &mut IterAppend, p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    let object_path = p.path.get_name();
    let path = p.tree
        .get(object_path)
        .expect("implicit argument must be in tree");

    let data =
        path.get_data()
            .as_ref()
            .ok_or_else(|| MethodErr::failed(&format!("no data for object path {}", object_path)))?;

    i.append(MessageItem::ObjectPath(data.parent.clone()));
    Ok(())
}
<|endoftext|>