<commit_before>use utils::address::Address;
use utils::bigint::{U256, M256};
use utils::gas::Gas;
use vm::{Memory, Storage, Log, Context};
use super::State;
use utils::rlp::WriteRLP;

use std::cmp::min;
use crypto::sha3::Sha3;
use crypto::digest::Digest;
use vm::eval::utils::{l64, copy_from_memory};

pub fn suicide<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>) {
    pop!(state, address: Address);
    let balance = state.account_state.balance(state.context.address).unwrap();
    state.account_state.increase_balance(address, balance);
    state.account_state.remove(state.context.address).unwrap();
}

pub fn log<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>, topic_len: usize) {
    pop!(state, index, len);
    let data = copy_from_memory(&state.memory, index, len);
    let mut topics = Vec::new();
    for _ in 0..topic_len {
        topics.push(state.stack.pop().unwrap());
    }

    state.logs.push(Log {
        address: state.context.address,
        data: data,
        topics: topics,
    });
}

pub fn sha3<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>) {
    pop!(state, from, len);
    let data = copy_from_memory(&state.memory, from, len);
    let mut sha3 = Sha3::keccak256();
    sha3.input(data.as_slice());
    let mut ret = [0u8; 32];
    sha3.result(&mut ret);
    push!(state, M256::from(ret.as_ref()));
}

pub fn create<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>, after_gas: Gas) -> Option<Context> {
    pop!(state, value: U256);
    pop!(state, init_start, init_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let init = copy_from_memory(&state.memory, init_start, init_len);
    let nonce = state.account_state.nonce(state.context.address).unwrap();
    let mut sha3 = Sha3::keccak256();
    let mut rlp: Vec<u8> = Vec::new();
    let mut address_array = [0u8; 32];
    state.context.address.write_rlp(&mut rlp);
    nonce.write_rlp(&mut rlp);
    sha3.input(rlp.as_slice());
    sha3.result(&mut address_array);
    let address = Address::from(M256::from(address_array));
    let context = Context {
        address: address,
        caller: state.context.address,
        code: init,
        data: Vec::new(),
        gas_limit: after_gas,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, address.into());
    Some(context)
}

pub fn call<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>, stipend_gas: Gas, after_gas: Gas) -> Option<(Context, (M256, M256))> {
    pop!(state, gas: Gas, to: Address, value: U256);
    pop!(state, in_start, in_len, out_start, out_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::from(1u64));
        return None;
    }

    let input = copy_from_memory(&state.memory, in_start, in_len);
    let gas_limit = min(l64(after_gas), gas + stipend_gas);
    let context = Context {
        address: to,
        caller: state.context.address,
        code: state.account_state.code(to).unwrap().into(),
        data: input,
        gas_limit: gas_limit,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, M256::zero());
    Some((context, (out_start, out_len)))
}
<commit_msg>Problem: before homestead should always use full gas Solution: switch to block 0x0 for now<commit_after>use utils::address::Address;
use utils::bigint::{U256, M256};
use utils::gas::Gas;
use vm::{Memory, Storage, Log, Context};
use super::State;
use utils::rlp::WriteRLP;

use crypto::sha3::Sha3;
use crypto::digest::Digest;
use vm::eval::utils::copy_from_memory;

pub fn suicide<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>) {
    pop!(state, address: Address);
    let balance = state.account_state.balance(state.context.address).unwrap();
    state.account_state.increase_balance(address, balance);
    state.account_state.remove(state.context.address).unwrap();
}

pub fn log<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>, topic_len: usize) {
    pop!(state, index, len);
    let data = copy_from_memory(&state.memory, index, len);
    let mut topics = Vec::new();
    for _ in 0..topic_len {
        topics.push(state.stack.pop().unwrap());
    }

    state.logs.push(Log {
        address: state.context.address,
        data: data,
        topics: topics,
    });
}

pub fn sha3<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>) {
    pop!(state, from, len);
    let data = copy_from_memory(&state.memory, from, len);
    let mut sha3 = Sha3::keccak256();
    sha3.input(data.as_slice());
    let mut ret = [0u8; 32];
    sha3.result(&mut ret);
    push!(state, M256::from(ret.as_ref()));
}

pub fn create<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>, after_gas: Gas) -> Option<Context> {
    pop!(state, value: U256);
    pop!(state, init_start, init_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::zero());
        return None;
    }

    let init = copy_from_memory(&state.memory, init_start, init_len);
    let nonce = state.account_state.nonce(state.context.address).unwrap();
    let mut sha3 = Sha3::keccak256();
    let mut rlp: Vec<u8> = Vec::new();
    let mut address_array = [0u8; 32];
    state.context.address.write_rlp(&mut rlp);
    nonce.write_rlp(&mut rlp);
    sha3.input(rlp.as_slice());
    sha3.result(&mut address_array);
    let address = Address::from(M256::from(address_array));
    let context = Context {
        address: address,
        caller: state.context.address,
        code: init,
        data: Vec::new(),
        gas_limit: after_gas,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, address.into());
    Some(context)
}

#[allow(unused_variables)]
pub fn call<M: Memory + Default, S: Storage + Default + Clone>(state: &mut State<M, S>, stipend_gas: Gas, after_gas: Gas) -> Option<(Context, (M256, M256))> {
    pop!(state, gas: Gas, to: Address, value: U256);
    pop!(state, in_start, in_len, out_start, out_len);
    if state.account_state.balance(state.context.address).unwrap() < value {
        push!(state, M256::from(1u64));
        return None;
    }

    let input = copy_from_memory(&state.memory, in_start, in_len);
    let gas_limit = gas + stipend_gas;
    let context = Context {
        address: to,
        caller: state.context.address,
        code: state.account_state.code(to).unwrap().into(),
        data: input,
        gas_limit: gas_limit,
        gas_price: state.context.gas_price,
        origin: state.context.origin,
        value: value,
    };
    push!(state, M256::zero());
    Some((context, (out_start, out_len)))
}
<|endoftext|>


<commit_before>use super::byteorder::{BigEndian, ByteOrder};
use super::amiga_hunk_parser::{HunkParser, Hunk, HunkType};
use super::musashi::Musashi;
use std::io;

// Memory layout of the 'Amiga'
// 0 - 512K is reserved for the "rom"
// 512 - 4MB - Executable has the range of 16MB
// 4MB - 16MB - 16MB -> Heap, bss, etc

static mut AMIGA_MEMORY: [u8; 16 * 1024 * 1024] = [0; 16 * 1024 * 1024];

const EXE_START: usize = 512 * 1024;

pub struct Amiga {
    pub dummy: i32,
}

impl Amiga {
    pub fn new() -> Amiga {
        Amiga { dummy: 0 }
    }

    pub fn parse_executable(&self, filename: &str) -> Result<Vec<Hunk>, io::Error> {
        HunkParser::parse_file(filename)
    }

    fn copy_data<'a>(src: &'a [u8], dest: &'a mut [u8], size: usize) {
        for i in 0..size {
            dest[i] = src[i];
        }
    }

    fn clear_memory<'a>(dest: &'a mut [u8], size: usize) {
        for i in 0..size {
            dest[i] = 0;
        }
    }

    pub fn load_code_data(hunks: &mut Vec<Hunk>, hunk_type: HunkType, offset: usize) -> usize {
        let mut curr_offset = offset;

        for hunk in hunks.iter_mut() {
            if hunk.hunk_type == hunk_type {
                hunk.memory_offset = curr_offset;
                hunk.code_data.as_ref().map(|data| {
                    unsafe {
                        // Needs to be unsafe because Musashi callbacks doesn't provide userdata
                        // thus the Amiga memory needs to be global
                        Self::copy_data(&data, &mut AMIGA_MEMORY[curr_offset..], hunk.data_size);
                    }

                    curr_offset += hunk.data_size;
                });
            }
        }

        curr_offset
    }

    fn init_bss_sections(hunks: &mut Vec<Hunk>, offset: usize) -> usize {
        let mut curr_offset = offset;

        for hunk in hunks.iter_mut() {
            if hunk.hunk_type == HunkType::Bss {
                hunk.memory_offset = curr_offset;
                hunk.code_data.as_ref().map(|_| {
                    unsafe {
                        // Needs to be unsafe because Musashi callbacks doesn't provide userdata
                        // thus the Amiga memory needs to be global
                        Self::clear_memory(&mut AMIGA_MEMORY[curr_offset..], hunk.data_size);
                    }

                    curr_offset += hunk.data_size;
                });
            }
        }

        curr_offset
    }

    fn load_to_memory(hunks: &mut Vec<Hunk>) {
        let code_end = Self::load_code_data(hunks, HunkType::Code, EXE_START);
        let data_end = Self::load_code_data(hunks, HunkType::Data, code_end);
        let bss_end = Self::init_bss_sections(hunks, data_end);

        println!("code end: {} data end: {} bss end: {}", code_end, data_end, bss_end);

        let mut pc = EXE_START as u32;

        while pc < code_end as u32 {
            pc += Musashi::disassemble(pc);
        }
    }

    pub fn load_executable_to_memory(&self, filename: &str) -> io::Result<()> {
        let mut hunks = Self::parse_executable(self, filename)?;

        /*
        for hunk in &hunks {
           println!("type {:?} - size {} - alloc_size {}", hunk.hunk_type, hunk.data_size, hunk.alloc_size);
        }
        */

        Self::load_to_memory(&mut hunks);

        for hunk in &hunks {
            println!("type {:?} - {:?}", hunk.hunk_type, hunk);
        }

        Ok(())
    }
}

