<commit_before>#![feature(inclusive_range_syntax)]

extern crate gtk;
extern crate gtk_sys;
extern crate gdk;
extern crate glib;
extern crate cairo;

use gtk::prelude::*;
use glib::translate::*;

const WINDOW_DEFAULT_WIDTH: i32 = 80;
const WINDOW_DEFAULT_HEIGHT: i32 = 80;
const DEFAULT_DPI: i32 = 96;

// make moving clones into closures more convenient
macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
    ($($n:ident),+ => move |$($p:tt : $z:ty),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p) : $z,)+| $body
        }
    );
}

fn make_window_draggable(window: &gtk::Window) {
    let mouse_position = std::rc::Rc::new(std::cell::Cell::new((0.0, 0.0)));
    window.connect_button_press_event(clone!(mouse_position => move |_window, event| {
        let button = event.as_ref().button;
        if button == 1 {
            mouse_position.set(event.get_position());
        }
        Inhibit(false)
    }));
    window.connect_motion_notify_event(move |window, event| {
        if event.get_state().contains(gdk::ModifierType::from_bits(256).unwrap()) {
            let (mx, my) = mouse_position.get();
            let x = event.as_ref().x_root - mx;
            let y = event.as_ref().y_root - my;
            window.move_(x as i32, y as i32);
        }
        Inhibit(false)
    });
}

fn cairo_image_surface_blur_alpha(surface: &mut cairo::ImageSurface, sigma: f64) {
    let width = surface.get_width();
    let height = surface.get_height();

    let src_stride = surface.get_stride();
    let mut src = surface.get_data().unwrap();

    let ksize = (sigma * 3.0).ceil() as i32 * 2 + 1;
    if ksize == 1 {
        return;
    }

    let mut kernel: Vec<f64> = Vec::with_capacity(ksize as usize);
    let scale = -0.5 / (sigma * sigma);
    let cons = 1.0 / (-scale / std::f64::consts::PI).sqrt();

    let mut sum = 0.0;
    let kcenter = ksize / 2;
    for i in 0..ksize {
        let x = (i - kcenter) as f64;
        let n = cons * ((x * x * scale).exp());
        kernel.push(n);
        sum += n;
    }

    let kernel = kernel.iter().map(|n| n / sum).collect::<Vec<f64>>();

    for y in 0..height {
        for x in 0..width {
            sum = 0.0;
            let mut amul = 0.0;
            for i in -kcenter...kcenter {
                if (x + i) >= 0 && (x + i) < width {
                    amul += src[(y * src_stride + (x + i) * 4 + 3) as usize] as f64 *
                            kernel[(kcenter + i) as usize];
                }
                sum += kernel[(kcenter + i) as usize];
            }
            src[(y * src_stride + x * 4 + 3) as usize] = (amul / sum) as u8;
        }
    }

    for x in 0..width {
        for y in 0..height {
            sum = 0.0;
            let mut amul = 0.0;
            for i in -kcenter...kcenter {
                if (y + i) >= 0 && (y + i) < height {
                    amul += src[((y + i) * src_stride + x * 4 + 3) as usize] as f64 *
                            kernel[(kcenter + i) as usize];
                }
                sum += kernel[(kcenter + i) as usize];
            }
            src[(y * src_stride + x * 4 + 3) as usize] = (amul / sum) as u8;
        }
    }
}

fn new_window_surface(window_size: (i32, i32), dpi_scale: f64) -> cairo::ImageSurface {
    let (window_width, window_height) = window_size;
    let window_y_center = window_height as f64 / 2.0;
    let window_x_center = window_width as f64 / 2.0;
    let circle_border = 5.0 * dpi_scale;
    let shadw_sigma = 2.0 * dpi_scale;
    let shadow_offset_x: f64 = 1.0 * dpi_scale;
    let shadow_offset_y: f64 = 1.0 * dpi_scale;
    let circle_radius = window_y_center - circle_border - shadow_offset_y.abs() -
                        (shadw_sigma * 3.0);

    let mut shadow =
        cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&shadow);
        cr.set_source_rgba(0.0, 0.0, 0.0, 0.5);
        cr.arc(window_x_center + shadow_offset_x,
               window_y_center + shadow_offset_y,
               circle_radius + circle_border,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
    }
    cairo_image_surface_blur_alpha(&mut shadow, shadw_sigma);
    let shadow_mask =
        cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&shadow_mask);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius + circle_border,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_operator(cairo::Operator::Out);
        cr.set_source_surface(&shadow, 0.0, 0.0);
        cr.paint();
    }
    let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&surface);
        cr.set_source_rgba(0.8, 0.8, 0.8, 0.5);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius + circle_border,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_source_surface(&shadow_mask, 0.0, 0.0);
        cr.paint();
    }
    let mut shadow =
        cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&shadow);
        cr.set_source_rgba(0.0, 0.0, 0.0, 0.5);
        cr.arc(window_x_center + shadow_offset_x,
               window_y_center + shadow_offset_y,
               circle_radius,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
    }
    cairo_image_surface_blur_alpha(&mut shadow, shadw_sigma);
    {
        let cr = cairo::Context::new(&surface);
        cr.set_source_surface(&shadow, 0.0, 0.0);
        cr.paint();
    }
    let mask = cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&mask);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_operator(cairo::Operator::Out);
        cr.set_source_surface(&surface, 0.0, 0.0);
        cr.paint();
    }
    let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&surface);
        cr.set_source_rgba(1.0, 1.0, 1.0, 0.9);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_source_surface(&mask, 0.0, 0.0);
        cr.paint();
    }

    surface
}

fn calculate_icons_position(x_center: f64,
                            y_center: f64,
                            radius: f64,
                            icons_num: i32)
                            -> Vec<(f64, f64)> {
    let mut result = Vec::with_capacity(icons_num as usize);

    let angle = 360.0_f64 / icons_num as f64;

    for i in 0..icons_num {
        let radians = (angle * i as f64).to_radians();
        let x = (radians.cos() * radius) + x_center;
        let y = (radians.sin() * radius) + y_center;

        result.push((x, y));
    }

    result
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }
    let dpi_scale = std::rc::Rc::new(std::cell::Cell::new(1.0));

    let window = gtk::Window::new(gtk::WindowType::Toplevel);
    window.set_title("Dropzone");
    window.set_default_size(WINDOW_DEFAULT_WIDTH, WINDOW_DEFAULT_WIDTH);
    window.set_app_paintable(true);
    window.set_position(gtk::WindowPosition::Center);
    window.set_type_hint(gdk::WindowTypeHint::Dock);

    let old_window_size = std::cell::Cell::new(None::<(i32, i32)>);
    let old_window_surface = std::cell::RefCell::new(None::<cairo::ImageSurface>);
    window.connect_draw(clone!(dpi_scale => move |window, cr| {
        cr.set_operator(cairo::Operator::Source);

        let window_size = window.get_size();
        if old_window_size.get().is_some() && window_size == old_window_size.get().unwrap() {
            // no need to redraw
            cr.set_source_surface(&old_window_surface.borrow()
                                       .clone()
                                       .unwrap(),
                                   0.0,
                                   0.0);
            cr.paint();
            return Inhibit(false);
        }
        old_window_size.set(Some(window_size));
        let surface = new_window_surface(window_size, dpi_scale.get());
        *old_window_surface.borrow_mut() = Some(surface.clone());

        cr.set_source_surface(&surface, 0.0, 0.0);

        cr.paint();

        Inhibit(false)
    }));

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    let update_visual =
        clone!(dpi_scale => move |window: &gtk::Window, _old_screen: &Option<gdk::Screen>| {
            let screen = gtk::WindowExt::get_screen(window).unwrap();
            let visual = screen.get_rgba_visual();
            window.set_visual(visual.as_ref());

            dpi_scale.set(screen.get_resolution() as f64 / DEFAULT_DPI as f64);
            window.resize((WINDOW_DEFAULT_WIDTH as f64 * dpi_scale.get()).ceil() as i32,
                          (WINDOW_DEFAULT_HEIGHT as f64 * dpi_scale.get()).ceil() as i32);
    });
    update_visual(&window, &None);
    window.connect_screen_changed(update_visual);

    make_window_draggable(&window);

    let icons_box = gtk::Layout::new(None, None);

    let (window_width, window_height) = window.get_size();
    for (x, y) in calculate_icons_position(window_width as f64 / 2.0,
                                           window_height as f64 / 2.0,
                                           window_width as f64 / 3.0,
                                           6) {
        let icon_size = window_width / 3;
        let center = icon_size as f64 / 2.0;

        let icon = gtk::DrawingArea::new();
        icon.set_size_request(icon_size, icon_size);

        icon.connect_draw(move |_icon, cr| {
            cr.set_source_rgba(1.0, 1.0, 1.0, 0.5);
            cr.arc(center, center, center, 0.0, 2.0 * std::f64::consts::PI);
            cr.fill();
            Inhibit(false)
        });

        unsafe {
            // FIXME: use wrapped API
            gtk_sys::gtk_drag_dest_set(icon.to_glib_none().0,
                                       gtk_sys::GtkDestDefaults::all(),
                                       std::ptr::null_mut(),
                                       0,
                                       gdk::DragAction::all());
        }
        icon.drag_dest_add_text_targets();
        icon.connect_drag_data_received(move |_self, _drag_context, _x, _y, data, _info, _time| {
                                            if let Some(text) = data.get_text() {
                                                println!("{}", text);
                                            }
                                        });

        icons_box.put(&icon, (x - center) as i32, (y - center) as i32);
    }
    window.add(&icons_box);

    window.show_all();

    gtk::main();
}
<commit_msg>add animation for subzone<commit_after>#![feature(inclusive_range_syntax)]

