<commit_before>use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::collections::binary_heap::{Iter as BinaryHeapIter};

use collectors::{Collector, DocumentMatch};

/// An f64 that cannot be NaN.
/// We need to order documents by score but NaN cannot be ordered, so we convert all scores into
/// RealF64 first, handling any invalid values while doing that conversion
#[derive(Copy, Clone, PartialEq, PartialOrd)]
struct RealF64(f64);

impl RealF64 {
    fn new(val: f64) -> Option<RealF64> {
        if val.is_nan() {
            None
        } else {
            Some(RealF64(val))
        }
    }
}

impl Eq for RealF64 {}

impl Ord for RealF64 {
    fn cmp(&self, other: &RealF64) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
struct ScoredDocument {
    id: u64,
    score: RealF64,
}

impl Ord for ScoredDocument {
    fn cmp(&self, other: &ScoredDocument) -> Ordering {
        // Notice that the we flip the ordering here
        other.score.cmp(&self.score)
    }
}

impl PartialOrd for ScoredDocument {
    fn partial_cmp(&self, other: &ScoredDocument) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

pub struct TopScoreCollector {
    max_docs: usize,
    heap: BinaryHeap<ScoredDocument>,
}

impl TopScoreCollector {
    pub fn new(max_docs: usize) -> TopScoreCollector {
        TopScoreCollector {
            max_docs: max_docs,
            heap: BinaryHeap::with_capacity(max_docs + 1),
        }
    }

    pub fn iter<'a>(&'a mut self) -> Iter<'a> {
        Iter {
            heap_iter: self.heap.iter(),
        }
    }
}

impl Collector for TopScoreCollector {
    fn needs_score(&self) -> bool {
        true
    }

    fn collect(&mut self, doc: DocumentMatch) {
        let doc_id = doc.doc_id();
        let score = doc.score();

        // Build a ScoredDocument object, checking that the score is set and not NaN
        let scored_document = match score {
            Some(score) => {
                // Convert to RealF64 which is orderable but does not support NaN
                match RealF64::new(score) {
                    Some(real_score) => {
                        ScoredDocument {
                            id: doc_id,
                            score: real_score,
                        }
                    }
                    None => {
                        // Score was NaN
                        panic!("document with 'NaN' score was passed into TopScoreCollector");
                    }
                }
            }
            None => {
                panic!("unscored document was passed into TopScoreCollector");
            }
        };

        // Now insert the document into the heap
        self.heap.push(scored_document);

        // Now reduce the heap size if it's too big
        if self.heap.len() > self.max_docs {
            self.heap.pop();
        }
    }
}

pub struct Iter<'a> {
    heap_iter: BinaryHeapIter<'a, ScoredDocument>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = DocumentMatch;

    fn next(&mut self) -> Option<DocumentMatch> {
        match self.heap_iter.next_back() {
            Some(scored_document) => {
                // Convert ScoredDocument back into DocumentMatch
                Some(DocumentMatch::new_scored(scored_document.id, scored_document.score.0))
            }
            None => None
        }
    }
}

#[cfg(test)]
mod tests {
    use collectors::{Collector, DocumentMatch};
    use super::TopScoreCollector;

    #[test]
    fn test_top_score_collector_inital_state() {
        let mut collector = TopScoreCollector::new(10);

        let docs = collector.iter().collect::<Vec<_>>();
        assert_eq!(docs.len(), 0);
    }

    #[test]
    fn test_top_score_collector_needs_score() {
        let collector = TopScoreCollector::new(10);

        assert_eq!(collector.needs_score(), true);
    }

    #[test]
    fn test_top_score_collector_collect() {
        let mut collector = TopScoreCollector::new(10);

        collector.collect(DocumentMatch::new_scored(0, 1.0f64));
        collector.collect(DocumentMatch::new_scored(1, 0.5f64));
        collector.collect(DocumentMatch::new_scored(2, 2.0f64));

        let docs = collector.iter().collect::<Vec<_>>();
        assert_eq!(docs.len(), 3);
        assert_eq!(docs[0].id, 2);
        assert_eq!(docs[1].id, 0);
        assert_eq!(docs[2].id, 1);
    }

    #[test]
    fn test_top_score_collector_truncate() {
        let mut collector = TopScoreCollector::new(2);

        collector.collect(DocumentMatch::new_scored(0, 1.0f64));
        collector.collect(DocumentMatch::new_scored(1, 0.5f64));
        collector.collect(DocumentMatch::new_scored(2, 2.0f64));

        let docs = collector.iter().collect::<Vec<_>>();
        assert_eq!(docs.len(), 2);
        assert_eq!(docs[0].id, 2);
        assert_eq!(docs[1].id, 0);
    }
}
<commit_msg>Fixed ordering returned by TopScoreCollector<commit_after>use std::cmp::Ordering;
use std::collections::BinaryHeap;

use collectors::{Collector, DocumentMatch};

/// An f64 that cannot be NaN.
/// We need to order documents by score but NaN cannot be ordered, so we convert all scores into
/// RealF64 first, handling any invalid values while doing that conversion
#[derive(Copy, Clone, PartialEq, PartialOrd)]
struct RealF64(f64);

impl RealF64 {
    fn new(val: f64) -> Option<RealF64> {
        if val.is_nan() {
            None
        } else {
            Some(RealF64(val))
        }
    }
}

impl Eq for RealF64 {}

impl Ord for RealF64 {
    fn cmp(&self, other: &RealF64) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
struct ScoredDocument {
    id: u64,
    score: RealF64,
}

impl Ord for ScoredDocument {
    fn cmp(&self, other: &ScoredDocument) -> Ordering {
        self.score.cmp(&other.score)
    }
}

impl PartialOrd for ScoredDocument {
    fn partial_cmp(&self, other: &ScoredDocument) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

pub struct TopScoreCollector {
    max_docs: usize,
    heap: BinaryHeap<ScoredDocument>,
}

impl TopScoreCollector {
    pub fn new(max_docs: usize) -> TopScoreCollector {
        TopScoreCollector {
            max_docs: max_docs,
            heap: BinaryHeap::with_capacity(max_docs + 1),
        }
    }

    pub fn into_sorted_vec(self) -> Vec<DocumentMatch> {
        self.heap.into_sorted_vec().iter()
            .map(|scored_document| {
                DocumentMatch::new_scored(scored_document.id, -scored_document.score.0)
            })
            .collect()
    }
}

impl Collector for TopScoreCollector {
    fn needs_score(&self) -> bool {
        true
    }

    fn collect(&mut self, doc: DocumentMatch) {
        let doc_id = doc.doc_id();
        let score = doc.score();

        // Build a ScoredDocument object, checking that the score is set and not NaN
        let scored_document = match score {
            Some(score) => {
                // Convert to RealF64 which is orderable but does not support NaN
                match RealF64::new(-score) {
                    Some(real_score) => {
                        ScoredDocument {
                            id: doc_id,
                            score: real_score,
                        }
                    }
                    None => {
                        // Score was NaN
                        panic!("document with 'NaN' score was passed into TopScoreCollector");
                    }
                }
            }
            None => {
                panic!("unscored document was passed into TopScoreCollector");
            }
        };

        // Now insert the document into the heap
        self.heap.push(scored_document);

        // Now reduce the heap size if it's too big
        if self.heap.len() > self.max_docs {
            self.heap.pop();
        }
    }
}

#[cfg(test)]
mod tests {
    use collectors::{Collector, DocumentMatch};
    use super::TopScoreCollector;

    #[test]
    fn test_top_score_collector_inital_state() {
        let collector = TopScoreCollector::new(10);

        let docs = collector.into_sorted_vec();
        assert_eq!(docs.len(), 0);
    }

    #[test]
    fn test_top_score_collector_needs_score() {
        let collector = TopScoreCollector::new(10);

        assert_eq!(collector.needs_score(), true);
    }

    #[test]
    fn test_top_score_collector_collect() {
        let mut collector = TopScoreCollector::new(10);

        collector.collect(DocumentMatch::new_scored(0, 1.0f64));
        collector.collect(DocumentMatch::new_scored(1, 0.5f64));
        collector.collect(DocumentMatch::new_scored(2, 2.0f64));
        collector.collect(DocumentMatch::new_scored(3, 1.5f64));

        let docs = collector.into_sorted_vec();
        assert_eq!(docs.len(), 4);
        assert_eq!(docs[0].id, 2);
        assert_eq!(docs[1].id, 3);
        assert_eq!(docs[2].id, 0);
        assert_eq!(docs[3].id, 1);
    }

