<commit_before>use rustc::lint::*;
use rustc::middle::ty::TypeVariants;
use rustc::middle::ty::fast_reject::simplify_type;
use rustc::middle::ty;
use rustc_front::hir::*;
use syntax::ast::{Attribute, MetaItemKind};
use syntax::codemap::Span;
use utils::{CLONE_TRAIT_PATH, HASH_PATH};
use utils::{match_path, span_lint_and_then};

/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq`
/// explicitly.
///
/// **Why is this bad?** The implementation of these traits must agree (for example for use with
/// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation  with
/// an explicitely defined `PartialEq`. In particular, the following must hold for any type:
///
/// ```rust
/// k1 == k2 -> hash(k1) == hash(k2)
/// ```
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Hash)]
/// struct Foo;
///
/// impl PartialEq for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub DERIVE_HASH_NOT_EQ,
    Warn,
    "deriving `Hash` but implementing `PartialEq` explicitly"
}

/// **What it does:** This lint warns about explicit `Clone` implementation for `Copy` types.
///
/// **Why is this bad?** To avoid surprising behaviour, these traits should agree and the behaviour
/// of `Copy` cannot be overridden. In almost all situations a `Copy` type should have a `Clone`
/// implementation that does nothing more than copy the object, which is what
/// `#[derive(Copy, Clone)]` gets you.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Copy)]
/// struct Foo;
///
/// impl Clone for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub EXPL_IMPL_CLONE_ON_COPY,
    Warn,
    "implementing `Clone` explicitly on `Copy` types"
}

pub struct Derive;

impl LintPass for Derive {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_NOT_EQ)
    }
}

impl LateLintPass for Derive {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow();

        if_let_chain! {[
            let ItemImpl(_, _, ref ast_generics, Some(ref trait_ref), ref ast_ty, _) = item.node,
            let Some(&ty) = ast_ty_to_ty_cache.get(&ast_ty.id)
        ], {
            if item.attrs.iter().any(is_automatically_derived) {
                check_hash_peq(cx, item.span, trait_ref, ty);
            }
            else if !ast_generics.is_lt_parameterized() {
                check_copy_clone(cx, item, trait_ref, ty);
            }
        }}
    }
}

/// Implementation of the `DERIVE_HASH_NOT_EQ` lint.
fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty) {
    // If `item` is an automatically derived `Hash` implementation
    if_let_chain! {[
        match_path(&trait_ref.path, &HASH_PATH),
        let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
    ], {
        let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id);

        cx.tcx.populate_implementations_for_trait_if_necessary(peq_trait_def.trait_ref.def_id);
        let peq_impls = peq_trait_def.borrow_impl_lists(cx.tcx).1;

        // Look for the PartialEq implementations for `ty`
        if_let_chain! {[
            let Some(simpl_ty) = simplify_type(cx.tcx, ty, false),
            let Some(impl_ids) = peq_impls.get(&simpl_ty)
        ], {
            for &impl_id in impl_ids {
                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");

                // Only care about `impl PartialEq<Foo> for Foo`
                if trait_ref.input_types()[0] == ty &&
                  !cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived) {
                    span_lint_and_then(
                        cx, DERIVE_HASH_NOT_EQ, span,
                        "you are deriving `Hash` but have implemented `PartialEq` explicitly",
                        |db| {
                        if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) {
                            db.span_note(
                                cx.tcx.map.span(node_id),
                                "`PartialEq` implemented here"
                            );
                        }
                    });
                }
            }
        }}
    }}
}

/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>,
                              item: &Item,
                              trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
    if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) {
        let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id);

        if ty.moves_by_default(&parameter_environment, item.span) {
            return; // ty is not Copy
        }

        // Some types are not Clone by default but could be cloned `by hand` if necessary
        match ty.sty {
            TypeVariants::TyEnum(def, substs) | TypeVariants::TyStruct(def, substs) => {
                for variant in &def.variants {
                    for field in &variant.fields {
                        match field.ty(cx.tcx, substs).sty {
                            TypeVariants::TyArray(_, size) if size > 32 => {
                                return;
                            }
                            TypeVariants::TyBareFn(..) => {
                                return;
                            }
                            TypeVariants::TyTuple(ref tys) if tys.len() > 12 => {
                                return;
                            }
                            _ => (),
                        }
                    }
                }
            }
            _ => (),
        }

        span_lint_and_then(cx,
                           DERIVE_HASH_NOT_EQ,
                           item.span,
                           "you are implementing `Clone` explicitly on a `Copy` type",
                           |db| {
                               db.span_note(item.span, "consider deriving `Clone` or removing `Copy`");
                           });
    }
}

/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d implementations have.
fn is_automatically_derived(attr: &Attribute) -> bool {
    if let MetaItemKind::Word(ref word) = attr.node.value.node {
        word == &"automatically_derived"
    } else {
        false
    }
}
<commit_msg>Make derive lint handle generics correctly<commit_after>use rustc::lint::*;
use rustc::middle::subst::Subst;
use rustc::middle::ty::TypeVariants;
use rustc::middle::ty::fast_reject::simplify_type;
use rustc::middle::ty;
use rustc_front::hir::*;
use syntax::ast::{Attribute, MetaItemKind};
use syntax::codemap::Span;
use utils::{CLONE_TRAIT_PATH, HASH_PATH};
use utils::{match_path, span_lint_and_then};

/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq`
/// explicitly.
///
/// **Why is this bad?** The implementation of these traits must agree (for example for use with
/// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation  with
/// an explicitely defined `PartialEq`. In particular, the following must hold for any type:
///
/// ```rust
/// k1 == k2 -> hash(k1) == hash(k2)
/// ```
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Hash)]
/// struct Foo;
///
/// impl PartialEq for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub DERIVE_HASH_NOT_EQ,
    Warn,
    "deriving `Hash` but implementing `PartialEq` explicitly"
}

/// **What it does:** This lint warns about explicit `Clone` implementation for `Copy` types.
///
/// **Why is this bad?** To avoid surprising behaviour, these traits should agree and the behaviour
/// of `Copy` cannot be overridden. In almost all situations a `Copy` type should have a `Clone`
/// implementation that does nothing more than copy the object, which is what
/// `#[derive(Copy, Clone)]` gets you.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Copy)]
/// struct Foo;
///
/// impl Clone for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub EXPL_IMPL_CLONE_ON_COPY,
    Warn,
    "implementing `Clone` explicitly on `Copy` types"
}

pub struct Derive;

impl LintPass for Derive {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_NOT_EQ)
    }
}

impl LateLintPass for Derive {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {

        if_let_chain! {[
            let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node
        ], {

            let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty;
            if item.attrs.iter().any(is_automatically_derived) {
                check_hash_peq(cx, item.span, trait_ref, ty);
            }
            else {
                check_copy_clone(cx, item, trait_ref, ty);
            }
        }}
    }
}

/// Implementation of the `DERIVE_HASH_NOT_EQ` lint.
fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty) {
    // If `item` is an automatically derived `Hash` implementation
    if_let_chain! {[
        match_path(&trait_ref.path, &HASH_PATH),
        let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
    ], {
        let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id);

        cx.tcx.populate_implementations_for_trait_if_necessary(peq_trait_def.trait_ref.def_id);
        let peq_impls = peq_trait_def.borrow_impl_lists(cx.tcx).1;

        // Look for the PartialEq implementations for `ty`
        if_let_chain! {[
            let Some(simpl_ty) = simplify_type(cx.tcx, ty, false),
            let Some(impl_ids) = peq_impls.get(&simpl_ty)
        ], {
            for &impl_id in impl_ids {
                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");

                // Only care about `impl PartialEq<Foo> for Foo`
                if trait_ref.input_types()[0] == ty &&
                  !cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived) {
                    span_lint_and_then(
                        cx, DERIVE_HASH_NOT_EQ, span,
                        "you are deriving `Hash` but have implemented `PartialEq` explicitly",
                        |db| {
                        if let Some(node_id) = cx.tcx.map.as_local_node_id(impl_id) {
                            db.span_note(
                                cx.tcx.map.span(node_id),
                                "`PartialEq` implemented here"
                            );
                        }
                    });
                }
            }
        }}
    }}
}

/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>,
                              item: &Item,
                              trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
    if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) {
        let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
        let subst_ty = ty.subst(cx.tcx, &parameter_environment.free_substs);

        if subst_ty.moves_by_default(&parameter_environment, item.span) {
            return; // ty is not Copy
        }

        // Some types are not Clone by default but could be cloned `by hand` if necessary
        match ty.sty {
            TypeVariants::TyEnum(def, substs) | TypeVariants::TyStruct(def, substs) => {
                for variant in &def.variants {
                    for field in &variant.fields {
                        match field.ty(cx.tcx, substs).sty {
                            TypeVariants::TyArray(_, size) if size > 32 => {
                                return;
                            }
                            TypeVariants::TyBareFn(..) => {
                                return;
                            }
                            TypeVariants::TyTuple(ref tys) if tys.len() > 12 => {
                                return;
                            }
                            _ => (),
                        }
                    }
                }
            }
            _ => (),
        }

        span_lint_and_then(cx,
                           DERIVE_HASH_NOT_EQ,
                           item.span,
                           "you are implementing `Clone` explicitly on a `Copy` type",
                           |db| {
                               db.span_note(item.span, "consider deriving `Clone` or removing `Copy`");
                           });
    }
}

/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d implementations have.
fn is_automatically_derived(attr: &Attribute) -> bool {
    if let MetaItemKind::Word(ref word) = attr.node.value.node {
        word == &"automatically_derived"
    } else {
        false
    }
}
<|endoftext|>