extern crate gtk;
extern crate gtk_sys;
extern crate gdk;
extern crate glib;
extern crate cairo;

use gtk::prelude::*;
use glib::translate::*;

const WINDOW_DEFAULT_WIDTH: i32 = 80;
const WINDOW_DEFAULT_HEIGHT: i32 = 80;
const DEFAULT_DPI: i32 = 96;

// make moving clones into closures more convenient
macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
    ($($n:ident),+ => move |$($p:tt : $z:ty),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p) : $z,)+| $body
        }
    );
}

fn make_window_draggable(window: &gtk::Window) {
    let mouse_position = std::rc::Rc::new(std::cell::Cell::new((0.0, 0.0)));
    window.connect_button_press_event(clone!(mouse_position => move |_window, event| {
        let button = event.as_ref().button;
        if button == 1 {
            mouse_position.set(event.get_position());
        }
        Inhibit(false)
    }));
    window.connect_motion_notify_event(move |window, event| {
        if event.get_state().contains(gdk::ModifierType::from_bits(256).unwrap()) {
            let (mx, my) = mouse_position.get();
            let x = event.as_ref().x_root - mx;
            let y = event.as_ref().y_root - my;
            window.move_(x as i32, y as i32);
        }
        Inhibit(false)
    });
}

fn cairo_image_surface_blur_alpha(surface: &mut cairo::ImageSurface, sigma: f64) {
    let width = surface.get_width();
    let height = surface.get_height();

    let src_stride = surface.get_stride();
    let mut src = surface.get_data().unwrap();

    let ksize = (sigma * 3.0).ceil() as i32 * 2 + 1;
    if ksize == 1 {
        return;
    }

    let mut kernel: Vec<f64> = Vec::with_capacity(ksize as usize);
    let scale = -0.5 / (sigma * sigma);
    let cons = 1.0 / (-scale / std::f64::consts::PI).sqrt();

    let mut sum = 0.0;
    let kcenter = ksize / 2;
    for i in 0..ksize {
        let x = (i - kcenter) as f64;
        let n = cons * ((x * x * scale).exp());
        kernel.push(n);
        sum += n;
    }

    let kernel = kernel.iter().map(|n| n / sum).collect::<Vec<f64>>();

    for y in 0..height {
        for x in 0..width {
            sum = 0.0;
            let mut amul = 0.0;
            for i in -kcenter...kcenter {
                if (x + i) >= 0 && (x + i) < width {
                    amul += src[(y * src_stride + (x + i) * 4 + 3) as usize] as f64 *
                            kernel[(kcenter + i) as usize];
                }
                sum += kernel[(kcenter + i) as usize];
            }
            src[(y * src_stride + x * 4 + 3) as usize] = (amul / sum) as u8;
        }
    }

    for x in 0..width {
        for y in 0..height {
            sum = 0.0;
            let mut amul = 0.0;
            for i in -kcenter...kcenter {
                if (y + i) >= 0 && (y + i) < height {
                    amul += src[((y + i) * src_stride + x * 4 + 3) as usize] as f64 *
                            kernel[(kcenter + i) as usize];
                }
                sum += kernel[(kcenter + i) as usize];
            }
            src[(y * src_stride + x * 4 + 3) as usize] = (amul / sum) as u8;
        }
    }
}

fn new_window_surface(window_size: (i32, i32), dpi_scale: f64) -> cairo::ImageSurface {
    let (window_width, window_height) = window_size;
    let window_y_center = window_height as f64 / 2.0;
    let window_x_center = window_width as f64 / 2.0;
    let circle_border = 5.0 * dpi_scale;
    let shadw_sigma = 2.0 * dpi_scale;
    let shadow_offset_x: f64 = 1.0 * dpi_scale;
    let shadow_offset_y: f64 = 1.0 * dpi_scale;
    let circle_radius = window_y_center - circle_border - shadow_offset_y.abs() -
                        (shadw_sigma * 3.0);

    let mut shadow =
        cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&shadow);
        cr.set_source_rgba(0.0, 0.0, 0.0, 0.5);
        cr.arc(window_x_center + shadow_offset_x,
               window_y_center + shadow_offset_y,
               circle_radius + circle_border,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
    }
    cairo_image_surface_blur_alpha(&mut shadow, shadw_sigma);
    let shadow_mask =
        cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&shadow_mask);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius + circle_border,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_operator(cairo::Operator::Out);
        cr.set_source_surface(&shadow, 0.0, 0.0);
        cr.paint();
    }
    let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&surface);
        cr.set_source_rgba(0.8, 0.8, 0.8, 0.5);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius + circle_border,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_source_surface(&shadow_mask, 0.0, 0.0);
        cr.paint();
    }
    let mut shadow =
        cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&shadow);
        cr.set_source_rgba(0.0, 0.0, 0.0, 0.5);
        cr.arc(window_x_center + shadow_offset_x,
               window_y_center + shadow_offset_y,
               circle_radius,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
    }
    cairo_image_surface_blur_alpha(&mut shadow, shadw_sigma);
    {
        let cr = cairo::Context::new(&surface);
        cr.set_source_surface(&shadow, 0.0, 0.0);
        cr.paint();
    }
    let mask = cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&mask);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_operator(cairo::Operator::Out);
        cr.set_source_surface(&surface, 0.0, 0.0);
        cr.paint();
    }
    let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, window_width, window_height);
    {
        let cr = cairo::Context::new(&surface);
        cr.set_source_rgba(1.0, 1.0, 1.0, 0.9);
        cr.arc(window_x_center,
               window_y_center,
               circle_radius,
               0.0,
               2.0 * std::f64::consts::PI);
        cr.fill();
        cr.set_source_surface(&mask, 0.0, 0.0);
        cr.paint();
    }

    surface
}

