<commit_before>use std::mem::size_of_val;
use rand::{ Rng, OsRng, ChaChaRng };
use newhope::{
    N, POLY_BYTES, SENDABYTES, SENDBBYTES,
    poly_frombytes, poly_tobytes,
    rec_frombytes, rec_tobytes,
    keygen, sharedb, shareda,
    sha3_256
};
use memsec::memzero;
use super::KeyExchange;

/// Newhope key exchange..
///
/// # Example(exchange)
/// ```
/// use sarkara::kex::{ KeyExchange, NewHope };
///
/// let (mut keya, mut keyb) = ([0; 32], [0; 32]);
/// let (sk, pk) = NewHope::keygen();
/// let rec = NewHope::exchange(&mut keyb, &pk);
/// NewHope::exchange_from(&mut keya, &sk, &rec);
///
/// assert_eq!(keya, keyb);
/// ```
///
/// # Example(import/export)
/// ```
/// # use sarkara::kex::{ KeyExchange, PrivateKey, NewHope };
/// # let (mut keya, mut keyb) = ([0; 32], [0; 32]);
/// # let (sk, pk) = NewHope::keygen();
/// let sk_bytes = sk.export();
/// let sk = PrivateKey::import(&sk_bytes);
/// # let rec = NewHope::exchange(&mut keyb, &pk);
/// # NewHope::exchange_from(&mut keya, &sk, &rec);
/// # assert_eq!(keya, keyb);
/// ```
pub struct NewHope;

impl KeyExchange for NewHope {
    type PrivateKey = PrivateKey;

    fn sk_length() -> usize { POLY_BYTES }
    fn pk_length() -> usize { SENDABYTES }
    fn rec_length() -> usize { SENDBBYTES }

    fn keygen() -> (Self::PrivateKey, Vec<u8>) {
        let (mut sk, mut pk) = ([0; N], vec![0; SENDABYTES]);
        let (mut pka, mut nonce) = ([0; N], [0; 32]);
        let mut rng = OsRng::new().unwrap().gen::<ChaChaRng>();

        rng.fill_bytes(&mut nonce);
        keygen(&mut sk, &mut pka, &nonce, rng);

        pk[..POLY_BYTES].clone_from_slice(&poly_tobytes(&pka));
        pk[POLY_BYTES..].clone_from_slice(&nonce);

        (PrivateKey(sk), pk)
    }

    fn exchange(sharedkey: &mut [u8], pka: &[u8]) -> Vec<u8> {
        let (mut key, mut pkb, mut rec) = ([0; 32], [0; N], [0; N]);
        let (pk, nonce) = pka.split_at(POLY_BYTES);

        sharedb(
            &mut key, &mut pkb, &mut rec,
            &poly_frombytes(pk), nonce, OsRng::new().unwrap().gen::<ChaChaRng>()
        );

        sha3_256(sharedkey, &key);

        let mut output = Vec::with_capacity(Self::rec_length());
        output.extend_from_slice(&poly_tobytes(&pkb));
        output.extend_from_slice(&rec_tobytes(&rec));
        output
    }

    fn exchange_from(sharedkey: &mut [u8], &PrivateKey(ref sk): &Self::PrivateKey, pkb: &[u8]) {
        let mut key = [0; 32];
        let (pk, rec) = pkb.split_at(POLY_BYTES);
        shareda(&mut key, sk, &poly_frombytes(pk), &rec_frombytes(rec));

        sha3_256(sharedkey, &key);
    }
}

/// Newhope private key.
pub struct PrivateKey(pub [u16; N]);

impl PrivateKey {
    /// import private key.
    pub fn import(input: &[u8]) -> PrivateKey {
        PrivateKey(poly_frombytes(input))
    }

    /// export private key.
    pub fn export(&self) -> [u8; POLY_BYTES] {
        poly_tobytes(&self.0)
    }
}

impl Drop for PrivateKey {
    fn drop(&mut self) {
        unsafe { memzero(self.0.as_mut_ptr(), size_of_val(&self.0)) }
    }
}
<commit_msg>refactor: mlock PrivateKey<commit_after>use std::mem::size_of_val;
use rand::{ Rng, OsRng, ChaChaRng };
use newhope::{
    N, POLY_BYTES, SENDABYTES, SENDBBYTES,
    poly_frombytes, poly_tobytes,
    rec_frombytes, rec_tobytes,
    keygen, sharedb, shareda,
    sha3_256
};
use memsec::{ mlock, munlock };
use super::KeyExchange;

/// Newhope key exchange..
///
/// # Example(exchange)
/// ```
/// use sarkara::kex::{ KeyExchange, NewHope };
///
/// let (mut keya, mut keyb) = ([0; 32], [0; 32]);
/// let (sk, pk) = NewHope::keygen();
/// let rec = NewHope::exchange(&mut keyb, &pk);
/// NewHope::exchange_from(&mut keya, &sk, &rec);
///
/// assert_eq!(keya, keyb);
/// ```
///
/// # Example(import/export)
/// ```
/// # use sarkara::kex::{ KeyExchange, PrivateKey, NewHope };
/// # let (mut keya, mut keyb) = ([0; 32], [0; 32]);
/// # let (sk, pk) = NewHope::keygen();
/// let sk_bytes = sk.export();
/// let sk = PrivateKey::import(&sk_bytes);
/// # let rec = NewHope::exchange(&mut keyb, &pk);
/// # NewHope::exchange_from(&mut keya, &sk, &rec);
/// # assert_eq!(keya, keyb);
/// ```
pub struct NewHope;

impl KeyExchange for NewHope {
    type PrivateKey = PrivateKey;

    fn sk_length() -> usize { POLY_BYTES }
    fn pk_length() -> usize { SENDABYTES }
    fn rec_length() -> usize { SENDBBYTES }

    fn keygen() -> (Self::PrivateKey, Vec<u8>) {
        let (mut sk, mut pk) = ([0; N], vec![0; SENDABYTES]);
        let (mut pka, mut nonce) = ([0; N], [0; 32]);
        let mut rng = OsRng::new().unwrap().gen::<ChaChaRng>();

        rng.fill_bytes(&mut nonce);
        keygen(&mut sk, &mut pka, &nonce, rng);

        pk[..POLY_BYTES].clone_from_slice(&poly_tobytes(&pka));
        pk[POLY_BYTES..].clone_from_slice(&nonce);

        unsafe { mlock(sk.as_mut_ptr(), size_of_val(&sk)) };
        (PrivateKey(sk), pk)
    }

    fn exchange(sharedkey: &mut [u8], pka: &[u8]) -> Vec<u8> {
        let (mut key, mut pkb, mut rec) = ([0; 32], [0; N], [0; N]);
        let (pk, nonce) = pka.split_at(POLY_BYTES);

        sharedb(
            &mut key, &mut pkb, &mut rec,
            &poly_frombytes(pk), nonce, OsRng::new().unwrap().gen::<ChaChaRng>()
        );

        sha3_256(sharedkey, &key);

        let mut output = Vec::with_capacity(Self::rec_length());
        output.extend_from_slice(&poly_tobytes(&pkb));
        output.extend_from_slice(&rec_tobytes(&rec));
        output
    }

    fn exchange_from(sharedkey: &mut [u8], &PrivateKey(ref sk): &Self::PrivateKey, pkb: &[u8]) {
        let mut key = [0; 32];
        let (pk, rec) = pkb.split_at(POLY_BYTES);
        shareda(&mut key, sk, &poly_frombytes(pk), &rec_frombytes(rec));

        sha3_256(sharedkey, &key);
    }
}

/// Newhope private key.
pub struct PrivateKey(pub [u16; N]);

impl PrivateKey {
    /// import private key.
    pub fn import(input: &[u8]) -> PrivateKey {
        let mut input = poly_frombytes(input);
        unsafe { mlock(input.as_mut_ptr(), size_of_val(&input)) };
        PrivateKey(input)
    }

    /// export private key.
    pub fn export(&self) -> [u8; POLY_BYTES] {
        poly_tobytes(&self.0)
    }
}

impl Drop for PrivateKey {
    fn drop(&mut self) {
        unsafe { munlock(self.0.as_mut_ptr(), size_of_val(&self.0)) };
    }
}
<|endoftext|>


<commit_before>
use size_hint;
use Itertools;

use std::mem::replace;
use std::fmt;

macro_rules! clone_fields {
    ($name:ident, $base:expr, $($field:ident),+) => (
        $name {
            $(
                $field : $base . $field .clone()
            ),*
        }
    );
}

/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
    where I: Iterator
{
    head: I::Item,
    tail: I,
}

impl<I> HeadTail<I>
    where I: Iterator
{
    /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
    fn new(mut it: I) -> Option<HeadTail<I>> {
        let head = it.next();
        head.map(|h| {
            HeadTail {
                head: h,
                tail: it,
            }
        })
    }

    /// Get the next element and update `head`, returning the old head in `Some`.
    ///
    /// Returns `None` when the tail is exhausted (only `head` then remains).
    fn next(&mut self) -> Option<I::Item> {
        if let Some(next) = self.tail.next() {
            Some(replace(&mut self.head, next))
        } else {
            None
        }
    }

    /// Hints at the size of the sequence, same as the `Iterator` method.
    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.tail.size_hint(), 1)
    }
}

impl<I> Clone for HeadTail<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    fn clone(&self) -> Self {
        clone_fields!(HeadTail, self, head, tail)
    }
}

/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    for i in (0..data.len() / 2).rev() {
        sift_down(data, i, &mut less_than);
    }
}

/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    debug_assert!(index <= heap.len());
    let mut pos = index;
    let mut child = 2 * pos + 1;
    // the `pos` conditional is to avoid a bounds check
    while pos < heap.len() && child < heap.len() {
        let right = child + 1;

        // pick the smaller of the two children
        if right < heap.len() && less_than(&heap[right], &heap[child]) {
            child = right;
        }

        // sift down is done if we are already in order
        if !less_than(&heap[child], &heap[pos]) {
            return;
        }
        heap.swap(pos, child);
        pos = child;
        child = 2 * pos + 1;
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMerge<I>
    where I: Iterator
{
    heap: Vec<HeadTail<I>>,
}

impl<I> fmt::Debug for KMerge<I>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(KMerge, heap);
}

