<commit_before>use crate::Store;
use std::borrow::Cow;
use std::sync::Arc;
use types::{BeaconBlock, BeaconState, BeaconStateError, EthSpec, Hash256, Slot};

/// Implemented for types that have ancestors (e.g., blocks, states) that may be iterated over.
///
/// ## Note
///
/// It is assumed that all ancestors for this object are stored in the database. If this is not the
/// case, the iterator will start returning `None` prior to genesis.
pub trait AncestorIter<U: Store, I: Iterator> {
    /// Returns an iterator over the roots of the ancestors of `self`.
    fn try_iter_ancestor_roots(&self, store: Arc<U>) -> Option<I>;
}

impl<'a, U: Store, E: EthSpec> AncestorIter<U, BlockRootsIterator<'a, E, U>> for BeaconBlock<E> {
    /// Iterates across all the prior block roots of `self`, starting at the most recent and ending
    /// at genesis.
    fn try_iter_ancestor_roots(&self, store: Arc<U>) -> Option<BlockRootsIterator<'a, E, U>> {
        let state = store.get::<BeaconState<E>>(&self.state_root).ok()??;

        Some(BlockRootsIterator::owned(store, state))
    }
}

impl<'a, U: Store, E: EthSpec> AncestorIter<U, StateRootsIterator<'a, E, U>> for BeaconState<E> {
    /// Iterates across all the prior state roots of `self`, starting at the most recent and ending
    /// at genesis.
    fn try_iter_ancestor_roots(&self, store: Arc<U>) -> Option<StateRootsIterator<'a, E, U>> {
        // The `self.clone()` here is wasteful.
        Some(StateRootsIterator::owned(store, self.clone(), self.slot))
    }
}

#[derive(Clone)]
pub struct StateRootsIterator<'a, T: EthSpec, U> {
    store: Arc<U>,
    beacon_state: Cow<'a, BeaconState<T>>,
    slot: Slot,
}

impl<'a, T: EthSpec, U: Store> StateRootsIterator<'a, T, U> {
    pub fn new(store: Arc<U>, beacon_state: &'a BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Borrowed(beacon_state),
        }
    }

    pub fn owned(store: Arc<U>, beacon_state: BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Owned(beacon_state),
        }
    }
}

impl<'a, T: EthSpec, U: Store> Iterator for StateRootsIterator<'a, T, U> {
    type Item = (Hash256, Slot);

    fn next(&mut self) -> Option<Self::Item> {
        if (self.slot == 0) || (self.slot > self.beacon_state.slot) {
            return None;
        }

        self.slot -= 1;

        match self.beacon_state.get_state_root(self.slot) {
            Ok(root) => Some((*root, self.slot)),
            Err(BeaconStateError::SlotOutOfBounds) => {
                // Read a `BeaconState` from the store that has access to prior historical root.
                let beacon_state: BeaconState<T> = {
                    let new_state_root = self.beacon_state.get_oldest_state_root().ok()?;

                    self.store.get(&new_state_root).ok()?
                }?;

                self.beacon_state = Cow::Owned(beacon_state);

                let root = self.beacon_state.get_state_root(self.slot).ok()?;

                Some((*root, self.slot))
            }
            _ => None,
        }
    }
}

#[derive(Clone)]
/// Extends `BlockRootsIterator`, returning `BeaconBlock` instances, instead of their roots.
pub struct BlockIterator<'a, T: EthSpec, U> {
    roots: BlockRootsIterator<'a, T, U>,
}

impl<'a, T: EthSpec, U: Store> BlockIterator<'a, T, U> {
    /// Create a new iterator over all blocks in the given `beacon_state` and prior states.
    pub fn new(store: Arc<U>, beacon_state: &'a BeaconState<T>) -> Self {
        Self {
            roots: BlockRootsIterator::new(store, beacon_state),
        }
    }

    /// Create a new iterator over all blocks in the given `beacon_state` and prior states.
    pub fn owned(store: Arc<U>, beacon_state: BeaconState<T>) -> Self {
        Self {
            roots: BlockRootsIterator::owned(store, beacon_state),
        }
    }
}

impl<'a, T: EthSpec, U: Store> Iterator for BlockIterator<'a, T, U> {
    type Item = BeaconBlock<T>;

    fn next(&mut self) -> Option<Self::Item> {
        let (root, _slot) = self.roots.next()?;
        self.roots.store.get(&root).ok()?
    }
}

/// Iterates backwards through block roots. If any specified slot is unable to be retrieved, the
/// iterator returns `None` indefinitely.
///
/// Uses the `block_roots` field of `BeaconState` to as the source of block roots and will
/// perform a lookup on the `Store` for a prior `BeaconState` if `block_roots` has been
/// exhausted.
///
/// Returns `None` for roots prior to genesis or when there is an error reading from `Store`.
#[derive(Clone)]
pub struct BlockRootsIterator<'a, T: EthSpec, U> {
    store: Arc<U>,
    beacon_state: Cow<'a, BeaconState<T>>,
    slot: Slot,
}

impl<'a, T: EthSpec, U: Store> BlockRootsIterator<'a, T, U> {
    /// Create a new iterator over all block roots in the given `beacon_state` and prior states.
    pub fn new(store: Arc<U>, beacon_state: &'a BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Borrowed(beacon_state),
        }
    }

    /// Create a new iterator over all block roots in the given `beacon_state` and prior states.
    pub fn owned(store: Arc<U>, beacon_state: BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Owned(beacon_state),
        }
    }
}

impl<'a, T: EthSpec, U: Store> Iterator for BlockRootsIterator<'a, T, U> {
    type Item = (Hash256, Slot);

    fn next(&mut self) -> Option<Self::Item> {
        if (self.slot == 0) || (self.slot > self.beacon_state.slot) {
            return None;
        }

        self.slot -= 1;

        match self.beacon_state.get_block_root(self.slot) {
            Ok(root) => Some((*root, self.slot)),
            Err(BeaconStateError::SlotOutOfBounds) => {
                // Read a `BeaconState` from the store that has access to prior historical root.
                let beacon_state: BeaconState<T> = {
                    // Load the earliest state from disk.
                    let new_state_root = self.beacon_state.get_oldest_state_root().ok()?;

                    self.store.get(&new_state_root).ok()?
                }?;

                self.beacon_state = Cow::Owned(beacon_state);

                let root = self.beacon_state.get_block_root(self.slot).ok()?;

                Some((*root, self.slot))
            }
            _ => None,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::MemoryStore;
    use types::{test_utils::TestingBeaconStateBuilder, Keypair, MainnetEthSpec};

    fn get_state<T: EthSpec>() -> BeaconState<T> {
        let builder = TestingBeaconStateBuilder::from_single_keypair(
            0,
            &Keypair::random(),
            &T::default_spec(),
        );
        let (state, _keypairs) = builder.build();
        state
    }

    #[test]
    fn block_root_iter() {
        let store = Arc::new(MemoryStore::open());
        let slots_per_historical_root = MainnetEthSpec::slots_per_historical_root();

        let mut state_a: BeaconState<MainnetEthSpec> = get_state();
        let mut state_b: BeaconState<MainnetEthSpec> = get_state();

        state_a.slot = Slot::from(slots_per_historical_root);
        state_b.slot = Slot::from(slots_per_historical_root * 2);

        let mut hashes = (0..).into_iter().map(|i| Hash256::from_low_u64_be(i));

        for root in &mut state_a.block_roots[..] {
            *root = hashes.next().unwrap()
        }
        for root in &mut state_b.block_roots[..] {
            *root = hashes.next().unwrap()
        }

        let state_a_root = hashes.next().unwrap();
        state_b.state_roots[0] = state_a_root;
        store.put(&state_a_root, &state_a).unwrap();

        let iter = BlockRootsIterator::new(store.clone(), &state_b);

        assert!(
            iter.clone().find(|(_root, slot)| *slot == 0).is_some(),
            "iter should contain zero slot"
        );

        let mut collected: Vec<(Hash256, Slot)> = iter.collect();
        collected.reverse();

        let expected_len = 2 * MainnetEthSpec::slots_per_historical_root();

        assert_eq!(collected.len(), expected_len);

        for i in 0..expected_len {
            assert_eq!(collected[i].0, Hash256::from_low_u64_be(i as u64));
        }
    }

    #[test]
    fn state_root_iter() {
        let store = Arc::new(MemoryStore::open());
        let slots_per_historical_root = MainnetEthSpec::slots_per_historical_root();

        let mut state_a: BeaconState<MainnetEthSpec> = get_state();
        let mut state_b: BeaconState<MainnetEthSpec> = get_state();

        state_a.slot = Slot::from(slots_per_historical_root);
        state_b.slot = Slot::from(slots_per_historical_root * 2);

        let mut hashes = (0..).into_iter().map(|i| Hash256::from_low_u64_be(i));

        for slot in 0..slots_per_historical_root {
            state_a
                .set_state_root(Slot::from(slot), hashes.next().unwrap())
                .expect(&format!("should set state_a slot {}", slot));
        }
        for slot in slots_per_historical_root..slots_per_historical_root * 2 {
            state_b
                .set_state_root(Slot::from(slot), hashes.next().unwrap())
                .expect(&format!("should set state_b slot {}", slot));
        }

        let state_a_root = Hash256::from_low_u64_be(slots_per_historical_root as u64);
        let state_b_root = Hash256::from_low_u64_be(slots_per_historical_root as u64 * 2);

        store.put(&state_a_root, &state_a).unwrap();
        store.put(&state_b_root, &state_b).unwrap();

        let iter = StateRootsIterator::new(store.clone(), &state_b);

        assert!(
            iter.clone().find(|(_root, slot)| *slot == 0).is_some(),
            "iter should contain zero slot"
        );

        let mut collected: Vec<(Hash256, Slot)> = iter.collect();
        collected.reverse();

        let expected_len = MainnetEthSpec::slots_per_historical_root() * 2;

        assert_eq!(collected.len(), expected_len, "collection length incorrect");

        for i in 0..expected_len {
            let (hash, slot) = collected[i];

            assert_eq!(slot, i as u64, "slot mismatch at {}: {} vs {}", i, slot, i);

            assert_eq!(
                hash,
                Hash256::from_low_u64_be(i as u64),
                "hash mismatch at {}",
                i
            );
        }
    }
}
<commit_msg>Fix compile error in store iters<commit_after>use crate::Store;
use std::borrow::Cow;
use std::sync::Arc;
use types::{BeaconBlock, BeaconState, BeaconStateError, EthSpec, Hash256, Slot};

/// Implemented for types that have ancestors (e.g., blocks, states) that may be iterated over.
///
/// ## Note
///
/// It is assumed that all ancestors for this object are stored in the database. If this is not the
/// case, the iterator will start returning `None` prior to genesis.
pub trait AncestorIter<U: Store, I: Iterator> {
    /// Returns an iterator over the roots of the ancestors of `self`.
    fn try_iter_ancestor_roots(&self, store: Arc<U>) -> Option<I>;
}

impl<'a, U: Store, E: EthSpec> AncestorIter<U, BlockRootsIterator<'a, E, U>> for BeaconBlock<E> {
    /// Iterates across all available prior block roots of `self`, starting at the most recent and ending
    /// at genesis.
    fn try_iter_ancestor_roots(&self, store: Arc<U>) -> Option<BlockRootsIterator<'a, E, U>> {
        let state = store.get::<BeaconState<E>>(&self.state_root).ok()??;

        Some(BlockRootsIterator::owned(store, state))
    }
}

impl<'a, U: Store, E: EthSpec> AncestorIter<U, StateRootsIterator<'a, E, U>> for BeaconState<E> {
    /// Iterates across all available prior state roots of `self`, starting at the most recent and ending
    /// at genesis.
    fn try_iter_ancestor_roots(&self, store: Arc<U>) -> Option<StateRootsIterator<'a, E, U>> {
        // The `self.clone()` here is wasteful.
        Some(StateRootsIterator::owned(store, self.clone()))
    }
}

