<commit_before>extern crate piston_window;

extern crate turtleide;

use canvas::{TurtleCanvas, Command, Radians};

fn main() {
    let canvas = TurtleCanvas::new();

    let dashed = false;
    for i in 0..361 {
        if dashed {
            canvas.apply(Command::Pen {
                enabled: i % 2 == 0,
            });
        }
        canvas.apply(Command::Move {
            distance: 10.,
        });
        canvas.apply(Command::Rotate {
            angle: Radians(1f64.to_radians()),
            clockwise: true,
        });
    }
}

mod canvas {
    use std::thread;
    use std::process;
    use std::time::{Instant, Duration};
    use std::sync::mpsc::{self, TryRecvError};
    use std::ops::{Add, Mul};

    use piston_window::*;

    use turtleide::Speed;

    #[derive(Default, Clone, Copy, Debug, PartialOrd, PartialEq)]
    pub struct Radians(pub f64);

    impl Radians {
        pub fn cos(self) -> f64 {
            self.0.cos()
        }

        pub fn sin(self) -> f64 {
            self.0.sin()
        }
    }

    impl Add for Radians {
        type Output = Self;

        fn add(self, other: Self) -> Self {
            Radians(self.0 + other.0)
        }
    }

    impl Mul<f64> for Radians {
        type Output = Self;

        fn mul(self, other: f64) -> Self {
            Radians(self.0 * other)
        }
    }

    trait ToCanvasCoordinates : Copy {
        fn to_canvas_coords(self, center: [f64; 2]) -> Self;
    }

    impl ToCanvasCoordinates for [f64; 2] {
        /// Transforms the given local coordinate into a point that can be drawn on the canvas.
        ///
        /// Takes into account the direction of the axis and center when converting
        /// `local` from cartesian coordinates.
        ///
        /// Origin in window is the top left corner and the y-axis goes down instead of up.
        fn to_canvas_coords(self, center: [f64; 2]) -> [f64; 2] {
            [center[0] + self[0], center[1] - self[1]]
        }
    }

    trait AsMillis {
        fn as_millis(&self) -> u64;
    }

    impl AsMillis for Duration {
        fn as_millis(&self) -> u64 {
            self.as_secs() * 1000 + (self.subsec_nanos() / 1_000_000) as u64
        }
    }

    pub enum Command {
        Move {
            distance: f64,
        },
        Rotate {
            angle: Radians,
            clockwise: bool,
        },
        Pen {
            enabled: bool,
        },
    }

    #[derive(Debug, Clone, Copy)]
    pub enum Color {
        Black,
        White,
        Transparent,
    }

    impl From<Color> for types::Color {
        fn from(color: Color) -> Self {
            match color {
                Color::Black => [0., 0., 0., 255.],
                Color::White => [255., 255., 255., 255.],
                Color::Transparent => [0., 0., 0., 0.],
            }
        }
    }

    #[derive(Debug, Clone)]
    struct Path {
        start: [f64; 2],
        end: [f64; 2],
        pen: Pen,
    }

    type Response = Result<(), ()>;

    struct TurtleState {
        pub position: [f64; 2],
        pub heading: Radians,
        pub speed: Speed,
    }

    impl Default for TurtleState {
        fn default() -> TurtleState {
            TurtleState {
                position: Default::default(),
                heading: Radians(90f64.to_radians()),
                speed: Speed::Five,
            }
        }
    }

    struct DrawingState {
        pen: Pen,
        //pub background: Color,
    }

    #[derive(Debug, Clone)]
    struct Pen {
        pub enabled: bool,
        pub thickness: f64,
        pub color: Color,
    }

    struct Animation {
        kind: AnimationKind,
        speed: Speed,
        start: Instant,
    }

    enum AnimationKind {
        Move {
            path: Path,
        },
        Rotation {
            target_angle: Radians,
            clockwise: bool,
        },
    }

    pub struct TurtleCanvas {
        thread_handle: Option<thread::JoinHandle<()>>,
        transmitter: mpsc::Sender<Command>,
        receiver: mpsc::Receiver<Response>,
    }

    impl TurtleCanvas {
        pub fn new() -> TurtleCanvas {
            let (drawing_tx, drawing_rx) = mpsc::channel();
            let (main_tx, main_rx) = mpsc::channel();

            let handle = thread::spawn(move || {
                let mut window: PistonWindow = WindowSettings::new(
                    "Turtle IDE", [800, 600]
                ).exit_on_esc(true).build().unwrap();
                let mut paths: Vec<Path> = Vec::new();
                let mut animation: Option<Animation> = None;
                let mut turtle = TurtleState::default();
                let mut drawing = DrawingState {
                    pen: Pen {
                        enabled: true,
                        thickness: 1.,
                        color: Color::Black,
                    },
                };

                while let Some(e) = window.next() {
                    match drawing_rx.try_recv() {
                        Ok(command) => {
                            if animation.is_some() {
                                unreachable!("The main thread did not wait for the animation to complete before sending another command")
                            }
                            match command {
                                Command::Move {distance} => {
                                    if distance != 0. {
                                        let start = turtle.position;
                                        let x = distance * turtle.heading.cos();
                                        let y = distance * turtle.heading.sin();
                                        let end = math::add(start, [x, y]);
                                        animation = Some(Animation {
                                            kind: AnimationKind::Move {
                                                path: Path {
                                                    start, end,
                                                    pen: drawing.pen.clone(),
                                                },
                                            },
                                            speed: turtle.speed,
                                            start: Instant::now(),
                                        });
                                    }
                                },
                                Command::Rotate {angle, clockwise} => {
                                    animation = Some(Animation {
                                        kind: AnimationKind::Rotation {
                                            target_angle: turtle.heading + angle,
                                            clockwise,
                                        },
                                        speed: turtle.speed,
                                        start: Instant::now(),
                                    });
                                },
                                Command::Pen {enabled} => {
                                    drawing.pen.enabled = enabled;
                                    main_tx.send(Ok(())).unwrap();
                                },
                            }
                        },
                        Err(TryRecvError::Empty) => {}, // Do nothing
                        Err(TryRecvError::Disconnected) => break, // Quit
                    }

                    window.draw_2d(&e, |c, g| {
                        clear([1.0; 4], g);

                        let view = c.get_view_size();
                        let width = view[0] as f64;
                        let height = view[1] as f64;
                        let center = [width * 0.5, height * 0.5];

                        let mut animation_complete = false;
                        if let Some(Animation {ref kind, ref speed, ref start}) = animation {
                            let elapsed = start.elapsed().as_millis() as f64;

                            match *kind {
                                AnimationKind::Move {ref path} => {
                                    // This code finds the point on the line between start and
                                    // end that we are supposed to be at right now using some
                                    // vector math.
                                    //
                                    // The basic idea is to find the vector that represents the
                                    // line between start and end, normalize it into a direction,
                                    // and then scale that vector to be the size that it should be
                                    // at the elapsed time based on the speed.
                                    let &Path {start, end, ref pen} = path;
                                    let speed = speed.to_absolute(); // px per second
                                    let path_line = math::sub(start, end);
                                    let path_length = math::square_len(path_line).sqrt();
                                    let direction = math::mul_scalar(path_line, 1./path_length);
                                    debug_assert_eq!(math::square_len(direction).sqrt(), 1.);
                                    // (px / sec) * (sec / 1000ms) * ms => px
                                    let offset = math::mul_scalar(direction, speed / 1000. * elapsed);
                                    let offset_length = math::square_len(offset).sqrt();

                                    let current = if offset_length >= path_length {
                                        paths.push(path.clone());
                                        animation_complete = true;
                                        end
                                    }
                                    else {
                                        math::add(start, offset)
                                    };

                                    turtle.position = current;

                                    let &Pen {thickness, color, enabled} = pen;
                                    if enabled {
                                        let start = start.to_canvas_coords(center);
                                        let current = current.to_canvas_coords(center);

                                        line(color.into(), thickness,
                                            [start[0], start[1], current[0], current[1]],
                                            c.transform, g);
                                    }
                                },
                                AnimationKind::Rotation {target_angle, clockwise} => {
                                    // TODO: Use the returned value in Radians and impl Div for Radians
                                    let speed = speed.to_rotation();
                                    animation_complete = true;
                                },
                            }
                        }
                        if animation_complete {
                            animation = None;
                            main_tx.send(Ok(())).unwrap();
                        }

                        for path in &paths {
                            if !path.pen.enabled {
                                continue;
                            }

                            let Path {start, end, ref pen} = *path;
                            let start = start.to_canvas_coords(center);
                            let end = end.to_canvas_coords(center);

                            line(pen.color.into(), pen.thickness,
                                [start[0], start[1], end[0], end[1]],
                                c.transform, g);
                        }

                        // Draw the turtle's shell
                        let cos = turtle.heading.cos();
                        let sin = turtle.heading.sin();
                        let turtle_x = turtle.position[0];
                        let turtle_y = turtle.position[1];
                        let shell: Vec<_> = [
                            [0., 15.],
                            [10., 0.],
                            [0., -15.],
                        ].into_iter().map(|pt| {
                            // Rotate each point by the heading and add the current turtle position
                            let x = cos * pt[0] - sin * pt[1] + turtle_x;
                            let y = sin * pt[0] + cos * pt[1] + turtle_y;
                            [x, y].to_canvas_coords(center)
                        }).collect();

                        polygon(Color::White.into(), &shell, c.transform, g);
                        for i in 0..shell.len() {
                            let start = shell[i];
                            let end = shell[(i + 1) % shell.len()];

                            line(Color::Black.into(), 1.,
                                [start[0], start[1], end[0], end[1]],
                                c.transform, g);
                        }
                    });
                }
            });

            Self {
                thread_handle: Some(handle),
                transmitter: drawing_tx,
                receiver: main_rx,
            }
        }