//
// This is kinda ugly but this is the way Musashi works. When we have
// our own 68k emulator this should be cleaned up and not be global
//

#[no_mangle]
pub extern "C" fn m68k_read_memory_32(address: u32) -> u32 {
    unsafe { BigEndian::read_u32(&AMIGA_MEMORY[address as usize..]) }
}

#[no_mangle]
pub extern "C" fn m68k_read_memory_16(address: u32) -> u16 {
    unsafe { BigEndian::read_u16(&AMIGA_MEMORY[address as usize..]) as u16 }
}

#[no_mangle]
pub extern "C" fn m68k_read_memory_8(address: u32) -> u32 {
    unsafe { AMIGA_MEMORY[address as usize] as u32 }
}

#[no_mangle]
pub extern "C" fn m68k_write_memory_8(address: u32, value: u32) {
    unsafe { AMIGA_MEMORY[address as usize] = value as u8 }
}

#[no_mangle]
pub extern "C" fn m68k_write_memory_16(address: u32, value: u32) {
    unsafe { BigEndian::write_u16(&mut AMIGA_MEMORY[address as usize..], value as u16) }
}

#[no_mangle]
pub extern "C" fn m68k_write_memory_32(address: u32, value: u32) {
    unsafe { BigEndian::write_u32(&mut AMIGA_MEMORY[address as usize..], value) }
}

#[no_mangle]
pub extern "C" fn m68k_read_disassembler_32(address: u32) -> u32 {
    m68k_read_memory_32(address)
}

#[no_mangle]
pub extern "C" fn m68k_read_disassembler_16(address: u32) -> u32 {
    m68k_read_memory_16(address) as u32
}

#[no_mangle]
pub extern "C" fn m68k_read_disassembler_8(address: u32) -> u32 {
    m68k_read_memory_8(address)
}
<commit_msg>Implemented relocation of Amiga code<commit_after>use super::byteorder::{BigEndian, ByteOrder};
use super::amiga_hunk_parser::{HunkParser, Hunk, HunkType};
use super::musashi::Musashi;
use std::io;

// Memory layout of the 'Amiga'
// 0 - 512K is reserved for the "rom"
// 512 - 4MB - Executable has the range of 16MB
// 4MB - 16MB - 16MB -> Heap, bss, etc

static mut AMIGA_MEMORY: [u8; 16 * 1024 * 1024] = [0; 16 * 1024 * 1024];

const EXE_START: usize = 512 * 1024;

pub struct Amiga {
    pub dummy: u32,
}

impl Amiga {
    pub fn new() -> Amiga {
        Amiga {
            dummy: 0,
        }
    }

    // TODO: We should store within the amiga what data is allowed to be accesed
    fn get_amiga_memory_long(offset: u32) -> u32 {
        unsafe {
            let v0 = AMIGA_MEMORY[offset as usize + 0] as u32;
            let v1 = AMIGA_MEMORY[offset as usize + 1] as u32;
            let v2 = AMIGA_MEMORY[offset as usize + 2] as u32;
            let v3 = AMIGA_MEMORY[offset as usize + 3] as u32;
            (v0 << 24) | (v1 << 16) | (v2 << 8) | v3
        }
    }

    // TODO: We should store within the amiga what data is allowed to be accesed
    fn set_amiga_memory_long(offset: u32, value: u32) {
        unsafe {
            AMIGA_MEMORY[offset as usize + 0] = ((value >> 24) & 0xff) as u8;
            AMIGA_MEMORY[offset as usize + 1] = ((value >> 16) & 0xff) as u8;
            AMIGA_MEMORY[offset as usize + 2] = ((value >> 8) & 0xff) as u8;
            AMIGA_MEMORY[offset as usize + 3] = ((value >> 0) & 0xff) as u8;
        }
    }

    pub fn parse_executable(filename: &str) -> Result<Vec<Hunk>, io::Error> {
        HunkParser::parse_file(filename)
    }

    fn copy_data<'a>(src: &'a [u8], dest: &'a mut [u8], size: usize) {
        for i in 0..size {
            dest[i] = src[i];
        }
    }

    fn clear_memory<'a>(dest: &'a mut [u8], size: usize) {
        for i in 0..size {
            dest[i] = 0;
        }
    }

    pub fn load_code_data(hunks: &mut Vec<Hunk>, hunk_type: HunkType, offset: usize) -> usize {
        let mut curr_offset = offset;

        for hunk in hunks.iter_mut() {
            if hunk.hunk_type == hunk_type {
                hunk.memory_offset = curr_offset;
                hunk.code_data.as_ref().map(|data| {
                    unsafe {
                        Self::copy_data(&data, &mut AMIGA_MEMORY[curr_offset..], hunk.data_size);
                    }

                    curr_offset += hunk.data_size;
                });
            }
        }

        curr_offset
    }

    fn init_bss_sections(hunks: &mut Vec<Hunk>, offset: usize) -> usize {
        let mut curr_offset = offset;

        for hunk in hunks.iter_mut() {
            if hunk.hunk_type == HunkType::Bss {
                hunk.memory_offset = curr_offset;
                hunk.code_data.as_ref().map(|_| {
                    unsafe {
                        // Needs to be unsafe because Musashi callbacks doesn't provide userdata
                        // thus the Amiga memory needs to be global
                        Self::clear_memory(&mut AMIGA_MEMORY[curr_offset..], hunk.data_size);
                    }

                    curr_offset += hunk.data_size;
                });
            }
        }

        curr_offset
    }

    fn reloc_hunk(hunk: &Hunk, hunks: &Vec<Hunk>) {
        if let Some(reloc_data) = hunk.reloc_32.as_ref() {
            let hunk_offset = hunk.memory_offset as u32;

            for reloc in reloc_data {
                let target_hunk_offset = hunks[reloc.target].memory_offset as u32;

                for offset in &reloc.data {
                    let write_target = hunk_offset + offset;
                    let value = Self::get_amiga_memory_long(write_target);
                    Self::set_amiga_memory_long(write_target, target_hunk_offset + value);
                }
            }
        }
    }

    ///
    /// Relocates the code within our memory region
    ///
    fn reloc_code_data(hunks: &Vec<Hunk>) {
        for hunk in hunks {
            if hunk.hunk_type == HunkType::Code || hunk.hunk_type == HunkType::Data {
                Self::reloc_hunk(hunk, hunks);
            }
        }
    }

    fn load_to_memory(hunks: &mut Vec<Hunk>) {
        let code_end = Self::load_code_data(hunks, HunkType::Code, EXE_START);
        let data_end = Self::load_code_data(hunks, HunkType::Data, code_end);
        let bss_end = Self::init_bss_sections(hunks, data_end);

        Self::reloc_code_data(hunks);

        println!("code end: {} data end: {} bss end: {}", code_end, data_end, bss_end);

        let mut pc = EXE_START as u32;

        while pc < code_end as u32 {
            pc += Musashi::disassemble(pc);
        }
    }

    pub fn load_executable_to_memory(&self, filename: &str) -> io::Result<()> {
        let mut hunks = Self::parse_executable(filename)?;

        /*
        for hunk in &hunks {
           println!("type {:?} - size {} - alloc_size {}", hunk.hunk_type, hunk.data_size, hunk.alloc_size);
        }
        */

        Self::load_to_memory(&mut hunks);

        for hunk in &hunks {
            println!("type {:?} - {:?}", hunk.hunk_type, hunk);
        }

        Ok(())
    }
}

//
// This is kinda ugly but this is the way Musashi works. When we have
// our own 68k emulator this should be cleaned up and not be global
//

#[no_mangle]
pub extern "C" fn m68k_read_memory_32(address: u32) -> u32 {
    unsafe { BigEndian::read_u32(&AMIGA_MEMORY[address as usize..]) }
}

#[no_mangle]
pub extern "C" fn m68k_read_memory_16(address: u32) -> u16 {
    unsafe { BigEndian::read_u16(&AMIGA_MEMORY[address as usize..]) as u16 }
}

#[no_mangle]
pub extern "C" fn m68k_read_memory_8(address: u32) -> u32 {
    unsafe { AMIGA_MEMORY[address as usize] as u32 }
}

#[no_mangle]
pub extern "C" fn m68k_write_memory_8(address: u32, value: u32) {
    unsafe { AMIGA_MEMORY[address as usize] = value as u8 }
}