    #[test]
    fn test_top_score_collector_truncate() {
        let mut collector = TopScoreCollector::new(2);

        collector.collect(DocumentMatch::new_scored(0, 1.0f64));
        collector.collect(DocumentMatch::new_scored(1, 0.5f64));
        collector.collect(DocumentMatch::new_scored(2, 2.0f64));

        let docs = collector.into_sorted_vec();
        assert_eq!(docs.len(), 2);
        assert_eq!(docs[0].id, 2);
        assert_eq!(docs[1].id, 0);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

extern crate native;
extern crate glfw;

use glfw::Context;

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::Visible(true));

    let (window, _) = glfw.create_window(640, 480, "Defaults", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();

    let (width, height) = window.get_size();
    println!("window size: ({}, {})", width, height);

    println!("Context version: {}",           window.get_context_version());
    println!("OpenGL forward compatible: {}", window.is_opengl_forward_compat());
    println!("OpenGL debug context: {}",      window.is_opengl_debug_context());
    println!("OpenGL profile: {}",            window.get_opengl_profile());

    let gl_params = [
        (gl::RED_BITS,          None,   "red bits"          ),
        (gl::GREEN_BITS,        None,   "green bits"        ),
        (gl::BLUE_BITS,         None,   "blue bits"         ),
        (gl::ALPHA_BITS,        None,   "alpha bits"        ),
        (gl::DEPTH_BITS,        None,   "depth bits"        ),
        (gl::STENCIL_BITS,      None,   "stencil bits"      ),
        (gl::ACCUM_RED_BITS,    None,   "accum red bits"    ),
        (gl::ACCUM_GREEN_BITS,  None,   "accum green bits"  ),
        (gl::ACCUM_BLUE_BITS,   None,   "accum blue bits"   ),
        (gl::ACCUM_ALPHA_BITS,  None,   "accum alpha bits"  ),
        (gl::STEREO,            None,   "stereo"            ),
        (gl::SAMPLES_ARB,       Some("GL_ARB_multisample"), "FSAA samples" ),
    ];

    for &(param, ext, name) in gl_params.iter() {
        if ext.map_or(true, |s| {
            glfw.extension_supported(s)
        }) {
            let value = 0;
            unsafe { gl::GetIntegerv(param, &value) };
            println!("OpenGL {:s}: {}", name, value);
        };
    }
}

mod gl {
    extern crate libc;

    #[cfg(target_os = "macos")]
    #[link(name="OpenGL", kind="framework")]
    extern { }

    #[cfg(target_os = "linux")]
    #[link(name="GL")]
    extern { }

    pub type GLenum = libc::c_uint;
    pub type GLint  = libc::c_int;

    pub static RED_BITS              : GLenum = 0x0D52;
    pub static GREEN_BITS            : GLenum = 0x0D53;
    pub static BLUE_BITS             : GLenum = 0x0D54;
    pub static ALPHA_BITS            : GLenum = 0x0D55;
    pub static DEPTH_BITS            : GLenum = 0x0D56;
    pub static STENCIL_BITS          : GLenum = 0x0D57;
    pub static ACCUM_RED_BITS        : GLenum = 0x0D58;
    pub static ACCUM_GREEN_BITS      : GLenum = 0x0D59;
    pub static ACCUM_BLUE_BITS       : GLenum = 0x0D5A;
    pub static ACCUM_ALPHA_BITS      : GLenum = 0x0D5B;
    pub static STEREO                : GLenum = 0x0C33;
    pub static SAMPLES_ARB           : GLenum = 0x80A9;

    #[inline(never)]
    #[allow(non_snake_case_functions)]
    pub unsafe fn GetIntegerv(pname: GLenum, params: *const GLint) {
        glGetIntegerv(pname, params)
    }

    extern "C" {
        fn glGetIntegerv(pname: GLenum, params: *const GLint);
    }
}
<commit_msg>Fix warning in example<commit_after>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

extern crate native;
extern crate glfw;

use glfw::Context;

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::Visible(true));

    let (window, _) = glfw.create_window(640, 480, "Defaults", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();

    let (width, height) = window.get_size();
    println!("window size: ({}, {})", width, height);

    println!("Context version: {}",           window.get_context_version());
    println!("OpenGL forward compatible: {}", window.is_opengl_forward_compat());
    println!("OpenGL debug context: {}",      window.is_opengl_debug_context());
    println!("OpenGL profile: {}",            window.get_opengl_profile());

    let gl_params = [
        (gl::RED_BITS,          None,   "red bits"          ),
        (gl::GREEN_BITS,        None,   "green bits"        ),
        (gl::BLUE_BITS,         None,   "blue bits"         ),
        (gl::ALPHA_BITS,        None,   "alpha bits"        ),
        (gl::DEPTH_BITS,        None,   "depth bits"        ),
        (gl::STENCIL_BITS,      None,   "stencil bits"      ),
        (gl::ACCUM_RED_BITS,    None,   "accum red bits"    ),
        (gl::ACCUM_GREEN_BITS,  None,   "accum green bits"  ),
        (gl::ACCUM_BLUE_BITS,   None,   "accum blue bits"   ),
        (gl::ACCUM_ALPHA_BITS,  None,   "accum alpha bits"  ),
        (gl::STEREO,            None,   "stereo"            ),
        (gl::SAMPLES_ARB,       Some("GL_ARB_multisample"), "FSAA samples" ),
    ];

    for &(param, ext, name) in gl_params.iter() {
        if ext.map_or(true, |s| {
            glfw.extension_supported(s)
        }) {
            let value = 0;
            unsafe { gl::GetIntegerv(param, &value) };
            println!("OpenGL {:s}: {}", name, value);
        };
    }
}

mod gl {
    extern crate libc;

    #[cfg(target_os = "macos")]
    #[link(name="OpenGL", kind="framework")]
    extern { }

    #[cfg(target_os = "linux")]
    #[link(name="GL")]
    extern { }

    pub type GLenum = libc::c_uint;
    pub type GLint  = libc::c_int;

    pub static RED_BITS              : GLenum = 0x0D52;
    pub static GREEN_BITS            : GLenum = 0x0D53;
    pub static BLUE_BITS             : GLenum = 0x0D54;
    pub static ALPHA_BITS            : GLenum = 0x0D55;
    pub static DEPTH_BITS            : GLenum = 0x0D56;
    pub static STENCIL_BITS          : GLenum = 0x0D57;
    pub static ACCUM_RED_BITS        : GLenum = 0x0D58;
    pub static ACCUM_GREEN_BITS      : GLenum = 0x0D59;
    pub static ACCUM_BLUE_BITS       : GLenum = 0x0D5A;
    pub static ACCUM_ALPHA_BITS      : GLenum = 0x0D5B;
    pub static STEREO                : GLenum = 0x0C33;
    pub static SAMPLES_ARB           : GLenum = 0x80A9;

    #[inline(never)]
    #[allow(non_snake_case)]
    pub unsafe fn GetIntegerv(pname: GLenum, params: *const GLint) {
        glGetIntegerv(pname, params)
    }

    extern "C" {
        fn glGetIntegerv(pname: GLenum, params: *const GLint);
    }
}
<|endoftext|>


<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::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();
            }
        }
    }
}
<commit_msg>Fixing debug assert so it doesn't fail due to floating point error<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() * 1000.).round(), 1000.);
                                    // (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>/// Represents a value in Forth's stack
#[derive(Clone, Copy)]
pub struct ForthNum {
    value: i32,
}

impl From<i32> for ForthNum {
    fn from(value: i32) -> ForthNum {
        ForthNum{value: value}
    }
}

impl From<ForthNum> for i32 {
    fn from(num: ForthNum) -> i32 {
        num.value
    }
}

impl From<bool> for ForthNum {
    fn from(value: bool) -> ForthNum {
        ForthNum{value: if value { -1 } else { 0 }}
    }
}

impl From<ForthNum> for bool {
    fn from(num: ForthNum) -> bool {
        num.value != 0
    }
}

impl From<char> for ForthNum {
    fn from(value: char) -> ForthNum {
        ForthNum{value: value as i32}
    }
}

impl From<ForthNum> for char {
    fn from(num: ForthNum) -> char {
        num.value as u8 as char
    }
}
<commit_msg>Cargo fmt<commit_after>/// Represents a value in Forth's stack
#[derive(Clone, Copy)]
pub struct ForthNum {
    value: i32,
}