        pub fn apply(&self, command: Command) {
            let result = self.transmitter.send(command).map_err(|_| ());
            let result = result.and_then(|_| {
                // Wait for the drawing animation to complete
                self.receiver.recv().map_err(|_| ())
            });
            match result {
                Ok(_) => {},
                Err(_) => {
                    // The connection has been closed so the window was closed
                    // or an error occurred on that thread
                    process::exit(0);
                },
            }
        }
    }

    impl Drop for TurtleCanvas {
        fn drop(&mut self) {
            if let Some(handle) = self.thread_handle.take() {
                handle.join().unwrap();
            }
        }
    }
}
<commit_msg>Changed the speed to Instant since none of the others work right now<commit_after>extern crate piston_window;

extern crate turtleide;

use canvas::{TurtleCanvas, Command, Radians};

fn main() {
    let canvas = TurtleCanvas::new();

    let dashed = false;
    for i in 0..361 {
        if dashed {
            canvas.apply(Command::Pen {
                enabled: i % 2 == 0,
            });
        }
        canvas.apply(Command::Move {
            distance: 10.,
        });
        canvas.apply(Command::Rotate {
            angle: Radians(1f64.to_radians()),
            clockwise: true,
        });
    }
}

mod canvas {
    use std::thread;
    use std::process;
    use std::time::{Instant, Duration};
    use std::sync::mpsc::{self, TryRecvError};
    use std::ops::{Add, Mul};

    use piston_window::*;

    use turtleide::Speed;

    #[derive(Default, Clone, Copy, Debug, PartialOrd, PartialEq)]
    pub struct Radians(pub f64);

    impl Radians {
        pub fn cos(self) -> f64 {
            self.0.cos()
        }

        pub fn sin(self) -> f64 {
            self.0.sin()
        }
    }

    impl Add for Radians {
        type Output = Self;

        fn add(self, other: Self) -> Self {
            Radians(self.0 + other.0)
        }
    }

    impl Mul<f64> for Radians {
        type Output = Self;

        fn mul(self, other: f64) -> Self {
            Radians(self.0 * other)
        }
    }

    trait ToCanvasCoordinates : Copy {
        fn to_canvas_coords(self, center: [f64; 2]) -> Self;
    }

    impl ToCanvasCoordinates for [f64; 2] {
        /// Transforms the given local coordinate into a point that can be drawn on the canvas.
        ///
        /// Takes into account the direction of the axis and center when converting
        /// `local` from cartesian coordinates.
        ///
        /// Origin in window is the top left corner and the y-axis goes down instead of up.
        fn to_canvas_coords(self, center: [f64; 2]) -> [f64; 2] {
            [center[0] + self[0], center[1] - self[1]]
        }
    }

    trait AsMillis {
        fn as_millis(&self) -> u64;
    }

    impl AsMillis for Duration {
        fn as_millis(&self) -> u64 {
            self.as_secs() * 1000 + (self.subsec_nanos() / 1_000_000) as u64
        }
    }

    pub enum Command {
        Move {
            distance: f64,
        },
        Rotate {
            angle: Radians,
            clockwise: bool,
        },
        Pen {
            enabled: bool,
        },
    }

    #[derive(Debug, Clone, Copy)]
    pub enum Color {
        Black,
        White,
        Transparent,
    }

    impl From<Color> for types::Color {
        fn from(color: Color) -> Self {
            match color {
                Color::Black => [0., 0., 0., 255.],
                Color::White => [255., 255., 255., 255.],
                Color::Transparent => [0., 0., 0., 0.],
            }
        }
    }

    #[derive(Debug, Clone)]
    struct Path {
        start: [f64; 2],
        end: [f64; 2],
        pen: Pen,
    }

    type Response = Result<(), ()>;

    struct TurtleState {
        pub position: [f64; 2],
        pub heading: Radians,
        pub speed: Speed,
    }

    impl Default for TurtleState {
        fn default() -> TurtleState {
            TurtleState {
                position: Default::default(),
                heading: Radians(90f64.to_radians()),
                speed: Speed::Instant,
            }
        }
    }

    struct DrawingState {
        pen: Pen,
        //pub background: Color,
    }

    #[derive(Debug, Clone)]
    struct Pen {
        pub enabled: bool,
        pub thickness: f64,
        pub color: Color,
    }

    struct Animation {
        kind: AnimationKind,
        speed: Speed,
        start: Instant,
    }

    enum AnimationKind {
        Move {
            path: Path,
        },
        Rotation {
            target_angle: Radians,
            clockwise: bool,
        },
    }

    pub struct TurtleCanvas {
        thread_handle: Option<thread::JoinHandle<()>>,
        transmitter: mpsc::Sender<Command>,
        receiver: mpsc::Receiver<Response>,
    }

