<commit_before>extern crate rosc;
extern crate byteorder;

use byteorder::{ByteOrder, BigEndian};
use std::mem;
use rosc::{types, errors, decoder, utils};

#[test]
fn test_decode_no_args() {
    // message to build: /some/valid/address/4 ,
    let raw_addr = "/some/valid/address/4";
    let addr = pad(raw_addr.as_bytes());
    let type_tags = pad(b",");
    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .collect();
    let osc_packet: Result<types::OscPacket, errors::OscError> = decoder::decode(&merged);
    assert!(osc_packet.is_ok());
    match osc_packet {
        Ok(types::OscPacket::Message(msg)) => {
            assert_eq!(raw_addr, msg.addr);
            assert!(msg.args.is_none());
        }
        Ok(_) => panic!("Expected an OscMessage!"),
        Err(e) => panic!(e),
    }
}

#[test]
fn test_decode_args() {
    // /another/valid/address/123 ,fdih 3.1415 3.14159265359 12345678i32
    // -1234567891011
    let raw_addr = "/another/valid/address/123";
    let addr = pad(raw_addr.as_bytes());
    // args
    let f = 3.1415f32;
    let mut f_bytes: [u8; 4] = [0u8; 4];
    BigEndian::write_f32(&mut f_bytes, f);
    assert_eq!(BigEndian::read_f32(&f_bytes), f);

    let d = 3.14159265359f64;
    let mut d_bytes: [u8; 8] = [0u8; 8];
    BigEndian::write_f64(&mut d_bytes, d);
    assert_eq!(BigEndian::read_f64(&d_bytes), d);

    let i = 12345678i32;
    let i_bytes: [u8; 4] = unsafe { mem::transmute(i.to_be()) };

    let l = -1234567891011i64;
    let h_bytes: [u8; 8] = unsafe { mem::transmute(l.to_be()) };

    let type_tags = pad(b",fdih");

    let args: Vec<u8> = f_bytes.iter()
                               .chain(d_bytes.iter())
                               .chain(i_bytes.iter())
                               .chain(h_bytes.iter())
                               .map(|x| *x)
                               .collect::<Vec<u8>>();

    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .chain(args)
                              .collect::<Vec<u8>>();

    let osc_packet: Result<types::OscPacket, errors::OscError> = decoder::decode(&merged);
    match osc_packet {
        Ok(types::OscPacket::Message(msg)) => {
            assert_eq!(raw_addr, msg.addr);
            for arg in msg.args.unwrap() {
                match arg {
                    types::OscType::OscInt(x) => assert_eq!(i, x),
                    types::OscType::OscLong(x) => assert_eq!(l, x),
                    types::OscType::OscFloat(x) => assert_eq!(f, x),
                    types::OscType::OscDouble(x) => assert_eq!(d, x),
                    _ => panic!(),
                }
            }
        }
        Ok(_) => panic!("Expected an OscMessage!"),
        Err(e) => panic!(e),
    }
}

fn pad(data: &[u8]) -> Vec<u8> {
    let pad_len: usize = utils::pad(data.len() as u64) as usize;
    let mut v: Vec<u8> = data.iter().cloned().collect();
    while v.len() < pad_len {
        v.push(0u8);
    }
    v
}<commit_msg>Refactor `pad` to `to_osc_string`<commit_after>extern crate rosc;
extern crate byteorder;

use byteorder::{ByteOrder, BigEndian};
use std::{mem, iter};

use rosc::{types, errors, decoder, utils};

#[test]
fn test_decode_no_args() {
    // message to build: /some/valid/address/4 ,
    let raw_addr = "/some/valid/address/4";
    let addr = to_osc_string(raw_addr.as_bytes());
    let type_tags = to_osc_string(b",");
    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .collect();
    let osc_packet: Result<types::OscPacket, errors::OscError> = decoder::decode(&merged);
    assert!(osc_packet.is_ok());
    match osc_packet {
        Ok(types::OscPacket::Message(msg)) => {
            assert_eq!(raw_addr, msg.addr);
            assert!(msg.args.is_none());
        }
        Ok(_) => panic!("Expected an OscMessage!"),
        Err(e) => panic!(e),
    }
}

#[test]
fn test_decode_args() {
    // /another/valid/address/123 ,fdih 3.1415 3.14159265359 12345678i32
    // -1234567891011
    let raw_addr = "/another/valid/address/123";
    let addr = to_osc_string(raw_addr.as_bytes());
    // args
    let f = 3.1415f32;
    let mut f_bytes: [u8; 4] = [0u8; 4];
    BigEndian::write_f32(&mut f_bytes, f);
    assert_eq!(BigEndian::read_f32(&f_bytes), f);

    let d = 3.14159265359f64;
    let mut d_bytes: [u8; 8] = [0u8; 8];
    BigEndian::write_f64(&mut d_bytes, d);
    assert_eq!(BigEndian::read_f64(&d_bytes), d);

    let i = 12345678i32;
    let i_bytes: [u8; 4] = unsafe { mem::transmute(i.to_be()) };

    let l = -1234567891011i64;
    let h_bytes: [u8; 8] = unsafe { mem::transmute(l.to_be()) };

    let type_tags = to_osc_string(b",fdsih");

    let args: Vec<u8> = f_bytes.iter()
                               .chain(d_bytes.iter())
                               .chain(i_bytes.iter())
                               .chain(h_bytes.iter())
                               .map(|x| *x)
                               .collect::<Vec<u8>>();

    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .chain(args)
                              .collect::<Vec<u8>>();

    let osc_packet: Result<types::OscPacket, errors::OscError> = decoder::decode(&merged);
    match osc_packet {
        Ok(types::OscPacket::Message(msg)) => {
            assert_eq!(raw_addr, msg.addr);
            for arg in msg.args.unwrap() {
                match arg {
                    types::OscType::OscInt(x) => assert_eq!(i, x),
                    types::OscType::OscLong(x) => assert_eq!(l, x),
                    types::OscType::OscFloat(x) => assert_eq!(f, x),
                    types::OscType::OscDouble(x) => assert_eq!(d, x),
                    _ => panic!(),
                }
            }
        }
        Ok(_) => panic!("Expected an OscMessage!"),
        Err(e) => panic!(e),
    }
}

/// Nul terminates the data and pads with zero bytes to a length that is a multiple of 4.
fn to_osc_string(data: &[u8]) -> Vec<u8> {
    let mut v: Vec<u8> = data.iter()
                             .cloned()
                             .chain(iter::once(0u8))
                             .collect();
    // v;
    let pad_len: usize = utils::pad(v.len() as u64) as usize;
    while v.len() < pad_len {
        v.push(0u8);
    }
    v
}<|endoftext|>


<commit_before>use super::{RootMove, MAX_MOVES};
use sync::GuardedBool;

use pleco::{MoveList, Board, PieceType, BitMove};

use std::slice;
use std::ops::{Deref,DerefMut,Index,IndexMut};
use std::iter::{Iterator,IntoIterator,FusedIterator,TrustedLen,ExactSizeIterator};
use std::ptr;

use std::mem::transmute;
use std::sync::atomic::{AtomicU16,Ordering,fence,AtomicBool,AtomicUsize};

use rand;
use rand::Rng;

pub struct RawRootMoveList {
    len: AtomicUsize,
    depth_completed: AtomicU16,
    stop: AtomicBool,
    kill: AtomicBool,
    pub finished: GuardedBool,
    moves: [RootMove; MAX_MOVES],
}

impl RawRootMoveList {
    pub fn init(&mut self) {
        self.depth_completed = AtomicU16::new(0);
        self.stop.store(true, Ordering::SeqCst);
        self.kill.store(false, Ordering::SeqCst);
        self.len = AtomicUsize::new(0);
        unsafe {
            let f = &mut self.finished;
            ptr::write_volatile(f, GuardedBool::new(true));
        }
    }
}

pub struct RootMoveList {
    pub moves: *mut RawRootMoveList
}

impl Clone for RootMoveList {
    fn clone(&self) -> Self {
        RootMoveList {
            moves: self.moves
        }
    }
}

unsafe impl Send for RootMoveList {}

impl RootMoveList {
    pub unsafe fn init(&mut self) {
        (*self.moves).init();
    }

    #[inline]
    pub fn len(&self) -> usize {
        unsafe {(*self.moves).len.load(Ordering::Release)}
    }

    pub fn clone_from_other(&mut self, other: &RootMoveList) {
        unsafe {
            (*self.moves).len.store(other.len(), Ordering::Acquire);
            let self_moves: *mut [RootMove; MAX_MOVES] = transmute::<*mut RootMove, *mut [RootMove; MAX_MOVES]>((*self.moves).moves.as_mut_ptr());
            let other_moves: *mut [RootMove; MAX_MOVES] =  transmute::<*mut RootMove, *mut [RootMove; MAX_MOVES]>((*other.moves).moves.as_mut_ptr());
            ptr::copy_nonoverlapping(other_moves, self_moves, 1);
        }
    }

    pub fn replace(&mut self, moves: &MoveList) {
        unsafe {
            (*self.moves).len.store(moves.len(), Ordering::Acquire);
            for (i, mov) in moves.iter().enumerate() {
                self[i] = RootMove::new(*mov);
            }
        }
    }

    #[inline]
    pub fn rollback(&mut self) {
        self.iter_mut()
            .for_each(|b| b.prev_score = b.score);
    }

    #[inline]
    pub fn first(&mut self) -> &mut RootMove {
        unsafe {
            self.get_unchecked_mut(0)
        }
    }

    #[inline]
    pub fn depth_completed(self) -> u16 {
        unsafe {
            (*self.moves).depth_completed.load(Ordering::SeqCst)
        }
    }

    #[inline]
    pub fn set_depth_completed(&mut self, depth: u16) {
        unsafe {
            fence(Ordering::SeqCst);
            (*self.moves).depth_completed.store(depth, Ordering::SeqCst);
        }
    }

    #[inline]
    pub fn set_finished(&mut self, finished: bool) {
        unsafe {
            (*self.moves).finished.set(finished);
        }
    }

    pub fn load_stop(&self) -> bool{
        unsafe {
            (*self.moves).stop.load(Ordering::SeqCst)
        }
    }

    pub fn set_stop(&mut self, stop: bool) {
        unsafe {
            (*self.moves).stop.store(stop, Ordering::Relaxed);
        }
    }

    pub fn kill(&mut self) {
        unsafe {
            (*self.moves).kill.store(true, Ordering::Relaxed);
        }
    }