#[derive(Clone)]
pub struct StateRootsIterator<'a, T: EthSpec, U> {
    store: Arc<U>,
    beacon_state: Cow<'a, BeaconState<T>>,
    slot: Slot,
}

impl<'a, T: EthSpec, U: Store> StateRootsIterator<'a, T, U> {
    pub fn new(store: Arc<U>, beacon_state: &'a BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Borrowed(beacon_state),
        }
    }

    pub fn owned(store: Arc<U>, beacon_state: BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Owned(beacon_state),
        }
    }
}

impl<'a, T: EthSpec, U: Store> Iterator for StateRootsIterator<'a, T, U> {
    type Item = (Hash256, Slot);

    fn next(&mut self) -> Option<Self::Item> {
        if (self.slot == 0) || (self.slot > self.beacon_state.slot) {
            return None;
        }

        self.slot -= 1;

        match self.beacon_state.get_state_root(self.slot) {
            Ok(root) => Some((*root, self.slot)),
            Err(BeaconStateError::SlotOutOfBounds) => {
                // Read a `BeaconState` from the store that has access to prior historical root.
                let beacon_state: BeaconState<T> = {
                    let new_state_root = self.beacon_state.get_oldest_state_root().ok()?;

                    self.store.get(&new_state_root).ok()?
                }?;

                self.beacon_state = Cow::Owned(beacon_state);

                let root = self.beacon_state.get_state_root(self.slot).ok()?;

                Some((*root, self.slot))
            }
            _ => None,
        }
    }
}

#[derive(Clone)]
/// Extends `BlockRootsIterator`, returning `BeaconBlock` instances, instead of their roots.
pub struct BlockIterator<'a, T: EthSpec, U> {
    roots: BlockRootsIterator<'a, T, U>,
}

impl<'a, T: EthSpec, U: Store> BlockIterator<'a, T, U> {
    /// Create a new iterator over all blocks in the given `beacon_state` and prior states.
    pub fn new(store: Arc<U>, beacon_state: &'a BeaconState<T>) -> Self {
        Self {
            roots: BlockRootsIterator::new(store, beacon_state),
        }
    }

    /// Create a new iterator over all blocks in the given `beacon_state` and prior states.
    pub fn owned(store: Arc<U>, beacon_state: BeaconState<T>) -> Self {
        Self {
            roots: BlockRootsIterator::owned(store, beacon_state),
        }
    }
}

impl<'a, T: EthSpec, U: Store> Iterator for BlockIterator<'a, T, U> {
    type Item = BeaconBlock<T>;

    fn next(&mut self) -> Option<Self::Item> {
        let (root, _slot) = self.roots.next()?;
        self.roots.store.get(&root).ok()?
    }
}

/// Iterates backwards through block roots. If any specified slot is unable to be retrieved, the
/// iterator returns `None` indefinitely.
///
/// Uses the `block_roots` field of `BeaconState` to as the source of block roots and will
/// perform a lookup on the `Store` for a prior `BeaconState` if `block_roots` has been
/// exhausted.
///
/// Returns `None` for roots prior to genesis or when there is an error reading from `Store`.
#[derive(Clone)]
pub struct BlockRootsIterator<'a, T: EthSpec, U> {
    store: Arc<U>,
    beacon_state: Cow<'a, BeaconState<T>>,
    slot: Slot,
}

impl<'a, T: EthSpec, U: Store> BlockRootsIterator<'a, T, U> {
    /// Create a new iterator over all block roots in the given `beacon_state` and prior states.
    pub fn new(store: Arc<U>, beacon_state: &'a BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Borrowed(beacon_state),
        }
    }

    /// Create a new iterator over all block roots in the given `beacon_state` and prior states.
    pub fn owned(store: Arc<U>, beacon_state: BeaconState<T>) -> Self {
        Self {
            store,
            slot: beacon_state.slot,
            beacon_state: Cow::Owned(beacon_state),
        }
    }
}

impl<'a, T: EthSpec, U: Store> Iterator for BlockRootsIterator<'a, T, U> {
    type Item = (Hash256, Slot);