    impl TurtleCanvas {
        pub fn new() -> TurtleCanvas {
            let (drawing_tx, drawing_rx) = mpsc::channel();
            let (main_tx, main_rx) = mpsc::channel();

            let handle = thread::spawn(move || {
                let mut window: PistonWindow = WindowSettings::new(
                    "Turtle IDE", [800, 600]
                ).exit_on_esc(true).build().unwrap();
                let mut paths: Vec<Path> = Vec::new();
                let mut animation: Option<Animation> = None;
                let mut turtle = TurtleState::default();
                let mut drawing = DrawingState {
                    pen: Pen {
                        enabled: true,
                        thickness: 1.,
                        color: Color::Black,
                    },
                };

                while let Some(e) = window.next() {
                    match drawing_rx.try_recv() {
                        Ok(command) => {
                            if animation.is_some() {
                                unreachable!("The main thread did not wait for the animation to complete before sending another command")
                            }
                            match command {
                                Command::Move {distance} => {
                                    if distance != 0. {
                                        let start = turtle.position;
                                        let x = distance * turtle.heading.cos();
                                        let y = distance * turtle.heading.sin();
                                        let end = math::add(start, [x, y]);
                                        animation = Some(Animation {
                                            kind: AnimationKind::Move {
                                                path: Path {
                                                    start, end,
                                                    pen: drawing.pen.clone(),
                                                },
                                            },
                                            speed: turtle.speed,
                                            start: Instant::now(),
                                        });
                                    }
                                },
                                Command::Rotate {angle, clockwise} => {
                                    animation = Some(Animation {
                                        kind: AnimationKind::Rotation {
                                            target_angle: turtle.heading + angle,
                                            clockwise,
                                        },
                                        speed: turtle.speed,
                                        start: Instant::now(),
                                    });
                                },
                                Command::Pen {enabled} => {
                                    drawing.pen.enabled = enabled;
                                    main_tx.send(Ok(())).unwrap();
                                },
                            }
                        },
                        Err(TryRecvError::Empty) => {}, // Do nothing
                        Err(TryRecvError::Disconnected) => break, // Quit
                    }

                    window.draw_2d(&e, |c, g| {
                        clear([1.0; 4], g);

                        let view = c.get_view_size();
                        let width = view[0] as f64;
                        let height = view[1] as f64;
                        let center = [width * 0.5, height * 0.5];

                        let mut animation_complete = false;
                        if let Some(Animation {ref kind, ref speed, ref start}) = animation {
                            let elapsed = start.elapsed().as_millis() as f64;

                            match *kind {
                                AnimationKind::Move {ref path} => {
                                    // This code finds the point on the line between start and
                                    // end that we are supposed to be at right now using some
                                    // vector math.
                                    //
                                    // The basic idea is to find the vector that represents the
                                    // line between start and end, normalize it into a direction,
                                    // and then scale that vector to be the size that it should be
                                    // at the elapsed time based on the speed.
                                    let &Path {start, end, ref pen} = path;
                                    let speed = speed.to_absolute(); // px per second
                                    let path_line = math::sub(start, end);
                                    let path_length = math::square_len(path_line).sqrt();
                                    let direction = math::mul_scalar(path_line, 1./path_length);
                                    debug_assert_eq!(math::square_len(direction).sqrt(), 1.);
                                    // (px / sec) * (sec / 1000ms) * ms => px
                                    let offset = math::mul_scalar(direction, speed / 1000. * elapsed);
                                    let offset_length = math::square_len(offset).sqrt();

                                    let current = if offset_length >= path_length {
                                        paths.push(path.clone());
                                        animation_complete = true;
                                        end
                                    }
                                    else {
                                        math::add(start, offset)
                                    };

                                    turtle.position = current;

                                    let &Pen {thickness, color, enabled} = pen;
                                    if enabled {
                                        let start = start.to_canvas_coords(center);
                                        let current = current.to_canvas_coords(center);

                                        line(color.into(), thickness,
                                            [start[0], start[1], current[0], current[1]],
                                            c.transform, g);
                                    }
                                },
                                AnimationKind::Rotation {target_angle, clockwise} => {
                                    // TODO: Use the returned value in Radians and impl Div for Radians
                                    let speed = speed.to_rotation();
                                    animation_complete = true;
                                },
                            }
                        }
                        if animation_complete {
                            animation = None;
                            main_tx.send(Ok(())).unwrap();
                        }

                        for path in &paths {
                            if !path.pen.enabled {
                                continue;
                            }

                            let Path {start, end, ref pen} = *path;
                            let start = start.to_canvas_coords(center);
                            let end = end.to_canvas_coords(center);

                            line(pen.color.into(), pen.thickness,
                                [start[0], start[1], end[0], end[1]],
                                c.transform, g);
                        }

                        // Draw the turtle's shell
                        let cos = turtle.heading.cos();
                        let sin = turtle.heading.sin();
                        let turtle_x = turtle.position[0];
                        let turtle_y = turtle.position[1];
                        let shell: Vec<_> = [
                            [0., 15.],
                            [10., 0.],
                            [0., -15.],
                        ].into_iter().map(|pt| {
                            // Rotate each point by the heading and add the current turtle position
                            let x = cos * pt[0] - sin * pt[1] + turtle_x;
                            let y = sin * pt[0] + cos * pt[1] + turtle_y;
                            [x, y].to_canvas_coords(center)
                        }).collect();

                        polygon(Color::White.into(), &shell, c.transform, g);
                        for i in 0..shell.len() {
                            let start = shell[i];
                            let end = shell[(i + 1) % shell.len()];

                            line(Color::Black.into(), 1.,
                                [start[0], start[1], end[0], end[1]],
                                c.transform, g);
                        }
                    });
                }
            });

            Self {
                thread_handle: Some(handle),
                transmitter: drawing_tx,
                receiver: main_rx,
            }
        }

        pub fn apply(&self, command: Command) {
            let result = self.transmitter.send(command).map_err(|_| ());
            let result = result.and_then(|_| {
                // Wait for the drawing animation to complete
                self.receiver.recv().map_err(|_| ())
            });
            match result {
                Ok(_) => {},
                Err(_) => {
                    // The connection has been closed so the window was closed
                    // or an error occurred on that thread
                    process::exit(0);
                },
            }
        }
    }

    impl Drop for TurtleCanvas {
        fn drop(&mut self) {
            if let Some(handle) = self.thread_handle.take() {
                handle.join().unwrap();
            }
        }
    }
}
<|endoftext|>


<commit_before>use clap::{arg, Arg, ArgAction, Command};

#[cfg(feature = "error-context")]
use super::utils;

#[test]
fn flag_using_short() {
    let m = Command::new("flag")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "-f", "-c"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
}