    pub fn get_kill(&self) -> bool {
        unsafe {
            (*self.moves).kill.load(Ordering::SeqCst)
        }
    }

    #[inline]
    pub fn mvv_laa_sort(&mut self, board: &Board) {
        self.sort_by_key(|root_move| {
            let a = root_move.bit_move;
            let piece = board.piece_at_sq((a).get_src()).unwrap();

            if a.is_capture() {
                piece.value() - board.captured_piece(a).unwrap().value()
            } else if a.is_castle() {
                1
            } else if piece == PieceType::P {
                if a.is_double_push().0 {
                    2
                } else {
                    3
                }
            } else {
                4
            }
        });
    }

    #[inline]
    pub fn shuffle(&mut self, thread_id: usize, board: &Board) {
        if thread_id == 0 || thread_id >= 20 {
            self.mvv_laa_sort(board);
        } else {
            rand::thread_rng().shuffle(self.as_mut());
        }
    }

    pub fn to_list(&self) -> MoveList {
        let vec =  self.iter().map(|m| m.bit_move).collect::<Vec<BitMove>>();
        MoveList::from(vec)
    }

    pub fn prev_best_score(&self) -> i32 {
        unsafe {
            self.get_unchecked(0).prev_score
        }
    }

    pub fn insert_score_depth(&mut self, index: usize, score: i32, depth: u16) {
        unsafe {
            let rm: &mut RootMove = self.get_unchecked_mut(index);
            rm.score = score;
            rm.depth_reached = depth;

        }
    }

    pub fn insert_score(&mut self, index: usize, score: i32) {
        unsafe {
            let rm: &mut RootMove = self.get_unchecked_mut(index);
            rm.score = score;
        }
    }
}

impl Deref for RootMoveList {
    type Target = [RootMove];

    #[inline]
    fn deref(&self) -> &[RootMove] {
        unsafe {
            let p = (*self.moves).moves.as_ptr();
            slice::from_raw_parts(p, self.len())
        }
    }
}

impl DerefMut for RootMoveList {
    #[inline]
    fn deref_mut(&mut self) -> &mut [RootMove] {
        unsafe {
            let p = (*self.moves).moves.as_mut_ptr();
            slice::from_raw_parts_mut(p, self.len())
        }
    }
}

impl Index<usize> for RootMoveList {
    type Output = RootMove;

    #[inline]
    fn index(&self, index: usize) -> &RootMove {
        &(**self)[index]
    }
}

impl IndexMut<usize> for RootMoveList {
    #[inline]
    fn index_mut(&mut self, index: usize) -> &mut RootMove {
        &mut (**self)[index]
    }
}

pub struct MoveIter<'a> {
    movelist: &'a RootMoveList,
    idx: usize,
    len: usize
}

impl<'a> Iterator for MoveIter<'a> {
    type Item = RootMove;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.len {
            None
        } else {
            unsafe {
                let m = *self.movelist.get_unchecked(self.idx);
                self.idx += 1;
                Some(m)
            }

        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len - self.idx, Some(self.len - self.idx))
    }
}

impl<'a> IntoIterator for &'a RootMoveList {
    type Item = RootMove;
    type IntoIter = MoveIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        MoveIter {
            movelist: &self,
            idx: 0,
            len: self.len()
        }
    }
}

impl<'a> ExactSizeIterator for MoveIter<'a> {}

impl<'a> FusedIterator for MoveIter<'a> {}

unsafe impl<'a> TrustedLen for MoveIter<'a> {}<commit_msg>Changed atomic orderings around again<commit_after>use super::{RootMove, MAX_MOVES};
use sync::GuardedBool;

use pleco::{MoveList, Board, PieceType, BitMove};

use std::slice;
use std::ops::{Deref,DerefMut,Index,IndexMut};
use std::iter::{Iterator,IntoIterator,FusedIterator,TrustedLen,ExactSizeIterator};
use std::ptr;

use std::mem::transmute;
use std::sync::atomic::{AtomicU16,Ordering,fence,AtomicBool,AtomicUsize};

use rand;
use rand::Rng;

pub struct RawRootMoveList {
    len: AtomicUsize,
    depth_completed: AtomicU16,
    stop: AtomicBool,
    kill: AtomicBool,
    pub finished: GuardedBool,
    moves: [RootMove; MAX_MOVES],
}

impl RawRootMoveList {
    pub fn init(&mut self) {
        self.depth_completed = AtomicU16::new(0);
        self.stop.store(true, Ordering::SeqCst);
        self.kill.store(false, Ordering::SeqCst);
        self.len = AtomicUsize::new(0);
        unsafe {
            let f = &mut self.finished;
            ptr::write_volatile(f, GuardedBool::new(true));
        }
    }
}

pub struct RootMoveList {
    pub moves: *mut RawRootMoveList
}

impl Clone for RootMoveList {
    fn clone(&self) -> Self {
        RootMoveList {
            moves: self.moves
        }
    }
}

unsafe impl Send for RootMoveList {}

impl RootMoveList {
    pub unsafe fn init(&mut self) {
        (*self.moves).init();
    }

    #[inline]
    pub fn len(&self) -> usize {
        unsafe {(*self.moves).len.load(Ordering::Acquire)}
    }

    pub fn clone_from_other(&mut self, other: &RootMoveList) {
        unsafe {
            (*self.moves).len.store(other.len(), Ordering::Release);
            let self_moves: *mut [RootMove; MAX_MOVES] = transmute::<*mut RootMove, *mut [RootMove; MAX_MOVES]>((*self.moves).moves.as_mut_ptr());
            let other_moves: *mut [RootMove; MAX_MOVES] =  transmute::<*mut RootMove, *mut [RootMove; MAX_MOVES]>((*other.moves).moves.as_mut_ptr());
            ptr::copy_nonoverlapping(other_moves, self_moves, 1);
        }
    }

    pub fn replace(&mut self, moves: &MoveList) {
        unsafe {
            (*self.moves).len.store(moves.len(), Ordering::Release);
            for (i, mov) in moves.iter().enumerate() {
                self[i] = RootMove::new(*mov);
            }
        }
    }

    #[inline]
    pub fn rollback(&mut self) {
        self.iter_mut()
            .for_each(|b| b.prev_score = b.score);
    }

    #[inline]
    pub fn first(&mut self) -> &mut RootMove {
        unsafe {
            self.get_unchecked_mut(0)
        }
    }

    #[inline]
    pub fn depth_completed(self) -> u16 {
        unsafe {
            (*self.moves).depth_completed.load(Ordering::SeqCst)
        }
    }

    #[inline]
    pub fn set_depth_completed(&mut self, depth: u16) {
        unsafe {
            fence(Ordering::SeqCst);
            (*self.moves).depth_completed.store(depth, Ordering::SeqCst);
        }
    }

    #[inline]
    pub fn set_finished(&mut self, finished: bool) {
        unsafe {
            (*self.moves).finished.set(finished);
        }
    }

    pub fn load_stop(&self) -> bool{
        unsafe {
            (*self.moves).stop.load(Ordering::SeqCst)
        }
    }

    pub fn set_stop(&mut self, stop: bool) {
        unsafe {
            (*self.moves).stop.store(stop, Ordering::Release);
        }
    }

    pub fn kill(&mut self) {
        unsafe {
            (*self.moves).kill.store(true, Ordering::Release);
        }
    }

    pub fn get_kill(&self) -> bool {
        unsafe {
            (*self.moves).kill.load(Ordering::SeqCst)
        }
    }

    #[inline]
    pub fn mvv_laa_sort(&mut self, board: &Board) {
        self.sort_by_key(|root_move| {
            let a = root_move.bit_move;
            let piece = board.piece_at_sq((a).get_src()).unwrap();

            if a.is_capture() {
                piece.value() - board.captured_piece(a).unwrap().value()
            } else if a.is_castle() {
                1
            } else if piece == PieceType::P {
                if a.is_double_push().0 {
                    2
                } else {
                    3
                }
            } else {
                4
            }
        });
    }

    #[inline]
    pub fn shuffle(&mut self, thread_id: usize, board: &Board) {
        if thread_id == 0 || thread_id >= 20 {
            self.mvv_laa_sort(board);
        } else {
            rand::thread_rng().shuffle(self.as_mut());
        }
    }

    pub fn to_list(&self) -> MoveList {
        let vec =  self.iter().map(|m| m.bit_move).collect::<Vec<BitMove>>();
        MoveList::from(vec)
    }

    pub fn prev_best_score(&self) -> i32 {
        unsafe {
            self.get_unchecked(0).prev_score
        }
    }

    pub fn insert_score_depth(&mut self, index: usize, score: i32, depth: u16) {
        unsafe {
            let rm: &mut RootMove = self.get_unchecked_mut(index);
            rm.score = score;
            rm.depth_reached = depth;

        }
    }

    pub fn insert_score(&mut self, index: usize, score: i32) {
        unsafe {
            let rm: &mut RootMove = self.get_unchecked_mut(index);
            rm.score = score;
        }
    }
}

impl Deref for RootMoveList {
    type Target = [RootMove];

    #[inline]
    fn deref(&self) -> &[RootMove] {
        unsafe {
            let p = (*self.moves).moves.as_ptr();
            slice::from_raw_parts(p, self.len())
        }
    }
}

impl DerefMut for RootMoveList {
    #[inline]
    fn deref_mut(&mut self) -> &mut [RootMove] {
        unsafe {
            let p = (*self.moves).moves.as_mut_ptr();
            slice::from_raw_parts_mut(p, self.len())
        }
    }
}

impl Index<usize> for RootMoveList {
    type Output = RootMove;

    #[inline]
    fn index(&self, index: usize) -> &RootMove {
        &(**self)[index]
    }
}

impl IndexMut<usize> for RootMoveList {
    #[inline]
    fn index_mut(&mut self, index: usize) -> &mut RootMove {
        &mut (**self)[index]
    }
}

pub struct MoveIter<'a> {
    movelist: &'a RootMoveList,
    idx: usize,
    len: usize
}

impl<'a> Iterator for MoveIter<'a> {
    type Item = RootMove;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.len {
            None
        } else {
            unsafe {
                let m = *self.movelist.get_unchecked(self.idx);
                self.idx += 1;
                Some(m)
            }

        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len - self.idx, Some(self.len - self.idx))
    }
}

