<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::io::Read;
use std::path::PathBuf;

use email::MimeMessage;

use libimagentryref::hasher::Hasher;
use libimagentryref::hasher::DefaultHasher;
use libimagentryref::error::RefErrorKind as REK;
use libimagentryref::error::ResultExt;
use libimagentryref::error::Result as RResult;

pub struct MailHasher {
    defaulthasher: DefaultHasher,
}

impl MailHasher {

    pub fn new() -> MailHasher {
        MailHasher { defaulthasher: DefaultHasher::new() }
    }

}

impl Hasher for MailHasher {

    fn hash_name(&self) -> &'static str {
        "default_mail_hasher"
    }

    fn create_hash<R: Read>(&mut self, pb: &PathBuf, c: &mut R) -> RResult<String> {
        use filters::filter::Filter;
        use email::Header;

        let mut s = String::new();
        try!(c.read_to_string(&mut s));

        MimeMessage::parse(&s)
            .chain_err(|| REK::RefHashingError)
            .and_then(|mail| {
                let has_key = |hdr: &Header, exp: &str| hdr.name == exp;

                let subject_filter = |hdr: &Header| has_key(hdr, "Subject");
                let from_filter    = |hdr: &Header| has_key(hdr, "From");
                let to_filter      = |hdr: &Header| has_key(hdr, "To");

                let filter = subject_filter.or(from_filter).or(to_filter);

                let mut v : Vec<String> = vec![];
                for hdr in mail.headers.iter().filter(|item| filter.filter(item)) {
                    let s = try!(hdr
                        .get_value()
                        .chain_err(|| REK::RefHashingError));

                    v.push(s);
                }
                let s : String = v.join("");

                self.defaulthasher.create_hash(pb, &mut s.as_bytes())
            })
    }

}
<commit_msg>Replace uses of try!() macro with "?" operator<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::io::Read;
use std::path::PathBuf;

use email::MimeMessage;

use libimagentryref::hasher::Hasher;
use libimagentryref::hasher::DefaultHasher;
use libimagentryref::error::RefErrorKind as REK;
use libimagentryref::error::ResultExt;
use libimagentryref::error::Result as RResult;

pub struct MailHasher {
    defaulthasher: DefaultHasher,
}

impl MailHasher {

    pub fn new() -> MailHasher {
        MailHasher { defaulthasher: DefaultHasher::new() }
    }

}

impl Hasher for MailHasher {

    fn hash_name(&self) -> &'static str {
        "default_mail_hasher"
    }

    fn create_hash<R: Read>(&mut self, pb: &PathBuf, c: &mut R) -> RResult<String> {
        use filters::filter::Filter;
        use email::Header;

        let mut s = String::new();
        c.read_to_string(&mut s)?;

        MimeMessage::parse(&s)
            .chain_err(|| REK::RefHashingError)
            .and_then(|mail| {
                let has_key = |hdr: &Header, exp: &str| hdr.name == exp;

                let subject_filter = |hdr: &Header| has_key(hdr, "Subject");
                let from_filter    = |hdr: &Header| has_key(hdr, "From");
                let to_filter      = |hdr: &Header| has_key(hdr, "To");

                let filter = subject_filter.or(from_filter).or(to_filter);

                let mut v : Vec<String> = vec![];
                for hdr in mail.headers.iter().filter(|item| filter.filter(item)) {
                    let s = hdr
                        .get_value()
                        .chain_err(|| REK::RefHashingError)?;

                    v.push(s);
                }
                let s : String = v.join("");

                self.defaulthasher.create_hash(pb, &mut s.as_bytes())
            })
    }

}
<|endoftext|>


<commit_before>use structures::paging::{Page, VirtAddr, PhysFrame};
use structures::paging::page_table::{PageTable, PageTableEntry, PageTableFlags};
use registers::control::Cr3;
use ux::u9;

pub struct RecursivePageTable<'a> {
    p4: &'a mut PageTable,
    recursive_index: u9,
}

#[derive(Debug)]
pub struct NotRecursivelyMapped;

#[derive(Debug)]
pub enum MapToError {
    FrameAllocationFailed,
    EntryWithInvalidFlagsPresent,
    PageAlreadyInUse,
}

#[derive(Debug)]
pub enum UnmapError {
    EntryWithInvalidFlagsPresent(Page, PageTableEntry),
    PageNotMapped(Page),
}

impl<'a> RecursivePageTable<'a> {
    pub fn new(table: &'a mut PageTable) -> Result<Self, NotRecursivelyMapped> {
        let page = Page::containing_address(VirtAddr::new(table as *const _ as u64));
        let recursive_index = page.p4_index();

        if page.p3_index() != recursive_index || page.p2_index() != recursive_index
            || page.p1_index() != recursive_index
        {
            return Err(NotRecursivelyMapped);
        }
        if Some(Cr3::read().0) != table[recursive_index].frame() {
            return Err(NotRecursivelyMapped);
        }

        Ok(RecursivePageTable { p4: table, recursive_index })
    }

    pub fn map_to<A>(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags,
            allocator: &mut A) -> Result<(), MapToError>
        where A: FnMut() -> Option<PhysFrame>
    {
        use structures::paging::PageTableFlags as Flags;
        let p4 = &mut self.p4;

        let mut create_next_table = |entry: &mut PageTableEntry| {
            if entry.is_unused() {
                if let Some(frame) = allocator() {
                    entry.set(frame, Flags::PRESENT | Flags::WRITABLE);
                    return Ok(true);
                } else {
                    return Err(MapToError::FrameAllocationFailed);
                }
            }
            if entry.flags().contains(Flags::HUGE_PAGE) {
                return Err(MapToError::EntryWithInvalidFlagsPresent);
            }
            Ok(false)
        };

        let p3_created = create_next_table(&mut p4[page.p4_index()])?;
        let p3 = unsafe { &mut *(p3_ptr(&page, self.recursive_index)) };
        if p3_created { p3.zero() }

        let p2_created = create_next_table(&mut p3[page.p3_index()])?;
        let p2 = unsafe { &mut *(p2_ptr(&page, self.recursive_index)) };
        if p2_created { p2.zero() }

        let p1_created = create_next_table(&mut p2[page.p2_index()])?;
        let p1 = unsafe { &mut *(p1_ptr(&page, self.recursive_index)) };
        if p1_created { p1.zero() }

        if !p1[page.p1_index()].is_unused() {
            return Err(MapToError::PageAlreadyInUse);
        }
        p1[page.p1_index()].set(frame, flags);

        Ok(())
    }

    pub fn identity_map<A>(&mut self, frame: PhysFrame, flags: PageTableFlags,
            allocator: &mut A) -> Result<(), MapToError>
        where A: FnMut() -> Option<PhysFrame>
    {
        let page = Page::containing_address(VirtAddr::new(frame.start_address().as_u64()));
        self.map_to(page, frame, flags, allocator)
    }

    pub fn unmap<A>(&mut self, page: Page, allocator: &mut A) -> Result<(), UnmapError>
        where A: FnMut(PhysFrame)
    {
        use structures::paging::PageTableFlags as Flags;

        let p4 = &mut self.p4;
        let p4_entry = &p4[page.p4_index()];
        if p4_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p4_entry.flags().contains(Flags::HUGE_PAGE) {
            return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p4_entry.clone()));
        }

        let p3 = unsafe { &mut *(p3_ptr(&page, self.recursive_index)) };
        let p3_entry = &p3[page.p3_index()];
        if p3_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p3_entry.flags().contains(Flags::HUGE_PAGE) {
            return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p3_entry.clone()));
        }

        let p2 = unsafe { &mut *(p2_ptr(&page, self.recursive_index)) };
        let p2_entry = &mut p2[page.p2_index()];
        if p2_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p2_entry.flags().contains(Flags::PRESENT | Flags::HUGE_PAGE) {
            let frame = match p2_entry.frame() {
                Some(frame) => frame,
                None => return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p2_entry.clone())),
            };
            allocator(frame);
            p2_entry.set_unused();
            return Ok(());
        }

        let p1 = unsafe { &mut *(p1_ptr(&page, self.recursive_index)) };
        let p1_entry = &mut p1[page.p1_index()];
        if p1_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p1_entry.flags().contains(Flags::PRESENT) {
            let frame = match p1_entry.frame() {
                Some(frame) => frame,
                None => return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p1_entry.clone())),
            };
            allocator(frame);
            p1_entry.set_unused();
            return Ok(());
        }
        Err(UnmapError::EntryWithInvalidFlagsPresent(page, p1_entry.clone()))
    }
}

fn p4_ptr(recursive_index: u9) -> *mut PageTable {
    Page::from_page_table_indices(
        recursive_index, recursive_index, recursive_index, recursive_index,
    ).start_address().as_mut_ptr()
}

fn p3_ptr(page: &Page, recursive_index: u9) -> *mut PageTable {
    Page::from_page_table_indices(
        recursive_index, recursive_index, recursive_index, page.p4_index()
    ).start_address().as_mut_ptr()
}