fn calculate_icons_position(x_center: f64,
                            y_center: f64,
                            radius: f64,
                            icons_num: i32)
                            -> Vec<(f64, f64)> {
    let mut result = Vec::with_capacity(icons_num as usize);

    let angle = 360.0_f64 / icons_num as f64;

    for i in 0..icons_num {
        let radians = (angle * i as f64).to_radians();
        let x = (radians.cos() * radius) + x_center;
        let y = (radians.sin() * radius) + y_center;

        result.push((x, y));
    }

    result
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }
    let dpi_scale = std::rc::Rc::new(std::cell::Cell::new(1.0));

    let window = gtk::Window::new(gtk::WindowType::Toplevel);
    window.set_title("Dropzone");
    window.set_default_size(WINDOW_DEFAULT_WIDTH, WINDOW_DEFAULT_WIDTH);
    window.set_app_paintable(true);
    window.set_position(gtk::WindowPosition::Center);
    window.set_type_hint(gdk::WindowTypeHint::Dock);

    let old_window_size = std::cell::Cell::new(None::<(i32, i32)>);
    let old_window_surface = std::cell::RefCell::new(None::<cairo::ImageSurface>);
    window.connect_draw(clone!(dpi_scale => move |window, cr| {
        cr.set_operator(cairo::Operator::Source);

        let window_size = window.get_size();
        if old_window_size.get().is_some() && window_size == old_window_size.get().unwrap() {
            // no need to redraw
            cr.set_source_surface(&old_window_surface.borrow()
                                       .clone()
                                       .unwrap(),
                                   0.0,
                                   0.0);
            cr.paint();
            return Inhibit(false);
        }
        old_window_size.set(Some(window_size));
        let surface = new_window_surface(window_size, dpi_scale.get());
        *old_window_surface.borrow_mut() = Some(surface.clone());

        cr.set_source_surface(&surface, 0.0, 0.0);

        cr.paint();

        Inhibit(false)
    }));

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    let update_visual =
        clone!(dpi_scale => move |window: &gtk::Window, _old_screen: &Option<gdk::Screen>| {
            let screen = gtk::WindowExt::get_screen(window).unwrap();
            let visual = screen.get_rgba_visual();
            window.set_visual(visual.as_ref());

            dpi_scale.set(screen.get_resolution() as f64 / DEFAULT_DPI as f64);
            window.resize((WINDOW_DEFAULT_WIDTH as f64 * dpi_scale.get()).ceil() as i32,
                          (WINDOW_DEFAULT_HEIGHT as f64 * dpi_scale.get()).ceil() as i32);
    });
    update_visual(&window, &None);
    window.connect_screen_changed(update_visual);

    make_window_draggable(&window);

    let icons_box = gtk::Layout::new(None, None);
    unsafe {
        // FIXME: use wrapped API
        gtk_sys::gtk_drag_dest_set(icons_box.to_glib_none().0,
                                   gtk_sys::GtkDestDefaults::all(),
                                   std::ptr::null_mut(),
                                   0,
                                   gdk::DragAction::all());
    }
    icons_box.drag_dest_add_text_targets();
    let icons_num = 6_i32;
    let icons = std::rc::Rc::new(std::cell::RefCell::new(Vec::with_capacity(icons_num as usize)));
    for _ in 0..icons_num {
        let icon = gtk::DrawingArea::new();
        icon.connect_draw(move |icon, cr| {
            let (width, _height) = icon.get_size_request();
            let center = width as f64 / 2.0;
            cr.set_source_rgba(1.0, 1.0, 1.0, 0.5);
            cr.arc(center, center, center, 0.0, 2.0 * std::f64::consts::PI);
            cr.fill();
            Inhibit(false)
        });

        unsafe {
            // FIXME: use wrapped API
            gtk_sys::gtk_drag_dest_set(icon.to_glib_none().0,
                                       gtk_sys::GtkDestDefaults::all(),
                                       std::ptr::null_mut(),
                                       0,
                                       gdk::DragAction::all());
        }
        icon.drag_dest_add_text_targets();
        icon.connect_drag_data_received(move |_self, _drag_context, _x, _y, data, _info, _time| {
            if let Some(text) = data.get_text() {
                println!("{}", text);
            }
        });

        icons_box.put(&icon, 0, 0);
        icon.hide();
        icons.borrow_mut().push(icon);
    }

    let mouse_drag_in = std::rc::Rc::new(std::cell::Cell::new(false));
    icons_box.connect_drag_motion(clone!(window, icons, dpi_scale => move |icons_box, _context, _, _, _| {
        if !mouse_drag_in.get() {
            mouse_drag_in.set(true);
            let mut animation_step = 10;
            let mut animation = {
                let window = window.clone();
                let icons_box = icons_box.clone();
                let icons = icons.clone();
                let dpi_scale = dpi_scale.clone();
                move || -> gtk::Continue {
                    let (window_width, window_height) = window.get_size();
                    for (i, &(x, y)) in calculate_icons_position(window_width as f64 / 2.0,
                                                                 window_height as f64 / 2.0,
                                                                 window_width as f64 / 3.0,
                                                                 icons_num).iter().enumerate() {
                        let icon = &icons.borrow()[i];
                        let icon_size_target = window_width / 3 + if animation_step > 3 {
                            (20.0 * dpi_scale.get()) as i32 // 惯性效果
                        } else {
                            0
                        };
                        let (width, _height) = icon.get_size_request();
                        let icon_size_now = if width > 0 { width } else { 0 };
                        let icon_size = icon_size_now + ((icon_size_target - icon_size_now) / animation_step);
                        let center = icon_size as f64 / 2.0;

                        icon.set_size_request(icon_size, icon_size);

                        icons_box.move_(icon, (x - center) as i32, (y - center) as i32);
                        icon.show();
                    }
                    animation_step -= 1;
                    if animation_step > 0 {
                        Continue(true)
                    } else {
                        Continue(false)
                    }
                }
            };

            animation();
            gtk::timeout_add(16, animation);
        }
        true
    }));

    window.add(&icons_box);

    window.show_all();

    gtk::main();
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate graphael;
use std::io;
use std::io::BufRead;
use graphael::Graph;

// Shorthand HashMap
// dict!({"yes": "1", "no": "0"}) => vec!($(($key, $value)),*).move_iter().collect();
// macro_rules! dict (
// 	({$($key:expr : $value:expr),*}) => (vec!($(($key, $value)),*).move_iter().collect())
// );

fn main() {
	println!("Graphael 0.1");

	print!("Enter a graph name> ");

	// Get the graph file name from stdin or use 'langs'
	let mut input = String::new();
	let graph_file = match io::stdin().read_line(&mut input) {
		Ok(_) => {
			println!("Using '{}'", &input.trim());
			input.trim().to_owned()
		},
		Err(e) => {
			println!("Error: {}.\nUsing 'langs'", e);
			"langs".to_string()
		}
	};

	// Read a already filled database
	let graph = Graph::read_from_file(format!("./data/{}.graph", graph_file));

	// Current state variable to keep track of which
	// type of query we are doing
	let mut current_state = 0;

	println!("1. Nodes with attribute.");
	println!("2. Nodes with key-value.");
	println!("3. Edges with label.");
	println!("4. Edges from node with label.");
	println!("5. Look up node.");
	println!("");
	print!(">>> ");

	// Read from stdin
	let locked_in = io::stdin();
	for line in locked_in.lock().lines() {
		match line {
			Ok(s) => {
				match current_state {
					// Initial state
					0 => match s.trim().parse::<i32>() {
						Ok(1) => current_state = 1,
						Ok(2) => current_state = 2,
						Ok(3) => current_state = 3,
						Ok(4) => current_state = 4,
						Ok(5) => current_state = 5,
						_ => current_state = 0
					},
					1 => { // Nodes with attribute
						println!("{:?}", graph.nodes_with_attr(&s.trim().to_string()));
						current_state = 0
					},
					2 => { // Node by key-value pair
						let kv : Vec<&str> = s.trim().split('=').map(|x| x.trim()).collect();
						println!("{:?}", graph.nodes_with_prop(&kv[0].to_string(), &kv[1].to_string()));
						current_state = 0
					},
					3 => { // Edges with label
						println!("{:?}", graph.edges_with_label(&s.trim().to_string()));
						current_state = 0
					},
					4 => { // Edges from node (NodeIndex) with label
						let node_label : Vec<&str> = s.trim().split("HAS").map(|x| x.trim()).collect();
						println!("{:?}", graph.edges_with_label_from((node_label[0].to_owned().parse::<usize>()).unwrap(), node_label[1]));
						current_state = 0
					},
					5 => { // Look up node by id (NodeIndex)
						let nodeid = (s.trim().parse::<usize>()).unwrap();
						println!("{:?}", graph.get_node(nodeid));
						current_state = 0
					},
					_ => { print!(">>> ") }
				}
			},
			Err(e) => panic!("Error: {}", e)
		};

		// Check the state and print accordingly
		match current_state {
			1 => print!("Enter attribute> "),
			2 => print!("Enter key-value> "),
			3 => print!("Enter label> "),
			4 => print!("Enter node and label> "),
			5 => print!("Enter node id> "),
			_ => {
				println!("");
				println!("1. Nodes with attribute.");
				println!("2. Nodes with key-value.");
				println!("3. Edges with label.");
				println!("4. Edges from node with label.");
				println!("5. Look up node by id.");
				println!("");
				print!(">>> ")
			}
		};
	}

}
<commit_msg>Shell now outputs prompt before asking for input<commit_after>extern crate rustc_serialize;
extern crate graphael;
use std::io::{self, BufRead, Write};
use graphael::Graph;

// Shorthand HashMap
// dict!({"yes": "1", "no": "0"}) => vec!($(($key, $value)),*).move_iter().collect();
// macro_rules! dict (
// 	({$($key:expr : $value:expr),*}) => (vec!($(($key, $value)),*).move_iter().collect())
// );