impl<'a> IntoIterator for &'a RootMoveList {
    type Item = RootMove;
    type IntoIter = MoveIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        MoveIter {
            movelist: &self,
            idx: 0,
            len: self.len()
        }
    }
}

impl<'a> ExactSizeIterator for MoveIter<'a> {}

impl<'a> FusedIterator for MoveIter<'a> {}

unsafe impl<'a> TrustedLen for MoveIter<'a> {}<|endoftext|>


<commit_before>use rustc_data_structures::graph::{self, iterate};
use rustc_graphviz as dot;
use rustc_middle::ty::TyCtxt;
use std::io::{self, Write};

pub struct GraphvizWriter<
    'a,
    G: graph::DirectedGraph + graph::WithSuccessors + graph::WithStartNode + graph::WithNumNodes,
    NodeContentFn: Fn(<G as rustc_data_structures::graph::DirectedGraph>::Node) -> Vec<String>,
    EdgeLabelsFn: Fn(<G as rustc_data_structures::graph::DirectedGraph>::Node) -> Vec<String>,
> {
    graph: &'a G,
    is_subgraph: bool,
    graphviz_name: String,
    graph_label: Option<String>,
    node_content_fn: NodeContentFn,
    edge_labels_fn: EdgeLabelsFn,
}

impl<
    'a,
    G: graph::DirectedGraph + graph::WithSuccessors + graph::WithStartNode + graph::WithNumNodes,
    NodeContentFn: Fn(<G as rustc_data_structures::graph::DirectedGraph>::Node) -> Vec<String>,
    EdgeLabelsFn: Fn(<G as rustc_data_structures::graph::DirectedGraph>::Node) -> Vec<String>,