impl From<i32> for ForthNum {
    fn from(value: i32) -> ForthNum {
        ForthNum { value: value }
    }
}

impl From<ForthNum> for i32 {
    fn from(num: ForthNum) -> i32 {
        num.value
    }
}

impl From<bool> for ForthNum {
    fn from(value: bool) -> ForthNum {
        ForthNum { value: if value { -1 } else { 0 } }
    }
}

impl From<ForthNum> for bool {
    fn from(num: ForthNum) -> bool {
        num.value != 0
    }
}

impl From<char> for ForthNum {
    fn from(value: char) -> ForthNum {
        ForthNum { value: value as i32 }
    }
}

impl From<ForthNum> for char {
    fn from(num: ForthNum) -> char {
        num.value as u8 as char
    }
}
<|endoftext|>


<commit_before>use std::process;

use utils::screen::Screen;
use utils::screen::ScreenStatus;

pub struct topController {
    screen: Screen,
}

impl topController {

    pub fn new() -> topController {
        topController {
            screen: Screen::new(),
        }
    }

    pub fn run(&mut self) {
        let commands = vec!["AWS".to_string(), "q".to_string()];
        self.screen.update_screen(r###"
   -----------------------------------------

   ██████╗  █████╗ ██╗    ██╗███████╗████████╗
   ██╔══██╗██╔══██╗██║    ██║██╔════╝╚══██╔══╝
   ██████╔╝███████║██║ █╗ ██║███████╗   ██║
   ██╔══██╗██╔══██║██║███╗██║╚════██║   ██║
   ██║  ██║██║  ██║╚███╔███╔╝███████║   ██║
   ╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚══════╝   ╚═╝

   ------------------------------------------

   rawst is the interactive tool for AWS CLI written in Rust.
   "###, &commands);

        match self.screen.select_line() {
            ScreenStatus::Selected(ref c) if c == "0" => self.aws(),
            _ => process::exit(0),
        }
    }

    fn aws(&self) {

    }
}
<commit_msg>Add aws controller<commit_after>use std::process;

use utils::screen::Screen;
use utils::screen::ScreenStatus;
use aws::awsController;

pub struct topController {
    screen: Screen,
}

impl topController {

    pub fn new() -> topController {
        topController {
            screen: Screen::new(),
        }
    }

    pub fn run(&mut self) {
        let commands = vec!["a".to_string(), "q".to_string()];
        self.screen.update_screen(r###"
   -----------------------------------------

   ██████╗  █████╗ ██╗    ██╗███████╗████████╗
   ██╔══██╗██╔══██╗██║    ██║██╔════╝╚══██╔══╝
   ██████╔╝███████║██║ █╗ ██║███████╗   ██║
   ██╔══██╗██╔══██║██║███╗██║╚════██║   ██║
   ██║  ██║██║  ██║╚███╔███╔╝███████║   ██║
   ╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚══════╝   ╚═╝

   ------------------------------------------

   rawst is the interactive tool for AWS CLI written in Rust.
   "###, &commands);

        match self.screen.select_line() {
            ScreenStatus::Selected(ref c) if c == "a" => self.aws(),
            _ => process::exit(0),
        }
    }

    fn aws(&self) {
        let mut aws = awsController::new();
        aws.run();
    }
}
<|endoftext|>


<commit_before>use alloc::heap::{Alloc, AllocErr, Layout};

use core::sync::atomic::{AtomicUsize, Ordering};

/// A simple allocator that allocates memory linearly and ignores freed memory.
#[derive(Debug)]
pub struct BumpAllocator {
    heap_start: usize,
    heap_end: usize,
    next: AtomicUsize,
}

impl BumpAllocator {
    pub const fn new(heap_start: usize, heap_end: usize) -> Self {
        Self { heap_start, heap_end, next: AtomicUsize::new(heap_start) }
    }
}

unsafe impl<'a> Alloc for &'a BumpAllocator {
    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
        loop {
            // load current state of the `next` field
            let current_next = self.next.load(Ordering::Relaxed);
            let alloc_start = align_up(current_next, layout.align());
            let alloc_end = alloc_start.saturating_add(layout.size());

            if alloc_end <= self.heap_end {
                // update the `next` pointer if it still has the value `current_next`
                let next_now = self.next.compare_and_swap(current_next, alloc_end,
                    Ordering::Relaxed);
                if next_now == current_next {
                    // next address was successfully updated, allocation succeeded
                    return Ok(alloc_start as *mut u8);
                }
            } else {
                return Err(AllocErr::Exhausted{ request: layout })
            }
        }
    }

    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
        // do nothing, leak memory
    }
}

/// Align downwards. Returns the greatest x with alignment `align`
/// so that x <= addr. The alignment must be a power of 2.
pub fn align_down(addr: usize, align: usize) -> usize {
    if align.is_power_of_two() {
        addr & !(align - 1)
    } else if align == 0 {
        addr
    } else {
        panic!("`align` must be a power of 2");
    }
}

/// Align upwards. Returns the smallest x with alignment `align`
/// so that x >= addr. The alignment must be a power of 2.
pub fn align_up(addr: usize, align: usize) -> usize {
    align_down(addr + align - 1, align)
}
<commit_msg>Panic on alloc::oom instead of calling intrinsics::abort (#375)<commit_after>use alloc::heap::{Alloc, AllocErr, Layout};

use core::sync::atomic::{AtomicUsize, Ordering};

/// A simple allocator that allocates memory linearly and ignores freed memory.
#[derive(Debug)]
pub struct BumpAllocator {
    heap_start: usize,
    heap_end: usize,
    next: AtomicUsize,
}

impl BumpAllocator {
    pub const fn new(heap_start: usize, heap_end: usize) -> Self {
        Self { heap_start, heap_end, next: AtomicUsize::new(heap_start) }
    }
}

unsafe impl<'a> Alloc for &'a BumpAllocator {
    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
        loop {
            // load current state of the `next` field
            let current_next = self.next.load(Ordering::Relaxed);
            let alloc_start = align_up(current_next, layout.align());
            let alloc_end = alloc_start.saturating_add(layout.size());

            if alloc_end <= self.heap_end {
                // update the `next` pointer if it still has the value `current_next`
                let next_now = self.next.compare_and_swap(current_next, alloc_end,
                    Ordering::Relaxed);
                if next_now == current_next {
                    // next address was successfully updated, allocation succeeded
                    return Ok(alloc_start as *mut u8);
                }
            } else {
                return Err(AllocErr::Exhausted{ request: layout })
            }
        }
    }

    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
        // do nothing, leak memory
    }

    fn oom(&mut self, _: AllocErr) -> ! {
        panic!("Out of memory");
    }
}

/// Align downwards. Returns the greatest x with alignment `align`
/// so that x <= addr. The alignment must be a power of 2.
pub fn align_down(addr: usize, align: usize) -> usize {
    if align.is_power_of_two() {
        addr & !(align - 1)
    } else if align == 0 {
        addr
    } else {
        panic!("`align` must be a power of 2");
    }
}

/// Align upwards. Returns the smallest x with alignment `align`
/// so that x >= addr. The alignment must be a power of 2.
pub fn align_up(addr: usize, align: usize) -> usize {
    align_down(addr + align - 1, align)
}
<|endoftext|>


<commit_before>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::os::windows::io::AsRawHandle;
use std::os::windows::io::RawHandle;
use std::ptr;
use std::time::Duration;

use win_util::LargeInteger;
use win_util::SecurityAttributes;
use win_util::SelfRelativeSecurityDescriptor;
use winapi::shared::minwindef::FALSE;
use winapi::shared::winerror::WAIT_TIMEOUT;
use winapi::um::synchapi::CancelWaitableTimer;
use winapi::um::synchapi::SetWaitableTimer;
use winapi::um::synchapi::WaitForSingleObject;
use winapi::um::winbase::CreateWaitableTimerA;
use winapi::um::winbase::INFINITE;
use winapi::um::winbase::WAIT_OBJECT_0;

use super::errno_result;
use super::win::nt_query_timer_resolution;
use super::Result;
use crate::descriptor::AsRawDescriptor;
use crate::descriptor::FromRawDescriptor;
use crate::descriptor::SafeDescriptor;
use crate::timer::Timer;
use crate::timer::WaitResult;

impl AsRawHandle for Timer {
    fn as_raw_handle(&self) -> RawHandle {
        self.handle.as_raw_descriptor()
    }
}