fn main() {
	println!("Graphael 0.1");

	print!("Enter a graph name> ");
	io::stdout().flush().unwrap();

	// Get the graph file name from stdin or use 'langs'
	let mut input = String::new();
	let graph_file = match io::stdin().read_line(&mut input) {
		Ok(_) => {
			println!("Using '{}'", &input.trim());
			input.trim().to_owned()
		},
		Err(e) => {
			println!("Error: {}.\nUsing 'langs'", e);
			"langs".to_string()
		}
	};

	// Read a already filled database
	let graph = Graph::read_from_file(format!("./data/{}.graph", graph_file));

	// Current state variable to keep track of which
	// type of query we are doing
	let mut current_state = 0;

	println!("1. Nodes with attribute.");
	println!("2. Nodes with key-value.");
	println!("3. Edges with label.");
	println!("4. Edges from node with label.");
	println!("5. Look up node.");
	println!("");
	print!(">>> ");
	io::stdout().flush().unwrap();

	// Read from stdin
	let locked_in = io::stdin();
	for line in locked_in.lock().lines() {
		match line {
			Ok(s) => {
				match current_state {
					// Initial state
					0 => match s.trim().parse::<i32>() {
						Ok(1) => current_state = 1,
						Ok(2) => current_state = 2,
						Ok(3) => current_state = 3,
						Ok(4) => current_state = 4,
						Ok(5) => current_state = 5,
						_ => current_state = 0
					},
					1 => { // Nodes with attribute
						println!("{:?}", graph.nodes_with_attr(&s.trim().to_string()));
						current_state = 0
					},
					2 => { // Node by key-value pair
						let kv : Vec<&str> = s.trim().split('=').map(|x| x.trim()).collect();
						println!("{:?}", graph.nodes_with_prop(&kv[0].to_string(), &kv[1].to_string()));
						current_state = 0
					},
					3 => { // Edges with label
						println!("{:?}", graph.edges_with_label(&s.trim().to_string()));
						current_state = 0
					},
					4 => { // Edges from node (NodeIndex) with label
						let node_label : Vec<&str> = s.trim().split("HAS").map(|x| x.trim()).collect();
						println!("{:?}", graph.edges_with_label_from((node_label[0].to_owned().parse::<usize>()).unwrap(), node_label[1]));
						current_state = 0
					},
					5 => { // Look up node by id (NodeIndex)
						let nodeid = (s.trim().parse::<usize>()).unwrap();
						println!("{:?}", graph.get_node(nodeid));
						current_state = 0
					},
					_ => { print!(">>> ") }
				}
			},
			Err(e) => panic!("Error: {}", e)
		};

		// Check the state and print accordingly
		match current_state {
			1 => print!("Enter attribute> "),
			2 => print!("Enter key-value> "),
			3 => print!("Enter label> "),
			4 => print!("Enter node and label> "),
			5 => print!("Enter node id> "),
			_ => {
				println!("");
				println!("1. Nodes with attribute.");
				println!("2. Nodes with key-value.");
				println!("3. Edges with label.");
				println!("4. Edges from node with label.");
				println!("5. Look up node by id.");
				println!("");
				print!(">>> ")
			}
		};
		io::stdout().flush().unwrap();
	}

}
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use aarch64_esr_decoder::{decode, Decoded};
use std::{env, num::ParseIntError};

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        eprintln!("Usage:");
        eprintln!("  {} <ESR value>", args[0]);
        return;
    }

    let esr = parse_number(&args[1]).unwrap();
    let decoded = decode(esr).unwrap();
    println!("{:#034x}", esr);
    print_decoded(&decoded, 0);
}

fn print_decoded(decoded: &Decoded, level: usize) {
    let indentation = " ".repeat(level * 2);
    println!("{}{}", indentation, decoded.description);
    for field in &decoded.fields {
        if field.width == 1 {
            println!("{}{:02}    {}", indentation, field.start, field);
        } else {
            println!(
                "{}{:02}-{:02} {}",
                indentation,
                field.start + field.width,
                field.start,
                field
            );
        }
        if let Some(field_decoded) = &field.decoded {
            print_decoded(field_decoded, level + 1);
        }
    }
}

/// Parse a decimal or hexadecimal number.
fn parse_number(s: &str) -> Result<u64, ParseIntError> {
    if s.starts_with("0x") {
        u64::from_str_radix(&s[2..], 16)
    } else {
        s.parse()
    }
}
<commit_msg>Print field bit ranges small-big, and closed rather than half-open.<commit_after>// Copyright 2021 Google LLC
//
// 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use aarch64_esr_decoder::{decode, Decoded};
use std::{env, num::ParseIntError};

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        eprintln!("Usage:");
        eprintln!("  {} <ESR value>", args[0]);
        return;
    }

    let esr = parse_number(&args[1]).unwrap();
    let decoded = decode(esr).unwrap();
    println!("{:#034x}", esr);
    print_decoded(&decoded, 0);
}

fn print_decoded(decoded: &Decoded, level: usize) {
    let indentation = " ".repeat(level * 2);
    println!("{}{}", indentation, decoded.description);
    for field in &decoded.fields {
        if field.width == 1 {
            println!("{}{:02}     {}", indentation, field.start, field);
        } else {
            println!(
                "{}{:02}..{:02} {}",
                indentation,
                field.start,
                field.start + field.width - 1,
                field
            );
        }
        if let Some(field_decoded) = &field.decoded {
            print_decoded(field_decoded, level + 1);
        }
    }
}

/// Parse a decimal or hexadecimal number.
fn parse_number(s: &str) -> Result<u64, ParseIntError> {
    if s.starts_with("0x") {
        u64::from_str_radix(&s[2..], 16)
    } else {
        s.parse()
    }
}
<|endoftext|>


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

use cgmath::{EuclideanSpace, InnerSpace, Point3, Quaternion, Rotation, Vector2, Vector3};
use collision::{Aabb, Aabb3};

#[derive(Debug, Clone)]
pub struct Cube {
    min: Point3<f64>,
    edge_length: f64,
}

impl Cube {
    pub fn bounding(aabb: &Aabb3<f64>) -> Self {
        let edge_length = (aabb.max().x - aabb.min().x)
            .max(aabb.max().y - aabb.min().y)
            .max(aabb.max().z - aabb.min().z);
        Cube {
            min: aabb.min,
            edge_length,
        }
    }

    pub fn to_aabb3(&self) -> Aabb3<f64> {
        Aabb3::new(self.min(), self.max())
    }

    pub fn new(min: Point3<f64>, edge_length: f64) -> Self {
        Cube { min, edge_length }
    }

    pub fn edge_length(&self) -> f64 {
        self.edge_length
    }

    pub fn min(&self) -> Point3<f64> {
        self.min
    }

    pub fn max(&self) -> Point3<f64> {
        Point3::new(
            self.min.x + self.edge_length,
            self.min.y + self.edge_length,
            self.min.z + self.edge_length,
        )
    }

    /// The center of the box.
    pub fn center(&self) -> Vector3<f64> {
        let min = self.min();
        let max = self.max();
        Vector3::new(
            (min.x + max.x) / 2.,
            (min.y + max.y) / 2.,
            (min.z + max.z) / 2.,
        )
    }
}

#[derive(Debug, Clone)]
pub struct OrientedBeam {
    // The members here are an implementation detail and differ from the
    // minimal representation in the gRPC message to speed up operations.
    // Rotation_inv and translation_inv together form the transform from world
    // coordinates into "beam coordinates".
    rotation_inv: Quaternion<f64>,
    translation_inv: Vector3<f64>,
    half_extent: Vector2<f64>,
    corners: [Point3<f64>; 4],
    separating_axes: [Vector3<f64>; 5],
}

impl OrientedBeam {
    pub fn new(
        rotation: Quaternion<f64>,
        translation: Vector3<f64>,
        half_extent: Vector2<f64>,
    ) -> Self {
        OrientedBeam {
            rotation_inv: rotation.conjugate(),
            translation_inv: -rotation.conjugate().rotate_vector(translation),
            half_extent,
            corners: OrientedBeam::precompute_corners(&rotation, &translation, &half_extent),
            separating_axes: OrientedBeam::precompute_separating_axes(&rotation),
        }
    }
    pub fn intersects(&self, aabb: &Aabb3<f64>) -> bool {
        // SAT algorithm
        // https://gamedev.stackexchange.com/questions/44500/how-many-and-which-axes-to-use-for-3d-obb-collision-with-sat
        for sep_axis in self.separating_axes.iter() {
            // Project the cube and the beam onto that axis
            let mut cube_min_proj = std::f64::MAX;
            let mut cube_max_proj = std::f64::MIN;
            for corner in aabb.to_corners().iter() {
                let corner_proj = corner.dot(*sep_axis);
                cube_min_proj = cube_min_proj.min(corner_proj);
                cube_max_proj = cube_max_proj.max(corner_proj);
            }
            // Project four "vertices" of the beam onto that axis
            let mut beam_min_proj = std::f64::MAX;
            let mut beam_max_proj = std::f64::MIN;
            for corner in self.corners.iter() {
                let corner_proj = corner.dot(*sep_axis);
                beam_min_proj = beam_min_proj.min(corner_proj);
                beam_max_proj = beam_max_proj.max(corner_proj);
            }
            if beam_min_proj > cube_max_proj || beam_max_proj < cube_min_proj {
                return false;
            }
        }
        true
    }