    fn next(&mut self) -> Option<Self::Item> {
        if (self.slot == 0) || (self.slot > self.beacon_state.slot) {
            return None;
        }

        self.slot -= 1;

        match self.beacon_state.get_block_root(self.slot) {
            Ok(root) => Some((*root, self.slot)),
            Err(BeaconStateError::SlotOutOfBounds) => {
                // Read a `BeaconState` from the store that has access to prior historical root.
                let beacon_state: BeaconState<T> = {
                    // Load the earliest state from disk.
                    let new_state_root = self.beacon_state.get_oldest_state_root().ok()?;

                    self.store.get(&new_state_root).ok()?
                }?;

                self.beacon_state = Cow::Owned(beacon_state);

                let root = self.beacon_state.get_block_root(self.slot).ok()?;

                Some((*root, self.slot))
            }
            _ => None,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::MemoryStore;
    use types::{test_utils::TestingBeaconStateBuilder, Keypair, MainnetEthSpec};

    fn get_state<T: EthSpec>() -> BeaconState<T> {
        let builder = TestingBeaconStateBuilder::from_single_keypair(
            0,
            &Keypair::random(),
            &T::default_spec(),
        );
        let (state, _keypairs) = builder.build();
        state
    }

    #[test]
    fn block_root_iter() {
        let store = Arc::new(MemoryStore::open());
        let slots_per_historical_root = MainnetEthSpec::slots_per_historical_root();

        let mut state_a: BeaconState<MainnetEthSpec> = get_state();
        let mut state_b: BeaconState<MainnetEthSpec> = get_state();

        state_a.slot = Slot::from(slots_per_historical_root);
        state_b.slot = Slot::from(slots_per_historical_root * 2);

        let mut hashes = (0..).into_iter().map(|i| Hash256::from_low_u64_be(i));

        for root in &mut state_a.block_roots[..] {
            *root = hashes.next().unwrap()
        }
        for root in &mut state_b.block_roots[..] {
            *root = hashes.next().unwrap()
        }

        let state_a_root = hashes.next().unwrap();
        state_b.state_roots[0] = state_a_root;
        store.put(&state_a_root, &state_a).unwrap();

        let iter = BlockRootsIterator::new(store.clone(), &state_b);

        assert!(
            iter.clone().find(|(_root, slot)| *slot == 0).is_some(),
            "iter should contain zero slot"
        );

        let mut collected: Vec<(Hash256, Slot)> = iter.collect();
        collected.reverse();

        let expected_len = 2 * MainnetEthSpec::slots_per_historical_root();

        assert_eq!(collected.len(), expected_len);

        for i in 0..expected_len {
            assert_eq!(collected[i].0, Hash256::from_low_u64_be(i as u64));
        }
    }

    #[test]
    fn state_root_iter() {
        let store = Arc::new(MemoryStore::open());
        let slots_per_historical_root = MainnetEthSpec::slots_per_historical_root();

        let mut state_a: BeaconState<MainnetEthSpec> = get_state();
        let mut state_b: BeaconState<MainnetEthSpec> = get_state();

        state_a.slot = Slot::from(slots_per_historical_root);
        state_b.slot = Slot::from(slots_per_historical_root * 2);

        let mut hashes = (0..).into_iter().map(|i| Hash256::from_low_u64_be(i));

        for slot in 0..slots_per_historical_root {
            state_a
                .set_state_root(Slot::from(slot), hashes.next().unwrap())
                .expect(&format!("should set state_a slot {}", slot));
        }
        for slot in slots_per_historical_root..slots_per_historical_root * 2 {
            state_b
                .set_state_root(Slot::from(slot), hashes.next().unwrap())
                .expect(&format!("should set state_b slot {}", slot));
        }

        let state_a_root = Hash256::from_low_u64_be(slots_per_historical_root as u64);
        let state_b_root = Hash256::from_low_u64_be(slots_per_historical_root as u64 * 2);

        store.put(&state_a_root, &state_a).unwrap();
        store.put(&state_b_root, &state_b).unwrap();

        let iter = StateRootsIterator::new(store.clone(), &state_b);

        assert!(
            iter.clone().find(|(_root, slot)| *slot == 0).is_some(),
            "iter should contain zero slot"
        );

        let mut collected: Vec<(Hash256, Slot)> = iter.collect();
        collected.reverse();

        let expected_len = MainnetEthSpec::slots_per_historical_root() * 2;

        assert_eq!(collected.len(), expected_len, "collection length incorrect");

        for i in 0..expected_len {
            let (hash, slot) = collected[i];

            assert_eq!(slot, i as u64, "slot mismatch at {}: {} vs {}", i, slot, i);

            assert_eq!(
                hash,
                Hash256::from_low_u64_be(i as u64),
                "hash mismatch at {}",
                i
            );
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std::env;
use std::fs::File;
use std::error::Error;
use std::path::PathBuf;
use std::io::prelude::*;
use response::{ToOutput, Response};
use request::Request;

/// Convenience method for creating a response from the basic components
/// required (a request body, content type, and response status).
///
/// # Examples
///
/// ```rust
/// use canteen::{Request, Response};
/// use canteen::utils;
///
/// fn handler(_: &Request) -> Response {
///     utils::make_response("Hello, world!", "text/plain", 200)
/// }
/// ```
pub fn make_response<T: ToOutput>(body: T, c_type: &str, status: u16) -> Response {
    let mut res = Response::new();

    res.set_status(status);
    res.set_content_type(c_type);
    res.append(body);

    res
}

/// Replace the URI escape codes with their ASCII equivalents.
pub fn replace_escape(path: &str) -> String {
    let mut fixed = String::from(path);
    let replaces: [(&str, &str); 22] = [
            ("%20", " "),
            ("%3C", "<"),
            ("%3E", ">"),
            ("%23", "#"),
            ("%25", "%"),
            ("%7B", "["),
            ("%7D", ")"),
            ("%7C", "|"),
            ("%5C", "\\"),
            ("%5E", "^"),
            ("%7E", "~"),
            ("%5B", "["),
            ("%5D", ")"),
            ("%60", "`"),
            ("%3B", ";"),
            ("%2F", "/"),
            ("%3F", "?"),
            ("%3A", ":"),
            ("%40", "@"),
            ("%3D", "="),
            ("%26", "&"),
            ("%24", "$"),
    ];

    for &(from, to) in replaces.iter() {
        fixed = fixed.replace(from, to);
    }

    fixed
}

fn err_body(message: &str, path: &str) -> String {
    format!("\
             \

Your request failed

{}: {}
", message, path)
}

/// Default handler function for HTTP 403 errors.
pub fn err_403(req: &Request) -> Response {
    make_response(err_body("forbidden", &req.path), "text/html", 403)
}

/// Default handler function for HTTP 403 errors for XHR.
pub fn err_403_json(message: &str) -> Response {
    make_response(format!("{{ message: 'forbidden: {}' }}", message), "application/json", 403)
}

/// Default handler function for HTTP 404 errors.
pub fn err_404(req: &Request) -> Response {
    make_response(err_body("not found", &req.path), "text/html", 404)
}

/// Default handler function for HTTP 500 errors for XHR.
pub fn err_404_json(message: &str) -> Response {
    make_response(format!("{{ message: 'not found: {}' }}", message), "application/json", 404)
}

/// Default handler function for HTTP 500 errors.
pub fn err_500(req: &Request) -> Response {
    make_response(err_body("internal server error", &req.path), "text/html", 500)
}

/// Default handler function for HTTP 500 errors for XHR.
pub fn err_500_json(message: &str) -> Response {
    make_response(format!("{{ message: 'internal server error: {}' }}", message), "application/json", 500)
}

/// Handler that sends static files relative to the current working directory.
pub fn static_file(req: &Request) -> Response {
    let mut res = Response::new();

    let cwd = env::current_dir().unwrap();
    let clean = replace_escape(&req.path);
    let mut fpath = PathBuf::from(&cwd);
    let mut fbuf: Vec<u8> = Vec::new();

    for chunk in clean.split('/') {
        if chunk == "" || chunk == "." || chunk == ".." {
            /* bzzzzt */
            continue;
        }

        fpath.push(&chunk);
    }

    let file = File::open(&fpath);

    match file {
        Ok(mut f)   => {
            match f.read_to_end(&mut fbuf) {
                Ok(_)   => {
                    res.set_status(200);
                    res.set_content_type("text/plain");
                    res.append(fbuf);
                },
                Err(e)  => {
                    return make_response(err_body("internal server error", e.description()), "text/html", 500);
                },
            }
        },
        Err(_)      => {
            return err_404(&req);
        }
    }

    res
}
<commit_msg>use the full lookup/replace table for percent escape codes, add escape replace test<commit_after>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std::env;
use std::fs::File;
use std::error::Error;
use std::path::PathBuf;
use std::io::prelude::*;
use response::{ToOutput, Response};
use request::Request;

/// Convenience method for creating a response from the basic components
/// required (a request body, content type, and response status).
///
/// # Examples
///
/// ```rust
/// use canteen::{Request, Response};
/// use canteen::utils;
///
/// fn handler(_: &Request) -> Response {
///     utils::make_response("Hello, world!", "text/plain", 200)
/// }
/// ```
pub fn make_response<T: ToOutput>(body: T, c_type: &str, status: u16) -> Response {
    let mut res = Response::new();

    res.set_status(status);
    res.set_content_type(c_type);
    res.append(body);

    res
}

/// Replace the URI escape codes with their ASCII equivalents.
pub fn replace_escape(path: &str) -> String {
    let mut fixed = String::from(path);
    let replaces: [(&str, &str); 175] = [
        ("%20", " "),
        ("%21", "!"),
        ("%22", "\""),
        ("%23", "#"),
        ("%24", "$"),
        ("%25", "%"),
        ("%26", "&"),
        ("%27", "'"),
        ("%28", "("),
        ("%29", ")"),
        ("%2A", "*"),
        ("%2B", "+"),
        ("%2C", ","),
        ("%2D", "-"),
        ("%2E", "."),
        ("%2F", "/"),
        ("%30", "0"),
        ("%31", "1"),
        ("%32", "2"),
        ("%33", "3"),
        ("%34", "4"),
        ("%35", "5"),
        ("%36", "6"),
        ("%37", "7"),
        ("%38", "8"),
        ("%39", "9"),
        ("%3A", ":"),
        ("%3B", ";"),
        ("%3C", "<"),
        ("%3D", "="),
        ("%3E", ">"),
        ("%3F", "?"),
        ("%40", "@"),
        ("%41", "A"),
        ("%42", "B"),
        ("%43", "C"),
        ("%44", "D"),
        ("%45", "E"),
        ("%46", "F"),
        ("%47", "G"),
        ("%48", "H"),
        ("%49", "I"),
        ("%4A", "J"),
        ("%4B", "K"),
        ("%4C", "L"),
        ("%4D", "M"),
        ("%4E", "N"),
        ("%4F", "O"),
        ("%50", "P"),
        ("%51", "Q"),
        ("%52", "R"),
        ("%53", "S"),
        ("%54", "T"),
        ("%55", "U"),
        ("%56", "V"),
        ("%57", "W"),
        ("%58", "X"),
        ("%59", "Y"),
        ("%5A", "Z"),
        ("%5B", "["),
        ("%5C", "\\"),
        ("%5D", "]"),
        ("%5E", "^"),
        ("%5F", "_"),
        ("%60", "`"),
        ("%61", "a"),
        ("%62", "b"),
        ("%63", "c"),
        ("%64", "d"),
        ("%65", "e"),
        ("%66", "f"),
        ("%67", "g"),
        ("%68", "h"),
        ("%69", "i"),
        ("%6A", "j"),
        ("%6B", "k"),
        ("%6C", "l"),
        ("%6D", "m"),
        ("%6E", "n"),
        ("%6F", "o"),
        ("%70", "p"),
        ("%71", "q"),
        ("%72", "r"),
        ("%73", "s"),
        ("%74", "t"),
        ("%75", "u"),
        ("%76", "v"),
        ("%77", "w"),
        ("%78", "x"),
        ("%79", "y"),
        ("%7A", "z"),
        ("%7B", "{"),
        ("%7C", "|"),
        ("%7D", "}"),
        ("%7E", "~"),
        ("%A2", "¢"),
        ("%A3", "£"),
        ("%A5", "¥"),
        ("%A6", "|"),
        ("%A7", "§"),
        ("%AB", "«"),
        ("%AC", "¬"),
        ("%AD", "¯"),
        ("%B0", "º"),
        ("%B1", "±"),
        ("%B2", "ª"),
        ("%B4", ","),
        ("%B5", "µ"),
        ("%BB", "»"),
        ("%BC", "¼"),
        ("%BD", "½"),
        ("%BF", "¿"),
        ("%C0", "À"),
        ("%C1", "Á"),
        ("%C2", "Â"),
        ("%C3", "Ã"),
        ("%C4", "Ä"),
        ("%C5", "Å"),
        ("%C6", "Æ"),
        ("%C7", "Ç"),
        ("%C8", "È"),
        ("%C9", "É"),
        ("%CA", "Ê"),
        ("%CB", "Ë"),
        ("%CC", "Ì"),
        ("%CD", "Í"),
        ("%CE", "Î"),
        ("%CF", "Ï"),
        ("%D0", "Ð"),
        ("%D1", "Ñ"),
        ("%D2", "Ò"),
        ("%D3", "Ó"),
        ("%D4", "Ô"),
        ("%D5", "Õ"),
        ("%D6", "Ö"),
        ("%D8", "Ø"),
        ("%D9", "Ù"),
        ("%DA", "Ú"),
        ("%DB", "Û"),
        ("%DC", "Ü"),
        ("%DD", "Ý"),
        ("%DE", "Þ"),
        ("%DF", "ß"),
        ("%E0", "à"),
        ("%E1", "á"),
        ("%E2", "â"),
        ("%E3", "ã"),
        ("%E4", "ä"),
        ("%E5", "å"),
        ("%E6", "æ"),
        ("%E7", "ç"),
        ("%E8", "è"),
        ("%E9", "é"),
        ("%EA", "ê"),
        ("%EB", "ë"),
        ("%EC", "ì"),
        ("%ED", "í"),
        ("%EE", "î"),
        ("%EF", "ï"),
        ("%F0", "ð"),
        ("%F1", "ñ"),
        ("%F2", "ò"),
        ("%F3", "ó"),
        ("%F4", "ô"),
        ("%F5", "õ"),
        ("%F6", "ö"),
        ("%F7", "÷"),
        ("%F8", "ø"),
        ("%F9", "ù"),
        ("%FA", "ú"),
        ("%FB", "û"),
        ("%FC", "ü"),
        ("%FD", "ý"),
        ("%FE", "þ"),
        ("%FF", "ÿ"),
    ];

    for &(from, to) in replaces.iter() {
        fixed = fixed.replace(from, to);
    }

    fixed
}

fn err_body(message: &str, path: &str) -> String {
    format!("\
             \

Your request failed

{}: {}
", message, path)
}

/// Default handler function for HTTP 403 errors.
pub fn err_403(req: &Request) -> Response {
    make_response(err_body("forbidden", &req.path), "text/html", 403)
}

/// Default handler function for HTTP 403 errors for XHR.
pub fn err_403_json(message: &str) -> Response {
    make_response(format!("{{ message: 'forbidden: {}' }}", message), "application/json", 403)
}

/// Default handler function for HTTP 404 errors.
pub fn err_404(req: &Request) -> Response {
    make_response(err_body("not found", &req.path), "text/html", 404)
}

/// Default handler function for HTTP 500 errors for XHR.
pub fn err_404_json(message: &str) -> Response {
    make_response(format!("{{ message: 'not found: {}' }}", message), "application/json", 404)
}

/// Default handler function for HTTP 500 errors.
pub fn err_500(req: &Request) -> Response {
    make_response(err_body("internal server error", &req.path), "text/html", 500)
}

/// Default handler function for HTTP 500 errors for XHR.
pub fn err_500_json(message: &str) -> Response {
    make_response(format!("{{ message: 'internal server error: {}' }}", message), "application/json", 500)
}

/// Handler that sends static files relative to the current working directory.
pub fn static_file(req: &Request) -> Response {
    let mut res = Response::new();

    let cwd = env::current_dir().unwrap();
    let clean = replace_escape(&req.path);
    let mut fpath = PathBuf::from(&cwd);
    let mut fbuf: Vec<u8> = Vec::new();

    for chunk in clean.split('/') {
        if chunk == "" || chunk == "." || chunk == ".." {
            /* bzzzzt */
            continue;
        }

        fpath.push(&chunk);
    }

    let file = File::open(&fpath);

    match file {
        Ok(mut f)   => {
            match f.read_to_end(&mut fbuf) {
                Ok(_)   => {
                    res.set_status(200);
                    res.set_content_type("text/plain");
                    res.append(fbuf);
                },
                Err(e)  => {
                    return make_response(err_body("internal server error", e.description()), "text/html", 500);
                },
            }
        },
        Err(_)      => {
            return err_404(&req);
        }
    }

    res
}

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

    #[test]
    fn test_replace_escape() {
        let path = "%61%62%63%64%65%66%67%68%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77%78%79%7A";
        assert_eq!("abcdefghijklmnopqrstuvwxyz", replace_escape(&path));
    }
}
<|endoftext|>


<commit_before>extern crate base64;

use self::base64::encode;
use http::retrieve_asset;
use regex::Regex;
use url::{ParseError, Url};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
    static ref EMPTY_STRING: String = String::new();
}

static MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime == "" {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    let mut re = String::new();

    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            re = String::from_utf8(item[1].to_vec()).unwrap();
            break;
        }
    }

    re
}

pub fn url_has_protocol(url: &str) -> bool {
    HAS_PROTOCOL.is_match(&url.to_lowercase())
}

pub fn is_data_url(url: &str) -> Result<bool, ParseError> {
    match Url::parse(url) {
        Ok(parsed_url) => Ok(parsed_url.scheme() == "data"),
        Err(err) => Err(err),
    }
}

pub fn is_valid_url(path: &str) -> bool {
    REGEX_URL.is_match(path)
}

pub fn resolve_url(from: &str, to: &str) -> Result<String, ParseError> {
    let result = if is_valid_url(to) {
        to.to_string()
    } else {
        Url::parse(from)?.join(to)?.to_string()
    };

    Ok(result)
}

pub fn resolve_css_imports(
    css_string: &str,
    href: &str,
    opt_user_agent: &str,
    opt_silent: bool,
    opt_insecure: bool,
) -> String {
    let mut resolved_css = String::from(css_string);
    let re = Regex::new(r###"(?P<import>@import )?url\((?P<to_repl>"?(?P<url>[^"]+)"?)\)"###).unwrap();

    for link in re.captures_iter(&css_string) {
        let target_link = link.name("url").unwrap().as_str();

        // Generate absolute URL for content
        let embedded_url = match resolve_url(href, target_link) {
            Ok(url) => url,
            Err(_) => continue, // Malformed URL
        };

        // Download the asset.  If it's more CSS, resolve that too
        let content = match link.name("import") {

            // The link is an @import link
            Some(_) => retrieve_asset(
                        &embedded_url,
                        false,      // Formating as data URL will be done later
                        "text/css", // Expect CSS
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )
                    .map(|(content, _)| resolve_css_imports(
                        &content,
                        &embedded_url,
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )),

            // The link is some other, non-@import link
            None => retrieve_asset(
                        &embedded_url,
                        true, // Format as data URL
                        "",   // Unknown MIME type
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    ).map(|(a, _)| a),

        }.unwrap_or_else(|_| EMPTY_STRING.clone());

        let replacement = format!("\"{}\"", &content);

        let t = resolved_css
            .replace(link.name("to_repl").unwrap().as_str(), &replacement)
            .to_string();
        resolved_css = t.clone();
    }

    let encoded_css = data_to_dataurl("text/css", resolved_css.as_bytes());

    encoded_css.to_string()
}
<commit_msg>Added fallback to absolute URL on failure to resolve CSS stylesheet @imports<commit_after>extern crate base64;

use self::base64::encode;
use http::retrieve_asset;
use regex::Regex;
use url::{ParseError, Url};
use std::io::{stderr, Write};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
    static ref EMPTY_STRING: String = String::new();
}

static MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime == "" {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    let mut re = String::new();

    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            re = String::from_utf8(item[1].to_vec()).unwrap();
            break;
        }
    }

    re
}

pub fn url_has_protocol(url: &str) -> bool {
    HAS_PROTOCOL.is_match(&url.to_lowercase())
}

pub fn is_data_url(url: &str) -> Result<bool, ParseError> {
    match Url::parse(url) {
        Ok(parsed_url) => Ok(parsed_url.scheme() == "data"),
        Err(err) => Err(err),
    }
}

pub fn is_valid_url(path: &str) -> bool {
    REGEX_URL.is_match(path)
}

pub fn resolve_url(from: &str, to: &str) -> Result<String, ParseError> {
    let result = if is_valid_url(to) {
        to.to_string()
    } else {
        Url::parse(from)?.join(to)?.to_string()
    };

    Ok(result)
}

pub fn resolve_css_imports(
    css_string: &str,
    href: &str,
    opt_user_agent: &str,
    opt_silent: bool,
    opt_insecure: bool,
) -> String {
    let mut resolved_css = String::from(css_string);
    let re = Regex::new(r###"(?P<import>@import )?url\((?P<to_repl>"?(?P<url>[^"]+)"?)\)"###).unwrap();

    for link in re.captures_iter(&css_string) {
        let target_link = link.name("url").unwrap().as_str();

        // Generate absolute URL for content
        let embedded_url = match resolve_url(href, target_link) {
            Ok(url) => url,
            Err(_) => continue, // Malformed URL
        };

        // Download the asset.  If it's more CSS, resolve that too
        let content = match link.name("import") {

            // The link is an @import link
            Some(_) => retrieve_asset(
                        &embedded_url,
                        false,      // Formating as data URL will be done later
                        "text/css", // Expect CSS
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )
                    .map(|(content, _)| resolve_css_imports(
                        &content,
                        &embedded_url,
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )),

            // The link is some other, non-@import link
            None => retrieve_asset(
                        &embedded_url,
                        true, // Format as data URL
                        "",   // Unknown MIME type
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    ).map(|(a, _)| a),

        }.unwrap_or_else(|e| {
            writeln!(
                stderr(),
                "Warning: {}",
                e,
            ).unwrap();

            //If failed to resolve, replace with absolute URL
            embedded_url
        });

        let replacement = format!("\"{}\"", &content);

        let t = resolved_css
            .replace(link.name("to_repl").unwrap().as_str(), &replacement)
            .to_string();
        resolved_css = t.clone();
    }

    let encoded_css = data_to_dataurl("text/css", resolved_css.as_bytes());

    encoded_css.to_string()
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
   /// Nil represents nil.
   Nil,
   /// Boolean represents true or false.
   Boolean(bool),
   /// Integer represents an integer.
   Integer(Integer),
   /// Float represents a floating point number.
   Float(Float),
   /// String extending Raw type represents a UTF-8 string.
   String(&'a str),
   /// Binary extending Raw type represents a byte array.
   Binary(&'a [u8]),
   /// Array represents a sequence of objects.
   Array(Vec<ValueRef<'a>>),
   /// Map represents key-value pairs of objects.
   Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
   /// Extended implements Extension interface: represents a tuple of type information and a byte
   /// array where type information is an integer whose meaning is defined by applications.
   Ext(i8, &'a [u8]),
}
<commit_msg>Value: integers and float enums are now Copy.<commit_after>#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
   /// Nil represents nil.
   Nil,
   /// Boolean represents true or false.
   Boolean(bool),
   /// Integer represents an integer.
   Integer(Integer),
   /// Float represents a floating point number.
   Float(Float),
   /// String extending Raw type represents a UTF-8 string.
   String(&'a str),
   /// Binary extending Raw type represents a byte array.
   Binary(&'a [u8]),
   /// Array represents a sequence of objects.
   Array(Vec<ValueRef<'a>>),
   /// Map represents key-value pairs of objects.
   Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
   /// Extended implements Extension interface: represents a tuple of type information and a byte
   /// array where type information is an integer whose meaning is defined by applications.
   Ext(i8, &'a [u8]),
}
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::{fmt, mem, ptr};
use std::ops::{Deref, Index};

use libc::{c_char, c_int, c_uint};
use ffi::core;
use ffi::prelude::LLVMValueRef;
use ffi::LLVMAttribute;
use ffi::core::{
	LLVMConstStringInContext,
	LLVMConstStructInContext,
	LLVMConstVector,

	LLVMGetValueName,
	LLVMSetValueName,

	LLVMGetElementType,
	LLVMGetEntryBasicBlock,
	LLVMAppendBasicBlockInContext,

	LLVMAddAttribute,
	LLVMGetAttribute,
	LLVMRemoveAttribute,

  LLVMAddFunctionAttr,
  LLVMGetFunctionAttr,
  LLVMRemoveFunctionAttr,

  LLVMGetParam,
  LLVMCountParams,
  LLVMGetFirstParam,
  LLVMGetNextParam,

  LLVMGetInitializer,
  LLVMSetInitializer,

  LLVMIsAGlobalValue,
  LLVMGetUndef,
  LLVMTypeOf,
};

use block::BasicBlock;
use context::{Context, GetContext};
use util::{self, CastFrom};
use ty::{FunctionType, Type};

/// A typed value that can be used as an operand in instructions.
pub struct Value;
native_ref!(&Value = LLVMValueRef);
impl_display!(Value, LLVMPrintValueToString);

impl Value
{
  /// Create a new constant struct from the values given.
  pub fn new_struct<'a>(context: &'a Context,
  	                    vals: &[&'a Value], packed: bool) -> &'a Value
  {
    unsafe {
    	LLVMConstStructInContext(context.into(),
    	                         vals.as_ptr() as *mut LLVMValueRef,
    		                       vals.len() as c_uint,
    		                       packed as c_int)
    }.into()
  }

  /// Create a new constant vector from the values given.
  pub fn new_vector<'a>(vals: &[&'a Value]) -> &'a Value
  {
    unsafe {
    	LLVMConstVector(vals.as_ptr() as *mut LLVMValueRef,
    		              vals.len() as c_uint)
    }.into()
  }

  /// Create a new constant C string from the text given.
  pub fn new_string<'a>(context: &'a Context,
  	                    text: &str,
  	                    rust_style: bool) -> &'a Value
  {
    unsafe {
      let ptr = text.as_ptr() as *const c_char;
      let len = text.len() as c_uint;
      LLVMConstStringInContext(context.into(), ptr, len, rust_style as c_int).into()
    }
  }

  /// Create a new constant undefined value of the given type.
  pub fn new_undef<'a>(ty: &'a Type) -> &'a Value
  {
    unsafe { LLVMGetUndef(ty.into()) }.into()
  }

  /// Returns the name of this value, or `None` if it lacks a name
  pub fn get_name(&self) -> Option<&str>
  {
    unsafe {
      let c_name = LLVMGetValueName(self.into());
      util::to_null_str(c_name as *mut i8)
    }
  }

  /// Sets the name of this value
  pub fn set_name(&self, name: &str)
  {
    let c_name = CString::new(name).unwrap();
    unsafe {
      LLVMSetValueName(self.into(), c_name.as_ptr())
    }
  }

  /// Returns the type of this value
  pub fn get_type(&self) -> &Type
  {
    unsafe { LLVMTypeOf(self.into()) }.into()
  }
}

pub struct GlobalValue;
native_ref!(&GlobalValue = LLVMValueRef);
deref!(GlobalValue, Value);

impl GlobalValue
{
	/// Sets the initial value for this global.
	pub fn set_initializer(&self, value: &Value)
	{
	  unsafe { LLVMSetInitializer(self.into(), value.into()) }
	}

	/// Gets the initial value for this global.
	pub fn get_initializer(&self) -> &Value
	{
	  unsafe { LLVMGetInitializer(self.into()) }.into()
	}
}

impl CastFrom for GlobalValue
{
  type From = Value;

  fn cast<'a>(val: &'a Value) -> Option<&'a GlobalValue>
  {
    let gv = unsafe { LLVMIsAGlobalValue(val.into()) };
    if gv == ptr::null_mut() {
      None
    } else {
      Some(gv.into())
    }
  }
}

/// Comparative operations on values.
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Predicate
{
  Equal,
  NotEqual,
  GreaterThan,
  GreaterThanOrEqual,
  LessThan,
  LessThanOrEqual
}

/// A function argument.
pub struct Arg;
native_ref!(&Arg = LLVMValueRef);

impl Deref for Arg
{
  type Target = Value;

  fn deref(&self) -> &Value
  {
    unsafe { mem::transmute(self) }
  }
}

impl Arg
{
  /// Add the attribute given to this argument.
  pub fn add_attribute(&self, attr: Attribute)
  {
    unsafe { LLVMAddAttribute(self.into(), attr.into()) }
  }

  /// Add all the attributes given to this argument.
  pub fn add_attributes(&self, attrs: &[Attribute])
  {
    let mut sum = LLVMAttribute::empty();
    for attr in attrs {
      let attr:LLVMAttribute = (*attr).into();
      sum = sum | attr;
    }
    unsafe { LLVMAddAttribute(self.into(), sum.into()) }
  }

  /// Returns true if this argument has the attribute given.
  pub fn has_attribute(&self, attr: Attribute) -> bool
  {
    unsafe {
      let other = LLVMGetAttribute(self.into());
      other.contains(attr.into())
    }
  }

  /// Returns true if this argument has all the attributes given.
  pub fn has_attributes(&self, attrs: &[Attribute]) -> bool
  {
    unsafe {
      let other = LLVMGetAttribute(self.into());
      for &attr in attrs {
        if !other.contains(attr.into()) {
            return false;
        }
      }
      return true;
    }
  }

  /// Remove an attribute from this argument.
  pub fn remove_attribute(&self, attr: Attribute)
  {
    unsafe {
    	LLVMRemoveAttribute(self.into(), attr.into())
    }
  }
}

/// A function that can be called and contains blocks.
pub struct Function;
native_ref!(&Function = LLVMValueRef);

impl Deref for Function
{
  type Target = Value;

  fn deref(&self) -> &Value
  {
    unsafe { mem::transmute(self) }
  }
}

impl Index<usize> for Function
{
  type Output = Arg;

  fn index(&self, index: usize) -> &Arg
  {
    unsafe {
      if index < LLVMCountParams(self.into()) as usize {
        LLVMGetParam(self.into(), index as c_uint).into()
      } else {
        panic!("no such index {} on {:?}", index, self.get_type())
      }
    }
  }
}

impl CastFrom for Function
{
  type From = Value;

  fn cast<'a>(val: &'a Value) -> Option<&'a Function>
  {
    let ty = val.get_type();
    let mut is_func = ty.is_function();

    if let Some(elem) = ty.get_element() {
      is_func = is_func || elem.is_function()
    }

    if is_func {
      Some(unsafe { mem::transmute(val) })
    } else {
      None
    }
  }
}

impl Function
{
  /// Add a basic block with the name given to the function and return it.
  pub fn append<'a>(&'a self, name: &str) -> &'a BasicBlock
  {
    util::with_cstr(name, |ptr| unsafe {
      LLVMAppendBasicBlockInContext(self.get_context().into(), self.into(), ptr).into()
    })
  }

  /// Returns the entry block of this function or `None` if there is none.
  pub fn get_entry(&self) -> Option<&BasicBlock>
  {
    unsafe { mem::transmute(LLVMGetEntryBasicBlock(self.into())) }
  }

  /// Returns the name of this function.
  pub fn get_name(&self) -> &str
  {
    unsafe {
      let c_name = LLVMGetValueName(self.into());
      util::to_str(c_name as *mut i8)
    }
  }

  /// Returns the function signature representing this function's signature.
  pub fn get_signature(&self) -> &FunctionType
  {
    unsafe {
      let ty = LLVMTypeOf(self.into());
      LLVMGetElementType(ty).into()
    }
  }

  /// Add the attribute given to this function.
  pub fn add_attribute(&self, attr: Attribute)
  {
    unsafe { LLVMAddFunctionAttr(self.into(), attr.into()) }
  }

  /// Add all the attributes given to this function.
  pub fn add_attributes(&self, attrs: &[Attribute])
  {
    let mut sum = LLVMAttribute::empty();

    for attr in attrs {
        let attr:LLVMAttribute = (*attr).into();
        sum = sum | attr;
    }

    unsafe { LLVMAddFunctionAttr(self.into(), sum.into()) }
  }

  /// Returns true if the attribute given is set in this function.
  pub fn has_attribute(&self, attr: Attribute) -> bool
  {
    unsafe {
      let other = LLVMGetFunctionAttr(self.into());
      other.contains(attr.into())
    }
  }

  /// Returns true if all the attributes given is set in this function.
  pub fn has_attributes(&self, attrs: &[Attribute]) -> bool
  {
    unsafe {
      let other = LLVMGetFunctionAttr(self.into());

      for &attr in attrs {
          if !other.contains(attr.into()) {
              return false;
          }
      }

      return true;
    }
  }

  /// Remove the attribute given from this function.
  pub fn remove_attribute(&self, attr: Attribute)
  {
    unsafe { LLVMRemoveFunctionAttr(self.into(), attr.into()) }
  }
}

impl<'a> IntoIterator for &'a Function
{
  type Item = &'a Arg;
  type IntoIter = ValueIter<'a, &'a Arg>;

  /// Iterate through the functions in the module
  fn into_iter(self) -> ValueIter<'a, &'a Arg>
  {
 		ValueIter::new(
 			unsafe { LLVMGetFirstParam(self.into()) },
 			LLVMGetNextParam)
  }
}

impl GetContext for Function
{
  fn get_context(&self) -> &Context
  {
    self.get_type().get_context()
  }
}

/// A way of indicating to LLVM how you want arguments / functions to be handled.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(C)]
pub enum Attribute
{
  /// Zero-extended before or after call.
  ZExt =              0b1,
  /// Sign-extended before or after call.
  SExt =              0b10,
  /// Mark the function as not returning.
  NoReturn =          0b100,
  /// Force argument to be passed in register.
  InReg =             0b1000,
  /// Hidden pointer to structure to return.
  StructRet =         0b10000,
  /// Function doesn't unwind stack.
  NoUnwind =          0b100000,
  /// Consider to not alias after call.
  NoAlias =           0b1000000,
  /// Pass structure by value.
  ByVal =             0b10000000,
  /// Nested function static chain.
  Nest =              0b100000000,
  /// Function doesn't access memory.
  ReadNone =          0b1000000000,
  /// Function only reads from memory.
  ReadOnly =          0b10000000000,
  /// Never inline this function.
  NoInline =          0b100000000000,
  /// Always inline this function.
  AlwaysInline =      0b1000000000000,
  /// Optimize this function for size.
  OptimizeForSize =   0b10000000000000,
  /// Stack protection.
  StackProtect =      0b100000000000000,
  /// Stack protection required.
  StackProtectReq =   0b1000000000000000,
  /// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from align(1)).
  Alignment =         0b10000000000000000,
  /// Function creates no aliases of pointer.
  NoCapture =         0b100000000000000000,
  /// Disable redzone.
  NoRedZone =         0b1000000000000000000,
  /// Disable implicit float instructions.
  NoImplicitFloat =   0b10000000000000000000,
  /// Naked function.
  Naked =             0b100000000000000000000,
  /// The source language has marked this function as inline.
  InlineHint =        0b1000000000000000000000,
  /// Alignment of stack for function (3 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from alignstack=(1)).
  StackAlignment =    0b11100000000000000000000000000,
  /// This function returns twice.
  ReturnsTwice =      0b100000000000000000000000000000,
  /// Function must be in unwind table.
  UWTable =           0b1000000000000000000000000000000,
  /// Function is called early/often, so lazy binding isn't effective.
  NonLazyBind =       0b10000000000000000000000000000000
}

impl From<LLVMAttribute> for Attribute
{
  fn from(attr: LLVMAttribute) -> Attribute
  {
    unsafe { mem::transmute(attr) }
  }
}

impl From<Attribute> for LLVMAttribute
{
  fn from(attr: Attribute) -> LLVMAttribute
  {
    unsafe { mem::transmute(attr) }
  }
}

impl GetContext for Value
{
  fn get_context(&self) -> &Context
  {
    self.get_type().get_context()
  }
}

/// Value Iterator implementation.
///
/// T can be all descendent types of LLVMValueRef.
#[derive(Copy, Clone)]
pub struct ValueIter<'a, T: From<LLVMValueRef>> {
  cur    : LLVMValueRef,
  step   : unsafe extern "C" fn(LLVMValueRef) -> LLVMValueRef,
  marker1: ::std::marker::PhantomData<&'a ()>,
  marker2: ::std::marker::PhantomData<T>,
}

impl<'a, T: From<LLVMValueRef>> ValueIter<'a, T>
{
	pub fn new(cur: LLVMValueRef,
		         step: unsafe extern "C" fn(LLVMValueRef) -> LLVMValueRef) -> Self
	{
		ValueIter {
			cur: cur,
			step: step,
			marker1: ::std::marker::PhantomData,
			marker2: ::std::marker::PhantomData
		}
	}
}

impl<'a, T: From<LLVMValueRef>> Iterator for ValueIter<'a, T>
{
  type Item = T;

  fn next(&mut self) -> Option<T>
  {
    let old: LLVMValueRef = self.cur;

    if !old.is_null() {
      self.cur = unsafe { (self.step)(old) };
      Some(old.into())
    } else {
      None
    }
  }
}<commit_msg>Add Function::num_params to return the number of parameters.<commit_after>use std::ffi::CString;
use std::{fmt, mem, ptr};
use std::ops::{Deref, Index};

use libc::{c_char, c_int, c_uint};
use ffi::core;
use ffi::prelude::LLVMValueRef;
use ffi::LLVMAttribute;
use ffi::core::{
	LLVMConstStringInContext,
	LLVMConstStructInContext,
	LLVMConstVector,

	LLVMGetValueName,
	LLVMSetValueName,

	LLVMGetElementType,
	LLVMGetEntryBasicBlock,
	LLVMAppendBasicBlockInContext,

	LLVMAddAttribute,
	LLVMGetAttribute,
	LLVMRemoveAttribute,

  LLVMAddFunctionAttr,
  LLVMGetFunctionAttr,
  LLVMRemoveFunctionAttr,

  LLVMGetParam,
  LLVMCountParams,
  LLVMGetFirstParam,
  LLVMGetNextParam,

  LLVMGetInitializer,
  LLVMSetInitializer,

  LLVMIsAGlobalValue,
  LLVMGetUndef,
  LLVMTypeOf,
};

use block::BasicBlock;
use context::{Context, GetContext};
use util::{self, CastFrom};
use ty::{FunctionType, Type};

/// A typed value that can be used as an operand in instructions.
pub struct Value;
native_ref!(&Value = LLVMValueRef);
impl_display!(Value, LLVMPrintValueToString);

impl Value
{
  /// Create a new constant struct from the values given.
  pub fn new_struct<'a>(context: &'a Context,
  	                    vals: &[&'a Value], packed: bool) -> &'a Value
  {
    unsafe {
    	LLVMConstStructInContext(context.into(),
    	                         vals.as_ptr() as *mut LLVMValueRef,
    		                       vals.len() as c_uint,
    		                       packed as c_int)
    }.into()
  }

  /// Create a new constant vector from the values given.
  pub fn new_vector<'a>(vals: &[&'a Value]) -> &'a Value
  {
    unsafe {
    	LLVMConstVector(vals.as_ptr() as *mut LLVMValueRef,
    		              vals.len() as c_uint)
    }.into()
  }

  /// Create a new constant C string from the text given.
  pub fn new_string<'a>(context: &'a Context,
  	                    text: &str,
  	                    rust_style: bool) -> &'a Value
  {
    unsafe {
      let ptr = text.as_ptr() as *const c_char;
      let len = text.len() as c_uint;
      LLVMConstStringInContext(context.into(), ptr, len, rust_style as c_int).into()
    }
  }