impl Timer {
    /// Creates a new timer.  The timer is initally disarmed and must be armed by calling
    /// `reset`. Note that this timer MAY wake/trigger early due to limitations on
    /// SetWaitableTimer (see https://github.com/rust-lang/rust/issues/43376).
    pub fn new() -> Result<Timer> {
        // Safe because this doesn't modify any memory and we check the return value.
        let handle = unsafe {
            CreateWaitableTimerA(
                // Not inheritable, duplicate before passing to child prcesses
                SecurityAttributes::new_with_security_descriptor(
                    SelfRelativeSecurityDescriptor::get_singleton(),
                    /* inherit= */ false,
                )
                .as_mut(),
                // This is a synchronization timer, not a manual-reset timer.
                FALSE,
                // TODO (colindr) b/145622516 - we may have to give this a name if we later
                // want to use names to test object equality
                ptr::null_mut(),
            )
        };

        if handle.is_null() {
            return errno_result();
        }

        // Safe because we uniquely own the file descriptor.
        Ok(Timer {
            handle: unsafe { SafeDescriptor::from_raw_descriptor(handle) },
            interval: None,
        })
    }

    /// Sets the timer to expire after `dur`. If `interval` is not `None` and non-zero
    /// it represents the period for repeated expirations after the initial expiration.
    /// Otherwise the timer will expire just once.  Cancels any existing duration and
    /// repeating interval.
    pub fn reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()> {
        // If interval is 0 or None it means that this timer does not repeat. We
        // set self.interval to None in this case so it can easily be checked
        // in self.wait.
        if interval == Some(Duration::from_secs(0)) {
            interval = None;
        }
        self.interval = interval;
        // Windows timers use negative values for relative times, and positive
        // values for absolute times, so we'll use negative times.

        // Windows timers also use a 64 number of 100 nanosecond intervals,
        // which we get like so: (dur.as_secs()*1e7 + dur.subsec_nanos()/100)

        let due_time = LargeInteger::new(
            -((dur.as_secs() * 10_000_000 + (dur.subsec_nanos() as u64) / 100) as i64),
        );
        let period: i32 = match interval {
            Some(int) => int.as_millis() as i32,
            None => 0,
        };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe {
            SetWaitableTimer(
                self.as_raw_descriptor(),
                &*due_time,
                period,
                None,            // no completion routine
                ptr::null_mut(), // or routine argument
                FALSE,           // no restoring system from power conservation mode
            )
        };
        if ret == 0 {
            return errno_result();
        }

        Ok(())
    }

    /// Waits until the timer expires or an optional wait timeout expires, whichever happens first.
    ///
    /// # Returns
    ///
    /// - `WaitResult::Expired` if the timer expired.
    /// - `WaitResult::Timeout` if `timeout` was not `None` and the timer did not expire within the
    ///   specified timeout period.
    pub fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> {
        let timeout = match timeout {
            None => INFINITE,
            Some(dur) => dur.as_millis() as u32,
        };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { WaitForSingleObject(self.as_raw_descriptor(), timeout) };

        // Should return WAIT_OBJECT_0, otherwise it's some sort of error or
        // timeout (which shouldn't happen in this case).
        match ret {
            WAIT_OBJECT_0 => Ok(WaitResult::Expired),
            WAIT_TIMEOUT => Ok(WaitResult::Timeout),
            _ => errno_result(),
        }
    }

    /// Waits until the timer expires.
    pub fn wait(&mut self) -> Result<WaitResult> {
        self.wait_for(None)
    }

    /// After a timer is triggered from an EventContext, mark the timer as having been waited for.
    /// If a timer is not marked waited, it will immediately trigger the event context again. This
    /// does not need to be called after calling Timer::wait.
    ///
    /// Returns true if the timer has been adjusted since the EventContext was triggered by this
    /// timer.
    pub fn mark_waited(&mut self) -> Result<bool> {
        // We use a synchronization timer on windows, meaning waiting on the timer automatically
        // un-signals the timer. We assume this is atomic so the return value is always false.
        Ok(false)
    }

    /// Disarms the timer.
    pub fn clear(&mut self) -> Result<()> {
        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { CancelWaitableTimer(self.as_raw_descriptor()) };

        if ret == 0 {
            return errno_result();
        }

        self.interval = None;
        Ok(())
    }

    /// Returns the resolution of timers on the host.
    pub fn resolution() -> Result<Duration> {
        nt_query_timer_resolution().map(|(current_res, _)| current_res)
    }
}
<commit_msg>base: windows: timer: fix interval < 1ms<commit_after>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::os::windows::io::AsRawHandle;
use std::os::windows::io::RawHandle;
use std::ptr;
use std::time::Duration;

use win_util::LargeInteger;
use win_util::SecurityAttributes;
use win_util::SelfRelativeSecurityDescriptor;
use winapi::shared::minwindef::FALSE;
use winapi::shared::winerror::WAIT_TIMEOUT;
use winapi::um::synchapi::CancelWaitableTimer;
use winapi::um::synchapi::SetWaitableTimer;
use winapi::um::synchapi::WaitForSingleObject;
use winapi::um::winbase::CreateWaitableTimerA;
use winapi::um::winbase::INFINITE;
use winapi::um::winbase::WAIT_OBJECT_0;

use super::errno_result;
use super::win::nt_query_timer_resolution;
use super::Result;
use crate::descriptor::AsRawDescriptor;
use crate::descriptor::FromRawDescriptor;
use crate::descriptor::SafeDescriptor;
use crate::timer::Timer;
use crate::timer::WaitResult;

impl AsRawHandle for Timer {
    fn as_raw_handle(&self) -> RawHandle {
        self.handle.as_raw_descriptor()
    }
}

impl Timer {
    /// Creates a new timer.  The timer is initally disarmed and must be armed by calling
    /// `reset`. Note that this timer MAY wake/trigger early due to limitations on
    /// SetWaitableTimer (see https://github.com/rust-lang/rust/issues/43376).
    pub fn new() -> Result<Timer> {
        // Safe because this doesn't modify any memory and we check the return value.
        let handle = unsafe {
            CreateWaitableTimerA(
                // Not inheritable, duplicate before passing to child prcesses
                SecurityAttributes::new_with_security_descriptor(
                    SelfRelativeSecurityDescriptor::get_singleton(),
                    /* inherit= */ false,
                )
                .as_mut(),
                // This is a synchronization timer, not a manual-reset timer.
                FALSE,
                // TODO (colindr) b/145622516 - we may have to give this a name if we later
                // want to use names to test object equality
                ptr::null_mut(),
            )
        };

        if handle.is_null() {
            return errno_result();
        }

        // Safe because we uniquely own the file descriptor.
        Ok(Timer {
            handle: unsafe { SafeDescriptor::from_raw_descriptor(handle) },
            interval: None,
        })
    }

    /// Sets the timer to expire after `dur`. If `interval` is not `None` and non-zero
    /// it represents the period for repeated expirations after the initial expiration.
    /// Otherwise the timer will expire just once.  Cancels any existing duration and
    /// repeating interval.
    pub fn reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()> {
        // If interval is 0 or None it means that this timer does not repeat. We
        // set self.interval to None in this case so it can easily be checked
        // in self.wait.
        if interval == Some(Duration::from_secs(0)) {
            interval = None;
        }
        self.interval = interval;
        // Windows timers use negative values for relative times, and positive
        // values for absolute times, so we'll use negative times.

        // Windows timers also use a 64 number of 100 nanosecond intervals,
        // which we get like so: (dur.as_secs()*1e7 + dur.subsec_nanos()/100)

        let due_time = LargeInteger::new(
            -((dur.as_secs() * 10_000_000 + (dur.subsec_nanos() as u64) / 100) as i64),
        );
        let period: i32 = match interval {
            // Period is in ms, and 0ms means non-periodic, so we convert to ms and
            // make sure it's non-zero.
            Some(int) => std::cmp::max(1, int.as_millis() as i32),
            // Period of 0ms=non-periodic.
            None => 0,
        };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe {
            SetWaitableTimer(
                self.as_raw_descriptor(),
                &*due_time,
                period,
                None,            // no completion routine
                ptr::null_mut(), // or routine argument
                FALSE,           // no restoring system from power conservation mode
            )
        };
        if ret == 0 {
            return errno_result();
        }

        Ok(())
    }