    pub fn contains(&self, p: &Point3<f64>) -> bool {
        // What is the point in beam coordinates?
        let Point3 { x, y, .. } = self.rotation_inv.rotate_point(*p) + self.translation_inv;
        x.abs() <= self.half_extent.x && y.abs() <= self.half_extent.y
    }

    fn precompute_corners(
        rotation: &Quaternion<f64>,
        translation: &Vector3<f64>,
        half_extent: &Vector2<f64>,
    ) -> [Point3<f64>; 4] {
        let transform =
            |x: f64, y: f64| rotation.rotate_point(Point3::new(x, y, 0.0)) + translation;
        [
            transform(half_extent.x, half_extent.y),
            transform(half_extent.x, -half_extent.y),
            transform(-half_extent.x, half_extent.y),
            transform(-half_extent.x, -half_extent.y),
        ]
    }

    fn precompute_separating_axes(rotation: &Quaternion<f64>) -> [Vector3<f64>; 5] {
        // The separating axis needs to be perpendicular to the beam's main
        // axis, i.e. the possible axes are the cross product of the three unit
        // vectors with the beam's main axis and the beam's face normals
        let main_axis = rotation.rotate_vector(Vector3::unit_z());
        [
            rotation.rotate_vector(Vector3::unit_x()),
            rotation.rotate_vector(Vector3::unit_y()),
            main_axis.cross(Vector3::unit_x()).normalize(),
            main_axis.cross(Vector3::unit_y()).normalize(),
            main_axis.cross(Vector3::unit_z()).normalize(),
        ]
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    // These tests were created in Blender by creating two cubes, naming one
    // "Beam" and scaling it up in its local z direction. The corresponding
    // object in Rust was defined by querying Blender's Python API with
    // bpy.data.objects['Beam'].rotation_euler.to_quaternion() and
    // bpy.data.objects['Beam'].location.

    fn some_beam() -> OrientedBeam {
        let quater = Quaternion::new(
            0.9292423725128174,
            -0.2677415907382965,
            -0.20863021910190582,
            -0.14593297243118286,
        );
        let translation = Vector3::new(1.0, 2.0, 0.0);
        let half_extent = Vector2::new(1.0, 1.0);
        OrientedBeam::new(quater, translation, half_extent)
    }

    #[test]
    fn test_beam_contains() {
        let point1 = Point3::new(-29.96, 57.85, 76.96); // (0, 0, 100) in local coordinates
        let point2 = Point3::new(-29.50, 58.83, 76.43); // (0, 1.2, 100) in local coordinates

        assert_eq!(some_beam().contains(&point1), true);
        assert_eq!(some_beam().contains(&point2), false);
    }

    #[test]
    fn test_beam_intersects() {
        let bbox1 = Aabb3::new(Point3::new(0.0, 0.0, 0.0), Point3::new(2.0, 2.0, 2.0));
        let bbox2 = Aabb3::new(Point3::new(0.0, 0.0, 3.0), Point3::new(2.0, 2.0, 5.0));
        // bbox3 is completely inside the beam, none of its faces intersect it
        let bbox3 = Aabb3::new(Point3::new(0.25, 1.8, 0.0), Point3::new(1.25, 2.8, 1.0));
        // bbox4 intersects the beam, but has no vertices inside it
        let bbox4 = Aabb3::new(Point3::new(-3.0, -2.0, -3.5), Point3::new(5.0, 6.0, 4.5));
        let bbox5 = Aabb3::new(Point3::new(2.1, -0.55, 0.0), Point3::new(4.1, 1.45, 2.0));
        let bbox6 = Aabb3::new(Point3::new(0.9, -1.67, 0.0), Point3::new(2.9, 0.33, 2.0));
        let bbox7 = Aabb3::new(Point3::new(0.9, -1.57, 0.0), Point3::new(2.9, 0.43, 2.0));
        assert_eq!(some_beam().intersects(&bbox1), true);
        assert_eq!(some_beam().intersects(&bbox2), false);
        assert_eq!(some_beam().intersects(&bbox3), true);
        assert_eq!(some_beam().intersects(&bbox4), true);
        assert_eq!(some_beam().intersects(&bbox5), false);
        assert_eq!(some_beam().intersects(&bbox6), false);
        assert_eq!(some_beam().intersects(&bbox7), true);
    }
}
<commit_msg>Handle special case of OrientedBeam query (#251)<commit_after>// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use cgmath::{EuclideanSpace, InnerSpace, Point3, Quaternion, Rotation, Vector2, Vector3};
use collision::{Aabb, Aabb3};

#[derive(Debug, Clone)]
pub struct Cube {
    min: Point3<f64>,
    edge_length: f64,
}

impl Cube {
    pub fn bounding(aabb: &Aabb3<f64>) -> Self {
        let edge_length = (aabb.max().x - aabb.min().x)
            .max(aabb.max().y - aabb.min().y)
            .max(aabb.max().z - aabb.min().z);
        Cube {
            min: aabb.min,
            edge_length,
        }
    }

    pub fn to_aabb3(&self) -> Aabb3<f64> {
        Aabb3::new(self.min(), self.max())
    }

    pub fn new(min: Point3<f64>, edge_length: f64) -> Self {
        Cube { min, edge_length }
    }

    pub fn edge_length(&self) -> f64 {
        self.edge_length
    }

    pub fn min(&self) -> Point3<f64> {
        self.min
    }

    pub fn max(&self) -> Point3<f64> {
        Point3::new(
            self.min.x + self.edge_length,
            self.min.y + self.edge_length,
            self.min.z + self.edge_length,
        )
    }

    /// The center of the box.
    pub fn center(&self) -> Vector3<f64> {
        let min = self.min();
        let max = self.max();
        Vector3::new(
            (min.x + max.x) / 2.,
            (min.y + max.y) / 2.,
            (min.z + max.z) / 2.,
        )
    }
}

#[derive(Debug, Clone)]
pub struct OrientedBeam {
    // The members here are an implementation detail and differ from the
    // minimal representation in the gRPC message to speed up operations.
    // Rotation_inv and translation_inv together form the transform from world
    // coordinates into "beam coordinates".
    rotation_inv: Quaternion<f64>,
    translation_inv: Vector3<f64>,
    half_extent: Vector2<f64>,
    corners: [Point3<f64>; 4],
    separating_axes: [Vector3<f64>; 5],
}

impl OrientedBeam {
    pub fn new(
        rotation: Quaternion<f64>,
        translation: Vector3<f64>,
        half_extent: Vector2<f64>,
    ) -> Self {
        OrientedBeam {
            rotation_inv: rotation.conjugate(),
            translation_inv: -rotation.conjugate().rotate_vector(translation),
            half_extent,
            corners: OrientedBeam::precompute_corners(&rotation, &translation, &half_extent),
            separating_axes: OrientedBeam::precompute_separating_axes(&rotation),
        }
    }
    pub fn intersects(&self, aabb: &Aabb3<f64>) -> bool {
        // SAT algorithm
        // https://gamedev.stackexchange.com/questions/44500/how-many-and-which-axes-to-use-for-3d-obb-collision-with-sat
        for sep_axis in self.separating_axes.iter() {
            if !sep_axis.x.is_finite() || !sep_axis.y.is_finite() || !sep_axis.z.is_finite() {
                // This guards against the separating axes being NaN, which may happen when the orientation aligns with the unit axes.
                continue;
            }
            // Project the cube and the beam onto that axis
            let mut cube_min_proj = std::f64::MAX;
            let mut cube_max_proj = std::f64::MIN;
            for corner in aabb.to_corners().iter() {
                let corner_proj = corner.dot(*sep_axis);
                cube_min_proj = cube_min_proj.min(corner_proj);
                cube_max_proj = cube_max_proj.max(corner_proj);
            }
            // Project four "vertices" of the beam onto that axis
            let mut beam_min_proj = std::f64::MAX;
            let mut beam_max_proj = std::f64::MIN;
            for corner in self.corners.iter() {
                let corner_proj = corner.dot(*sep_axis);
                beam_min_proj = beam_min_proj.min(corner_proj);
                beam_max_proj = beam_max_proj.max(corner_proj);
            }
            if beam_min_proj > cube_max_proj || beam_max_proj < cube_min_proj {
                return false;
            }
        }
        true
    }

    pub fn contains(&self, p: &Point3<f64>) -> bool {
        // What is the point in beam coordinates?
        let Point3 { x, y, .. } = self.rotation_inv.rotate_point(*p) + self.translation_inv;
        x.abs() <= self.half_extent.x && y.abs() <= self.half_extent.y
    }

    fn precompute_corners(
        rotation: &Quaternion<f64>,
        translation: &Vector3<f64>,
        half_extent: &Vector2<f64>,
    ) -> [Point3<f64>; 4] {
        let transform =
            |x: f64, y: f64| rotation.rotate_point(Point3::new(x, y, 0.0)) + translation;
        [
            transform(half_extent.x, half_extent.y),
            transform(half_extent.x, -half_extent.y),
            transform(-half_extent.x, half_extent.y),
            transform(-half_extent.x, -half_extent.y),
        ]
    }

    fn precompute_separating_axes(rotation: &Quaternion<f64>) -> [Vector3<f64>; 5] {
        // The separating axis needs to be perpendicular to the beam's main
        // axis, i.e. the possible axes are the cross product of the three unit
        // vectors with the beam's main axis and the beam's face normals.
        let main_axis = rotation.rotate_vector(Vector3::unit_z());
        [
            rotation.rotate_vector(Vector3::unit_x()),
            rotation.rotate_vector(Vector3::unit_y()),
            main_axis.cross(Vector3::unit_x()).normalize(),
            main_axis.cross(Vector3::unit_y()).normalize(),
            main_axis.cross(Vector3::unit_z()).normalize(),
        ]
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cgmath::Zero;
    // These tests were created in Blender by creating two cubes, naming one
    // "Beam" and scaling it up in its local z direction. The corresponding
    // object in Rust was defined by querying Blender's Python API with
    // bpy.data.objects['Beam'].rotation_euler.to_quaternion() and
    // bpy.data.objects['Beam'].location.

    fn some_beam() -> OrientedBeam {
        let quater = Quaternion::new(
            0.9292423725128174,
            -0.2677415907382965,
            -0.20863021910190582,
            -0.14593297243118286,
        );
        let translation = Vector3::new(1.0, 2.0, 0.0);
        let half_extent = Vector2::new(1.0, 1.0);
        OrientedBeam::new(quater, translation, half_extent)
    }

    #[test]
    fn test_beam_contains() {
        let point1 = Point3::new(-29.96, 57.85, 76.96); // (0, 0, 100) in local coordinates
        let point2 = Point3::new(-29.50, 58.83, 76.43); // (0, 1.2, 100) in local coordinates

        assert_eq!(some_beam().contains(&point1), true);
        assert_eq!(some_beam().contains(&point2), false);
    }

    #[test]
    fn test_beam_intersects() {
        let bbox1 = Aabb3::new(Point3::new(0.0, 0.0, 0.0), Point3::new(2.0, 2.0, 2.0));
        let bbox2 = Aabb3::new(Point3::new(0.0, 0.0, 3.0), Point3::new(2.0, 2.0, 5.0));
        // bbox3 is completely inside the beam, none of its faces intersect it
        let bbox3 = Aabb3::new(Point3::new(0.25, 1.8, 0.0), Point3::new(1.25, 2.8, 1.0));
        // bbox4 intersects the beam, but has no vertices inside it
        let bbox4 = Aabb3::new(Point3::new(-3.0, -2.0, -3.5), Point3::new(5.0, 6.0, 4.5));
        let bbox5 = Aabb3::new(Point3::new(2.1, -0.55, 0.0), Point3::new(4.1, 1.45, 2.0));
        let bbox6 = Aabb3::new(Point3::new(0.9, -1.67, 0.0), Point3::new(2.9, 0.33, 2.0));
        let bbox7 = Aabb3::new(Point3::new(0.9, -1.57, 0.0), Point3::new(2.9, 0.43, 2.0));
        assert_eq!(some_beam().intersects(&bbox1), true);
        assert_eq!(some_beam().intersects(&bbox2), false);
        assert_eq!(some_beam().intersects(&bbox3), true);
        assert_eq!(some_beam().intersects(&bbox4), true);
        assert_eq!(some_beam().intersects(&bbox5), false);
        assert_eq!(some_beam().intersects(&bbox6), false);
        assert_eq!(some_beam().intersects(&bbox7), true);
        let vertical_beam =
            OrientedBeam::new(Quaternion::zero(), Vector3::zero(), Vector2::new(1.0, 1.0));
        assert_eq!(vertical_beam.intersects(&bbox1), true);
    }
}
<|endoftext|>


<commit_before>use std::time::Duration;
use std::thread::JoinGuard;
use std::sync::mpsc::SyncSender;

use game::Color;
use types::NumMoves;
use search;

pub use self::mode::Mode;

mod mode;

pub struct State {
    pub search_state: Option<search::State>,
    pub search_guard: Option<JoinGuard<()>>,
    pub search_chan: Option<SyncSender<search::Cmd>>,
    pub mode: Mode,
    pub start_search_time: Option<u64>,
    pub start_move_time: Option<u64>,
    pub time_data: Option<TimeData>,
    pub ucinewgame_support: bool,
}
impl State {
    pub fn new() -> State {
        State {
            search_state: None,
            search_guard: None,
            search_chan: None,
            mode: Mode::new(),
            start_search_time: None,
            start_move_time: None,
            time_data: None,
            ucinewgame_support: false,
        }
    }
}

#[derive(Copy, Clone)]
pub enum TimeData {
    TimeLeft(TimeLeftData),
    ExactTime(Duration),
}

#[derive(Copy, Clone)]
pub struct TimeLeftData {
    pub w_time: Option<Duration>,
    pub b_time: Option<Duration>,
    pub w_inc: Option<Duration>,
    pub b_inc: Option<Duration>,
    pub moves_to_go: Option<NumMoves>,
}
impl TimeLeftData {
    pub fn time(&self, c: Color) -> Option<Duration> {
        match c {
            Color::White => self.w_time,
            Color::Black => self.b_time,
        }
    }
    pub fn set_time(&mut self, c: Color, val: Option<Duration>) {
        match c {
            Color::White => self.w_time = val,
            Color::Black => self.b_time = val,
        }
    }
    pub fn inc(&self, c: Color) -> Option<Duration> {
        match c {
            Color::White => self.w_inc,
            Color::Black => self.b_inc,
        }
    }
    pub fn set_inc(&mut self, c: Color, val: Option<Duration>) {
        match c {
            Color::White => self.w_inc = val,
            Color::Black => self.b_inc = val,
        }
    }
}
<commit_msg>Change stuff related to time.<commit_after>use std::time::Duration;
use std::thread::JoinGuard;
use std::sync::mpsc::SyncSender;

use game::Color;
use types::NumMoves;
use search;

pub use self::mode::Mode;

mod mode;

pub struct State {
    pub search_state: Option<search::State>,
    pub search_guard: Option<JoinGuard<()>>,
    pub search_chan: Option<SyncSender<search::Cmd>>,
    pub mode: Mode,
    pub start_search_time: Option<u64>,
    pub start_move_time: Option<u64>,
    pub time_data: Option<TimeData>,
    pub ucinewgame_support: bool,
}
impl State {
    pub fn new() -> State {
        State {
            search_state: None,
            search_guard: None,
            search_chan: None,
            mode: Mode::new(),
            start_search_time: None,
            start_move_time: None,
            time_data: None,
            ucinewgame_support: false,
        }
    }
}

#[derive(Clone)]
pub enum TimeData {
    TimeLeft(TimeLeftData),
    ExactTime(Duration),
    Infinite,
}
impl TimeData {
    pub fn set_time(&mut self, c: Color, val: Option<Duration>) {
        self.force_time_left();
        match *self {
            TimeData::TimeLeft(ref mut x) => x.set_time(c, val),
            _ => unreachable!(),
        }
    }
    pub fn set_inc(&mut self, c: Color, val: Option<Duration>) {
        self.force_time_left();
        match *self {
            TimeData::TimeLeft(ref mut x) => x.set_inc(c, val),
            _ => unreachable!(),
        }
    }
    pub fn set_moves_to_go(&mut self, val: Option<NumMoves>) {
        self.force_time_left();
        match *self {
            TimeData::TimeLeft(ref mut x) => x.moves_to_go = val,
            _ => unreachable!(),
        }
    }
    fn force_time_left(&mut self) {
        match *self {
            TimeData::TimeLeft(_) => {},
            ref mut x => *x = TimeData::TimeLeft(TimeLeftData::new()),
        }
    }
}

#[derive(Clone)]
pub struct TimeLeftData {
    pub w_time: Option<Duration>,
    pub b_time: Option<Duration>,
    pub w_inc: Option<Duration>,
    pub b_inc: Option<Duration>,
    pub moves_to_go: Option<NumMoves>,
}
impl TimeLeftData {
    pub fn new() -> TimeLeftData {
        TimeLeftData {
            w_time: None,
            b_time: None,
            w_inc: None,
            b_inc: None,
            moves_to_go: None,
        }
    }
    pub fn time(&self, c: Color) -> Option<Duration> {
        match c {
            Color::White => self.w_time,
            Color::Black => self.b_time,
        }
    }
    pub fn set_time(&mut self, c: Color, val: Option<Duration>) {
        match c {
            Color::White => self.w_time = val,
            Color::Black => self.b_time = val,
        }
    }
    pub fn inc(&self, c: Color) -> Option<Duration> {
        match c {
            Color::White => self.w_inc,
            Color::Black => self.b_inc,
        }
    }
    pub fn set_inc(&mut self, c: Color, val: Option<Duration>) {
        match c {
            Color::White => self.w_inc = val,
            Color::Black => self.b_inc = val,
        }
    }
}
<|endoftext|>


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

//! Sane serialization & deserialization of cryptographic structs into hex

use crate::keychain::BlindingFactor;
use crate::serde::{Deserialize, Deserializer, Serializer};
use crate::util::secp::pedersen::{Commitment, RangeProof};
use crate::util::{from_hex, to_hex};

/// Serializes a secp PublicKey to and from hex
pub mod pubkey_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp::key::PublicKey;
	use crate::util::{from_hex, static_secp_instance, to_hex};

	///
	pub fn serialize<S>(key: &PublicKey, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		serializer.serialize_str(&to_hex(key.serialize_vec(&static_secp, false).to_vec()))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
	where
		D: Deserializer<'de>,
	{
		use serde::de::Error;
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				PublicKey::from_slice(&static_secp, &bytes)
					.map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Serializes an Option<secp::Signature> to and from hex
pub mod option_sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp;
	use crate::util::static_secp_instance;
	use crate::util::{from_hex, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &Option<secp::Signature>, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		match sig {
			Some(sig) => {
				let static_secp = static_secp_instance();
				let static_secp = static_secp.lock();
				serializer.serialize_str(&to_hex(sig.serialize_der(&static_secp)))
			}
			None => serializer.serialize_none(),
		}
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<secp::Signature>, D::Error>
	where
		D: Deserializer<'de>,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();

		Option::<&str>::deserialize(deserializer).and_then(|res| match res {
			Some(string) => from_hex(string.to_string())
				.map_err(|err| Error::custom(err.to_string()))
				.and_then(|bytes: Vec<u8>| {
					secp::Signature::from_der(&static_secp, &bytes)
						.map(|val| Some(val))
						.map_err(|err| Error::custom(err.to_string()))
				}),
			None => Ok(None),
		})
	}

}

/// Serializes a secp::Signature to and from hex
pub mod sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp;
	use crate::util::static_secp_instance;
	use crate::util::{from_hex, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &secp::Signature, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		serializer.serialize_str(&to_hex(sig.serialize_der(&static_secp)))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<secp::Signature, D::Error>
	where
		D: Deserializer<'de>,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				secp::Signature::from_der(&static_secp, &bytes)
					.map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Creates a BlindingFactor from a hex string
pub fn blind_from_hex<'de, D>(deserializer: D) -> Result<BlindingFactor, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer).and_then(|string| {
		BlindingFactor::from_hex(&string).map_err(|err| Error::custom(err.to_string()))
	})
}

/// Creates a RangeProof from a hex string
pub fn rangeproof_from_hex<'de, D>(deserializer: D) -> Result<RangeProof, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::{Error, IntoDeserializer};

	let val = String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))?;
	RangeProof::deserialize(val.into_deserializer())
}