#[no_mangle]
pub extern "C" fn m68k_write_memory_16(address: u32, value: u32) {
    unsafe { BigEndian::write_u16(&mut AMIGA_MEMORY[address as usize..], value as u16) }
}

#[no_mangle]
pub extern "C" fn m68k_write_memory_32(address: u32, value: u32) {
    unsafe { BigEndian::write_u32(&mut AMIGA_MEMORY[address as usize..], value) }
}

#[no_mangle]
pub extern "C" fn m68k_read_disassembler_32(address: u32) -> u32 {
    m68k_read_memory_32(address)
}

#[no_mangle]
pub extern "C" fn m68k_read_disassembler_16(address: u32) -> u32 {
    m68k_read_memory_16(address) as u32
}

#[no_mangle]
pub extern "C" fn m68k_read_disassembler_8(address: u32) -> u32 {
    m68k_read_memory_8(address)
}
<|endoftext|>


<commit_before>use std::collections::{
    HashMap,
    BinaryHeap,
};
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};

use std::hash::Hash;

use scored::MinScored;
use super::visit::{
    EdgeRef,
    GraphBase,
    IntoEdges,
    VisitMap,
    Visitable,
};

use algo::Measure;

/// [Generic] A* shortest path algorithm.
///
/// Compute the length of the shortest path from `start` to `finish`.
///
/// `finish` is implicitly given via the `is_goal` callback, which should return `true` if the
/// given node is the finish node.
///
/// The function `edge_cost` should return the cost for a particular edge, which is used to compute
/// path costs.
///
/// The function `estimate_cost` should return the estimated cost to the finish for a particular
/// node, also used to compute path costs.
///
/// ```
/// use petgraph::Graph;
/// use petgraph::algo::astar;
///
/// let mut g = Graph::new();
/// let a = g.add_node((0., 0.));
/// let b = g.add_node((2., 0.));
/// let c = g.add_node((1., 1.));
/// let d = g.add_node((0., 2.));
/// let e = g.add_node((3., 3.));
/// let f = g.add_node((4., 2.));
/// g.extend_with_edges(&[
///     (a, b, 2),
///     (a, d, 4),
///     (b, c, 1),
///     (b, f, 7),
///     (c, e, 5),
///     (e, f, 1),
///     (d, e, 1),
/// ]);
///
/// let path = astar(&g, a, |finish| finish == f, |e| *e.weight(), |_| 0);
/// assert_eq!(path, Some((6, vec![a, d, e, f])));
/// ```
///
/// The graph should be `Visitable` and implement `IntoEdges`. Edge costs must be non-negative.
///
/// Returns the total cost + the path of subsequent `NodeId` from start to finish, if one was
/// found.
pub fn astar<G, F, H, K, IsGoal>(graph: G, start: G::NodeId, mut is_goal: IsGoal,
                                     mut edge_cost: F, mut estimate_cost: H)
    -> Option<(K, Vec<G::NodeId>)>
    where G: IntoEdges + Visitable,
          IsGoal: FnMut(G::NodeId) -> bool,
          G::NodeId: Eq + Hash,
          F: FnMut(G::EdgeRef) -> K,
          H: FnMut(G::NodeId) -> K,
          K: Measure + Copy,
{
    let mut visited = graph.visit_map();
    let mut visit_next = BinaryHeap::new();
    let mut scores = HashMap::new();
    let mut path_tracker = PathTracker::<G>::new();

    let zero_score = K::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(estimate_cost(start), start));

    while let Some(MinScored(_, node)) = visit_next.pop() {
        if is_goal(node) {
            let path = path_tracker.reconstruct_path_to(node);
            let cost = scores[&node];
            return Some((cost, path));
        }

        // Don't visit the same node several times, as the first time it was visited it was using
        // the shortest available path.
        if !visited.visit(node) {
            continue
        }

        // This lookup can be unwrapped without fear of panic since the node was necessarily scored
        // before adding him to `visit_next`.
        let node_score = scores[&node];

        for edge in graph.edges(node) {
            let next = edge.target();
            if visited.is_visited(&next) {
                continue
            }

            let mut next_score = node_score + edge_cost(edge);

            match scores.entry(next) {
                Occupied(ent) => {
                    let old_score = *ent.get();
                    if next_score < old_score {
                        *ent.into_mut() = next_score;
                        path_tracker.set_predecessor(next, node);
                    } else {
                        next_score = old_score;
                    }
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    path_tracker.set_predecessor(next, node);
                }
            }

            let next_estimate_score = next_score + estimate_cost(next);
            visit_next.push(MinScored(next_estimate_score, next));
        }
    }

    None
}

struct PathTracker<G>
    where G: GraphBase,
          G::NodeId: Eq + Hash,
{
    came_from: HashMap<G::NodeId, G::NodeId>,
}

impl<G> PathTracker<G>
    where G: GraphBase,
          G::NodeId: Eq + Hash,
{
    fn new() -> PathTracker<G> {
        PathTracker {
            came_from: HashMap::new(),
        }
    }

    fn set_predecessor(&mut self, node: G::NodeId, previous: G::NodeId) {
        self.came_from.insert(node, previous);
    }

    fn reconstruct_path_to(&self, last: G::NodeId) -> Vec<G::NodeId> {
        let mut path = vec![last];

        let mut current = last;
        loop {
            if let Some(&previous) = self.came_from.get(&current) {
                path.push(previous);
                current = previous;
            } else {
                break
            }
        }

        path.reverse();

        path
    }
}
<commit_msg>A*: update docstring<commit_after>use std::collections::{
    HashMap,
    BinaryHeap,
};
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};

use std::hash::Hash;

use scored::MinScored;
use super::visit::{
    EdgeRef,
    GraphBase,
    IntoEdges,
    VisitMap,
    Visitable,
};

use algo::Measure;

/// [Generic] A* shortest path algorithm.
///
/// Computes the shortest path from `start` to `finish`, including the total path cost.
///
/// `finish` is implicitly given via the `is_goal` callback, which should return `true` if the
/// given node is the finish node.
///
/// The function `edge_cost` should return the cost for a particular edge. Edge costs must be
/// non-negative.
///
/// The function `estimate_cost` should return the estimated cost to the finish for a particular
/// node. For the algorithm to find the actual shortest path, it should be admissible, meaning that
/// it should never overestimate the actual cost to get to the nearest goal node. Estimate costs
/// must also be non-negative.
///
/// The graph should be `Visitable` and implement `IntoEdges`.
///
/// ```
/// use petgraph::Graph;
/// use petgraph::algo::astar;
///
/// let mut g = Graph::new();
/// let a = g.add_node((0., 0.));
/// let b = g.add_node((2., 0.));
/// let c = g.add_node((1., 1.));
/// let d = g.add_node((0., 2.));
/// let e = g.add_node((3., 3.));
/// let f = g.add_node((4., 2.));
/// g.extend_with_edges(&[
///     (a, b, 2),
///     (a, d, 4),
///     (b, c, 1),
///     (b, f, 7),
///     (c, e, 5),
///     (e, f, 1),
///     (d, e, 1),
/// ]);
///
/// let path = astar(&g, a, |finish| finish == f, |e| *e.weight(), |_| 0);
/// assert_eq!(path, Some((6, vec![a, d, e, f])));
/// ```
///
/// Returns the total cost + the path of subsequent `NodeId` from start to finish, if one was
/// found.
pub fn astar<G, F, H, K, IsGoal>(graph: G, start: G::NodeId, mut is_goal: IsGoal,
                                     mut edge_cost: F, mut estimate_cost: H)
    -> Option<(K, Vec<G::NodeId>)>
    where G: IntoEdges + Visitable,
          IsGoal: FnMut(G::NodeId) -> bool,
          G::NodeId: Eq + Hash,
          F: FnMut(G::EdgeRef) -> K,
          H: FnMut(G::NodeId) -> K,
          K: Measure + Copy,
{
    let mut visited = graph.visit_map();
    let mut visit_next = BinaryHeap::new();
    let mut scores = HashMap::new();
    let mut path_tracker = PathTracker::<G>::new();

    let zero_score = K::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(estimate_cost(start), start));

    while let Some(MinScored(_, node)) = visit_next.pop() {
        if is_goal(node) {
            let path = path_tracker.reconstruct_path_to(node);
            let cost = scores[&node];
            return Some((cost, path));
        }

        // Don't visit the same node several times, as the first time it was visited it was using
        // the shortest available path.
        if !visited.visit(node) {
            continue
        }

        // This lookup can be unwrapped without fear of panic since the node was necessarily scored
        // before adding him to `visit_next`.
        let node_score = scores[&node];

        for edge in graph.edges(node) {
            let next = edge.target();
            if visited.is_visited(&next) {
                continue
            }

            let mut next_score = node_score + edge_cost(edge);

            match scores.entry(next) {
                Occupied(ent) => {
                    let old_score = *ent.get();
                    if next_score < old_score {
                        *ent.into_mut() = next_score;
                        path_tracker.set_predecessor(next, node);
                    } else {
                        next_score = old_score;
                    }
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    path_tracker.set_predecessor(next, node);
                }
            }

            let next_estimate_score = next_score + estimate_cost(next);
            visit_next.push(MinScored(next_estimate_score, next));
        }
    }

    None
}