/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// Equivalent to `iterable.into_iter().kmerge()`.
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
///     /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
    where I: IntoIterator,
          I::Item: IntoIterator,
          <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| a.head < b.head);
    KMerge { heap: heap }
}

impl<I> Clone for KMerge<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    fn clone(&self) -> KMerge<I> {
        clone_fields!(KMerge, self, heap)
    }
}

impl<I> Iterator for KMerge<I>
    where I: Iterator,
          I::Item: PartialOrd
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        sift_down(&mut self.heap, 0, |a, b| a.head < b.head);
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMergeBy<I, F>
    where I: Iterator,
{
    heap: Vec<HeadTail<I>>,
    less_than: F,
}

/// Create an iterator that merges elements of the contained iterators.
///
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
    -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
    where I: IntoIterator,
          I::Item: IntoIterator,
          F: FnMut(&<<I as IntoIterator>::Item as IntoIterator>::Item,
                   &<<I as IntoIterator>::Item as IntoIterator>::Item) -> bool
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap: Vec<_> = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| less_than(&a.head, &b.head));
    KMergeBy { heap: heap, less_than: less_than }
}

impl<I, F> Iterator for KMergeBy<I, F>
    where I: Iterator,
          F: FnMut(&I::Item, &I::Item) -> bool
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        let less_than = &mut self.less_than;
        sift_down(&mut self.heap, 0, |a, b| less_than(&a.head, &b.head));
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}
<commit_msg>Impl Debug for KMergeBy<commit_after>
use size_hint;
use Itertools;

use std::mem::replace;
use std::fmt;

macro_rules! clone_fields {
    ($name:ident, $base:expr, $($field:ident),+) => (
        $name {
            $(
                $field : $base . $field .clone()
            ),*
        }
    );
}

/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
    where I: Iterator
{
    head: I::Item,
    tail: I,
}

impl<I> HeadTail<I>
    where I: Iterator
{
    /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
    fn new(mut it: I) -> Option<HeadTail<I>> {
        let head = it.next();
        head.map(|h| {
            HeadTail {
                head: h,
                tail: it,
            }
        })
    }

    /// Get the next element and update `head`, returning the old head in `Some`.
    ///
    /// Returns `None` when the tail is exhausted (only `head` then remains).
    fn next(&mut self) -> Option<I::Item> {
        if let Some(next) = self.tail.next() {
            Some(replace(&mut self.head, next))
        } else {
            None
        }
    }

    /// Hints at the size of the sequence, same as the `Iterator` method.
    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.tail.size_hint(), 1)
    }
}

impl<I> Clone for HeadTail<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    fn clone(&self) -> Self {
        clone_fields!(HeadTail, self, head, tail)
    }
}

/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    for i in (0..data.len() / 2).rev() {
        sift_down(data, i, &mut less_than);
    }
}

/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
    where S: FnMut(&T, &T) -> bool
{
    debug_assert!(index <= heap.len());
    let mut pos = index;
    let mut child = 2 * pos + 1;
    // the `pos` conditional is to avoid a bounds check
    while pos < heap.len() && child < heap.len() {
        let right = child + 1;

        // pick the smaller of the two children
        if right < heap.len() && less_than(&heap[right], &heap[child]) {
            child = right;
        }

        // sift down is done if we are already in order
        if !less_than(&heap[child], &heap[pos]) {
            return;
        }
        heap.swap(pos, child);
        pos = child;
        child = 2 * pos + 1;
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMerge<I>
    where I: Iterator
{
    heap: Vec<HeadTail<I>>,
}

impl<I> fmt::Debug for KMerge<I>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(KMerge, heap);
}

/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// Equivalent to `iterable.into_iter().kmerge()`.
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
///     /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
    where I: IntoIterator,
          I::Item: IntoIterator,
          <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| a.head < b.head);
    KMerge { heap: heap }
}

impl<I> Clone for KMerge<I>
    where I: Iterator + Clone,
          I::Item: Clone
{
    fn clone(&self) -> KMerge<I> {
        clone_fields!(KMerge, self, heap)
    }
}

impl<I> Iterator for KMerge<I>
    where I: Iterator,
          I::Item: PartialOrd
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        sift_down(&mut self.heap, 0, |a, b| a.head < b.head);
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}

/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMergeBy<I, F>
    where I: Iterator,
{
    heap: Vec<HeadTail<I>>,
    less_than: F,
}

impl<I, F> fmt::Debug for KMergeBy<I, F>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(KMergeBy, heap);
}

/// Create an iterator that merges elements of the contained iterators.
///
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
    -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
    where I: IntoIterator,
          I::Item: IntoIterator,
          F: FnMut(&<<I as IntoIterator>::Item as IntoIterator>::Item,
                   &<<I as IntoIterator>::Item as IntoIterator>::Item) -> bool
{
    let iter = iterable.into_iter();
    let (lower, _) = iter.size_hint();
    let mut heap: Vec<_> = Vec::with_capacity(lower);
    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
    heapify(&mut heap, |a, b| less_than(&a.head, &b.head));
    KMergeBy { heap: heap, less_than: less_than }
}

impl<I, F> Iterator for KMergeBy<I, F>
    where I: Iterator,
          F: FnMut(&I::Item, &I::Item) -> bool
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.heap.is_empty() {
            return None;
        }
        let result = if let Some(next) = self.heap[0].next() {
            next
        } else {
            self.heap.swap_remove(0).head
        };
        let less_than = &mut self.less_than;
        sift_down(&mut self.heap, 0, |a, b| less_than(&a.head, &b.head));
        Some(result)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.heap.iter()
                 .map(|i| i.size_hint())
                 .fold1(size_hint::add)
                 .unwrap_or((0, Some(0)))
    }
}
<|endoftext|>


<commit_before>use cgmath::{Matrix4, Point3, Vector3};
use cgmath;
use character::controls::CharacterInputState;
use graphics::orientation::{Orientation, Stance};
use data;
use game::constants::{ASPECT_RATIO, VIEW_DISTANCE, RUN_SPRITE_OFFSET, CHARSHEET_TOTAL_WIDTH, SPRITE_OFFSET};
use shaders::{pipe, VertexData, CharacterSheet, Position, Projection};
use gfx;
use gfx_app::graphics::load_texture;
use gfx_app::mouse_controls::MouseInputState;
use gfx_app::{ColorFormat, DepthFormat};
use graphics::{Dimensions, get_orientation};
use graphics::camera::CameraInputState;
use critter::{CharacterSprite, CritterData};
use specs;

mod audio;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("../shaders/character.f.glsl");

pub struct CharacterDrawable {
  projection: Projection,
  position: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
  audio: audio::CharacterAudio
}