fn p2_ptr(page: &Page, recursive_index: u9) -> *mut PageTable {
    Page::from_page_table_indices(
        recursive_index, recursive_index, page.p4_index(), page.p3_index()
    ).start_address().as_mut_ptr()
}

fn p1_ptr(page: &Page, recursive_index: u9) -> *mut PageTable {
    Page::from_page_table_indices(
        recursive_index, page.p4_index(), page.p3_index(), page.p2_index()
    ).start_address().as_mut_ptr()
}
<commit_msg>Remove unused p4_ptr function<commit_after>use structures::paging::{Page, VirtAddr, PhysFrame};
use structures::paging::page_table::{PageTable, PageTableEntry, PageTableFlags};
use registers::control::Cr3;
use ux::u9;

pub struct RecursivePageTable<'a> {
    p4: &'a mut PageTable,
    recursive_index: u9,
}

#[derive(Debug)]
pub struct NotRecursivelyMapped;

#[derive(Debug)]
pub enum MapToError {
    FrameAllocationFailed,
    EntryWithInvalidFlagsPresent,
    PageAlreadyInUse,
}

#[derive(Debug)]
pub enum UnmapError {
    EntryWithInvalidFlagsPresent(Page, PageTableEntry),
    PageNotMapped(Page),
}

impl<'a> RecursivePageTable<'a> {
    pub fn new(table: &'a mut PageTable) -> Result<Self, NotRecursivelyMapped> {
        let page = Page::containing_address(VirtAddr::new(table as *const _ as u64));
        let recursive_index = page.p4_index();

        if page.p3_index() != recursive_index || page.p2_index() != recursive_index
            || page.p1_index() != recursive_index
        {
            return Err(NotRecursivelyMapped);
        }
        if Some(Cr3::read().0) != table[recursive_index].frame() {
            return Err(NotRecursivelyMapped);
        }

        Ok(RecursivePageTable { p4: table, recursive_index })
    }

    pub fn map_to<A>(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags,
            allocator: &mut A) -> Result<(), MapToError>
        where A: FnMut() -> Option<PhysFrame>
    {
        use structures::paging::PageTableFlags as Flags;
        let p4 = &mut self.p4;

        let mut create_next_table = |entry: &mut PageTableEntry| {
            if entry.is_unused() {
                if let Some(frame) = allocator() {
                    entry.set(frame, Flags::PRESENT | Flags::WRITABLE);
                    return Ok(true);
                } else {
                    return Err(MapToError::FrameAllocationFailed);
                }
            }
            if entry.flags().contains(Flags::HUGE_PAGE) {
                return Err(MapToError::EntryWithInvalidFlagsPresent);
            }
            Ok(false)
        };

        let p3_created = create_next_table(&mut p4[page.p4_index()])?;
        let p3 = unsafe { &mut *(p3_ptr(&page, self.recursive_index)) };
        if p3_created { p3.zero() }

        let p2_created = create_next_table(&mut p3[page.p3_index()])?;
        let p2 = unsafe { &mut *(p2_ptr(&page, self.recursive_index)) };
        if p2_created { p2.zero() }

        let p1_created = create_next_table(&mut p2[page.p2_index()])?;
        let p1 = unsafe { &mut *(p1_ptr(&page, self.recursive_index)) };
        if p1_created { p1.zero() }

        if !p1[page.p1_index()].is_unused() {
            return Err(MapToError::PageAlreadyInUse);
        }
        p1[page.p1_index()].set(frame, flags);

        Ok(())
    }

    pub fn identity_map<A>(&mut self, frame: PhysFrame, flags: PageTableFlags,
            allocator: &mut A) -> Result<(), MapToError>
        where A: FnMut() -> Option<PhysFrame>
    {
        let page = Page::containing_address(VirtAddr::new(frame.start_address().as_u64()));
        self.map_to(page, frame, flags, allocator)
    }

    pub fn unmap<A>(&mut self, page: Page, allocator: &mut A) -> Result<(), UnmapError>
        where A: FnMut(PhysFrame)
    {
        use structures::paging::PageTableFlags as Flags;

        let p4 = &mut self.p4;
        let p4_entry = &p4[page.p4_index()];
        if p4_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p4_entry.flags().contains(Flags::HUGE_PAGE) {
            return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p4_entry.clone()));
        }

        let p3 = unsafe { &mut *(p3_ptr(&page, self.recursive_index)) };
        let p3_entry = &p3[page.p3_index()];
        if p3_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p3_entry.flags().contains(Flags::HUGE_PAGE) {
            return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p3_entry.clone()));
        }

        let p2 = unsafe { &mut *(p2_ptr(&page, self.recursive_index)) };
        let p2_entry = &mut p2[page.p2_index()];
        if p2_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p2_entry.flags().contains(Flags::PRESENT | Flags::HUGE_PAGE) {
            let frame = match p2_entry.frame() {
                Some(frame) => frame,
                None => return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p2_entry.clone())),
            };
            allocator(frame);
            p2_entry.set_unused();
            return Ok(());
        }

        let p1 = unsafe { &mut *(p1_ptr(&page, self.recursive_index)) };
        let p1_entry = &mut p1[page.p1_index()];
        if p1_entry.is_unused() { return Err(UnmapError::PageNotMapped(page)); }
        if p1_entry.flags().contains(Flags::PRESENT) {
            let frame = match p1_entry.frame() {
                Some(frame) => frame,
                None => return Err(UnmapError::EntryWithInvalidFlagsPresent(page, p1_entry.clone())),
            };
            allocator(frame);
            p1_entry.set_unused();
            return Ok(());
        }
        Err(UnmapError::EntryWithInvalidFlagsPresent(page, p1_entry.clone()))
    }
}

fn p3_ptr(page: &Page, recursive_index: u9) -> *mut PageTable {
    Page::from_page_table_indices(
        recursive_index, recursive_index, recursive_index, page.p4_index()
    ).start_address().as_mut_ptr()
}

fn p2_ptr(page: &Page, recursive_index: u9) -> *mut PageTable {
    Page::from_page_table_indices(
        recursive_index, recursive_index, page.p4_index(), page.p3_index()
    ).start_address().as_mut_ptr()
}

fn p1_ptr(page: &Page, recursive_index: u9) -> *mut PageTable {
    Page::from_page_table_indices(
        recursive_index, page.p4_index(), page.p3_index(), page.p2_index()
    ).start_address().as_mut_ptr()
}
<|endoftext|>


<commit_before>

use jeebie::disasm::metadata::{ CB_DISASM_TABLE, DISASM_TABLE };

pub struct Disassembler {
    pc: usize,
}

impl Disassembler {

    pub fn new() -> Self {
        Disassembler { pc: 0 }
    }

    pub fn rom_to_string(data: &[u8]) -> Result<String, String> {
        let mut d = Disassembler::new();
        let mut out = String::new();

        while let Ok(instr) = d.get_instruction_str(data) {
            out = out + &instr + "\n";
        }

        Ok(out)
    }

    fn get_opcode_name(&mut self, data: &[u8]) -> Result<String, String> {
        match data.get(self.pc) {
            Some(&0xCB) => {
                self.pc = self.pc.wrapping_add(1);

                if let Some(second_byte) = data.get(self.pc) {
                    Ok(String::from(CB_DISASM_TABLE[*second_byte as usize]))
                } else {
                    Err(String::from("2 Byte opcode incomplete (CB prefix)"))
                }
            },
            Some(byte) => Ok(String::from(DISASM_TABLE[*byte as usize])),
            None => Err(String::from("End of data reached")),
        }
    }

    /// Returns an instruction string with the appropriate immediate
    /// values filled in.
    pub fn get_instruction_str(&mut self, data: &[u8]) -> Result<String, String> {
        let pc = self.pc;
        let mut instr = match self.get_opcode_name(data) {
            Ok(s) => s,
            Err(s) => return Err(s),
        };

        let low = data.get(self.pc.wrapping_add(1)).map(|x| *x as u16);
        let high = data.get(self.pc.wrapping_add(2)).map(|x| (*x as u16) << 8);
        self.pc = self.pc.wrapping_add(1);

        if instr.contains("nn") {
            let immediate16 = match (low, high) {
                (Some(l), Some(h)) => h | l,
                _ => return Err(String::from("3 Byte opcode incomplete, missing immediate value"))
            };

            let nn = format!("${:04x}", immediate16);
            instr = instr.replace("nn", &nn);
            self.pc = self.pc.wrapping_add(2);
        }

        if instr.contains("n") || instr.contains("*") {
            let immediate8 = match low {
                Some(l) => l,
                None => return Err(String::from("2 Byte opcode incomplete, missing immediate value"))
            };

            let n = format!("${:02x}", immediate8);
            let n_signed = format!("{}", immediate8 as i8);

            instr = instr.replace("n", &n);
            instr = instr.replace("*", &n_signed);
            self.pc = self.pc.wrapping_add(1);
        }

        Ok(format!("{:<20}; ${:04x}", instr, pc))
    }
}

#[test]
fn test_single_instr() {
    let mut d = Disassembler::new();
    let data: [u8; 2] = [0x00, 0x07];

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("NOP"));
    assert_eq!(1, d.pc);

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("RLCA"));
    assert_eq!(2, d.pc);
}