/// Creates a Pedersen Commitment from a hex string
pub fn commitment_from_hex<'de, D>(deserializer: D) -> Result<Commitment, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
		.and_then(|bytes: Vec<u8>| Ok(Commitment::from_vec(bytes.to_vec())))
}

/// Seralizes a byte string into hex
pub fn as_hex<T, S>(bytes: T, serializer: S) -> Result<S::Ok, S::Error>
where
	T: AsRef<[u8]>,
	S: Serializer,
{
	serializer.serialize_str(&to_hex(bytes.as_ref().to_vec()))
}

// Test serialization methods of components that are being used
#[cfg(test)]
mod test {
	use super::*;
	use crate::libtx::aggsig;
	use crate::util::secp::key::{PublicKey, SecretKey};
	use crate::util::secp::{Message, Signature};
	use crate::util::static_secp_instance;

	use serde_json;

	use rand::{thread_rng, Rng};

	#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
	struct SerTest {
		#[serde(with = "pubkey_serde")]
		pub pub_key: PublicKey,
		#[serde(with = "option_sig_serde")]
		pub opt_sig: Option<Signature>,
		#[serde(with = "sig_serde")]
		pub sig: Signature,
	}

	impl SerTest {
		pub fn random() -> SerTest {
			let static_secp = static_secp_instance();
			let secp = static_secp.lock();
			let sk = SecretKey::new(&secp, &mut thread_rng());
			let mut msg = [0u8; 32];
			thread_rng().fill(&mut msg);
			let msg = Message::from_slice(&msg).unwrap();
			let sig = aggsig::sign_single(&secp, &msg, &sk, None).unwrap();
			SerTest {
				pub_key: PublicKey::from_secret_key(&secp, &sk).unwrap(),
				opt_sig: Some(sig.clone()),
				sig: sig.clone(),
			}
		}
	}