    /// Waits until the timer expires or an optional wait timeout expires, whichever happens first.
    ///
    /// # Returns
    ///
    /// - `WaitResult::Expired` if the timer expired.
    /// - `WaitResult::Timeout` if `timeout` was not `None` and the timer did not expire within the
    ///   specified timeout period.
    pub fn wait_for(&mut self, timeout: Option<Duration>) -> Result<WaitResult> {
        let timeout = match timeout {
            None => INFINITE,
            Some(dur) => dur.as_millis() as u32,
        };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { WaitForSingleObject(self.as_raw_descriptor(), timeout) };

        // Should return WAIT_OBJECT_0, otherwise it's some sort of error or
        // timeout (which shouldn't happen in this case).
        match ret {
            WAIT_OBJECT_0 => Ok(WaitResult::Expired),
            WAIT_TIMEOUT => Ok(WaitResult::Timeout),
            _ => errno_result(),
        }
    }

    /// Waits until the timer expires.
    pub fn wait(&mut self) -> Result<WaitResult> {
        self.wait_for(None)
    }

    /// After a timer is triggered from an EventContext, mark the timer as having been waited for.
    /// If a timer is not marked waited, it will immediately trigger the event context again. This
    /// does not need to be called after calling Timer::wait.
    ///
    /// Returns true if the timer has been adjusted since the EventContext was triggered by this
    /// timer.
    pub fn mark_waited(&mut self) -> Result<bool> {
        // We use a synchronization timer on windows, meaning waiting on the timer automatically
        // un-signals the timer. We assume this is atomic so the return value is always false.
        Ok(false)
    }

    /// Disarms the timer.
    pub fn clear(&mut self) -> Result<()> {
        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { CancelWaitableTimer(self.as_raw_descriptor()) };

        if ret == 0 {
            return errno_result();
        }

        self.interval = None;
        Ok(())
    }

    /// Returns the resolution of timers on the host.
    pub fn resolution() -> Result<Duration> {
        nt_query_timer_resolution().map(|(current_res, _)| current_res)
    }
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt as _, WriteBytesExt as _};
use shakmaty::uci::Uci;
use shakmaty::{Role, Square};
use std::convert::TryFrom;
use std::io::{self, Read, Write};

pub fn read_uci<R: Read>(reader: &mut R) -> io::Result<Uci> {
    let n = reader.read_u16::<LittleEndian>()?;
    let from = Square::try_from(n & 63).unwrap();
    let to = Square::try_from((n >> 6) & 63).unwrap();
    let role = Role::try_from(n >> 12).ok();
    Ok(if from == to {
        match role {
            Some(role) => Uci::Put { role, to },
            None => Uci::Null,
        }
    } else {
        Uci::Normal {
            from,
            to,
            promotion: role,
        }
    })
}

pub fn write_uci<W: Write>(writer: &mut W, uci: &Uci) -> io::Result<()> {
    let (from, to, role) = match *uci {
        Uci::Normal {
            from,
            to,
            promotion,
        } => (from, to, promotion),
        Uci::Put { role, to } => (to, to, Some(role)),
        Uci::Null => (Square::A1, Square::A1, None),
    };
    writer.write_u16::<LittleEndian>(
        u16::from(from) | (u16::from(to) << 6) | (role.map(u16::from).unwrap_or_default() << 12),
    )
}

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

    #[test]
    fn test_uci_roundtrip() {
        let moves = [
            Uci::Null,
            Uci::Normal {
                from: Square::A1,
                to: Square::H8,
                promotion: None,
            },
            Uci::Normal {
                from: Square::A2,
                to: Square::A1,
                promotion: Some(Role::King),
            },
            Uci::Put {
                to: Square::A1,
                role: Role::Knight,
            },
        ];

        let mut writer = Cursor::new(Vec::new());
        for uci in &moves {
            write_uci(&mut writer, uci).unwrap();
        }

        let mut reader = Cursor::new(writer.into_inner());
        for uci in moves {
            assert_eq!(uci, read_uci(&mut reader).unwrap());
        }
    }
}
<commit_msg>avoid unwrap except in tests<commit_after>use byteorder::{LittleEndian, ReadBytesExt as _, WriteBytesExt as _};
use shakmaty::uci::Uci;
use shakmaty::{Role, Square};
use std::convert::TryFrom;
use std::io::{self, Read, Write};

pub fn read_uci<R: Read>(reader: &mut R) -> io::Result<Uci> {
    let n = reader.read_u16::<LittleEndian>()?;
    let from = Square::new(u32::from(n & 63));
    let to = Square::new(u32::from((n >> 6) & 63));
    let role = Role::try_from(n >> 12).ok();
    Ok(if from == to {
        match role {
            Some(role) => Uci::Put { role, to },
            None => Uci::Null,
        }
    } else {
        Uci::Normal {
            from,
            to,
            promotion: role,
        }
    })
}

pub fn write_uci<W: Write>(writer: &mut W, uci: &Uci) -> io::Result<()> {
    let (from, to, role) = match *uci {
        Uci::Normal {
            from,
            to,
            promotion,
        } => (from, to, promotion),
        Uci::Put { role, to } => (to, to, Some(role)),
        Uci::Null => (Square::A1, Square::A1, None),
    };
    writer.write_u16::<LittleEndian>(
        u16::from(from) | (u16::from(to) << 6) | (role.map(u16::from).unwrap_or_default() << 12),
    )
}

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

    #[test]
    fn test_uci_roundtrip() {
        let moves = [
            Uci::Null,
            Uci::Normal {
                from: Square::A1,
                to: Square::H8,
                promotion: None,
            },
            Uci::Normal {
                from: Square::A2,
                to: Square::A1,
                promotion: Some(Role::King),
            },
            Uci::Put {
                to: Square::A1,
                role: Role::Knight,
            },
        ];

        let mut writer = Cursor::new(Vec::new());
        for uci in &moves {
            write_uci(&mut writer, uci).unwrap();
        }

        let mut reader = Cursor::new(writer.into_inner());
        for uci in moves {
            assert_eq!(uci, read_uci(&mut reader).unwrap());
        }
    }
}
<|endoftext|>


<commit_before>use ::{KeyType, ValueType};

use wal_file::KeyValuePair;

use std::iter::{Peekable, empty, Map};
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Entry;
use std::collections::btree_map::Entry::{Occupied, Vacant};
use std::collections::btree_map;
use std::collections::btree_set;

pub struct MultiMap<K: KeyType, V: ValueType> {
    multi_map: BTreeMap<K, BTreeSet<V>>,
    count: usize  // total number of KV pairs
}

pub struct MultiMapIterator<'a, K: KeyType + 'a, V: ValueType + 'a> {
    cur_key: Option<&'a K>,
    key_it: btree_map::Iter<'a,K,BTreeSet<V>>,
    value_it: Option<btree_set::Iter<'a,V>>,
}

impl <'a, K: KeyType, V: ValueType> MultiMap<K,V> {
    pub fn new() -> MultiMap<K,V> {
        return MultiMap{multi_map: BTreeMap::<K,BTreeSet<V>>::new(), count: 0};
    }

    pub fn insert(&mut self, key: K, value: V) -> usize {
        self.count += 1;

        if let Some(set) = self.multi_map.get_mut(&key) {
            set.insert(value);
            return self.count;
        }

        let mut set = BTreeSet::<V>::new();

        set.insert(value);

        self.multi_map.insert(key, set);

        return self.count;
    }

    /*
     * Might want to re-think this and return an Error
     * as there isn't a great way to tell the user that a
     * key or value wasn't found
     */
    pub fn delete(&mut self, key: K, value: V) -> usize {
        if let Occupied(mut entry) = self.multi_map.entry(key) {

            if entry.get_mut().remove(&value) {
                self.count -= 1;
            }

            if entry.get().is_empty() {
                entry.remove_entry();
            }
        }

        return self.count;
    }

    pub fn size(&self) -> usize {
        return self.count;
    }
}

impl <'a, K: KeyType, V: ValueType> IntoIterator for &'a mut MultiMap<K,V> {
    type Item = KeyValuePair<K,V>;
    type IntoIter = MultiMapIterator<'a,K,V>;

    fn into_iter(self) -> Self::IntoIter {
        let mut key_it = self.multi_map.iter();
        let cur_entry = key_it.next();

        // check to see if our map is empty
        if cur_entry.is_none() {
            return MultiMapIterator{cur_key: None, key_it: key_it, value_it: None};
        }

        // safe to call unwrap as we tested above
        let (cur_key, cur_set) = cur_entry.unwrap();

        return MultiMapIterator{cur_key: Some(cur_key), key_it: key_it, value_it: Some(cur_set.iter())};
    }
}

