<commit_before>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

const MAX_UDP_SIZE: u16 = 65535;
pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

pub type UnderlyingError = Box<Error + Send + Sync>;
#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(UnderlyingError),
    DeserializeError(UnderlyingError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => err.description(),
            TransitError::SerializeError(ref err) => err.description(),
            TransitError::DeserializeError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

impl From<io::Error> for TransitError {
    fn from(err: io::Error) -> TransitError {
        TransitError::IoError(err)
    }
}

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(Box::new(err))
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(Box::new(err))
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> Result<Transit<T>, TransitError> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let mut buf = [0; MAX_UDP_SIZE as usize];
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        let data = try!(deserialize(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(MAX_UDP_SIZE as u64);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> Result<SocketAddr, TransitError> {
        let addr = try!(self.socket.local_addr());
        Ok(addr)
    }
}

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

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<commit_msg>Do not allocate buffer on every recv_from call<commit_after>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

const MAX_UDP_SIZE: u16 = 65535;
pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
    buffer: Box<[u8]>,
}

pub type UnderlyingError = Box<Error + Send + Sync>;
#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(UnderlyingError),
    DeserializeError(UnderlyingError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => err.description(),
            TransitError::SerializeError(ref err) => err.description(),
            TransitError::DeserializeError(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

impl From<io::Error> for TransitError {
    fn from(err: io::Error) -> TransitError {
        TransitError::IoError(err)
    }
}

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(Box::new(err))
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(Box::new(err))
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let mut transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> Result<Transit<T>, TransitError> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
            buffer: (0..MAX_UDP_SIZE as usize)
            .map(|_x| 0u8)
            .collect::<Vec<u8>>()
            .into_boxed_slice(),
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&mut self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let (n, addr) = try!(self.socket.recv_from(&mut self.buffer));
        let data = try!(deserialize(&self.buffer[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(MAX_UDP_SIZE as u64);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> Result<SocketAddr, TransitError> {
        let addr = try!(self.socket.local_addr());
        Ok(addr)
    }
}

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

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let mut transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let mut transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let mut transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<|endoftext|>


<commit_before>use ui::{Rect, Layer, MouseEvent, ZLayer, Point2I, RectI, Text, Element};
use cgmath::vec2;

use std::fmt;
use std::fmt::Debug;

// man, that function ... can't even clone that thing
pub struct View<Ev> {
    pub frame: Rect<i32>,
    pub on_event: Option<Box<Fn(MouseEvent) -> Option<Ev>>>,
    pub layers: Vec<Layer>,
    pub sub_views : Vec<View<Ev>>,
}

impl<Ev> fmt::Debug for View<Ev> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "View {{ frame: {:?}, layers: {:?} sub_view: {:?} }}", self.frame, self.layers, self.sub_views)
    }
}

impl<Ev> View<Ev> {
    pub fn iter<'a>(&'a self) -> ViewIterator<'a, Ev> {
        let queue = vec![(self, vec2(0, 0), 0)];
        ViewIterator {
            queue,
        }
    }

    pub fn layer_iter<'a>(&'a self) -> LayerIterator<'a, Ev> {
        let queue = vec![(self, vec2(0, 0), 0)];
        LayerIterator {
            views: queue,
            layer_idx: 0,
        }
    }
}

pub struct ViewIterator<'a, Ev> where Ev: 'a {
    queue : Vec<(&'a View<Ev>, Point2I, ZLayer)>,
}

impl<'a, Ev> Iterator for ViewIterator<'a, Ev> {
    type Item = (&'a View<Ev>, RectI, ZLayer);

    fn next(&mut self) -> Option<(&'a View<Ev>, RectI, ZLayer)> {
        if let Some((view, parent_origin, z)) = self.queue.pop() {
            for sv in &view.sub_views {
                self.queue.push((sv, parent_origin + view.frame.min, z+1));
            }
            Some((view, view.frame.offset(parent_origin), z))
        } else {
            None
        }
    }
}

pub struct LayerIterator<'a, Ev> where Ev: 'a {
    views : Vec<(&'a View<Ev>, Point2I, ZLayer)>,
    layer_idx: usize,
}

impl<'a, Ev> Iterator for LayerIterator<'a, Ev> {
    type Item = (&'a Layer, RectI, (ZLayer, ZLayer));

    fn next(&mut self) -> Option<(&'a Layer, RectI, (ZLayer, ZLayer))> {
        if let Some(&(view, parent_origin, z)) = self.views.last() {
            if self.layer_idx < view.layers.len() {
                let l = &view.layers[self.layer_idx];
                let layer_z = self.layer_idx as ZLayer;
                self.layer_idx += 1;
                let layer_frame = l.frame.offset(parent_origin + view.frame.min);
                return Some((l, layer_frame, (z, layer_z)));
            } else {
                // reset layer for next view
                self.layer_idx = 0;
            }
        }

        // no more layers
        if let Some((view, parent_origin, z)) = self.views.pop() {
            for sv in &view.sub_views {
                self.views.push((sv, parent_origin + view.frame.min, z+1));
            }
            self.next()
        } else {
            None
        }
    }
}

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

    pub fn empty_view(at:Point2I) -> View<()> {
        View {
            frame : Rect {
                min: at,
                max: at + vec2(10, 10),
            },
            on_event: None,
            layers : Vec::new(),
            sub_views: Vec::new(),
        }
    }

    pub fn view_with_text(at:Point2I) -> View<()> {
        let mut layers = Vec::new();

        for i in 0..3 {

            layers.push(Layer {
                frame: Rect {
                    min: vec2(0, i * 30),
                    max: vec2(100, (i + 1) * 30),
                },
                content: Element::Text(Text::new("awesome".into())),
            });
        }

        View {
            frame : Rect {
                min: at,
                max: at + vec2(50, 100),
            },
            on_event: None,
            layers : layers,
            sub_views: Vec::new(),
        }
    }

    #[test]
    fn view_iterator() {
        let mut v = empty_view(vec2(100, 100));
        for i in 0..3 {
            v.sub_views.push(empty_view(vec2(10 * i, 10)));
        }

        println!("====== VIEWS =======");

        for (v, r, z) in v.iter() {
            println!("view -> {:?} rect -> {:?} z -> {:?}", v, r, z);
        }
    }

    #[test]
    fn layer_iterator() {
        let mut v = empty_view(vec2(100, 100));
        for i in 0..3 {
            v.sub_views.push(view_with_text(vec2(100 * i, 0)));
        }

        println!("====== LAYERS =======");

        for (l, r, z) in v.layer_iter() {
            println!("layer -> {:?} rect -> {:?} z -> {:?}", l, r, z);
        }
    }
}<commit_msg>Reduced View debug format<commit_after>use ui::{Rect, Layer, MouseEvent, ZLayer, Point2I, RectI, Text, Element};
use cgmath::vec2;

use std::fmt;
use std::fmt::Debug;

// man, that function ... can't even clone that thing
pub struct View<Ev> {
    pub frame: Rect<i32>,
    pub on_event: Option<Box<Fn(MouseEvent) -> Option<Ev>>>,
    pub layers: Vec<Layer>,
    pub sub_views : Vec<View<Ev>>,
}

impl<Ev> fmt::Debug for View<Ev> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "View {{ frame: {:?}, layers: {:?} sub_view: {:?} }}", self.frame, self.layers.len(), self.sub_views.len())
    }
}

impl<Ev> View<Ev> {
    pub fn iter<'a>(&'a self) -> ViewIterator<'a, Ev> {
        let queue = vec![(self, vec2(0, 0), 0)];
        ViewIterator {
            queue,
        }
    }

    pub fn layer_iter<'a>(&'a self) -> LayerIterator<'a, Ev> {
        let queue = vec![(self, vec2(0, 0), 0)];
        LayerIterator {
            views: queue,
            layer_idx: 0,
        }
    }
}