	#[test]
	fn ser_secp_primitives() {
		for _ in 0..10 {
			let s = SerTest::random();
			println!("Before Serialization: {:?}", s);
			let serialized = serde_json::to_string_pretty(&s).unwrap();
			println!("JSON: {}", serialized);
			let deserialized: SerTest = serde_json::from_str(&serialized).unwrap();
			println!("After Serialization: {:?}", deserialized);
			println!();
			assert_eq!(s, deserialized);
		}
	}
}
<commit_msg>[1.1.0] Serialise sigs as raw data, not DER encoded (#2668)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Sane serialization & deserialization of cryptographic structs into hex

use crate::keychain::BlindingFactor;
use crate::serde::{Deserialize, Deserializer, Serializer};
use crate::util::secp::pedersen::{Commitment, RangeProof};
use crate::util::{from_hex, to_hex};

/// Serializes a secp PublicKey to and from hex
pub mod pubkey_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp::key::PublicKey;
	use crate::util::{from_hex, static_secp_instance, to_hex};

	///
	pub fn serialize<S>(key: &PublicKey, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		serializer.serialize_str(&to_hex(key.serialize_vec(&static_secp, false).to_vec()))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
	where
		D: Deserializer<'de>,
	{
		use serde::de::Error;
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				PublicKey::from_slice(&static_secp, &bytes)
					.map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Serializes an Option<secp::Signature> to and from hex
pub mod option_sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp;
	use crate::util::{from_hex, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &Option<secp::Signature>, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		match sig {
			Some(sig) => serializer.serialize_str(&to_hex(sig.to_raw_data().to_vec())),
			None => serializer.serialize_none(),
		}
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<secp::Signature>, D::Error>
	where
		D: Deserializer<'de>,
	{
		Option::<&str>::deserialize(deserializer).and_then(|res| match res {
			Some(string) => from_hex(string.to_string())
				.map_err(|err| Error::custom(err.to_string()))
				.and_then(|bytes: Vec<u8>| {
					let mut b = [0u8; 64];
					b.copy_from_slice(&bytes[0..64]);
					secp::Signature::from_raw_data(&b)
						.map(|val| Some(val))
						.map_err(|err| Error::custom(err.to_string()))
				}),
			None => Ok(None),
		})
	}

}

/// Serializes a secp::Signature to and from hex
pub mod sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp;
	use crate::util::static_secp_instance;
	use crate::util::{from_hex, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &secp::Signature, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		serializer.serialize_str(&to_hex(sig.serialize_der(&static_secp)))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<secp::Signature, D::Error>
	where
		D: Deserializer<'de>,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				secp::Signature::from_der(&static_secp, &bytes)
					.map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Creates a BlindingFactor from a hex string
pub fn blind_from_hex<'de, D>(deserializer: D) -> Result<BlindingFactor, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer).and_then(|string| {
		BlindingFactor::from_hex(&string).map_err(|err| Error::custom(err.to_string()))
	})
}

/// Creates a RangeProof from a hex string
pub fn rangeproof_from_hex<'de, D>(deserializer: D) -> Result<RangeProof, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::{Error, IntoDeserializer};

	let val = String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))?;
	RangeProof::deserialize(val.into_deserializer())
}