struct PathTracker<G>
    where G: GraphBase,
          G::NodeId: Eq + Hash,
{
    came_from: HashMap<G::NodeId, G::NodeId>,
}

impl<G> PathTracker<G>
    where G: GraphBase,
          G::NodeId: Eq + Hash,
{
    fn new() -> PathTracker<G> {
        PathTracker {
            came_from: HashMap::new(),
        }
    }

    fn set_predecessor(&mut self, node: G::NodeId, previous: G::NodeId) {
        self.came_from.insert(node, previous);
    }

    fn reconstruct_path_to(&self, last: G::NodeId) -> Vec<G::NodeId> {
        let mut path = vec![last];

        let mut current = last;
        loop {
            if let Some(&previous) = self.came_from.get(&current) {
                path.push(previous);
                current = previous;
            } else {
                break
            }
        }

        path.reverse();

        path
    }
}
<|endoftext|>


<commit_before>use std::num::{next_power_of_two};
use image::{GenericImage, SubImage, ImageBuf, Rgba, Pixel};
use util;
use geom::{V2, Rect};

pub struct AtlasBuilder {
    images: Vec<ImageBuf<Rgba<u8>>>,
    draw_offsets: Vec<V2<int>>,
}

impl AtlasBuilder {
    pub fn new() -> AtlasBuilder {
        AtlasBuilder {
            images: vec![],
            draw_offsets: vec![],
        }
    }

    pub fn push<P: Pixel<u8>, I: GenericImage<P>>(
        &mut self, offset: V2<int>, mut image: I) -> uint {

        let Rect(pos, dim) = util::crop_alpha(&image);
        let cropped = SubImage::new(&mut image,
            pos.0 as u32, pos.1 as u32, dim.0 as u32, dim.1 as u32);

        let (w, h) = cropped.dimensions();
        let img = ImageBuf::from_pixels(
            cropped.pixels().map::<Rgba<u8>>(
                |(_x, _y, p)| p.to_rgba())
            .collect(),
            w, h);
        self.images.push(img);
        self.draw_offsets.push(pos - offset);
        self.images.len()
    }
}

pub struct Atlas {
    pub image: ImageBuf<Rgba<u8>>,
    pub vertices: Vec<Rect<f32>>,
    pub texcoords: Vec<Rect<f32>>,
}

impl Atlas {
    pub fn new(builder: &AtlasBuilder) -> Atlas {
        // Add 1 pixel edges to images to prevent texturing artifacts from
        // adjacent pixels in separate subimages.
        let dims : Vec<V2<int>> = builder.images.iter()
            .map(|img| { let (w, h) = img.dimensions(); V2(w as int + 1, h as int + 1) })
            .collect();

        // Guesstimate the size for the atlas container.
        let total_area = dims.iter().map(|dim| dim.0 * dim.1).fold(0, |a, b| a + b);
        let mut d = next_power_of_two((total_area as f64).sqrt() as uint) as u32;
        let mut offsets;

        loop {
            assert!(d < 1000000000); // Sanity check
            match util::pack_rectangles(V2(d as int, d as int), &dims) {
                Some(ret) => {
                    offsets = ret;
                    break;
                }
                None => {
                    d = d * 2;
                }
            }
        }

        // Blit subimages to atlas image.
        let mut image: ImageBuf<Rgba<u8>> = ImageBuf::new(d, d);
        for (i, &offset) in offsets.iter().enumerate() {
            util::blit(&builder.images[i], &mut image, offset);
        }

        let image_dim = V2(d, d);

        // Construct subimage rectangles.
        let texcoords: Vec<Rect<f32>> = offsets.iter().enumerate()
            .map(|(i, &offset)| Rect(scale_vec(offset, image_dim), scale_vec(dims[i], image_dim)))
            .collect();

        let vertices: Vec<Rect<f32>> = builder.draw_offsets.iter().enumerate()
            .map(|(i, &offset)| Rect(offset.map(|x| x as f32), dims[i].map(|x| x as f32)))
            .collect();

        assert!(texcoords.len() == vertices.len());

        return Atlas {
            image: image,
            vertices: vertices,
            texcoords: texcoords,
        };

        fn scale_vec(pixel_vec: V2<int>, image_dim: V2<u32>) -> V2<f32> {
            V2(pixel_vec.0 as f32 / image_dim.0 as f32,
              pixel_vec.1 as f32 / image_dim.1 as f32)
        }
    }
}
<commit_msg>Atlas builder now generates correct tile indices<commit_after>use std::num::{next_power_of_two};
use image::{GenericImage, SubImage, ImageBuf, Rgba, Pixel};
use util;
use geom::{V2, Rect};

pub struct AtlasBuilder {
    images: Vec<ImageBuf<Rgba<u8>>>,
    draw_offsets: Vec<V2<int>>,
}

impl AtlasBuilder {
    pub fn new() -> AtlasBuilder {
        AtlasBuilder {
            images: vec![],
            draw_offsets: vec![],
        }
    }

    pub fn push<P: Pixel<u8>, I: GenericImage<P>>(
        &mut self, offset: V2<int>, mut image: I) -> uint {

        let Rect(pos, dim) = util::crop_alpha(&image);
        let cropped = SubImage::new(&mut image,
            pos.0 as u32, pos.1 as u32, dim.0 as u32, dim.1 as u32);

        let (w, h) = cropped.dimensions();
        let img = ImageBuf::from_pixels(
            cropped.pixels().map::<Rgba<u8>>(
                |(_x, _y, p)| p.to_rgba())
            .collect(),
            w, h);
        self.images.push(img);
        self.draw_offsets.push(pos - offset);
        self.images.len() - 1
    }
}

pub struct Atlas {
    pub image: ImageBuf<Rgba<u8>>,
    pub vertices: Vec<Rect<f32>>,
    pub texcoords: Vec<Rect<f32>>,
}

impl Atlas {
    pub fn new(builder: &AtlasBuilder) -> Atlas {
        // Add 1 pixel edges to images to prevent texturing artifacts from
        // adjacent pixels in separate subimages.
        let dims : Vec<V2<int>> = builder.images.iter()
            .map(|img| { let (w, h) = img.dimensions(); V2(w as int + 1, h as int + 1) })
            .collect();

        // Guesstimate the size for the atlas container.
        let total_area = dims.iter().map(|dim| dim.0 * dim.1).fold(0, |a, b| a + b);
        let mut d = next_power_of_two((total_area as f64).sqrt() as uint) as u32;
        let mut offsets;

        loop {
            assert!(d < 1000000000); // Sanity check
            match util::pack_rectangles(V2(d as int, d as int), &dims) {
                Some(ret) => {
                    offsets = ret;
                    break;
                }
                None => {
                    d = d * 2;
                }
            }
        }

        // Blit subimages to atlas image.
        let mut image: ImageBuf<Rgba<u8>> = ImageBuf::new(d, d);
        for (i, &offset) in offsets.iter().enumerate() {
            util::blit(&builder.images[i], &mut image, offset);
        }

        let image_dim = V2(d, d);

        // Construct subimage rectangles.
        let texcoords: Vec<Rect<f32>> = offsets.iter().enumerate()
            .map(|(i, &offset)| Rect(scale_vec(offset, image_dim), scale_vec(dims[i], image_dim)))
            .collect();

        let vertices: Vec<Rect<f32>> = builder.draw_offsets.iter().enumerate()
            .map(|(i, &offset)| Rect(offset.map(|x| x as f32), dims[i].map(|x| x as f32)))
            .collect();

        assert!(texcoords.len() == vertices.len());

        return Atlas {
            image: image,
            vertices: vertices,
            texcoords: texcoords,
        };

        fn scale_vec(pixel_vec: V2<int>, image_dim: V2<u32>) -> V2<f32> {
            V2(pixel_vec.0 as f32 / image_dim.0 as f32,
              pixel_vec.1 as f32 / image_dim.1 as f32)
        }
    }
}
<|endoftext|>


<commit_before>use std::hash;
use std::hash::Hash;
use std::int::MAX;
use std::num::Int;

/// Our fixed-point loop needs a way of hashing the "current state" (type `St`).
/// The details of what states are and how they relate need not be revealed.
/// We hide all of these details in a "state system" (type `Sys`).
/// `next` checks for unstepped states to become the "current state".
/// `step` updates the system at the "current state".
trait Step {
    type St : Hash ;
    type Sys ;
    fn step (st:Self::St, sys:Self::Sys) -> Self::Sys ;
    fn next (sys:Self::Sys) -> Option<Self::St> ;
}