pub struct ViewIterator<'a, Ev> where Ev: 'a {
    queue : Vec<(&'a View<Ev>, Point2I, ZLayer)>,
}

impl<'a, Ev> Iterator for ViewIterator<'a, Ev> {
    type Item = (&'a View<Ev>, RectI, ZLayer);

    fn next(&mut self) -> Option<(&'a View<Ev>, RectI, ZLayer)> {
        if let Some((view, parent_origin, z)) = self.queue.pop() {
            for sv in &view.sub_views {
                self.queue.push((sv, parent_origin + view.frame.min, z+1));
            }
            Some((view, view.frame.offset(parent_origin), z))
        } else {
            None
        }
    }
}

pub struct LayerIterator<'a, Ev> where Ev: 'a {
    views : Vec<(&'a View<Ev>, Point2I, ZLayer)>,
    layer_idx: usize,
}

impl<'a, Ev> Iterator for LayerIterator<'a, Ev> {
    type Item = (&'a Layer, RectI, (ZLayer, ZLayer));

    fn next(&mut self) -> Option<(&'a Layer, RectI, (ZLayer, ZLayer))> {
        if let Some(&(view, parent_origin, z)) = self.views.last() {
            if self.layer_idx < view.layers.len() {
                let l = &view.layers[self.layer_idx];
                let layer_z = self.layer_idx as ZLayer;
                self.layer_idx += 1;
                let layer_frame = l.frame.offset(parent_origin + view.frame.min);
                return Some((l, layer_frame, (z, layer_z)));
            } else {
                // reset layer for next view
                self.layer_idx = 0;
            }
        }

        // no more layers
        if let Some((view, parent_origin, z)) = self.views.pop() {
            for sv in &view.sub_views {
                self.views.push((sv, parent_origin + view.frame.min, z+1));
            }
            self.next()
        } else {
            None
        }
    }
}

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

    pub fn empty_view(at:Point2I) -> View<()> {
        View {
            frame : Rect {
                min: at,
                max: at + vec2(10, 10),
            },
            on_event: None,
            layers : Vec::new(),
            sub_views: Vec::new(),
        }
    }

    pub fn view_with_text(at:Point2I) -> View<()> {
        let mut layers = Vec::new();

        for i in 0..3 {

            layers.push(Layer {
                frame: Rect {
                    min: vec2(0, i * 30),
                    max: vec2(100, (i + 1) * 30),
                },
                content: Element::Text(Text::new("awesome".into())),
            });
        }

        View {
            frame : Rect {
                min: at,
                max: at + vec2(50, 100),
            },
            on_event: None,
            layers : layers,
            sub_views: Vec::new(),
        }
    }

    #[test]
    fn view_iterator() {
        let mut v = empty_view(vec2(100, 100));
        for i in 0..3 {
            let mut nv = empty_view(vec2(100 * i, 10));
            for j in 0..2 {
                nv.sub_views.push(empty_view(vec2(0, 30 * i)));
            }
            v.sub_views.push(nv);
        }

        println!("====== VIEWS =======");

        for (v, r, z) in v.iter() {
            println!("view -> {:?} rect -> {:?} z -> {:?}", v, r, z);
        }
    }

    #[test]
    fn layer_iterator() {
        let mut v = empty_view(vec2(100, 100));
        for i in 0..3 {
            v.sub_views.push(view_with_text(vec2(100 * i, 0)));
        }

        println!("====== LAYERS =======");

        for (l, r, z) in v.layer_iter() {
            println!("layer -> {:?} rect -> {:?} z -> {:?}", l, r, z);
        }
    }
}<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc_front::hir::*;
use syntax::codemap::Span;

use unicode_normalization::UnicodeNormalization;

use utils::span_help_and_lint;

declare_lint!{ pub ZERO_WIDTH_SPACE, Deny,
               "using a zero-width space in a string literal, which is confusing" }
declare_lint!{ pub NON_ASCII_LITERAL, Allow,
               "using any literal non-ASCII chars in a string literal; suggests \
                using the \\u escape instead" }
declare_lint!{ pub UNICODE_NOT_NFC, Allow,
               "using a unicode literal not in NFC normal form (see \
               http://www.unicode.org/reports/tr15/ for further information)" }

#[derive(Copy, Clone)]
pub struct Unicode;

impl LintPass for Unicode {
    fn get_lints(&self) -> LintArray {
        lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprLit(ref lit) = expr.node {
            if let LitStr(ref string, _) = lit.node {
                check_str(cx, string, lit.span)
            }
        }
    }
}

fn escape<T: Iterator<Item=char>>(s: T) -> String {
    let mut result = String::new();
    for c in s {
        if c as u32 > 0x7F {
            for d in c.escape_unicode() { result.push(d) };
        } else {
            result.push(c);
        }
    }
    result
}

fn check_str(cx: &Context, string: &str, span: Span) {
    if string.contains('\u{200B}') {
        span_help_and_lint(cx, ZERO_WIDTH_SPACE, span,
            "zero-width space detected",
            &format!("Consider replacing the string with:\n\"{}\"",
                string.replace("\u{200B}", "\\u{200B}")));
    }
    if string.chars().any(|c| c as u32 > 0x7F) {
        span_help_and_lint(cx, NON_ASCII_LITERAL, span,
            "literal non-ASCII character detected",
            &format!("Consider replacing the string with:\n\"{}\"",
                if cx.current_level(UNICODE_NOT_NFC) == Level::Allow {
                    escape(string.chars())
                } else {
                    escape(string.nfc())
                }));
    }
    if string.chars().zip(string.nfc()).any(|(a, b)| a != b) {
        if cx.current_level(NON_ASCII_LITERAL) == Level::Allow {
            span_help_and_lint(cx, UNICODE_NOT_NFC, span,
                "non-nfc unicode sequence detected",
                &format!("Consider replacing the string with:\n\"{}\"",
                    string.nfc().collect::<String>()));
        }
    }
}
<commit_msg>fixed dogfood by using snippet instead of the (escaped) literal string<commit_after>use rustc::lint::*;
use rustc_front::hir::*;
use syntax::codemap::Span;

use unicode_normalization::UnicodeNormalization;

use utils::{snippet, span_help_and_lint};

declare_lint!{ pub ZERO_WIDTH_SPACE, Deny,
               "using a zero-width space in a string literal, which is confusing" }
declare_lint!{ pub NON_ASCII_LITERAL, Allow,
               "using any literal non-ASCII chars in a string literal; suggests \
                using the \\u escape instead" }
declare_lint!{ pub UNICODE_NOT_NFC, Allow,
               "using a unicode literal not in NFC normal form (see \
               http://www.unicode.org/reports/tr15/ for further information)" }

#[derive(Copy, Clone)]
pub struct Unicode;

impl LintPass for Unicode {
    fn get_lints(&self) -> LintArray {
        lint_array!(ZERO_WIDTH_SPACE, NON_ASCII_LITERAL, UNICODE_NOT_NFC)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprLit(ref lit) = expr.node {
            if let LitStr(_, _) = lit.node {
                check_str(cx, lit.span)
            }
        }
    }
}

fn escape<T: Iterator<Item=char>>(s: T) -> String {
    let mut result = String::new();
    for c in s {
        if c as u32 > 0x7F {
            for d in c.escape_unicode() { result.push(d) };
        } else {
            result.push(c);
        }
    }
    result
}

fn check_str(cx: &Context, span: Span) {
    let string = snippet(cx, span, "");
    if string.contains('\u{200B}') {
        span_help_and_lint(cx, ZERO_WIDTH_SPACE, span,
            "zero-width space detected",
            &format!("Consider replacing the string with:\n\"{}\"",
                string.replace("\u{200B}", "\\u{200B}")));
    }
    if string.chars().any(|c| c as u32 > 0x7F) {
        span_help_and_lint(cx, NON_ASCII_LITERAL, span,
            "literal non-ASCII character detected",
            &format!("Consider replacing the string with:\n\"{}\"",
                if cx.current_level(UNICODE_NOT_NFC) == Level::Allow {
                    escape(string.chars())
                } else {
                    escape(string.nfc())
                }));
    }
    if cx.current_level(NON_ASCII_LITERAL) == Level::Allow &&
            string.chars().zip(string.nfc()).any(|(a, b)| a != b) {
        span_help_and_lint(cx, UNICODE_NOT_NFC, span,
            "non-nfc unicode sequence detected",
            &format!("Consider replacing the string with:\n\"{}\"",
                string.nfc().collect::<String>()));
    }
}
<|endoftext|>


<commit_before>// Test that a custom handler works on wasm32-unknown-unknown
#![cfg(all(
    target_arch = "wasm32",
    target_os = "unknown",
    feature = "custom",
    not(feature = "js")
))]