#[test]
fn test_immediate8_instr() {
    let mut d = Disassembler::new();
    let data: [u8; 4] = [0x26, 0x07, 0x20, 0xFF];

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("LD H,$07"));
    assert_eq!(2, d.pc);

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("JR NZ,-1"));
    assert_eq!(4, d.pc);
}

#[test]
fn test_immediate16_instr() {
    let mut d = Disassembler::new();
    let data: [u8; 5] = [0x31, 0x20, 0x04, 0x00, 0x04];

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("LD SP,$0420"));
    assert_eq!(3, d.pc);

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("NOP"));
    assert_eq!(4, d.pc);

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("INC B"));
    assert_eq!(5, d.pc);
}<commit_msg>Changed Disassembler to have immutable interface<commit_after>//! A simple disassembler, useful for showing the actual assembly code and eventually debugging.

use jeebie::disasm::metadata::{ CB_DISASM_TABLE, DISASM_TABLE };
use std::cell::Cell;

/// The disassembler struct, it has internal mutable state required to disassemble a binary file
/// from start to finish, but exposes an immutable interface.
pub struct Disassembler {
    pc: Cell<usize>,
}

impl Disassembler {

    pub fn new() -> Self {
        Disassembler { pc: Cell::new(0) }
    }

    pub fn rom_to_string(data: &[u8]) -> Result<String, String> {
        let d = Disassembler::new();
        let mut out = String::new();

        while let Ok(instr) = d.get_instruction_str(data) {
            out = out + &instr + "\n";
        }

        Ok(out)
    }

    fn get_opcode_name(&self, data: &[u8]) -> Result<String, String> {
        match data.get(self.pc.get()) {
            Some(&0xCB) => {
                self.pc.set(self.pc.get().wrapping_add(1));

                if let Some(second_byte) = data.get(self.pc.get()) {
                    Ok(String::from(CB_DISASM_TABLE[*second_byte as usize]))
                } else {
                    Err(String::from("2 Byte opcode incomplete (CB prefix)"))
                }
            },
            Some(byte) => Ok(String::from(DISASM_TABLE[*byte as usize])),
            None => Err(String::from("End of data reached")),
        }
    }

    /// Returns an instruction string with the appropriate immediate
    /// values filled in.
    pub fn get_instruction_str(&self, data: &[u8]) -> Result<String, String> {
        let pc = self.pc.get();
        let mut instr = match self.get_opcode_name(data) {
            Ok(s) => s,
            Err(s) => return Err(s),
        };

        let low = data.get(self.pc.get().wrapping_add(1)).map(|x| *x as u16);
        let high = data.get(self.pc.get().wrapping_add(2)).map(|x| (*x as u16) << 8);
        self.pc.set(self.pc.get().wrapping_add(1));

        if instr.contains("nn") {
            let immediate16 = match (low, high) {
                (Some(l), Some(h)) => h | l,
                _ => return Err(String::from("3 Byte opcode incomplete, missing immediate value"))
            };

            let nn = format!("${:04x}", immediate16);
            instr = instr.replace("nn", &nn);
            self.pc.set(self.pc.get().wrapping_add(2));
        }

        if instr.contains("n") || instr.contains("*") {
            let immediate8 = match low {
                Some(l) => l,
                None => return Err(String::from("2 Byte opcode incomplete, missing immediate value"))
            };

            let n = format!("${:02x}", immediate8);
            let n_signed = format!("{}", immediate8 as i8);

            instr = instr.replace("n", &n);
            instr = instr.replace("*", &n_signed);
            self.pc.set(self.pc.get().wrapping_add(1));
        }

        Ok(format!("{:<20}; ${:04x}", instr, pc))
    }
}

#[test]
fn test_single_instr() {
    let d = Disassembler::new();
    let data: [u8; 2] = [0x00, 0x07];

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("NOP"));
    assert_eq!(1, d.pc.get());

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("RLCA"));
    assert_eq!(2, d.pc.get());
}

#[test]
fn test_immediate8_instr() {
    let d = Disassembler::new();
    let data: [u8; 4] = [0x26, 0x07, 0x20, 0xFF];

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("LD H,$07"));
    assert_eq!(2, d.pc.get());

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("JR NZ,-1"));
    assert_eq!(4, d.pc.get());
}

#[test]
fn test_immediate16_instr() {
    let d = Disassembler::new();
    let data: [u8; 5] = [0x31, 0x20, 0x04, 0x00, 0x04];

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("LD SP,$0420"));
    assert_eq!(3, d.pc.get());

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("NOP"));
    assert_eq!(4, d.pc.get());

    let instr = d.get_instruction_str(&data).unwrap();
    assert!(instr.starts_with("INC B"));
    assert_eq!(5, d.pc.get());
}<|endoftext|>


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

// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
// * Functions called by the compiler itself.

pub use self::LangItem::*;

use dep_graph::DepNode;
use hir::map as hir_map;
use session::Session;
use middle::cstore::CrateStore;
use hir::def_id::DefId;
use ty;
use middle::weak_lang_items;
use util::nodemap::FnvHashMap;

use syntax::ast;
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::InternedString;
use hir::intravisit::Visitor;
use hir;

// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! lets_do_this {
    (
        $( $variant:ident, $name:expr, $method:ident; )*
    ) => {

enum_from_u32! {
    #[derive(Copy, Clone, PartialEq, Eq, Hash)]
    pub enum LangItem {
        $($variant,)*
    }
}

pub struct LanguageItems {
    pub items: Vec<Option<DefId>>,
    pub missing: Vec<LangItem>,
}

impl LanguageItems {
    pub fn new() -> LanguageItems {
        fn foo(_: LangItem) -> Option<DefId> { None }

        LanguageItems {
            items: vec!($(foo($variant)),*),
            missing: Vec::new(),
        }
    }

    pub fn items(&self) -> &[Option<DefId>] {
        &*self.items
    }

    pub fn item_name(index: usize) -> &'static str {
        let item: Option<LangItem> = LangItem::from_u32(index as u32);
        match item {
            $( Some($variant) => $name, )*
            None => "???"
        }
    }

    pub fn require(&self, it: LangItem) -> Result<DefId, String> {
        match self.items[it as usize] {
            Some(id) => Ok(id),
            None => {
                Err(format!("requires `{}` lang_item",
                            LanguageItems::item_name(it as usize)))
            }
        }
    }

    pub fn require_owned_box(&self) -> Result<DefId, String> {
        self.require(OwnedBoxLangItem)
    }

    pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
                             -> Result<DefId, String>
    {
        match bound {
            ty::BoundSend => self.require(SendTraitLangItem),
            ty::BoundSized => self.require(SizedTraitLangItem),
            ty::BoundCopy => self.require(CopyTraitLangItem),
            ty::BoundSync => self.require(SyncTraitLangItem),
        }
    }

    pub fn to_builtin_kind(&self, id: DefId) -> Option<ty::BuiltinBound> {
        if Some(id) == self.send_trait() {
            Some(ty::BoundSend)
        } else if Some(id) == self.sized_trait() {
            Some(ty::BoundSized)
        } else if Some(id) == self.copy_trait() {
            Some(ty::BoundCopy)
        } else if Some(id) == self.sync_trait() {
            Some(ty::BoundSync)
        } else {
            None
        }
    }

    pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
        let def_id_kinds = [
            (self.fn_trait(), ty::ClosureKind::Fn),
            (self.fn_mut_trait(), ty::ClosureKind::FnMut),
            (self.fn_once_trait(), ty::ClosureKind::FnOnce),
            ];

        for &(opt_def_id, kind) in &def_id_kinds {
            if Some(id) == opt_def_id {
                return Some(kind);
            }
        }

        None
    }

    $(
        #[allow(dead_code)]
        pub fn $method(&self) -> Option<DefId> {
            self.items[$variant as usize]
        }
    )*
}

struct LanguageItemCollector<'a, 'tcx: 'a> {
    items: LanguageItems,

    ast_map: &'a hir_map::Map<'tcx>,

    session: &'a Session,

    item_refs: FnvHashMap<&'static str, usize>,
}

impl<'a, 'v, 'tcx> Visitor<'v> for LanguageItemCollector<'a, 'tcx> {
    fn visit_item(&mut self, item: &hir::Item) {
        if let Some(value) = extract(&item.attrs) {
            let item_index = self.item_refs.get(&value[..]).cloned();

            if let Some(item_index) = item_index {
                self.collect_item(item_index, self.ast_map.local_def_id(item.id))
            } else {
                let span = self.ast_map.span(item.id);
                span_err!(self.session, span, E0522,
                          "definition of an unknown language item: `{}`.",
                          &value[..]);
            }
        }
    }
}

impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
    pub fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>)
               -> LanguageItemCollector<'a, 'tcx> {
        let mut item_refs = FnvHashMap();

        $( item_refs.insert($name, $variant as usize); )*

        LanguageItemCollector {
            session: session,
            ast_map: ast_map,
            items: LanguageItems::new(),
            item_refs: item_refs,
        }
    }

    pub fn collect_item(&mut self, item_index: usize,
                        item_def_id: DefId) {
        // Check for duplicates.
        match self.items.items[item_index] {
            Some(original_def_id) if original_def_id != item_def_id => {
                let cstore = &self.session.cstore;
                let span = self.ast_map.span_if_local(item_def_id)
                                       .expect("we should have found local duplicate earlier");
                let mut err = struct_span_err!(self.session,
                                               span,
                                               E0152,
                                               "duplicate lang item found: `{}`.",
                                               LanguageItems::item_name(item_index));
                if let Some(span) = self.ast_map.span_if_local(original_def_id) {
                    span_note!(&mut err, span,
                               "first defined here.");
                } else {
                    err.note(&format!("first defined in crate `{}`.",
                                      cstore.crate_name(original_def_id.krate)));
                }
                err.emit();
            }
            _ => {
                // OK.
            }
        }

        // Matched.
        self.items.items[item_index] = Some(item_def_id);
    }

    pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
        krate.visit_all_items(self);
    }

    pub fn collect_external_language_items(&mut self) {
        let cstore = &self.session.cstore;

        for cnum in cstore.crates() {
            for (index, item_index) in cstore.lang_items(cnum) {
                let def_id = DefId { krate: cnum, index: index };
                self.collect_item(item_index, def_id);
            }
        }
    }

    pub fn collect(&mut self, krate: &hir::Crate) {
        self.collect_external_language_items();
        self.collect_local_language_items(krate);
    }
}

pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
    for attribute in attrs {
        match attribute.value_str() {
            Some(ref value) if attribute.check_name("lang") => {
                return Some(value.clone());
            }
            _ => {}
        }
    }

    return None;
}

pub fn collect_language_items(session: &Session,
                              map: &hir_map::Map)
                              -> LanguageItems {
    let _task = map.dep_graph.in_task(DepNode::CollectLanguageItems);
    let krate: &hir::Crate = map.krate();
    let mut collector = LanguageItemCollector::new(session, map);
    collector.collect(krate);
    let LanguageItemCollector { mut items, .. } = collector;
    weak_lang_items::check_crate(krate, session, &mut items);
    items
}

// End of the macro
    }
}

lets_do_this! {
//  Variant name,                    Name,                      Method name;
    CharImplItem,                    "char",                    char_impl;
    StrImplItem,                     "str",                     str_impl;
    SliceImplItem,                   "slice",                   slice_impl;
    ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
    MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
    I8ImplItem,                      "i8",                      i8_impl;
    I16ImplItem,                     "i16",                     i16_impl;
    I32ImplItem,                     "i32",                     i32_impl;
    I64ImplItem,                     "i64",                     i64_impl;
    IsizeImplItem,                   "isize",                   isize_impl;
    U8ImplItem,                      "u8",                      u8_impl;
    U16ImplItem,                     "u16",                     u16_impl;
    U32ImplItem,                     "u32",                     u32_impl;
    U64ImplItem,                     "u64",                     u64_impl;
    UsizeImplItem,                   "usize",                   usize_impl;
    F32ImplItem,                     "f32",                     f32_impl;
    F64ImplItem,                     "f64",                     f64_impl;

    SendTraitLangItem,               "send",                    send_trait;
    SizedTraitLangItem,              "sized",                   sized_trait;
    UnsizeTraitLangItem,             "unsize",                  unsize_trait;
    CopyTraitLangItem,               "copy",                    copy_trait;
    SyncTraitLangItem,               "sync",                    sync_trait;

    DropTraitLangItem,               "drop",                    drop_trait;

    CoerceUnsizedTraitLangItem,      "coerce_unsized",          coerce_unsized_trait;

    AddTraitLangItem,                "add",                     add_trait;
    SubTraitLangItem,                "sub",                     sub_trait;
    MulTraitLangItem,                "mul",                     mul_trait;
    DivTraitLangItem,                "div",                     div_trait;
    RemTraitLangItem,                "rem",                     rem_trait;
    NegTraitLangItem,                "neg",                     neg_trait;
    NotTraitLangItem,                "not",                     not_trait;
    BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
    BitAndTraitLangItem,             "bitand",                  bitand_trait;
    BitOrTraitLangItem,              "bitor",                   bitor_trait;
    ShlTraitLangItem,                "shl",                     shl_trait;
    ShrTraitLangItem,                "shr",                     shr_trait;
    AddAssignTraitLangItem,          "add_assign",              add_assign_trait;
    SubAssignTraitLangItem,          "sub_assign",              sub_assign_trait;
    MulAssignTraitLangItem,          "mul_assign",              mul_assign_trait;
    DivAssignTraitLangItem,          "div_assign",              div_assign_trait;
    RemAssignTraitLangItem,          "rem_assign",              rem_assign_trait;
    BitXorAssignTraitLangItem,       "bitxor_assign",           bitxor_assign_trait;
    BitAndAssignTraitLangItem,       "bitand_assign",           bitand_assign_trait;
    BitOrAssignTraitLangItem,        "bitor_assign",            bitor_assign_trait;
    ShlAssignTraitLangItem,          "shl_assign",              shl_assign_trait;
    ShrAssignTraitLangItem,          "shr_assign",              shr_assign_trait;
    IndexTraitLangItem,              "index",                   index_trait;
    IndexMutTraitLangItem,           "index_mut",               index_mut_trait;

    UnsafeCellTypeLangItem,          "unsafe_cell",             unsafe_cell_type;

    DerefTraitLangItem,              "deref",                   deref_trait;
    DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;

    FnTraitLangItem,                 "fn",                      fn_trait;
    FnMutTraitLangItem,              "fn_mut",                  fn_mut_trait;
    FnOnceTraitLangItem,             "fn_once",                 fn_once_trait;

    EqTraitLangItem,                 "eq",                      eq_trait;
    OrdTraitLangItem,                "ord",                     ord_trait;

    StrEqFnLangItem,                 "str_eq",                  str_eq_fn;

    // A number of panic-related lang items. The `panic` item corresponds to
    // divide-by-zero and various panic cases with `match`. The
    // `panic_bounds_check` item is for indexing arrays.
    //
    // The `begin_unwind` lang item has a predefined symbol name and is sort of
    // a "weak lang item" in the sense that a crate is not required to have it
    // defined to use it, but a final product is required to define it
    // somewhere. Additionally, there are restrictions on crates that use a weak
    // lang item, but do not have it defined.
    PanicFnLangItem,                 "panic",                   panic_fn;
    PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
    PanicFmtLangItem,                "panic_fmt",               panic_fmt;

    ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
    ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
    BoxFreeFnLangItem,               "box_free",                box_free_fn;
    StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;

    StartFnLangItem,                 "start",                   start_fn;

    EhPersonalityLangItem,           "eh_personality",          eh_personality;
    EhPersonalityCatchLangItem,      "eh_personality_catch",    eh_personality_catch;
    EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
    MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;

    OwnedBoxLangItem,                "owned_box",               owned_box;

    PhantomDataItem,                 "phantom_data",            phantom_data;

    // Deprecated:
    CovariantTypeItem,               "covariant_type",          covariant_type;
    ContravariantTypeItem,           "contravariant_type",      contravariant_type;
    InvariantTypeItem,               "invariant_type",          invariant_type;
    CovariantLifetimeItem,           "covariant_lifetime",      covariant_lifetime;
    ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
    InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;

    NoCopyItem,                      "no_copy_bound",           no_copy_bound;

    NonZeroItem,                     "non_zero",                non_zero;

    DebugTraitLangItem,              "debug_trait",             debug_trait;
}
<commit_msg>Rollup merge of #32970 - taralx:patch-2, r=alexcrichton<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
// * Functions called by the compiler itself.

pub use self::LangItem::*;

use dep_graph::DepNode;
use hir::map as hir_map;
use session::Session;
use middle::cstore::CrateStore;
use hir::def_id::DefId;
use ty;
use middle::weak_lang_items;
use util::nodemap::FnvHashMap;

use syntax::ast;
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::InternedString;
use hir::intravisit::Visitor;
use hir;

// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! lets_do_this {
    (
        $( $variant:ident, $name:expr, $method:ident; )*
    ) => {

enum_from_u32! {
    #[derive(Copy, Clone, PartialEq, Eq, Hash)]
    pub enum LangItem {
        $($variant,)*
    }
}

pub struct LanguageItems {
    pub items: Vec<Option<DefId>>,
    pub missing: Vec<LangItem>,
}

impl LanguageItems {
    pub fn new() -> LanguageItems {
        fn foo(_: LangItem) -> Option<DefId> { None }

        LanguageItems {
            items: vec!($(foo($variant)),*),
            missing: Vec::new(),
        }
    }

    pub fn items(&self) -> &[Option<DefId>] {
        &*self.items
    }

    pub fn item_name(index: usize) -> &'static str {
        let item: Option<LangItem> = LangItem::from_u32(index as u32);
        match item {
            $( Some($variant) => $name, )*
            None => "???"
        }
    }

    pub fn require(&self, it: LangItem) -> Result<DefId, String> {
        match self.items[it as usize] {
            Some(id) => Ok(id),
            None => {
                Err(format!("requires `{}` lang_item",
                            LanguageItems::item_name(it as usize)))
            }
        }
    }

    pub fn require_owned_box(&self) -> Result<DefId, String> {
        self.require(OwnedBoxLangItem)
    }

    pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
                             -> Result<DefId, String>
    {
        match bound {
            ty::BoundSend => self.require(SendTraitLangItem),
            ty::BoundSized => self.require(SizedTraitLangItem),
            ty::BoundCopy => self.require(CopyTraitLangItem),
            ty::BoundSync => self.require(SyncTraitLangItem),
        }
    }

    pub fn to_builtin_kind(&self, id: DefId) -> Option<ty::BuiltinBound> {
        if Some(id) == self.send_trait() {
            Some(ty::BoundSend)
        } else if Some(id) == self.sized_trait() {
            Some(ty::BoundSized)
        } else if Some(id) == self.copy_trait() {
            Some(ty::BoundCopy)
        } else if Some(id) == self.sync_trait() {
            Some(ty::BoundSync)
        } else {
            None
        }
    }

    pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
        let def_id_kinds = [
            (self.fn_trait(), ty::ClosureKind::Fn),
            (self.fn_mut_trait(), ty::ClosureKind::FnMut),
            (self.fn_once_trait(), ty::ClosureKind::FnOnce),
            ];

        for &(opt_def_id, kind) in &def_id_kinds {
            if Some(id) == opt_def_id {
                return Some(kind);
            }
        }

        None
    }

    $(
        #[allow(dead_code)]
        pub fn $method(&self) -> Option<DefId> {
            self.items[$variant as usize]
        }
    )*
}

struct LanguageItemCollector<'a, 'tcx: 'a> {
    items: LanguageItems,

    ast_map: &'a hir_map::Map<'tcx>,

    session: &'a Session,

    item_refs: FnvHashMap<&'static str, usize>,
}

impl<'a, 'v, 'tcx> Visitor<'v> for LanguageItemCollector<'a, 'tcx> {
    fn visit_item(&mut self, item: &hir::Item) {
        if let Some(value) = extract(&item.attrs) {
            let item_index = self.item_refs.get(&value[..]).cloned();

            if let Some(item_index) = item_index {
                self.collect_item(item_index, self.ast_map.local_def_id(item.id))
            } else {
                let span = self.ast_map.span(item.id);
                span_err!(self.session, span, E0522,
                          "definition of an unknown language item: `{}`.",
                          &value[..]);
            }
        }
    }
}

impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
    pub fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>)
               -> LanguageItemCollector<'a, 'tcx> {
        let mut item_refs = FnvHashMap();

        $( item_refs.insert($name, $variant as usize); )*

        LanguageItemCollector {
            session: session,
            ast_map: ast_map,
            items: LanguageItems::new(),
            item_refs: item_refs,
        }
    }

    pub fn collect_item(&mut self, item_index: usize,
                        item_def_id: DefId) {
        // Check for duplicates.
        match self.items.items[item_index] {
            Some(original_def_id) if original_def_id != item_def_id => {
                let cstore = &self.session.cstore;
                let name = LanguageItems::item_name(item_index);
                let mut err = match self.ast_map.span_if_local(item_def_id) {
                    Some(span) => struct_span_err!(
                        self.session,
                        span,
                        E0152,
                        "duplicate lang item found: `{}`.",
                        name),
                    None => self.session.struct_err(&format!(
                            "duplicate lang item in crate `{}`: `{}`.",
                            cstore.crate_name(item_def_id.krate),
                            name)),
                };
                if let Some(span) = self.ast_map.span_if_local(original_def_id) {
                    span_note!(&mut err, span,
                               "first defined here.");
                } else {
                    err.note(&format!("first defined in crate `{}`.",
                                      cstore.crate_name(original_def_id.krate)));
                }
                err.emit();
            }
            _ => {
                // OK.
            }
        }

        // Matched.
        self.items.items[item_index] = Some(item_def_id);
    }

    pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
        krate.visit_all_items(self);
    }

    pub fn collect_external_language_items(&mut self) {
        let cstore = &self.session.cstore;

        for cnum in cstore.crates() {
            for (index, item_index) in cstore.lang_items(cnum) {
                let def_id = DefId { krate: cnum, index: index };
                self.collect_item(item_index, def_id);
            }
        }
    }

    pub fn collect(&mut self, krate: &hir::Crate) {
        self.collect_external_language_items();
        self.collect_local_language_items(krate);
    }
}

pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
    for attribute in attrs {
        match attribute.value_str() {
            Some(ref value) if attribute.check_name("lang") => {
                return Some(value.clone());
            }
            _ => {}
        }
    }

    return None;
}

pub fn collect_language_items(session: &Session,
                              map: &hir_map::Map)
                              -> LanguageItems {
    let _task = map.dep_graph.in_task(DepNode::CollectLanguageItems);
    let krate: &hir::Crate = map.krate();
    let mut collector = LanguageItemCollector::new(session, map);
    collector.collect(krate);
    let LanguageItemCollector { mut items, .. } = collector;
    weak_lang_items::check_crate(krate, session, &mut items);
    items
}

// End of the macro
    }
}

lets_do_this! {
//  Variant name,                    Name,                      Method name;
    CharImplItem,                    "char",                    char_impl;
    StrImplItem,                     "str",                     str_impl;
    SliceImplItem,                   "slice",                   slice_impl;
    ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
    MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
    I8ImplItem,                      "i8",                      i8_impl;
    I16ImplItem,                     "i16",                     i16_impl;
    I32ImplItem,                     "i32",                     i32_impl;
    I64ImplItem,                     "i64",                     i64_impl;
    IsizeImplItem,                   "isize",                   isize_impl;
    U8ImplItem,                      "u8",                      u8_impl;
    U16ImplItem,                     "u16",                     u16_impl;
    U32ImplItem,                     "u32",                     u32_impl;
    U64ImplItem,                     "u64",                     u64_impl;
    UsizeImplItem,                   "usize",                   usize_impl;
    F32ImplItem,                     "f32",                     f32_impl;
    F64ImplItem,                     "f64",                     f64_impl;

    SendTraitLangItem,               "send",                    send_trait;
    SizedTraitLangItem,              "sized",                   sized_trait;
    UnsizeTraitLangItem,             "unsize",                  unsize_trait;
    CopyTraitLangItem,               "copy",                    copy_trait;
    SyncTraitLangItem,               "sync",                    sync_trait;

    DropTraitLangItem,               "drop",                    drop_trait;

    CoerceUnsizedTraitLangItem,      "coerce_unsized",          coerce_unsized_trait;

    AddTraitLangItem,                "add",                     add_trait;
    SubTraitLangItem,                "sub",                     sub_trait;
    MulTraitLangItem,                "mul",                     mul_trait;
    DivTraitLangItem,                "div",                     div_trait;
    RemTraitLangItem,                "rem",                     rem_trait;
    NegTraitLangItem,                "neg",                     neg_trait;
    NotTraitLangItem,                "not",                     not_trait;
    BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
    BitAndTraitLangItem,             "bitand",                  bitand_trait;
    BitOrTraitLangItem,              "bitor",                   bitor_trait;
    ShlTraitLangItem,                "shl",                     shl_trait;
    ShrTraitLangItem,                "shr",                     shr_trait;
    AddAssignTraitLangItem,          "add_assign",              add_assign_trait;
    SubAssignTraitLangItem,          "sub_assign",              sub_assign_trait;
    MulAssignTraitLangItem,          "mul_assign",              mul_assign_trait;
    DivAssignTraitLangItem,          "div_assign",              div_assign_trait;
    RemAssignTraitLangItem,          "rem_assign",              rem_assign_trait;
    BitXorAssignTraitLangItem,       "bitxor_assign",           bitxor_assign_trait;
    BitAndAssignTraitLangItem,       "bitand_assign",           bitand_assign_trait;
    BitOrAssignTraitLangItem,        "bitor_assign",            bitor_assign_trait;
    ShlAssignTraitLangItem,          "shl_assign",              shl_assign_trait;
    ShrAssignTraitLangItem,          "shr_assign",              shr_assign_trait;
    IndexTraitLangItem,              "index",                   index_trait;
    IndexMutTraitLangItem,           "index_mut",               index_mut_trait;

    UnsafeCellTypeLangItem,          "unsafe_cell",             unsafe_cell_type;

    DerefTraitLangItem,              "deref",                   deref_trait;
    DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;

    FnTraitLangItem,                 "fn",                      fn_trait;
    FnMutTraitLangItem,              "fn_mut",                  fn_mut_trait;
    FnOnceTraitLangItem,             "fn_once",                 fn_once_trait;

    EqTraitLangItem,                 "eq",                      eq_trait;
    OrdTraitLangItem,                "ord",                     ord_trait;

    StrEqFnLangItem,                 "str_eq",                  str_eq_fn;

    // A number of panic-related lang items. The `panic` item corresponds to
    // divide-by-zero and various panic cases with `match`. The
    // `panic_bounds_check` item is for indexing arrays.
    //
    // The `begin_unwind` lang item has a predefined symbol name and is sort of
    // a "weak lang item" in the sense that a crate is not required to have it
    // defined to use it, but a final product is required to define it
    // somewhere. Additionally, there are restrictions on crates that use a weak
    // lang item, but do not have it defined.
    PanicFnLangItem,                 "panic",                   panic_fn;
    PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
    PanicFmtLangItem,                "panic_fmt",               panic_fmt;

    ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
    ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
    BoxFreeFnLangItem,               "box_free",                box_free_fn;
    StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;

    StartFnLangItem,                 "start",                   start_fn;

    EhPersonalityLangItem,           "eh_personality",          eh_personality;
    EhPersonalityCatchLangItem,      "eh_personality_catch",    eh_personality_catch;
    EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
    MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;

    OwnedBoxLangItem,                "owned_box",               owned_box;

    PhantomDataItem,                 "phantom_data",            phantom_data;

    // Deprecated:
    CovariantTypeItem,               "covariant_type",          covariant_type;
    ContravariantTypeItem,           "contravariant_type",      contravariant_type;
    InvariantTypeItem,               "invariant_type",          invariant_type;
    CovariantLifetimeItem,           "covariant_lifetime",      covariant_lifetime;
    ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
    InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;

    NoCopyItem,                      "no_copy_bound",           no_copy_bound;

    NonZeroItem,                     "non_zero",                non_zero;

    DebugTraitLangItem,              "debug_trait",             debug_trait;
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::rand;
use std::rand::Rng;
use cgmath::vector::{Vector3, Vector, EuclideanVector};
use visualizer::geom;
use core::types::{MapPos, UnitId};
use core::game_state::GameState;
use core::core;
use visualizer::mesh::{MeshId};
use visualizer::scene::{
    Scene,
    SceneNode,
    NodeId,
    MIN_MARKER_NODE_ID,
    SHELL_NODE_ID,
};
use visualizer::types::{MFloat, WorldPos, Time};
use visualizer::unit_type_visual_info::{UnitTypeVisualInfo};

fn unit_id_to_node_id(unit_id: UnitId) -> NodeId {
    NodeId{id: unit_id.id}
}

fn marker_id(unit_id: UnitId) -> NodeId {
    NodeId{id: MIN_MARKER_NODE_ID.id + unit_id.id}
}

pub trait EventVisualizer {
    fn is_finished(&self) -> bool;
    fn draw(&mut self, scene: &mut Scene, dtime: Time);
    fn end(&mut self, scene: &mut Scene, state: &GameState);
}

pub struct EventMoveVisualizer {
    unit_id: UnitId,
    path: Vec<WorldPos>,
    move: MoveHelper,
    speed: MFloat,
}

impl EventVisualizer for EventMoveVisualizer {
    fn is_finished(&self) -> bool {
        self.path.len() == 1
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let pos = self.move.step(dtime);
        {
            let marker_node = scene.nodes.get_mut(&marker_id(self.unit_id));
            marker_node.pos.v = pos.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0));
        }
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = pos;
        if self.move.is_finished() {
            let _ = self.path.remove(0);
            if self.path.len() > 1 {
                self.update_waypoint(node);
            }
            node.pos = self.current_waypoint();
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        assert!(self.path.len() == 1);
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.current_waypoint();
    }
}