#[test]
fn lots_o_flags_sep() {
    let r = Command::new("opts")
        .args_override_self(true)
        .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue))
        .try_get_matches_from(vec![
            "", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
    let m = r.unwrap();
    assert!(m.contains_id("o"));
    assert!(*m.get_one::<bool>("o").expect("defaulted by clap"));
}

#[test]
fn lots_o_flags_combined() {
    let r = Command::new("opts")
        .args_override_self(true)
        .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue))
        .try_get_matches_from(vec![
            "",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-ooooooooooooooooooooooooooooooooooooooooo",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
    let m = r.unwrap();
    assert!(m.contains_id("o"));
    assert!(*m.get_one::<bool>("o").expect("defaulted by clap"));
}

#[test]
fn flag_using_long() {
    let m = Command::new("flag")
        .args(&[
            arg!(--flag "some flag").action(ArgAction::SetTrue),
            arg!(--color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "--flag", "--color"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
}

#[test]
fn flag_using_long_with_literals() {
    use clap::error::ErrorKind;

    let m = Command::new("flag")
        .arg(
            Arg::new("rainbow")
                .long("rainbow")
                .action(ArgAction::SetTrue),
        )
        .try_get_matches_from(vec!["", "--rainbow=false"]);
    assert!(m.is_err(), "{:#?}", m.unwrap());
    assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyValues);
}

#[test]
fn flag_using_mixed() {
    let m = Command::new("flag")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "-f", "--color"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));

    let m = Command::new("flag")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "--flag", "-c"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
}

#[test]
fn multiple_flags_in_single() {
    let m = Command::new("multe_flags")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
            arg!(-d --debug "another other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "-fcd"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("debug").expect("defaulted by clap"));
}

#[test]
#[cfg(feature = "error-context")]
fn issue_1284_argument_in_flag_style() {
    const USE_FLAG_AS_ARGUMENT: &str = "\
error: Found argument '--another-flag' which wasn't expected, or isn't valid in this context

  If you tried to supply `--another-flag` as a value rather than a flag, use `-- --another-flag`

Usage: mycat [OPTIONS] [filename]

For more information try '--help'
";

    let cmd = Command::new("mycat")
        .arg(Arg::new("filename"))
        .arg(Arg::new("a-flag").long("a-flag").action(ArgAction::SetTrue));

    let m = cmd
        .clone()
        .try_get_matches_from(vec!["", "--", "--another-flag"])
        .unwrap();
    assert_eq!(
        m.get_one::<String>("filename").map(|v| v.as_str()),
        Some("--another-flag")
    );

    let m = cmd
        .clone()
        .try_get_matches_from(vec!["", "--a-flag"])
        .unwrap();
    assert!(*m.get_one::<bool>("a-flag").expect("defaulted by clap"));

    let m = cmd
        .clone()
        .try_get_matches_from(vec!["", "--", "--a-flag"])
        .unwrap();
    assert_eq!(
        m.get_one::<String>("filename").map(|v| v.as_str()),
        Some("--a-flag")
    );

    utils::assert_output(cmd, "mycat --another-flag", USE_FLAG_AS_ARGUMENT, true);
}

#[test]
#[cfg(feature = "error-context")]
fn issue_2308_multiple_dashes() {
    static MULTIPLE_DASHES: &str = "\
error: Found argument '-----' which wasn't expected, or isn't valid in this context

  If you tried to supply `-----` as a value rather than a flag, use `-- -----`

Usage: test <arg>

For more information try '--help'
";
    let cmd = Command::new("test").arg(Arg::new("arg").action(ArgAction::Set).required(true));

    utils::assert_output(cmd, "test -----", MULTIPLE_DASHES, true);
}

#[test]
#[cfg(debug_assertions)]
#[should_panic = "Argument filename: long \"--filename\" must not start with a `-`, that will be handled by the parser"]
fn leading_dash_stripped() {
    let cmd = Command::new("mycat").arg(Arg::new("filename").long("--filename"));
    cmd.debug_assert();
}
<commit_msg>test(parser): Verify existing --flag=bad-value case<commit_after>use clap::{arg, Arg, ArgAction, Command};

#[cfg(feature = "error-context")]
use super::utils;

#[test]
fn flag_using_short() {
    let m = Command::new("flag")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "-f", "-c"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
}

#[test]
fn lots_o_flags_sep() {
    let r = Command::new("opts")
        .args_override_self(true)
        .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue))
        .try_get_matches_from(vec![
            "", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
    let m = r.unwrap();
    assert!(m.contains_id("o"));
    assert!(*m.get_one::<bool>("o").expect("defaulted by clap"));
}

#[test]
fn lots_o_flags_combined() {
    let r = Command::new("opts")
        .args_override_self(true)
        .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue))
        .try_get_matches_from(vec![
            "",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-ooooooooooooooooooooooooooooooooooooooooo",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
    let m = r.unwrap();
    assert!(m.contains_id("o"));
    assert!(*m.get_one::<bool>("o").expect("defaulted by clap"));
}

#[test]
fn flag_using_long() {
    let m = Command::new("flag")
        .args(&[
            arg!(--flag "some flag").action(ArgAction::SetTrue),
            arg!(--color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "--flag", "--color"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
}

#[test]
fn flag_using_long_with_literals() {
    use clap::error::ErrorKind;

    let m = Command::new("flag")
        .arg(
            Arg::new("rainbow")
                .long("rainbow")
                .action(ArgAction::SetTrue),
        )
        .try_get_matches_from(vec!["", "--rainbow=false"]);
    assert!(m.is_err(), "{:#?}", m.unwrap());
    assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyValues);
}

#[test]
fn flag_using_mixed() {
    let m = Command::new("flag")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "-f", "--color"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));

    let m = Command::new("flag")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "--flag", "-c"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
}

#[test]
fn multiple_flags_in_single() {
    let m = Command::new("multe_flags")
        .args(&[
            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
            arg!(-d --debug "another other flag").action(ArgAction::SetTrue),
        ])
        .try_get_matches_from(vec!["", "-fcd"])
        .unwrap();
    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
    assert!(*m.get_one::<bool>("debug").expect("defaulted by clap"));
}

#[test]
#[cfg(feature = "error-context")]
fn unexpected_value_error() {
    const USE_FLAG_AS_ARGUMENT: &str = "\
error: The value 'foo' was provided to '--a-flag' but it wasn't expecting any more values

mycat [OPTIONS] [filename]

For more information try '--help'
";

    let cmd = Command::new("mycat")
        .arg(Arg::new("filename"))
        .arg(Arg::new("a-flag").long("a-flag").action(ArgAction::SetTrue));

    utils::assert_output(cmd, "mycat --a-flag=foo", USE_FLAG_AS_ARGUMENT, true);
}

#[test]
#[cfg(feature = "error-context")]
fn issue_1284_argument_in_flag_style() {
    const USE_FLAG_AS_ARGUMENT: &str = "\
error: Found argument '--another-flag' which wasn't expected, or isn't valid in this context

  If you tried to supply `--another-flag` as a value rather than a flag, use `-- --another-flag`

Usage: mycat [OPTIONS] [filename]

For more information try '--help'
";

    let cmd = Command::new("mycat")
        .arg(Arg::new("filename"))
        .arg(Arg::new("a-flag").long("a-flag").action(ArgAction::SetTrue));

    let m = cmd
        .clone()
        .try_get_matches_from(vec!["", "--", "--another-flag"])
        .unwrap();
    assert_eq!(
        m.get_one::<String>("filename").map(|v| v.as_str()),
        Some("--another-flag")
    );

    let m = cmd
        .clone()
        .try_get_matches_from(vec!["", "--a-flag"])
        .unwrap();
    assert!(*m.get_one::<bool>("a-flag").expect("defaulted by clap"));

    let m = cmd
        .clone()
        .try_get_matches_from(vec!["", "--", "--a-flag"])
        .unwrap();
    assert_eq!(
        m.get_one::<String>("filename").map(|v| v.as_str()),
        Some("--a-flag")
    );

    utils::assert_output(cmd, "mycat --another-flag", USE_FLAG_AS_ARGUMENT, true);
}

#[test]
#[cfg(feature = "error-context")]
fn issue_2308_multiple_dashes() {
    static MULTIPLE_DASHES: &str = "\
error: Found argument '-----' which wasn't expected, or isn't valid in this context

  If you tried to supply `-----` as a value rather than a flag, use `-- -----`

Usage: test <arg>

For more information try '--help'
";
    let cmd = Command::new("test").arg(Arg::new("arg").action(ArgAction::Set).required(true));

    utils::assert_output(cmd, "test -----", MULTIPLE_DASHES, true);
}

#[test]
#[cfg(debug_assertions)]
#[should_panic = "Argument filename: long \"--filename\" must not start with a `-`, that will be handled by the parser"]
fn leading_dash_stripped() {
    let cmd = Command::new("mycat").arg(Arg::new("filename").long("--filename"));
    cmd.debug_assert();
}
<|endoftext|>


<commit_before>extern crate janeiro;

#[macro_use]
extern crate log;
extern crate env_logger;

use std::str;

use janeiro::{Rio, Transport, Protocol, Reason};

struct HttpClientProtocol;
impl HttpClientProtocol {
    fn new() -> HttpClientProtocol {
        HttpClientProtocol
    }
}

impl Protocol for HttpClientProtocol {

    fn connection_made(&self, transport: &mut Transport) {
        debug!("Connection made");
        let data = b"GET /\r\nHost: www.gandi.net\r\nAccept: text/html\r\n\r\n";
        transport.write(data);
    }

    #[allow(unused_variables)]
    fn data_received(&self, data: &[u8], transport: &mut Transport) {
        let s_data = str::from_utf8(data).unwrap().trim();

        debug!("{}", s_data);
        //transport.hang_up();

    }

    fn connection_lost(&self, reason: Reason) {
        match reason {
            Reason::ConnectionLost => info!("Connection closed by peer"),
            Reason::HangUp => info!("Hang hup"),
        }
    }
}

fn main() {
    env_logger::init().unwrap();
    info!("Start the client");
    let mut rio = Rio::new();
    let protocol = HttpClientProtocol::new();
    rio.connect("217.70.184.1:80", Box::new(protocol));
    info!("Start running the loop");
    rio.run_forever();
}
<commit_msg>Use print to display the response in http cli<commit_after>extern crate janeiro;

#[macro_use]
extern crate log;
extern crate env_logger;

use std::str;

use janeiro::{Rio, Transport, Protocol, Reason};

struct HttpClientProtocol;
impl HttpClientProtocol {
    fn new() -> HttpClientProtocol {
        HttpClientProtocol
    }
}

impl Protocol for HttpClientProtocol {

    fn connection_made(&self, transport: &mut Transport) {
        debug!("Connection made");
        let data = b"GET /\r\nHost: www.gandi.net\r\nAccept: text/html\r\n\r\n";
        transport.write(data);
    }

    #[allow(unused_variables)]
    fn data_received(&self, data: &[u8], transport: &mut Transport) {
        let s_data = str::from_utf8(data).unwrap().trim();

        println!("==========================================================");
        println!("{}", s_data);
        println!("==========================================================");
        //transport.hang_up();

    }

    fn connection_lost(&self, reason: Reason) {
        match reason {
            Reason::ConnectionLost => info!("Connection closed by peer"),
            Reason::HangUp => info!("Hang hup"),
        }
    }
}

fn main() {
    env_logger::init().unwrap();
    info!("Start the client");
    let mut rio = Rio::new();
    let protocol = HttpClientProtocol::new();
    rio.connect("217.70.184.1:80", Box::new(protocol));
    info!("Start running the loop");
    rio.run_forever();
}
<|endoftext|>


<commit_before>extern crate nom;

use nom::IResult;
use nom::bytes::complete::tag;
use nom::sequence::{separated_pair, terminated};
use nom::character::complete::alphanumeric1;
use nom::combinator::iterator;
use std::iter::Iterator;
use std::collections::HashMap;

fn main() {
  let mut data = "abcabcabcabc";
  let data2 = data.clone();

  fn parser(i: &str) -> IResult<&str, &str> {
    tag("abc")(i)
  }

  let it = std::iter::from_fn(move|| {
    match parser(data) {
      Ok((i, o)) => {
        data = i;
        Some(o)
      },
      _ => None
    }
  });

  for value in it {
    println!("parser returned: {}", value);
  }

  println!("\n********************\n");

  println!("data is now: {:?}", data2);

  let data = "abcabcabcabc";
  let res = std::iter::repeat(parser).take(3).try_fold((data, Vec::new()), |(data, mut acc), parser| {
    parser(data).map(|(i, o)| {
      acc.push(o);
      (i, acc)
    })
  });

  // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))"
  println!("\nparser iterator returned: {:?}", res);

  println!("\n********************\n");

  let data = "key1:value1,key2:value2,key3:value3,;";

  let mut nom_it = iterator(data, terminated(separated_pair(alphanumeric1, tag(":"), alphanumeric1), tag(",")));

  let res = nom_it.map(|(k, v)| (k.to_uppercase(), v)).collect::<HashMap<_, _>>();

  let parser_result: IResult<_, _> = nom_it.finish();
  let (remaining_input, ()) = parser_result.unwrap();

  // will print "iterator returned {"key1": "value1", "key3": "value3", "key2": "value2"}, remaining input is ';'"
  println!("iterator returned {:?}, remaining input is '{}'", res, remaining_input);
}
<commit_msg>add more comments on the iterator example<commit_after>extern crate nom;

use nom::IResult;
use nom::bytes::complete::tag;
use nom::sequence::{separated_pair, terminated};
use nom::character::complete::alphanumeric1;
use nom::combinator::iterator;
use std::iter::Iterator;
use std::collections::HashMap;

fn main() {
  let mut data = "abcabcabcabc";

  fn parser(i: &str) -> IResult<&str, &str> {
    tag("abc")(i)
  }

  // `from_fn` (available from Rust 1.34) can create an iterator
  // from a closure
  let it = std::iter::from_fn(move|| {
    match parser(data) {
      // when successful, a nom parser returns a tuple of
      // the remaining input and the output value.
      // So we replace the captured input data with the
      // remaining input, to be parsed on the next call
      Ok((i, o)) => {
        data = i;
        Some(o)
      },
      _ => None
    }
  });

  for value in it {
    println!("parser returned: {}", value);
  }

  println!("\n********************\n");

  let data = "abcabcabcabc";

  // if `from_fn` is not available, it is possible to fold
  // over an iterator of functions
  let res = std::iter::repeat(parser).take(3).try_fold((data, Vec::new()), |(data, mut acc), parser| {
    parser(data).map(|(i, o)| {
      acc.push(o);
      (i, acc)
    })
  });

  // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))"
  println!("\nparser iterator returned: {:?}", res);

  println!("\n********************\n");

  let data = "key1:value1,key2:value2,key3:value3,;";

  // `nom::combinator::iterator` will return an iterator
  // producing the parsed values. Compared to the previous
  // solutions:
  // - we can work with a normal iterator like `from_fn`
  // - we can get the remaining input afterwards, like with the `try_fold` trick
  let mut nom_it = iterator(data, terminated(separated_pair(alphanumeric1, tag(":"), alphanumeric1), tag(",")));

  let res = nom_it.map(|(k, v)| (k.to_uppercase(), v)).collect::<HashMap<_, _>>();

  let parser_result: IResult<_, _> = nom_it.finish();
  let (remaining_input, ()) = parser_result.unwrap();

  // will print "iterator returned {"key1": "value1", "key3": "value3", "key2": "value2"}, remaining input is ';'"
  println!("iterator returned {:?}, remaining input is '{}'", res, remaining_input);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-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.

//! Mesh loading.
//!
//! A `Mesh` describes the geometry of an object. All or part of a `Mesh` can be drawn with a
//! single draw call. A `Mesh` consists of a series of vertices, each with a certain amount of
//! user-specified attributes. These attributes are fed into shader programs. The easiest way to
//! create a mesh is to use the `#[vertex_format]` attribute on a struct, upload them into a
//! `Buffer`, and then use `Mesh::from`.

use device;
use device::{PrimitiveType, Resources, VertexCount};
use device::attrib;
use device::handle::Buffer as BufferHandle;
use device::handle::IndexBuffer as IndexBufferHandle;

/// Describes a single attribute of a vertex buffer, including its type, name, etc.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Attribute<R: Resources> {
    /// A name to match the shader input
    pub name: String,
    /// Vertex buffer to contain the data
    pub buffer: device::handle::RawBuffer<R>,
    /// Format of the attribute
    pub format: attrib::Format,
}

/// A trait implemented automatically for user vertex structure by
/// `#[vertex_format] attribute
#[allow(missing_docs)]
pub trait VertexFormat {
    /// Create the attributes for this type, using the given buffer.
    fn generate<R: Resources>(buffer: device::handle::RawBuffer<R>) -> Vec<Attribute<R>>;
}

/// Describes geometry to render.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Mesh<R: Resources> {
    /// Number of vertices in the mesh.
    pub num_vertices: device::VertexCount,
    /// Vertex attributes to use.
    pub attributes: Vec<Attribute<R>>,
}

impl<R: Resources> Mesh<R> {
    /// Create a new mesh, which is a `TriangleList` with no attributes and `nv` vertices.
    pub fn new(nv: device::VertexCount) -> Mesh<R> {
        Mesh {
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    /// Create a new `Mesh` from a struct that implements `VertexFormat` and a buffer.
    pub fn from_format<V: VertexFormat>(buf: BufferHandle<R, V>, nv: device::VertexCount)
                       -> Mesh<R> {
        Mesh {
            num_vertices: nv,
            attributes: <V as VertexFormat>::generate(buf.raw().clone()),
        }
    }

    /// Create a new intanced `Mesh` given a vertex buffer and an instance buffer.
    pub fn from_format_instanced<V: VertexFormat, U: VertexFormat>(
                                 buf: BufferHandle<R, V>,
                                 nv: device::VertexCount,
                                 inst: BufferHandle<R, U>) -> Mesh<R> {
        let per_vertex   = <V as VertexFormat>::generate(buf.raw().clone());
        let per_instance = <U as VertexFormat>::generate(inst.raw().clone());

        let mut attributes = per_vertex;
        for mut at in per_instance.into_iter() {
            at.format.instance_rate = 1;
            attributes.push(at);
        }

        Mesh {
            num_vertices: nv,
            attributes: attributes,
        }
    }
}

/// Description of a subset of `Mesh` data to render.
///
/// Only vertices between `start` and `end` are rendered. The
/// source of the vertex data is dependent on the `kind` value.
///
/// The `prim_type` defines how the mesh contents are interpreted.
/// For example,  `Point` typed vertex slice can be used to do shape
/// blending, while still rendereing it as an indexed `TriangleList`.
#[derive(Clone, Debug, PartialEq)]
pub struct Slice<R: Resources> {
    /// Start index of vertices to draw.
    pub start: VertexCount,
    /// End index of vertices to draw.
    pub end: VertexCount,
    /// Primitive type to render collections of vertices as.
    pub prim_type: PrimitiveType,
    /// Source of the vertex ordering when drawing.
    pub kind: SliceKind<R>,
}

impl<R: Resources> Slice<R> {
    /// Get the number of primitives in this slice.
    pub fn get_prim_count(&self) -> u32 {
        use device::PrimitiveType::*;
        let nv = (self.end - self.start) as u32;
        match self.prim_type {
            Point => nv,
            Line => nv / 2,
            LineStrip => (nv-1),
            TriangleList => nv / 3,
            TriangleStrip | TriangleFan => (nv-2) / 3,
        }
    }
}

/// Source of vertex ordering for a slice
#[derive(Clone, Debug, PartialEq)]
pub enum SliceKind<R: Resources> {
    /// Render vertex data directly from the `Mesh`'s buffer.
    Vertex,
    /// The `Index*` buffer contains a list of indices into the `Mesh`
    /// data, so every vertex attribute does not need to be duplicated, only
    /// its position in the `Mesh`. The base index is added to this index
    /// before fetching the vertex from the buffer.  For example, when drawing
    /// a square, two triangles are needed.  Using only `Vertex`, one
    /// would need 6 separate vertices, 3 for each triangle. However, two of
    /// the vertices will be identical, wasting space for the duplicated
    /// attributes.  Instead, the `Mesh` can store 4 vertices and an
    /// `Index8` can be used instead.
    Index8(IndexBufferHandle<R, u8>, VertexCount),
    /// As `Index8` but with `u16` indices
    Index16(IndexBufferHandle<R, u16>, VertexCount),
    /// As `Index8` but with `u32` indices
    Index32(IndexBufferHandle<R, u32>, VertexCount),
}

/// Helper methods for cleanly getting the slice of a type.
pub trait ToSlice<R: Resources> {
    /// Get the slice of a type.
    fn to_slice(&self, pt: PrimitiveType) -> Slice<R>;
}

impl<R: Resources> ToSlice<R> for Mesh<R> {
    /// Return a vertex slice of the whole mesh.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.num_vertices,
            prim_type: ty,
            kind: SliceKind::Vertex
        }
    }
}

impl<R: Resources> ToSlice<R> for IndexBufferHandle<R, u8> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index8(self.clone(), 0)
        }
    }
}