use wasm_bindgen_test::wasm_bindgen_test as test;
#[cfg(feature = "test-in-browser")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

use core::{
    num::NonZeroU32,
    sync::atomic::{AtomicU8, Ordering},
};
use getrandom::{getrandom, register_custom_getrandom, Error};

fn len7_err() -> Error {
    NonZeroU32::new(Error::INTERNAL_START + 7).unwrap().into()
}

fn super_insecure_rng(buf: &mut [u8]) -> Result<(), Error> {
    // Length 7 buffers return a custom error
    if buf.len() == 7 {
        return Err(len7_err());
    }
    // Otherwise, increment an atomic counter
    static COUNTER: AtomicU8 = AtomicU8::new(0);
    for b in buf {
        *b = COUNTER.fetch_add(1, Ordering::Relaxed);
    }
    Ok(())
}

register_custom_getrandom!(super_insecure_rng);

#[test]
fn custom_rng_output() {
    let mut buf = [0u8; 4];
    assert_eq!(getrandom(&mut buf), Ok(()));
    assert_eq!(buf, [0, 1, 2, 3]);
    assert_eq!(getrandom(&mut buf), Ok(()));
    assert_eq!(buf, [4, 5, 6, 7]);
}

#[test]
fn rng_err_output() {
    assert_eq!(getrandom(&mut [0; 7]), Err(len7_err()));
}
<commit_msg>Remove state from Custom RNG<commit_after>// Test that a custom handler works on wasm32-unknown-unknown
#![cfg(all(
    target_arch = "wasm32",
    target_os = "unknown",
    feature = "custom",
    not(feature = "js")
))]

use wasm_bindgen_test::wasm_bindgen_test as test;
#[cfg(feature = "test-in-browser")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

use core::num::NonZeroU32;
use getrandom::{getrandom, register_custom_getrandom, Error};

fn len7_err() -> Error {
    NonZeroU32::new(Error::INTERNAL_START + 7).unwrap().into()
}

fn super_insecure_rng(buf: &mut [u8]) -> Result<(), Error> {
    // Length 7 buffers return a custom error
    if buf.len() == 7 {
        return Err(len7_err());
    }
    // Otherwise, fill bytes based on input length
    let mut start = buf.len() as u8;
    for b in buf {
        *b = start;
        start = start.wrapping_mul(3);
    }
    Ok(())
}

register_custom_getrandom!(super_insecure_rng);

#[test]
fn custom_rng_output() {
    let mut buf = [0u8; 4];
    assert_eq!(getrandom(&mut buf), Ok(()));
    assert_eq!(buf, [4, 12, 36, 108]);

    let mut buf = [0u8; 3];
    assert_eq!(getrandom(&mut buf), Ok(()));
    assert_eq!(buf, [3, 9, 27]);
}

#[test]
fn rng_err_output() {
    assert_eq!(getrandom(&mut [0; 7]), Err(len7_err()));
}
<|endoftext|>


<commit_before>// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use Api;
use registry::{Enum, Registry, Cmd};
use std::io;

pub mod debug_struct_gen;
pub mod global_gen;
pub mod static_gen;
pub mod struct_gen;
pub mod static_struct_gen;

/// Trait for a bindings generator.
pub trait Generator {
    /// Builds the GL bindings.
    fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write;
}

pub fn gen_struct_name(api: Api) -> &'static str {
    match api {
        Api::Gl => "Gl",
        Api::Glx => "Glx",
        Api::Wgl => "Wgl",
        Api::Egl => "Egl",
        Api::GlCore => "GlCore",
        Api::Gles1 => "Gles1",
        Api::Gles2 => "Gles2",
        Api::Glsc2 => "Glsc2",
    }
}

/// This function generates a `const name: type = value;` item.
pub fn gen_enum_item<W>(enm: &Enum, types_prefix: &str, dest: &mut W) -> io::Result<()>
    where W: io::Write
{
    writeln!(dest,
        "#[allow(dead_code, non_upper_case_globals)] pub const {ident}: {types_prefix}{ty} = {value}{cast_suffix};",
        ident = enm.ident,
        types_prefix = if enm.ty == "&'static str" { "" } else { types_prefix },
        ty = enm.ty,
        value = enm.value,
        cast_suffix = match enm.cast {
            true => format!(" as {}{}", types_prefix, enm.ty),
            false => String::new(),
        },
    )
}

/// Generates all the type aliases for a namespace.
///
/// Aliases are either `pub type = ...` or `#[repr(C)] pub struct ... { ... }` and contain all the
/// things that we can't obtain from the XML files.
pub fn gen_types<W>(api: Api, dest: &mut W) -> io::Result<()>
    where W: io::Write
{
    if let Api::Egl = api {
        try!(writeln!(dest, "{}", include_str!("templates/types/egl.rs")));
        return Ok(());
    }

    try!(writeln!(dest, "{}", include_str!("templates/types/gl.rs")));

    match api {
        Api::Glx => try!(writeln!(dest, "{}", include_str!("templates/types/glx.rs"))),
        Api::Wgl => try!(writeln!(dest, "{}", include_str!("templates/types/wgl.rs"))),
        _ => {}
    }

    Ok(())
}

/// Generates the list of Rust `Arg`s that a `Cmd` requires.
pub fn gen_parameters(cmd: &Cmd, with_idents: bool, with_types: bool) -> Vec<String> {
    cmd.params
        .iter()
        .map(|binding| {
            // returning
            if with_idents && with_types {
                format!("{}: {}", binding.ident, binding.ty)
            } else if with_types {
                format!("{}", binding.ty)
            } else if with_idents {
                format!("{}", binding.ident)
            } else {
                panic!()
            }
        })
        .collect()
}

/// Generates the native symbol name of a `Cmd`.
///
/// Example results: `"glClear"`, `"wglCreateContext"`, etc.
pub fn gen_symbol_name(api: Api, cmd: &str) -> String {
    match api {
        Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => format!("gl{}", cmd),
        Api::Glx => format!("glX{}", cmd),
        Api::Wgl => format!("wgl{}", cmd),
        Api::Egl => format!("egl{}", cmd),
    }
}
<commit_msg>Link to generators in README from doc-comment<commit_after>// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use Api;
use registry::{Enum, Registry, Cmd};
use std::io;

pub mod debug_struct_gen;
pub mod global_gen;
pub mod static_gen;
pub mod struct_gen;
pub mod static_struct_gen;

/// Trait for a bindings generator.
///
/// See https://github.com/brendanzab/gl-rs/tree/master/gl_generator#generator-types
pub trait Generator {
    /// Builds the GL bindings.
    fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()> where W: io::Write;
}

pub fn gen_struct_name(api: Api) -> &'static str {
    match api {
        Api::Gl => "Gl",
        Api::Glx => "Glx",
        Api::Wgl => "Wgl",
        Api::Egl => "Egl",
        Api::GlCore => "GlCore",
        Api::Gles1 => "Gles1",
        Api::Gles2 => "Gles2",
        Api::Glsc2 => "Glsc2",
    }
}