impl EventMoveVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        unit_id: UnitId,
        unit_type_visual_info: &UnitTypeVisualInfo,
        path: Vec<MapPos>
    ) -> Box<EventVisualizer> {
        let mut world_path = Vec::new();
        for map_pos in path.iter() {
            let world_pos = geom::map_pos_to_world_pos(*map_pos);
            world_path.push(world_pos);
        }
        let speed = unit_type_visual_info.move_speed;
        let node_id = unit_id_to_node_id(unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.rot = geom::get_rot_angle(
            world_path[0], world_path[1]);
        let move = MoveHelper::new(
            world_path[0], world_path[1], speed);
        let mut vis = box EventMoveVisualizer {
            unit_id: unit_id,
            path: world_path,
            move: move,
            speed: speed,
        };
        vis.update_waypoint(node);
        vis as Box<EventVisualizer>
    }

    fn update_waypoint(&mut self, node: &mut SceneNode) {
        self.move = MoveHelper::new(
            self.current_waypoint(),
            self.next_waypoint(),
            self.speed,
        );
        node.rot = geom::get_rot_angle(
            self.current_waypoint(),
            self.next_waypoint()
        );
    }

    fn current_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 1);
        self.path[0]
    }

    fn next_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 2);
        self.path[1]
    }
}

pub struct EventEndTurnVisualizer;