trait Fp<S:Step> {
    fn work_tree (left_lev:int, sys:S::Sys, parent_lev:int) -> S::Sys ;
    fn fp ( st:S::Sys ) -> S::Sys ;
}

struct FpS;

impl<S:Step> Fp<S> for FpS {

    fn work_tree (left_lev:int, sys:S::Sys, parent_lev:int) -> S::Sys {

        panic!("!");
        // let nxt = Step::next(sys) ;
        // match nxt {
        //     None => sys,
        //     Some(st) => {
        //         let st_lev = Int::trailing_zeros(hash::hash(&st)) as int ;
        //         if ( left_lev <= st_lev &&
        //              st_lev   <= parent_lev )
        //         {
        //             let sys = Step::step(st, sys) ;
        //             let sys = Fp::work_tree ( -1,     sys, st_lev );
        //             let sys = Fp::work_tree ( st_lev, sys, parent_lev );
        //             sys
        //         }
        //         else {
        //             sys
        //         }
        //     }
        // }

    }

    fn fp (sys:S::Sys) -> S::Sys {
        //Fp::work_tree (-1, sys, MAX );
        panic!("!");
    }
}
<commit_msg>fixed type issues in balfp; learning more about traits in Rust<commit_after>use std::hash;
use std::hash::Hash;
use std::int::MAX;
use std::num::Int;
use std::result::Result;

trait FpFn {
    // Fixed-point Function.
    //
    /// The Self type need not be stateful at all.
    ///
    /// Instead, a FpFn exposes its state (abstractly) to the loop
    /// that contains it.  There are two parts:
    //
    ///  - The loop iteration's current state (type `St`)
    //
    ///  - Any "meta-state" needed to explore the space of states
    ///  (type `Sys`)
    //
    /// Our fixed-point loop needs a way of hashing the "current
    /// state" (type `St`).  The details of what states are and how
    /// they relate need not be revealed.  We hide all of these
    /// details in a "state system" (type `Sys`).  `next` checks for
    /// unstepped states to become the "current state", or returns Err
    /// if no unexplored states exist.  `step` updates the system at
    /// the "current state".

    type St : Hash ;
    type Sys ;
    fn step (self:& Self, st:Self::St, sys:Self::Sys) -> Self::Sys ;
    fn next (self:& Self, sys:Self::Sys) -> Result<(Self::St, Self::Sys), Self::Sys> ;
}