/// This function generates a `const name: type = value;` item.
pub fn gen_enum_item<W>(enm: &Enum, types_prefix: &str, dest: &mut W) -> io::Result<()>
    where W: io::Write
{
    writeln!(dest,
        "#[allow(dead_code, non_upper_case_globals)] pub const {ident}: {types_prefix}{ty} = {value}{cast_suffix};",
        ident = enm.ident,
        types_prefix = if enm.ty == "&'static str" { "" } else { types_prefix },
        ty = enm.ty,
        value = enm.value,
        cast_suffix = match enm.cast {
            true => format!(" as {}{}", types_prefix, enm.ty),
            false => String::new(),
        },
    )
}

/// Generates all the type aliases for a namespace.
///
/// Aliases are either `pub type = ...` or `#[repr(C)] pub struct ... { ... }` and contain all the
/// things that we can't obtain from the XML files.
pub fn gen_types<W>(api: Api, dest: &mut W) -> io::Result<()>
    where W: io::Write
{
    if let Api::Egl = api {
        try!(writeln!(dest, "{}", include_str!("templates/types/egl.rs")));
        return Ok(());
    }

    try!(writeln!(dest, "{}", include_str!("templates/types/gl.rs")));

    match api {
        Api::Glx => try!(writeln!(dest, "{}", include_str!("templates/types/glx.rs"))),
        Api::Wgl => try!(writeln!(dest, "{}", include_str!("templates/types/wgl.rs"))),
        _ => {}
    }

    Ok(())
}

/// Generates the list of Rust `Arg`s that a `Cmd` requires.
pub fn gen_parameters(cmd: &Cmd, with_idents: bool, with_types: bool) -> Vec<String> {
    cmd.params
        .iter()
        .map(|binding| {
            // returning
            if with_idents && with_types {
                format!("{}: {}", binding.ident, binding.ty)
            } else if with_types {
                format!("{}", binding.ty)
            } else if with_idents {
                format!("{}", binding.ident)
            } else {
                panic!()
            }
        })
        .collect()
}

/// Generates the native symbol name of a `Cmd`.
///
/// Example results: `"glClear"`, `"wglCreateContext"`, etc.
pub fn gen_symbol_name(api: Api, cmd: &str) -> String {
    match api {
        Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => format!("gl{}", cmd),
        Api::Glx => format!("glX{}", cmd),
        Api::Wgl => format!("wgl{}", cmd),
        Api::Egl => format!("egl{}", cmd),
    }
}
<|endoftext|>


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

use Rng;
use distributions::Distribution;

/// The Bernoulli distribution.
///
/// This is a special case of the Binomial distribution where `n = 1`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Bernoulli, Distribution};
///
/// let d = Bernoulli::new(0.3);
/// let v = d.sample(&mut rand::thread_rng());
/// println!("{} is from a Bernoulli distribution", v);
/// ```
///
/// # Precision
///
/// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`),
/// so only probabilities that are multiples of 2-64 can be
/// represented.
#[derive(Clone, Copy, Debug)]
pub struct Bernoulli {
    /// Probability of success, relative to the maximal integer.
    p_int: u64,
}

impl Bernoulli {
    /// Construct a new `Bernoulli` with the given probability of success `p`.
    ///
    /// # Panics
    ///
    /// If `p < 0` or `p > 1`.
    ///
    /// # Precision
    ///
    /// For `p = 1.0`, the resulting distribution will always generate true.
    /// For `p = 0.0`, the resulting distribution will always generate false.
    ///
    /// This method is accurate for any input `p` in the range `[0, 1]` which is
    /// a multiple of 2-64. (Note that not all multiples of
    /// 2-64 in `[0, 1]` can be represented as a `f64`.)
    #[inline]
    pub fn new(p: f64) -> Bernoulli {
        assert!(p >= 0.0 & p <= 1.0, "Bernoulli::new not called with 0 <= p <= 0");
        let p_int = if p < 1.0 {
            (p * (::core::u64::MAX as f64)) as u64
        } else {
            // Avoid overflow: u64::MAX as f64 cannot be represented as u64.
            ::core::u64::MAX
        };
        Bernoulli { p_int }
    }
}

impl Distribution<bool> for Bernoulli {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
        // Make sure to always return true for p = 1.0.
        if self.p_int == ::core::u64::MAX {
            return true;
        }
        let r: u64 = rng.gen();
        r < self.p_int
    }
}

#[cfg(test)]
mod test {
    use {Rng, SmallRng, FromEntropy};
    use distributions::Distribution;
    use super::Bernoulli;

    #[test]
    fn test_trivial() {
        let mut r = SmallRng::from_entropy();
        let always_false = Bernoulli::new(0.0);
        let always_true = Bernoulli::new(1.0);
        for _ in 0..5 {
            assert_eq!(r.sample::<bool, _>(&always_false), false);
            assert_eq!(r.sample::<bool, _>(&always_true), true);
            assert_eq!(Distribution::<bool>::sample(&always_false, &mut r), false);
            assert_eq!(Distribution::<bool>::sample(&always_true, &mut r), true);
        }
    }

    #[test]
    fn test_average() {
        const P: f64 = 0.3;
        let d = Bernoulli::new(P);
        const N: u32 = 10_000_000;

        let mut sum: u32 = 0;
        let mut rng = SmallRng::from_entropy();
        for _ in 0..N {
            if d.sample(&mut rng) {
                sum += 1;
            }
        }
        let avg = (sum as f64) / (N as f64);

        assert!((avg - P).abs() < 1e-3);
    }
}
<commit_msg>Fix chained comparison<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! The Bernoulli distribution.

use Rng;
use distributions::Distribution;

/// The Bernoulli distribution.
///
/// This is a special case of the Binomial distribution where `n = 1`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Bernoulli, Distribution};
///
/// let d = Bernoulli::new(0.3);
/// let v = d.sample(&mut rand::thread_rng());
/// println!("{} is from a Bernoulli distribution", v);
/// ```
///
/// # Precision
///
/// This `Bernoulli` distribution uses 64 bits from the RNG (a `u64`),
/// so only probabilities that are multiples of 2-64 can be
/// represented.
#[derive(Clone, Copy, Debug)]
pub struct Bernoulli {
    /// Probability of success, relative to the maximal integer.
    p_int: u64,
}

impl Bernoulli {
    /// Construct a new `Bernoulli` with the given probability of success `p`.
    ///
    /// # Panics
    ///
    /// If `p < 0` or `p > 1`.
    ///
    /// # Precision
    ///
    /// For `p = 1.0`, the resulting distribution will always generate true.
    /// For `p = 0.0`, the resulting distribution will always generate false.
    ///
    /// This method is accurate for any input `p` in the range `[0, 1]` which is
    /// a multiple of 2-64. (Note that not all multiples of
    /// 2-64 in `[0, 1]` can be represented as a `f64`.)
    #[inline]
    pub fn new(p: f64) -> Bernoulli {
        assert!((p >= 0.0) & (p <= 1.0), "Bernoulli::new not called with 0 <= p <= 0");
        let p_int = if p < 1.0 {
            (p * (::core::u64::MAX as f64)) as u64
        } else {
            // Avoid overflow: u64::MAX as f64 cannot be represented as u64.
            ::core::u64::MAX
        };
        Bernoulli { p_int }
    }
}

impl Distribution<bool> for Bernoulli {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
        // Make sure to always return true for p = 1.0.
        if self.p_int == ::core::u64::MAX {
            return true;
        }
        let r: u64 = rng.gen();
        r < self.p_int
    }
}

#[cfg(test)]
mod test {
    use {Rng, SmallRng, FromEntropy};
    use distributions::Distribution;
    use super::Bernoulli;