impl<R: Resources> ToSlice<R> for IndexBufferHandle<R, u16> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index16(self.clone(), 0)
        }
    }
}

impl<R: Resources> ToSlice<R> for IndexBufferHandle<R, u32> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index32(self.clone(), 0)
        }
    }
}

/// Index of a vertex attribute inside the mesh
pub type AttributeIndex = usize;

/// Describes kinds of errors that may occur in the mesh linking
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// A required attribute was missing.
    AttributeMissing(String),
    /// An attribute's type from the vertex format differed from the type used in the shader.
    AttributeType(String, device::shade::BaseType),
    /// An attribute index is out of supported bounds
    AttributeIndex(AttributeIndex),
    /// An input index is out of supported bounds
    ShaderInputIndex(usize),
}

const BITS_PER_ATTRIBUTE: AttributeIndex = 4;
const MESH_ATTRIBUTE_MASK: AttributeIndex = (1 << BITS_PER_ATTRIBUTE) - 1;
const MAX_SHADER_INPUTS: usize = 64 / BITS_PER_ATTRIBUTE;

/// An iterator over mesh attributes.
#[derive(Clone, Copy)]
pub struct AttributeIter {
    value: u64,
}

impl Iterator for AttributeIter {
    type Item = AttributeIndex;

    fn next(&mut self) -> Option<AttributeIndex> {
        let id = (self.value as AttributeIndex) & MESH_ATTRIBUTE_MASK;
        self.value >>= BITS_PER_ATTRIBUTE;
        Some(id)
    }
}