trait FpLp<F:FpFn> {
    fn work_tree (self:&Self, f:&F, left_lev:int, sys:F::Sys, parent_lev:int) -> F::Sys {
        let nxt = f.next(sys) ;
        match nxt {
            Err(sys) => sys,
            Ok((st,sys)) => {
                let st_lev = Int::trailing_zeros(hash::hash(&st)) as int ;
                if ( left_lev <= st_lev &&
                     st_lev   <= parent_lev )
                {
                    let sys : F::Sys = f.step(st, sys) ;
                    let sys : F::Sys = self.work_tree (f, -1,     sys, st_lev );
                    let sys : F::Sys = self.work_tree (f, st_lev, sys, parent_lev );
                    sys
                }
                else {
                    sys
                }
            }
        }
    }
    fn compute (self:&Self, f:&F, sys:F::Sys) -> F::Sys {
        self.work_tree (f, -1, sys, MAX )
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate bencher;
extern crate kdtree;
extern crate rand;

use bencher::Bencher;
use rand::Rng;

use kdtree::kdtree::test_common::*;

fn gen_random() -> f64 {
    rand::thread_rng().gen_range(0., 10000.)
}

fn generate_points(point_count : usize) -> Vec<Point3WithId> {
    let mut points : Vec<Point3WithId> = vec![];

    for i in 0 .. point_count {
        points.push(Point3WithId::new(i as i32, gen_random(),gen_random(),gen_random()));
    }

    points
}

fn bench_creating_1000_node_tree(b: &mut Bencher) {
    let len = 1000usize;
    let mut points = generate_points(len);

    b.iter(|| {
        kdtree::kdtree::Kdtree::new(&mut points.clone());
    });
}

fn bench_single_loop_times_for_1000_node_tree(b: &mut Bencher) {
    let len = 1000usize;
    let mut points = generate_points(len);

    let tree = kdtree::kdtree::Kdtree::new(&mut points.clone());

    b.iter(|| tree.nearest_search(&points[0]));
}

fn bench_creating_1000_000_node_tree(b: &mut Bencher) {
    let len = 1000_000usize;
    let mut points = generate_points(len);

    b.iter(|| {
        kdtree::kdtree::Kdtree::new(&mut points.clone());
    });
}

fn bench_adding_same_node_to_1000_tree(b: &mut Bencher) {
    let len = 1000usize;
    let mut points = generate_points(len);
    let mut tree = kdtree::kdtree::Kdtree::new(&mut points);

    let point = Point3WithId::new(-1 as i32, gen_random(),gen_random(),gen_random());
    b.iter(|| {
        tree.insert_node(point);
    });
}

benchmark_group!(benches, bench_creating_1000_node_tree,bench_single_loop_times_for_1000_node_tree, bench_adding_to_1000_tree);
benchmark_main!(benches);<commit_msg>Fixed compilation err&warn<commit_after>#[macro_use] extern crate bencher;
extern crate kdtree;
extern crate rand;

use bencher::Bencher;
use rand::Rng;

use kdtree::kdtree::test_common::*;

fn gen_random() -> f64 {
    rand::thread_rng().gen_range(0., 10000.)
}

fn generate_points(point_count : usize) -> Vec<Point3WithId> {
    let mut points : Vec<Point3WithId> = vec![];

    for i in 0 .. point_count {
        points.push(Point3WithId::new(i as i32, gen_random(),gen_random(),gen_random()));
    }

    points
}

fn bench_creating_1000_node_tree(b: &mut Bencher) {
    let len = 1000usize;
    let points = generate_points(len);

    b.iter(|| {
        kdtree::kdtree::Kdtree::new(&mut points.clone());
    });
}

fn bench_single_loop_times_for_1000_node_tree(b: &mut Bencher) {
    let len = 1000usize;
    let points = generate_points(len);

    let tree = kdtree::kdtree::Kdtree::new(&mut points.clone());

    b.iter(|| tree.nearest_search(&points[0]));
}

fn bench_creating_1000_000_node_tree(b: &mut Bencher) {
    let len = 1000_000usize;
    let points = generate_points(len);

    b.iter(|| {
        kdtree::kdtree::Kdtree::new(&mut points.clone());
    });
}

fn bench_adding_same_node_to_1000_tree(b: &mut Bencher) {
    let len = 1000usize;
    let mut points = generate_points(len);
    let mut tree = kdtree::kdtree::Kdtree::new(&mut points);

    let point = Point3WithId::new(-1 as i32, gen_random(),gen_random(),gen_random());
    b.iter(|| {
        tree.insert_node(point);
    });
}

benchmark_group!(benches, bench_creating_1000_node_tree,bench_single_loop_times_for_1000_node_tree, bench_adding_same_node_to_1000_tree);
benchmark_main!(benches);<|endoftext|>


<commit_before>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// 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.
/*===============================================================================================*/

extern crate serde;
extern crate zip;

use ::util::Directory;
use ::util::serialization::{Deserializer, Serializer};

use self::serde::{Serialize, Deserialize};
use self::zip::ZipArchive;

use std::fs::File;
use std::io;
use std::path::Path;

/*===============================================================================================*/
/*------CONFIG LOADER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Allows the loading of configuration files.
#[derive (Copy, Clone)]
pub struct ConfigLoader;

/*===============================================================================================*/
/*------CONFIG LOADER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigLoader {

    /// Initializes the config loader
    pub fn init (&self) {

        info! ("Copying default config files.");

        // Open the persistent config path
        let p_config_dir = Directory::get_persistent_config_directory ();
        let config_pkg   = format! ("{}cfg.respkg", Directory::get_resource_directory ());

        // Open the file location
        match File::open (&config_pkg) {

            Ok (a) => {

                // Open the zip archive
                match ZipArchive::new (a) {

                    Ok (mut archive) => {

                        // Iterate through the zip file entries
                        for i in 0..archive.len () {

                            // Get the file and set ouput path
                            let mut file = archive.by_index (i).unwrap ();
                            let out_path = format! ("{}{}", p_config_dir, file.name ());

                            // Check if the config file already exists.
                            if Path::new (&out_path).exists () {
                                continue;
                            }

                            // Unpack the file to the directory
                            info! ("Unpacking \"{}\" to \"{}\".", file.name (), out_path);

                            // Unpack the file to the output path
                            let mut out_file = File::create (&out_path).unwrap ();
                            io::copy (&mut file, &mut out_file).unwrap ();
                        }
                    },

                    Err (e) => warn! ("Could not open resource package \"{}\".\n{}", config_pkg, e)
                }
            },

            Err (e) => warn! ("Could not open resource package \"{}\".\n{}", config_pkg, e)
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Creates a new config file.
    pub fn new_config<T: Default + Serialize> (&self, cfg_dir: &str, config_name: &str) -> Result<(), ()> {

        let cfg_path = &format! ("{}{}.cfg", cfg_dir, config_name);
        info! ("Creating new config file \"{}\".", cfg_path);

        match Serializer::to_file::<T> (&T::default (), cfg_path) {

            Ok (_) => Ok (()),
            Err (e) => {

                error! ("Could not create config file \"{}\".\n{}", cfg_path, e);
                Err (())
            }
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads the config file of a given name.
    pub fn load_config<T: Deserialize> (&self, cfg_dir: &str, config_name: &str) -> Result<T, ()> {

        let cfg_path = &format! ("{}{}.cfg", cfg_dir, config_name);
        info! ("Loading config file \"{}\".", cfg_path);

        match Deserializer::from_file::<T> (cfg_path) {

            Ok (config) => Ok (config),
            Err (e) => {

                error! ("Config file \"{}\" could not be loaded.\n{}", cfg_path, e);
                Err (())
            }
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves the config file of a given name.
    pub fn save_config<T: Serialize> (&self, cfg_dir: &str, config_name: &str, config_data: &T) -> Result<(), ()> {

        let cfg_path = &format! ("{}{}.cfg", cfg_dir, config_name);
        info! ("Saving config file \"{}\".", cfg_path);

        match Serializer::to_file::<T> (config_data, cfg_path) {

            Ok (_) => Ok (()),
            Err (e) => {

                error! ("Could not save to config file \"{}\".\n{}", cfg_path, e);
                Err (())
            }
        }
    }
}
<commit_msg>Changed default config location<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// 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.
/*===============================================================================================*/

extern crate serde;
extern crate zip;

use ::util::Directory;
use ::util::serialization::{Deserializer, Serializer};

use self::serde::{Serialize, Deserialize};
use self::zip::ZipArchive;

use std::fs::File;
use std::io;
use std::path::Path;

/*===============================================================================================*/
/*------CONFIG LOADER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Allows the loading of configuration files.
#[derive (Copy, Clone)]
pub struct ConfigLoader;

/*===============================================================================================*/
/*------CONFIG LOADER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigLoader {

    /// Initializes the config loader
    pub fn init (&self) {

        info! ("Copying default config files.");

        // Open the persistent config path
        let p_config_dir = Directory::get_persistent_config_directory ();
        let config_pkg   = format! ("{}config.respkg", Directory::get_config_directory ());

        // Open the file location
        match File::open (&config_pkg) {

            Ok (a) => {

                // Open the zip archive
                match ZipArchive::new (a) {

                    Ok (mut archive) => {

                        // Iterate through the zip file entries
                        for i in 0..archive.len () {

                            // Get the file and set ouput path
                            let mut file = archive.by_index (i).unwrap ();
                            let out_path = format! ("{}{}", p_config_dir, file.name ());

                            // Check if the config file already exists.
                            if Path::new (&out_path).exists () {
                                continue;
                            }

                            // Unpack the file to the directory
                            info! ("Unpacking \"{}\" to \"{}\".", file.name (), out_path);

                            // Unpack the file to the output path
                            let mut out_file = File::create (&out_path).unwrap ();
                            io::copy (&mut file, &mut out_file).unwrap ();
                        }
                    },

                    Err (e) => warn! ("Could not open resource package \"{}\".\n{}", config_pkg, e)
                }
            },

            Err (e) => warn! ("Could not open resource package \"{}\".\n{}", config_pkg, e)
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Creates a new config file.
    pub fn new_config<T: Default + Serialize> (&self, cfg_dir: &str, config_name: &str) -> Result<(), ()> {

        let cfg_path = &format! ("{}{}.cfg", cfg_dir, config_name);
        info! ("Creating new config file \"{}\".", cfg_path);

        match Serializer::to_file::<T> (&T::default (), cfg_path) {

            Ok (_) => Ok (()),
            Err (e) => {

                error! ("Could not create config file \"{}\".\n{}", cfg_path, e);
                Err (())
            }
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads the config file of a given name.
    pub fn load_config<T: Deserialize> (&self, cfg_dir: &str, config_name: &str) -> Result<T, ()> {

        let cfg_path = &format! ("{}{}.cfg", cfg_dir, config_name);
        info! ("Loading config file \"{}\".", cfg_path);

        match Deserializer::from_file::<T> (cfg_path) {

            Ok (config) => Ok (config),
            Err (e) => {

                error! ("Config file \"{}\" could not be loaded.\n{}", cfg_path, e);
                Err (())
            }
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves the config file of a given name.
    pub fn save_config<T: Serialize> (&self, cfg_dir: &str, config_name: &str, config_data: &T) -> Result<(), ()> {

        let cfg_path = &format! ("{}{}.cfg", cfg_dir, config_name);
        info! ("Saving config file \"{}\".", cfg_path);

        match Serializer::to_file::<T> (config_data, cfg_path) {

            Ok (_) => Ok (()),
            Err (e) => {

                error! ("Could not save to config file \"{}\".\n{}", cfg_path, e);
                Err (())
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate gcc;

fn main() {
	gcc::compile_library("liblz4.a", &[
		"liblz4/lib/lz4.c",
		"liblz4/lib/lz4frame.c",
		"liblz4/lib/lz4hc.c",
		"liblz4/lib/xxhash.c",
	]);
}
<commit_msg>Modified build script to *always* compile the C code with -O3 optimization<commit_after>extern crate gcc;

fn main() {
    let mut compiler = gcc::Config::new();
    compiler
        .file("liblz4/lib/lz4.c")
        .file("liblz4/lib/lz4frame.c")
        .file("liblz4/lib/lz4hc.c")
        .file("liblz4/lib/xxhash.c")
        // We always compile the C with optimization, because otherwise it is 20x slower.
        .opt_level(3) ;
    compiler.compile("liblz4.a");
}
<|endoftext|>


<commit_before>use super::command;

// An item on the chain
#[derive(Clone)]
pub enum Item<'a> {
    FatalCommand(String),
    NonFatalCommand(String),
    ResultProcessor(&'a Fn(&command::Result) -> command::Result),
    CommandModifier(&'a Fn(&command::Result, Option<&'a mut Item>) -> Option<&'a mut Item<'a>>)
}

pub struct CommandChain<'a> {
    pub commands: Vec<Item<'a>>,
    pub old_commands: Vec<Item<'a>>,
    pub result: Option<command::Result>
}

impl<'a> CommandChain<'a> {

    pub fn new() -> Self {
        CommandChain {
            commands: Vec::new(),
            old_commands: Vec::new(),
            result: None
        }
    }

    pub fn result_proc(mut self, f: &'a Fn(&command::Result) -> command::Result) -> Self {
        self.commands.push(Item::ResultProcessor(f));
        self
    }

    pub fn cmd(mut self, command_string: &str) -> Self {
        self.commands.push(Item::FatalCommand(String::from(command_string)));
        self
    }

    pub fn cmd_nonfatal(mut self, command_string: &str) -> Self {
        self.commands.push(Item::NonFatalCommand(String::from(command_string)));
        self
    }

    fn run_command(cmd_str : &str) -> command::Result {
        let result = command::run_host_cmd(cmd_str);
        if result.success {
            info!("stdout:{}", result.stdout);
        } else {
            warn!("stderr:{}", result.stderr);
        }
        result
    }

    // Executes the chain and returns self, with vector reset
    pub fn execute(mut self) -> Self {
        for item in self.commands.iter() {
            match item {
                &Item::FatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    if !result.success {
                        self.result = Some(result);
                        break
                    }
                    self.result = Some(result);
                },
                &Item::NonFatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    self.result = Some(result);
                },
                &Item::ResultProcessor(f) => {
                    self.result = {
                        if let Some(ref mut curr_res) = self.result {
                            Some(f(&curr_res))
                        } else {
                            warn!("Executing ResultProcessor with no current result is a no-op!");
                            None
                        }
                    };
                },
                &Item::CommandModifier(f) => {
                    // TODO: implement me!
                }
            }
        }
        self.old_commands.extend(self.commands.clone());
        self.commands = Vec::new();
        self
    }
}
<commit_msg>result mapped command first attempt<commit_after>use super::command;

// An item on the chain
#[derive(Clone)]
pub enum Item<'a> {
    FatalCommand(String),
    NonFatalCommand(String),
    ResultMappedCommand(&'a Fn(&command::Result, String) -> String, String, bool),
    ResultProcessor(&'a Fn(&command::Result) -> command::Result),
}

pub struct CommandChain<'a> {
    pub commands: Vec<Item<'a>>,
    pub old_commands: Vec<Item<'a>>,
    pub result: Option<command::Result>
}

impl<'a> CommandChain<'a> {

    pub fn new() -> Self {
        CommandChain {
            commands: Vec::new(),
            old_commands: Vec::new(),
            result: None
        }
    }

    pub fn result_proc(mut self, f: &'a Fn(&command::Result) -> command::Result) -> Self {
        self.commands.push(Item::ResultProcessor(f));
        self
    }

    pub fn cmd(mut self, command_string: &str) -> Self {
        self.commands.push(Item::FatalCommand(String::from(command_string)));
        self
    }

    pub fn cmd_nonfatal(mut self, command_string: &str) -> Self {
        self.commands.push(Item::NonFatalCommand(String::from(command_string)));
        self
    }

    fn run_command(cmd_str : &str) -> command::Result {
        let result = command::run_host_cmd(cmd_str);
        if result.success {
            info!("stdout:{}", result.stdout);
        } else {
            warn!("stderr:{}", result.stderr);
        }
        result
    }

    // Executes the chain and returns self, with vector reset
    pub fn execute(mut self) -> Self {
        for item in self.commands.iter() {
            match item {
                &Item::FatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    if !result.success {
                        self.result = Some(result);
                        break
                    }
                    self.result = Some(result);
                },
                &Item::NonFatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    self.result = Some(result);
                },
                &Item::ResultProcessor(f) => {
                    self.result = {
                        if let Some(ref mut curr_res) = self.result {
                            Some(f(&curr_res))
                        } else {
                            warn!("Executing ResultProcessor with no current result is a no-op!");
                            None
                        }
                    };
                },
                &Item::ResultMappedCommand(f, ref s, is_fatal) => {
                    let mapped_command : String = {
                        if let Some(ref mut curr_res) = self.result {
                            f(&curr_res, s.to_string())
                        } else {
                            warn!("Executing ResultMappedCommand with no current result is a no-op!");
                            s.to_string()
                        }
                    };
                    let result = CommandChain::run_command(&mapped_command);
                    if is_fatal && !result.success {
                        self.result = Some(result);
                        break
                    }
                    self.result = Some(result);
                }
            }
        }
        self.old_commands.extend(self.commands.clone());
        self.commands = Vec::new();
        self
    }
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::io;
use std::str::Utf8Error;
use std::{error, fmt};

use serde;

/// The result of a serialization or deserialization operation.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An error that can be produced during (de)serializing.
pub type Error = Box<ErrorKind>;

/// The kind of error that can be produced during a serialization or deserialization.
#[derive(Debug)]
pub enum ErrorKind {
    /// If the error stems from the reader/writer that is being used
    /// during (de)serialization, that error will be stored and returned here.
    Io(io::Error),
    /// Returned if the deserializer attempts to deserialize a string that is not valid utf8
    InvalidUtf8Encoding(Utf8Error),
    /// Returned if the deserializer attempts to deserialize a bool that was
    /// not encoded as either a 1 or a 0
    InvalidBoolEncoding(u8),
    /// Returned if the deserializer attempts to deserialize a char that is not in the correct format.
    InvalidCharEncoding,
    /// Returned if the deserializer attempts to deserialize the tag of an enum that is
    /// not in the expected ranges
    InvalidTagEncoding(usize),
    /// Serde has a deserialize_any method that lets the format hint to the
    /// object which route to take in deserializing.
    DeserializeAnyNotSupported,
    /// If (de)serializing a message takes more than the provided size limit, this
    /// error is returned.
    SizeLimit,
    /// Bincode can not encode sequences of unknown length (like iterators).
    SequenceMustHaveLength,
    /// A custom error message from Serde.
    Custom(String),
}

impl StdError for ErrorKind {
    fn description(&self) -> &str {
        match *self {
            ErrorKind::Io(ref err) => error::Error::description(err),
            ErrorKind::InvalidUtf8Encoding(_) => "string is not valid utf8",
            ErrorKind::InvalidBoolEncoding(_) => "invalid u8 while decoding bool",
            ErrorKind::InvalidCharEncoding => "char is not valid",
            ErrorKind::InvalidTagEncoding(_) => "tag for enum is not valid",
            ErrorKind::SequenceMustHaveLength => {
                "Bincode can only encode sequences and maps that have a knowable size ahead of time"
            }
            ErrorKind::DeserializeAnyNotSupported => {
                "Bincode doesn't support serde::Deserializer::deserialize_any"
            }
            ErrorKind::SizeLimit => "the size limit has been reached",
            ErrorKind::Custom(ref msg) => msg,
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            ErrorKind::Io(ref err) => Some(err),
            ErrorKind::InvalidUtf8Encoding(_) => None,
            ErrorKind::InvalidBoolEncoding(_) => None,
            ErrorKind::InvalidCharEncoding => None,
            ErrorKind::InvalidTagEncoding(_) => None,
            ErrorKind::SequenceMustHaveLength => None,
            ErrorKind::DeserializeAnyNotSupported => None,
            ErrorKind::SizeLimit => None,
            ErrorKind::Custom(_) => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        ErrorKind::Io(err).into()
    }
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ErrorKind::Io(ref ioerr) => write!(fmt, "io error: {}", ioerr),
            ErrorKind::InvalidUtf8Encoding(ref e) => write!(fmt, "{}: {}", self.description(), e),
            ErrorKind::InvalidBoolEncoding(b) => {
                write!(fmt, "{}, expected 0 or 1, found {}", self.description(), b)
            }
            ErrorKind::InvalidCharEncoding => write!(fmt, "{}", self.description()),
            ErrorKind::InvalidTagEncoding(tag) => {
                write!(fmt, "{}, found {}", self.description(), tag)
            }
            ErrorKind::SequenceMustHaveLength => write!(fmt, "{}", self.description()),
            ErrorKind::SizeLimit => write!(fmt, "{}", self.description()),
            ErrorKind::DeserializeAnyNotSupported => write!(
                fmt,
                "Bincode does not support the serde::Deserializer::deserialize_any method"
            ),
            ErrorKind::Custom(ref s) => s.fmt(fmt),
        }
    }
}

impl serde::de::Error for Error {
    fn custom<T: fmt::Display>(desc: T) -> Error {
        ErrorKind::Custom(desc.to_string()).into()
    }
}

impl serde::ser::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ErrorKind::Custom(msg.to_string()).into()
    }
}
<commit_msg>Remove dyn<commit_after>use std::error::Error as StdError;
use std::io;
use std::str::Utf8Error;
use std::{error, fmt};

use serde;

/// The result of a serialization or deserialization operation.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An error that can be produced during (de)serializing.
pub type Error = Box<ErrorKind>;

/// The kind of error that can be produced during a serialization or deserialization.
#[derive(Debug)]
pub enum ErrorKind {
    /// If the error stems from the reader/writer that is being used
    /// during (de)serialization, that error will be stored and returned here.
    Io(io::Error),
    /// Returned if the deserializer attempts to deserialize a string that is not valid utf8
    InvalidUtf8Encoding(Utf8Error),
    /// Returned if the deserializer attempts to deserialize a bool that was
    /// not encoded as either a 1 or a 0
    InvalidBoolEncoding(u8),
    /// Returned if the deserializer attempts to deserialize a char that is not in the correct format.
    InvalidCharEncoding,
    /// Returned if the deserializer attempts to deserialize the tag of an enum that is
    /// not in the expected ranges
    InvalidTagEncoding(usize),
    /// Serde has a deserialize_any method that lets the format hint to the
    /// object which route to take in deserializing.
    DeserializeAnyNotSupported,
    /// If (de)serializing a message takes more than the provided size limit, this
    /// error is returned.
    SizeLimit,
    /// Bincode can not encode sequences of unknown length (like iterators).
    SequenceMustHaveLength,
    /// A custom error message from Serde.
    Custom(String),
}

impl StdError for ErrorKind {
    fn description(&self) -> &str {
        match *self {
            ErrorKind::Io(ref err) => error::Error::description(err),
            ErrorKind::InvalidUtf8Encoding(_) => "string is not valid utf8",
            ErrorKind::InvalidBoolEncoding(_) => "invalid u8 while decoding bool",
            ErrorKind::InvalidCharEncoding => "char is not valid",
            ErrorKind::InvalidTagEncoding(_) => "tag for enum is not valid",
            ErrorKind::SequenceMustHaveLength => {
                "Bincode can only encode sequences and maps that have a knowable size ahead of time"
            }
            ErrorKind::DeserializeAnyNotSupported => {
                "Bincode doesn't support serde::Deserializer::deserialize_any"
            }
            ErrorKind::SizeLimit => "the size limit has been reached",
            ErrorKind::Custom(ref msg) => msg,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ErrorKind::Io(ref err) => Some(err),
            ErrorKind::InvalidUtf8Encoding(_) => None,
            ErrorKind::InvalidBoolEncoding(_) => None,
            ErrorKind::InvalidCharEncoding => None,
            ErrorKind::InvalidTagEncoding(_) => None,
            ErrorKind::SequenceMustHaveLength => None,
            ErrorKind::DeserializeAnyNotSupported => None,
            ErrorKind::SizeLimit => None,
            ErrorKind::Custom(_) => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        ErrorKind::Io(err).into()
    }
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ErrorKind::Io(ref ioerr) => write!(fmt, "io error: {}", ioerr),
            ErrorKind::InvalidUtf8Encoding(ref e) => write!(fmt, "{}: {}", self.description(), e),
            ErrorKind::InvalidBoolEncoding(b) => {
                write!(fmt, "{}, expected 0 or 1, found {}", self.description(), b)
            }
            ErrorKind::InvalidCharEncoding => write!(fmt, "{}", self.description()),
            ErrorKind::InvalidTagEncoding(tag) => {
                write!(fmt, "{}, found {}", self.description(), tag)
            }
            ErrorKind::SequenceMustHaveLength => write!(fmt, "{}", self.description()),
            ErrorKind::SizeLimit => write!(fmt, "{}", self.description()),
            ErrorKind::DeserializeAnyNotSupported => write!(
                fmt,
                "Bincode does not support the serde::Deserializer::deserialize_any method"
            ),
            ErrorKind::Custom(ref s) => s.fmt(fmt),
        }
    }
}

impl serde::de::Error for Error {
    fn custom<T: fmt::Display>(desc: T) -> Error {
        ErrorKind::Custom(desc.to_string()).into()
    }
}

impl serde::ser::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ErrorKind::Custom(msg.to_string()).into()
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};

use buffer::Cursor;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug)]
pub struct Error {
    span: Span,
    message: String,
}

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate syn;
    /// #
    /// use syn::{Ident, LitStr, Token};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            span: span,
            message: message.to_string(),
        }
    }

    pub fn span(&self) -> Span {
        self.span
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn into_compile_error(self) -> TokenStream {
        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", self.span)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(self.span);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(self.span);
                        string
                    })])
                });
                group.set_span(self.span);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<commit_msg>Provide Clone for Error<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};

use buffer::Cursor;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug, Clone)]
pub struct Error {
    span: Span,
    message: String,
}

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate syn;
    /// #
    /// use syn::{Ident, LitStr, Token};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            span: span,
            message: message.to_string(),
        }
    }

    pub fn span(&self) -> Span {
        self.span
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn into_compile_error(self) -> TokenStream {
        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", self.span)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(self.span);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(self.span);
                        string
                    })])
                });
                group.set_span(self.span);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<|endoftext|>


<commit_before>#![doc="Defines errors related to SciRust library
"]

// std imports

// local imports

/// Enum for errors related to SciRust library
#[deriving(Show)]
pub enum SRError{

    /******************************************************
     *
     *   General matrix operation errors
     *
     *******************************************************/

    /// The matrix is empty
    EmptyMatrix,
    /// The dimensions of two matrices mismatch
    DimensionsMismatch,
    /// The matrix is not a square matrix
    IsNotSquareMatrix,
    /// The matrix is not a vector
    IsNotAVector,
    /// Indicates that a matrix is not full rank
    IsNotFullRankMatrix,
    /// Indicates that the matrix is full rank
    IsFullRankMatrix,
    /// The matrix is singular
    IsSingular,
    /// The matrix is invertible (non-singular)
    IsNonSingular,
    /// The matrix is positive definite
    IsPositiveDefinite,
    /// The matrix is positive semi definite
    IsPositiveSemiDefinite,
    /// The matrix is negative definite
    IsNegativeDefinite,
    /// The matrix is negative semi definite
    IsNegativeSemiDefinite,
    /// The matrix is non-definite
    IsNonDefinite,

    /******************************************************
     *
     *   Errors related to solving a system of linear equations
     *
     *******************************************************/

    /// The dimensions of left and right hand side don't match
    LRDimensionMismatch,
    /// There is no solution to the system of equations
    NoSolution,
    /// There are infinite solutions to the system of equations.
    InfiniteSolutions,

    /******************************************************
     *
     *   Discrete numbers related stuff
     *
     *******************************************************/

    /// The number is not a power of two
    IsNotPowerOfTwo,

}

impl SRError{