> GraphvizWriter<'a, G, NodeContentFn, EdgeLabelsFn>
{
    pub fn new(
        graph: &'a G,
        graphviz_name: &str,
        node_content_fn: NodeContentFn,
        edge_labels_fn: EdgeLabelsFn,
    ) -> Self {
        Self {
            graph,
            is_subgraph: false,
            graphviz_name: graphviz_name.to_owned(),
            graph_label: None,
            node_content_fn,
            edge_labels_fn,
        }
    }

    pub fn new_subgraph(
        graph: &'a G,
        graphviz_name: &str,
        node_content_fn: NodeContentFn,
        edge_labels_fn: EdgeLabelsFn,
    ) -> Self {
        Self {
            graph,
            is_subgraph: true,
            graphviz_name: graphviz_name.to_owned(),
            graph_label: None,
            node_content_fn,
            edge_labels_fn,
        }
    }

    pub fn set_graph_label(&mut self, graph_label: &str) {
        self.graph_label = Some(graph_label.to_owned());
    }

    /// Write a graphviz DOT of the graph
    pub fn write_graphviz<'tcx, W>(&self, tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        let kind = if self.is_subgraph { "subgraph" } else { "digraph" };
        let cluster = if self.is_subgraph { "cluster_" } else { "" }; // Print border around graph
        // FIXME(richkadel): If/when migrating the MIR graphviz to this generic implementation,
        // prepend "Mir_" to the graphviz_safe_def_name(def_id)
        writeln!(w, "{} {}{} {{", kind, cluster, self.graphviz_name)?;

        // Global graph properties
        let font = format!(r#"fontname="{}""#, tcx.sess.opts.debugging_opts.graphviz_font);
        let mut graph_attrs = vec![&font[..]];
        let mut content_attrs = vec![&font[..]];

        let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
        if dark_mode {
            graph_attrs.push(r#"bgcolor="black""#);
            graph_attrs.push(r#"fontcolor="white""#);
            content_attrs.push(r#"color="white""#);
            content_attrs.push(r#"fontcolor="white""#);
        }

        writeln!(w, r#"    graph [{}];"#, graph_attrs.join(" "))?;
        let content_attrs_str = content_attrs.join(" ");
        writeln!(w, r#"    node [{}];"#, content_attrs_str)?;
        writeln!(w, r#"    edge [{}];"#, content_attrs_str)?;

        // Graph label
        if let Some(graph_label) = &self.graph_label {
            self.write_graph_label(graph_label, w)?;
        }

        // Nodes
        for node in iterate::post_order_from(self.graph, self.graph.start_node()) {
            self.write_node(node, dark_mode, w)?;
        }

        // Edges
        for source in iterate::post_order_from(self.graph, self.graph.start_node()) {
            self.write_edges(source, w)?;
        }
        writeln!(w, "}}")
    }

    /// Write a graphviz DOT node for the given node.
    pub fn write_node<W>(&self, node: G::Node, dark_mode: bool, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
        write!(w, r#"    {} [shape="none", label=<"#, self.node(node))?;

        write!(w, r#"
"#)?;

        // FIXME(richkadel): If/when migrating the MIR graphviz to this generic implementation,
        // we need generic way to know if node header should have a different color. For example,
        // for MIR:
        //
        // let (blk, bgcolor) = if data.is_cleanup {
        //     let color = if dark_mode { "royalblue" } else { "lightblue" };
        //     (format!("{:?} (cleanup)", node), color)
        // } else {
        //     let color = if dark_mode { "dimgray" } else { "gray" };
        //     (format!("{:?}", node), color)
        // };
        let color = if dark_mode { "dimgray" } else { "gray" };
        let (blk, bgcolor) = (format!("{:?}", node), color);
        write!(
            w,
            r#"
{blk}
"#,
            attrs = r#"align="center""#,
            colspan = 1,
            blk = blk,
            bgcolor = bgcolor
        )?;

        for section in (self.node_content_fn)(node) {
            write!(
                w,
                r#"
{}
"#,
                dot::escape_html(&section).replace("\n", "
")
            )?;
        }

        // Close the table
        write!(w, "
")?;

        // Close the node label and the node itself.
        writeln!(w, ">];")
    }

    /// Write graphviz DOT edges with labels between the given node and all of its successors.
    fn write_edges<W>(&self, source: G::Node, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        let edge_labels = (self.edge_labels_fn)(source);
        for (index, target) in self.graph.successors(source).enumerate() {
            let src = self.node(source);
            let trg = self.node(target);
            let escaped_edge_label = if let Some(edge_label) = edge_labels.get(index) {
                dot::escape_html(edge_label).replace("\n", r#"
"#)
            } else {
                "".to_owned()
            };
            writeln!(w, r#"    {} -> {} [label=<{}>];"#, src, trg, escaped_edge_label)?;
        }
        Ok(())
    }

    /// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
    /// will appear below the graph.
    fn write_graph_label<W>(&self, label: &str, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        let lines = label.split('\n').map(|s| dot::escape_html(s)).collect::<Vec<_>>();
        let escaped_label = lines.join(r#"
"#);
        writeln!(w, r#"    label=<

{}

>;"#, escaped_label)
    }

    fn node(&self, node: G::Node) -> String {
        format!("{:?}__{}", node, self.graphviz_name)
    }
}
<commit_msg>Rollup merge of #82212 - est31:graph_graph_graph, r=oli-obk<commit_after>use rustc_data_structures::graph::{self, iterate};
use rustc_graphviz as dot;
use rustc_middle::ty::TyCtxt;
use std::io::{self, Write};

pub struct GraphvizWriter<
    'a,
    G: graph::DirectedGraph + graph::WithSuccessors + graph::WithStartNode + graph::WithNumNodes,
    NodeContentFn: Fn(<G as graph::DirectedGraph>::Node) -> Vec<String>,
    EdgeLabelsFn: Fn(<G as graph::DirectedGraph>::Node) -> Vec<String>,
> {
    graph: &'a G,
    is_subgraph: bool,
    graphviz_name: String,
    graph_label: Option<String>,
    node_content_fn: NodeContentFn,
    edge_labels_fn: EdgeLabelsFn,
}

impl<
    'a,
    G: graph::DirectedGraph + graph::WithSuccessors + graph::WithStartNode + graph::WithNumNodes,
    NodeContentFn: Fn(<G as graph::DirectedGraph>::Node) -> Vec<String>,
    EdgeLabelsFn: Fn(<G as graph::DirectedGraph>::Node) -> Vec<String>,
> GraphvizWriter<'a, G, NodeContentFn, EdgeLabelsFn>
{
    pub fn new(
        graph: &'a G,
        graphviz_name: &str,
        node_content_fn: NodeContentFn,
        edge_labels_fn: EdgeLabelsFn,
    ) -> Self {
        Self {
            graph,
            is_subgraph: false,
            graphviz_name: graphviz_name.to_owned(),
            graph_label: None,
            node_content_fn,
            edge_labels_fn,
        }
    }

    pub fn new_subgraph(
        graph: &'a G,
        graphviz_name: &str,
        node_content_fn: NodeContentFn,
        edge_labels_fn: EdgeLabelsFn,
    ) -> Self {
        Self {
            graph,
            is_subgraph: true,
            graphviz_name: graphviz_name.to_owned(),
            graph_label: None,
            node_content_fn,
            edge_labels_fn,
        }
    }

    pub fn set_graph_label(&mut self, graph_label: &str) {
        self.graph_label = Some(graph_label.to_owned());
    }

    /// Write a graphviz DOT of the graph
    pub fn write_graphviz<'tcx, W>(&self, tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        let kind = if self.is_subgraph { "subgraph" } else { "digraph" };
        let cluster = if self.is_subgraph { "cluster_" } else { "" }; // Print border around graph
        // FIXME(richkadel): If/when migrating the MIR graphviz to this generic implementation,
        // prepend "Mir_" to the graphviz_safe_def_name(def_id)
        writeln!(w, "{} {}{} {{", kind, cluster, self.graphviz_name)?;

        // Global graph properties
        let font = format!(r#"fontname="{}""#, tcx.sess.opts.debugging_opts.graphviz_font);
        let mut graph_attrs = vec![&font[..]];
        let mut content_attrs = vec![&font[..]];

        let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
        if dark_mode {
            graph_attrs.push(r#"bgcolor="black""#);
            graph_attrs.push(r#"fontcolor="white""#);
            content_attrs.push(r#"color="white""#);
            content_attrs.push(r#"fontcolor="white""#);
        }

        writeln!(w, r#"    graph [{}];"#, graph_attrs.join(" "))?;
        let content_attrs_str = content_attrs.join(" ");
        writeln!(w, r#"    node [{}];"#, content_attrs_str)?;
        writeln!(w, r#"    edge [{}];"#, content_attrs_str)?;

        // Graph label
        if let Some(graph_label) = &self.graph_label {
            self.write_graph_label(graph_label, w)?;
        }

        // Nodes
        for node in iterate::post_order_from(self.graph, self.graph.start_node()) {
            self.write_node(node, dark_mode, w)?;
        }

        // Edges
        for source in iterate::post_order_from(self.graph, self.graph.start_node()) {
            self.write_edges(source, w)?;
        }
        writeln!(w, "}}")
    }

    /// Write a graphviz DOT node for the given node.
    pub fn write_node<W>(&self, node: G::Node, dark_mode: bool, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        // Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
        write!(w, r#"    {} [shape="none", label=<"#, self.node(node))?;

        write!(w, r#"
"#)?;

        // FIXME(richkadel): If/when migrating the MIR graphviz to this generic implementation,
        // we need generic way to know if node header should have a different color. For example,
        // for MIR:
        //
        // let (blk, bgcolor) = if data.is_cleanup {
        //     let color = if dark_mode { "royalblue" } else { "lightblue" };
        //     (format!("{:?} (cleanup)", node), color)
        // } else {
        //     let color = if dark_mode { "dimgray" } else { "gray" };
        //     (format!("{:?}", node), color)
        // };
        let color = if dark_mode { "dimgray" } else { "gray" };
        let (blk, bgcolor) = (format!("{:?}", node), color);
        write!(
            w,
            r#"
{blk}
"#,
            attrs = r#"align="center""#,
            colspan = 1,
            blk = blk,
            bgcolor = bgcolor
        )?;

        for section in (self.node_content_fn)(node) {
            write!(
                w,
                r#"
{}
"#,
                dot::escape_html(&section).replace("\n", "
")
            )?;
        }

        // Close the table
        write!(w, "
")?;

        // Close the node label and the node itself.
        writeln!(w, ">];")
    }

    /// Write graphviz DOT edges with labels between the given node and all of its successors.
    fn write_edges<W>(&self, source: G::Node, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        let edge_labels = (self.edge_labels_fn)(source);
        for (index, target) in self.graph.successors(source).enumerate() {
            let src = self.node(source);
            let trg = self.node(target);
            let escaped_edge_label = if let Some(edge_label) = edge_labels.get(index) {
                dot::escape_html(edge_label).replace("\n", r#"
"#)
            } else {
                "".to_owned()
            };
            writeln!(w, r#"    {} -> {} [label=<{}>];"#, src, trg, escaped_edge_label)?;
        }
        Ok(())
    }

    /// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
    /// will appear below the graph.
    fn write_graph_label<W>(&self, label: &str, w: &mut W) -> io::Result<()>
    where
        W: Write,
    {
        let lines = label.split('\n').map(|s| dot::escape_html(s)).collect::<Vec<_>>();
        let escaped_label = lines.join(r#"
"#);
        writeln!(w, r#"    label=<

{}

>;"#, escaped_label)
    }

    fn node(&self, node: G::Node) -> String {
        format!("{:?}__{}", node, self.graphviz_name)
    }
}
<|endoftext|>


<commit_before>extern crate native;

use std::comm;

fn main() {
    let (tx, rx): (Sender<uint>, Receiver<uint>) = comm::channel();

    for ii in range(0u, 10) {
        let task_tx = tx.clone(); // clone the Sender

        spawn(proc() {
            task_tx.send(ii);

            println!("task {} is done", ii);
        });
    }

    for _ in range(0u, 10) {
        println!("Recieved {}", rx.recv());
    }
}
<commit_msg>add some delay<commit_after>extern crate native;

use std::comm;
use std::io::timer;
use std::time::duration::Duration;

fn main() {
    let (tx, rx): (Sender<uint>, Receiver<uint>) = comm::channel();

    for ii in range(0u, 10) {
        let interval = Duration::milliseconds(ii as i64 * 20i64);
        let task_tx = tx.clone(); // clone the Sender

        spawn(proc() {
            task_tx.send(ii);
            timer::sleep(interval);
            println!("task {} is done", ii);
        });
    }

    for _ in range(0u, 10) {
        println!("Recieved {}", rx.recv());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Yusuke Sasaki
//
// This software is released under the MIT License.
// See http://opensource.org/licenses/mit-license.php or <LICENSE>.

extern crate gurobi;
use gurobi::*;

macro_rules! def_var {
  ($model:expr, $name:ident : binary) => {
    let $name = $model.add_var(stringify!($name), Binary, 0.0, 0.0, 1.0, &[], &[]).unwrap();
  };

  ($model:expr, $name:ident : integer [$lb:expr, $ub:expr]) => {
    let $name = $model.add_var(stringify!($name), Integer, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
  };

  ($model:expr, $name:ident : real [$lb:expr, $ub:expr]) => {
    let $name = $model.add_var(stringify!($name), Continuous, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
  };

  ($model:expr, $name:ident : binary, $($t:tt)*) => {
    let $name = $model.add_var(stringify!($name), Binary, 0.0, 0.0, 1.0, &[], &[]).unwrap();
    def_var!($model, $($t)*);
  };

  ($model:expr, $name:ident : integer [$lb:expr, $ub:expr], $($t:tt)*) => {
    let $name = $model.add_var(stringify!($name), Integer, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
    def_var!($model, $($t)*);
  };

  ($model:expr, $name:ident : real [$lb:expr, $ub:expr], $($t:tt)*) => {
    let $name = $model.add_var(stringify!($name), Continuous, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
    def_var!($model, $($t)*);
  };
}

macro_rules! add_constr {
  { $model:expr, $name:ident : $lhs:tt <= $rhs:tt } => {
    $model.add_constr(stringify!($name), $lhs, Less, ($rhs).into()).unwrap();
  };

  { $model:expr, $name:ident : $lhs:tt == $rhs:tt } => {
    $model.add_constr(stringify!($name), $lhs, Equal, ($rhs).into()).unwrap();
  };

  { $model:expr, $name:ident : $lhs:tt >= $rhs:tt } => {
    $model.add_constr(stringify!($name), $lhs, Greater, ($rhs).into()).unwrap();
  };

  ($model:expr, $name:ident : $lhs:tt <= $rhs:tt, $($s:tt)*) => {
    $model.add_constr(stringify!($name), $lhs, Less, ($rhs).into()).unwrap();
    add_constr!($model, $($s)*);
  };

  ($model:expr, $name:ident : $lhs:tt == $rhs:tt, $($s:tt)*) => {
    $model.add_constr(stringify!($name), $lhs, Equal, ($rhs).into()).unwrap();
    add_constr!($model, $($s)*);
  };

  ($model:expr, $name:ident : $lhs:tt >= $rhs:tt, $($s:tt)*) => {
    $model.add_constr(stringify!($name), $lhs, Greater, ($rhs).into()).unwrap();
    add_constr!($model, $($s)*);
  };
}

macro_rules! def_model {
  { env:  $env:ident,
    name: $name:expr,
    vars: { $($t:tt)* },
    objective: { $($o:tt)* },
    constrs: { $($c:tt)* }
  } => { {
    let mut model = Model::new($name, &$env).unwrap();

    def_var!(model, $($t)*);
    model.update().unwrap();

    add_constr!(model, $($c)*);
    model.update().unwrap();

    model.set_objective($($o)*).unwrap();
    model.update().unwrap();

    model
  } }
}

fn main() {
  let env = Env::new("mip_build.log").unwrap();

  let model = def_model! {
    env: env,
    name: "mip_build",
    vars: {
      x: binary,
      y: binary,
      z: binary,
      s: integer[0, 2],
      t: real[0,10]
    },
    objective: { &x + &y + 2.0 * &z, Maximize },
    constrs: {
      c0: (&x + 2.0 * &y + 3.0 * &z) <= 4,
      c1: (&x + &y) <= 1,
      c2: (1.0 * &s) == 0,
      c3: (1.0 * &t) == 0
    }
  };

  model.write("mip.lp").unwrap();
}
<commit_msg>update<commit_after>// Copyright (c) 2016 Yusuke Sasaki
//
// This software is released under the MIT License.
// See http://opensource.org/licenses/mit-license.php or <LICENSE>.

extern crate gurobi;
use gurobi::*;

macro_rules! def_var {
  ($model:expr, $name:ident : binary) => {
    let $name = $model.add_var(stringify!($name), Binary, 0.0, 0.0, 1.0, &[], &[]).unwrap();
  };

  ($model:expr, $name:ident : integer [$lb:expr, $ub:expr]) => {
    let $name = $model.add_var(stringify!($name), Integer, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
  };

  ($model:expr, $name:ident : real [$lb:expr, $ub:expr]) => {
    let $name = $model.add_var(stringify!($name), Continuous, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
  };

  ($model:expr, $name:ident : binary, $($t:tt)*) => {
    let $name = $model.add_var(stringify!($name), Binary, 0.0, 0.0, 1.0, &[], &[]).unwrap();
    def_var!($model, $($t)*);
  };

  ($model:expr, $name:ident : integer [$lb:expr, $ub:expr], $($t:tt)*) => {
    let $name = $model.add_var(stringify!($name), Integer, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
    def_var!($model, $($t)*);
  };

  ($model:expr, $name:ident : real [$lb:expr, $ub:expr], $($t:tt)*) => {
    let $name = $model.add_var(stringify!($name), Continuous, 0.0, ($lb).into(), ($ub).into(), &[], &[]).unwrap();
    def_var!($model, $($t)*);
  };
}

macro_rules! add_constr {
  { $model:expr, $name:ident : $lhs:tt <= $rhs:tt } => {
    $model.add_constr(stringify!($name), $lhs, Less, ($rhs).into()).unwrap();
  };

  { $model:expr, $name:ident : $lhs:tt == $rhs:tt } => {
    $model.add_constr(stringify!($name), $lhs, Equal, ($rhs).into()).unwrap();
  };

  { $model:expr, $name:ident : $lhs:tt >= $rhs:tt } => {
    $model.add_constr(stringify!($name), $lhs, Greater, ($rhs).into()).unwrap();
  };

  ($model:expr, $name:ident : $lhs:tt <= $rhs:tt, $($s:tt)*) => {
    $model.add_constr(stringify!($name), $lhs, Less, ($rhs).into()).unwrap();
    add_constr!($model, $($s)*);
  };

  ($model:expr, $name:ident : $lhs:tt == $rhs:tt, $($s:tt)*) => {
    $model.add_constr(stringify!($name), $lhs, Equal, ($rhs).into()).unwrap();
    add_constr!($model, $($s)*);
  };

  ($model:expr, $name:ident : $lhs:tt >= $rhs:tt, $($s:tt)*) => {
    $model.add_constr(stringify!($name), $lhs, Greater, ($rhs).into()).unwrap();
    add_constr!($model, $($s)*);
  };
}

macro_rules! set_objective {
  ($model:expr, expr: ($($t:tt)*), sense: $sense:ident) => {
    $model.set_objective($($t)*, $sense).unwrap();
  }
}

macro_rules! def_model {
  { env:  $env:ident,
    name: $name:expr,
    vars: { $($t:tt)* },
    objective: { $($o:tt)* },
    constrs: { $($c:tt)* }
  } => { {
    let mut model = Model::new($name, &$env).unwrap();

    def_var!(model, $($t)*);
    model.update().unwrap();

    add_constr!(model, $($c)*);
    model.update().unwrap();

    set_objective!(model, $($o)*);
    model.update().unwrap();

    model
  } }
}

fn main() {
  let env = Env::new("mip_build.log").unwrap();

  let model = def_model! {
    env: env,
    name: "mip_build",
    vars: {
      x: binary,
      y: binary,
      z: binary,
      s: integer[0, 2],
      t: real[0,10]
    },
    objective: {
      expr: (&x + &y + 2.0 * &z),
      sense: Maximize
    },
    constrs: {
      c0: (&x + 2.0 * &y + 3.0 * &z) <= 4,
      c1: (&x + &y) <= 1,
      c2: (1.0 * &s) == 0,
      c3: (1.0 * &t) == 0
    }
  };

  model.write("mip.lp").unwrap();
}
<|endoftext|>


<commit_before>// Build mcuboot as a library, based on the requested features.

extern crate cc;

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

fn main() {
    // Feature flags.
    let sig_rsa = env::var("CARGO_FEATURE_SIG_RSA").is_ok();
    let sig_rsa3072 = env::var("CARGO_FEATURE_SIG_RSA3072").is_ok();
    let sig_ecdsa = env::var("CARGO_FEATURE_SIG_ECDSA").is_ok();
    let sig_ed25519 = env::var("CARGO_FEATURE_SIG_ED25519").is_ok();
    let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
    let swap_move = env::var("CARGO_FEATURE_SWAP_MOVE").is_ok();
    let validate_primary_slot =
                  env::var("CARGO_FEATURE_VALIDATE_PRIMARY_SLOT").is_ok();
    let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
    let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();
    let enc_ec256 = env::var("CARGO_FEATURE_ENC_EC256").is_ok();
    let bootstrap = env::var("CARGO_FEATURE_BOOTSTRAP").is_ok();
    let multiimage = env::var("CARGO_FEATURE_MULTIIMAGE").is_ok();
    let downgrade_prevention = env::var("CARGO_FEATURE_DOWNGRADE_PREVENTION").is_ok();

    let mut conf = cc::Build::new();
    conf.define("__BOOTSIM__", None);
    conf.define("MCUBOOT_HAVE_LOGGING", None);
    conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
    conf.define("MCUBOOT_HAVE_ASSERT_H", None);
    conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
    conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));

    if downgrade_prevention && !overwrite_only {
        panic!("Downgrade prevention requires overwrite only");
    }

    if bootstrap {
        conf.define("MCUBOOT_BOOTSTRAP", None);
    }

    if validate_primary_slot {
        conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
    }

    if downgrade_prevention {
        conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
    }

    // Currently no more than one sig type can be used simultaneously.
    if vec![sig_rsa, sig_rsa3072, sig_ecdsa, sig_ed25519].iter()
        .fold(0, |sum, &v| sum + v as i32) > 1 {
        panic!("mcuboot does not support more than one sig type at the same time");
    }

    if sig_rsa || sig_rsa3072 {
        conf.define("MCUBOOT_SIGN_RSA", None);
        // The Kconfig style defines must be added here as well because
        // they are used internally by "config-rsa.h"
        if sig_rsa {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
        } else {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
        }
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.include("../../ext/mbedtls/include");
        conf.file("../../ext/mbedtls/library/sha256.c");
        conf.file("csupport/keys.c");

        conf.file("../../ext/mbedtls/library/rsa.c");
        conf.file("../../ext/mbedtls/library/bignum.c");
        conf.file("../../ext/mbedtls/library/platform.c");
        conf.file("../../ext/mbedtls/library/platform_util.c");
        conf.file("../../ext/mbedtls/library/asn1parse.c");
    } else if sig_ecdsa {
        conf.define("MCUBOOT_SIGN_EC256", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        if !enc_kw {
            conf.include("../../ext/mbedtls-asn1/include");
        }
        conf.include("../../ext/tinycrypt/lib/include");

        conf.file("csupport/keys.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if sig_ed25519 {
        conf.define("MCUBOOT_SIGN_ED25519", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        conf.include("../../ext/tinycrypt/lib/include");
        conf.include("../../ext/tinycrypt-sha512/lib/include");
        conf.include("../../ext/mbedtls-asn1/include");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt-sha512/lib/source/sha512.c");
        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("csupport/keys.c");
        conf.file("../../ext/fiat/src/curve25519.c");
        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if !enc_ec256 {
        // No signature type, only sha256 validation. The default
        // configuration file bundled with mbedTLS is sufficient.
        // When using ECIES-P256 rely on Tinycrypt.
        conf.define("MCUBOOT_USE_MBED_TLS", None);
        conf.include("../../ext/mbedtls/include");
        conf.file("../../ext/mbedtls/library/sha256.c");
    }

    if overwrite_only {
        conf.define("MCUBOOT_OVERWRITE_ONLY", None);
        conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
    }

    if swap_move {
        conf.define("MCUBOOT_SWAP_USING_MOVE", None);
    }

    if enc_rsa {
        conf.define("MCUBOOT_ENCRYPT_RSA", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls/include");
        conf.file("../../ext/mbedtls/library/sha256.c");

        conf.file("../../ext/mbedtls/library/platform.c");
        conf.file("../../ext/mbedtls/library/platform_util.c");
        conf.file("../../ext/mbedtls/library/rsa.c");
        conf.file("../../ext/mbedtls/library/rsa_internal.c");
        conf.file("../../ext/mbedtls/library/md.c");
        conf.file("../../ext/mbedtls/library/md_wrap.c");
        conf.file("../../ext/mbedtls/library/aes.c");
        conf.file("../../ext/mbedtls/library/bignum.c");
        conf.file("../../ext/mbedtls/library/asn1parse.c");
    }

    if enc_kw {
        conf.define("MCUBOOT_ENCRYPT_KW", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        if sig_rsa || sig_rsa3072 {
            conf.file("../../ext/mbedtls/library/sha256.c");
        }

        /* Simulator uses Mbed-TLS to wrap keys */
        conf.include("../../ext/mbedtls/include");
        conf.file("../../ext/mbedtls/library/platform.c");
        conf.file("../../ext/mbedtls/library/platform_util.c");
        conf.file("../../ext/mbedtls/library/nist_kw.c");
        conf.file("../../ext/mbedtls/library/cipher.c");
        conf.file("../../ext/mbedtls/library/cipher_wrap.c");
        conf.file("../../ext/mbedtls/library/aes.c");

        if sig_ecdsa {
            conf.define("MCUBOOT_USE_TINYCRYPT", None);

            conf.include("../../ext/tinycrypt/lib/include");

            conf.file("../../ext/tinycrypt/lib/source/utils.c");
            conf.file("../../ext/tinycrypt/lib/source/sha256.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        }

        if sig_ed25519 {
            panic!("ed25519 does not support image encryption with KW yet");
        }
    }

    if enc_ec256 {
        conf.define("MCUBOOT_ENCRYPT_EC256", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);
        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls-asn1/include");
        conf.include("../../ext/tinycrypt/lib/include");

        /* FIXME: fail with other signature schemes ? */

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");

        conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        conf.file("../../ext/tinycrypt/lib/source/hmac.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dh.c");
    }

    if sig_rsa && enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
    } else if sig_rsa || sig_rsa3072 || enc_rsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
    } else if (sig_ecdsa || enc_ec256) && !enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if sig_ed25519 {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
    }

    conf.file("../../boot/bootutil/src/image_validate.c");
    if sig_rsa || sig_rsa3072 {
        conf.file("../../boot/bootutil/src/image_rsa.c");
    } else if sig_ecdsa {
        conf.file("../../boot/bootutil/src/image_ec256.c");
    } else if sig_ed25519 {
        conf.file("../../boot/bootutil/src/image_ed25519.c");
    }
    conf.file("../../boot/bootutil/src/loader.c");
    conf.file("../../boot/bootutil/src/swap_misc.c");
    conf.file("../../boot/bootutil/src/swap_scratch.c");
    conf.file("../../boot/bootutil/src/swap_move.c");
    conf.file("../../boot/bootutil/src/caps.c");
    conf.file("../../boot/bootutil/src/bootutil_misc.c");
    conf.file("../../boot/bootutil/src/tlv.c");
    conf.file("csupport/run.c");
    conf.include("../../boot/bootutil/include");
    conf.include("csupport");
    conf.include("../../boot/zephyr/include");
    conf.debug(true);
    conf.flag("-Wall");
    conf.flag("-Werror");

    // FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
    // It has incomplete std=c11 and std=c99 support but std=c99 was checked
    // to build correctly so leaving it here to updated in the future...
    conf.flag("-std=c99");

    conf.compile("libbootutil.a");

    walk_dir("../../boot").unwrap();
    walk_dir("../../ext/tinycrypt/lib/source").unwrap();
    walk_dir("../../ext/mbedtls-asn1").unwrap();
    walk_dir("csupport").unwrap();
    walk_dir("../../ext/mbedtls/include").unwrap();
    walk_dir("../../ext/mbedtls/library").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<commit_msg>sim: fix paths for mbed-cryto<commit_after>// Build mcuboot as a library, based on the requested features.

extern crate cc;

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

fn main() {
    // Feature flags.
    let sig_rsa = env::var("CARGO_FEATURE_SIG_RSA").is_ok();
    let sig_rsa3072 = env::var("CARGO_FEATURE_SIG_RSA3072").is_ok();
    let sig_ecdsa = env::var("CARGO_FEATURE_SIG_ECDSA").is_ok();
    let sig_ed25519 = env::var("CARGO_FEATURE_SIG_ED25519").is_ok();
    let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
    let swap_move = env::var("CARGO_FEATURE_SWAP_MOVE").is_ok();
    let validate_primary_slot =
                  env::var("CARGO_FEATURE_VALIDATE_PRIMARY_SLOT").is_ok();
    let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
    let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();
    let enc_ec256 = env::var("CARGO_FEATURE_ENC_EC256").is_ok();
    let bootstrap = env::var("CARGO_FEATURE_BOOTSTRAP").is_ok();
    let multiimage = env::var("CARGO_FEATURE_MULTIIMAGE").is_ok();
    let downgrade_prevention = env::var("CARGO_FEATURE_DOWNGRADE_PREVENTION").is_ok();

    let mut conf = cc::Build::new();
    conf.define("__BOOTSIM__", None);
    conf.define("MCUBOOT_HAVE_LOGGING", None);
    conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
    conf.define("MCUBOOT_HAVE_ASSERT_H", None);
    conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
    conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));

    if downgrade_prevention && !overwrite_only {
        panic!("Downgrade prevention requires overwrite only");
    }

    if bootstrap {
        conf.define("MCUBOOT_BOOTSTRAP", None);
    }

    if validate_primary_slot {
        conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
    }

    if downgrade_prevention {
        conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
    }

    // Currently no more than one sig type can be used simultaneously.
    if vec![sig_rsa, sig_rsa3072, sig_ecdsa, sig_ed25519].iter()
        .fold(0, |sum, &v| sum + v as i32) > 1 {
        panic!("mcuboot does not support more than one sig type at the same time");
    }

    if sig_rsa || sig_rsa3072 {
        conf.define("MCUBOOT_SIGN_RSA", None);
        // The Kconfig style defines must be added here as well because
        // they are used internally by "config-rsa.h"
        if sig_rsa {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
        } else {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
        }
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
        conf.file("csupport/keys.c");

        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
    } else if sig_ecdsa {
        conf.define("MCUBOOT_SIGN_EC256", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        if !enc_kw {
            conf.include("../../ext/mbedtls-asn1/include");
        }
        conf.include("../../ext/tinycrypt/lib/include");

        conf.file("csupport/keys.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if sig_ed25519 {
        conf.define("MCUBOOT_SIGN_ED25519", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        conf.include("../../ext/tinycrypt/lib/include");
        conf.include("../../ext/tinycrypt-sha512/lib/include");
        conf.include("../../ext/mbedtls-asn1/include");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt-sha512/lib/source/sha512.c");
        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("csupport/keys.c");
        conf.file("../../ext/fiat/src/curve25519.c");
        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if !enc_ec256 {
        // No signature type, only sha256 validation. The default
        // configuration file bundled with mbedTLS is sufficient.
        // When using ECIES-P256 rely on Tinycrypt.
        conf.define("MCUBOOT_USE_MBED_TLS", None);
        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
    }

    if overwrite_only {
        conf.define("MCUBOOT_OVERWRITE_ONLY", None);
        conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
    }

    if swap_move {
        conf.define("MCUBOOT_SWAP_USING_MOVE", None);
    }

    if enc_rsa {
        conf.define("MCUBOOT_ENCRYPT_RSA", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");

        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
        conf.file("../../ext/mbedtls/crypto/library/rsa_internal.c");
        conf.file("../../ext/mbedtls/crypto/library/md.c");
        conf.file("../../ext/mbedtls/crypto/library/aes.c");
        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
    }

    if enc_kw {
        conf.define("MCUBOOT_ENCRYPT_KW", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        if sig_rsa || sig_rsa3072 {
            conf.file("../../ext/mbedtls/crypto/library/sha256.c");
        }

        /* Simulator uses Mbed-TLS to wrap keys */
        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/nist_kw.c");
        conf.file("../../ext/mbedtls/crypto/library/cipher.c");
        conf.file("../../ext/mbedtls/crypto/library/cipher_wrap.c");
        conf.file("../../ext/mbedtls/crypto/library/aes.c");

        if sig_ecdsa {
            conf.define("MCUBOOT_USE_TINYCRYPT", None);

            conf.include("../../ext/tinycrypt/lib/include");

            conf.file("../../ext/tinycrypt/lib/source/utils.c");
            conf.file("../../ext/tinycrypt/lib/source/sha256.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        }

        if sig_ed25519 {
            panic!("ed25519 does not support image encryption with KW yet");
        }
    }

    if enc_ec256 {
        conf.define("MCUBOOT_ENCRYPT_EC256", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);
        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls-asn1/include");
        conf.include("../../ext/tinycrypt/lib/include");

        /* FIXME: fail with other signature schemes ? */

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");

        conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        conf.file("../../ext/tinycrypt/lib/source/hmac.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dh.c");
    }

    if sig_rsa && enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
    } else if sig_rsa || sig_rsa3072 || enc_rsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
    } else if (sig_ecdsa || enc_ec256) && !enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if sig_ed25519 {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
    }

    conf.file("../../boot/bootutil/src/image_validate.c");
    if sig_rsa || sig_rsa3072 {
        conf.file("../../boot/bootutil/src/image_rsa.c");
    } else if sig_ecdsa {
        conf.file("../../boot/bootutil/src/image_ec256.c");
    } else if sig_ed25519 {
        conf.file("../../boot/bootutil/src/image_ed25519.c");
    }
    conf.file("../../boot/bootutil/src/loader.c");
    conf.file("../../boot/bootutil/src/swap_misc.c");
    conf.file("../../boot/bootutil/src/swap_scratch.c");
    conf.file("../../boot/bootutil/src/swap_move.c");
    conf.file("../../boot/bootutil/src/caps.c");
    conf.file("../../boot/bootutil/src/bootutil_misc.c");
    conf.file("../../boot/bootutil/src/tlv.c");
    conf.file("csupport/run.c");
    conf.include("../../boot/bootutil/include");
    conf.include("csupport");
    conf.include("../../boot/zephyr/include");
    conf.debug(true);
    conf.flag("-Wall");
    conf.flag("-Werror");

    // FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
    // It has incomplete std=c11 and std=c99 support but std=c99 was checked
    // to build correctly so leaving it here to updated in the future...
    conf.flag("-std=c99");

    conf.compile("libbootutil.a");

    walk_dir("../../boot").unwrap();
    walk_dir("../../ext/tinycrypt/lib/source").unwrap();
    walk_dir("../../ext/mbedtls-asn1").unwrap();
    walk_dir("csupport").unwrap();
    walk_dir("../../ext/mbedtls/crypto/include").unwrap();
    walk_dir("../../ext/mbedtls/crypto/library").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<|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 back::link::exported_name;
use driver::session;
use lib::llvm::ValueRef;
use middle::subst;
use middle::subst::Subst;
use middle::trans::base::{set_llvm_fn_attrs, set_inline_hint};
use middle::trans::base::{trans_enum_variant, push_ctxt, get_item_val};
use middle::trans::base::{trans_fn, decl_internal_rust_fn};
use middle::trans::base;
use middle::trans::common::*;
use middle::trans::intrinsic;
use middle::ty;
use middle::typeck;
use util::ppaux::Repr;

use syntax::abi;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::local_def;
use std::hash::{sip, Hash};

pub fn monomorphic_fn(ccx: &CrateContext,
                      fn_id: ast::DefId,
                      real_substs: &subst::Substs,
                      vtables: Option<typeck::vtable_res>,
                      self_vtables: Option<typeck::vtable_param_res>,
                      ref_id: Option<ast::NodeId>)
    -> (ValueRef, bool) {
    debug!("monomorphic_fn(\
            fn_id={}, \
            real_substs={}, \
            vtables={}, \
            self_vtable={}, \
            ref_id={:?})",
           fn_id.repr(ccx.tcx()),
           real_substs.repr(ccx.tcx()),
           vtables.repr(ccx.tcx()),
           self_vtables.repr(ccx.tcx()),
           ref_id);

    assert!(real_substs.tps.iter().all(|t| {
        !ty::type_needs_infer(*t) && !ty::type_has_params(*t)
    }));

    let _icx = push_ctxt("monomorphic_fn");

    let substs_iter = real_substs.self_ty.iter().chain(real_substs.tps.iter());
    let param_ids: Vec<MonoParamId> = match vtables {
        Some(ref vts) => {
            debug!("make_mono_id vtables={} psubsts={}",
                   vts.repr(ccx.tcx()), real_substs.tps.repr(ccx.tcx()));
            let vts_iter = self_vtables.iter().chain(vts.iter());
            vts_iter.zip(substs_iter).map(|(vtable, subst)| MonoParamId {
                subst: *subst,
                // Do we really need the vtables to be hashed? Isn't the type enough?
                vtables: vtable.iter().map(|vt| make_vtable_id(ccx, vt)).collect()
            }).collect()
        }
        None => substs_iter.map(|subst| MonoParamId {
            subst: *subst,
            vtables: Vec::new()
        }).collect()
    };

    let hash_id = MonoId {
        def: fn_id,
        params: param_ids
    };

    match ccx.monomorphized.borrow().find(&hash_id) {
        Some(&val) => {
            debug!("leaving monomorphic fn {}",
            ty::item_path_str(ccx.tcx(), fn_id));
            return (val, false);
        }
        None => ()
    }

    let psubsts = param_substs {
        substs: (*real_substs).clone(),
        vtables: vtables,
        self_vtables: self_vtables
    };

    debug!("monomorphic_fn(\
            fn_id={}, \
            psubsts={}, \
            hash_id={:?})",
           fn_id.repr(ccx.tcx()),
           psubsts.repr(ccx.tcx()),
           hash_id);

    let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
    let llitem_ty = tpt.ty;

    // We need to do special handling of the substitutions if we are
    // calling a static provided method. This is sort of unfortunate.
    let mut is_static_provided = None;

    let map_node = session::expect(
        ccx.sess(),
        ccx.tcx.map.find(fn_id.node),
        || {
            format!("while monomorphizing {:?}, couldn't find it in \
                     the item map (may have attempted to monomorphize \
                     an item defined in a different crate?)",
                    fn_id)
        });

    match map_node {
        ast_map::NodeForeignItem(_) => {
            if ccx.tcx.map.get_foreign_abi(fn_id.node) != abi::RustIntrinsic {
                // Foreign externs don't have to be monomorphized.
                return (get_item_val(ccx, fn_id.node), true);
            }
        }
        ast_map::NodeTraitMethod(method) => {
            match *method {
                ast::Provided(m) => {
                    // If this is a static provided method, indicate that
                    // and stash the number of params on the method.
                    if m.explicit_self.node == ast::SelfStatic {
                        is_static_provided = Some(m.generics.ty_params.len());
                    }
                }
                _ => {}
            }
        }
        _ => {}
    }

    debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
    let mono_ty = match is_static_provided {
        None => llitem_ty.subst(ccx.tcx(), real_substs),
        Some(num_method_ty_params) => {
            // Static default methods are a little unfortunate, in
            // that the "internal" and "external" type of them differ.
            // Internally, the method body can refer to Self, but the
            // externally visible type of the method has a type param
            // inserted in between the trait type params and the
            // method type params. The substs that we are given are
            // the proper substs *internally* to the method body, so
            // we have to use those when compiling it.
            //
            // In order to get the proper substitution to use on the
            // type of the method, we pull apart the substitution and
            // stick a substitution for the self type in.
            // This is a bit unfortunate.

            let idx = real_substs.tps.len() - num_method_ty_params;
            let mut tps = Vec::new();
            tps.push_all(real_substs.tps.slice(0, idx));
            tps.push(real_substs.self_ty.unwrap());
            tps.push_all(real_substs.tps.tailn(idx));

            let substs = subst::Substs { regions: subst::ErasedRegions,
                                         self_ty: None,
                                         tps: tps };

            debug!("static default: changed substitution to {}",
                   substs.repr(ccx.tcx()));

            llitem_ty.subst(ccx.tcx(), &substs)
        }
    };

    ccx.stats.n_monos.set(ccx.stats.n_monos.get() + 1);

    let depth;
    {
        let mut monomorphizing = ccx.monomorphizing.borrow_mut();
        depth = match monomorphizing.find(&fn_id) {
            Some(&d) => d, None => 0
        };

        // Random cut-off -- code that needs to instantiate the same function
        // recursively more than thirty times can probably safely be assumed
        // to be causing an infinite expansion.
        if depth > ccx.sess().recursion_limit.get() {
            ccx.sess().span_fatal(ccx.tcx.map.span(fn_id.node),
                "reached the recursion limit during monomorphization");
        }

        monomorphizing.insert(fn_id, depth + 1);
    }

    let s = ccx.tcx.map.with_path(fn_id.node, |path| {
        let mut state = sip::SipState::new();
        hash_id.hash(&mut state);
        mono_ty.hash(&mut state);

        exported_name(path,
                      format!("h{}", state.result()).as_slice(),
                      ccx.link_meta.crateid.version_or_default())
    });
    debug!("monomorphize_fn mangled to {}", s);

    // This shouldn't need to option dance.
    let mut hash_id = Some(hash_id);
    let mk_lldecl = || {
        let lldecl = decl_internal_rust_fn(ccx, mono_ty, s.as_slice());
        ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl);
        lldecl
    };

    let lldecl = match map_node {
        ast_map::NodeItem(i) => {
            match *i {
              ast::Item {
                  node: ast::ItemFn(decl, _, _, _, body),
                  ..
              } => {
                  let d = mk_lldecl();
                  set_llvm_fn_attrs(i.attrs.as_slice(), d);
                  trans_fn(ccx, decl, body, d, Some(&psubsts), fn_id.node, []);
                  d
              }
              _ => {
                ccx.sess().bug("Can't monomorphize this kind of item")
              }
            }
        }
        ast_map::NodeForeignItem(i) => {
            let simple = intrinsic::get_simple_intrinsic(ccx, i);
            match simple {
                Some(decl) => decl,
                None => {
                    let d = mk_lldecl();
                    intrinsic::trans_intrinsic(ccx, d, i, &psubsts, ref_id);
                    d
                }
            }
        }
        ast_map::NodeVariant(v) => {
            let parent = ccx.tcx.map.get_parent(fn_id.node);
            let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
            let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
            let d = mk_lldecl();
            set_inline_hint(d);
            match v.node.kind {
                ast::TupleVariantKind(ref args) => {
                    trans_enum_variant(ccx,
                                       parent,
                                       v,
                                       args.as_slice(),
                                       this_tv.disr_val,
                                       Some(&psubsts),
                                       d);
                }
                ast::StructVariantKind(_) =>
                    ccx.sess().bug("can't monomorphize struct variants"),
            }
            d
        }
        ast_map::NodeMethod(mth) => {
            let d = mk_lldecl();
            set_llvm_fn_attrs(mth.attrs.as_slice(), d);
            trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
            d
        }
        ast_map::NodeTraitMethod(method) => {
            match *method {
                ast::Provided(mth) => {
                    let d = mk_lldecl();
                    set_llvm_fn_attrs(mth.attrs.as_slice(), d);
                    trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
                    d
                }
                _ => {
                    ccx.sess().bug(format!("can't monomorphize a {:?}",
                                           map_node).as_slice())
                }
            }
        }
        ast_map::NodeStructCtor(struct_def) => {
            let d = mk_lldecl();
            set_inline_hint(d);
            base::trans_tuple_struct(ccx,
                                     struct_def.fields.as_slice(),
                                     struct_def.ctor_id.expect("ast-mapped tuple struct \
                                                                didn't have a ctor id"),
                                     Some(&psubsts),
                                     d);
            d
        }

        // Ugh -- but this ensures any new variants won't be forgotten
        ast_map::NodeLifetime(..) |
        ast_map::NodeExpr(..) |
        ast_map::NodeStmt(..) |
        ast_map::NodeArg(..) |
        ast_map::NodeBlock(..) |
        ast_map::NodePat(..) |
        ast_map::NodeLocal(..) => {
            ccx.sess().bug(format!("can't monomorphize a {:?}",
                                   map_node).as_slice())
        }
    };

    ccx.monomorphizing.borrow_mut().insert(fn_id, depth);

    debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
    (lldecl, false)
}

// Used to identify cached monomorphized functions and vtables
#[deriving(PartialEq, Eq, Hash)]
pub struct MonoParamId {
    pub subst: ty::t,
    // Do we really need the vtables to be hashed? Isn't the type enough?
    pub vtables: Vec<MonoId>
}

#[deriving(PartialEq, Eq, Hash)]
pub struct MonoId {
    pub def: ast::DefId,
    pub params: Vec<MonoParamId>
}

pub fn make_vtable_id(ccx: &CrateContext,
                      origin: &typeck::vtable_origin)
                      -> MonoId {
    match origin {
        &typeck::vtable_static(impl_id, ref substs, ref sub_vtables) => {
            MonoId {
                def: impl_id,
                // FIXME(NDM) -- this is pretty bogus. It ignores self-type,
                // and vtables are not necessary, AND they are not guaranteed
                // to be same length as the number of TPS ANYHOW!
                params: sub_vtables.iter().zip(substs.tps.iter()).map(|(vtable, subst)| {
                    MonoParamId {
                        subst: *subst,
                        // Do we really need the vtables to be hashed? Isn't the type enough?
                        vtables: vtable.iter().map(|vt| make_vtable_id(ccx, vt)).collect()
                    }
                }).collect()
            }
        }

        // can't this be checked at the callee?
        _ => fail!("make_vtable_id needs vtable_static")
    }
}
<commit_msg>Simplify MonoId not to include parameters which, given coherence, are purely derived<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 back::link::exported_name;
use driver::session;
use lib::llvm::ValueRef;
use middle::subst;
use middle::subst::Subst;
use middle::trans::base::{set_llvm_fn_attrs, set_inline_hint};
use middle::trans::base::{trans_enum_variant, push_ctxt, get_item_val};
use middle::trans::base::{trans_fn, decl_internal_rust_fn};
use middle::trans::base;
use middle::trans::common::*;
use middle::trans::intrinsic;
use middle::ty;
use middle::typeck;
use util::ppaux::Repr;

use syntax::abi;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::local_def;
use std::hash::{sip, Hash};

pub fn monomorphic_fn(ccx: &CrateContext,
                      fn_id: ast::DefId,
                      real_substs: &subst::Substs,
                      vtables: Option<typeck::vtable_res>,
                      self_vtables: Option<typeck::vtable_param_res>,
                      ref_id: Option<ast::NodeId>)
    -> (ValueRef, bool) {
    debug!("monomorphic_fn(\
            fn_id={}, \
            real_substs={}, \
            vtables={}, \
            self_vtable={}, \
            ref_id={:?})",
           fn_id.repr(ccx.tcx()),
           real_substs.repr(ccx.tcx()),
           vtables.repr(ccx.tcx()),
           self_vtables.repr(ccx.tcx()),
           ref_id);

    assert!(real_substs.tps.iter().all(|t| {
        !ty::type_needs_infer(*t) && !ty::type_has_params(*t)
    }));

    let _icx = push_ctxt("monomorphic_fn");

    let substs_iter = real_substs.self_ty.iter().chain(real_substs.tps.iter());
    let param_ids: Vec<ty::t> = substs_iter.map(|t| *t).collect();
    let hash_id = MonoId {
        def: fn_id,
        params: param_ids
    };

    match ccx.monomorphized.borrow().find(&hash_id) {
        Some(&val) => {
            debug!("leaving monomorphic fn {}",
            ty::item_path_str(ccx.tcx(), fn_id));
            return (val, false);
        }
        None => ()
    }

    let psubsts = param_substs {
        substs: (*real_substs).clone(),
        vtables: vtables,
        self_vtables: self_vtables
    };

    debug!("monomorphic_fn(\
            fn_id={}, \
            psubsts={}, \
            hash_id={:?})",
           fn_id.repr(ccx.tcx()),
           psubsts.repr(ccx.tcx()),
           hash_id);

    let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
    let llitem_ty = tpt.ty;

    // We need to do special handling of the substitutions if we are
    // calling a static provided method. This is sort of unfortunate.
    let mut is_static_provided = None;

    let map_node = session::expect(
        ccx.sess(),
        ccx.tcx.map.find(fn_id.node),
        || {
            format!("while monomorphizing {:?}, couldn't find it in \
                     the item map (may have attempted to monomorphize \
                     an item defined in a different crate?)",
                    fn_id)
        });

    match map_node {
        ast_map::NodeForeignItem(_) => {
            if ccx.tcx.map.get_foreign_abi(fn_id.node) != abi::RustIntrinsic {
                // Foreign externs don't have to be monomorphized.
                return (get_item_val(ccx, fn_id.node), true);
            }
        }
        ast_map::NodeTraitMethod(method) => {
            match *method {
                ast::Provided(m) => {
                    // If this is a static provided method, indicate that
                    // and stash the number of params on the method.
                    if m.explicit_self.node == ast::SelfStatic {
                        is_static_provided = Some(m.generics.ty_params.len());
                    }
                }
                _ => {}
            }
        }
        _ => {}
    }

    debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
    let mono_ty = match is_static_provided {
        None => llitem_ty.subst(ccx.tcx(), real_substs),
        Some(num_method_ty_params) => {
            // Static default methods are a little unfortunate, in
            // that the "internal" and "external" type of them differ.
            // Internally, the method body can refer to Self, but the
            // externally visible type of the method has a type param
            // inserted in between the trait type params and the
            // method type params. The substs that we are given are
            // the proper substs *internally* to the method body, so
            // we have to use those when compiling it.
            //
            // In order to get the proper substitution to use on the
            // type of the method, we pull apart the substitution and
            // stick a substitution for the self type in.
            // This is a bit unfortunate.

            let idx = real_substs.tps.len() - num_method_ty_params;
            let mut tps = Vec::new();
            tps.push_all(real_substs.tps.slice(0, idx));
            tps.push(real_substs.self_ty.unwrap());
            tps.push_all(real_substs.tps.tailn(idx));

            let substs = subst::Substs { regions: subst::ErasedRegions,
                                         self_ty: None,
                                         tps: tps };

            debug!("static default: changed substitution to {}",
                   substs.repr(ccx.tcx()));

            llitem_ty.subst(ccx.tcx(), &substs)
        }
    };

    ccx.stats.n_monos.set(ccx.stats.n_monos.get() + 1);

    let depth;
    {
        let mut monomorphizing = ccx.monomorphizing.borrow_mut();
        depth = match monomorphizing.find(&fn_id) {
            Some(&d) => d, None => 0
        };

        // Random cut-off -- code that needs to instantiate the same function
        // recursively more than thirty times can probably safely be assumed
        // to be causing an infinite expansion.
        if depth > ccx.sess().recursion_limit.get() {
            ccx.sess().span_fatal(ccx.tcx.map.span(fn_id.node),
                "reached the recursion limit during monomorphization");
        }

        monomorphizing.insert(fn_id, depth + 1);
    }

    let s = ccx.tcx.map.with_path(fn_id.node, |path| {
        let mut state = sip::SipState::new();
        hash_id.hash(&mut state);
        mono_ty.hash(&mut state);

        exported_name(path,
                      format!("h{}", state.result()).as_slice(),
                      ccx.link_meta.crateid.version_or_default())
    });
    debug!("monomorphize_fn mangled to {}", s);

    // This shouldn't need to option dance.
    let mut hash_id = Some(hash_id);
    let mk_lldecl = || {
        let lldecl = decl_internal_rust_fn(ccx, mono_ty, s.as_slice());
        ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl);
        lldecl
    };

    let lldecl = match map_node {
        ast_map::NodeItem(i) => {
            match *i {
              ast::Item {
                  node: ast::ItemFn(decl, _, _, _, body),
                  ..
              } => {
                  let d = mk_lldecl();
                  set_llvm_fn_attrs(i.attrs.as_slice(), d);
                  trans_fn(ccx, decl, body, d, Some(&psubsts), fn_id.node, []);
                  d
              }
              _ => {
                ccx.sess().bug("Can't monomorphize this kind of item")
              }
            }
        }
        ast_map::NodeForeignItem(i) => {
            let simple = intrinsic::get_simple_intrinsic(ccx, i);
            match simple {
                Some(decl) => decl,
                None => {
                    let d = mk_lldecl();
                    intrinsic::trans_intrinsic(ccx, d, i, &psubsts, ref_id);
                    d
                }
            }
        }
        ast_map::NodeVariant(v) => {
            let parent = ccx.tcx.map.get_parent(fn_id.node);
            let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
            let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
            let d = mk_lldecl();
            set_inline_hint(d);
            match v.node.kind {
                ast::TupleVariantKind(ref args) => {
                    trans_enum_variant(ccx,
                                       parent,
                                       v,
                                       args.as_slice(),
                                       this_tv.disr_val,
                                       Some(&psubsts),
                                       d);
                }
                ast::StructVariantKind(_) =>
                    ccx.sess().bug("can't monomorphize struct variants"),
            }
            d
        }
        ast_map::NodeMethod(mth) => {
            let d = mk_lldecl();
            set_llvm_fn_attrs(mth.attrs.as_slice(), d);
            trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
            d
        }
        ast_map::NodeTraitMethod(method) => {
            match *method {
                ast::Provided(mth) => {
                    let d = mk_lldecl();
                    set_llvm_fn_attrs(mth.attrs.as_slice(), d);
                    trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
                    d
                }
                _ => {
                    ccx.sess().bug(format!("can't monomorphize a {:?}",
                                           map_node).as_slice())
                }
            }
        }
        ast_map::NodeStructCtor(struct_def) => {
            let d = mk_lldecl();
            set_inline_hint(d);
            base::trans_tuple_struct(ccx,
                                     struct_def.fields.as_slice(),
                                     struct_def.ctor_id.expect("ast-mapped tuple struct \
                                                                didn't have a ctor id"),
                                     Some(&psubsts),
                                     d);
            d
        }

        // Ugh -- but this ensures any new variants won't be forgotten
        ast_map::NodeLifetime(..) |
        ast_map::NodeExpr(..) |
        ast_map::NodeStmt(..) |
        ast_map::NodeArg(..) |
        ast_map::NodeBlock(..) |
        ast_map::NodePat(..) |
        ast_map::NodeLocal(..) => {
            ccx.sess().bug(format!("can't monomorphize a {:?}",
                                   map_node).as_slice())
        }
    };

    ccx.monomorphizing.borrow_mut().insert(fn_id, depth);

    debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
    (lldecl, false)
}

// Used to identify cached monomorphized functions and vtables
#[deriving(PartialEq, Eq, Hash)]
pub struct MonoParamId {
    pub subst: ty::t,
}

#[deriving(PartialEq, Eq, Hash)]
pub struct MonoId {
    pub def: ast::DefId,
    pub params: Vec<ty::t>
}

pub fn make_vtable_id(_ccx: &CrateContext,
                      origin: &typeck::vtable_origin)
                      -> MonoId {
    match origin {
        &typeck::vtable_static(impl_id, ref substs, _) => {
            MonoId {
                def: impl_id,
                params: substs.tps.iter().map(|subst| *subst).collect()
            }
        }

        // can't this be checked at the callee?
        _ => fail!("make_vtable_id needs vtable_static")
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate genmesh;
extern crate clock_ticks;
extern crate obj;

use std::old_io::timer;
use std::time::duration::Duration;
use glium::{self, Display};
use glium::vertex::VertexBufferAny;

pub mod camera;

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F) where F: FnMut() -> Action {
    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();

    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        };

        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;

        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;

            // if you have a game, update the state here
        }

        timer::sleep(Duration::nanoseconds((FIXED_TIME_STAMP - accumulator) as i64));
    }
}

/// Returns a vertex buffer that should be rendered as `TrianglesList`.
pub fn load_wavefront(display: &Display, data: &[u8]) -> VertexBufferAny {
    #[derive(Copy)]
    struct Vertex {
        position: [f32; 3],
        normal: [f32; 3],
        texture: [f32; 2],
    }

    implement_vertex!(Vertex, position, normal, texture);

    let mut data = ::std::io::BufReader::new(data);
    let data = obj::Obj::load(&mut data);

    let mut vertex_data = Vec::new();

    for shape in data.object_iter().next().unwrap().group_iter().flat_map(|g| g.indices().iter()) {
        match shape {
            &genmesh::Polygon::PolyTri(genmesh::Triangle { x: v1, y: v2, z: v3 }) => {
                for v in [v1, v2, v3].iter() {
                    let position = data.position()[v.0];
                    let texture = v.1.map(|index| data.texture()[index]);
                    let normal = v.2.map(|index| data.normal()[index]);

                    let texture = texture.unwrap_or([0.0, 0.0]);
                    let normal = normal.unwrap_or([0.0, 0.0, 0.0]);

                    vertex_data.push(Vertex {
                        position: position,
                        normal: normal,
                        texture: texture,
                    })
                }
            },
            _ => unimplemented!()
        }
    }

    glium::vertex::VertexBuffer::new(display, vertex_data).into_vertex_buffer_any()
}
<commit_msg>Replace std::old_io::timer::sleep with std::thread::sleep<commit_after>#![allow(dead_code)]

extern crate genmesh;
extern crate clock_ticks;
extern crate obj;

use std::thread;
use std::time::duration::Duration;
use glium::{self, Display};
use glium::vertex::VertexBufferAny;

pub mod camera;

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F) where F: FnMut() -> Action {
    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();

    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        };

        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;

        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;

            // if you have a game, update the state here
        }

        thread::sleep(Duration::nanoseconds((FIXED_TIME_STAMP - accumulator) as i64));
    }
}

/// Returns a vertex buffer that should be rendered as `TrianglesList`.
pub fn load_wavefront(display: &Display, data: &[u8]) -> VertexBufferAny {
    #[derive(Copy)]
    struct Vertex {
        position: [f32; 3],
        normal: [f32; 3],
        texture: [f32; 2],
    }

    implement_vertex!(Vertex, position, normal, texture);

    let mut data = ::std::io::BufReader::new(data);
    let data = obj::Obj::load(&mut data);

    let mut vertex_data = Vec::new();

    for shape in data.object_iter().next().unwrap().group_iter().flat_map(|g| g.indices().iter()) {
        match shape {
            &genmesh::Polygon::PolyTri(genmesh::Triangle { x: v1, y: v2, z: v3 }) => {
                for v in [v1, v2, v3].iter() {
                    let position = data.position()[v.0];
                    let texture = v.1.map(|index| data.texture()[index]);
                    let normal = v.2.map(|index| data.normal()[index]);

                    let texture = texture.unwrap_or([0.0, 0.0]);
                    let normal = normal.unwrap_or([0.0, 0.0, 0.0]);

                    vertex_data.push(Vertex {
                        position: position,
                        normal: normal,
                        texture: texture,
                    })
                }
            },
            _ => unimplemented!()
        }
    }

    glium::vertex::VertexBuffer::new(display, vertex_data).into_vertex_buffer_any()
}
<|endoftext|>


<commit_before>pub fn is_leap_year(year: isize) -> bool {
    (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
}
<commit_msg>Test the simple case first<commit_after>pub fn is_leap_year(year: isize) -> bool {
    (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)
}
<|endoftext|>