  /// Create a new constant undefined value of the given type.
  pub fn new_undef<'a>(ty: &'a Type) -> &'a Value
  {
    unsafe { LLVMGetUndef(ty.into()) }.into()
  }

  /// Returns the name of this value, or `None` if it lacks a name
  pub fn get_name(&self) -> Option<&str>
  {
    unsafe {
      let c_name = LLVMGetValueName(self.into());
      util::to_null_str(c_name as *mut i8)
    }
  }

  /// Sets the name of this value
  pub fn set_name(&self, name: &str)
  {
    let c_name = CString::new(name).unwrap();
    unsafe {
      LLVMSetValueName(self.into(), c_name.as_ptr())
    }
  }

  /// Returns the type of this value
  pub fn get_type(&self) -> &Type
  {
    unsafe { LLVMTypeOf(self.into()) }.into()
  }
}

pub struct GlobalValue;
native_ref!(&GlobalValue = LLVMValueRef);
deref!(GlobalValue, Value);

impl GlobalValue
{
	/// Sets the initial value for this global.
	pub fn set_initializer(&self, value: &Value)
	{
	  unsafe { LLVMSetInitializer(self.into(), value.into()) }
	}

	/// Gets the initial value for this global.
	pub fn get_initializer(&self) -> &Value
	{
	  unsafe { LLVMGetInitializer(self.into()) }.into()
	}
}