impl <'a, K: KeyType, V: ValueType> Iterator for MultiMapIterator<'a,K,V> {
    type Item = KeyValuePair<K,V>;

    fn next(&mut self) -> Option<Self::Item> {
        // this is our invariant, when it's None we've gone through everything
        if self.cur_key.is_none() {
            return None
        }

        // should be safe to call unwrap here, because we checked for None above
        let mut cur_val = self.value_it.as_mut().unwrap().next();

        // check to see if we've gone through everything in the set
        if cur_val.is_none() {
            let cur_entry = self.key_it.next(); // increment our key iterator

            if cur_entry.is_none() {
                self.cur_key = None; // set our invariant
                return None;
            }

            // safe to call unwrap because we checked it above
            let (cur_key, cur_set) = cur_entry.unwrap();

            self.cur_key = Some(cur_key); // set our key
            self.value_it = Some(cur_set.iter()); // set our value iterator
            cur_val = self.value_it.as_mut().unwrap().next(); // set our current value
        }

        return Some(KeyValuePair{key: self.cur_key.unwrap().clone(), value: cur_val.unwrap().clone()});
    }
}

#[cfg(test)]
mod tests {
    use multi_map::{MultiMap, MultiMapIterator};
    use wal_file::KeyValuePair;

    #[test]
    fn test_insert() {
        let mut mmap = MultiMap::<i32,String>::new();

        assert!(mmap.insert(12, String::from("abc")) == 1);
        assert!(mmap.insert(23, String::from("abc")) == 2);
        assert!(mmap.insert(23, String::from("def")) == 3);

        let mut it = mmap.into_iter();

        let e1 = it.next().unwrap();
        assert!(12 == e1.key);
        assert!(String::from("abc") == e1.value);

        let e2 = it.next().unwrap();
        assert!(23 == e2.key);
        assert!(String::from("abc") == e2.value);

        let e3 = it.next().unwrap();
        assert!(23 == e3.key);
        assert!(String::from("def") == e3.value);
    }

    #[test]
    fn test_delete() {
        let mut mmap = MultiMap::<i32,String>::new();

        assert!(mmap.insert(12, String::from("abc")) == 1);
        assert!(mmap.insert(23, String::from("abc")) == 2);
        assert!(mmap.insert(23, String::from("def")) == 3);

        assert!(mmap.size() == 3);

        assert!(mmap.delete(12, String::from("abc")) == 2);
        assert!(mmap.delete(23, String::from("abc")) == 1);
        assert!(mmap.delete(23, String::from("abc")) == 1); // should NOT find this one
        assert!(mmap.delete(23, String::from("def")) == 0);

        assert!(mmap.size() == 0);

        let mut it = mmap.into_iter();

        assert!(it.next() == None);
    }
}

<commit_msg>Added get method to multi_map<commit_after>use ::{KeyType, ValueType};

use wal_file::KeyValuePair;

use std::iter::{empty, Map};
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Entry;
use std::collections::btree_map::Entry::{Occupied, Vacant};
use std::collections::btree_map;
use std::collections::btree_set;
use std::collections::btree_set::Iter;

pub struct MultiMap<K: KeyType, V: ValueType> {
    multi_map: BTreeMap<K, BTreeSet<V>>,
    count: usize  // total number of KV pairs
}

pub struct MultiMapIterator<'a, K: KeyType + 'a, V: ValueType + 'a> {
    cur_key: Option<&'a K>,
    key_it: btree_map::Iter<'a,K,BTreeSet<V>>,
    value_it: Option<btree_set::Iter<'a,V>>,
}

impl <'a, K: KeyType, V: ValueType> MultiMap<K,V> {
    pub fn new() -> MultiMap<K,V> {
        return MultiMap{multi_map: BTreeMap::<K,BTreeSet<V>>::new(), count: 0};
    }

    pub fn insert(&mut self, key: K, value: V) -> usize {
        self.count += 1;

        if let Some(set) = self.multi_map.get_mut(&key) {
            set.insert(value);
            return self.count;
        }

        let mut set = BTreeSet::<V>::new();

        set.insert(value);

        self.multi_map.insert(key, set);

        return self.count;
    }

    /*
     * It would be nice to return a "generic" iterator here
     * not one tied to our underlying implementation. Not really
     * sure how: https://goo.gl/9sisAb
     */
    pub fn get(&self, key: &K) -> Option<Iter<V>> {
        return self.multi_map.get(key).map(|set| set.iter());
    }

    /*
     * Might want to re-think this and return an Error
     * as there isn't a great way to tell the user that a
     * key or value wasn't found
     */
    pub fn delete(&mut self, key: K, value: V) -> usize {
        if let Occupied(mut entry) = self.multi_map.entry(key) {

            if entry.get_mut().remove(&value) {
                self.count -= 1;
            }

            if entry.get().is_empty() {
                entry.remove_entry();
            }
        }

        return self.count;
    }

    pub fn size(&self) -> usize {
        return self.count;
    }
}

impl <'a, K: KeyType, V: ValueType> IntoIterator for &'a mut MultiMap<K,V> {
    type Item = KeyValuePair<K,V>;
    type IntoIter = MultiMapIterator<'a,K,V>;

    fn into_iter(self) -> Self::IntoIter {
        let mut key_it = self.multi_map.iter();
        let cur_entry = key_it.next();

        // check to see if our map is empty
        if cur_entry.is_none() {
            return MultiMapIterator{cur_key: None, key_it: key_it, value_it: None};
        }

        // safe to call unwrap as we tested above
        let (cur_key, cur_set) = cur_entry.unwrap();

        return MultiMapIterator{cur_key: Some(cur_key), key_it: key_it, value_it: Some(cur_set.iter())};
    }
}

impl <'a, K: KeyType, V: ValueType> Iterator for MultiMapIterator<'a,K,V> {
    type Item = KeyValuePair<K,V>;

    fn next(&mut self) -> Option<Self::Item> {
        // this is our invariant, when it's None we've gone through everything
        if self.cur_key.is_none() {
            return None
        }

        // should be safe to call unwrap here, because we checked for None above
        let mut cur_val = self.value_it.as_mut().unwrap().next();

        // check to see if we've gone through everything in the set
        if cur_val.is_none() {
            let cur_entry = self.key_it.next(); // increment our key iterator

            if cur_entry.is_none() {
                self.cur_key = None; // set our invariant
                return None;
            }

            // safe to call unwrap because we checked it above
            let (cur_key, cur_set) = cur_entry.unwrap();

            self.cur_key = Some(cur_key); // set our key
            self.value_it = Some(cur_set.iter()); // set our value iterator
            cur_val = self.value_it.as_mut().unwrap().next(); // set our current value
        }

        return Some(KeyValuePair{key: self.cur_key.unwrap().clone(), value: cur_val.unwrap().clone()});
    }
}

#[cfg(test)]
mod tests {
    use multi_map::{MultiMap, MultiMapIterator};
    use wal_file::KeyValuePair;

    #[test]
    fn test_insert() {
        let mut mmap = MultiMap::<i32,String>::new();

        assert!(mmap.insert(12, String::from("abc")) == 1);
        assert!(mmap.insert(23, String::from("abc")) == 2);
        assert!(mmap.insert(23, String::from("def")) == 3);

        let mut it = mmap.into_iter();

        let e1 = it.next().unwrap();
        assert!(12 == e1.key);
        assert!(String::from("abc") == e1.value);

        let e2 = it.next().unwrap();
        assert!(23 == e2.key);
        assert!(String::from("abc") == e2.value);

        let e3 = it.next().unwrap();
        assert!(23 == e3.key);
        assert!(String::from("def") == e3.value);
    }

    #[test]
    fn test_get() {
        let mut mmap = MultiMap::<i32,String>::new();

        assert!(mmap.insert(12, String::from("abc")) == 1);
        assert!(mmap.insert(23, String::from("abc")) == 2);
        assert!(mmap.insert(23, String::from("def")) == 3);

        let mut it1 = mmap.get(&12).unwrap();

        assert!(it1.next().unwrap() == "abc");
        assert!(it1.next() == None);

        let mut it2 = mmap.get(&23).unwrap();

        assert!(it2.next().unwrap() == "abc");
        assert!(it2.next().unwrap() == "def");
        assert!(it2.next() == None);
    }