    #[test]
    fn test_trivial() {
        let mut r = SmallRng::from_entropy();
        let always_false = Bernoulli::new(0.0);
        let always_true = Bernoulli::new(1.0);
        for _ in 0..5 {
            assert_eq!(r.sample::<bool, _>(&always_false), false);
            assert_eq!(r.sample::<bool, _>(&always_true), true);
            assert_eq!(Distribution::<bool>::sample(&always_false, &mut r), false);
            assert_eq!(Distribution::<bool>::sample(&always_true, &mut r), true);
        }
    }

    #[test]
    fn test_average() {
        const P: f64 = 0.3;
        let d = Bernoulli::new(P);
        const N: u32 = 10_000_000;

        let mut sum: u32 = 0;
        let mut rng = SmallRng::from_entropy();
        for _ in 0..N {
            if d.sample(&mut rng) {
                sum += 1;
            }
        }
        let avg = (sum as f64) / (N as f64);

        assert!((avg - P).abs() < 1e-3);
    }
}
<|endoftext|>


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

//! The dirichlet distribution.

use Rng;
use distributions::{Distribution, gamma::Gamma};

/// The dirichelet distribution `Dirichlet(alpha)`.
///
/// The Dirichlet distribution } is a family of continuous multivariate probability distributions parameterized by
/// a vector alpha of positive reals
/// It is a multivariate generalization of the beta distribution.
///
/// # Example
///
/// ```
/// use rand::prelude::*;
/// use rand::distributions::Dirichlet;
///
/// let dirichlet = Dirichlet::new(&vec![1.0, 2.0, 3.0]);
/// let samples = dirichlet.sample(&mut rand::thread_rng());
/// println!("{:?} is from a Dirichlet([1.0, 2.0, 3.0]) distribution", samples);
/// ```

#[derive(Clone, Debug)]
pub struct Dirichlet {
    /// Concentration parameters (alpha)
    alpha: Vec<f64>,
}

impl Dirichlet {
    /// Construct a new `Dirichlet` with the given alpha parameter
    /// `alpha`. Panics if `alpha.len() < 2`.
    #[inline]
    pub fn new(alpha: &[f64]) -> Dirichlet {
        assert!(
            alpha.len() > 1,
            "Dirichlet::new called with `alpha` with length <  2"
        );
        for i in 0..alpha.len() {
            assert!(
                alpha[i] > 0.0,
                "Dirichlet::new called with `alpha`  <=  0.0"
            );
        }

        Dirichlet {
            alpha: alpha.to_vec(),
        }
    }

    /// Construct a new `Dirichlet` with the given shape parameter and size
    /// `alpha`. Panics if `alpha <= 0.0`.
    /// `size` . Panic if `size < 2`
    #[inline]
    pub fn new_with_param(alpha: f64, size: usize) -> Dirichlet {
        assert!(alpha > 0.0, "Dirichlet::new called with `alpha`  <=  0.0");
        assert!(size > 1, "Dirichlet::new called with `size`  <=  1");
        Dirichlet {
            alpha: vec![alpha; size],
        }
    }
}

impl Distribution<Vec<f64>> for Dirichlet {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec<f64> {
        let n = self.alpha.len();
        let mut samples = vec![0.0f64; n];
        let mut sum = 0.0f64;

        for i in 0..n {
            let g = Gamma::new(self.alpha[i], 1.0);
            samples[i] = g.sample(rng);
            sum += samples[i];
        }
        let invacc = 1.0 / sum;
        for i in 0..n {
            samples[i] *= invacc;
        }
        samples
    }
}

#[cfg(test)]
mod test {
    use super::Dirichlet;
    use distributions::Distribution;