impl CastFrom for GlobalValue
{
  type From = Value;

  fn cast<'a>(val: &'a Value) -> Option<&'a GlobalValue>
  {
    let gv = unsafe { LLVMIsAGlobalValue(val.into()) };
    if gv == ptr::null_mut() {
      None
    } else {
      Some(gv.into())
    }
  }
}

/// Comparative operations on values.
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Predicate
{
  Equal,
  NotEqual,
  GreaterThan,
  GreaterThanOrEqual,
  LessThan,
  LessThanOrEqual
}

/// A function argument.
pub struct Arg;
native_ref!(&Arg = LLVMValueRef);

impl Deref for Arg
{
  type Target = Value;

  fn deref(&self) -> &Value
  {
    unsafe { mem::transmute(self) }
  }
}

impl Arg
{
  /// Add the attribute given to this argument.
  pub fn add_attribute(&self, attr: Attribute)
  {
    unsafe { LLVMAddAttribute(self.into(), attr.into()) }
  }

  /// Add all the attributes given to this argument.
  pub fn add_attributes(&self, attrs: &[Attribute])
  {
    let mut sum = LLVMAttribute::empty();
    for attr in attrs {
      let attr:LLVMAttribute = (*attr).into();
      sum = sum | attr;
    }
    unsafe { LLVMAddAttribute(self.into(), sum.into()) }
  }