<commit_before>//! KISS-UI top-level dialogs (windows)

use widget_prelude::*;

use ::iup_sys;

use std::ffi::CString;

/// A top-level dialog that can create a new native window when shown,
/// and can contain a single widget (which can be a container for many widgets).
pub struct Dialog(BaseWidget);

impl Dialog {
    /// Create a new dialog with a single child.
    ///
    /// To create a dialog containing multiple widgets, use a struct from the `container` module.
    ///
    /// ##Note
    /// This does **not** make the dialog appear on screen. `.show()` must be called after the
    /// dialog has been configured.
    ///
    /// ##Panics
    /// If called outside a valid KISS-UI context.
    pub fn new<W>(contents: W) -> Dialog where W: Into<BaseWidget> {
        assert_kiss_running!();

        unsafe {
            let ptr = iup_sys::IupDialog(contents.into().ptr());
            Dialog(BaseWidget::from_ptr(ptr))
        }
    }

    /// Set the title of this dialog, which will appear in the title bar of the native window.
    pub fn set_title(mut self, title: &str) -> Self {
        self.set_str_attribute(::attrs::TITLE, title);
        self
    }

    /// Set the size of this dialog in pixels.
    pub fn set_size_pixels(mut self, width: u32, height: u32) -> Self {
        let rastersize = format!("{}x{}", width, height);
        self.set_str_attribute(::attrs::RASTERSIZE, rastersize);
        self
    }

    /// Get a child of this dialog named by `name`.
    ///
    /// Returns `None` if the child was not found.
    pub fn get_child(&self, name: &str) -> Option<BaseWidget> {
        let name = CString::new(name).unwrap();

        unsafe {
            let child_ptr = iup_sys::IupGetDialogChild(self.ptr(), name.as_ptr());
            BaseWidget::from_ptr_opt(child_ptr)
        }
    }

    /// Destroy this dialog, deallocating it and all attached children.
    pub fn destroy(self) {
        self.0.destroy()
    }
}

impl_base_widget! { Dialog, Dialog, "dialog" }

impl_on_show! { Dialog }

pub fn popup_message_dialog<T: Into<Vec<u8>>, M: Into<Vec<u8>>>(title: T, message: M) {
    assert_kiss_running!();

    let title = CString::new(title).unwrap();
    let message = CString::new(message).unwrap();

    unsafe {
        iup_sys::IupMessage(title.as_ptr(), message.as_ptr());
    }
}
<commit_msg>Add `Dialog::empty()`<commit_after>//! KISS-UI top-level dialogs (windows)

use widget_prelude::*;

use ::iup_sys;

use std::ffi::CString;
use std::ptr;

/// A top-level dialog that can create a new native window when shown,
/// and can contain a single widget (which can be a container for many widgets).
pub struct Dialog(BaseWidget);

impl Dialog {
    /// Create a new dialog with a single child.
    ///
    /// To create a dialog containing multiple widgets, use a struct from the `container` module.
    ///
    /// ##Note
    /// This does **not** make the dialog appear on screen. `.show()` must be called after the
    /// dialog has been configured.
    ///
    /// ##Panics
    /// If called outside a valid KISS-UI context.
    pub fn new<W>(contents: W) -> Dialog where W: Into<BaseWidget> {
        assert_kiss_running!();

        unsafe {
            let ptr = iup_sys::IupDialog(contents.into().ptr());
            Dialog(BaseWidget::from_ptr(ptr))
        }
    }

    /// Create a new dialog with no children.
    ///
    /// ##Panics
    /// If called outside a valid KISS-UI context.
    pub fn empty() -> Dialog {
        assert_kiss_running!();

        unsafe {
            let ptr = iup_sys::IupDialog(ptr::null_mut());
            Dialog(BaseWidget::from_ptr(ptr))
        }
    }

    /// Set the title of this dialog, which will appear in the title bar of the native window.
    pub fn set_title(mut self, title: &str) -> Self {
        self.set_str_attribute(::attrs::TITLE, title);
        self
    }

    /// Set the size of this dialog in pixels.
    pub fn set_size_pixels(mut self, width: u32, height: u32) -> Self {
        let rastersize = format!("{}x{}", width, height);
        self.set_str_attribute(::attrs::RASTERSIZE, rastersize);
        self
    }

    /// Get a child of this dialog named by `name`.
    ///
    /// Returns `None` if the child was not found.
    pub fn get_child(&self, name: &str) -> Option<BaseWidget> {
        let name = CString::new(name).unwrap();

        unsafe {
            let child_ptr = iup_sys::IupGetDialogChild(self.ptr(), name.as_ptr());
            BaseWidget::from_ptr_opt(child_ptr)
        }
    }

    /// Destroy this dialog, deallocating it and all attached children.
    pub fn destroy(self) {
        self.0.destroy()
    }
}

impl_base_widget! { Dialog, Dialog, "dialog" }

impl_on_show! { Dialog }

pub fn popup_message_dialog<T: Into<Vec<u8>>, M: Into<Vec<u8>>>(title: T, message: M) {
    assert_kiss_running!();

    let title = CString::new(title).unwrap();
    let message = CString::new(message).unwrap();

    unsafe {
        iup_sys::IupMessage(title.as_ptr(), message.as_ptr());
    }
}
<|endoftext|>


<commit_before>// Code courtesy of spawnedartifact

extern crate clap;