/// Holds a remapping table from shader inputs to mesh attributes.
#[derive(Clone, Copy)]
pub struct Link {
    table: u64,
}

impl Link {
    /// Match mesh attributes against shader inputs, produce a mesh link.
    /// Exposed to public to allow external `Batch` implementations to use it.
    pub fn new<R: Resources>(mesh: &Mesh<R>, pinfo: &device::shade::ProgramInfo)
                             -> Result<Link, Error> {
        let mut indices = Vec::new();
        for sat in pinfo.attributes.iter() {
            match mesh.attributes.iter().enumerate()
                      .find(|&(_, a)| a.name == sat.name) {
                Some((attrib_id, vat)) => match vat.format.elem_type.is_compatible(sat.base_type) {
                    Ok(_) => indices.push(attrib_id),
                    Err(_) => return Err(Error::AttributeType(sat.name.clone(), sat.base_type)),
                },
                None => return Err(Error::AttributeMissing(sat.name.clone())),
            }
        }
        Link::from_iter(indices.into_iter())
    }

    /// Construct a new link from an iterator over attribute indices.
    pub fn from_iter<I: Iterator<Item = AttributeIndex>>(iter: I)
                     -> Result<Link, Error> {
        let mut table = 0u64;
        for (input, attrib) in iter.enumerate() {
            if input >= MAX_SHADER_INPUTS {
                return Err(Error::ShaderInputIndex(input))
            } else if attrib > MESH_ATTRIBUTE_MASK {
                return Err(Error::AttributeIndex(attrib))
            } else {
                table |= (attrib as u64) << (input * BITS_PER_ATTRIBUTE);
            }
        }
        Ok(Link {
            table: table,
        })
    }