  /// Returns true if this argument has the attribute given.
  pub fn has_attribute(&self, attr: Attribute) -> bool
  {
    unsafe {
      let other = LLVMGetAttribute(self.into());
      other.contains(attr.into())
    }
  }

  /// Returns true if this argument has all the attributes given.
  pub fn has_attributes(&self, attrs: &[Attribute]) -> bool
  {
    unsafe {
      let other = LLVMGetAttribute(self.into());
      for &attr in attrs {
        if !other.contains(attr.into()) {
            return false;
        }
      }
      return true;
    }
  }

  /// Remove an attribute from this argument.
  pub fn remove_attribute(&self, attr: Attribute)
  {
    unsafe {
    	LLVMRemoveAttribute(self.into(), attr.into())
    }
  }
}

/// A function that can be called and contains blocks.
pub struct Function;
native_ref!(&Function = LLVMValueRef);

impl Deref for Function
{
  type Target = Value;

  fn deref(&self) -> &Value
  {
    unsafe { mem::transmute(self) }
  }
}

impl Index<usize> for Function
{
  type Output = Arg;

  fn index(&self, index: usize) -> &Arg
  {
    unsafe {
      if index < LLVMCountParams(self.into()) as usize {
        LLVMGetParam(self.into(), index as c_uint).into()
      } else {
        panic!("no such index {} on {:?}", index, self.get_type())
      }
    }
  }
}

impl CastFrom for Function
{
  type From = Value;

  fn cast<'a>(val: &'a Value) -> Option<&'a Function>
  {
    let ty = val.get_type();
    let mut is_func = ty.is_function();

    if let Some(elem) = ty.get_element() {
      is_func = is_func || elem.is_function()
    }

    if is_func {
      Some(unsafe { mem::transmute(val) })
    } else {
      None
    }
  }
}

impl Function
{
  /// Add a basic block with the name given to the function and return it.
  pub fn append<'a>(&'a self, name: &str) -> &'a BasicBlock
  {
    util::with_cstr(name, |ptr| unsafe {
      LLVMAppendBasicBlockInContext(self.get_context().into(), self.into(), ptr).into()
    })
  }

  /// Returns the entry block of this function or `None` if there is none.
  pub fn get_entry(&self) -> Option<&BasicBlock>
  {
    unsafe { mem::transmute(LLVMGetEntryBasicBlock(self.into())) }
  }

  /// Returns the name of this function.
  pub fn get_name(&self) -> &str
  {
    unsafe {
      let c_name = LLVMGetValueName(self.into());
      util::to_str(c_name as *mut i8)
    }
  }

  /// Returns the function signature representing this function's signature.
  pub fn get_signature(&self) -> &FunctionType
  {
    unsafe {
      let ty = LLVMTypeOf(self.into());
      LLVMGetElementType(ty).into()
    }
  }

  /// Returns the number of function parameters
  pub fn num_params(&self) -> usize
  {
    unsafe {
      LLVMCountParams(self.into()) as usize
    }
  }

  /// Add the attribute given to this function.
  pub fn add_attribute(&self, attr: Attribute)
  {
    unsafe { LLVMAddFunctionAttr(self.into(), attr.into()) }
  }

  /// Add all the attributes given to this function.
  pub fn add_attributes(&self, attrs: &[Attribute])
  {
    let mut sum = LLVMAttribute::empty();

    for attr in attrs {
        let attr:LLVMAttribute = (*attr).into();
        sum = sum | attr;
    }

    unsafe { LLVMAddFunctionAttr(self.into(), sum.into()) }
  }

  /// Returns true if the attribute given is set in this function.
  pub fn has_attribute(&self, attr: Attribute) -> bool
  {
    unsafe {
      let other = LLVMGetFunctionAttr(self.into());
      other.contains(attr.into())
    }
  }

  /// Returns true if all the attributes given is set in this function.
  pub fn has_attributes(&self, attrs: &[Attribute]) -> bool
  {
    unsafe {
      let other = LLVMGetFunctionAttr(self.into());

      for &attr in attrs {
          if !other.contains(attr.into()) {
              return false;
          }
      }

      return true;
    }
  }

  /// Remove the attribute given from this function.
  pub fn remove_attribute(&self, attr: Attribute)
  {
    unsafe { LLVMRemoveFunctionAttr(self.into(), attr.into()) }
  }
}

impl<'a> IntoIterator for &'a Function
{
  type Item = &'a Arg;
  type IntoIter = ValueIter<'a, &'a Arg>;