impl CharacterDrawable {
  pub fn new(view: Matrix4<f32>) -> CharacterDrawable {
    CharacterDrawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), ASPECT_RATIO, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      stance: Stance::Normal,
      direction: Orientation::Right,
      audio: audio::CharacterAudio::new(),
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, cs: &mut CharacterSprite, mouse_input: &mut MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    if mouse_input.left_click_point.is_some() {
      self.stance = Stance::Firing;
      self.orientation = get_orientation(mouse_input);
      if cs.character_fire_idx == 1 {
        self.audio.play_pistol();
      }
    } else {
      self.stance = Stance::Normal;
      let dx = new_position.position[0] - self.position.position[0];
      let dy = new_position.position[1] - self.position.position[1];
      self.orientation =
        if dx == 0.0 && dy < 0.0       { Orientation::Down }
        else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
        else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
        else if dx == 0.0 && dy == 0.0 { Orientation::Still }
        else if dx > 0.0 && dy == 0.0  { Orientation::Right }
        else if dx < 0.0 && dy == 0.0  { Orientation::Left }
        else if dx == 0.0 && dy > 0.0  { Orientation::Up }
        else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
        else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
        else { unreachable!() };
      self.position = new_position;
    }
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct CharacterDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> CharacterDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> CharacterDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let tilesheet_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, tilesheet_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    CharacterDrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, character_fire_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let char_sprite = if drawable.orientation == Orientation::Still && drawable.stance == Stance::Normal {
      let sprite_idx = (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else if drawable.stance == Stance::Normal {
      drawable.direction = drawable.orientation;
      let sprite_idx = (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else {
      let sprite_idx = (drawable.orientation as usize * 8 + character_fire_idx) as usize;
      (&self.data[sprite_idx], sprite_idx)
    };

    let elements_x = CHARSHEET_TOTAL_WIDTH / (char_sprite.0.data[2] + SPRITE_OFFSET);
    CharacterSheet {
      div: elements_x,
      index: char_sprite.1 as f32
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &mut self.get_next_sprite(character.character_idx,
                                                             character.character_fire_idx,
                                                             &mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut character, dim, mut terrain_input, mut character_input, mut character_sprite, mut mouse_input) =
      arg.fetch(|w| (
        w.write::<CharacterDrawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<CameraInputState>(),
        w.write::<CharacterInputState>(),
        w.write::<CharacterSprite>(),
        w.write::<MouseInputState>()));

    for (c, ti, ci, cs, mi) in (&mut character, &mut terrain_input, &mut character_input, &mut character_sprite, &mut mouse_input).join() {
      let world_to_clip = dim.world_to_projection(ti);
      c.update(&world_to_clip, ci, cs, mi);
    }
  }
}
<commit_msg>Rename variable<commit_after>use cgmath::{Matrix4, Point3, Vector3};
use cgmath;
use character::controls::CharacterInputState;
use graphics::orientation::{Orientation, Stance};
use data;
use game::constants::{ASPECT_RATIO, VIEW_DISTANCE, RUN_SPRITE_OFFSET, CHARSHEET_TOTAL_WIDTH, SPRITE_OFFSET};
use shaders::{pipe, VertexData, CharacterSheet, Position, Projection};
use gfx;
use gfx_app::graphics::load_texture;
use gfx_app::mouse_controls::MouseInputState;
use gfx_app::{ColorFormat, DepthFormat};
use graphics::{Dimensions, get_orientation};
use graphics::camera::CameraInputState;
use critter::{CharacterSprite, CritterData};
use specs;

mod audio;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("../shaders/character.f.glsl");

pub struct CharacterDrawable {
  projection: Projection,
  position: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
  audio: audio::CharacterAudio
}

impl CharacterDrawable {
  pub fn new(view: Matrix4<f32>) -> CharacterDrawable {
    CharacterDrawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), ASPECT_RATIO, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      stance: Stance::Normal,
      direction: Orientation::Right,
      audio: audio::CharacterAudio::new(),
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, cs: &mut CharacterSprite, mouse_input: &mut MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    if mouse_input.left_click_point.is_some() {
      self.stance = Stance::Firing;
      self.orientation = get_orientation(mouse_input);
      if cs.character_fire_idx == 1 {
        self.audio.play_pistol();
      }
    } else {
      self.stance = Stance::Normal;
      let dx = new_position.position[0] - self.position.position[0];
      let dy = new_position.position[1] - self.position.position[1];
      self.orientation =
        if dx == 0.0 && dy < 0.0       { Orientation::Down }
        else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
        else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
        else if dx == 0.0 && dy == 0.0 { Orientation::Still }
        else if dx > 0.0 && dy == 0.0  { Orientation::Right }
        else if dx < 0.0 && dy == 0.0  { Orientation::Left }
        else if dx == 0.0 && dy > 0.0  { Orientation::Up }
        else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
        else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
        else { unreachable!() };
      self.position = new_position;
    }
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct CharacterDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> CharacterDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> CharacterDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let charter_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, charter_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    CharacterDrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, character_fire_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let char_sprite = if drawable.orientation == Orientation::Still && drawable.stance == Stance::Normal {
      let sprite_idx = (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else if drawable.stance == Stance::Normal {
      drawable.direction = drawable.orientation;
      let sprite_idx = (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET) as usize;
      (&self.data[sprite_idx], sprite_idx)
    } else {
      let sprite_idx = (drawable.orientation as usize * 8 + character_fire_idx) as usize;
      (&self.data[sprite_idx], sprite_idx)
    };

    let elements_x = CHARSHEET_TOTAL_WIDTH / (char_sprite.0.data[2] + SPRITE_OFFSET);
    CharacterSheet {
      div: elements_x,
      index: char_sprite.1 as f32
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &mut self.get_next_sprite(character.character_idx,
                                                             character.character_fire_idx,
                                                             &mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut character, dim, mut terrain_input, mut character_input, mut character_sprite, mut mouse_input) =
      arg.fetch(|w| (
        w.write::<CharacterDrawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<CameraInputState>(),
        w.write::<CharacterInputState>(),
        w.write::<CharacterSprite>(),
        w.write::<MouseInputState>()));

    for (c, ti, ci, cs, mi) in (&mut character, &mut terrain_input, &mut character_input, &mut character_sprite, &mut mouse_input).join() {
      let world_to_clip = dim.world_to_projection(ti);
      c.update(&world_to_clip, ci, cs, mi);
    }
  }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use super::ffi;
use libc::{c_int, c_uint, c_void, c_float, c_double};
use std::string::raw::from_buf;

pub use ffi::TrackingState;
pub use ffi::FovPort;
pub use ffi::Sizei;

//-----------------------------------------------------------------------------------
// Enum wrappers
//-----------------------------------------------------------------------------------

#[deriving(PartialEq, Show)]
pub enum HmdType {
  HmdNone,
  HmdDK1,
  HmdDKHD,
  HmdDK2,
  HmdOther,
}
impl HmdType {
  fn from_ffi(c: c_uint) -> HmdType {
    match c {
      ffi::Hmd_None       => HmdNone,
      ffi::Hmd_DK1        => HmdDK1,
      ffi::Hmd_DKHD       => HmdDKHD,
      ffi::Hmd_DK2        => HmdDK2,
      _                   => HmdOther
    }
  }
  fn to_ffi(&self) -> c_uint {
    match *self {
      HmdNone             => ffi::Hmd_None,
      HmdDK1              => ffi::Hmd_DK1,
      HmdDKHD             => ffi::Hmd_DKHD,
      HmdDK2              => ffi::Hmd_DK2,
      HmdOther            => ffi::Hmd_Other
    }
  }
}

#[deriving(PartialEq, Show)]
pub enum EyeType {
  EyeL,
  EyeR,
}

impl EyeType {
  fn from_ffi(c: c_uint) -> EyeType {
    match c {
      ffi::Eye_Left  => EyeL,
      ffi::Eye_Right => EyeR,
      _ => panic!("Invalid eye type {}", c)
    }
  }
  fn to_ffi(&self) -> c_uint {
    match *self {
      EyeL => ffi::Eye_Left,
      EyeR => ffi::Eye_Right
    }
  }
}

//-----------------------------------------------------------------------------------
// Bitset wrappers
//-----------------------------------------------------------------------------------

pub struct BitMask {
  pub mask: c_uint,
}
impl BitMask {
  fn check_flag(&self, flag: c_uint) -> bool {
    self.mask & flag == flag
  }
  fn set_flag(&self, flag: c_uint, new_state: bool) -> BitMask {
    BitMask { mask:
      match new_state {
        true  => self.mask |  flag,
        false => self.mask & !flag,
      }
    }
  }
}

pub type HmdCaps = BitMask;
pub type DistortionCaps = BitMask;
pub type TrackingCaps = BitMask;

/*
/// Eventually, a type-safe approach like the following is better as the approach above.
/// However, since all the bitmasks are still subject to change in the SDK,
/// I chose a more low level approach for the time being...

#[deriving(Show)]
pub struct HmdCaps {
  flags: c_uint
}

impl HmdCaps {
  // non setable flags
  pub fn present(&self) -> bool {
    self.flags & ffi::HmdCap_Present == ffi::HmdCap_Present
  }
  pub fn available(&self) -> bool {
    self.flags & ffi::HmdCap_Available == ffi::HmdCap_Available
  }
  pub fn captured(&self) -> bool {
    self.flags & ffi::HmdCap_Captured == ffi::HmdCap_Captured
  }
  pub fn extend_desktop(&self) -> bool {
    self.flags & ffi::HmdCap_ExtendDesktop == ffi::HmdCap_ExtendDesktop
  }

  // setable flags
  pub fn no_mirror_to_window(&self) -> bool {
    self.flags & ffi::HmdCap_NoMirrorToWindow == ffi::HmdCap_NoMirrorToWindow
  }
  pub fn set_no_mirror_to_window(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_NoMirrorToWindow,
        false => self.flags & !ffi::HmdCap_NoMirrorToWindow,
      }
    }
  }

  pub fn display_off(&self) -> bool {
    self.flags & ffi::HmdCap_DisplayOff == ffi::HmdCap_DisplayOff
  }
  pub fn set_display_off(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_DisplayOff,
        false => self.flags & !ffi::HmdCap_DisplayOff,
      }
    }
  }

  pub fn low_persistance(&self) -> bool {
    self.flags & ffi::HmdCap_LowPersistence == ffi::HmdCap_LowPersistence
  }
  pub fn set_low_persistance(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_LowPersistence,
        false => self.flags & !ffi::HmdCap_LowPersistence,
      }
    }
  }

  pub fn dynamic_prediction(&self) -> bool {
    self.flags & ffi::HmdCap_DynamicPrediction == ffi::HmdCap_DynamicPrediction
  }
  pub fn set_dynamic_prediction(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_DynamicPrediction,
        false => self.flags & !ffi::HmdCap_DynamicPrediction,
      }
    }
  }

  pub fn no_vsync(&self) -> bool {
    self.flags & ffi::HmdCap_NoVSync == ffi::HmdCap_NoVSync
  }
  pub fn set_no_vsync(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_NoVSync,
        false => self.flags & !ffi::HmdCap_NoVSync,
      }
    }
  }
}
*/

//-----------------------------------------------------------------------------------
// Wrapper for general OVR library
//-----------------------------------------------------------------------------------

pub struct Ovr;

impl Ovr {

  pub fn initialize() -> Option<Ovr> {
    unsafe {
      if ffi::ovr_Initialize() != 0i8 {
        Some(Ovr)
      } else {
        None
      }
    }
  }

  pub fn detect(&self) -> int {
    unsafe { ffi::ovrHmd_Detect() as int }
  }

  pub fn create_hmd(&self, index: int) -> Option<Hmd> {
    unsafe {
      let ptr = ffi::ovrHmd_Create(index as i32);
      if !ptr.is_null() {
        Some(Hmd{ ptr: ptr })
      } else {
        None
      }
    }
  }

  pub fn create_hmd_debug(&self, hmd_type: HmdType) -> Option<Hmd> {
    unsafe {
      let ptr = ffi::ovrHmd_CreateDebug(hmd_type.to_ffi());
      if !ptr.is_null() {
        Some(Hmd{ ptr: ptr })
      } else {
        None
      }
    }
  }

}

impl Drop for Ovr {
  fn drop(&mut self) {
    unsafe { ffi::ovr_Shutdown(); }
  }
}

//-----------------------------------------------------------------------------------
// Wrapper for HMD
//-----------------------------------------------------------------------------------

pub struct Hmd {
  ptr: *mut ffi::Hmd
}

impl Hmd {

  pub fn get_last_error(&self) -> Option<String> {
    unsafe {
      let ptr = ffi::ovrHmd_GetLastError(self.ptr);
      match ptr.is_null() {
        true  => None,
        false => Some(from_buf(ptr as *const u8)),
      }
    }
  }

  /// TODO
  pub fn attach_to_window() {
    unimplemented!()
  }

  pub fn get_enabled_caps(&self) -> HmdCaps {
    unsafe {
      let flags = ffi::ovrHmd_GetEnabledCaps(self.ptr);
      HmdCaps{ mask: flags }
    }
  }

  pub fn set_enabled_caps(&self, caps: HmdCaps) {
    unsafe {
      let flags = caps.mask;
      ffi::ovrHmd_SetEnabledCaps(self.ptr, flags);
    }
  }

  pub fn configure_tracking(&self, supported_tracking_caps: TrackingCaps, required_tracking_caps: TrackingCaps) -> bool {
    unsafe {
      let ovr_bool = ffi::ovrHmd_ConfigureTracking(
        self.ptr, supported_tracking_caps.mask, required_tracking_caps.mask
      );
      ovr_bool != 0i8
    }
  }

  pub fn recenter_pose(&self) {
    unsafe {
      ffi::ovrHmd_RecenterPose(self.ptr);
    }
  }

  pub fn get_tracking_state(&self, abs_time: f64) -> TrackingState {
    unsafe {
      ffi::ovrHmd_GetTrackingState(self.ptr, abs_time)
    }
  }

  pub fn get_fov_texture_size(&self, eye: EyeType, fov: FovPort, pixels_per_display_pixel: f32) -> Sizei {
    unsafe {
      ffi::ovrHmd_GetFovTextureSize(self.ptr, eye.to_ffi(), fov, pixels_per_display_pixel)
    }
  }

  pub fn configure_rendering(&self) {
    unsafe {
      //ffi::ovrHmd_ConfigureRendering(self.ptr);
    }
  }

/*

  pub fn ovrHmd_ConfigureRendering(hmd: *mut Hmd,
                                   apiConfig: *const RenderAPIConfig,
                                   distortionCaps: c_uint,
                                   eyeFovIn: *const FovPort,
                                   eyeRenderDescOut: *mut EyeRenderDesc) -> OvrBool;

    pub fn get_sensor_state(&self, abs_time: f64) -> SensorState {
        unsafe {
            SensorState::from_ll(ll::ovrHmd_GetSensorState(self.ptr, abs_time))
        }
    }

    pub fn get_sensor_description(&self) -> Option<SensorDescription> {
        unsafe {
            let mut c_desc = ll::SensorDesc {
                vendor_id: 0,
                product_id: 0,
                serial_number: [0,.. 24]
            };

            if !ll::ovrHmd_GetSensorDesc(self.ptr, &mut c_desc as *mut ll::SensorDesc) {
                None
            } else {
                Some(SensorDescription::from_ll(c_desc))
            }
        }
    }

    pub fn get_description(&self) -> HmdDescription {
        unsafe {
            let mut c_desc = Default::default();
            ll::ovrHmd_GetDesc(self.ptr, &mut c_desc);
            HmdDescription::from_ll(c_desc)
        }
    }

    pub fn get_fov_texture_size(&self,
                                eye: EyeType,
                                fov: FovPort,
                                pixels_per_display_pixel: f32) -> ll::Sizei {
        unsafe {
            ll::ovrHmd_GetFovTextureSize(self.ptr,
                                         eye.to_ll(),
                                         fov.to_ll(),
                                         pixels_per_display_pixel)
        }
    }

    pub fn configure_rendering<RC: ToRenderConfig>(&self,
                               api_config: &RC,
                               cap: DistortionCapabilities,
                               eye_fov: PerEye<FovPort>) -> Option<PerEye<EyeRenderDescriptor>> {
        unsafe {
            let mut out: PerEye<ll::EyeRenderDesc> = PerEye::new(Default::default(),
                                                                 Default::default());
            let was_started = ll::ovrHmd_ConfigureRendering(
                self.ptr,
                &api_config.to_render_config(),
                cap.flags,
                eye_fov.map(|_, d| d.to_ll()).ptr(),
                out.mut_ptr()
            );

            if was_started {
                Some(out.map(|_, d| EyeRenderDescriptor::from_ll(d)))
            } else {
                None
            }
        }
    }

    pub fn begin_frame(&self, frame_index: uint) -> FrameTiming {
        unsafe {
            FrameTiming::from_ll(
                ll::ovrHmd_BeginFrame(self.ptr, frame_index as c_uint)
            )
        }
    }

    pub fn end_frame(&self) {
        unsafe {
            ll::ovrHmd_EndFrame(self.ptr);
        }
    }

    pub fn begin_eye_render(&self, eye: EyeType) -> Pose {
        unsafe {
            Pose::from_ll(ll::ovrHmd_BeginEyeRender(self.ptr, eye.to_ll()))
        }
    }

    pub fn end_eye_render<T: ToTexture>(&self,
                                        eye: EyeType,
                                        pose: Pose,
                                        texture: &T) {
        unsafe {
            ll::ovrHmd_EndEyeRender(self.ptr,
                                    eye.to_ll(),
                                    pose.to_ll(),
                                    &texture.to_texture());
        }
    }
    */
}

impl Drop for Hmd {
  fn drop(&mut self) {
    unsafe {ffi::ovrHmd_Destroy(self.ptr)}
  }
}

<commit_msg>more functions...<commit_after>#![allow(dead_code)]

use super::ffi;
use libc::{c_int, c_uint, c_void, c_float, c_double};
use std::string::raw::from_buf;
use std::default::Default;

pub use ffi::TrackingState;
pub use ffi::FovPort;
pub use ffi::Sizei;
pub use ffi::RenderAPIConfig;
pub use ffi::RenderAPIConfigHeader;
pub use ffi::EyeRenderDesc;

//-----------------------------------------------------------------------------------
// Enum wrappers
//-----------------------------------------------------------------------------------

#[deriving(PartialEq, Show)]
pub enum HmdType {
  HmdNone,
  HmdDK1,
  HmdDKHD,
  HmdDK2,
  HmdOther,
}
impl HmdType {
  fn from_ffi(c: c_uint) -> HmdType {
    match c {
      ffi::Hmd_None       => HmdNone,
      ffi::Hmd_DK1        => HmdDK1,
      ffi::Hmd_DKHD       => HmdDKHD,
      ffi::Hmd_DK2        => HmdDK2,
      _                   => HmdOther
    }
  }
  fn to_ffi(&self) -> c_uint {
    match *self {
      HmdNone             => ffi::Hmd_None,
      HmdDK1              => ffi::Hmd_DK1,
      HmdDKHD             => ffi::Hmd_DKHD,
      HmdDK2              => ffi::Hmd_DK2,
      HmdOther            => ffi::Hmd_Other
    }
  }
}

#[deriving(PartialEq, Show)]
pub enum EyeType {
  EyeL,
  EyeR,
}

impl EyeType {
  fn from_ffi(c: c_uint) -> EyeType {
    match c {
      ffi::Eye_Left  => EyeL,
      ffi::Eye_Right => EyeR,
      _ => panic!("Invalid eye type {}", c)
    }
  }
  fn to_ffi(&self) -> c_uint {
    match *self {
      EyeL => ffi::Eye_Left,
      EyeR => ffi::Eye_Right
    }
  }
}

//-----------------------------------------------------------------------------------
// Bitset wrappers
//-----------------------------------------------------------------------------------

pub struct BitMask {
  pub mask: c_uint,
}
impl BitMask {
  fn check_flag(&self, flag: c_uint) -> bool {
    self.mask & flag == flag
  }
  fn set_flag(&self, flag: c_uint, new_state: bool) -> BitMask {
    BitMask { mask:
      match new_state {
        true  => self.mask |  flag,
        false => self.mask & !flag,
      }
    }
  }
}

pub type HmdCaps = BitMask;
pub type DistortionCaps = BitMask;
pub type TrackingCaps = BitMask;

/*
/// Eventually, a type-safe approach like the following is better as the approach above.
/// However, since all the bitmasks are still subject to change in the SDK,
/// I chose a more low level approach for the time being...

#[deriving(Show)]
pub struct HmdCaps {
  flags: c_uint
}

impl HmdCaps {
  // non setable flags
  pub fn present(&self) -> bool {
    self.flags & ffi::HmdCap_Present == ffi::HmdCap_Present
  }
  pub fn available(&self) -> bool {
    self.flags & ffi::HmdCap_Available == ffi::HmdCap_Available
  }
  pub fn captured(&self) -> bool {
    self.flags & ffi::HmdCap_Captured == ffi::HmdCap_Captured
  }
  pub fn extend_desktop(&self) -> bool {
    self.flags & ffi::HmdCap_ExtendDesktop == ffi::HmdCap_ExtendDesktop
  }

  // setable flags
  pub fn no_mirror_to_window(&self) -> bool {
    self.flags & ffi::HmdCap_NoMirrorToWindow == ffi::HmdCap_NoMirrorToWindow
  }
  pub fn set_no_mirror_to_window(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_NoMirrorToWindow,
        false => self.flags & !ffi::HmdCap_NoMirrorToWindow,
      }
    }
  }

  pub fn display_off(&self) -> bool {
    self.flags & ffi::HmdCap_DisplayOff == ffi::HmdCap_DisplayOff
  }
  pub fn set_display_off(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_DisplayOff,
        false => self.flags & !ffi::HmdCap_DisplayOff,
      }
    }
  }

  pub fn low_persistance(&self) -> bool {
    self.flags & ffi::HmdCap_LowPersistence == ffi::HmdCap_LowPersistence
  }
  pub fn set_low_persistance(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_LowPersistence,
        false => self.flags & !ffi::HmdCap_LowPersistence,
      }
    }
  }

  pub fn dynamic_prediction(&self) -> bool {
    self.flags & ffi::HmdCap_DynamicPrediction == ffi::HmdCap_DynamicPrediction
  }
  pub fn set_dynamic_prediction(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_DynamicPrediction,
        false => self.flags & !ffi::HmdCap_DynamicPrediction,
      }
    }
  }

  pub fn no_vsync(&self) -> bool {
    self.flags & ffi::HmdCap_NoVSync == ffi::HmdCap_NoVSync
  }
  pub fn set_no_vsync(&self, flag: bool) -> HmdCaps {
    HmdCaps { flags:
      match flag {
        true  => self.flags |  ffi::HmdCap_NoVSync,
        false => self.flags & !ffi::HmdCap_NoVSync,
      }
    }
  }
}
*/

//-----------------------------------------------------------------------------------
// Wrapper for general OVR library
//-----------------------------------------------------------------------------------

pub struct Ovr;

impl Ovr {

  pub fn initialize() -> Option<Ovr> {
    unsafe {
      if ffi::ovr_Initialize() != 0i8 {
        Some(Ovr)
      } else {
        None
      }
    }
  }

  pub fn detect(&self) -> int {
    unsafe { ffi::ovrHmd_Detect() as int }
  }

  pub fn create_hmd(&self, index: int) -> Option<Hmd> {
    unsafe {
      let ptr = ffi::ovrHmd_Create(index as i32);
      if !ptr.is_null() {
        Some(Hmd{ ptr: ptr })
      } else {
        None
      }
    }
  }

  pub fn create_hmd_debug(&self, hmd_type: HmdType) -> Option<Hmd> {
    unsafe {
      let ptr = ffi::ovrHmd_CreateDebug(hmd_type.to_ffi());
      if !ptr.is_null() {
        Some(Hmd{ ptr: ptr })
      } else {
        None
      }
    }
  }

}

impl Drop for Ovr {
  fn drop(&mut self) {
    unsafe { ffi::ovr_Shutdown(); }
  }
}

//-----------------------------------------------------------------------------------
// Wrapper for HMD
//-----------------------------------------------------------------------------------

pub struct Hmd {
  ptr: *mut ffi::Hmd
}

impl Hmd {

  pub fn get_last_error(&self) -> Option<String> {
    unsafe {
      let ptr = ffi::ovrHmd_GetLastError(self.ptr);
      match ptr.is_null() {
        true  => None,
        false => Some(from_buf(ptr as *const u8)),
      }
    }
  }

  /// TODO
  pub fn attach_to_window() {
    unimplemented!()
  }

  pub fn get_enabled_caps(&self) -> HmdCaps {
    unsafe {
      let flags = ffi::ovrHmd_GetEnabledCaps(self.ptr);
      HmdCaps{ mask: flags }
    }
  }

  pub fn set_enabled_caps(&self, caps: HmdCaps) {
    unsafe {
      let flags = caps.mask;
      ffi::ovrHmd_SetEnabledCaps(self.ptr, flags);
    }
  }

  pub fn configure_tracking(&self, supported_tracking_caps: TrackingCaps, required_tracking_caps: TrackingCaps) -> bool {
    unsafe {
      let ovr_bool = ffi::ovrHmd_ConfigureTracking(
        self.ptr, supported_tracking_caps.mask, required_tracking_caps.mask
      );
      ovr_bool != 0i8
    }
  }

  pub fn recenter_pose(&self) {
    unsafe {
      ffi::ovrHmd_RecenterPose(self.ptr);
    }
  }

  pub fn get_tracking_state(&self, abs_time: f64) -> TrackingState {
    unsafe {
      ffi::ovrHmd_GetTrackingState(self.ptr, abs_time)
    }
  }

  pub fn get_fov_texture_size(&self, eye: EyeType, fov: FovPort, pixels_per_display_pixel: f32) -> Sizei {
    unsafe {
      ffi::ovrHmd_GetFovTextureSize(self.ptr, eye.to_ffi(), fov, pixels_per_display_pixel)
    }
  }

  pub fn configure_rendering(
    &self,
    api_config: RenderAPIConfig,
    distortion_caps: DistortionCaps,
    eye_fov_in: [FovPort, ..2],
  ) -> [EyeRenderDesc, ..2] {
    unsafe {
      let eye_fov_in_ptr: *const FovPort = &eye_fov_in[0];
      let mut eye_render_desc_out: [EyeRenderDesc, ..2] = [Default::default(), Default::default()];
      let eye_render_desc_out_ptr: *mut EyeRenderDesc = &mut eye_render_desc_out[0];
      ffi::ovrHmd_ConfigureRendering(self.ptr, &api_config, distortion_caps.mask, eye_fov_in_ptr, eye_render_desc_out_ptr);
      eye_render_desc_out
    }
  }

/*

  pub fn ovrHmd_ConfigureRendering(hmd: *mut Hmd,
                                   apiConfig: *const RenderAPIConfig,
                                   distortionCaps: c_uint,
                                   eyeFovIn: *const FovPort,
                                   eyeRenderDescOut: *mut EyeRenderDesc) -> OvrBool;

    pub fn get_sensor_state(&self, abs_time: f64) -> SensorState {
        unsafe {
            SensorState::from_ll(ll::ovrHmd_GetSensorState(self.ptr, abs_time))
        }
    }

    pub fn get_sensor_description(&self) -> Option<SensorDescription> {
        unsafe {
            let mut c_desc = ll::SensorDesc {
                vendor_id: 0,
                product_id: 0,
                serial_number: [0,.. 24]
            };

            if !ll::ovrHmd_GetSensorDesc(self.ptr, &mut c_desc as *mut ll::SensorDesc) {
                None
            } else {
                Some(SensorDescription::from_ll(c_desc))
            }
        }
    }

    pub fn get_description(&self) -> HmdDescription {
        unsafe {
            let mut c_desc = Default::default();
            ll::ovrHmd_GetDesc(self.ptr, &mut c_desc);
            HmdDescription::from_ll(c_desc)
        }
    }

    pub fn get_fov_texture_size(&self,
                                eye: EyeType,
                                fov: FovPort,
                                pixels_per_display_pixel: f32) -> ll::Sizei {
        unsafe {
            ll::ovrHmd_GetFovTextureSize(self.ptr,
                                         eye.to_ll(),
                                         fov.to_ll(),
                                         pixels_per_display_pixel)
        }
    }

    pub fn configure_rendering<RC: ToRenderConfig>(&self,
                               api_config: &RC,
                               cap: DistortionCapabilities,
                               eye_fov: PerEye<FovPort>) -> Option<PerEye<EyeRenderDescriptor>> {
        unsafe {
            let mut out: PerEye<ll::EyeRenderDesc> = PerEye::new(Default::default(),
                                                                 Default::default());
            let was_started = ll::ovrHmd_ConfigureRendering(
                self.ptr,
                &api_config.to_render_config(),
                cap.flags,
                eye_fov.map(|_, d| d.to_ll()).ptr(),
                out.mut_ptr()
            );

            if was_started {
                Some(out.map(|_, d| EyeRenderDescriptor::from_ll(d)))
            } else {
                None
            }
        }
    }

    pub fn begin_frame(&self, frame_index: uint) -> FrameTiming {
        unsafe {
            FrameTiming::from_ll(
                ll::ovrHmd_BeginFrame(self.ptr, frame_index as c_uint)
            )
        }
    }

    pub fn end_frame(&self) {
        unsafe {
            ll::ovrHmd_EndFrame(self.ptr);
        }
    }

    pub fn begin_eye_render(&self, eye: EyeType) -> Pose {
        unsafe {
            Pose::from_ll(ll::ovrHmd_BeginEyeRender(self.ptr, eye.to_ll()))
        }
    }

    pub fn end_eye_render<T: ToTexture>(&self,
                                        eye: EyeType,
                                        pose: Pose,
                                        texture: &T) {
        unsafe {
            ll::ovrHmd_EndEyeRender(self.ptr,
                                    eye.to_ll(),
                                    pose.to_ll(),
                                    &texture.to_texture());
        }
    }
    */
}

impl Drop for Hmd {
  fn drop(&mut self) {
    unsafe {ffi::ovrHmd_Destroy(self.ptr)}
  }
}

<|endoftext|>


<commit_before>extern crate csv;
use lib::models::*;
use std;

pub fn write(nodes: Vec<Node>, edges: Vec<Edge>) {
    let edges_path = std::path::Path::new("edges.csv");
    let mut edges_csv = csv::Writer::from_file(edges_path).unwrap();
    edges_csv.encode(vec!["id",
                     "source",
                     "target",
                     "length",
                     "foot",
                     "car_forward",
                     "car_backward",
                     "bike_forward",
                     "bike_backward"])
        .expect("CSV: unable to write edge header");
    for edge in edges {
        edges_csv.encode((edge.id,
                     edge.source,
                     edge.target,
                     edge.length(),
                     edge.properties.foot,
                     edge.properties.car_forward,
                     edge.properties.car_backward,
                     edge.properties.bike_forward,
                     edge.properties.bike_backward))
            .expect("CSV: unable to write edge");
    }

    let nodes_path = std::path::Path::new("nodes.csv");
    let mut nodes_csv = csv::Writer::from_file(nodes_path).unwrap();
    nodes_csv.encode(vec!["id", "lon", "lat"]).expect("CSV: unable to write node header");
    for node in nodes {
        nodes_csv.encode((node.id, node.coord.lon, node.coord.lat))
            .expect("CSV: unable to write node");
    }
}
<commit_msg>Export geometry<commit_after>extern crate csv;
use lib::models::*;
use std;

pub fn write(nodes: Vec<Node>, edges: Vec<Edge>) {
    let edges_path = std::path::Path::new("edges.csv");
    let mut edges_csv = csv::Writer::from_file(edges_path).unwrap();
    edges_csv.encode(vec!["id",
                     "source",
                     "target",
                     "length",
                     "foot",
                     "car_forward",
                     "car_backward",
                     "bike_forward",
                     "bike_backward",
                     "wkt"])
        .expect("CSV: unable to write edge header");
    for edge in edges {
        edges_csv.encode((edge.id,
                     edge.source,
                     edge.target,
                     edge.length(),
                     edge.properties.foot,
                     edge.properties.car_forward,
                     edge.properties.car_backward,
                     edge.properties.bike_forward,
                     edge.properties.bike_backward,
                     edge.as_wkt()))
            .expect("CSV: unable to write edge");
    }

    let nodes_path = std::path::Path::new("nodes.csv");
    let mut nodes_csv = csv::Writer::from_file(nodes_path).unwrap();
    nodes_csv.encode(vec!["id", "lon", "lat"]).expect("CSV: unable to write node header");
    for node in nodes {
        nodes_csv.encode((node.id, node.coord.lon, node.coord.lat))
            .expect("CSV: unable to write node");
    }
}
<|endoftext|>


<commit_before>extern crate walkdir;

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

use walkdir::{DirEntry, WalkDir};

fn build_hermit(src_dir: &Path, target_dir_opt: Option<&Path>) {
	let profile = env::var("PROFILE").expect("PROFILE was not set");
	let mut cmd = Command::new("cargo");
	cmd.current_dir(src_dir)
		.arg("build")
		.arg("-Z")
		.arg("build-std=core,alloc")
		.arg("--target")
		.arg("x86_64-unknown-hermit-kernel");

	if let Some(target_dir) = target_dir_opt {
		cmd.arg("--target-dir").arg(target_dir);
	}
	let target_dir = match target_dir_opt {
		Some(target_dir) => target_dir.to_path_buf(),
		None => src_dir.join("target"),
	};

	if profile == "release" {
		cmd.arg("--release");
	}

	#[cfg(feature = "instrument")]
	cmd.env("RUSTFLAGS", "-Z instrument-mcount");
	// if instrument is not set, ensure that instrument is not in environment variables!
	#[cfg(not(feature = "instrument"))]
	cmd.env(
		"RUSTFLAGS",
		env::var("RUSTFLAGS")
			.unwrap_or_else(|_| "".into())
			.replace("-Z instrument-mcount", ""),
	);

	let output = cmd.output().expect("Unable to build kernel");
	let stdout = std::string::String::from_utf8(output.stdout);
	let stderr = std::string::String::from_utf8(output.stderr);

	println!("Build libhermit-rs output-status: {}", output.status);
	println!("Build libhermit-rs output-stdout: {}", stdout.unwrap());
	println!("Build libhermit-rs output-stderr: {}", stderr.unwrap());
	assert!(output.status.success());

	let lib_location = target_dir
		.join("x86_64-unknown-hermit-kernel")
		.join(&profile)
		.canonicalize()
		.unwrap(); // Must exist after building
	println!("cargo:rustc-link-search=native={}", lib_location.display());
	println!("cargo:rustc-link-lib=static=hermit");

	//HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
	// Doesn't actually rebuild atm - see: https://github.com/rust-lang/cargo/issues/8306
	println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
}

#[cfg(all(not(feature = "rustc-dep-of-std"), not(feature = "with_submodule")))]
fn build() {
	#[cfg(windows)]
	let out_dir = env::temp_dir();
	#[cfg(not(windows))]
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let src_dir = out_dir.join("rusty-hermit");

	let _output = Command::new("cargo")
		.current_dir(out_dir)
		.arg("download")
		.arg("--output")
		.arg(src_dir.clone().into_os_string())
		.arg("--extract")
		.arg("rusty-hermit")
		.output()
		.expect("Unable to download rusty-hermit. Please install `cargo-download`.");

	build_hermit(src_dir.as_ref(), None);
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn build() {
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let target_dir = out_dir.clone().join("target");
	let src_dir = env::current_dir()
		.unwrap()
		.parent()
		.unwrap()
		.join("libhermit-rs");

	build_hermit(src_dir.as_ref(), Some(target_dir.as_ref()));
	configure_cargo_rerun_if_changed(src_dir.as_ref());
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn configure_cargo_rerun_if_changed(src_dir: &Path) {
	fn is_not_ignored(entry: &DirEntry) -> bool {
		// Ignore .git .vscode and target directories, but not .cargo or .github
		if entry.depth() == 1
			&& entry.path().is_dir()
			&& (entry.path().ends_with("target")
				|| entry.path().ends_with(".git")
				|| entry.path().ends_with(".vscode"))
		{
			return false;
		}
		true
	}

	WalkDir::new(src_dir)
		.into_iter()
		.filter_entry(|e| is_not_ignored(e))
		.filter_map(|v| v.ok())
		.filter_map(|v| v.path().canonicalize().ok())
		.for_each(|x| println!("cargo:rerun-if-changed={}", x.display()));
}

#[cfg(not(feature = "rustc-dep-of-std"))]
fn create_constants() {
	let out_dir = env::var("OUT_DIR").expect("No out dir");
	let dest_path = Path::new(&out_dir).join("constants.rs");
	let mut f = File::create(&dest_path).expect("Could not create file");

	let ip = option_env!("HERMIT_IP");
	let ip = ip.map_or("10.0.5.3", |v| v);

	let gateway = option_env!("HERMIT_GATEWAY");
	let gateway = gateway.map_or("10.0.5.1", |v| v);

	let mask = option_env!("HERMIT_MASK");
	let mask = mask.map_or("255.255.255.0", |v| v);

	writeln!(&mut f, "const HERMIT_IP: &str = \"{}\";", ip).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_IP");

	writeln!(&mut f, "const HERMIT_GATEWAY: &str = \"{}\";", gateway).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_GATEWAY");

	writeln!(&mut f, "const HERMIT_MASK: &str = \"{}\";", mask).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_MASK");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	create_constants();
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<commit_msg>minor changes to pass the format check<commit_after>extern crate walkdir;

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

use walkdir::{DirEntry, WalkDir};

fn build_hermit(src_dir: &Path, target_dir_opt: Option<&Path>) {
	let profile = env::var("PROFILE").expect("PROFILE was not set");
	let mut cmd = Command::new("cargo");
	cmd.current_dir(src_dir)
		.arg("build")
		.arg("-Z")
		.arg("build-std=core,alloc")
		.arg("--target")
		.arg("x86_64-unknown-hermit-kernel");

	if let Some(target_dir) = target_dir_opt {
		cmd.arg("--target-dir").arg(target_dir);
	}
	let target_dir = match target_dir_opt {
		Some(target_dir) => target_dir.to_path_buf(),
		None => src_dir.join("target"),
	};

	if profile == "release" {
		cmd.arg("--release");
	}

	#[cfg(feature = "instrument")]
	cmd.env("RUSTFLAGS", "-Z instrument-mcount");
	// if instrument is not set, ensure that instrument is not in environment variables!
	#[cfg(not(feature = "instrument"))]
	cmd.env(
		"RUSTFLAGS",
		env::var("RUSTFLAGS")
			.unwrap_or_else(|_| "".into())
			.replace("-Z instrument-mcount", ""),
	);

	let output = cmd.output().expect("Unable to build kernel");
	let stdout = std::string::String::from_utf8(output.stdout);
	let stderr = std::string::String::from_utf8(output.stderr);

	println!("Build libhermit-rs output-status: {}", output.status);
	println!("Build libhermit-rs output-stdout: {}", stdout.unwrap());
	println!("Build libhermit-rs output-stderr: {}", stderr.unwrap());
	assert!(output.status.success());

	let lib_location = target_dir
		.join("x86_64-unknown-hermit-kernel")
		.join(&profile)
		.canonicalize()
		.unwrap(); // Must exist after building
	println!("cargo:rustc-link-search=native={}", lib_location.display());
	println!("cargo:rustc-link-lib=static=hermit");

	//HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
	// Doesn't actually rebuild atm - see: https://github.com/rust-lang/cargo/issues/8306
	println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
}

#[cfg(all(not(feature = "rustc-dep-of-std"), not(feature = "with_submodule")))]
fn build() {
	#[cfg(windows)]
	let out_dir = env::temp_dir();
	#[cfg(not(windows))]
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let src_dir = out_dir.join("rusty-hermit");

	let _output = Command::new("cargo")
		.current_dir(out_dir)
		.arg("download")
		.arg("--output")
		.arg(src_dir.clone().into_os_string())
		.arg("--extract")
		.arg("rusty-hermit")
		.output()
		.expect("Unable to download rusty-hermit. Please install `cargo-download`.");

	build_hermit(src_dir.as_ref(), None);
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn build() {
	let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
	let target_dir = out_dir.clone().join("target");
	let src_dir = env::current_dir()
		.unwrap()
		.parent()
		.unwrap()
		.join("libhermit-rs");

	build_hermit(src_dir.as_ref(), Some(target_dir.as_ref()));
	configure_cargo_rerun_if_changed(src_dir.as_ref());
}

#[cfg(all(not(feature = "rustc-dep-of-std"), feature = "with_submodule"))]
fn configure_cargo_rerun_if_changed(src_dir: &Path) {
	fn is_not_ignored(entry: &DirEntry) -> bool {
		// Ignore .git .vscode and target directories, but not .cargo or .github
		if entry.depth() == 1
			&& entry.path().is_dir()
			&& (entry.path().ends_with("target")
				|| entry.path().ends_with(".git")
				|| entry.path().ends_with(".vscode"))
		{
			return false;
		}
		true
	}

	WalkDir::new(src_dir)
		.into_iter()
		.filter_entry(|e| is_not_ignored(e))
		.filter_map(|v| v.ok())
		.filter_map(|v| v.path().canonicalize().ok())
		.for_each(|x| println!("cargo:rerun-if-changed={}", x.display()));
}

#[cfg(not(feature = "rustc-dep-of-std"))]
fn create_constants() {
	let out_dir = env::var("OUT_DIR").expect("No out dir");
	let dest_path = Path::new(&out_dir).join("constants.rs");
	let mut f = File::create(&dest_path).expect("Could not create file");

	let ip = option_env!("HERMIT_IP");
	let ip = ip.map_or("10.0.5.3", |v| v);

	let gateway = option_env!("HERMIT_GATEWAY");
	let gateway = gateway.map_or("10.0.5.1", |v| v);

	let mask = option_env!("HERMIT_MASK");
	let mask = mask.map_or("255.255.255.0", |v| v);

	writeln!(&mut f, "const HERMIT_IP: &str = \"{}\";", ip).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_IP");

	writeln!(&mut f, "const HERMIT_GATEWAY: &str = \"{}\";", gateway)
		.expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_GATEWAY");

	writeln!(&mut f, "const HERMIT_MASK: &str = \"{}\";", mask).expect("Could not write file");
	println!("cargo:rerun-if-env-changed=HERMIT_MASK");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	create_constants();
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<|endoftext|>


<commit_before>use std::cmp::{Ordering};
use std::hash::{Hash, Hasher};
use calx::{V2, HexGeom, astar_path_with, LatticeNode, Dir6};
use calx::{Projection, color};
use calx_ecs::{Entity};
use world::{World, Goal, matches_mask, ComponentNum, Anim, Tween};
use spr::{Spr};
use ::{Sprite};

pub struct PathPos<'a> {
    pub world: &'a World,
    pub pos: V2<i32>,
}

impl<'a> PartialEq for PathPos<'a> { fn eq(&self, other: &PathPos<'a>) -> bool { self.pos == other.pos } }
impl<'a> Eq for PathPos<'a> {}
impl<'a> PartialOrd for PathPos<'a> { fn partial_cmp(&self, other: &PathPos<'a>) -> Option<Ordering> { self.pos.partial_cmp(&other.pos) } }
impl<'a> Ord for PathPos<'a> { fn cmp(&self, other: &PathPos<'a>) -> Ordering { self.pos.cmp(&other.pos) } }
impl<'a> Clone for PathPos<'a> { fn clone(&self) -> PathPos<'a> { PathPos { world: self.world, pos: self.pos } } }
impl<'a> Hash for PathPos<'a> { fn hash<H>(&self, state: &mut H) where H: Hasher { self.pos.hash(state) } }

impl<'a> PathPos<'a> {
    pub fn new(world: &'a World, pos: V2<i32>) -> PathPos<'a> {
        PathPos {
            world: world,
            pos: pos,
        }
    }
}

impl<'a> LatticeNode for PathPos<'a> {
    fn neighbors(&self) -> Vec<PathPos<'a>> {
        let mut ret = Vec::new();
        for i in Dir6::iter() {
            let pos = self.pos + i.to_v2();
            if self.world.terrain_at(pos).can_walk() {
                ret.push(PathPos::new(self.world, pos));
            }
        }
        ret
    }
}

pub fn find_path(ctx: &World, orig: V2<i32>, dest: V2<i32>) -> Option<Vec<V2<i32>>> {
    if let Some(path) = astar_path_with(
        |x, y| (x.pos-y.pos).hex_dist(), PathPos::new(ctx, orig), PathPos::new(ctx, dest), 1000) {
        // Skip the first step since that's where we are already.
        Some(path.iter().skip(1).map(|x| x.pos).collect())
    } else {
        None
    }
}

pub fn move_to(ctx: &mut World, e: Entity, dest: V2<i32>) {
    ctx.ecs.mob[e].goals.clear();

    ctx.ecs.mob[e].goals.push(Goal::MoveTo(dest));
}

pub fn is_player(ctx: &World, mob: Entity) -> bool {
    ctx.ecs.desc[mob].icon == Spr::Avatar
}

pub fn mobs(ctx: &World) -> Vec<Entity> {
    ctx.ecs.iter().filter(|&&e| matches_mask(&ctx.ecs, e, build_mask!(desc, mob, pos))).cloned().collect()
}

pub fn sprite(ctx: &World, e: Entity, p: &Projection) -> Option<Sprite> {
    if !ctx.ecs.pos.contains(e) || !ctx.ecs.desc.contains(e) { return None; }

    let cell_pos = ctx.ecs.pos[e];
    let spr = ctx.ecs.desc[e].icon;
    let color = ctx.ecs.desc[e].color;

    let default_anim = Anim::Standstill;
    let anim = if ctx.ecs.mob.contains(e) { &ctx.ecs.mob[e].anim } else { &default_anim };

    let draw_pos = anim.get_pos(cell_pos, ctx.anim_t, p);

    Some(Sprite::new(spr, draw_pos, 0, color, color::BLACK))
}

pub fn mob_at(ctx: &World, pos: V2<i32>) -> Option<Entity> {
    mobs(ctx).into_iter().filter(|&mob| ctx.ecs.pos[mob] == pos).next()
}

pub fn can_enter(ctx: &World, e: Entity, pos: V2<i32>) -> Option<BlockCause> {
    if !ctx.terrain_at(pos).can_walk() { return Some(BlockCause::Terrain); }
    match mob_at(ctx, pos) {
        Some(m) if m != e => { return Some(BlockCause::Mob(m)); }
        _ => { return None; }
    }
}

pub enum BlockCause {
    Terrain,
    Mob(Entity),
}

pub fn step(ctx: &mut World, e: Entity, dir: Dir6) -> Option<BlockCause> {
    let old_pos = ctx.ecs.pos[e];

    let new_pos = old_pos + dir.to_v2();

    let cause = can_enter(ctx, e, new_pos);

    if cause.is_some() {
        return cause;
    } else {
        let mob = &mut ctx.ecs.mob[e];
        let move_delay = 12;
        mob.action_delay = move_delay;
        mob.anim = Anim::Move(
            Tween::new(ctx.anim_t, old_pos, move_delay));
    }

    ctx.ecs.pos[e] = new_pos;

    None
}

/// Best movement direction to get towards destination.
pub fn way_towards(ctx: &World, e: Entity, dest: V2<i32>) -> Option<Dir6> {
    // XXX: A*-pathing anew for every step, VERY wasteful.
    if let Some(node) =  find_path(ctx, ctx.ecs.pos[e], dest).map_or(None, |x| x.first().map(|&y| y)) {
        Some(Dir6::from_v2(node - ctx.ecs.pos[e]))
    } else {
        None
    }
}

pub fn update_mob(ctx: &mut World, e: Entity) {
    let old_pos = ctx.ecs.pos[e];

    if ctx.ecs.mob[e].action_delay > 0 {
        ctx.ecs.mob[e].action_delay -= 1;
    } else {
        match ctx.ecs.mob[e].goals.first() {
            None => {}
            Some(&Goal::MoveTo(pos)) => {
                if old_pos == pos {
                    // Already there, remove goal.
                    ctx.ecs.mob[e].goals.remove(0);
                } else {
                    match way_towards(ctx, e, pos) {
                        Some(dir) => { step(ctx, e, dir); }
                        None => { ctx.ecs.mob[e].goals.remove(0); }
                    }
                }
            }
            _ => {
                unimplemented!();
            }
        }
    }
}

pub fn ready_to_act(ctx: &World, e: Entity) -> bool {
    ctx.ecs.mob[e].action_delay == 0
}
<commit_msg>Faster default movement<commit_after>use std::cmp::{Ordering};
use std::hash::{Hash, Hasher};
use calx::{V2, HexGeom, astar_path_with, LatticeNode, Dir6};
use calx::{Projection, color};
use calx_ecs::{Entity};
use world::{World, Goal, matches_mask, ComponentNum, Anim, Tween};
use spr::{Spr};
use ::{Sprite};

pub struct PathPos<'a> {
    pub world: &'a World,
    pub pos: V2<i32>,
}

impl<'a> PartialEq for PathPos<'a> { fn eq(&self, other: &PathPos<'a>) -> bool { self.pos == other.pos } }
impl<'a> Eq for PathPos<'a> {}
impl<'a> PartialOrd for PathPos<'a> { fn partial_cmp(&self, other: &PathPos<'a>) -> Option<Ordering> { self.pos.partial_cmp(&other.pos) } }
impl<'a> Ord for PathPos<'a> { fn cmp(&self, other: &PathPos<'a>) -> Ordering { self.pos.cmp(&other.pos) } }
impl<'a> Clone for PathPos<'a> { fn clone(&self) -> PathPos<'a> { PathPos { world: self.world, pos: self.pos } } }
impl<'a> Hash for PathPos<'a> { fn hash<H>(&self, state: &mut H) where H: Hasher { self.pos.hash(state) } }

impl<'a> PathPos<'a> {
    pub fn new(world: &'a World, pos: V2<i32>) -> PathPos<'a> {
        PathPos {
            world: world,
            pos: pos,
        }
    }
}

impl<'a> LatticeNode for PathPos<'a> {
    fn neighbors(&self) -> Vec<PathPos<'a>> {
        let mut ret = Vec::new();
        for i in Dir6::iter() {
            let pos = self.pos + i.to_v2();
            if self.world.terrain_at(pos).can_walk() {
                ret.push(PathPos::new(self.world, pos));
            }
        }
        ret
    }
}

pub fn find_path(ctx: &World, orig: V2<i32>, dest: V2<i32>) -> Option<Vec<V2<i32>>> {
    if let Some(path) = astar_path_with(
        |x, y| (x.pos-y.pos).hex_dist(), PathPos::new(ctx, orig), PathPos::new(ctx, dest), 1000) {
        // Skip the first step since that's where we are already.
        Some(path.iter().skip(1).map(|x| x.pos).collect())
    } else {
        None
    }
}

pub fn move_to(ctx: &mut World, e: Entity, dest: V2<i32>) {
    ctx.ecs.mob[e].goals.clear();

    ctx.ecs.mob[e].goals.push(Goal::MoveTo(dest));
}

pub fn is_player(ctx: &World, mob: Entity) -> bool {
    ctx.ecs.desc[mob].icon == Spr::Avatar
}

pub fn mobs(ctx: &World) -> Vec<Entity> {
    ctx.ecs.iter().filter(|&&e| matches_mask(&ctx.ecs, e, build_mask!(desc, mob, pos))).cloned().collect()
}

pub fn sprite(ctx: &World, e: Entity, p: &Projection) -> Option<Sprite> {
    if !ctx.ecs.pos.contains(e) || !ctx.ecs.desc.contains(e) { return None; }

    let cell_pos = ctx.ecs.pos[e];
    let spr = ctx.ecs.desc[e].icon;
    let color = ctx.ecs.desc[e].color;

    let default_anim = Anim::Standstill;
    let anim = if ctx.ecs.mob.contains(e) { &ctx.ecs.mob[e].anim } else { &default_anim };

    let draw_pos = anim.get_pos(cell_pos, ctx.anim_t, p);

    Some(Sprite::new(spr, draw_pos, 0, color, color::BLACK))
}

pub fn mob_at(ctx: &World, pos: V2<i32>) -> Option<Entity> {
    mobs(ctx).into_iter().filter(|&mob| ctx.ecs.pos[mob] == pos).next()
}

pub fn can_enter(ctx: &World, e: Entity, pos: V2<i32>) -> Option<BlockCause> {
    if !ctx.terrain_at(pos).can_walk() { return Some(BlockCause::Terrain); }
    match mob_at(ctx, pos) {
        Some(m) if m != e => { return Some(BlockCause::Mob(m)); }
        _ => { return None; }
    }
}

pub enum BlockCause {
    Terrain,
    Mob(Entity),
}

pub fn step(ctx: &mut World, e: Entity, dir: Dir6) -> Option<BlockCause> {
    let old_pos = ctx.ecs.pos[e];

    let new_pos = old_pos + dir.to_v2();

    let cause = can_enter(ctx, e, new_pos);

    if cause.is_some() {
        return cause;
    } else {
        let mob = &mut ctx.ecs.mob[e];
        let move_delay = 6;
        mob.action_delay = move_delay;
        mob.anim = Anim::Move(
            Tween::new(ctx.anim_t, old_pos, move_delay));
    }

    ctx.ecs.pos[e] = new_pos;

    None
}

/// Best movement direction to get towards destination.
pub fn way_towards(ctx: &World, e: Entity, dest: V2<i32>) -> Option<Dir6> {
    // XXX: A*-pathing anew for every step, VERY wasteful.
    if let Some(node) =  find_path(ctx, ctx.ecs.pos[e], dest).map_or(None, |x| x.first().map(|&y| y)) {
        Some(Dir6::from_v2(node - ctx.ecs.pos[e]))
    } else {
        None
    }
}

pub fn update_mob(ctx: &mut World, e: Entity) {
    let old_pos = ctx.ecs.pos[e];

    if ctx.ecs.mob[e].action_delay > 0 {
        ctx.ecs.mob[e].action_delay -= 1;
    } else {
        match ctx.ecs.mob[e].goals.first() {
            None => {}
            Some(&Goal::MoveTo(pos)) => {
                if old_pos == pos {
                    // Already there, remove goal.
                    ctx.ecs.mob[e].goals.remove(0);
                } else {
                    match way_towards(ctx, e, pos) {
                        Some(dir) => { step(ctx, e, dir); }
                        None => { ctx.ecs.mob[e].goals.remove(0); }
                    }
                }
            }
            _ => {
                unimplemented!();
            }
        }
    }
}

pub fn ready_to_act(ctx: &World, e: Entity) -> bool {
    ctx.ecs.mob[e].action_delay == 0
}
<|endoftext|>


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

use driver::config;
use driver::session::Session;

use syntax::ast;
use syntax::attr;
use syntax::codemap::DUMMY_SP;
use syntax::codemap;
use syntax::fold::Folder;
use syntax::fold;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::util::small_vector::SmallVector;

pub static VERSION: &'static str = "0.11.0-pre";

pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
                               -> ast::Crate {
    if use_std(&krate) {
        inject_crates_ref(sess, krate)
    } else {
        krate
    }
}

pub fn maybe_inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
    if use_std(&krate) {
        inject_prelude(sess, krate)
    } else {
        krate
    }
}

fn use_std(krate: &ast::Crate) -> bool {
    !attr::contains_name(krate.attrs.as_slice(), "no_std")
}

fn use_start(krate: &ast::Crate) -> bool {
    !attr::contains_name(krate.attrs.as_slice(), "no_start")
}

fn no_prelude(attrs: &[ast::Attribute]) -> bool {
    attr::contains_name(attrs, "no_implicit_prelude")
}

struct StandardLibraryInjector<'a> {
    sess: &'a Session,
}

pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
    match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
        Some("1") => None,
        _ => {
            Some((token::intern_and_get_ident(format!("{}\\#{}",
                                                      krate,
                                                      VERSION)),
                  ast::CookedStr))
        }
    }
}

impl<'a> fold::Folder for StandardLibraryInjector<'a> {
    fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
        let mut vis = vec!(ast::ViewItem {
            node: ast::ViewItemExternCrate(token::str_to_ident("std"),
                                         with_version("std"),
                                         ast::DUMMY_NODE_ID),
            attrs: vec!(
                attr::mk_attr(attr::mk_list_item(
                        InternedString::new("phase"),
                        vec!(
                            attr::mk_word_item(InternedString::new("syntax")),
                            attr::mk_word_item(InternedString::new("link")
                        ))))),
            vis: ast::Inherited,
            span: DUMMY_SP
        });

        let any_exe = self.sess.crate_types.borrow().iter().any(|ty| {
            *ty == config::CrateTypeExecutable
        });
        if use_start(&krate) && any_exe {
            vis.push(ast::ViewItem {
                node: ast::ViewItemExternCrate(token::str_to_ident("native"),
                                             with_version("native"),
                                             ast::DUMMY_NODE_ID),
                attrs: Vec::new(),
                vis: ast::Inherited,
                span: DUMMY_SP
            });
        }

        vis.push_all_move(krate.module.view_items.clone());
        let new_module = ast::Mod {
            view_items: vis,
            ..krate.module.clone()
        };

        ast::Crate {
            module: new_module,
            ..krate
        }
    }
}

fn inject_crates_ref(sess: &Session, krate: ast::Crate) -> ast::Crate {
    let mut fold = StandardLibraryInjector {
        sess: sess,
    };
    fold.fold_crate(krate)
}

struct PreludeInjector<'a> {
    sess: &'a Session,
}

impl<'a> fold::Folder for PreludeInjector<'a> {
    fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
        if !no_prelude(krate.attrs.as_slice()) {
            // only add `use std::prelude::*;` if there wasn't a
            // `#![no_implicit_prelude]` at the crate level.
            ast::Crate {
                module: self.fold_mod(&krate.module),
                ..krate
            }
        } else {
            krate
        }
    }

    fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
        if !no_prelude(item.attrs.as_slice()) {
            // only recur if there wasn't `#![no_implicit_prelude]`
            // on this item, i.e. this means that the prelude is not
            // implicitly imported though the whole subtree
            fold::noop_fold_item(item, self)
        } else {
            SmallVector::one(item)
        }
    }

    fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod {
        let prelude_path = ast::Path {
            span: DUMMY_SP,
            global: false,
            segments: vec!(
                ast::PathSegment {
                    identifier: token::str_to_ident("std"),
                    lifetimes: Vec::new(),
                    types: OwnedSlice::empty(),
                },
                ast::PathSegment {
                    identifier: token::str_to_ident("prelude"),
                    lifetimes: Vec::new(),
                    types: OwnedSlice::empty(),
                }),
        };

        let vp = @codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID));
        let vi2 = ast::ViewItem {
            node: ast::ViewItemUse(vp),
            attrs: Vec::new(),
            vis: ast::Inherited,
            span: DUMMY_SP,
        };

        let vis = (vec!(vi2)).append(module.view_items.as_slice());

        // FIXME #2543: Bad copy.
        let new_module = ast::Mod {
            view_items: vis,
            ..(*module).clone()
        };
        fold::noop_fold_mod(&new_module, self)
    }
}

fn inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
    let mut fold = PreludeInjector {
        sess: sess,
    };
    fold.fold_crate(krate)
}
<commit_msg>rustc: Make std_inject valid for pretty-printer<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use driver::config;
use driver::session::Session;

use syntax::ast;
use syntax::attr;
use syntax::codemap::DUMMY_SP;
use syntax::codemap;
use syntax::fold::Folder;
use syntax::fold;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::util::small_vector::SmallVector;

pub static VERSION: &'static str = "0.11.0-pre";

pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
                               -> ast::Crate {
    if use_std(&krate) {
        inject_crates_ref(sess, krate)
    } else {
        krate
    }
}

pub fn maybe_inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
    if use_std(&krate) {
        inject_prelude(sess, krate)
    } else {
        krate
    }
}

fn use_std(krate: &ast::Crate) -> bool {
    !attr::contains_name(krate.attrs.as_slice(), "no_std")
}

fn use_start(krate: &ast::Crate) -> bool {
    !attr::contains_name(krate.attrs.as_slice(), "no_start")
}

fn no_prelude(attrs: &[ast::Attribute]) -> bool {
    attr::contains_name(attrs, "no_implicit_prelude")
}

struct StandardLibraryInjector<'a> {
    sess: &'a Session,
}

pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
    match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
        Some("1") => None,
        _ => {
            Some((token::intern_and_get_ident(format!("{}\\#{}",
                                                      krate,
                                                      VERSION)),
                  ast::CookedStr))
        }
    }
}

impl<'a> fold::Folder for StandardLibraryInjector<'a> {
    fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
        let mut vis = vec!(ast::ViewItem {
            node: ast::ViewItemExternCrate(token::str_to_ident("std"),
                                         with_version("std"),
                                         ast::DUMMY_NODE_ID),
            attrs: vec!(
                attr::mk_attr(attr::mk_list_item(
                        InternedString::new("phase"),
                        vec!(
                            attr::mk_word_item(InternedString::new("syntax")),
                            attr::mk_word_item(InternedString::new("link")
                        ))))),
            vis: ast::Inherited,
            span: DUMMY_SP
        });

        let any_exe = self.sess.crate_types.borrow().iter().any(|ty| {
            *ty == config::CrateTypeExecutable
        });
        if use_start(&krate) && any_exe {
            vis.push(ast::ViewItem {
                node: ast::ViewItemExternCrate(token::str_to_ident("native"),
                                             with_version("native"),
                                             ast::DUMMY_NODE_ID),
                attrs: Vec::new(),
                vis: ast::Inherited,
                span: DUMMY_SP
            });
        }

        // `extern crate` must be precede `use` items
        vis.push_all_move(krate.module.view_items.clone());
        let new_module = ast::Mod {
            view_items: vis,
            ..krate.module.clone()
        };

        ast::Crate {
            module: new_module,
            ..krate
        }
    }
}

fn inject_crates_ref(sess: &Session, krate: ast::Crate) -> ast::Crate {
    let mut fold = StandardLibraryInjector {
        sess: sess,
    };
    fold.fold_crate(krate)
}

struct PreludeInjector<'a> {
    sess: &'a Session,
}

impl<'a> fold::Folder for PreludeInjector<'a> {
    fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
        if !no_prelude(krate.attrs.as_slice()) {
            // only add `use std::prelude::*;` if there wasn't a
            // `#![no_implicit_prelude]` at the crate level.

            let mut attrs = krate.attrs.clone();

            // fold_mod() will insert glob path.
            let globs_attr = attr::mk_attr(attr::mk_list_item(
                InternedString::new("feature"),
                vec!(
                    attr::mk_word_item(InternedString::new("globs")),
                )));
            attrs.push(globs_attr);

            ast::Crate {
                module: self.fold_mod(&krate.module),
                attrs: attrs,
                ..krate
            }
        } else {
            krate
        }
    }

    fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
        if !no_prelude(item.attrs.as_slice()) {
            // only recur if there wasn't `#![no_implicit_prelude]`
            // on this item, i.e. this means that the prelude is not
            // implicitly imported though the whole subtree
            fold::noop_fold_item(item, self)
        } else {
            SmallVector::one(item)
        }
    }

    fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod {
        let prelude_path = ast::Path {
            span: DUMMY_SP,
            global: false,
            segments: vec!(
                ast::PathSegment {
                    identifier: token::str_to_ident("std"),
                    lifetimes: Vec::new(),
                    types: OwnedSlice::empty(),
                },
                ast::PathSegment {
                    identifier: token::str_to_ident("prelude"),
                    lifetimes: Vec::new(),
                    types: OwnedSlice::empty(),
                }),
        };

        let vp = @codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID));
        let vi2 = ast::ViewItem {
            node: ast::ViewItemUse(vp),
            attrs: Vec::new(),
            vis: ast::Inherited,
            span: DUMMY_SP,
        };

        let (crates, uses) = module.view_items.partitioned(|x| {
            match x.node {
                ast::ViewItemExternCrate(..) => true,
                _ => false,
            }
        });

        // add vi2 after any `extern crate` but before any `use`
        let mut view_items = crates;
        view_items.push(vi2);
        view_items.push_all_move(uses);

        let new_module = ast::Mod {
            view_items: view_items,
            ..(*module).clone()
        };
        fold::noop_fold_mod(&new_module, self)
    }
}

fn inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
    let mut fold = PreludeInjector {
        sess: sess,
    };
    fold.fold_crate(krate)
}
<|endoftext|>