    #[test]
    fn test_dirichlet() {
        let d = Dirichlet::new(&vec![1.0, 2.0, 3.0]);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    fn test_dirichlet_with_param() {
        let alpha = 0.5f64;
        let size = 2;
        let d = Dirichlet::new_with_param(alpha, size);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_length() {
        Dirichlet::new_with_param(0.5f64, 1);
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_alpha() {
        Dirichlet::new_with_param(0.0f64, 2);
    }
}
<commit_msg>modifying to support stable version<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The dirichlet distribution.

use Rng;
use distributions::Distribution;
use distributions::gamma::Gamma;

/// The dirichelet distribution `Dirichlet(alpha)`.
///
/// The Dirichlet distribution } is a family of continuous multivariate probability distributions parameterized by
/// a vector alpha of positive reals
/// It is a multivariate generalization of the beta distribution.
///
/// # Example
///
/// ```
/// use rand::prelude::*;
/// use rand::distributions::Dirichlet;
///
/// let dirichlet = Dirichlet::new(&vec![1.0, 2.0, 3.0]);
/// let samples = dirichlet.sample(&mut rand::thread_rng());
/// println!("{:?} is from a Dirichlet([1.0, 2.0, 3.0]) distribution", samples);
/// ```

#[derive(Clone, Debug)]
pub struct Dirichlet {
    /// Concentration parameters (alpha)
    alpha: Vec<f64>,
}

impl Dirichlet {
    /// Construct a new `Dirichlet` with the given alpha parameter
    /// `alpha`. Panics if `alpha.len() < 2`.
    #[inline]
    pub fn new(alpha: &[f64]) -> Dirichlet {
        assert!(
            alpha.len() > 1,
            "Dirichlet::new called with `alpha` with length <  2"
        );
        for i in 0..alpha.len() {
            assert!(
                alpha[i] > 0.0,
                "Dirichlet::new called with `alpha`  <=  0.0"
            );
        }

        Dirichlet {
            alpha: alpha.to_vec(),
        }
    }

    /// Construct a new `Dirichlet` with the given shape parameter and size
    /// `alpha`. Panics if `alpha <= 0.0`.
    /// `size` . Panic if `size < 2`
    #[inline]
    pub fn new_with_param(alpha: f64, size: usize) -> Dirichlet {
        assert!(alpha > 0.0, "Dirichlet::new called with `alpha`  <=  0.0");
        assert!(size > 1, "Dirichlet::new called with `size`  <=  1");
        Dirichlet {
            alpha: vec![alpha; size],
        }
    }
}

impl Distribution<Vec<f64>> for Dirichlet {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec<f64> {
        let n = self.alpha.len();
        let mut samples = vec![0.0f64; n];
        let mut sum = 0.0f64;

        for i in 0..n {
            let g = Gamma::new(self.alpha[i], 1.0);
            samples[i] = g.sample(rng);
            sum += samples[i];
        }
        let invacc = 1.0 / sum;
        for i in 0..n {
            samples[i] *= invacc;
        }
        samples
    }
}

#[cfg(test)]
mod test {
    use super::Dirichlet;
    use distributions::Distribution;

    #[test]
    fn test_dirichlet() {
        let d = Dirichlet::new(&vec![1.0, 2.0, 3.0]);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    fn test_dirichlet_with_param() {
        let alpha = 0.5f64;
        let size = 2;
        let d = Dirichlet::new_with_param(alpha, size);
        let mut rng = ::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_length() {
        Dirichlet::new_with_param(0.5f64, 1);
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_alpha() {
        Dirichlet::new_with_param(0.0f64, 2);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Memory profiling functions.

use libc::{c_char,c_int,c_void,size_t};
use std::borrow::ToOwned;
use std::ffi::CString;
use std::old_io::timer::sleep;
#[cfg(target_os="linux")]
use std::old_io::File;
use std::mem;
use std::mem::size_of;
#[cfg(target_os="linux")]
use std::os::page_size;
use std::ptr::null_mut;
use std::sync::mpsc::{Sender, channel, Receiver};
use std::time::duration::Duration;
use task::spawn_named;
#[cfg(target_os="macos")]
use task_info::task_basic_info::{virtual_size,resident_size};

pub struct MemoryProfilerChan(pub Sender<MemoryProfilerMsg>);

impl MemoryProfilerChan {
    pub fn send(&self, msg: MemoryProfilerMsg) {
        let MemoryProfilerChan(ref c) = *self;
        c.send(msg).unwrap();
    }
}

pub enum MemoryProfilerMsg {
    /// Message used to force print the memory profiling metrics.
    Print,
    /// Tells the memory profiler to shut down.
    Exit,
}

pub struct MemoryProfiler {
    pub port: Receiver<MemoryProfilerMsg>,
}

impl MemoryProfiler {
    pub fn create(period: Option<f64>) -> MemoryProfilerChan {
        let (chan, port) = channel();
        match period {
            Some(period) => {
                let period = Duration::milliseconds((period * 1000f64) as i64);
                let chan = chan.clone();
                spawn_named("Memory profiler timer".to_owned(), move || {
                    loop {
                        sleep(period);
                        if chan.send(MemoryProfilerMsg::Print).is_err() {
                            break;
                        }
                    }
                });
                // Spawn the memory profiler.
                spawn_named("Memory profiler".to_owned(), move || {
                    let memory_profiler = MemoryProfiler::new(port);
                    memory_profiler.start();
                });
            }
            None => {
                // No-op to handle messages when the memory profiler is
                // inactive.
                spawn_named("Memory profiler".to_owned(), move || {
                    loop {
                        match port.recv() {
                            Err(_) | Ok(MemoryProfilerMsg::Exit) => break,
                            _ => {}
                        }
                    }
                });
            }
        }

        MemoryProfilerChan(chan)
    }

    pub fn new(port: Receiver<MemoryProfilerMsg>) -> MemoryProfiler {
        MemoryProfiler {
            port: port
        }
    }

    pub fn start(&self) {
        loop {
            match self.port.recv() {
               Ok(msg) => {
                   if !self.handle_msg(msg) {
                       break
                   }
               }
               _ => break
            }
        }
    }

    fn handle_msg(&self, msg: MemoryProfilerMsg) -> bool {
        match msg {
            MemoryProfilerMsg::Print => {
                self.handle_print_msg();
                true
            },
            MemoryProfilerMsg::Exit => false
        }
    }

    fn print_measurement(path: &str, nbytes: Option<u64>) {
        match nbytes {
            Some(nbytes) => {
                let mebi = 1024f64 * 1024f64;
                println!("{:24}: {:12.2}", path, (nbytes as f64) / mebi);
            }
            None => {
                println!("{:24}: {:>12}", path, "???");
            }
        }
    }

    fn handle_print_msg(&self) {
        println!("{:24}: {:12}", "_category_", "_size (MiB)_");

        // Virtual and physical memory usage, as reported by the OS.
        MemoryProfiler::print_measurement("vsize", get_vsize());
        MemoryProfiler::print_measurement("resident", get_resident());

        // Total number of bytes allocated by the application on the system
        // heap.
        MemoryProfiler::print_measurement("system-heap-allocated",
                                          get_system_heap_allocated());

        // The descriptions of the following jemalloc measurements are taken
        // directly from the jemalloc documentation.

        // "Total number of bytes allocated by the application."
        MemoryProfiler::print_measurement("jemalloc-heap-allocated",
                                          get_jemalloc_stat("stats.allocated"));

        // "Total number of bytes in active pages allocated by the application.
        // This is a multiple of the page size, and greater than or equal to
        // |stats.allocated|."
        MemoryProfiler::print_measurement("jemalloc-heap-active",
                                          get_jemalloc_stat("stats.active"));

        // "Total number of bytes in chunks mapped on behalf of the application.
        // This is a multiple of the chunk size, and is at least as large as
        // |stats.active|. This does not include inactive chunks."
        MemoryProfiler::print_measurement("jemalloc-heap-mapped",
                                          get_jemalloc_stat("stats.mapped"));

        println!("");
    }
}

#[cfg(target_os="linux")]
extern {
    fn mallinfo() -> struct_mallinfo;
}

#[cfg(target_os="linux")]
#[repr(C)]
pub struct struct_mallinfo {
    arena:    c_int,
    ordblks:  c_int,
    smblks:   c_int,
    hblks:    c_int,
    hblkhd:   c_int,
    usmblks:  c_int,
    fsmblks:  c_int,
    uordblks: c_int,
    fordblks: c_int,
    keepcost: c_int,
}

#[cfg(target_os="linux")]
fn get_system_heap_allocated() -> Option<u64> {
    let mut info: struct_mallinfo;
    unsafe {
        info = mallinfo();
    }
    // The documentation in the glibc man page makes it sound like |uordblks|
    // would suffice, but that only gets the small allocations that are put in
    // the brk heap. We need |hblkhd| as well to get the larger allocations
    // that are mmapped.
    Some((info.hblkhd + info.uordblks) as u64)
}

#[cfg(not(target_os="linux"))]
fn get_system_heap_allocated() -> Option<u64> {
    None
}

extern {
    fn je_mallctl(name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t,
                  newp: *mut c_void, newlen: size_t) -> c_int;
}

fn get_jemalloc_stat(name: &'static str) -> Option<u64> {
    let mut old: size_t = 0;
    let c_name = CString::from_slice(name.as_bytes());
    let oldp = &mut old as *mut _ as *mut c_void;
    let mut oldlen = size_of::<size_t>() as size_t;
    let rv: c_int;
    unsafe {
        rv = je_mallctl(c_name.as_ptr(), oldp, &mut oldlen, null_mut(), 0);
        mem::forget(c_name); // XXX correct?
    }
    if rv == 0 { Some(old as u64) } else { None }
}

// Like std::macros::try!, but for Option<>.
macro_rules! option_try(
    ($e:expr) => (match $e { Some(e) => e, None => return None })
);

#[cfg(target_os="linux")]
fn get_proc_self_statm_field(field: uint) -> Option<u64> {
    let mut f = File::open(&Path::new("/proc/self/statm"));
    match f.read_to_string() {
        Ok(contents) => {
            let s = option_try!(contents.as_slice().words().nth(field));
            let npages: u64 = option_try!(s.parse().ok());
            Some(npages * (page_size() as u64))
        }
        Err(_) => None
    }
}

#[cfg(target_os="linux")]
fn get_vsize() -> Option<u64> {
    get_proc_self_statm_field(0)
}

#[cfg(target_os="linux")]
fn get_resident() -> Option<u64> {
    get_proc_self_statm_field(1)
}

#[cfg(target_os="macos")]
fn get_vsize() -> Option<u64> {
    virtual_size()
}

#[cfg(target_os="macos")]
fn get_resident() -> Option<u64> {
    resident_size()
}

#[cfg(not(any(target_os="linux", target_os = "macos")))]
fn get_vsize() -> Option<u64> {
    None
}

#[cfg(not(any(target_os="linux", target_os = "macos")))]
fn get_resident() -> Option<u64> {
    None
}
<commit_msg>Fix jemalloc memory measurements.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Memory profiling functions.

use libc::{c_char,c_int,c_void,size_t};
use std::borrow::ToOwned;
use std::ffi::CString;
use std::old_io::timer::sleep;
#[cfg(target_os="linux")]
use std::old_io::File;
use std::mem;
use std::mem::size_of;
#[cfg(target_os="linux")]
use std::os::page_size;
use std::ptr::null_mut;
use std::sync::mpsc::{Sender, channel, Receiver};
use std::time::duration::Duration;
use task::spawn_named;
#[cfg(target_os="macos")]
use task_info::task_basic_info::{virtual_size,resident_size};

pub struct MemoryProfilerChan(pub Sender<MemoryProfilerMsg>);

impl MemoryProfilerChan {
    pub fn send(&self, msg: MemoryProfilerMsg) {
        let MemoryProfilerChan(ref c) = *self;
        c.send(msg).unwrap();
    }
}

pub enum MemoryProfilerMsg {
    /// Message used to force print the memory profiling metrics.
    Print,
    /// Tells the memory profiler to shut down.
    Exit,
}

pub struct MemoryProfiler {
    pub port: Receiver<MemoryProfilerMsg>,
}

impl MemoryProfiler {
    pub fn create(period: Option<f64>) -> MemoryProfilerChan {
        let (chan, port) = channel();
        match period {
            Some(period) => {
                let period = Duration::milliseconds((period * 1000f64) as i64);
                let chan = chan.clone();
                spawn_named("Memory profiler timer".to_owned(), move || {
                    loop {
                        sleep(period);
                        if chan.send(MemoryProfilerMsg::Print).is_err() {
                            break;
                        }
                    }
                });
                // Spawn the memory profiler.
                spawn_named("Memory profiler".to_owned(), move || {
                    let memory_profiler = MemoryProfiler::new(port);
                    memory_profiler.start();
                });
            }
            None => {
                // No-op to handle messages when the memory profiler is
                // inactive.
                spawn_named("Memory profiler".to_owned(), move || {
                    loop {
                        match port.recv() {
                            Err(_) | Ok(MemoryProfilerMsg::Exit) => break,
                            _ => {}
                        }
                    }
                });
            }
        }

        MemoryProfilerChan(chan)
    }

    pub fn new(port: Receiver<MemoryProfilerMsg>) -> MemoryProfiler {
        MemoryProfiler {
            port: port
        }
    }

    pub fn start(&self) {
        loop {
            match self.port.recv() {
               Ok(msg) => {
                   if !self.handle_msg(msg) {
                       break
                   }
               }
               _ => break
            }
        }
    }

    fn handle_msg(&self, msg: MemoryProfilerMsg) -> bool {
        match msg {
            MemoryProfilerMsg::Print => {
                self.handle_print_msg();
                true
            },
            MemoryProfilerMsg::Exit => false
        }
    }

    fn print_measurement(path: &str, nbytes: Option<u64>) {
        match nbytes {
            Some(nbytes) => {
                let mebi = 1024f64 * 1024f64;
                println!("{:24}: {:12.2}", path, (nbytes as f64) / mebi);
            }
            None => {
                println!("{:24}: {:>12}", path, "???");
            }
        }
    }

    fn handle_print_msg(&self) {
        println!("{:24}: {:12}", "_category_", "_size (MiB)_");

        // Virtual and physical memory usage, as reported by the OS.
        MemoryProfiler::print_measurement("vsize", get_vsize());
        MemoryProfiler::print_measurement("resident", get_resident());

        // Total number of bytes allocated by the application on the system
        // heap.
        MemoryProfiler::print_measurement("system-heap-allocated",
                                          get_system_heap_allocated());

        // The descriptions of the following jemalloc measurements are taken
        // directly from the jemalloc documentation.

        // "Total number of bytes allocated by the application."
        MemoryProfiler::print_measurement("jemalloc-heap-allocated",
                                          get_jemalloc_stat("stats.allocated"));

        // "Total number of bytes in active pages allocated by the application.
        // This is a multiple of the page size, and greater than or equal to
        // |stats.allocated|."
        MemoryProfiler::print_measurement("jemalloc-heap-active",
                                          get_jemalloc_stat("stats.active"));

        // "Total number of bytes in chunks mapped on behalf of the application.
        // This is a multiple of the chunk size, and is at least as large as
        // |stats.active|. This does not include inactive chunks."
        MemoryProfiler::print_measurement("jemalloc-heap-mapped",
                                          get_jemalloc_stat("stats.mapped"));

        println!("");
    }
}

#[cfg(target_os="linux")]
extern {
    fn mallinfo() -> struct_mallinfo;
}

#[cfg(target_os="linux")]
#[repr(C)]
pub struct struct_mallinfo {
    arena:    c_int,
    ordblks:  c_int,
    smblks:   c_int,
    hblks:    c_int,
    hblkhd:   c_int,
    usmblks:  c_int,
    fsmblks:  c_int,
    uordblks: c_int,
    fordblks: c_int,
    keepcost: c_int,
}

#[cfg(target_os="linux")]
fn get_system_heap_allocated() -> Option<u64> {
    let mut info: struct_mallinfo;
    unsafe {
        info = mallinfo();
    }
    // The documentation in the glibc man page makes it sound like |uordblks|
    // would suffice, but that only gets the small allocations that are put in
    // the brk heap. We need |hblkhd| as well to get the larger allocations
    // that are mmapped.
    Some((info.hblkhd + info.uordblks) as u64)
}

#[cfg(not(target_os="linux"))]
fn get_system_heap_allocated() -> Option<u64> {
    None
}

extern {
    fn je_mallctl(name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t,
                  newp: *mut c_void, newlen: size_t) -> c_int;
}

fn get_jemalloc_stat(value_name: &str) -> Option<u64> {
    // Before we request the measurement of interest, we first send an "epoch"
    // request. Without that jemalloc gives cached statistics(!) which can be
    // highly inaccurate.
    let epoch_name = "epoch";
    let epoch_c_name = CString::from_slice(epoch_name.as_bytes());
    let mut epoch: u64 = 0;
    let epoch_ptr = &mut epoch as *mut _ as *mut c_void;
    let mut epoch_len = size_of::<u64>() as size_t;

    let value_c_name = CString::from_slice(value_name.as_bytes());
    let mut value: size_t = 0;
    let value_ptr = &mut value as *mut _ as *mut c_void;
    let mut value_len = size_of::<size_t>() as size_t;

    let mut rv: c_int;
    unsafe {
        // Using the same values for the `old` and `new` parameters is enough
        // to get the statistics updated.
        rv = je_mallctl(epoch_c_name.as_ptr(), epoch_ptr, &mut epoch_len, epoch_ptr, epoch_len);
        if rv == 0 {
            rv = je_mallctl(value_c_name.as_ptr(), value_ptr, &mut value_len, null_mut(), 0);
        }
    }
    if rv == 0 { Some(value as u64) } else { None }
}

// Like std::macros::try!, but for Option<>.
macro_rules! option_try(
    ($e:expr) => (match $e { Some(e) => e, None => return None })
);

#[cfg(target_os="linux")]
fn get_proc_self_statm_field(field: uint) -> Option<u64> {
    let mut f = File::open(&Path::new("/proc/self/statm"));
    match f.read_to_string() {
        Ok(contents) => {
            let s = option_try!(contents.as_slice().words().nth(field));
            let npages: u64 = option_try!(s.parse().ok());
            Some(npages * (page_size() as u64))
        }
        Err(_) => None
    }
}

#[cfg(target_os="linux")]
fn get_vsize() -> Option<u64> {
    get_proc_self_statm_field(0)
}

#[cfg(target_os="linux")]
fn get_resident() -> Option<u64> {
    get_proc_self_statm_field(1)
}

#[cfg(target_os="macos")]
fn get_vsize() -> Option<u64> {
    virtual_size()
}

#[cfg(target_os="macos")]
fn get_resident() -> Option<u64> {
    resident_size()
}

#[cfg(not(any(target_os="linux", target_os = "macos")))]
fn get_vsize() -> Option<u64> {
    None
}

#[cfg(not(any(target_os="linux", target_os = "macos")))]
fn get_resident() -> Option<u64> {
    None
}
<|endoftext|>


<commit_before>#![cfg(test)]
use crate::per_block_processing;
use super::block_processing_builder::BlockProcessingBuilder;
use types::*;

pub const VALIDATOR_COUNT: usize = 10;

#[test]
fn runs_without_error() {
    let spec = ChainSpec::foundation();
    let mut builder = BlockProcessingBuilder::new(VALIDATOR_COUNT, &spec);

    // Set the state and block to be in the last slot of the 4th epoch.
    let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    builder.set_slot(last_slot_of_epoch, &spec);

    builder.build_caches(&spec);

    let (block, mut state) = builder.build(&spec);

    per_block_processing(&mut state, &block, &spec).unwrap();
}

//  process_block_header
//      Invalid::StateSlotMismatch
//      Invalid::ParentBlockRootMismatch

//  verify_block_signature
//      Invalid::BadSignature

//  process_randao
//      Invalid::BadRandaoSignature

//  process_proposer_slashings
//      Invalid::MaxProposerSlashingsExceeded
//      verify_proposer_slashing
//          Invalid::ProposerUnknown
//          Invalid::ProposalSlotMismatch
//          Invalid::ProposalsIdentical
//          Invalid::ProposerAlreadySlashed
//          Invalid::ProposerAlreadyWithdrawn
//          Invalid::BadProposal1Signature
//          Invalid::BadProposal2Signature

//  process_attester_slashings
//      Invalid::MaxAttesterSlashingsExceed
//      verify_attester_slashing
//          Invalid::AttestationDataIdentical
//          Invalid::NotSlashable
//          Invalid::SlashableAttestation1Invalid
//          Invalid::SlashableAttestation2Invalid

//  process_attestations
//      Invalid::MaxAttestationsExceeded
//      validate_attestation
//          Invalid::PreGenesis
//          Invalid::IncludedTooLate
//          Invalid::IncludedTooEarly
//          Invalid::BadPreviousCrosslink
//          Invalid::AggregationBitfieldIsEmpty
//          Invalid::CustodyBitfieldHasSetBits
//          Invalid::NoCommitteeForShard
//          Invalid::BadCustodyBitfieldLength
//          Invalid::BadAggregationBitfieldLength
//          Invalid::ShardBlockRootNotZero
//          verify_justified_epoch_and_root
//              Invalid::WrongJustifiedEpoch (current)
//              Invalid::WrongJustifiedRoot (current)
//              Invalid::WrongJustifiedEpoch (previous)
//              Invalid::WrongJustifiedRoot (previous)
//          verify_attestation_signature
//              Invalid::BadAggregationBitfieldLength
//              Invalid::BadCustodyBitfieldLength
//              BeaconStateError::UnknownValidator
//              Invalid::BadSignature

//  process_deposits
//      Invalid::MaxDepositsExceeded
//      verify_deposit
//          Invalid::BadProofOfPossession
//          Invalid::BadMerkleProof
//      verify_deposit_index
//          Invalid::BadIndex

//  process_exits
//      Invalid::MaxExitsExceeded
//      verify_exit
//          Invalid::ValidatorUnknown
//          Invalid::AlreadyExited
//          Invalid::AlreadyInitiatedExited
//          Invalid::FutureEpoch
//          Invalid::TooYoungToLeave
//          Invalid::BadSignature

//  process_transfers
//      Invalid::MaxTransfersExceed
//      verify_transfer
//          Invalid::FromValidatorUnknown
//          Invalid::FeeOverflow
//          Invalid::FromBalanceInsufficient (amount)
//          Invalid::FromBalanceInsufficient (fee)
//          Invalid::InvalidResultingFromBalance
//          Invalid::TransferSlotInPast
//          Invalid::StateSlotMismatch
//          Invalid::FromValidatorUnknown (???)
//          Invalid::FromValidatorIneligableForTransfer
//          Invalid::WithdrawalCredentialsMismatch
//          Invalid::BadSignature

<commit_msg>process_block_header tests<commit_after>#![cfg(test)]
use crate::per_block_processing;
use super::block_processing_builder::BlockProcessingBuilder;
use super::errors::*;
use types::*;

pub const VALIDATOR_COUNT: usize = 10;

#[test]
fn runs_without_error() {
    let spec = ChainSpec::foundation();
    let (block, mut state) = get_block_state(&spec);

    per_block_processing(&mut state, &block, &spec).unwrap();
}

#[test]
fn process_block_header_invalid_state_slot() {
    let spec = ChainSpec::foundation();
    let (mut block, mut state) = get_block_state(&spec);

    state.slot = Slot::new(133713);
    block.slot = Slot::new(424242);

    let result = per_block_processing(&mut state, &block, &spec);

    assert_eq!(result, Err(BlockProcessingError::Invalid(BlockInvalid::StateSlotMismatch)));
}

#[test]
#[ignore]
fn process_block_header_invalid_parent_block_root() {
    // this will be changed in spec 0.5.1 to use signed root
}

fn get_block_state(spec: &ChainSpec) -> (BeaconBlock, BeaconState) {
    let mut builder = BlockProcessingBuilder::new(VALIDATOR_COUNT, &spec);

    // Set the state and block to be in the last slot of the 4th epoch.
    let last_slot_of_epoch = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    builder.set_slot(last_slot_of_epoch, &spec);
    builder.build_caches(&spec);

    let (block, state) = builder.build(&spec);

    (block, state)
}

//  verify_block_signature
//      Invalid::BadSignature

//  process_randao
//      Invalid::BadRandaoSignature

//  process_proposer_slashings
//      Invalid::MaxProposerSlashingsExceeded
//      verify_proposer_slashing
//          Invalid::ProposerUnknown
//          Invalid::ProposalSlotMismatch
//          Invalid::ProposalsIdentical
//          Invalid::ProposerAlreadySlashed
//          Invalid::ProposerAlreadyWithdrawn
//          Invalid::BadProposal1Signature
//          Invalid::BadProposal2Signature

//  process_attester_slashings
//      Invalid::MaxAttesterSlashingsExceed
//      verify_attester_slashing
//          Invalid::AttestationDataIdentical
//          Invalid::NotSlashable
//          Invalid::SlashableAttestation1Invalid
//          Invalid::SlashableAttestation2Invalid

//  process_attestations
//      Invalid::MaxAttestationsExceeded
//      validate_attestation
//          Invalid::PreGenesis
//          Invalid::IncludedTooLate
//          Invalid::IncludedTooEarly
//          Invalid::BadPreviousCrosslink
//          Invalid::AggregationBitfieldIsEmpty
//          Invalid::CustodyBitfieldHasSetBits
//          Invalid::NoCommitteeForShard
//          Invalid::BadCustodyBitfieldLength
//          Invalid::BadAggregationBitfieldLength
//          Invalid::ShardBlockRootNotZero
//          verify_justified_epoch_and_root
//              Invalid::WrongJustifiedEpoch (current)
//              Invalid::WrongJustifiedRoot (current)
//              Invalid::WrongJustifiedEpoch (previous)
//              Invalid::WrongJustifiedRoot (previous)
//          verify_attestation_signature
//              Invalid::BadAggregationBitfieldLength
//              Invalid::BadCustodyBitfieldLength
//              BeaconStateError::UnknownValidator
//              Invalid::BadSignature

//  process_deposits
//      Invalid::MaxDepositsExceeded
//      verify_deposit
//          Invalid::BadProofOfPossession
//          Invalid::BadMerkleProof
//      verify_deposit_index
//          Invalid::BadIndex

//  process_exits
//      Invalid::MaxExitsExceeded
//      verify_exit
//          Invalid::ValidatorUnknown
//          Invalid::AlreadyExited
//          Invalid::AlreadyInitiatedExited
//          Invalid::FutureEpoch
//          Invalid::TooYoungToLeave
//          Invalid::BadSignature

//  process_transfers
//      Invalid::MaxTransfersExceed
//      verify_transfer
//          Invalid::FromValidatorUnknown
//          Invalid::FeeOverflow
//          Invalid::FromBalanceInsufficient (amount)
//          Invalid::FromBalanceInsufficient (fee)
//          Invalid::InvalidResultingFromBalance
//          Invalid::TransferSlotInPast
//          Invalid::StateSlotMismatch
//          Invalid::FromValidatorUnknown (???)
//          Invalid::FromValidatorIneligableForTransfer
//          Invalid::WithdrawalCredentialsMismatch
//          Invalid::BadSignature

<|endoftext|>