    #[test]
    fn test_delete() {
        let mut mmap = MultiMap::<i32,String>::new();

        assert!(mmap.insert(12, String::from("abc")) == 1);
        assert!(mmap.insert(23, String::from("abc")) == 2);
        assert!(mmap.insert(23, String::from("def")) == 3);

        assert!(mmap.size() == 3);

        assert!(mmap.delete(12, String::from("abc")) == 2);
        assert!(mmap.delete(23, String::from("abc")) == 1);
        assert!(mmap.delete(23, String::from("abc")) == 1); // should NOT find this one
        assert!(mmap.delete(23, String::from("def")) == 0);

        assert!(mmap.size() == 0);

        let mut it = mmap.into_iter();

        assert!(it.next() == None);
    }
}

<|endoftext|>


<commit_before>use std::uint::iterate;
use std::num::{Zero, Algebraic, Bounded};
use std::rand::{Rand, Rng, RngUtil};
use std::vec::{map};
use std::cmp::ApproxEq;
use ndim::dvec::{DVec, zero_vec_with_dim, is_zero_vec};
use traits::basis::Basis;
use traits::ring::Ring;
use traits::division_ring::DivisionRing;
use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::translation::Translation;
use traits::flatten::Flatten;
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};

// D is a phantom parameter, used only as a dimensional token.
// Its allows use to encode the vector dimension at the type-level.
// It can be anything implementing the Dim trait. However, to avoid confusion,
// using d0, d1, d2, d3, ..., d7 (or your own dn) are prefered.
#[deriving(Eq, Ord, ToStr)]
pub struct NVec<D, N>
{ at: DVec<N> }

impl<D: Dim, N> Dim for NVec<D, N>
{
  #[inline(always)]
  fn dim() -> uint
  { Dim::dim::<D>() }
}

impl<D, N: Clone> Clone for NVec<D, N>
{
  #[inline(always)]
  fn clone(&self) -> NVec<D, N>
  { NVec{ at: self.at.clone() } }
}

impl<D, N: Copy + Add<N,N>> Add<NVec<D, N>, NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn add(&self, other: &NVec<D, N>) -> NVec<D, N>
  { NVec { at: self.at + other.at } }
}

impl<D, N: Copy + Sub<N,N>> Sub<NVec<D, N>, NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn sub(&self, other: &NVec<D, N>) -> NVec<D, N>
  { NVec { at: self.at - other.at } }
}

impl<D, N: Copy + Neg<N>> Neg<NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn neg(&self) -> NVec<D, N>
  { NVec { at: -self.at } }
}

impl<D: Dim, N: Copy + Ring>
Dot<N> for NVec<D, N>
{
  #[inline(always)]
  fn dot(&self, other: &NVec<D, N>) -> N
  { self.at.dot(&other.at) }
}

impl<D: Dim, N: Copy + Ring> SubDot<N> for NVec<D, N>
{
  #[inline(always)]
  fn sub_dot(&self, a: &NVec<D, N>, b: &NVec<D, N>) -> N
  { self.at.sub_dot(&a.at, &b.at) }
}

impl<D: Dim, N: Copy + Mul<N, N>>
ScalarMul<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_mul(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_mul(s) } }

  #[inline(always)]
  fn scalar_mul_inplace(&mut self, s: &N)
  { self.at.scalar_mul_inplace(s) }
}

impl<D: Dim, N: Copy + Div<N, N>>
ScalarDiv<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_div(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_div(s) } }

  #[inline(always)]
  fn scalar_div_inplace(&mut self, s: &N)
  { self.at.scalar_div_inplace(s) }
}

impl<D: Dim, N: Copy + Add<N, N>>
ScalarAdd<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_add(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_add(s) } }

  #[inline(always)]
  fn scalar_add_inplace(&mut self, s: &N)
  { self.at.scalar_add_inplace(s) }
}

impl<D: Dim, N: Copy + Sub<N, N>>
ScalarSub<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_sub(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_sub(s) } }

  #[inline(always)]
  fn scalar_sub_inplace(&mut self, s: &N)
  { self.scalar_sub_inplace(s) }
}

impl<D: Dim, N: Clone + Copy + Add<N, N>> Translation<NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn translation(&self) -> NVec<D, N>
  { self.clone() }

  #[inline(always)]
  fn translated(&self, t: &NVec<D, N>) -> NVec<D, N>
  { self + *t }

  #[inline(always)]
  fn translate(&mut self, t: &NVec<D, N>)
  { *self = *self + *t; }
}

impl<D: Dim, N: Copy + DivisionRing + Algebraic + Clone>
Norm<N> for NVec<D, N>
{
  #[inline(always)]
  fn sqnorm(&self) -> N
  { self.dot(self) }

  #[inline(always)]
  fn norm(&self) -> N
  { self.sqnorm().sqrt() }

  #[inline(always)]
  fn normalized(&self) -> NVec<D, N>
  {
    let mut res : NVec<D, N> = self.clone();

    res.normalize();

    res
  }

  #[inline(always)]
  fn normalize(&mut self) -> N
  { self.at.normalize() }
}

impl<D: Dim,
     N: Copy + DivisionRing + Algebraic + Clone + ApproxEq<N>>
Basis for NVec<D, N>
{
  #[inline(always)]
  fn canonical_basis() -> ~[NVec<D, N>]
  { map(DVec::canonical_basis_with_dim(Dim::dim::<D>()), |&e| NVec { at: e }) }

  #[inline(always)]
  fn orthogonal_subspace_basis(&self) -> ~[NVec<D, N>]
  { map(self.at.orthogonal_subspace_basis(), |&e| NVec { at: e }) }
}

// FIXME: I dont really know how te generalize the cross product int
// n-dimensions…
// impl<N: Copy + Mul<N, N> + Sub<N, N>> Cross<N> for NVec<D, N>
// {
//   fn cross(&self, other: &NVec<D, N>) -> N
//   { self.x * other.y - self.y * other.x }
// }

impl<D: Dim, N: Copy + Zero> Zero for NVec<D, N>
{
  #[inline(always)]
  fn zero() -> NVec<D, N>
  { NVec { at: zero_vec_with_dim(Dim::dim::<D>()) } }

  #[inline(always)]
  fn is_zero(&self) -> bool
  { is_zero_vec(&self.at) }
}

impl<D, N: ApproxEq<N>> ApproxEq<N> for NVec<D, N>
{
  #[inline(always)]
  fn approx_epsilon() -> N
  { ApproxEq::approx_epsilon::<N, N>() }

  #[inline(always)]
  fn approx_eq(&self, other: &NVec<D, N>) -> bool
  { self.at.approx_eq(&other.at) }

  #[inline(always)]
  fn approx_eq_eps(&self, other: &NVec<D, N>, epsilon: &N) -> bool
  { self.at.approx_eq_eps(&other.at, epsilon) }
}

impl<D: Dim, N: Rand + Zero + Copy> Rand for NVec<D, N>
{
  #[inline(always)]
  fn rand<R: Rng>(rng: &mut R) -> NVec<D, N>
  {
    let     dim = Dim::dim::<D>();
    let mut res : NVec<D, N> = Zero::zero();

    for iterate(0u, dim) |i|
    { res.at.at[i] = rng.gen() }

    res
  }
}

impl<D: Dim, N: Zero + Copy> Flatten<N> for NVec<D, N>
{
  #[inline(always)]
  fn flat_size() -> uint
  { Dim::dim::<D>() }

  #[inline(always)]
  fn from_flattened(l: &[N], off: uint) -> NVec<D, N>
  {
    let     dim = Dim::dim::<D>();
    let mut res = Zero::zero::<NVec<D, N>>();

    for iterate(0u, dim) |i|
    { res.at.at[i] = copy l[off + i] }

    res
  }

  #[inline(always)]
  fn flatten(&self) -> ~[N]
  {
    let     dim = Dim::dim::<D>();
    let mut res = ~[];

    for iterate(0u, dim) |i|
    { res.push(copy self.at.at[i]) }

    res
  }

  #[inline(always)]
  fn flatten_to(&self, l: &mut [N], off: uint)
  {
    let dim = Dim::dim::<D>();

    for iterate(0u, dim) |i|
    { l[off + i] = copy self.at.at[i] }
  }
}

impl<D: Dim, N: Bounded + Zero + Add<N, N> + Copy> Bounded for NVec<D, N>
{
  #[inline(always)]
  fn max_value() -> NVec<D, N>
  { Zero::zero::<NVec<D, N>>().scalar_add(&Bounded::max_value()) }