  /// Iterate through the functions in the module
  fn into_iter(self) -> ValueIter<'a, &'a Arg>
  {
 		ValueIter::new(
 			unsafe { LLVMGetFirstParam(self.into()) },
 			LLVMGetNextParam)
  }
}

impl GetContext for Function
{
  fn get_context(&self) -> &Context
  {
    self.get_type().get_context()
  }
}

/// A way of indicating to LLVM how you want arguments / functions to be handled.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(C)]
pub enum Attribute
{
  /// Zero-extended before or after call.
  ZExt =              0b1,
  /// Sign-extended before or after call.
  SExt =              0b10,
  /// Mark the function as not returning.
  NoReturn =          0b100,
  /// Force argument to be passed in register.
  InReg =             0b1000,
  /// Hidden pointer to structure to return.
  StructRet =         0b10000,
  /// Function doesn't unwind stack.
  NoUnwind =          0b100000,
  /// Consider to not alias after call.
  NoAlias =           0b1000000,
  /// Pass structure by value.
  ByVal =             0b10000000,
  /// Nested function static chain.
  Nest =              0b100000000,
  /// Function doesn't access memory.
  ReadNone =          0b1000000000,
  /// Function only reads from memory.
  ReadOnly =          0b10000000000,
  /// Never inline this function.
  NoInline =          0b100000000000,
  /// Always inline this function.
  AlwaysInline =      0b1000000000000,
  /// Optimize this function for size.
  OptimizeForSize =   0b10000000000000,
  /// Stack protection.
  StackProtect =      0b100000000000000,
  /// Stack protection required.
  StackProtectReq =   0b1000000000000000,
  /// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from align(1)).
  Alignment =         0b10000000000000000,
  /// Function creates no aliases of pointer.
  NoCapture =         0b100000000000000000,
  /// Disable redzone.
  NoRedZone =         0b1000000000000000000,
  /// Disable implicit float instructions.
  NoImplicitFloat =   0b10000000000000000000,
  /// Naked function.
  Naked =             0b100000000000000000000,
  /// The source language has marked this function as inline.
  InlineHint =        0b1000000000000000000000,
  /// Alignment of stack for function (3 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from alignstack=(1)).
  StackAlignment =    0b11100000000000000000000000000,
  /// This function returns twice.
  ReturnsTwice =      0b100000000000000000000000000000,
  /// Function must be in unwind table.
  UWTable =           0b1000000000000000000000000000000,
  /// Function is called early/often, so lazy binding isn't effective.
  NonLazyBind =       0b10000000000000000000000000000000
}

impl From<LLVMAttribute> for Attribute
{
  fn from(attr: LLVMAttribute) -> Attribute
  {
    unsafe { mem::transmute(attr) }
  }
}

impl From<Attribute> for LLVMAttribute
{
  fn from(attr: Attribute) -> LLVMAttribute
  {
    unsafe { mem::transmute(attr) }
  }
}

impl GetContext for Value
{
  fn get_context(&self) -> &Context
  {
    self.get_type().get_context()
  }
}

/// Value Iterator implementation.
///
/// T can be all descendent types of LLVMValueRef.
#[derive(Copy, Clone)]
pub struct ValueIter<'a, T: From<LLVMValueRef>> {
  cur    : LLVMValueRef,
  step   : unsafe extern "C" fn(LLVMValueRef) -> LLVMValueRef,
  marker1: ::std::marker::PhantomData<&'a ()>,
  marker2: ::std::marker::PhantomData<T>,
}

impl<'a, T: From<LLVMValueRef>> ValueIter<'a, T>
{
	pub fn new(cur: LLVMValueRef,
		         step: unsafe extern "C" fn(LLVMValueRef) -> LLVMValueRef) -> Self
	{
		ValueIter {
			cur: cur,
			step: step,
			marker1: ::std::marker::PhantomData,
			marker2: ::std::marker::PhantomData
		}
	}
}

impl<'a, T: From<LLVMValueRef>> Iterator for ValueIter<'a, T>
{
  type Item = T;

  fn next(&mut self) -> Option<T>
  {
    let old: LLVMValueRef = self.cur;

    if !old.is_null() {
      self.cur = unsafe { (self.step)(old) };
      Some(old.into())
    } else {
      None
    }
  }
}<|endoftext|>


<commit_before>extern crate regex;

use colored::*;
use std::process::exit;
use regex::RegexSet;
use nom::IResult;
use std::path::PathBuf;

pub fn file_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {
    let processed_vec: Vec<&str> = process_to_vector(file);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    debugln!("{:?}", lines.clone().collect::<Vec<&str>>());

    let maybe_set = RegexSet::new(lines);
    if let Ok(s) = maybe_set {
        s
    }
    else {
        eprintln!("{}: failed to parse .gitignore at {:?}, ignoring", "Warning".yellow(), file_path);
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty)
            .expect("Error creating regex from empty vector")
    }
}

pub fn process_to_vector(input: &str) -> Vec<&str> {
    match process(input) {
        IResult::Done(_, result) => result,
        _ => { eprintln!("{}: Failed to parse gitignore", "Error".red()) ; exit(0xf001) }
    }
}

named!(process<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(options) >>
        (r)
    )
);

named!(options<&str, &str>,
    alt!(
        gitignore_comment |
        is_not!("*?.#") |
        parse_asterix |
        parse_period |
        parse_questionmark |
        parse_not_comment
    )
);

named!(parse_not_comment<&str, &str>,
    do_parse!(
        is_not!("\n") >>
        ("#")
    )
);

named!(first_line<&str, &str>,
    do_parse!(
        tag!("#") >>
        is_not!("\n") >>
        tag!("\n") >>
        ("\n")
    )
);

named!(gitignore_comment<&str, &str>,
    do_parse!(
        tag!("\n#") >>
        is_not!("\n") >>
        //tag!("\n") >>
        ("\n")
    )
);

named!(parse_period<&str, &str>,
    do_parse!(
        tag!(".") >>
        ("\\.")
    )
);

named!(parse_asterix<&str, &str>,
    do_parse!(
        tag!("*") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".*")
    )
);

named!(parse_questionmark<&str, &str>,
    do_parse!(
        tag!("?") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".")
    )
);
<commit_msg>workscargo release<commit_after>extern crate regex;

use colored::*;
use std::process::exit;
use regex::RegexSet;
use nom::IResult;
use std::path::PathBuf;

pub fn file_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {
    let processed_vec: Vec<&str> = process_to_vector(file);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    debugln!("{:?}", lines.clone().collect::<Vec<&str>>());

    let maybe_set = RegexSet::new(lines);
    if let Ok(s) = maybe_set {
        s
    }
    else {
        eprintln!("{}: failed to parse .gitignore at {:?}, ignoring", "Warning".yellow(), file_path);
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty)
            .expect("Error creating regex from empty vector")
    }
}

pub fn process_to_vector(input: &str) -> Vec<&str> {
    match process(input) {
        IResult::Done(_, result) => result,
        _ => { eprintln!("{}: Failed to parse gitignore", "Error".red()) ; exit(0xf001) }
    }
}

named!(process<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(options) >>
        (r)
    )
);

named!(options<&str, &str>,
    alt!(
        gitignore_comment |
        tag!("\n") |
        is_not!("*?.#") |
        parse_asterix |
        parse_period |
        parse_questionmark |
        parse_not_comment
    )
);

named!(parse_not_comment<&str, &str>,
    do_parse!(
        is_not!("\n") >>
        ("#")
    )
);

named!(first_line<&str, &str>,
    do_parse!(
        tag!("#") >>
        is_not!("\n") >>
        tag!("\n") >>
        ("\n")
    )
);

named!(gitignore_comment<&str, &str>,
    do_parse!(
        tag!("\n#") >>
        is_not!("\n") >>
        ("\n")
    )
);

named!(parse_period<&str, &str>,
    do_parse!(
        tag!(".") >>
        ("\\.")
    )
);

named!(parse_asterix<&str, &str>,
    do_parse!(
        tag!("*") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".*")
    )
);

named!(parse_questionmark<&str, &str>,
    do_parse!(
        tag!("?") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".")
    )
);
<|endoftext|>


<commit_before>use libc::{uint64_t, int64_t, c_double, c_int};
use std::mem;

/// Typedef for the window completion callback function.
pub type HeartbeatWindowCompleteFn = extern fn(*const Heartbeat, *const HeartbeatRecord, uint64_t);

#[link(name = "hbs-pow")]
extern {
    /// Initialize a Heartbeat.
    fn heartbeat_init(hb: *mut Heartbeat,
                      window_size: uint64_t,
                      window_buffer: *mut HeartbeatRecord,
                      hwc_callback: Option<HeartbeatWindowCompleteFn>) -> c_int;

    /// Issue a heartbeat.
    fn heartbeat(hb: *mut Heartbeat,
                 user_tag: uint64_t,
                 work: uint64_t,
                 start_time: int64_t,
                 end_time: int64_t);

    /// Issue a heartbeat with energy data.
    fn heartbeat_pow(hb: *mut Heartbeat,
                     user_tag: uint64_t,
                     work: uint64_t,
                     start_time: int64_t,
                     end_time: int64_t,
                     start_energy: uint64_t,
                     end_energy: uint64_t);

    /// Writes the window buffer to the log specified by the file descriptor.
    pub fn heartbeat_log_window_buffer(hb: *const Heartbeat,
                                       fd: c_int,
                                       print_header: c_int) -> c_int;

    /// Utility function to get the most recent user-specified tag
    fn hb_get_user_tag(hb: *const Heartbeat) -> uint64_t;

    /// Utility function to get the current window performance.
    fn hb_get_window_rate(hb: *const Heartbeat) -> c_double;

    /// Utility function to get the current window power.
    fn hb_get_window_power(hb: *const Heartbeat) -> c_double;
}

/// Time data.
#[derive(Clone, Copy)]
#[repr(C)]
struct HeartbeatTimeData {
    total_time: int64_t,
    window_time: int64_t,
}

/// Work data.
#[derive(Clone, Copy)]
#[repr(C)]
struct HeartbeatWorkData {
    total_work: uint64_t,
    window_work: uint64_t,
}

/// Energy data
#[derive(Clone, Copy)]
#[repr(C)]
struct HeartbeatEnergyData {
    total_energy: uint64_t,
    window_energy: uint64_t,
}

/// A Heartbeat record with current rates (performance and power).
#[derive(Clone, Copy)]
#[repr(C)]
pub struct HeartbeatRecord {
    pub id: uint64_t,
    pub user_tag: uint64_t,