    /// Convert to an iterator returning attribute indices
    pub fn to_iter(&self) -> AttributeIter {
        AttributeIter {
            value: self.table,
        }
    }
}
<commit_msg>Refactored the mesh module<commit_after>// Copyright 2014 The Gfx-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.

//! Mesh loading.
//!
//! A `Mesh` describes the geometry of an object. All or part of a `Mesh` can be drawn with a
//! single draw call. A `Mesh` consists of a series of vertices, each with a certain amount of
//! user-specified attributes. These attributes are fed into shader programs. The easiest way to
//! create a mesh is to use the `#[vertex_format]` attribute on a struct, upload them into a
//! `Buffer`, and then use `Mesh::from`.

use device::{PrimitiveType, Resources, VertexCount};
use device::{attrib, handle, shade};

/// Describes a single attribute of a vertex buffer, including its type, name, etc.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Attribute<R: Resources> {
    /// A name to match the shader input
    pub name: String,
    /// Vertex buffer to contain the data
    pub buffer: handle::RawBuffer<R>,
    /// Format of the attribute
    pub format: attrib::Format,
}

/// A trait implemented automatically for user vertex structure by
/// `#[vertex_format] attribute
#[allow(missing_docs)]
pub trait VertexFormat {
    /// Create the attributes for this type, using the given buffer.
    fn generate<R: Resources>(buffer: &handle::Buffer<R, Self>) -> Vec<Attribute<R>>;
}

/// Describes geometry to render.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Mesh<R: Resources> {
    /// Number of vertices in the mesh.
    pub num_vertices: VertexCount,
    /// Vertex attributes to use.
    pub attributes: Vec<Attribute<R>>,
}

impl<R: Resources> Mesh<R> {
    /// Create a new mesh, which is a `TriangleList` with no attributes and `nv` vertices.
    pub fn new(nv: VertexCount) -> Mesh<R> {
        Mesh {
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    /// Create a new `Mesh` from a struct that implements `VertexFormat` and a buffer.
    pub fn from_format<V: VertexFormat>(buf: handle::Buffer<R, V>, nv: VertexCount)
                       -> Mesh<R> {
        Mesh {
            num_vertices: nv,
            attributes: V::generate(&buf),
        }
    }

    /// Create a new intanced `Mesh` given a vertex buffer and an instance buffer.
    pub fn from_format_instanced<V: VertexFormat, U: VertexFormat>(
                                 buf: handle::Buffer<R, V>,
                                 nv: VertexCount,
                                 inst: handle::Buffer<R, U>) -> Mesh<R> {
        let per_vertex   = V::generate(&buf);
        let per_instance = U::generate(&inst);

        let mut attributes = per_vertex;
        attributes.extend(per_instance.into_iter().map(|mut a| {
            a.format.instance_rate = 1;
            a
        }));

        Mesh {
            num_vertices: nv,
            attributes: attributes,
        }
    }
}

/// Description of a subset of `Mesh` data to render.
///
/// Only vertices between `start` and `end` are rendered. The
/// source of the vertex data is dependent on the `kind` value.
///
/// The `prim_type` defines how the mesh contents are interpreted.
/// For example,  `Point` typed vertex slice can be used to do shape
/// blending, while still rendereing it as an indexed `TriangleList`.
#[derive(Clone, Debug, PartialEq)]
pub struct Slice<R: Resources> {
    /// Start index of vertices to draw.
    pub start: VertexCount,
    /// End index of vertices to draw.
    pub end: VertexCount,
    /// Primitive type to render collections of vertices as.
    pub prim_type: PrimitiveType,
    /// Source of the vertex ordering when drawing.
    pub kind: SliceKind<R>,
}

impl<R: Resources> Slice<R> {
    /// Get the number of primitives in this slice.
    pub fn get_prim_count(&self) -> u32 {
        use device::PrimitiveType::*;
        let nv = (self.end - self.start) as u32;
        match self.prim_type {
            Point => nv,
            Line => nv / 2,
            LineStrip => (nv-1),
            TriangleList => nv / 3,
            TriangleStrip | TriangleFan => (nv-2) / 3,
        }
    }
}

/// Source of vertex ordering for a slice
#[derive(Clone, Debug, PartialEq)]
pub enum SliceKind<R: Resources> {
    /// Render vertex data directly from the `Mesh`'s buffer.
    Vertex,
    /// The `Index*` buffer contains a list of indices into the `Mesh`
    /// data, so every vertex attribute does not need to be duplicated, only
    /// its position in the `Mesh`. The base index is added to this index
    /// before fetching the vertex from the buffer.  For example, when drawing
    /// a square, two triangles are needed.  Using only `Vertex`, one
    /// would need 6 separate vertices, 3 for each triangle. However, two of
    /// the vertices will be identical, wasting space for the duplicated
    /// attributes.  Instead, the `Mesh` can store 4 vertices and an
    /// `Index8` can be used instead.
    Index8(handle::IndexBuffer<R, u8>, VertexCount),
    /// As `Index8` but with `u16` indices
    Index16(handle::IndexBuffer<R, u16>, VertexCount),
    /// As `Index8` but with `u32` indices
    Index32(handle::IndexBuffer<R, u32>, VertexCount),
}

/// Helper methods for cleanly getting the slice of a type.
pub trait ToSlice<R: Resources> {
    /// Get the slice of a type.
    fn to_slice(&self, pt: PrimitiveType) -> Slice<R>;
}

impl<R: Resources> ToSlice<R> for Mesh<R> {
    /// Return a vertex slice of the whole mesh.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.num_vertices,
            prim_type: ty,
            kind: SliceKind::Vertex
        }
    }
}