  #[inline(always)]
  fn min_value() -> NVec<D, N>
  { Zero::zero::<NVec<D, N>>().scalar_add(&Bounded::min_value()) }
}
<commit_msg>Fix some infinite recursion on nvec.<commit_after>use std::uint::iterate;
use std::num::{Zero, Algebraic, Bounded};
use std::rand::{Rand, Rng, RngUtil};
use std::vec::{map};
use std::cmp::ApproxEq;
use ndim::dvec::{DVec, zero_vec_with_dim, is_zero_vec};
use traits::basis::Basis;
use traits::ring::Ring;
use traits::division_ring::DivisionRing;
use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::translation::Translation;
use traits::flatten::Flatten;
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};

// D is a phantom parameter, used only as a dimensional token.
// Its allows use to encode the vector dimension at the type-level.
// It can be anything implementing the Dim trait. However, to avoid confusion,
// using d0, d1, d2, d3, ..., d7 (or your own dn) are prefered.
#[deriving(Eq, Ord, ToStr)]
pub struct NVec<D, N>
{ at: DVec<N> }

impl<D: Dim, N> Dim for NVec<D, N>
{
  #[inline(always)]
  fn dim() -> uint
  { Dim::dim::<D>() }
}

impl<D, N: Clone> Clone for NVec<D, N>
{
  #[inline(always)]
  fn clone(&self) -> NVec<D, N>
  { NVec{ at: self.at.clone() } }
}

impl<D, N: Copy + Add<N,N>> Add<NVec<D, N>, NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn add(&self, other: &NVec<D, N>) -> NVec<D, N>
  { NVec { at: self.at + other.at } }
}

impl<D, N: Copy + Sub<N,N>> Sub<NVec<D, N>, NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn sub(&self, other: &NVec<D, N>) -> NVec<D, N>
  { NVec { at: self.at - other.at } }
}

impl<D, N: Copy + Neg<N>> Neg<NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn neg(&self) -> NVec<D, N>
  { NVec { at: -self.at } }
}

impl<D: Dim, N: Copy + Ring>
Dot<N> for NVec<D, N>
{
  #[inline(always)]
  fn dot(&self, other: &NVec<D, N>) -> N
  { self.at.dot(&other.at) }
}

impl<D: Dim, N: Copy + Ring> SubDot<N> for NVec<D, N>
{
  #[inline(always)]
  fn sub_dot(&self, a: &NVec<D, N>, b: &NVec<D, N>) -> N
  { self.at.sub_dot(&a.at, &b.at) }
}

impl<D: Dim, N: Copy + Mul<N, N>>
ScalarMul<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_mul(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_mul(s) } }

  #[inline(always)]
  fn scalar_mul_inplace(&mut self, s: &N)
  { self.at.scalar_mul_inplace(s) }
}

impl<D: Dim, N: Copy + Div<N, N>>
ScalarDiv<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_div(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_div(s) } }

  #[inline(always)]
  fn scalar_div_inplace(&mut self, s: &N)
  { self.at.scalar_div_inplace(s) }
}

impl<D: Dim, N: Copy + Add<N, N>>
ScalarAdd<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_add(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_add(s) } }

  #[inline(always)]
  fn scalar_add_inplace(&mut self, s: &N)
  { self.at.scalar_add_inplace(s) }
}

impl<D: Dim, N: Copy + Sub<N, N>>
ScalarSub<N> for NVec<D, N>
{
  #[inline(always)]
  fn scalar_sub(&self, s: &N) -> NVec<D, N>
  { NVec { at: self.at.scalar_sub(s) } }

  #[inline(always)]
  fn scalar_sub_inplace(&mut self, s: &N)
  { self.at.scalar_sub_inplace(s) }
}

impl<D: Dim, N: Clone + Copy + Add<N, N>> Translation<NVec<D, N>> for NVec<D, N>
{
  #[inline(always)]
  fn translation(&self) -> NVec<D, N>
  { self.clone() }

  #[inline(always)]
  fn translated(&self, t: &NVec<D, N>) -> NVec<D, N>
  { self + *t }

  #[inline(always)]
  fn translate(&mut self, t: &NVec<D, N>)
  { *self = *self + *t; }
}

impl<D: Dim, N: Copy + DivisionRing + Algebraic + Clone>
Norm<N> for NVec<D, N>
{
  #[inline(always)]
  fn sqnorm(&self) -> N
  { self.at.sqnorm() }

  #[inline(always)]
  fn norm(&self) -> N
  { self.at.norm() }

  #[inline(always)]
  fn normalized(&self) -> NVec<D, N>
  {
    let mut res : NVec<D, N> = self.clone();

    res.normalize();

    res
  }

  #[inline(always)]
  fn normalize(&mut self) -> N
  { self.at.normalize() }
}

impl<D: Dim,
     N: Copy + DivisionRing + Algebraic + Clone + ApproxEq<N>>
Basis for NVec<D, N>
{
  #[inline(always)]
  fn canonical_basis() -> ~[NVec<D, N>]
  { map(DVec::canonical_basis_with_dim(Dim::dim::<D>()), |&e| NVec { at: e }) }

  #[inline(always)]
  fn orthogonal_subspace_basis(&self) -> ~[NVec<D, N>]
  { map(self.at.orthogonal_subspace_basis(), |&e| NVec { at: e }) }
}

// FIXME: I dont really know how te generalize the cross product int
// n-dimensions…
// impl<N: Copy + Mul<N, N> + Sub<N, N>> Cross<N> for NVec<D, N>
// {
//   fn cross(&self, other: &NVec<D, N>) -> N
//   { self.x * other.y - self.y * other.x }
// }

impl<D: Dim, N: Copy + Zero> Zero for NVec<D, N>
{
  #[inline(always)]
  fn zero() -> NVec<D, N>
  { NVec { at: zero_vec_with_dim(Dim::dim::<D>()) } }

  #[inline(always)]
  fn is_zero(&self) -> bool
  { is_zero_vec(&self.at) }
}

impl<D, N: ApproxEq<N>> ApproxEq<N> for NVec<D, N>
{
  #[inline(always)]
  fn approx_epsilon() -> N
  { ApproxEq::approx_epsilon::<N, N>() }

  #[inline(always)]
  fn approx_eq(&self, other: &NVec<D, N>) -> bool
  { self.at.approx_eq(&other.at) }

  #[inline(always)]
  fn approx_eq_eps(&self, other: &NVec<D, N>, epsilon: &N) -> bool
  { self.at.approx_eq_eps(&other.at, epsilon) }
}

impl<D: Dim, N: Rand + Zero + Copy> Rand for NVec<D, N>
{
  #[inline(always)]
  fn rand<R: Rng>(rng: &mut R) -> NVec<D, N>
  {
    let     dim = Dim::dim::<D>();
    let mut res : NVec<D, N> = Zero::zero();

    for iterate(0u, dim) |i|
    { res.at.at[i] = rng.gen() }

    res
  }
}

impl<D: Dim, N: Zero + Copy> Flatten<N> for NVec<D, N>
{
  #[inline(always)]
  fn flat_size() -> uint
  { Dim::dim::<D>() }

  #[inline(always)]
  fn from_flattened(l: &[N], off: uint) -> NVec<D, N>
  {
    let     dim = Dim::dim::<D>();
    let mut res = Zero::zero::<NVec<D, N>>();

    for iterate(0u, dim) |i|
    { res.at.at[i] = copy l[off + i] }

    res
  }

  #[inline(always)]
  fn flatten(&self) -> ~[N]
  {
    let     dim = Dim::dim::<D>();
    let mut res = ~[];

    for iterate(0u, dim) |i|
    { res.push(copy self.at.at[i]) }

    res
  }

  #[inline(always)]
  fn flatten_to(&self, l: &mut [N], off: uint)
  {
    let dim = Dim::dim::<D>();

    for iterate(0u, dim) |i|
    { l[off + i] = copy self.at.at[i] }
  }
}

impl<D: Dim, N: Bounded + Zero + Add<N, N> + Copy> Bounded for NVec<D, N>
{
  #[inline(always)]
  fn max_value() -> NVec<D, N>
  { Zero::zero::<NVec<D, N>>().scalar_add(&Bounded::max_value()) }

  #[inline(always)]
  fn min_value() -> NVec<D, N>
  { Zero::zero::<NVec<D, N>>().scalar_add(&Bounded::min_value()) }
}
<|endoftext|>