/// Creates a Pedersen Commitment from a hex string
pub fn commitment_from_hex<'de, D>(deserializer: D) -> Result<Commitment, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
		.and_then(|bytes: Vec<u8>| Ok(Commitment::from_vec(bytes.to_vec())))
}

/// Seralizes a byte string into hex
pub fn as_hex<T, S>(bytes: T, serializer: S) -> Result<S::Ok, S::Error>
where
	T: AsRef<[u8]>,
	S: Serializer,
{
	serializer.serialize_str(&to_hex(bytes.as_ref().to_vec()))
}

// Test serialization methods of components that are being used
#[cfg(test)]
mod test {
	use super::*;
	use crate::libtx::aggsig;
	use crate::util::secp::key::{PublicKey, SecretKey};
	use crate::util::secp::{Message, Signature};
	use crate::util::static_secp_instance;

	use serde_json;

	use rand::{thread_rng, Rng};

	#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
	struct SerTest {
		#[serde(with = "pubkey_serde")]
		pub pub_key: PublicKey,
		#[serde(with = "option_sig_serde")]
		pub opt_sig: Option<Signature>,
		#[serde(with = "sig_serde")]
		pub sig: Signature,
	}

	impl SerTest {
		pub fn random() -> SerTest {
			let static_secp = static_secp_instance();
			let secp = static_secp.lock();
			let sk = SecretKey::new(&secp, &mut thread_rng());
			let mut msg = [0u8; 32];
			thread_rng().fill(&mut msg);
			let msg = Message::from_slice(&msg).unwrap();
			let sig = aggsig::sign_single(&secp, &msg, &sk, None).unwrap();
			SerTest {
				pub_key: PublicKey::from_secret_key(&secp, &sk).unwrap(),
				opt_sig: Some(sig.clone()),
				sig: sig.clone(),
			}
		}
	}

	#[test]
	fn ser_secp_primitives() {
		for _ in 0..10 {
			let s = SerTest::random();
			println!("Before Serialization: {:?}", s);
			let serialized = serde_json::to_string_pretty(&s).unwrap();
			println!("JSON: {}", serialized);
			let deserialized: SerTest = serde_json::from_str(&serialized).unwrap();
			println!("After Serialization: {:?}", deserialized);
			println!();
			assert_eq!(s, deserialized);
		}
	}
}
<|endoftext|>


<commit_before>use nom::{Err, IResult, Needed};

use std::io;
use std::io::Read;
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Continue,
  EndOfInput,
  Unknown,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(_)      => Err(ErrorKind::Unknown),
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(_)      => Err(ErrorKind::Unknown),
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg> Export self inside of utility module<commit_after>use nom::{Err, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Continue,
  EndOfInput,
  Unknown,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(_)      => Err(ErrorKind::Unknown),
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(_)      => Err(ErrorKind::Unknown),
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


<commit_before>use num::{Signed, Unsigned};
use approx::Approx;

#[inline(always)]
pub fn inverse<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[0];
    out[1] = -a[1];
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0];
    inverse(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn lerp<'a, 'b, T: Unsigned, N: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2], t: N) -> &'a mut [T; 2] {
    let t_f64 = t.to_f64();
    out[0] = T::from_f64((a[0] + (b[0] - a[0])).to_f64() * t_f64);
    out[1] = T::from_f64((a[1] + (b[1] - a[1])).to_f64() * t_f64);
    out
}
#[test]
fn test_lerp() {
    let mut v = [0, 0];
    lerp(&mut v, &[0, 0], &[2, 2], 0.5);
    assert_eq!(v[0], 1);
    assert_eq!(v[1], 1);
}

#[inline(always)]
pub fn perp_l<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = a[1];
    out[1] = -a[0];
    out
}
#[test]
fn test_perp_l() {
    let mut v = [0, 0];
    perp_l(&mut v, &[1, 1]);
    assert!(v[0] == 1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn perp_r<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[1];
    out[1] = a[0];
    out
}
#[test]
fn test_perp_r() {
    let mut v = [0, 0];
    perp_r(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == 1);
}

#[inline(always)]
pub fn min<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0];
    min(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [0, 0]);
}

#[inline(always)]
pub fn max<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0];
    max(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn clamp<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], min: &'b [T; 2], max: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0];
    clamp(&mut v, &[2, 2], &[0, 0], &[1, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn eq<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !nq(a, b)
}
#[test]
fn test_eq() {
    assert_eq!(eq(&[1f32, 1f32], &[1f32, 1f32]), true);
    assert_eq!(eq(&[0f32, 0f32], &[1f32, 1f32]), false);
}

#[inline(always)]
pub fn nq<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !a[0].approx_eq(b[0]) ||
    !a[1].approx_eq(b[1])
}
#[test]
fn test_nq() {
    assert_eq!(nq(&[1f32, 1f32], &[1f32, 1f32]), false);
    assert_eq!(nq(&[0f32, 0f32], &[1f32, 1f32]), true);
}
<commit_msg>updates<commit_after>use num::{Signed, Unsigned};
use approx::Approx;

#[inline(always)]
pub fn inverse<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[0];
    out[1] = -a[1];
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0];
    inverse(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn lerp<'a, 'b, T: Unsigned, N: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2], t: N) -> &'a mut [T; 2] {
    let t_f64 = t.to_f64();
    out[0] = T::from_f64((a[0] + (b[0] - a[0])).to_f64() * t_f64);
    out[1] = T::from_f64((a[1] + (b[1] - a[1])).to_f64() * t_f64);
    out
}
#[test]
fn test_lerp() {
    let mut v = [0, 0];
    lerp(&mut v, &[0, 0], &[2, 2], 0.5);
    assert_eq!(v[0], 1);
    assert_eq!(v[1], 1);
}

#[inline(always)]
pub fn perp_l<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = a[1];
    out[1] = -a[0];
    out
}
#[test]
fn test_perp_l() {
    let mut v = [0, 0];
    perp_l(&mut v, &[1, 1]);
    assert!(v[0] == 1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn perp_r<'a, 'b, T: Signed>(out: &'a mut [T; 2], a: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = -a[1];
    out[1] = a[0];
    out
}
#[test]
fn test_perp_r() {
    let mut v = [0, 0];
    perp_r(&mut v, &[1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == 1);
}

#[inline(always)]
pub fn min<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0];
    min(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [0, 0]);
}

#[inline(always)]
pub fn max<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], b: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0];
    max(&mut v, &[1, 0], &[0, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn clamp<'a, 'b, T: Unsigned>(out: &'a mut [T; 2], a: &'b [T; 2], min: &'b [T; 2], max: &'b [T; 2]) -> &'a mut [T; 2] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0];
    clamp(&mut v, &[2, 2], &[0, 0], &[1, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn eq<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !ne(a, b)
}
#[test]
fn test_eq() {
    assert_eq!(eq(&[1f32, 1f32], &[1f32, 1f32]), true);
    assert_eq!(eq(&[0f32, 0f32], &[1f32, 1f32]), false);
}

#[inline(always)]
pub fn neq<'a, T: Unsigned>(a: &'a [T; 2], b: &'a [T; 2]) -> bool {
    !a[0].approx_eq(b[0]) ||
    !a[1].approx_eq(b[1])
}
#[test]
fn test_ne() {
    assert_eq!(ne(&[1f32, 1f32], &[1f32, 1f32]), false);
    assert_eq!(ne(&[0f32, 0f32], &[1f32, 1f32]), true);
}
<|endoftext|>