impl<R: Resources> ToSlice<R> for handle::IndexBuffer<R, u8> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index8(self.clone(), 0)
        }
    }
}

impl<R: Resources> ToSlice<R> for handle::IndexBuffer<R, u16> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index16(self.clone(), 0)
        }
    }
}

impl<R: Resources> ToSlice<R> for handle::IndexBuffer<R, u32> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index32(self.clone(), 0)
        }
    }
}

/// Index of a vertex attribute inside the mesh
pub type AttributeIndex = usize;

/// Describes kinds of errors that may occur in the mesh linking
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// A required attribute was missing.
    AttributeMissing(String),
    /// An attribute's type from the vertex format differed from the type used in the shader.
    AttributeType(String, shade::BaseType),
    /// An attribute index is out of supported bounds
    AttributeIndex(AttributeIndex),
    /// An input index is out of supported bounds
    ShaderInputIndex(usize),
}

const BITS_PER_ATTRIBUTE: AttributeIndex = 4;
const MESH_ATTRIBUTE_MASK: AttributeIndex = (1 << BITS_PER_ATTRIBUTE) - 1;
const MAX_SHADER_INPUTS: usize = 64 / BITS_PER_ATTRIBUTE;

/// An iterator over mesh attributes.
#[derive(Clone, Copy)]
pub struct AttributeIter {
    value: u64,
}

impl Iterator for AttributeIter {
    type Item = AttributeIndex;

    fn next(&mut self) -> Option<AttributeIndex> {
        let id = (self.value as AttributeIndex) & MESH_ATTRIBUTE_MASK;
        self.value >>= BITS_PER_ATTRIBUTE;
        Some(id)
    }
}

/// Holds a remapping table from shader inputs to mesh attributes.
#[derive(Clone, Copy)]
pub struct Link {
    table: u64,
}

impl Link {
    /// Match mesh attributes against shader inputs, produce a mesh link.
    /// Exposed to public to allow external `Batch` implementations to use it.
    pub fn new<R: Resources>(mesh: &Mesh<R>, pinfo: &shade::ProgramInfo)
                             -> Result<Link, Error> {
        let mut indices = Vec::new();
        for sat in pinfo.attributes.iter() {
            match mesh.attributes.iter().enumerate()
                      .find(|&(_, a)| a.name == sat.name) {
                Some((attrib_id, vat)) => match vat.format.elem_type.is_compatible(sat.base_type) {
                    Ok(_) => indices.push(attrib_id),
                    Err(_) => return Err(Error::AttributeType(sat.name.clone(), sat.base_type)),
                },
                None => return Err(Error::AttributeMissing(sat.name.clone())),
            }
        }
        Link::from_iter(indices.into_iter())
    }

    /// Construct a new link from an iterator over attribute indices.
    pub fn from_iter<I: Iterator<Item = AttributeIndex>>(iter: I)
                     -> Result<Link, Error> {
        let mut table = 0u64;
        for (input, attrib) in iter.enumerate() {
            if input >= MAX_SHADER_INPUTS {
                return Err(Error::ShaderInputIndex(input))
            } else if attrib > MESH_ATTRIBUTE_MASK {
                return Err(Error::AttributeIndex(attrib))
            } else {
                table |= (attrib as u64) << (input * BITS_PER_ATTRIBUTE);
            }
        }
        Ok(Link {
            table: table,
        })
    }

    /// Convert to an iterator returning attribute indices
    pub fn to_iter(&self) -> AttributeIter {
        AttributeIter {
            value: self.table,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// 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.

//! Thread-local random number generator

use std::cell::UnsafeCell;

use {RngCore, CryptoRng, SeedableRng, Error};
use rngs::adapter::ReseedingRng;
use rngs::EntropyRng;
use rand_hc::Hc128Core;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`thread_rng`]: ../fn.thread_rng.html
/// [`ReseedingRng`]: adapter/struct.ReseedingRng.html
/// [`StdRng`]: struct.StdRng.html
/// [`EntropyRng`]: struct.EntropyRng.html
/// [HC-128]: ../../rand_hc/struct.Hc128Rng.html
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Hc128Core, EntropyRng>,
}

thread_local!(
    static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>> = {
        let mut entropy_source = EntropyRng::new();
        let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    entropy_source);
        UnsafeCell::new(rng)
    }
);

/// Retrieve the lazily-initialized thread-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.
///
/// For more information see [`ThreadRng`].
///
/// [`ThreadRng`]: rngs/struct.ThreadRng.html
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.get()) }
}

impl Default for ThreadRng {
    fn default() -> ThreadRng {
        ::prelude::thread_rng()
    }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng).next_u64() }
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        unsafe { (*self.rng).fill_bytes(dest) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    #[cfg(not(feature="stdweb"))]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0, 1), 0);
    }
}
<commit_msg>Requested comment<commit_after>// Copyright 2018 Developers of the Rand project.
//
// 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.

//! Thread-local random number generator

use std::cell::UnsafeCell;

use {RngCore, CryptoRng, SeedableRng, Error};
use rngs::adapter::ReseedingRng;
use rngs::EntropyRng;
use rand_hc::Hc128Core;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`thread_rng`]: ../fn.thread_rng.html
/// [`ReseedingRng`]: adapter/struct.ReseedingRng.html
/// [`StdRng`]: struct.StdRng.html
/// [`EntropyRng`]: struct.EntropyRng.html
/// [HC-128]: ../../rand_hc/struct.Hc128Rng.html
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Hc128Core, EntropyRng>,
}

thread_local!(
    static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>> = {
        let mut entropy_source = EntropyRng::new();
        let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    entropy_source);
        UnsafeCell::new(rng)
    }
);

/// Retrieve the lazily-initialized thread-local random number generator,
/// seeded by the system. Intended to be used in method chaining style,
/// e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.  Invoked by the `Default` trait, making
/// `ThreadRng::default()` equivelent.
///
/// For more information see [`ThreadRng`].
///
/// [`ThreadRng`]: rngs/struct.ThreadRng.html
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.get()) }
}

impl Default for ThreadRng {
    fn default() -> ThreadRng {
        ::prelude::thread_rng()
    }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng).next_u64() }
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        unsafe { (*self.rng).fill_bytes(dest) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    #[cfg(not(feature="stdweb"))]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0, 1), 0);
    }
}
<|endoftext|>


<commit_before>//! Types for the *m.room.create* event.

use ruma_identifiers::UserId;

state_event! {
    /// This is the first event in a room and cannot be changed. It acts as the root of all other
    /// events.
    pub struct CreateEvent(CreateEventContent) {}
}

/// The payload of a `CreateEvent`.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CreateEventContent {
    /// The `user_id` of the room creator. This is set by the homeserver.
    pub creator: UserId,
    /// Whether or not this room's data should be transferred to other homeservers.
    pub federate: bool,
}
<commit_msg>Make the federate field optional<commit_after>//! Types for the *m.room.create* event.

use ruma_identifiers::UserId;

state_event! {
    /// This is the first event in a room and cannot be changed. It acts as the root of all other
    /// events.
    pub struct CreateEvent(CreateEventContent) {}
}

/// The payload of a `CreateEvent`.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CreateEventContent {
    /// The `user_id` of the room creator. This is set by the homeserver.
    pub creator: UserId,
    /// Whether or not this room's data should be transferred to other homeservers.
    pub federate: Option<bool>,
}
<|endoftext|>