pub fn pp_opcode(first_byte: u8, second_byte: u8, third_byte: u8, pc: u16) -> (String, u8) {
    let x = (first_byte >> 6) & 0b011;
    let y = (first_byte >> 3) & 0b111;
    let z = first_byte & 0b111;
    let p = (first_byte >> 4) & 0b011;
    let q = (first_byte >> 3) & 0b001;

    let mut instruction_size = 1;

    // This garbage is here because two closures can't borrow same var.
    let mut prefix_used = 0;
    let mut used_a8 = 0;
    let mut used_d8 = 0;
    let mut used_r8 = 0;
    let mut used_a16 = 0;
    let mut used_d16 = 0;

    // This moved here to create a scope for closures to allow accessing
    // "used_*" vars later.
    let mnemonic = {
        let mut prefix = || prefix_used += 1;

        // Argument accessors. Will brake if used twice in a
        // row. Because of this, there is almost no point in using
        // them.
        let mut a8 = || {
            used_a8 += 1; //instruction_size += 1;
            format!("${:02X}", second_byte)
        };

        let mut d8 = || {
            used_d8 += 1; //instruction_size += 1;
            format!("${:02X}", second_byte)
        };

        // Because jump is relative to post pc increment we need to
        // know instruction size here.
        let mut r8 = |insize| {
            used_r8 += 1; //instruction_size += 1;
            // jump is relative to post pc increment!
            format!("Addr_{:04X}",
                    (((pc + insize) as i32) + ((second_byte as i8) as i32)) as u16)
        };

        let mut a16 = || {
            used_a16 += 2; //instruction_size += 2;
            format!("${:04X}",
                    (((third_byte as u16) << 8) | (second_byte as u16)))
        };

        let mut d16 = || {
            used_d16 += 2; //instruction_size += 2;
            format!("${:04X}",
                    (((third_byte as u16) << 8) | (second_byte as u16)))
        };

        // Converting indexes encoded in commands to symbolic arguments
        fn idx_r(i: u8) -> &'static str {
            ["B", "C", "D", "E", "H", "L", "(HL)", "A"][i as usize]
        };

        fn idx_rp(i: u8) -> &'static str {
            ["BC", "DE", "HL", "SP"][i as usize]
        };

        fn idx_rp2(i: u8) -> &'static str {
            ["BC", "DE", "HL", "AF"][i as usize]
        };

        fn idx_cc(i: u8) -> &'static str {
            ["NZ", "Z", "NC", "C"][i as usize]
        };

        fn idx_alu(i: u8) -> &'static str {
            ["ADD A,", "ADC A,", "SUB", "SBC A,", "AND", "XOR", "OR", "CP"][i as usize]
        };

        fn idx_rot(i: u8) -> &'static str {
            ["RLC", "RRC", "RL", "RR", "SLA", "SRA", "SWAP", "SRL"][i as usize]
        };

        fn illegal_op(byte: u8) -> String {
            format!(".DB ${:02X}", byte)
        }

        // The value of mnemonic =
        match x {
            0 => {
                match z {
                    0 => {
                        match y {
                            0 => "NOP".to_string(),
                            1 => format!("LD ({}),SP", a16()),
                            2 => format!("STOP {}", d8()),
                            3 => format!("JR {}", r8(2)),
                            4 => format!("JR NZ,{}", r8(2)),
                            5 => format!("JR Z,{}", r8(2)),
                            6 => format!("JR NC,{}", r8(2)),
                            7 => format!("JR C,{}", r8(2)),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    1 => {
                        match q {
                            0 => format!("LD {},{}", idx_rp(p), d16()),
                            1 => format!("ADD HL,{}", idx_rp(p)),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    2 => {
                        match q {
                            0 => {
                                match p {
                                    0 => "LD (BC),A".to_string(),
                                    1 => "LD (DE),A".to_string(),
                                    2 => "LD (HL+),A".to_string(),
                                    3 => "LD (HL-),A".to_string(),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            1 => {
                                match p {
                                    0 => "LD A,(BC)".to_string(),
                                    1 => "LD A,(DE)".to_string(),
                                    2 => "LD A,(HL+)".to_string(),
                                    3 => "LD A,(HL-)".to_string(),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    3 => {
                        match q {
                            0 => format!("INC {}", idx_rp(p)),
                            1 => format!("DEC {}", idx_rp(p)),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    4 => format!("INC {}", idx_r(y)),
                    5 => format!("DEC {}", idx_r(y)),
                    6 => format!("LD {},{}", idx_r(y), d8()),
                    7 => {
                        match y {
                            0 => "RLCA".to_string(),
                            1 => "RRCA".to_string(),
                            2 => "RLA".to_string(),
                            3 => "RRA".to_string(),
                            4 => "DAA".to_string(),
                            5 => "CPL".to_string(),
                            6 => "SCF".to_string(),
                            7 => "CCF".to_string(),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    _ => unreachable!("Impossible opcode"),
                }
            }
            1 => {
                match (z, y) {
                    (6, 6) => "HALT".to_string(),
                    _ => format!("LD {},{}", idx_r(y), idx_r(z)),
                }
            }
            // FIXME cheating here a bit with idx_alu value
            2 => format!("{} {}", idx_alu(y), idx_r(z)),
            3 => {
                match z {
                    0 => {
                        match y {
                            0...3 => format!("RET {}", idx_cc(y)),
                            // 4 => format!("LDH ({}),A", a8()),
                            4 => format!("LD ($FF00+{}),A", a8()),
                            5 => format!("ADD SP,{}", r8(0)), // FIXME
                            // 6 => format!("LDH A,({})", a8()),
                            6 => format!("LD A,($FF00+{})", a8()),
                            7 => format!("LD HL,(sp + {})", r8(0)), // FIXME
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    1 => {
                        match q {
                            0 => format!("POP {}", idx_rp2(p)),
                            1 => {
                                match p {
                                    0 => "RET".to_string(),
                                    1 => "RETI".to_string(),
                                    2 => "JP (HL)".to_string(),
                                    3 => "LD SP,HL".to_string(),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    2 => {
                        match y {
                            0...3 => format!("JP {},{}", idx_cc(y), a16()),
                            4 => "LD ($FF00+C),A".to_string(),
                            5 => format!("LD ({}),A", a16()),
                            6 => "LD A,($FF00+C)".to_string(),
                            7 => format!("LD A,({})", a16()),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    3 => {
                        match y {
                            0 => format!("JP {}", a16()),
                            1 => {
                                // Prefix
                                prefix();
                                let x = (second_byte >> 6) & 0b011;
                                let y = (second_byte >> 3) & 0b111;
                                let z = (second_byte >> 0) & 0b111;

                                // WARNING: a8, d8, d16, etc. are broken here
                                match x {
                                    0 => format!("{} {}", idx_rot(y), idx_r(z)),
                                    1 => format!("BIT {},{}", y, idx_r(z)),
                                    2 => format!("RES {},{}", y, idx_r(z)),
                                    3 => format!("SET {},{}", y, idx_r(z)),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            2...5 => illegal_op(first_byte),
                            6 => "DI".to_string(),
                            7 => "EI".to_string(),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    4 => {
                        match y {
                            0...3 => format!("CALL {},{}", idx_cc(y), a16()),
                            4...7 => illegal_op(first_byte),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    5 => {
                        match q {
                            0 => format!("PUSH {}", idx_rp2(p)),
                            1 => {
                                match p {
                                    0 => format!("CALL {}", a16()),
                                    1...3 => illegal_op(first_byte),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    6 => format!("{} {}", idx_alu(y), d8()),
                    7 => format!("RST {:02X}H", y * 8),
                    _ => unreachable!("Impossible opcode"),
                }
            }
            _ => unreachable!("Impossible opcode"),
        }
    };

    // This garbage is here because two closures can't borrow same var.
    instruction_size += prefix_used;
    instruction_size += used_a8;
    instruction_size += used_r8;
    instruction_size += used_d8;
    instruction_size += used_a16;
    instruction_size += used_d16;
    (mnemonic, instruction_size)
}

#[allow(dead_code)]
fn disasm_rom(rom: [u8; 0x8000], rom_size: usize) {
    let mut pc = 0;

    while pc < rom_size {
        let (mnemonic, size) = pp_opcode(rom[pc], rom[pc + 1], rom[pc + 2], pc as u16);
        println!("\t{}\t\t; ${:04X} 0x{:02X} {}", mnemonic, pc, rom[pc], size);
        pc += size as usize;
    }
}

pub fn disasm_rom_to_vec(rom: [u8; 0x8000], rom_size: usize) -> Vec<(String, u16)> {
    let mut pc = 0;
    let mut ret: Vec<(String, u16)> = vec![];

    while pc < rom_size {
        let (mnemonic, size) = pp_opcode(rom[pc], rom[pc + 1], rom[pc + 2], pc as u16);
        ret.push((format!("0x{:04X}\t{}", pc, mnemonic), pc as u16));
        pc += size as usize;
    }

    ret
}

pub fn binsearch_inst(vec: &Vec<(String, u16)>,
                      desired_pc: u16,
                      begin: usize,
                      end: usize)
                      -> Option<usize> {
    if end < begin {
        return None;
    } else if end - begin <= 10 {
        for x in begin..(end + 1) {
            let (_, b) = vec[x];
            if b == desired_pc {
                return Some(x);
            }
        }
        return None;
    }

    let search = if (end + begin) % 2 == 0 {
        (end + begin) / 2
    } else {
        ((end + begin) / 2) + 1
    };

    let (_, b) = vec[search];

    return if b == desired_pc {
        Some(search)
    } else if b > desired_pc {
        binsearch_inst(vec, desired_pc, begin, (search + 1) as usize)
    } else {
        // if b > desired_pc {
        binsearch_inst(vec, desired_pc, (search - 1) as usize, end)
    };
}

#[allow(dead_code)]
fn main() {
    // // Print "[prefix] opcode size mnemonic" table
    // for i in 0..255 {
    //     let (mnemonic, size) = pp_opcode(i, 0xF2, 0x02, 0x2FFF);
    //     println!("0x{:02X} {} {:?}", i, size, mnemonic);
    // }
    // for i in 0..255 {
    //     let (mnemonic, size) = pp_opcode(0xCB, i, 0x02, 0x2FFF);
    //     println!("0xCB 0x{:02X} {} {:?}", i, size, mnemonic);
    // }
    use std::fs::File;
    use std::io::Read;
    use clap::{Arg, App};

    let matches = App::new("disasm")
        .version("0.1")
        .author("spawnedartifact")
        .about("GB z80 disassembler")
        .arg(Arg::with_name("game")
            .short("g")
            .long("game")
            .value_name("FILE")
            .help("Specifies ROM to load")
            .takes_value(true))
        .get_matches();

    let file_path = matches.value_of("game").expect("Could not open rom");
    let mut rom = File::open(file_path).expect("Could not open rom file");
    let mut rom_buffer: [u8; 0x8000] = [0u8; 0x8000];

    let rom_size = rom.read(&mut rom_buffer).unwrap();

    disasm_rom(rom_buffer, rom_size);
}
<commit_msg>Disasm crash fixes<commit_after>// Code courtesy of spawnedartifact

extern crate clap;

use std::num::Wrapping;

pub fn pp_opcode(first_byte: u8, second_byte: u8, third_byte: u8, pc: u16) -> (String, u8) {
    let x = (first_byte >> 6) & 0b011;
    let y = (first_byte >> 3) & 0b111;
    let z = first_byte & 0b111;
    let p = (first_byte >> 4) & 0b011;
    let q = (first_byte >> 3) & 0b001;

    let mut instruction_size = 1;

    // This garbage is here because two closures can't borrow same var.
    let mut prefix_used = 0;
    let mut used_a8 = 0;
    let mut used_d8 = 0;
    let mut used_r8 = 0;
    let mut used_a16 = 0;
    let mut used_d16 = 0;

    // This moved here to create a scope for closures to allow accessing
    // "used_*" vars later.
    let mnemonic = {
        let mut prefix = || prefix_used += 1;

        // Argument accessors. Will brake if used twice in a
        // row. Because of this, there is almost no point in using
        // them.
        let mut a8 = || {
            used_a8 += 1; //instruction_size += 1;
            format!("${:02X}", second_byte)
        };

        let mut d8 = || {
            used_d8 += 1; //instruction_size += 1;
            format!("${:02X}", second_byte)
        };

        // Because jump is relative to post pc increment we need to
        // know instruction size here.
        let mut r8 = |insize| {
            used_r8 += 1; //instruction_size += 1;
            // jump is relative to post pc increment!
            let addr = (Wrapping(pc) +
                        Wrapping(insize) +
                        Wrapping((second_byte as i8) as u16)).0;
            format!("Addr_{:04X}", addr)
        };

        let mut a16 = || {
            used_a16 += 2; //instruction_size += 2;
            format!("${:04X}",
                    (((third_byte as u16) << 8) | (second_byte as u16)))
        };

        let mut d16 = || {
            used_d16 += 2; //instruction_size += 2;
            format!("${:04X}",
                    (((third_byte as u16) << 8) | (second_byte as u16)))
        };

        // Converting indexes encoded in commands to symbolic arguments
        fn idx_r(i: u8) -> &'static str {
            ["B", "C", "D", "E", "H", "L", "(HL)", "A"][i as usize]
        };

        fn idx_rp(i: u8) -> &'static str {
            ["BC", "DE", "HL", "SP"][i as usize]
        };

        fn idx_rp2(i: u8) -> &'static str {
            ["BC", "DE", "HL", "AF"][i as usize]
        };

        fn idx_cc(i: u8) -> &'static str {
            ["NZ", "Z", "NC", "C"][i as usize]
        };

        fn idx_alu(i: u8) -> &'static str {
            ["ADD A,", "ADC A,", "SUB", "SBC A,", "AND", "XOR", "OR", "CP"][i as usize]
        };

        fn idx_rot(i: u8) -> &'static str {
            ["RLC", "RRC", "RL", "RR", "SLA", "SRA", "SWAP", "SRL"][i as usize]
        };

        fn illegal_op(byte: u8) -> String {
            format!(".DB ${:02X}", byte)
        }

        // The value of mnemonic =
        match x {
            0 => {
                match z {
                    0 => {
                        match y {
                            0 => "NOP".to_string(),
                            1 => format!("LD ({}),SP", a16()),
                            2 => format!("STOP {}", d8()),
                            3 => format!("JR {}", r8(2)),
                            4 => format!("JR NZ,{}", r8(2)),
                            5 => format!("JR Z,{}", r8(2)),
                            6 => format!("JR NC,{}", r8(2)),
                            7 => format!("JR C,{}", r8(2)),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    1 => {
                        match q {
                            0 => format!("LD {},{}", idx_rp(p), d16()),
                            1 => format!("ADD HL,{}", idx_rp(p)),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    2 => {
                        match q {
                            0 => {
                                match p {
                                    0 => "LD (BC),A".to_string(),
                                    1 => "LD (DE),A".to_string(),
                                    2 => "LD (HL+),A".to_string(),
                                    3 => "LD (HL-),A".to_string(),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            1 => {
                                match p {
                                    0 => "LD A,(BC)".to_string(),
                                    1 => "LD A,(DE)".to_string(),
                                    2 => "LD A,(HL+)".to_string(),
                                    3 => "LD A,(HL-)".to_string(),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    3 => {
                        match q {
                            0 => format!("INC {}", idx_rp(p)),
                            1 => format!("DEC {}", idx_rp(p)),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    4 => format!("INC {}", idx_r(y)),
                    5 => format!("DEC {}", idx_r(y)),
                    6 => format!("LD {},{}", idx_r(y), d8()),
                    7 => {
                        match y {
                            0 => "RLCA".to_string(),
                            1 => "RRCA".to_string(),
                            2 => "RLA".to_string(),
                            3 => "RRA".to_string(),
                            4 => "DAA".to_string(),
                            5 => "CPL".to_string(),
                            6 => "SCF".to_string(),
                            7 => "CCF".to_string(),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    _ => unreachable!("Impossible opcode"),
                }
            }
            1 => {
                match (z, y) {
                    (6, 6) => "HALT".to_string(),
                    _ => format!("LD {},{}", idx_r(y), idx_r(z)),
                }
            }
            // FIXME cheating here a bit with idx_alu value
            2 => format!("{} {}", idx_alu(y), idx_r(z)),
            3 => {
                match z {
                    0 => {
                        match y {
                            0...3 => format!("RET {}", idx_cc(y)),
                            // 4 => format!("LDH ({}),A", a8()),
                            4 => format!("LD ($FF00+{}),A", a8()),
                            5 => format!("ADD SP,{}", r8(0)), // FIXME
                            // 6 => format!("LDH A,({})", a8()),
                            6 => format!("LD A,($FF00+{})", a8()),
                            7 => format!("LD HL,(sp + {})", r8(0)), // FIXME
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    1 => {
                        match q {
                            0 => format!("POP {}", idx_rp2(p)),
                            1 => {
                                match p {
                                    0 => "RET".to_string(),
                                    1 => "RETI".to_string(),
                                    2 => "JP (HL)".to_string(),
                                    3 => "LD SP,HL".to_string(),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    2 => {
                        match y {
                            0...3 => format!("JP {},{}", idx_cc(y), a16()),
                            4 => "LD ($FF00+C),A".to_string(),
                            5 => format!("LD ({}),A", a16()),
                            6 => "LD A,($FF00+C)".to_string(),
                            7 => format!("LD A,({})", a16()),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    3 => {
                        match y {
                            0 => format!("JP {}", a16()),
                            1 => {
                                // Prefix
                                prefix();
                                let x = (second_byte >> 6) & 0b011;
                                let y = (second_byte >> 3) & 0b111;
                                let z = (second_byte >> 0) & 0b111;

                                // WARNING: a8, d8, d16, etc. are broken here
                                match x {
                                    0 => format!("{} {}", idx_rot(y), idx_r(z)),
                                    1 => format!("BIT {},{}", y, idx_r(z)),
                                    2 => format!("RES {},{}", y, idx_r(z)),
                                    3 => format!("SET {},{}", y, idx_r(z)),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            2...5 => illegal_op(first_byte),
                            6 => "DI".to_string(),
                            7 => "EI".to_string(),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    4 => {
                        match y {
                            0...3 => format!("CALL {},{}", idx_cc(y), a16()),
                            4...7 => illegal_op(first_byte),
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    5 => {
                        match q {
                            0 => format!("PUSH {}", idx_rp2(p)),
                            1 => {
                                match p {
                                    0 => format!("CALL {}", a16()),
                                    1...3 => illegal_op(first_byte),
                                    _ => unreachable!("Impossible opcode"),
                                }
                            }
                            _ => unreachable!("Impossible opcode"),
                        }
                    }
                    6 => format!("{} {}", idx_alu(y), d8()),
                    7 => format!("RST {:02X}H", y * 8),
                    _ => unreachable!("Impossible opcode"),
                }
            }
            _ => unreachable!("Impossible opcode"),
        }
    };

    // This garbage is here because two closures can't borrow same var.
    instruction_size += prefix_used;
    instruction_size += used_a8;
    instruction_size += used_r8;
    instruction_size += used_d8;
    instruction_size += used_a16;
    instruction_size += used_d16;
    (mnemonic, instruction_size)
}

#[allow(dead_code)]
fn disasm_rom(rom: [u8; 0x8000], rom_size: usize) {
    let mut pc = 0;

    let crash_preventing_size = rom_size - 2; // FIXME
    while pc < crash_preventing_size {
        let b1 = rom[pc];
        let b2 = rom[pc + 1];
        let b3 = rom[pc + 2];
        let (mnemonic, size) = pp_opcode(b1, b2, b3, pc as u16);
        print!("\t{:25}; ${:04X} ", mnemonic, pc);
        match size {
            1 => print!("{:02x}", b1),
            2 => print!("{:02x}{:02x}", b1, b2),
            3 => print!("{:02x}{:02x}{:02x}", b1, b2, b3),
            _ => unreachable!(),
        }
        println!();

        pc += size as usize;
    }
}

pub fn disasm_rom_to_vec(rom: [u8; 0x8000], rom_size: usize) -> Vec<(String, u16)> {
    let mut pc = 0;
    let mut ret: Vec<(String, u16)> = vec![];

    while pc < rom_size {
        let (mnemonic, size) = pp_opcode(rom[pc], rom[pc + 1], rom[pc + 2], pc as u16);
        ret.push((format!("0x{:04X}\t{}", pc, mnemonic), pc as u16));
        pc += size as usize;
    }

    ret
}

pub fn binsearch_inst(vec: &Vec<(String, u16)>,
                      desired_pc: u16,
                      begin: usize,
                      end: usize)
                      -> Option<usize> {
    if end < begin {
        return None;
    } else if end - begin <= 10 {
        for x in begin..(end + 1) {
            let (_, b) = vec[x];
            if b == desired_pc {
                return Some(x);
            }
        }
        return None;
    }

    let search = if (end + begin) % 2 == 0 {
        (end + begin) / 2
    } else {
        ((end + begin) / 2) + 1
    };

    let (_, b) = vec[search];

    return if b == desired_pc {
        Some(search)
    } else if b > desired_pc {
        binsearch_inst(vec, desired_pc, begin, (search + 1) as usize)
    } else {
        // if b > desired_pc {
        binsearch_inst(vec, desired_pc, (search - 1) as usize, end)
    };
}

#[allow(dead_code)]
fn main() {
    // // Print "[prefix] opcode size mnemonic" table
    // for i in 0..255 {
    //     let (mnemonic, size) = pp_opcode(i, 0xF2, 0x02, 0x2FFF);
    //     println!("0x{:02X} {} {:?}", i, size, mnemonic);
    // }
    // for i in 0..255 {
    //     let (mnemonic, size) = pp_opcode(0xCB, i, 0x02, 0x2FFF);
    //     println!("0xCB 0x{:02X} {} {:?}", i, size, mnemonic);
    // }
    use std::fs::File;
    use std::io::Read;
    use clap::{Arg, App};

    let matches = App::new("disasm")
        .version("0.1")
        .author("spawnedartifact")
        .about("GB z80 disassembler")
        .arg(Arg::with_name("game")
             .index(1)
             .value_name("FILE")
             .help("Specifies ROM to disassemble")
             .takes_value(true))
        .get_matches();

    let file_path = matches.value_of("game").expect("Could not open rom");
    let mut rom = File::open(file_path).expect("Could not open rom file");
    let mut rom_buffer: [u8; 0x8000] = [0u8; 0x8000];

    let rom_size = rom.read(&mut rom_buffer).unwrap();

    disasm_rom(rom_buffer, rom_size);
}
<|endoftext|>


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

use reqwest::header;
use serde_json;

error_chain! {
    links {
        PublicKey(::openssh_keys::errors::Error, ::openssh_keys::errors::ErrorKind);
        AuthorizedKeys(::update_ssh_keys::errors::Error, ::update_ssh_keys::errors::ErrorKind) #[cfg(feature = "cl-legacy")];
    }
    foreign_links {
        Log(::slog::Error);
        XmlDeserialize(::serde_xml_rs::Error);
        Base64Decode(::base64::DecodeError);
        Io(::std::io::Error);
        Json(serde_json::Error);
        Reqwest(::reqwest::Error);
        OpensslStack(::openssl::error::ErrorStack);
        HeaderValue(header::InvalidHeaderValue);
    }
    errors {
        UnknownProvider(p: String) {
            description("unknown provider")
            display("unknown provider '{}'", p)
        }
    }
}
<commit_msg>errors: whitelist deprecation warnings from error-chain<commit_after>// Copyright 2017 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(deprecated)]

use reqwest::header;
use serde_json;

error_chain! {
    links {
        PublicKey(::openssh_keys::errors::Error, ::openssh_keys::errors::ErrorKind);
        AuthorizedKeys(::update_ssh_keys::errors::Error, ::update_ssh_keys::errors::ErrorKind) #[cfg(feature = "cl-legacy")];
    }
    foreign_links {
        Log(::slog::Error);
        XmlDeserialize(::serde_xml_rs::Error);
        Base64Decode(::base64::DecodeError);
        Io(::std::io::Error);
        Json(serde_json::Error);
        Reqwest(::reqwest::Error);
        OpensslStack(::openssl::error::ErrorStack);
        HeaderValue(header::InvalidHeaderValue);
    }
    errors {
        UnknownProvider(p: String) {
            description("unknown provider")
            display("unknown provider '{}'", p)
        }
    }
}
<|endoftext|>


<commit_before>use std::iter;
use rustwlc::Size;
use std::fmt::{self, Debug};
use std::cmp::{Eq, PartialEq};
use cairo::{Context, ImageSurface, Format, Operator, Status, SolidPattern};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Color {
    red: u32,
    green: u32,
    blue: u32
}

#[derive(Clone)]
/// A border for a container.
pub struct Border {
    context: Context,
    thickness: u32,
    color: Color,
    size: Size
}

/// All the borders of a container (top, bottom, left, right)
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Borders {
    top: Option<Border>,
    bottom: Option<Border>,
    right: Option<Border>,
    left: Option<Border>
}

impl Color {
    pub fn new(red: u32, green: u32, blue: u32) -> Self {
        Color { red: red, green: green, blue: blue}
    }
}

impl Border {
    pub fn new(size: Size, thickness: u32, color: Color) -> Self {
        let Size { w, h } = size;
        let h = h as i32;
        let w = w as i32;
        // TODO Magic numbers
        let stride = calculate_stride(w as u32) as i32;
        let data: Vec<u8> = iter::repeat(0).take(w as usize * stride as usize).collect();
        let buffer = data.into_boxed_slice();
        let surface = ImageSurface::create_for_data(buffer, drop_data, Format::ARgb32, h, w, stride);
        let context = Context::new(&surface);
        context.set_operator(Operator::Source);
        match context.status() {
            Status::Success => {},
            err => {
                panic!("Cairo context failed with {:#?}", err);
            }
        }
        Border {
            context: context,
            thickness: thickness,
            color: color,
            size: size
        }
    }

    /// Renders a line, starting from (x, y) to (x + width, y + height).
    pub fn render(&mut self, mut x: f64, mut y: f64) {
        let Color { red, green, blue} = self.color;
        let Size { w, h } = self.size;
        let mut w = w as f64;
        let mut h = h as f64;
        let pattern = SolidPattern::from_rgb(red as f64 / 255.0,
                                             green as f64 / 255.0,
                                             blue as f64 / 255.0);
        self.context.set_source(&pattern);
        if w > 1.0 && h > 1.0 {
            self.context.rectangle(x, y, w, h);
            self.context.fill();
        } else {
            if w == 1.0 {
                x += 0.5;
                h += y;
                w = x;
            }

            if h == 1.0 {
                y += 0.5;
                w += x;
                h = y;
            }

            self.context.move_to(x, y);
            self.context.set_line_width(1.0);
            self.context.line_to(w, h);
            self.context.stroke();
        }
    }
}

impl Debug for Border {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Debug")
            .field("thickness", &self.thickness as &Debug)
            .field("color", &self.color as &Debug)
            .finish()
    }
}

impl PartialEq for Border {
    fn eq(&self, other: &Border) -> bool {
        (self.thickness == other.thickness && self.color == other.color
         && self.size == other.size)
    }
}

impl Eq for Border {}

unsafe impl Send for Border {}
unsafe impl Sync for Border {}

impl Borders {
    pub fn new(top: Option<Border>, bottom: Option<Border>,
               left: Option<Border>, right: Option<Border>) -> Self {
        Borders {
            top: top,
            bottom: bottom,
            left: left,
            right: right
        }
    }
}

/// Calculates the stride for ARgb32 encoded buffers
fn calculate_stride(width: u32) -> u32 {
    // function stolen from CAIRO_STRIDE_FOR_WIDTH macro in cairoint.h
    // Can be found in the most recent version of the cairo source
    (32 * width + 7) / 8 + 4 & !4
}

fn drop_data(_: Box<[u8]>) {}

#[cfg(tests)]
mod tests {
    use super::calculate_stride;

    #[test]
    fn test_calculate_stride() {
        let test_data = [
            (100, 400),
            (200, 800),
            (300, 1200),
            (400, 1600),
            (500, 2000),
            (600, 2400),
            (700, 2800),
            (800, 3200),
            (900, 3600)
        ];
        for &(width, stride) in test_data.iter() {
            assert_eq!(calculate_stride(width), stride);
        }
    }
}
<commit_msg>Borders store geometry, not sizes<commit_after>use std::iter;
use rustwlc::{Geometry, Size};
use std::fmt::{self, Debug};
use std::cmp::{Eq, PartialEq};
use cairo::{Context, ImageSurface, Format, Operator, Status, SolidPattern};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Color {
    red: u32,
    green: u32,
    blue: u32
}

#[derive(Clone)]
/// A border for a container.
pub struct Border {
    context: Context,
    thickness: u32,
    color: Color,
    geometry: Geometry
}

/// All the borders of a container (top, bottom, left, right)
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Borders {
    top: Option<Border>,
    bottom: Option<Border>,
    right: Option<Border>,
    left: Option<Border>
}

impl Color {
    pub fn new(red: u32, green: u32, blue: u32) -> Self {
        Color { red: red, green: green, blue: blue}
    }
}

impl Border {
    pub fn new(geometry: Geometry, thickness: u32, color: Color) -> Self {
        let Size { w, h } = geometry.size;
        let h = h as i32;
        let w = w as i32;
        let stride = calculate_stride(w as u32) as i32;
        let data: Vec<u8> = iter::repeat(0).take(w as usize * stride as usize).collect();
        let buffer = data.into_boxed_slice();
        let surface = ImageSurface::create_for_data(buffer, drop_data, Format::ARgb32, h, w, stride);
        let context = Context::new(&surface);
        context.set_operator(Operator::Source);
        match context.status() {
            Status::Success => {},
            err => {
                panic!("Cairo context failed with {:#?}", err);
            }
        }
        Border {
            context: context,
            thickness: thickness,
            color: color,
            geometry: geometry
        }
    }

    /// Renders a line, starting from (x, y) to (x + width, y + height).
    pub fn render(&self, mut x: f64, mut y: f64) {
        let Color { red, green, blue} = self.color;
        let Size { w, h } = self.geometry.size;
        let mut w = w as f64;
        let mut h = h as f64;
        let pattern = SolidPattern::from_rgb(red as f64 / 255.0,
                                             green as f64 / 255.0,
                                             blue as f64 / 255.0);
        self.context.set_source(&pattern);
        if w > 1.0 && h > 1.0 {
            self.context.rectangle(x, y, w, h);
            self.context.fill();
        } else {
            if w == 1.0 {
                x += 0.5;
                h += y;
                w = x;
            }

            if h == 1.0 {
                y += 0.5;
                w += x;
                h = y;
            }

            self.context.move_to(x, y);
            self.context.set_line_width(1.0);
            self.context.line_to(w, h);
            self.context.stroke();
        }
    }
}

impl Debug for Border {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Debug")
            .field("thickness", &self.thickness as &Debug)
            .field("color", &self.color as &Debug)
            .finish()
    }
}

impl PartialEq for Border {
    fn eq(&self, other: &Border) -> bool {
        (self.thickness == other.thickness && self.color == other.color
         && self.geometry == other.geometry)
    }
}

impl Eq for Border {}

unsafe impl Send for Border {}
unsafe impl Sync for Border {}

impl Borders {
    pub fn new(top: Option<Border>, bottom: Option<Border>,
               left: Option<Border>, right: Option<Border>) -> Self {
        Borders {
            top: top,
            bottom: bottom,
            left: left,
            right: right
        }
    }

    /// Renders each border at their respective geometries.
    pub fn render(&self) {
        let borders = vec![&self.top, &self.bottom, &self.left, &self.right];
        for border in borders.iter().flat_map(|maybe_g| maybe_g.into_iter()) {
        }
    }
}

/// Calculates the stride for ARgb32 encoded buffers
fn calculate_stride(width: u32) -> u32 {
    // function stolen from CAIRO_STRIDE_FOR_WIDTH macro in cairoint.h
    // Can be found in the most recent version of the cairo source
    (32 * width + 7) / 8 + 4 & !4
}

fn drop_data(_: Box<[u8]>) {}

#[cfg(tests)]
mod tests {
    use super::calculate_stride;

    #[test]
    fn test_calculate_stride() {
        let test_data = [
            (100, 400),
            (200, 800),
            (300, 1200),
            (400, 1600),
            (500, 2000),
            (600, 2400),
            (700, 2800),
            (800, 3200),
            (900, 3600)
        ];
        for &(width, stride) in test_data.iter() {
            assert_eq!(calculate_stride(width), stride);
        }
    }
}
<|endoftext|>


<commit_before>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use BuildQuery;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Default, Clone, Copy, Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Default)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    http_proxy: Option<String>,
    pagination: Option<Pagination>,
    client: hyper::Client,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
            // client: {:?}, \
            //    self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn _new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            http_proxy: env::var("HTTP_PROXY").ok(),
            pagination: None,
            client: hyper::Client::new(),
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        warn!("Using insecure http:// protocol: Token will be sent in clear!");
        GitLab::_new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::_new("https", domain, 443, private_token)
    }

    pub fn http_proxy(&self) -> Option<&str> {
        self.http_proxy.as_ref().map(|proxy| &**proxy)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let params_splitter = if query.find('?').is_some() { "&" } else { "?" };
        let mut url = format!("{}://{}:{}/api/v{}/{}{}private_token={}",
                              self.scheme,
                              self.domain,
                              self.port,
                              API_VERSION,
                              query,
                              params_splitter,
                              self.private_token);

        self.pagination.as_ref().map(|pagination| {
            url.push_str(&format!("&page={}&per_page={}", pagination.page, pagination.per_page));
        });

        url
    }

    // pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
    //     let url = self.build_url("version");
    //     // Close connections after each GET.
    //     self.client.get(&url).header(hyper::header::Connection::close()).send()
    // }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        // FIXME: Properly handle any errors. Use chain_error crate.

        let url = self.build_url(query);
        info!("url: {:?}", url);

        // Close connections after each GET.
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body:\n{:?}", body);

        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }

    pub fn projects(&self) -> ::projects::ProjectsLister {
        ::projects::ProjectsLister::new(&self)
    }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        // self.get(&query)
        unimplemented!();
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<commit_msg>Re-activate proxy support, deleting now useless `http_proxy()` method.<commit_after>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use hyper;
use serde;
use serde_json;

use BuildQuery;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Default, Clone, Copy, Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Default)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    pagination: Option<Pagination>,
    client: hyper::Client,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
            // client: {:?}, \
            //    self.client,
               self.pagination)
    }
}

impl GitLab {
    pub fn _new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            private_token: private_token.to_string(),
            pagination: None,
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        warn!("Using insecure http:// protocol: Token will be sent in clear!");
        GitLab::_new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::_new("https", domain, 443, private_token)
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com:\
    ///                     443/api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let params_splitter = if query.find('?').is_some() { "&" } else { "?" };
        let mut url = format!("{}://{}:{}/api/v{}/{}{}private_token={}",
                              self.scheme,
                              self.domain,
                              self.port,
                              API_VERSION,
                              query,
                              params_splitter,
                              self.private_token);

        self.pagination.as_ref().map(|pagination| {
            url.push_str(&format!("&page={}&per_page={}", pagination.page, pagination.per_page));
        });

        url
    }

    // pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
    //     let url = self.build_url("version");
    //     // Close connections after each GET.
    //     self.client.get(&url).header(hyper::header::Connection::close()).send()
    // }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T, serde_json::Error>
        where T: serde::Deserialize
    {
        // FIXME: Properly handle any errors. Use chain_error crate.

        let url = self.build_url(query);
        info!("url: {:?}", url);

        // Close connections after each GET.
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .unwrap();
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        debug!("body:\n{:?}", body);

        assert_eq!(res.status, hyper::status::StatusCode::Ok);

        serde_json::from_str(body.as_str())
    }

    // pub fn version(&self) -> Result<Version, serde_json::Error> {
    //     self.get("version")
    // }
    //
    // pub fn groups(&self) -> Result<Groups, serde_json::Error> {
    //     self.get("groups")
    // }

    pub fn projects(&self) -> ::projects::ProjectsLister {
        ::projects::ProjectsLister::new(&self)
    }

    pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
        let query = listing.build_query();
        // self.get(&query)
        unimplemented!();
    }

    pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
        let query = ::groups::owned_groups::Listing::new().build_query();
        info!("query: {:?}", query);
        self.get(&query)
    }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<|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.

fn op1() -> Result<isize, &'static str> { Ok(666) }
fn op2() -> Result<isize, &'static str> { Err("sadface") }

#[test]
fn test_and() {
    assert_eq!(op1().and(Ok(667)).unwrap(), 667);
    assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
               "bad");

    assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface");
    assert_eq!(op2().and(Err::<i32,&'static str>("bad")).unwrap_err(),
               "sadface");
}

#[test]
fn test_and_then() {
    assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
    assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
               "bad");

    assert_eq!(op2().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap_err(),
               "sadface");
    assert_eq!(op2().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
               "sadface");
}

#[test]
fn test_or() {
    assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
    assert_eq!(op1().or(Err("bad")).unwrap(), 666);

    assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
    assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
}

#[test]
fn test_or_else() {
    assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
    assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);

    assert_eq!(op2().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 667);
    assert_eq!(op2().or_else(|e| Err::<isize, &'static str>(e)).unwrap_err(),
               "sadface");
}

#[test]
fn test_impl_map() {
    assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
    assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
}

#[test]
fn test_impl_map_err() {
    assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
    assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
}

#[test]
fn test_collect() {
    let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
    assert!(v == Ok(vec![]));

    let v: Result<Vec<isize>, ()> = (0..3).map(|x| Ok::<isize, ()>(x)).collect();
    assert!(v == Ok(vec![0, 1, 2]));

    let v: Result<Vec<isize>, isize> = (0..3).map(|x| {
        if x > 1 { Err(x) } else { Ok(x) }
    }).collect();
    assert!(v == Err(2));

    // test that it does not take more elements than it needs
    let mut functions: [Box<Fn() -> Result<(), isize>>; 3] =
        [box || Ok(()), box || Err(1), box || panic!()];

    let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
    assert!(v == Err(1));
}

#[test]
fn test_fmt_default() {
    let ok: Result<isize, &'static str> = Ok(100);
    let err: Result<isize, &'static str> = Err("Err");

    let s = format!("{:?}", ok);
    assert_eq!(s, "Ok(100)");
    let s = format!("{:?}", err);
    assert_eq!(s, "Err(\"Err\")");
}

#[test]
fn test_unwrap_or() {
    let ok: Result<isize, &'static str> = Ok(100);
    let ok_err: Result<isize, &'static str> = Err("Err");

    assert_eq!(ok.unwrap_or(50), 100);
    assert_eq!(ok_err.unwrap_or(50), 50);
}

#[test]
fn test_unwrap_or_else() {
    fn handler(msg: &'static str) -> isize {
        if msg == "I got this." {
            50
        } else {
            panic!("BadBad")
        }
    }

    let ok: Result<isize, &'static str> = Ok(100);
    let ok_err: Result<isize, &'static str> = Err("I got this.");

    assert_eq!(ok.unwrap_or_else(handler), 100);
    assert_eq!(ok_err.unwrap_or_else(handler), 50);
}

#[test]
#[should_panic]
pub fn test_unwrap_or_else_panic() {
    fn handler(msg: &'static str) -> isize {
        if msg == "I got this." {
            50
        } else {
            panic!("BadBad")
        }
    }

    let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
    let _ : isize = bad_err.unwrap_or_else(handler);
}

#[test]
pub fn test_expect_ok() {
    let ok: Result<isize, &'static str> = Ok(100);
    assert_eq!(ok.expect("Unexpected error"), 100);
}
#[test]
#[should_panic(expected="Got expected error: \"All good\"")]
pub fn test_expect_err() {
    let err: Result<isize, &'static str> = Err("All good");
    err.expect("Got expected error");
}

#[test]
pub fn test_iter() {
    let ok: Result<isize, &'static str> = Ok(100);
    let mut it = ok.iter();
    assert_eq!(it.size_hint(), (1, Some(1)));
    assert_eq!(it.next(), Some(&100));
    assert_eq!(it.size_hint(), (0, Some(0)));
    assert!(it.next().is_none());
    assert_eq!((&ok).into_iter().next(), Some(&100));

    let err: Result<isize, &'static str> = Err("error");
    assert_eq!(err.iter().next(), None);
}

#[test]
pub fn test_iter_mut() {
    let mut ok: Result<isize, &'static str> = Ok(100);
    for loc in ok.iter_mut() {
        *loc = 200;
    }
    assert_eq!(ok, Ok(200));
    for loc in &mut ok {
        *loc = 300;
    }
    assert_eq!(ok, Ok(300));

    let mut err: Result<isize, &'static str> = Err("error");
    for loc in err.iter_mut() {
        *loc = 200;
    }
    assert_eq!(err, Err("error"));
}

#[test]
pub fn test_unwrap_or_default() {
    assert_eq!(op1().unwrap_or_default(), 666);
    assert_eq!(op2().unwrap_or_default(), 0);
}
<commit_msg>Fix `test_unwrap_or_default`<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.

#![feature(result_unwrap_or_default)]

fn op1() -> Result<isize, &'static str> { Ok(666) }
fn op2() -> Result<isize, &'static str> { Err("sadface") }

#[test]
fn test_and() {
    assert_eq!(op1().and(Ok(667)).unwrap(), 667);
    assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
               "bad");

    assert_eq!(op2().and(Ok(667)).unwrap_err(), "sadface");
    assert_eq!(op2().and(Err::<i32,&'static str>("bad")).unwrap_err(),
               "sadface");
}

#[test]
fn test_and_then() {
    assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
    assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
               "bad");

    assert_eq!(op2().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap_err(),
               "sadface");
    assert_eq!(op2().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
               "sadface");
}

#[test]
fn test_or() {
    assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
    assert_eq!(op1().or(Err("bad")).unwrap(), 666);

    assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
    assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
}

#[test]
fn test_or_else() {
    assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
    assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);

    assert_eq!(op2().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 667);
    assert_eq!(op2().or_else(|e| Err::<isize, &'static str>(e)).unwrap_err(),
               "sadface");
}

#[test]
fn test_impl_map() {
    assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
    assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
}

#[test]
fn test_impl_map_err() {
    assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
    assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
}

#[test]
fn test_collect() {
    let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
    assert!(v == Ok(vec![]));

    let v: Result<Vec<isize>, ()> = (0..3).map(|x| Ok::<isize, ()>(x)).collect();
    assert!(v == Ok(vec![0, 1, 2]));

    let v: Result<Vec<isize>, isize> = (0..3).map(|x| {
        if x > 1 { Err(x) } else { Ok(x) }
    }).collect();
    assert!(v == Err(2));

    // test that it does not take more elements than it needs
    let mut functions: [Box<Fn() -> Result<(), isize>>; 3] =
        [box || Ok(()), box || Err(1), box || panic!()];

    let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
    assert!(v == Err(1));
}

#[test]
fn test_fmt_default() {
    let ok: Result<isize, &'static str> = Ok(100);
    let err: Result<isize, &'static str> = Err("Err");

    let s = format!("{:?}", ok);
    assert_eq!(s, "Ok(100)");
    let s = format!("{:?}", err);
    assert_eq!(s, "Err(\"Err\")");
}

#[test]
fn test_unwrap_or() {
    let ok: Result<isize, &'static str> = Ok(100);
    let ok_err: Result<isize, &'static str> = Err("Err");

    assert_eq!(ok.unwrap_or(50), 100);
    assert_eq!(ok_err.unwrap_or(50), 50);
}

#[test]
fn test_unwrap_or_else() {
    fn handler(msg: &'static str) -> isize {
        if msg == "I got this." {
            50
        } else {
            panic!("BadBad")
        }
    }

    let ok: Result<isize, &'static str> = Ok(100);
    let ok_err: Result<isize, &'static str> = Err("I got this.");

    assert_eq!(ok.unwrap_or_else(handler), 100);
    assert_eq!(ok_err.unwrap_or_else(handler), 50);
}

#[test]
#[should_panic]
pub fn test_unwrap_or_else_panic() {
    fn handler(msg: &'static str) -> isize {
        if msg == "I got this." {
            50
        } else {
            panic!("BadBad")
        }
    }

    let bad_err: Result<isize, &'static str> = Err("Unrecoverable mess.");
    let _ : isize = bad_err.unwrap_or_else(handler);
}

#[test]
pub fn test_expect_ok() {
    let ok: Result<isize, &'static str> = Ok(100);
    assert_eq!(ok.expect("Unexpected error"), 100);
}
#[test]
#[should_panic(expected="Got expected error: \"All good\"")]
pub fn test_expect_err() {
    let err: Result<isize, &'static str> = Err("All good");
    err.expect("Got expected error");
}

#[test]
pub fn test_iter() {
    let ok: Result<isize, &'static str> = Ok(100);
    let mut it = ok.iter();
    assert_eq!(it.size_hint(), (1, Some(1)));
    assert_eq!(it.next(), Some(&100));
    assert_eq!(it.size_hint(), (0, Some(0)));
    assert!(it.next().is_none());
    assert_eq!((&ok).into_iter().next(), Some(&100));

    let err: Result<isize, &'static str> = Err("error");
    assert_eq!(err.iter().next(), None);
}

#[test]
pub fn test_iter_mut() {
    let mut ok: Result<isize, &'static str> = Ok(100);
    for loc in ok.iter_mut() {
        *loc = 200;
    }
    assert_eq!(ok, Ok(200));
    for loc in &mut ok {
        *loc = 300;
    }
    assert_eq!(ok, Ok(300));

    let mut err: Result<isize, &'static str> = Err("error");
    for loc in err.iter_mut() {
        *loc = 200;
    }
    assert_eq!(err, Err("error"));
}

#[test]
pub fn test_unwrap_or_default() {
    assert_eq!(op1().unwrap_or_default(), 666);
    assert_eq!(op2().unwrap_or_default(), 0);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014-2015 Mathias Hällman
 *
 * 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/.
 */

/*
 * A key can be of any of the following types:
 *   - Function key such as F1 or F24
 *   - Symbolic key such as enter or escape
 *   - Unicode codepoint such as a, ä, or あ
 * The key also records key modifier information.
 */
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum Key {
  Fn{num: isize, mods: KeyMod},
  Sym{sym: KeySym, mods: KeyMod},
  Unicode{codepoint: char, mods: KeyMod},
}

#[derive(Clone, Copy, Eq, Hash, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum KeySym
{
  Unknown = -1,
  None = 0,

  /* Special names in C0 */
  Backspace,
  Tab,
  Enter,
  Escape,

  /* Special names in G0 */
  Space,
  Del,

  /* Special keys */
  Up,
  Down,
  Left,
  Right,
  Begin,
  Find,
  Insert,
  Delete,
  Select,
  Pageup,
  Pagedown,
  Home,
  End,

  /* Special keys from terminfo */
  Cancel,
  Clear,
  Close,
  Command,
  Copy,
  Exit,
  Help,
  Mark,
  Message,
  Move,
  Open,
  Options,
  Print,
  Redo,
  Reference,
  Refresh,
  Replace,
  Restart,
  Resume,
  Save,
  Suspend,
  Undo,

  /* Numeric keypad special keys */
  KP0,
  KP1,
  KP2,
  KP3,
  KP4,
  KP5,
  KP6,
  KP7,
  KP8,
  KP9,
  KPEnter,
  KPPlus,
  KPMinus,
  KPMult,
  KPDiv,
  KPComma,
  KPPeriod,
  KPEquals,

  /* et cetera ad nauseum */
  NSyms,
}

bitflags! {
  #[derive(Debug)]
  flags KeyMod: u8 {
    const MOD_NONE  = 0,
    const MOD_SHIFT = 1 << 0,
    const MOD_ALT   = 1 << 1,
    const MOD_CTRL  = 1 << 2,
  }
}

#[allow(dead_code)]  // as the name suggests, this function should not be called
fn totally_useless_function_just_to_suppress_warnings_about_dead_code() {
  let mut a = MOD_NONE;
  a.toggle(MOD_NONE); a.remove(MOD_NONE); a.intersects(MOD_NONE);
  a.is_all(); KeyMod::from_bits_truncate(0); KeyMod::from_bits(0);
  a.insert(MOD_NONE); a.contains(MOD_NONE);
}
<commit_msg>Revert "Hack: skip cfg_attr"<commit_after>/*
 * Copyright (c) 2014-2015 Mathias Hällman
 *
 * 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/.
 */

/*
 * A key can be of any of the following types:
 *   - Function key such as F1 or F24
 *   - Symbolic key such as enter or escape
 *   - Unicode codepoint such as a, ä, or あ
 * The key also records key modifier information.
 */
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum Key {
  Fn{num: isize, mods: KeyMod},
  Sym{sym: KeySym, mods: KeyMod},
  Unicode{codepoint: char, mods: KeyMod},
}

#[derive(Clone, Copy, Eq, Hash, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub enum KeySym
{
  Unknown = -1,
  None = 0,

  /* Special names in C0 */
  Backspace,
  Tab,
  Enter,
  Escape,

  /* Special names in G0 */
  Space,
  Del,

  /* Special keys */
  Up,
  Down,
  Left,
  Right,
  Begin,
  Find,
  Insert,
  Delete,
  Select,
  Pageup,
  Pagedown,
  Home,
  End,

  /* Special keys from terminfo */
  Cancel,
  Clear,
  Close,
  Command,
  Copy,
  Exit,
  Help,
  Mark,
  Message,
  Move,
  Open,
  Options,
  Print,
  Redo,
  Reference,
  Refresh,
  Replace,
  Restart,
  Resume,
  Save,
  Suspend,
  Undo,

  /* Numeric keypad special keys */
  KP0,
  KP1,
  KP2,
  KP3,
  KP4,
  KP5,
  KP6,
  KP7,
  KP8,
  KP9,
  KPEnter,
  KPPlus,
  KPMinus,
  KPMult,
  KPDiv,
  KPComma,
  KPPeriod,
  KPEquals,

  /* et cetera ad nauseum */
  NSyms,
}

bitflags! {
  #[cfg_attr(test, derive(Debug))]
  flags KeyMod: u8 {
    const MOD_NONE  = 0,
    const MOD_SHIFT = 1 << 0,
    const MOD_ALT   = 1 << 1,
    const MOD_CTRL  = 1 << 2,
  }
}

#[allow(dead_code)]  // as the name suggests, this function should not be called
fn totally_useless_function_just_to_suppress_warnings_about_dead_code() {
  let mut a = MOD_NONE;
  a.toggle(MOD_NONE); a.remove(MOD_NONE); a.intersects(MOD_NONE);
  a.is_all(); KeyMod::from_bits_truncate(0); KeyMod::from_bits(0);
  a.insert(MOD_NONE); a.contains(MOD_NONE);
}
<|endoftext|>


<commit_before>extern crate walkdir;

use self::walkdir::{DirEntry as WalkDirEntry, WalkDir, WalkDirIterator};

use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::io::Error as IoError;
use std::path::{Path, PathBuf};
use std::result::Result;

macro_rules! path_buf {
    ($($x: expr),+) => {
        PathBuf::new()
            $(.join($x))+
    };
}

pub fn ls<P: AsRef<Path>>(path: P) -> Result<Vec<String>, IoError> {
    let dirs = try!(fs::read_dir(path));
    let dirs = dirs
        .filter_map(Result::ok)
        .map(|d| d.file_name())
        .map(OsString::into_string)
        .filter_map(Result::ok)
        .collect::<Vec<String>>();
    Ok(dirs)
}

pub fn is_empty_dir<P: AsRef<Path>>(path: P) -> bool {
    match fs::read_dir(path) {
        Ok(rd) => rd.count() == 0,
        Err(_) => false,
    }
}

fn is_hidden_name(file_name: &str) -> bool {
    file_name.starts_with(".") && file_name.len() > 1 && file_name != ".."
}
#[test]
fn is_hidden_name_should_return_true() {
    let file_names = [
        ".a",
        ".ab",
        ".abc",
        "..a",
        "...",
    ];
    for file_name in &file_names {
        assert!(is_hidden_name(file_name));
    }
}
#[test]
fn is_hidden_name_should_return_false() {
    let file_names = [
        "",

        ".",
        "..",
        "a",
        "ab",
        "abc",
    ];
    for file_name in &file_names {
        assert!(!is_hidden_name(file_name));
    }
}

fn is_hidden(entry: &WalkDirEntry) -> bool {
    entry
        .file_name()
        .to_str()
        .map_or(false, is_hidden_name)
}

pub fn walk_dir<P: AsRef<Path>>(root: P) -> BTreeSet<String> {
    let walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(|e| !is_hidden(e))
        .filter_map(Result::ok)
        .filter(|e| !e.file_type().is_dir())
        .collect::<Vec<WalkDirEntry>>();

    walker
        .into_iter()
        .filter_map(|e| e.path().to_str().map(|s| s.to_string()))
        .collect::<BTreeSet<String>>()
}

pub fn dirs_ordered_by_descending_depth<P: AsRef<Path>>(root: P) -> Vec<PathBuf> {
    let mut walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(|e| !is_hidden(e))
        .filter_entry(|e| e.file_type().is_dir())
        .filter_map(Result::ok)
        .collect::<Vec<WalkDirEntry>>();

    walker.sort_by(|l, r| {
        let l_depth = &l.depth();
        let r_depth = &r.depth();
        r_depth.cmp(l_depth)
    });

    walker
        .into_iter()
        .map(|e| e.path().to_path_buf())
        .collect::<Vec<PathBuf>>()
}

#[cfg(test)]
mod tests {
    use super::*;

    use std::fs::{self, File};
    use std::io::Write;
    use std::path::{Path, PathBuf};

    const D1: &'static str = "directory1";
    const D2: &'static str = "directory2";
    const D3: &'static str = "directory3";
    const F1: &'static str = "file1";
    const F2: &'static str = "file2";
    const F3: &'static str = "file3";

    fn remove_dirs_and_files() {
        let path_to_d1 = Path::new(D1);
        let path_to_f1 = Path::new(F1);

        fs::remove_dir_all(path_to_d1).ok();
        if path_to_f1.is_file() {
            fs::remove_file(path_to_f1).ok();
        }
    }

    fn create_dirs_and_files() {
        remove_dirs_and_files();

        let path_to_d1 = Path::new(D1);
        let path_to_d2 = path_to_d1.join(D2);
        let path_to_d3 = path_to_d2.join(D3);
        let path_to_f1 = Path::new(F1);
        let path_to_f2 = path_to_d1.join(F2);
        let path_to_f3 = path_to_d2.join(F3);

        fs::create_dir_all(path_to_d3).ok();

        let mut f = File::create(path_to_f1).unwrap();
        f.write("\n".as_ref()).ok();
        fs::copy(path_to_f1, path_to_f2).ok();
        fs::copy(path_to_f1, path_to_f3).ok();
    }

    #[test]
    fn path_buf_macro_should_create_path_buf() {
        let paths = [
            (Path::new("path").to_path_buf()          , path_buf!["path"              ]),
            (Path::new("path").join("to")             , path_buf!["path", "to"        ]),
            (Path::new("path").join("to").join("file"), path_buf!["path", "to", "file"]),
        ];
        for &(ref correct, ref calculated) in &paths {
            assert_eq!(correct, calculated);
        }
    }

    #[test]
    fn ls_should_return_ok() {
    }
    #[test]
    fn ls_should_return_err() {
    }

    #[test]
    fn is_empty_dir_should_return_true() {
    }
    #[test]
    fn is_empty_dir_should_return_false() {
    }

    #[test]
    fn walk_dir_should_return_b_tree_set() {
    }

    #[test]
    fn dirs_ordered_by_descending_depth_should_return_vec() {
    }
}
<commit_msg>[Test] Add simple test for ls()<commit_after>extern crate walkdir;

use self::walkdir::{DirEntry as WalkDirEntry, WalkDir, WalkDirIterator};

use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::io::Error as IoError;
use std::path::{Path, PathBuf};
use std::result::Result;

macro_rules! path_buf {
    ($($x: expr),+) => {
        PathBuf::new()
            $(.join($x))+
    };
}

pub fn ls<P: AsRef<Path>>(path: P) -> Result<Vec<String>, IoError> {
    let dirs = try!(fs::read_dir(path));
    let dirs = dirs
        .filter_map(Result::ok)
        .map(|d| d.file_name())
        .map(OsString::into_string)
        .filter_map(Result::ok)
        .collect::<Vec<String>>();
    Ok(dirs)
}

pub fn is_empty_dir<P: AsRef<Path>>(path: P) -> bool {
    match fs::read_dir(path) {
        Ok(rd) => rd.count() == 0,
        Err(_) => false,
    }
}

fn is_hidden_name(file_name: &str) -> bool {
    file_name.starts_with(".") && file_name.len() > 1 && file_name != ".."
}
#[test]
fn is_hidden_name_should_return_true() {
    let file_names = [
        ".a",
        ".ab",
        ".abc",
        "..a",
        "...",
    ];
    for file_name in &file_names {
        assert!(is_hidden_name(file_name));
    }
}
#[test]
fn is_hidden_name_should_return_false() {
    let file_names = [
        "",

        ".",
        "..",
        "a",
        "ab",
        "abc",
    ];
    for file_name in &file_names {
        assert!(!is_hidden_name(file_name));
    }
}

fn is_hidden(entry: &WalkDirEntry) -> bool {
    entry
        .file_name()
        .to_str()
        .map_or(false, is_hidden_name)
}

pub fn walk_dir<P: AsRef<Path>>(root: P) -> BTreeSet<String> {
    let walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(|e| !is_hidden(e))
        .filter_map(Result::ok)
        .filter(|e| !e.file_type().is_dir())
        .collect::<Vec<WalkDirEntry>>();

    walker
        .into_iter()
        .filter_map(|e| e.path().to_str().map(|s| s.to_string()))
        .collect::<BTreeSet<String>>()
}

pub fn dirs_ordered_by_descending_depth<P: AsRef<Path>>(root: P) -> Vec<PathBuf> {
    let mut walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(|e| !is_hidden(e))
        .filter_entry(|e| e.file_type().is_dir())
        .filter_map(Result::ok)
        .collect::<Vec<WalkDirEntry>>();

    walker.sort_by(|l, r| {
        let l_depth = &l.depth();
        let r_depth = &r.depth();
        r_depth.cmp(l_depth)
    });

    walker
        .into_iter()
        .map(|e| e.path().to_path_buf())
        .collect::<Vec<PathBuf>>()
}

#[cfg(test)]
mod tests {
    use super::*;

    use std::fs::{self, File};
    use std::io::Write;
    use std::path::{Path, PathBuf};

    const D1: &'static str = "directory1";
    const D2: &'static str = "directory2";
    const D3: &'static str = "directory3";
    const F1: &'static str = "file1";
    const F2: &'static str = "file2";

    struct TestHelper;
    impl TestHelper {
        fn path_to_d1() -> PathBuf {
            PathBuf::new().join(D1)
        }
        fn path_to_d2() -> PathBuf {
            Self::path_to_d1().join(D2)
        }
        fn path_to_d3() -> PathBuf {
            Self::path_to_d2().join(D3)
        }

        fn path_to_f1() -> PathBuf {
            Self::path_to_d1().join(F1)
        }
        fn path_to_f2() -> PathBuf {
            Self::path_to_d2().join(F2)
        }

        fn remove_dirs_and_files() {
            fs::remove_dir_all(Self::path_to_d1()).ok();
        }

        fn create_dirs_and_files() {
            Self::remove_dirs_and_files();

            fs::create_dir_all(Self::path_to_d3()).ok();

            let mut f = File::create(Self::path_to_f1()).unwrap();
            f.write("\n".as_ref()).ok();
            fs::copy(Self::path_to_f1(), Self::path_to_f2()).ok();
        }
    }

    #[test]
    fn path_buf_macro_should_create_path_buf() {
        let paths = [
            (Path::new("path").to_path_buf()          , path_buf!["path"              ]),
            (Path::new("path").join("to")             , path_buf!["path", "to"        ]),
            (Path::new("path").join("to").join("file"), path_buf!["path", "to", "file"]),
        ];
        for &(ref correct, ref calculated) in &paths {
            assert_eq!(correct, calculated);
        }
    }

    #[test]
    fn ls_should_return_ok() {
        TestHelper::create_dirs_and_files();

        let empty_vec: Vec<String> = Vec::new();

        assert_eq!(vec![D2.to_string(), F1.to_string()], ls(TestHelper::path_to_d1()).unwrap());
        assert_eq!(vec![D3.to_string(), F2.to_string()], ls(TestHelper::path_to_d2()).unwrap());
        assert_eq!(empty_vec                           , ls(TestHelper::path_to_d3()).unwrap());

        TestHelper::remove_dirs_and_files();
    }
    #[test]
    fn ls_should_return_err() {
        // need to cause permission error
    }

    #[test]
    fn is_empty_dir_should_return_true() {
    }
    #[test]
    fn is_empty_dir_should_return_false() {
    }

    #[test]
    fn walk_dir_should_return_b_tree_set() {
    }

    #[test]
    fn dirs_ordered_by_descending_depth_should_return_vec() {
    }
}
<|endoftext|>