    pub work: uint64_t,
    pub start_time: int64_t,
    pub end_time: int64_t,
    pub global_perf: c_double,
    pub window_perf: c_double,
    pub instant_perf: c_double,

    pub start_energy: uint64_t,
    pub end_energy: uint64_t,
    pub global_pwr: c_double,
    pub window_pwr: c_double,
    pub instant_pwr: c_double,
}

/// A `Heartbeat` is used for tracking performance/power of recurring jobs.
/// This represents a C struct.
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Heartbeat {
    counter: uint64_t,
    buffer_index: uint64_t,
    read_index: uint64_t,
    window_size: uint64_t,
    window_buffer: *mut HeartbeatRecord,
    hwc_callback: HeartbeatWindowCompleteFn,

    td: HeartbeatTimeData,
    wd: HeartbeatWorkData,
    ed: HeartbeatEnergyData,
}

/// Heartbeat wrapper. Contains the window data buffer.
pub struct HeartbeatSimple {
    pub hb: Heartbeat,
    pub hbr: Vec<HeartbeatRecord>,
}

impl HeartbeatSimple {
    /// Allocate and initialize a new `Heartbeat`.
    pub fn new(window_size: usize,
               hwc_callback: Option<HeartbeatWindowCompleteFn>) -> Result<HeartbeatSimple, &'static str> {
        unsafe {
            let mut hb = HeartbeatSimple {
                hb: mem::uninitialized(),
                hbr: Vec::with_capacity(window_size)
            };
            match heartbeat_init(&mut hb.hb, window_size as u64, hb.hbr.as_mut_ptr(), hwc_callback) {
                0 => Ok(hb),
                _ => Err("Failed to initialize heartbeat")
            }
        }
    }

    /// Issue a heartbeat.
    pub fn heartbeat(&mut self,
                     tag: u64,
                     work: u64,
                     start_time: i64,
                     end_time: i64) {
        unsafe {
            heartbeat(&mut self.hb, tag, work, start_time, end_time)
        }
    }

    /// Issue a heartbeat with energy data.
    pub fn heartbeat_pow(&mut self,
                         tag: u64,
                         work: u64,
                         start_time: i64,
                         end_time: i64,
                         start_energy: u64,
                         end_energy: u64) {
        unsafe {
            heartbeat_pow(&mut self.hb, tag, work, start_time, end_time, start_energy, end_energy)
        }
    }

    /// Utility function to get the most recent user-specified tag
    pub fn get_tag(&self) -> u64 {
        unsafe {
            hb_get_user_tag(&self.hb)
        }
    }

    /// Utility function to get the current window performance.
    pub fn get_window_perf(&self) -> f64 {
        unsafe {
            hb_get_window_rate(&self.hb)
        }
    }

    /// Utility function to get the current window power.
    pub fn get_window_pwr(&self) -> f64 {
        unsafe {
            hb_get_window_power(&self.hb)
        }
    }
}

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

    extern fn heartbeat_window_complete_callback(hb: *const Heartbeat,
                                                 _hbr: *const HeartbeatRecord,
                                                 _size: uint64_t) {
    const STDOUT: i32 = 1;
    unsafe {
        heartbeat_log_window_buffer(hb, STDOUT, 0);
    }
}

    #[test]
    fn test_simple() {
        const TIME_INC: i64 = 1000000000;
        const ENERGY_INC: u64 = 1000000;
        let mut hb = HeartbeatSimple::new(5, Some(heartbeat_window_complete_callback)).unwrap();
        let mut start_time: i64 = 0;
        let mut end_time: i64 = TIME_INC;
        let mut start_energy: u64 = 0;
        let mut end_energy: u64 = ENERGY_INC;
        let mut tag: u64 = 0;
        for _ in 0..10 {
            hb.heartbeat_pow(tag, 1, start_time, end_time, start_energy, end_energy);
            assert!(hb.get_tag() == tag);
            assert!(hb.get_window_perf() == 1.0);
            assert!(hb.get_window_pwr() == 1.0);
            tag += 1;
            start_time = end_time;
            end_time += TIME_INC;
            start_energy = end_energy;
            end_energy += ENERGY_INC;
        }
    }
}
<commit_msg>start and end times are now strictly unsigned values<commit_after>use libc::{uint64_t, c_double, c_int};
use std::mem;

/// Typedef for the window completion callback function.
pub type HeartbeatWindowCompleteFn = extern fn(*const Heartbeat, *const HeartbeatRecord, uint64_t);

#[link(name = "hbs-pow")]
extern {
    /// Initialize a Heartbeat.
    fn heartbeat_init(hb: *mut Heartbeat,
                      window_size: uint64_t,
                      window_buffer: *mut HeartbeatRecord,
                      hwc_callback: Option<HeartbeatWindowCompleteFn>) -> c_int;

    /// Issue a heartbeat.
    fn heartbeat(hb: *mut Heartbeat,
                 user_tag: uint64_t,
                 work: uint64_t,
                 start_time: uint64_t,
                 end_time: uint64_t);

    /// Issue a heartbeat with energy data.
    fn heartbeat_pow(hb: *mut Heartbeat,
                     user_tag: uint64_t,
                     work: uint64_t,
                     start_time: uint64_t,
                     end_time: uint64_t,
                     start_energy: uint64_t,
                     end_energy: uint64_t);

    /// Writes the window buffer to the log specified by the file descriptor.
    pub fn heartbeat_log_window_buffer(hb: *const Heartbeat,
                                       fd: c_int,
                                       print_header: c_int) -> c_int;

    /// Utility function to get the most recent user-specified tag
    fn hb_get_user_tag(hb: *const Heartbeat) -> uint64_t;

    /// Utility function to get the current window performance.
    fn hb_get_window_rate(hb: *const Heartbeat) -> c_double;

    /// Utility function to get the current window power.
    fn hb_get_window_power(hb: *const Heartbeat) -> c_double;
}

/// Time data.
#[derive(Clone, Copy)]
#[repr(C)]
struct HeartbeatTimeData {
    total_time: uint64_t,
    window_time: uint64_t,
}

/// Work data.
#[derive(Clone, Copy)]
#[repr(C)]
struct HeartbeatWorkData {
    total_work: uint64_t,
    window_work: uint64_t,
}

/// Energy data
#[derive(Clone, Copy)]
#[repr(C)]
struct HeartbeatEnergyData {
    total_energy: uint64_t,
    window_energy: uint64_t,
}

/// A Heartbeat record with current rates (performance and power).
#[derive(Clone, Copy)]
#[repr(C)]
pub struct HeartbeatRecord {
    pub id: uint64_t,
    pub user_tag: uint64_t,

    pub work: uint64_t,
    pub start_time: uint64_t,
    pub end_time: uint64_t,
    pub global_perf: c_double,
    pub window_perf: c_double,
    pub instant_perf: c_double,

    pub start_energy: uint64_t,
    pub end_energy: uint64_t,
    pub global_pwr: c_double,
    pub window_pwr: c_double,
    pub instant_pwr: c_double,
}

/// A `Heartbeat` is used for tracking performance/power of recurring jobs.
/// This represents a C struct.
#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Heartbeat {
    counter: uint64_t,
    buffer_index: uint64_t,
    read_index: uint64_t,
    window_size: uint64_t,
    window_buffer: *mut HeartbeatRecord,
    hwc_callback: HeartbeatWindowCompleteFn,

    td: HeartbeatTimeData,
    wd: HeartbeatWorkData,
    ed: HeartbeatEnergyData,
}

/// Heartbeat wrapper. Contains the window data buffer.
pub struct HeartbeatSimple {
    pub hb: Heartbeat,
    pub hbr: Vec<HeartbeatRecord>,
}

impl HeartbeatSimple {
    /// Allocate and initialize a new `Heartbeat`.
    pub fn new(window_size: usize,
               hwc_callback: Option<HeartbeatWindowCompleteFn>) -> Result<HeartbeatSimple, &'static str> {
        unsafe {
            let mut hb = HeartbeatSimple {
                hb: mem::uninitialized(),
                hbr: Vec::with_capacity(window_size)
            };
            match heartbeat_init(&mut hb.hb, window_size as u64, hb.hbr.as_mut_ptr(), hwc_callback) {
                0 => Ok(hb),
                _ => Err("Failed to initialize heartbeat")
            }
        }
    }

    /// Issue a heartbeat.
    pub fn heartbeat(&mut self,
                     tag: u64,
                     work: u64,
                     start_time: u64,
                     end_time: u64) {
        unsafe {
            heartbeat(&mut self.hb, tag, work, start_time, end_time)
        }
    }

    /// Issue a heartbeat with energy data.
    pub fn heartbeat_pow(&mut self,
                         tag: u64,
                         work: u64,
                         start_time: u64,
                         end_time: u64,
                         start_energy: u64,
                         end_energy: u64) {
        unsafe {
            heartbeat_pow(&mut self.hb, tag, work, start_time, end_time, start_energy, end_energy)
        }
    }

    /// Utility function to get the most recent user-specified tag
    pub fn get_tag(&self) -> u64 {
        unsafe {
            hb_get_user_tag(&self.hb)
        }
    }

    /// Utility function to get the current window performance.
    pub fn get_window_perf(&self) -> f64 {
        unsafe {
            hb_get_window_rate(&self.hb)
        }
    }

    /// Utility function to get the current window power.
    pub fn get_window_pwr(&self) -> f64 {
        unsafe {
            hb_get_window_power(&self.hb)
        }
    }
}

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

    extern fn heartbeat_window_complete_callback(hb: *const Heartbeat,
                                                 _hbr: *const HeartbeatRecord,
                                                 _size: uint64_t) {
    const STDOUT: i32 = 1;
    unsafe {
        heartbeat_log_window_buffer(hb, STDOUT, 0);
    }
}

    #[test]
    fn test_simple() {
        const TIME_INC: u64 = 1000000000;
        const ENERGY_INC: u64 = 1000000;
        let mut hb = HeartbeatSimple::new(5, Some(heartbeat_window_complete_callback)).unwrap();
        let mut start_time: u64 = 0;
        let mut end_time: u64 = TIME_INC;
        let mut start_energy: u64 = 0;
        let mut end_energy: u64 = ENERGY_INC;
        let mut tag: u64 = 0;
        for _ in 0..10 {
            hb.heartbeat_pow(tag, 1, start_time, end_time, start_energy, end_energy);
            assert!(hb.get_tag() == tag);
            assert!(hb.get_window_perf() == 1.0);
            assert!(hb.get_window_pwr() == 1.0);
            tag += 1;
            start_time = end_time;
            end_time += TIME_INC;
            start_energy = end_energy;
            end_energy += ENERGY_INC;
        }
    }
}
<|endoftext|>