    /// Converts enum values to string representation
    pub fn to_string(&self) -> String {
        match *self{
            //  Matrices
            SRError::EmptyMatrix => format!("Matrix is empty"),
            SRError::DimensionsMismatch => format!("Dimensions don't match"),
            SRError::IsNotSquareMatrix => format!("Matrix is not square"),
            SRError::IsNotAVector => format!("Matrix is not a vector"),
            SRError::IsNotFullRankMatrix => format!("Matrix is not full rank"),
            SRError::IsFullRankMatrix => format!("Matrix is full rank"),
            SRError::IsSingular => format!("Matrix is singular"),
            SRError::IsNonSingular => format!("Matrix is not singular"),
            SRError::IsPositiveDefinite => format!("Matrix is positive definite"),
            SRError::IsPositiveSemiDefinite => format!("Matrix is positive semi-definite"),
            SRError::IsNegativeDefinite => format!("Matrix is negative definite"),
            SRError::IsNegativeSemiDefinite => format!("Matrix is negative semi-definite"),
            SRError::IsNonDefinite => format!("Matrix is non-definite"),
            // Linear systems
            SRError::LRDimensionMismatch => format!("The dimensions of LHS and RHS don't match"),
            SRError::NoSolution => format!("No solution"),
            SRError::InfiniteSolutions => format!("Infinite solutions"),
            // Discrete numbers
            SRError::IsNotPowerOfTwo => format!("Number is not power of two"),

        }
    }
}

<commit_msg>SRResult type added.<commit_after>#![doc="Defines errors related to SciRust library
"]

// std imports

// local imports

/// Enum for errors related to SciRust library
#[deriving(Show)]
pub enum SRError{