impl EventEndTurnVisualizer {
    pub fn new() -> Box<EventVisualizer> {
        box EventEndTurnVisualizer as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventEndTurnVisualizer {
    fn is_finished(&self) -> bool {
        true
    }

    fn draw(&mut self, _: &mut Scene, _: Time) {}

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct EventCreateUnitVisualizer {
    id: UnitId,
    move: MoveHelper,
}

// TODO: use generic algorithm
fn get_unit_scene_nodes(
    core: &core::Core,
    type_id: core::UnitTypeId,
    mesh_id: MeshId,
) -> Vec<SceneNode> {
    let count = core.get_unit_type(type_id).count;
    match count {
        1 => vec![
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.0, y: 0.0, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
        ],
        4 => vec![
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.2, y: 0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: 0.2, y: -0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: -0.2, y: 0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
            SceneNode {
                pos: WorldPos{v: Vector3{x: -0.2, y: -0.2, z: 0.0}},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            },
        ],
        _ => fail!("TODO: not implemented"),
    }
}

impl EventCreateUnitVisualizer {
    pub fn new(
        core: &core::Core,
        scene: &mut Scene,
        _: &GameState,
        id: UnitId,
        type_id: core::UnitTypeId,
        pos: MapPos,
        mesh_id: MeshId,
        marker_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(id);
        let world_pos = geom::map_pos_to_world_pos(pos);
        let to = world_pos;
        let from = WorldPos{v: to.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let rot = rand::task_rng().gen_range::<MFloat>(0.0, 360.0);
        scene.nodes.insert(node_id, SceneNode {
            pos: from,
            rot: rot,
            mesh_id: None,
            children: get_unit_scene_nodes(core, type_id, mesh_id),
        });
        scene.nodes.insert(marker_id(id), SceneNode {
            pos: WorldPos{v: to.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))},
            rot: 0.0,
            mesh_id: Some(marker_mesh_id),
            children: Vec::new(),
        });
        let move = MoveHelper::new(from, to, 1.0);
        box EventCreateUnitVisualizer {
            id: id,
            move: move,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventCreateUnitVisualizer {
    fn is_finished(&self) -> bool {
        self.move.is_finished()
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let node_id = unit_id_to_node_id(self.id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.move.step(dtime);
    }

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct MoveHelper {
    to: WorldPos,
    current: WorldPos,
    dist: MFloat,
    current_dist: MFloat,
    dir: Vector3<MFloat>,
}

impl MoveHelper {
    pub fn new(
        from: WorldPos,
        to: WorldPos,
        speed: MFloat
    ) -> MoveHelper {
        let dir = to.v.sub_v(&from.v).normalize();
        let dist = geom::dist(from, to);
        MoveHelper {
            to: to,
            current: from,
            dist: dist,
            current_dist: 0.0,
            dir: dir.mul_s(speed),
        }
    }

    pub fn is_finished(&self) -> bool {
        self.current_dist >= self.dist
    }

    pub fn step(&mut self, dtime: Time) -> WorldPos {
        let dt = dtime.n as MFloat / 1000000000.0;
        let step = self.dir.mul_s(dt);
        self.current_dist += step.length();
        self.current.v.add_self_v(&step);
        if self.is_finished() {
            self.current = self.to;
        }
        self.current
    }
}

fn vec3_z(z: MFloat) -> Vector3<MFloat> {
    Vector3{x: 0.0, y: 0.0, z: z}
}

pub struct EventAttackUnitVisualizer {
    defender_id: UnitId,
    killed: bool,
    move: MoveHelper,
    shell_move: MoveHelper,
}

impl EventAttackUnitVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        attacker_id: UnitId,
        defender_id: UnitId,
        killed: bool,
        shell_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(defender_id);
        let from = scene.nodes.get(&node_id).pos;
        let to = WorldPos{v: from.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let move = MoveHelper::new(from, to, 1.0);
        let shell_move = {
            let from = scene.nodes.get(&unit_id_to_node_id(attacker_id)).pos;
            let to = scene.nodes.get(&unit_id_to_node_id(defender_id)).pos;
            scene.nodes.insert(SHELL_NODE_ID, SceneNode {
                pos: from,
                rot: 0.0,
                mesh_id: Some(shell_mesh_id),
                children: Vec::new(),
            });
            MoveHelper::new(from, to, 10.0)
        };
        box EventAttackUnitVisualizer {
            defender_id: defender_id,
            killed: killed,
            move: move,
            shell_move: shell_move,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventAttackUnitVisualizer {
    fn is_finished(&self) -> bool {
        if self.killed {
            self.move.is_finished()
        } else {
            self.shell_move.is_finished()
        }
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        scene.nodes.get_mut(&SHELL_NODE_ID).pos = self.shell_move.step(dtime);
        if self.killed {
            if self.shell_move.is_finished() {
                let node_id = unit_id_to_node_id(self.defender_id);
                scene.nodes.get_mut(&node_id).pos = self.move.step(dtime);
            }
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        if self.killed {
            let node_id = unit_id_to_node_id(self.defender_id);
            scene.nodes.remove(&node_id);
            scene.nodes.remove(&marker_id(self.defender_id));
        }
        scene.nodes.remove(&SHELL_NODE_ID);
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>visualizer/event_visualizer.rs: get_unit_scene_nodes(): Generic algorithm<commit_after>// See LICENSE file for copyright and license details.

use std::rand;
use std::rand::Rng;
use cgmath::vector::{Vector3, Vector, EuclideanVector};
use visualizer::geom;
use core::types::{MapPos, UnitId};
use core::game_state::GameState;
use core::core;
use visualizer::mesh::{MeshId};
use visualizer::scene::{
    Scene,
    SceneNode,
    NodeId,
    MIN_MARKER_NODE_ID,
    SHELL_NODE_ID,
};
use visualizer::types::{MFloat, WorldPos, Time};
use visualizer::unit_type_visual_info::{UnitTypeVisualInfo};

fn unit_id_to_node_id(unit_id: UnitId) -> NodeId {
    NodeId{id: unit_id.id}
}

fn marker_id(unit_id: UnitId) -> NodeId {
    NodeId{id: MIN_MARKER_NODE_ID.id + unit_id.id}
}

pub trait EventVisualizer {
    fn is_finished(&self) -> bool;
    fn draw(&mut self, scene: &mut Scene, dtime: Time);
    fn end(&mut self, scene: &mut Scene, state: &GameState);
}

pub struct EventMoveVisualizer {
    unit_id: UnitId,
    path: Vec<WorldPos>,
    move: MoveHelper,
    speed: MFloat,
}

impl EventVisualizer for EventMoveVisualizer {
    fn is_finished(&self) -> bool {
        self.path.len() == 1
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let pos = self.move.step(dtime);
        {
            let marker_node = scene.nodes.get_mut(&marker_id(self.unit_id));
            marker_node.pos.v = pos.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0));
        }
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = pos;
        if self.move.is_finished() {
            let _ = self.path.remove(0);
            if self.path.len() > 1 {
                self.update_waypoint(node);
            }
            node.pos = self.current_waypoint();
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        assert!(self.path.len() == 1);
        let node_id = unit_id_to_node_id(self.unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.current_waypoint();
    }
}

impl EventMoveVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        unit_id: UnitId,
        unit_type_visual_info: &UnitTypeVisualInfo,
        path: Vec<MapPos>
    ) -> Box<EventVisualizer> {
        let mut world_path = Vec::new();
        for map_pos in path.iter() {
            let world_pos = geom::map_pos_to_world_pos(*map_pos);
            world_path.push(world_pos);
        }
        let speed = unit_type_visual_info.move_speed;
        let node_id = unit_id_to_node_id(unit_id);
        let node = scene.nodes.get_mut(&node_id);
        node.rot = geom::get_rot_angle(
            world_path[0], world_path[1]);
        let move = MoveHelper::new(
            world_path[0], world_path[1], speed);
        let mut vis = box EventMoveVisualizer {
            unit_id: unit_id,
            path: world_path,
            move: move,
            speed: speed,
        };
        vis.update_waypoint(node);
        vis as Box<EventVisualizer>
    }

    fn update_waypoint(&mut self, node: &mut SceneNode) {
        self.move = MoveHelper::new(
            self.current_waypoint(),
            self.next_waypoint(),
            self.speed,
        );
        node.rot = geom::get_rot_angle(
            self.current_waypoint(),
            self.next_waypoint()
        );
    }

    fn current_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 1);
        self.path[0]
    }

    fn next_waypoint(&self) -> WorldPos {
        assert!(self.path.len() >= 2);
        self.path[1]
    }
}

pub struct EventEndTurnVisualizer;

impl EventEndTurnVisualizer {
    pub fn new() -> Box<EventVisualizer> {
        box EventEndTurnVisualizer as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventEndTurnVisualizer {
    fn is_finished(&self) -> bool {
        true
    }

    fn draw(&mut self, _: &mut Scene, _: Time) {}

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct EventCreateUnitVisualizer {
    id: UnitId,
    move: MoveHelper,
}

fn get_unit_scene_nodes(
    core: &core::Core,
    type_id: core::UnitTypeId,
    mesh_id: MeshId,
) -> Vec<SceneNode> {
    let count = core.get_unit_type(type_id).count;
    let mut vec = Vec::new();
    if count == 1 {
        vec![SceneNode {
            pos: WorldPos{v: Vector3{x: 0.0, y: 0.0, z: 0.0}},
            rot: 0.0,
            mesh_id: Some(mesh_id),
            children: vec![],
        }]
    } else {
        for i in range(0, count) {
            let pos = geom::index_to_circle_vertex(count, i).v.mul_s(0.5f32);
            vec.push(SceneNode {
                pos: WorldPos{v: pos},
                rot: 0.0,
                mesh_id: Some(mesh_id),
                children: vec![],
            });
        }
        vec
    }
}

impl EventCreateUnitVisualizer {
    pub fn new(
        core: &core::Core,
        scene: &mut Scene,
        _: &GameState,
        id: UnitId,
        type_id: core::UnitTypeId,
        pos: MapPos,
        mesh_id: MeshId,
        marker_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(id);
        let world_pos = geom::map_pos_to_world_pos(pos);
        let to = world_pos;
        let from = WorldPos{v: to.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let rot = rand::task_rng().gen_range::<MFloat>(0.0, 360.0);
        scene.nodes.insert(node_id, SceneNode {
            pos: from,
            rot: rot,
            mesh_id: None,
            children: get_unit_scene_nodes(core, type_id, mesh_id),
        });
        scene.nodes.insert(marker_id(id), SceneNode {
            pos: WorldPos{v: to.v.add_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))},
            rot: 0.0,
            mesh_id: Some(marker_mesh_id),
            children: Vec::new(),
        });
        let move = MoveHelper::new(from, to, 1.0);
        box EventCreateUnitVisualizer {
            id: id,
            move: move,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventCreateUnitVisualizer {
    fn is_finished(&self) -> bool {
        self.move.is_finished()
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        let node_id = unit_id_to_node_id(self.id);
        let node = scene.nodes.get_mut(&node_id);
        node.pos = self.move.step(dtime);
    }

    fn end(&mut self, _: &mut Scene, _: &GameState) {}
}

pub struct MoveHelper {
    to: WorldPos,
    current: WorldPos,
    dist: MFloat,
    current_dist: MFloat,
    dir: Vector3<MFloat>,
}

impl MoveHelper {
    pub fn new(
        from: WorldPos,
        to: WorldPos,
        speed: MFloat
    ) -> MoveHelper {
        let dir = to.v.sub_v(&from.v).normalize();
        let dist = geom::dist(from, to);
        MoveHelper {
            to: to,
            current: from,
            dist: dist,
            current_dist: 0.0,
            dir: dir.mul_s(speed),
        }
    }

    pub fn is_finished(&self) -> bool {
        self.current_dist >= self.dist
    }

    pub fn step(&mut self, dtime: Time) -> WorldPos {
        let dt = dtime.n as MFloat / 1000000000.0;
        let step = self.dir.mul_s(dt);
        self.current_dist += step.length();
        self.current.v.add_self_v(&step);
        if self.is_finished() {
            self.current = self.to;
        }
        self.current
    }
}

fn vec3_z(z: MFloat) -> Vector3<MFloat> {
    Vector3{x: 0.0, y: 0.0, z: z}
}

pub struct EventAttackUnitVisualizer {
    defender_id: UnitId,
    killed: bool,
    move: MoveHelper,
    shell_move: MoveHelper,
}

impl EventAttackUnitVisualizer {
    pub fn new(
        scene: &mut Scene,
        _: &GameState,
        attacker_id: UnitId,
        defender_id: UnitId,
        killed: bool,
        shell_mesh_id: MeshId
    ) -> Box<EventVisualizer> {
        let node_id = unit_id_to_node_id(defender_id);
        let from = scene.nodes.get(&node_id).pos;
        let to = WorldPos{v: from.v.sub_v(&vec3_z(geom::HEX_EX_RADIUS / 2.0))};
        let move = MoveHelper::new(from, to, 1.0);
        let shell_move = {
            let from = scene.nodes.get(&unit_id_to_node_id(attacker_id)).pos;
            let to = scene.nodes.get(&unit_id_to_node_id(defender_id)).pos;
            scene.nodes.insert(SHELL_NODE_ID, SceneNode {
                pos: from,
                rot: 0.0,
                mesh_id: Some(shell_mesh_id),
                children: Vec::new(),
            });
            MoveHelper::new(from, to, 10.0)
        };
        box EventAttackUnitVisualizer {
            defender_id: defender_id,
            killed: killed,
            move: move,
            shell_move: shell_move,
        } as Box<EventVisualizer>
    }
}

impl EventVisualizer for EventAttackUnitVisualizer {
    fn is_finished(&self) -> bool {
        if self.killed {
            self.move.is_finished()
        } else {
            self.shell_move.is_finished()
        }
    }

    fn draw(&mut self, scene: &mut Scene, dtime: Time) {
        scene.nodes.get_mut(&SHELL_NODE_ID).pos = self.shell_move.step(dtime);
        if self.killed {
            if self.shell_move.is_finished() {
                let node_id = unit_id_to_node_id(self.defender_id);
                scene.nodes.get_mut(&node_id).pos = self.move.step(dtime);
            }
        }
    }

    fn end(&mut self, scene: &mut Scene, _: &GameState) {
        if self.killed {
            let node_id = unit_id_to_node_id(self.defender_id);
            scene.nodes.remove(&node_id);
            scene.nodes.remove(&marker_id(self.defender_id));
        }
        scene.nodes.remove(&SHELL_NODE_ID);
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>// run-pass

#![feature(ip)]
#![feature(const_ipv6)]

use std::net::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};

fn main() {
    const IP_ADDRESS : Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);

    const SEGMENTS : [u16; 8] = IP_ADDRESS.segments();
    assert_eq!(SEGMENTS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 1]);

    const OCTETS : [u8; 16] = IP_ADDRESS.octets();
    assert_eq!(OCTETS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0, 0, 1]);

    const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
    assert!(!IS_UNSPECIFIED);

    const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
    assert!(IS_LOOPBACK);

    const IS_GLOBAL : bool = IP_ADDRESS.is_global();
    assert!(!IS_GLOBAL);

    const IS_UNIQUE_LOCAL : bool = IP_ADDRESS.is_unique_local();
    assert!(!IS_UNIQUE_LOCAL);

    const IS_UNICAST_LINK_LOCAL_STRICT : bool = IP_ADDRESS.is_unicast_link_local_strict();
    assert!(!IS_UNICAST_LINK_LOCAL_STRICT);

    const IS_UNICAST_LINK_LOCAL : bool = IP_ADDRESS.is_unicast_link_local();
    assert!(!IS_UNICAST_LINK_LOCAL);

    const IS_UNICAST_SITE_LOCAL : bool = IP_ADDRESS.is_unicast_site_local();
    assert!(!IS_UNICAST_SITE_LOCAL);

    const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
    assert!(!IS_DOCUMENTATION);

    const IS_UNICAST_GLOBAL : bool = IP_ADDRESS.is_unicast_global();
    assert!(!IS_UNICAST_GLOBAL);

    const MULTICAST_SCOPE : Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
    assert_eq!(MULTICAST_SCOPE, None);

    const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
    assert!(!IS_MULTICAST);

    const IP_V4 : Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
    assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
}<commit_msg>Add trailing newline to `ipv6.rs`<commit_after>// run-pass

#![feature(ip)]
#![feature(const_ipv6)]

use std::net::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};

fn main() {
    const IP_ADDRESS : Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
    assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);

    const SEGMENTS : [u16; 8] = IP_ADDRESS.segments();
    assert_eq!(SEGMENTS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 1]);

    const OCTETS : [u8; 16] = IP_ADDRESS.octets();
    assert_eq!(OCTETS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0, 0, 1]);

    const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
    assert!(!IS_UNSPECIFIED);

    const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
    assert!(IS_LOOPBACK);

    const IS_GLOBAL : bool = IP_ADDRESS.is_global();
    assert!(!IS_GLOBAL);

    const IS_UNIQUE_LOCAL : bool = IP_ADDRESS.is_unique_local();
    assert!(!IS_UNIQUE_LOCAL);

    const IS_UNICAST_LINK_LOCAL_STRICT : bool = IP_ADDRESS.is_unicast_link_local_strict();
    assert!(!IS_UNICAST_LINK_LOCAL_STRICT);

    const IS_UNICAST_LINK_LOCAL : bool = IP_ADDRESS.is_unicast_link_local();
    assert!(!IS_UNICAST_LINK_LOCAL);

    const IS_UNICAST_SITE_LOCAL : bool = IP_ADDRESS.is_unicast_site_local();
    assert!(!IS_UNICAST_SITE_LOCAL);

    const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
    assert!(!IS_DOCUMENTATION);

    const IS_UNICAST_GLOBAL : bool = IP_ADDRESS.is_unicast_global();
    assert!(!IS_UNICAST_GLOBAL);

    const MULTICAST_SCOPE : Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
    assert_eq!(MULTICAST_SCOPE, None);

    const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
    assert!(!IS_MULTICAST);

    const IP_V4 : Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
    assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
}
<|endoftext|>


<commit_before>use std::io::{Error, ErrorKind};
use std::ops::Add;
use std::result::Result;

fn range_vec<T>(nl: &Vec<T>, i: usize, j: usize) -> Result<Vec<T>, Error>
where
    T: Copy + Clone,
{
    if i >= nl.len() {
        return Result::Err(Error::new(
            ErrorKind::Other,
            "first index larger than length",
        ));
    }

    let mut jj;

    if j > nl.len() {
        jj = nl.len();
    } else {
        jj = j;
    }

    let mut ind = 0;
    let mut result: Vec<T> = vec![];

    for this in nl {
        if ind >= i && ind <= jj {
            result.push(*this);
        }
        ind += 1;
    }

    Result::Ok(result)
}

fn sum_vec<T>(nl: &Vec<T>) -> T
where
    T: Add<Output = T> + Copy + Clone,
{
    let mut result: T = *nl.first().unwrap();
    if let Some((_, last)) = nl.split_first() {
        for this in last {
            result = result + (*this);
        }
    }
    result
}

fn sum_range<T>(nl: &Vec<T>, i: usize, j: usize) -> Result<T, Error>
where
    T: Add<Output = T> + Copy + Clone,
{
    match range_vec(nl, i, j) {
        Result::Ok(temp_l) => return Result::Ok(sum_vec(&temp_l)),
        Result::Err(e) => return Result::Err(e),
    }
}

fn main() {
    let a = vec![-2, 0, 3, -5, 2, -1];
    println!("{:?}", range_vec(&a, 0, 1));
    println!("{:?}", range_vec(&a, 2, 6));
    println!("{:?}", range_vec(&a, 6, 6));
    println!("{:?}", range_vec(&a, 5, 6));
    //main thread cannot use `?`
    //println!("{:?}", range_vec(&a, 2, 6)?);

    println!("{:?}", sum_vec(&a));

    println!("{:?}", sum_range(&a, 0, 2));
    println!("{:?}", sum_range(&a, 2, 5));
    println!("{:?}", sum_range(&a, 0, 5));
}
<commit_msg>test result in main()<commit_after>use std::io::{Error, ErrorKind};
use std::ops::Add;
use std::result::Result;

fn range_vec<T>(nl: &Vec<T>, i: usize, j: usize) -> Result<Vec<T>, Error>
where
    T: Copy + Clone,
{
    if i >= nl.len() {
        return Result::Err(Error::new(
            ErrorKind::Other,
            "first index larger than length",
        ));
    }

    let mut jj;

    if j > nl.len() {
        jj = nl.len();
    } else {
        jj = j;
    }

    let mut ind = 0;
    let mut result: Vec<T> = vec![];

    for this in nl {
        if ind >= i && ind <= jj {
            result.push(*this);
        }
        ind += 1;
    }

    Result::Ok(result)
}

fn sum_vec<T>(nl: &Vec<T>) -> T
where
    T: Add<Output = T> + Copy + Clone,
{
    let mut result: T = *nl.first().unwrap();
    if let Some((_, last)) = nl.split_first() {
        for this in last {
            result = result + (*this);
        }
    }
    result
}

fn sum_range<T>(nl: &Vec<T>, i: usize, j: usize) -> Result<T, Error>
where
    T: Add<Output = T> + Copy + Clone,
{
    match range_vec(nl, i, j) {
        Result::Ok(temp_l) => return Result::Ok(sum_vec(&temp_l)),
        Result::Err(e) => return Result::Err(e),
    }
}

fn main() -> Result<(), std::io::Error> {
    let a = vec![-2, 0, 3, -5, 2, -1];
    println!("{:?}", range_vec(&a, 0, 1));
    println!("{:?}", range_vec(&a, 2, 6));
    println!("{:?}", range_vec(&a, 6, 6));
    println!("{:?}", range_vec(&a, 5, 6));

    //main thread cannot use `?`
    //1.26 can use `?`
    //https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
    let b = range_vec(&a, 2, 6)?;
    println!("{:?}", b);

    println!("{:?}", sum_vec(&a));

    println!("{:?}", sum_range(&a, 0, 2));
    println!("{:?}", sum_range(&a, 2, 5));
    println!("{:?}", sum_range(&a, 0, 5));

    Result::Ok(())
}
<|endoftext|>