    /******************************************************
     *
     *   General matrix operation errors
     *
     *******************************************************/

    /// The matrix is empty
    EmptyMatrix,
    /// The dimensions of two matrices mismatch
    DimensionsMismatch,
    /// The matrix is not a square matrix
    IsNotSquareMatrix,
    /// The matrix is not a vector
    IsNotAVector,
    /// Indicates that a matrix is not full rank
    IsNotFullRankMatrix,
    /// Indicates that the matrix is full rank
    IsFullRankMatrix,
    /// The matrix is singular
    IsSingular,
    /// The matrix is invertible (non-singular)
    IsNonSingular,
    /// The matrix is positive definite
    IsPositiveDefinite,
    /// The matrix is positive semi definite
    IsPositiveSemiDefinite,
    /// The matrix is negative definite
    IsNegativeDefinite,
    /// The matrix is negative semi definite
    IsNegativeSemiDefinite,
    /// The matrix is non-definite
    IsNonDefinite,

    /******************************************************
     *
     *   Errors related to solving a system of linear equations
     *
     *******************************************************/

    /// The dimensions of left and right hand side don't match
    LRDimensionMismatch,
    /// There is no solution to the system of equations
    NoSolution,
    /// There are infinite solutions to the system of equations.
    InfiniteSolutions,

    /******************************************************
     *
     *   Discrete numbers related stuff
     *
     *******************************************************/

    /// The number is not a power of two
    IsNotPowerOfTwo,

}

///A convenient typedef of the return value of SciRust API
/// whenever applicable.
type SRResult<T> = Result<T, SRError>;

impl SRError{

    /// Converts enum values to string representation
    pub fn to_string(&self) -> String {
        match *self{
            //  Matrices
            SRError::EmptyMatrix => format!("Matrix is empty"),
            SRError::DimensionsMismatch => format!("Dimensions don't match"),
            SRError::IsNotSquareMatrix => format!("Matrix is not square"),
            SRError::IsNotAVector => format!("Matrix is not a vector"),
            SRError::IsNotFullRankMatrix => format!("Matrix is not full rank"),
            SRError::IsFullRankMatrix => format!("Matrix is full rank"),
            SRError::IsSingular => format!("Matrix is singular"),
            SRError::IsNonSingular => format!("Matrix is not singular"),
            SRError::IsPositiveDefinite => format!("Matrix is positive definite"),
            SRError::IsPositiveSemiDefinite => format!("Matrix is positive semi-definite"),
            SRError::IsNegativeDefinite => format!("Matrix is negative definite"),
            SRError::IsNegativeSemiDefinite => format!("Matrix is negative semi-definite"),
            SRError::IsNonDefinite => format!("Matrix is non-definite"),
            // Linear systems
            SRError::LRDimensionMismatch => format!("The dimensions of LHS and RHS don't match"),
            SRError::NoSolution => format!("No solution"),
            SRError::InfiniteSolutions => format!("Infinite solutions"),
            // Discrete numbers
            SRError::IsNotPowerOfTwo => format!("Number is not power of two"),

        }
    }
}

<|endoftext|>