<commit_before>use super::*;
use std::fmt::Debug;

#[test]
fn stream_basic()
{
    let sink = Sink::new();
    let stream = sink.stream();
    let rx = stream.channel();
    let signal = stream.hold(0);

    sink.send(42);
    sink.send(33);
    sink.feed(0..5);

    let result: Vec<i32> = rx.try_iter().collect();
    assert_eq!(result, [42, 33, 0, 1, 2, 3, 4]);
    assert_eq!(signal.sample(), 4);
}

#[test]
fn signal_basic()
{
    let signal = Signal::Constant(42);
    assert_eq!(signal.sample(), 42);
    signal.sample_with(|val| assert_eq!(*val, 42));

    let val = 33;
    let signal = Signal::from_fn(move || val);
    assert_eq!(signal.sample(), val);

    let sink = Sink::new();
    let stream = sink.stream();
    let s_double = stream.hold(0).map(|a| *a * 2);
    let s_odd = stream.hold_if(0, |a| *a % 2 != 0);

    sink.send(2);
    sink.send(3);
    sink.send(4);

    assert_eq!(s_double.sample(), 8);
    assert_eq!(s_odd.sample(), 3);
}

fn vec_cons<T: Clone>(mut v: Vec<T>, x: Cow<T>) -> Vec<T> { v.push(x.into_owned()); v }

#[test]
fn stream_operations()
{
    let sink: Sink<i32> = Sink::new();
    let stream = sink.stream();

    let s_string = stream.map(|a| a.to_string()).fold(vec![], vec_cons);
    let s_odd = stream.filter(|a| a % 2 != 0).fold(vec![], vec_cons);
    let s_even_half = stream.filter_map(|a| if *a % 2 == 0 { Some(*a / 2) } else { None }).fold(vec![], vec_cons);
    let (pos, neg) = stream.map(|a| if *a > 0 { Ok(*a) } else { Err(*a) }).split();
    let s_pos = pos.fold(vec![], vec_cons);
    let s_neg = neg.fold(vec![], vec_cons);
    let s_merged = pos.merge(&neg.map(|a| -*a)).fold(vec![], vec_cons);
    let s_accum = stream.fold(vec![], vec_cons).snapshot(&stream, |s, _| s.into_owned()).fold(vec![], vec_cons);
    let s_cloned = stream.fold_clone(vec![], vec_cons);

    sink.feed(vec![5, 8, 13, -2, 42, -33]);

    assert_eq!(s_string.sample(), ["5", "8", "13", "-2", "42", "-33"]);
    assert_eq!(s_odd.sample(), [5, 13, -33]);
    assert_eq!(s_even_half.sample(), [4, -1, 21]);
    assert_eq!(s_pos.sample(), [5, 8, 13, 42]);
    assert_eq!(s_neg.sample(), [-2, -33]);
    assert_eq!(s_merged.sample(), [5, 8, 13, 2, 42, 33]);
    assert_eq!(s_accum.sample(), [vec![5], vec![5, 8], vec![5, 8, 13], vec![5, 8, 13, -2], vec![5, 8, 13, -2, 42], vec![5, 8, 13, -2, 42, -33]]);
    assert_eq!(s_cloned.sample(), [5, 8, 13, -2, 42, -33]);
}

#[cfg(feature="either")]
#[test]
fn merge_with()
{
    let sink1: Sink<i32> = Sink::new();
    let sink2: Sink<f32> = Sink::new();
    let stream: Stream<Result<_, _>> = sink1.stream().merge_with(&sink2.stream(), |e| e.either(|l| Ok(*l), |r| Err(*r)));
    let result = stream.fold(vec![], vec_cons);

    sink1.send(1);
    sink2.send(2.0);
    sink1.send(3);
    sink1.send(4);
    sink2.send(5.0);

    assert_eq!(result.sample(), [Ok(1), Err(2.0), Ok(3), Ok(4), Err(5.0)]);
}

#[test]
fn stream_channel()
{
    let sink = Sink::new();
    let rx = sink.stream().channel();

    let thread = std::thread::spawn(move || {
        let sink2 = Sink::new();
        let s_sum = sink2.stream().fold(0, |a, n| a + *n);
        while let Ok(_) = rx.recv().map(|v| sink2.send(v)) { /* empty */ }
        s_sum.into_rwlock().unwrap()
    });

    sink.feed(1..100);
    drop(sink);

    let result: Signal<i32> = thread.join().unwrap().into();
    assert_eq!(result.sample(), 4950);
}

#[test]
fn stream_switch()
{
    let stream_sink = Sink::new();
    let sink1 = Sink::new();
    let sink2 = Sink::new();

    let switched = stream_sink.stream().switch();
    let events = switched.channel();

    sink1.send(1);
    sink2.send(2);

    stream_sink.send(sink2.stream());
    sink1.send(3);
    sink2.send(4);
    assert_eq!(events.try_recv(), Ok(4));

    stream_sink.send(sink1.stream());
    sink1.send(5);
    sink2.send(6);
    assert_eq!(events.try_recv(), Ok(5));
}

#[test]
fn signal_switch()
{
    let signal_sink = Sink::new();
    let switched = signal_sink.stream().hold(Signal::Constant(0)).switch();

    signal_sink.send(Signal::Constant(1));
    assert_eq!(switched.sample(), 1);

    signal_sink.send(2.into());
    assert_eq!(switched.sample(), 2);
}

#[derive(Debug)]
struct Storage<T>(Vec<T>);

impl<T> Storage<T>
{
    fn new() -> Self { Storage(Vec::new()) }
    fn push(mut self, a: T) -> Self { self.0.push(a); self }
}

impl<T: Debug> Clone for Storage<T>
{
    fn clone(&self) -> Self { panic!("storage cloned! {:?}", self.0) }
}

#[test]
fn cloning()
{
    let sink = Sink::new();
    let accum = sink.stream().fold(Storage::new(), |a, v| a.push(*v));

    sink.feed(0..5);
    accum.sample_with(|res| assert_eq!(res.0, [0, 1, 2, 3, 4]));
}

#[test]
fn filter_extra()
{
    let sink = Sink::new();
    let stream = sink.stream();
    let sign_res = stream.map(|a| if *a >= 0 { Ok(*a) } else { Err(*a) });
    let even_opt = stream.map(|a| if *a % 2 == 0 { Some(*a) } else { None });
    let s_even = even_opt.filter_some().fold(vec![], vec_cons);
    let s_pos = sign_res.filter_first().fold(vec![], vec_cons);
    let s_neg = sign_res.filter_second().fold(vec![], vec_cons);

    sink.feed(vec![1, 8, -3, 42, -66]);

    assert_eq!(s_even.sample(), [8, 42, -66]);
    assert_eq!(s_pos.sample(), [1, 8, 42]);
    assert_eq!(s_neg.sample(), [-3, -66]);
}

#[test]
fn reentrant()
{
    let sink = Sink::new();
    let cloned = sink.clone();
    let sig = sink.stream()
        .filter_map(move |n| if *n < 10 { cloned.send(*n + 1); None } else { Some(*n) })
        .hold(0);

    sink.send(1);
    assert_eq!(sig.sample(), 10);
}

#[allow(unused_variables)]
#[test]
fn deletion()
{
    use std::cell::Cell;

    fn stream_cell(src: &Stream<i32>, i: i32) -> (Stream<i32>, Rc<Cell<i32>>)
    {
        let cell = Rc::new(Cell::new(0));
        let cloned = cell.clone();
        let stream = src.map(move |n| *n + i).inspect(move |n| cloned.set(*n));
        (stream, cell)
    }

    let sink = Sink::new();
    let stream = sink.stream();
    let (s1, c1) = stream_cell(&stream, 1);
    let (s2, c2) = stream_cell(&stream, 2);
    let (s3, c3) = stream_cell(&stream, 3);

    sink.send(10);
    assert_eq!(c1.get(), 11);
    assert_eq!(c2.get(), 12);
    assert_eq!(c3.get(), 13);

    drop(s2);
    sink.send(20);
    assert_eq!(c1.get(), 21);
    assert_eq!(c2.get(), 12);
    assert_eq!(c3.get(), 23);
}

#[test]
fn map_n()
{
    let sink = Sink::new();
    let s_out = sink.stream()
        .map_n(|a, sink| for _ in 0 .. *a { sink.send(*a) })
        .fold(vec![], vec_cons);

    sink.feed(0..4);

    assert_eq!(s_out.sample(), [1, 2, 2, 3, 3, 3]);
}
<commit_msg>simplified code in test case<commit_after>use super::*;
use std::fmt::Debug;

#[test]
fn stream_basic()
{
    let sink = Sink::new();
    let stream = sink.stream();
    let rx = stream.channel();
    let signal = stream.hold(0);

    sink.send(42);
    sink.send(33);
    sink.feed(0..5);

    let result: Vec<i32> = rx.try_iter().collect();
    assert_eq!(result, [42, 33, 0, 1, 2, 3, 4]);
    assert_eq!(signal.sample(), 4);
}

#[test]
fn signal_basic()
{
    let signal = Signal::Constant(42);
    assert_eq!(signal.sample(), 42);
    signal.sample_with(|val| assert_eq!(*val, 42));

    let val = 33;
    let signal = Signal::from_fn(move || val);
    assert_eq!(signal.sample(), val);

    let sink = Sink::new();
    let stream = sink.stream();
    let s_double = stream.hold(0).map(|a| *a * 2);
    let s_odd = stream.hold_if(0, |a| *a % 2 != 0);

    sink.send(2);
    sink.send(3);
    sink.send(4);

    assert_eq!(s_double.sample(), 8);
    assert_eq!(s_odd.sample(), 3);
}

fn vec_cons<T: Clone>(mut v: Vec<T>, x: Cow<T>) -> Vec<T> { v.push(x.into_owned()); v }

#[test]
fn stream_operations()
{
    let sink: Sink<i32> = Sink::new();
    let stream = sink.stream();

    let s_string = stream.map(|a| a.to_string()).fold(vec![], vec_cons);
    let s_odd = stream.filter(|a| a % 2 != 0).fold(vec![], vec_cons);
    let s_even_half = stream.filter_map(|a| if *a % 2 == 0 { Some(*a / 2) } else { None }).fold(vec![], vec_cons);
    let (pos, neg) = stream.map(|a| if *a > 0 { Ok(*a) } else { Err(*a) }).split();
    let s_pos = pos.fold(vec![], vec_cons);
    let s_neg = neg.fold(vec![], vec_cons);
    let s_merged = pos.merge(&neg.map(|a| -*a)).fold(vec![], vec_cons);
    let s_accum = stream.fold(vec![], vec_cons).snapshot(&stream, |s, _| s.into_owned()).fold(vec![], vec_cons);
    let s_cloned = stream.fold_clone(vec![], vec_cons);

    sink.feed(vec![5, 8, 13, -2, 42, -33]);

    assert_eq!(s_string.sample(), ["5", "8", "13", "-2", "42", "-33"]);
    assert_eq!(s_odd.sample(), [5, 13, -33]);
    assert_eq!(s_even_half.sample(), [4, -1, 21]);
    assert_eq!(s_pos.sample(), [5, 8, 13, 42]);
    assert_eq!(s_neg.sample(), [-2, -33]);
    assert_eq!(s_merged.sample(), [5, 8, 13, 2, 42, 33]);
    assert_eq!(s_accum.sample(), [vec![5], vec![5, 8], vec![5, 8, 13], vec![5, 8, 13, -2], vec![5, 8, 13, -2, 42], vec![5, 8, 13, -2, 42, -33]]);
    assert_eq!(s_cloned.sample(), [5, 8, 13, -2, 42, -33]);
}

#[cfg(feature="either")]
#[test]
fn merge_with()
{
    let sink1: Sink<i32> = Sink::new();
    let sink2: Sink<f32> = Sink::new();
    let stream: Stream<Result<_, _>> = sink1.stream().merge_with(&sink2.stream(), |e| e.either(|l| Ok(*l), |r| Err(*r)));
    let result = stream.fold(vec![], vec_cons);

    sink1.send(1);
    sink2.send(2.0);
    sink1.send(3);
    sink1.send(4);
    sink2.send(5.0);

    assert_eq!(result.sample(), [Ok(1), Err(2.0), Ok(3), Ok(4), Err(5.0)]);
}

#[test]
fn stream_channel()
{
    let sink = Sink::new();
    let rx = sink.stream().channel();

    let thread = std::thread::spawn(move || {
        let sink2 = Sink::new();
        let s_sum = sink2.stream().fold(0, |a, n| a + *n);
        sink2.feed(rx.iter());
        s_sum.into_rwlock().unwrap()
    });

    sink.feed(1..100);
    drop(sink);

    let result: Signal<i32> = thread.join().unwrap().into();
    assert_eq!(result.sample(), 4950);
}

#[test]
fn stream_switch()
{
    let stream_sink = Sink::new();
    let sink1 = Sink::new();
    let sink2 = Sink::new();

    let switched = stream_sink.stream().switch();
    let events = switched.channel();

    sink1.send(1);
    sink2.send(2);

    stream_sink.send(sink2.stream());
    sink1.send(3);
    sink2.send(4);
    assert_eq!(events.try_recv(), Ok(4));

    stream_sink.send(sink1.stream());
    sink1.send(5);
    sink2.send(6);
    assert_eq!(events.try_recv(), Ok(5));
}

#[test]
fn signal_switch()
{
    let signal_sink = Sink::new();
    let switched = signal_sink.stream().hold(Signal::Constant(0)).switch();

    signal_sink.send(Signal::Constant(1));
    assert_eq!(switched.sample(), 1);

    signal_sink.send(2.into());
    assert_eq!(switched.sample(), 2);
}

#[derive(Debug)]
struct Storage<T>(Vec<T>);

impl<T> Storage<T>
{
    fn new() -> Self { Storage(Vec::new()) }
    fn push(mut self, a: T) -> Self { self.0.push(a); self }
}

impl<T: Debug> Clone for Storage<T>
{
    fn clone(&self) -> Self { panic!("storage cloned! {:?}", self.0) }
}

#[test]
fn cloning()
{
    let sink = Sink::new();
    let accum = sink.stream().fold(Storage::new(), |a, v| a.push(*v));

    sink.feed(0..5);
    accum.sample_with(|res| assert_eq!(res.0, [0, 1, 2, 3, 4]));
}

#[test]
fn filter_extra()
{
    let sink = Sink::new();
    let stream = sink.stream();
    let sign_res = stream.map(|a| if *a >= 0 { Ok(*a) } else { Err(*a) });
    let even_opt = stream.map(|a| if *a % 2 == 0 { Some(*a) } else { None });
    let s_even = even_opt.filter_some().fold(vec![], vec_cons);
    let s_pos = sign_res.filter_first().fold(vec![], vec_cons);
    let s_neg = sign_res.filter_second().fold(vec![], vec_cons);

    sink.feed(vec![1, 8, -3, 42, -66]);

    assert_eq!(s_even.sample(), [8, 42, -66]);
    assert_eq!(s_pos.sample(), [1, 8, 42]);
    assert_eq!(s_neg.sample(), [-3, -66]);
}

#[test]
fn reentrant()
{
    let sink = Sink::new();
    let cloned = sink.clone();
    let sig = sink.stream()
        .filter_map(move |n| if *n < 10 { cloned.send(*n + 1); None } else { Some(*n) })
        .hold(0);

    sink.send(1);
    assert_eq!(sig.sample(), 10);
}

#[allow(unused_variables)]
#[test]
fn deletion()
{
    use std::cell::Cell;

    fn stream_cell(src: &Stream<i32>, i: i32) -> (Stream<i32>, Rc<Cell<i32>>)
    {
        let cell = Rc::new(Cell::new(0));
        let cloned = cell.clone();
        let stream = src.map(move |n| *n + i).inspect(move |n| cloned.set(*n));
        (stream, cell)
    }

    let sink = Sink::new();
    let stream = sink.stream();
    let (s1, c1) = stream_cell(&stream, 1);
    let (s2, c2) = stream_cell(&stream, 2);
    let (s3, c3) = stream_cell(&stream, 3);

    sink.send(10);
    assert_eq!(c1.get(), 11);
    assert_eq!(c2.get(), 12);
    assert_eq!(c3.get(), 13);

    drop(s2);
    sink.send(20);
    assert_eq!(c1.get(), 21);
    assert_eq!(c2.get(), 12);
    assert_eq!(c3.get(), 23);
}

#[test]
fn map_n()
{
    let sink = Sink::new();
    let s_out = sink.stream()
        .map_n(|a, sink| for _ in 0 .. *a { sink.send(*a) })
        .fold(vec![], vec_cons);

    sink.feed(0..4);

    assert_eq!(s_out.sample(), [1, 2, 2, 3, 3, 3]);
}
<|endoftext|>


<commit_before>use {Location, UIButton};
use image::{ImageBuffer, Rgba};

const DECORATION_SIZE: i32 = 8;
const DECORATION_TOP_SIZE: i32 = 32;

#[cfg(target_endian = "little")]
macro_rules! auto_endian(
    ($a: expr, $r: expr, $g: expr, $b: expr) => {
        [$b, $g, $r, $a]
    }
);

#[cfg(target_endian = "big")]
macro_rules! auto_endian(
    ($a: expr, $r: expr, $g: expr, $b: expr) => {
        [$a, $r, $g, $b]
    }
);

// defining the color scheme
const INACTIVE_BORDER: [u8; 4] = auto_endian!(0xFF, 0x60, 0x60, 0x60);
const ACTIVE_BORDER: [u8; 4] = auto_endian!(0xFF, 0x80, 0x80, 0x80);
const RED_BUTTON_REGULAR: [u8; 4] = auto_endian!(0xFF, 0xFF, 0x40, 0x40);
const RED_BUTTON_HOVER: [u8; 4] = auto_endian!(0xFF, 0xB0, 0x40, 0x40);
const GREEN_BUTTON_REGULAR: [u8; 4] = auto_endian!(0xFF, 0x40, 0xFF, 0x40);
const GREEN_BUTTON_HOVER: [u8; 4] = auto_endian!(0xFF, 0x40, 0xB0, 0xF0);
const YELLOW_BUTTON_REGULAR: [u8; 4] = auto_endian!(0xFF, 0xB0, 0xB0, 0x40);
const YELLOW_BUTTON_HOVER: [u8; 4] = auto_endian!(0xFF, 0xFF, 0xFF, 0x40);
const YELLOW_BUTTON_DISABLED: [u8; 4] = auto_endian!(0xFF, 0x80, 0x80, 0x20);

/// Compute on which part of the window given point falls
pub(crate) fn compute_location((x, y): (f64, f64), (w, h): (i32, i32)) -> Location {
    if y <= DECORATION_TOP_SIZE as f64 {
        // we are in the top part
        if x <= DECORATION_SIZE as f64 {
            Location::TopLeft
        } else if x <= (w + DECORATION_SIZE) as f64 {
            if y <= DECORATION_SIZE as f64 {
                Location::Top
            } else {
                // check for buttons
                if (w >= 24) && (x > (w + DECORATION_SIZE - 24) as f64) && (x <= (w + DECORATION_SIZE) as f64)
                    && (y > DECORATION_SIZE as f64) && (y <= (DECORATION_SIZE + 16) as f64)
                {
                    Location::Button(UIButton::Close)
                } else if (w >= 56) && (x > (w + DECORATION_SIZE - 56) as f64)
                    && (x <= (w + DECORATION_SIZE - 32) as f64)
                    && (y > DECORATION_SIZE as f64)
                    && (y <= (DECORATION_SIZE + 16) as f64)
                {
                    Location::Button(UIButton::Maximize)
                } else if (w >= 88) && (x > (w + DECORATION_SIZE - 88) as f64)
                    && (x <= (w + DECORATION_SIZE - 64) as f64)
                    && (y > DECORATION_SIZE as f64)
                    && (y <= (DECORATION_SIZE + 16) as f64)
                {
                    Location::Button(UIButton::Minimize)
                } else {
                    Location::TopBar
                }
            }
        } else {
            Location::TopRight
        }
    } else if y <= (DECORATION_TOP_SIZE + h) as f64 {
        if x <= DECORATION_SIZE as f64 {
            Location::Left
        } else if x <= (w + DECORATION_SIZE) as f64 {
            Location::Inside
        } else {
            Location::Right
        }
    } else {
        if x <= DECORATION_SIZE as f64 {
            Location::BottomLeft
        } else if x <= (w + DECORATION_SIZE) as f64 {
            Location::Bottom
        } else {
            Location::BottomRight
        }
    }
}

/// Offset at which the contents should be drawn relative to the top-left
/// corner of the decorations
pub(crate) fn subsurface_offset() -> (i32, i32) {
    (DECORATION_SIZE, DECORATION_TOP_SIZE)
}

/// Subtracts the border dimensions from the given dimensions.
pub fn subtract_borders(width: i32, height: i32) -> (i32, i32) {
    (
        width - 2 * (DECORATION_SIZE as i32),
        height - DECORATION_SIZE as i32 - DECORATION_TOP_SIZE as i32,
    )
}

/// Adds the border dimensions to the given dimensions.
pub fn add_borders(width: i32, height: i32) -> (i32, i32) {
    (
        width + 2 * (DECORATION_SIZE as i32),
        height + DECORATION_SIZE as i32 + DECORATION_TOP_SIZE as i32,
    )
}

/// Total number of pixels of the rectangle containing the whole
/// decorated window
pub(crate) fn pxcount(w: i32, h: i32) -> i32 {
    (w + 2 * DECORATION_SIZE) * (h + DECORATION_SIZE + DECORATION_TOP_SIZE)
}

/// Draw the decorations on the rectangle
///
/// Actual contents of the window will be drawn on top
pub(crate) fn draw_contents(canvas: &mut [u8], w: u32, h: u32, activated: bool, maximized: bool,
                            maximizable: bool, ptr_location: Location) {
    let ds = DECORATION_SIZE as u32;
    let dts = DECORATION_TOP_SIZE as u32;
    let mut canvas = ImageBuffer::<Rgba<u8>, _>::from_raw(w + 2 * ds, h + ds + dts, canvas).unwrap();
    // draw the borders
    let border_rectangles = [
        (0, 0, w + 2 * ds, dts),      // top rectangle
        (0, dts, ds, h),              // left rectangle
        (w + ds, dts, ds, h),         // right rectangle
        (0, h + dts, w + 2 * ds, ds), // bottom rectangle
    ];

    // We've built an ImageBuffer from a raw &[u8] buffer, and the wayland spec
    // explicitly says we should use native endiannes
    // also we're doing ARGB (while image expects RGBA), though as long as we
    // only blit pixels it's not very important

    // fill these rectangles with grey
    let border_color = if activated {
        ACTIVE_BORDER
    } else {
        INACTIVE_BORDER
    };
    for &(x, y, w, h) in &border_rectangles {
        for xx in x..(x + w) {
            for yy in y..(y + h) {
                canvas.put_pixel(xx, yy, Rgba { data: border_color });
            }
        }
    }

    // draw the red close button
    if w >= 24 {
        let button_color = if let Location::Button(UIButton::Close) = ptr_location {
            RED_BUTTON_HOVER
        } else {
            RED_BUTTON_REGULAR
        };
        for xx in (w + ds - 24)..(w + ds) {
            for yy in ds..(ds + 16) {
                canvas.put_pixel(xx, yy, Rgba { data: button_color });
            }
        }
    }

    // draw the yellow maximize button
    if w >= 56 {
        let button_color = if maximizable {
            if let Location::Button(UIButton::Maximize) = ptr_location {
                YELLOW_BUTTON_HOVER
            } else {
                YELLOW_BUTTON_REGULAR
            }
        } else {
            YELLOW_BUTTON_DISABLED
        };
        for xx in (w + ds - 56)..(w + ds - 32) {
            for yy in ds..(ds + 16) {
                canvas.put_pixel(xx, yy, Rgba { data: button_color });
            }
        }
    }

    // draw the green minimize button
    if w >= 88 {
        let button_color = if let Location::Button(UIButton::Minimize) = ptr_location {
            GREEN_BUTTON_HOVER
        } else {
            GREEN_BUTTON_REGULAR
        };
        for xx in (w + ds - 88)..(w + ds - 64) {
            for yy in ds..(ds + 16) {
                canvas.put_pixel(xx, yy, Rgba { data: button_color });
            }
        }
    }
}
<commit_msg>Increase border 1px under content to erase glitches<commit_after>use {Location, UIButton};
use image::{ImageBuffer, Rgba};

const DECORATION_SIZE: i32 = 8;
const DECORATION_TOP_SIZE: i32 = 32;

#[cfg(target_endian = "little")]
macro_rules! auto_endian(
    ($a: expr, $r: expr, $g: expr, $b: expr) => {
        [$b, $g, $r, $a]
    }
);

#[cfg(target_endian = "big")]
macro_rules! auto_endian(
    ($a: expr, $r: expr, $g: expr, $b: expr) => {
        [$a, $r, $g, $b]
    }
);

// defining the color scheme
const INACTIVE_BORDER: [u8; 4] = auto_endian!(0xFF, 0x60, 0x60, 0x60);
const ACTIVE_BORDER: [u8; 4] = auto_endian!(0xFF, 0x80, 0x80, 0x80);
const RED_BUTTON_REGULAR: [u8; 4] = auto_endian!(0xFF, 0xFF, 0x40, 0x40);
const RED_BUTTON_HOVER: [u8; 4] = auto_endian!(0xFF, 0xB0, 0x40, 0x40);
const GREEN_BUTTON_REGULAR: [u8; 4] = auto_endian!(0xFF, 0x40, 0xFF, 0x40);
const GREEN_BUTTON_HOVER: [u8; 4] = auto_endian!(0xFF, 0x40, 0xB0, 0xF0);
const YELLOW_BUTTON_REGULAR: [u8; 4] = auto_endian!(0xFF, 0xB0, 0xB0, 0x40);
const YELLOW_BUTTON_HOVER: [u8; 4] = auto_endian!(0xFF, 0xFF, 0xFF, 0x40);
const YELLOW_BUTTON_DISABLED: [u8; 4] = auto_endian!(0xFF, 0x80, 0x80, 0x20);

/// Compute on which part of the window given point falls
pub(crate) fn compute_location((x, y): (f64, f64), (w, h): (i32, i32)) -> Location {
    if y <= DECORATION_TOP_SIZE as f64 {
        // we are in the top part
        if x <= DECORATION_SIZE as f64 {
            Location::TopLeft
        } else if x <= (w + DECORATION_SIZE) as f64 {
            if y <= DECORATION_SIZE as f64 {
                Location::Top
            } else {
                // check for buttons
                if (w >= 24) && (x > (w + DECORATION_SIZE - 24) as f64) && (x <= (w + DECORATION_SIZE) as f64)
                    && (y > DECORATION_SIZE as f64) && (y <= (DECORATION_SIZE + 16) as f64)
                {
                    Location::Button(UIButton::Close)
                } else if (w >= 56) && (x > (w + DECORATION_SIZE - 56) as f64)
                    && (x <= (w + DECORATION_SIZE - 32) as f64)
                    && (y > DECORATION_SIZE as f64)
                    && (y <= (DECORATION_SIZE + 16) as f64)
                {
                    Location::Button(UIButton::Maximize)
                } else if (w >= 88) && (x > (w + DECORATION_SIZE - 88) as f64)
                    && (x <= (w + DECORATION_SIZE - 64) as f64)
                    && (y > DECORATION_SIZE as f64)
                    && (y <= (DECORATION_SIZE + 16) as f64)
                {
                    Location::Button(UIButton::Minimize)
                } else {
                    Location::TopBar
                }
            }
        } else {
            Location::TopRight
        }
    } else if y <= (DECORATION_TOP_SIZE + h) as f64 {
        if x <= DECORATION_SIZE as f64 {
            Location::Left
        } else if x <= (w + DECORATION_SIZE) as f64 {
            Location::Inside
        } else {
            Location::Right
        }
    } else {
        if x <= DECORATION_SIZE as f64 {
            Location::BottomLeft
        } else if x <= (w + DECORATION_SIZE) as f64 {
            Location::Bottom
        } else {
            Location::BottomRight
        }
    }
}

/// Offset at which the contents should be drawn relative to the top-left
/// corner of the decorations
pub(crate) fn subsurface_offset() -> (i32, i32) {
    (DECORATION_SIZE, DECORATION_TOP_SIZE)
}

/// Subtracts the border dimensions from the given dimensions.
pub fn subtract_borders(width: i32, height: i32) -> (i32, i32) {
    (
        width - 2 * (DECORATION_SIZE as i32),
        height - DECORATION_SIZE as i32 - DECORATION_TOP_SIZE as i32,
    )
}

/// Adds the border dimensions to the given dimensions.
pub fn add_borders(width: i32, height: i32) -> (i32, i32) {
    (
        width + 2 * (DECORATION_SIZE as i32),
        height + DECORATION_SIZE as i32 + DECORATION_TOP_SIZE as i32,
    )
}

/// Total number of pixels of the rectangle containing the whole
/// decorated window
pub(crate) fn pxcount(w: i32, h: i32) -> i32 {
    (w + 2 * DECORATION_SIZE) * (h + DECORATION_SIZE + DECORATION_TOP_SIZE)
}

/// Draw the decorations on the rectangle
///
/// Actual contents of the window will be drawn on top
pub(crate) fn draw_contents(canvas: &mut [u8], w: u32, h: u32, activated: bool, maximized: bool,
                            maximizable: bool, ptr_location: Location) {
    let ds = DECORATION_SIZE as u32;
    let dts = DECORATION_TOP_SIZE as u32;
    let mut canvas = ImageBuffer::<Rgba<u8>, _>::from_raw(w + 2 * ds, h + ds + dts, canvas).unwrap();
    // draw the borders
    let border_rectangles = [
        (0, 0, w + 2 * ds, dts+1),      // top rectangle
        (0, dts, ds+1, h),              // left rectangle
        (w + ds-1, dts, ds+1, h),         // right rectangle
        (0, h + dts-1, w + 2 * ds, ds+1), // bottom rectangle
    ];

    // We've built an ImageBuffer from a raw &[u8] buffer, and the wayland spec
    // explicitly says we should use native endiannes
    // also we're doing ARGB (while image expects RGBA), though as long as we
    // only blit pixels it's not very important

    // fill these rectangles with grey
    let border_color = if activated {
        ACTIVE_BORDER
    } else {
        INACTIVE_BORDER
    };
    for &(x, y, w, h) in &border_rectangles {
        for xx in x..(x + w) {
            for yy in y..(y + h) {
                canvas.put_pixel(xx, yy, Rgba { data: border_color });
            }
        }
    }

    // draw the red close button
    if w >= 24 {
        let button_color = if let Location::Button(UIButton::Close) = ptr_location {
            RED_BUTTON_HOVER
        } else {
            RED_BUTTON_REGULAR
        };
        for xx in (w + ds - 24)..(w + ds) {
            for yy in ds..(ds + 16) {
                canvas.put_pixel(xx, yy, Rgba { data: button_color });
            }
        }
    }

    // draw the yellow maximize button
    if w >= 56 {
        let button_color = if maximizable {
            if let Location::Button(UIButton::Maximize) = ptr_location {
                YELLOW_BUTTON_HOVER
            } else {
                YELLOW_BUTTON_REGULAR
            }
        } else {
            YELLOW_BUTTON_DISABLED
        };
        for xx in (w + ds - 56)..(w + ds - 32) {
            for yy in ds..(ds + 16) {
                canvas.put_pixel(xx, yy, Rgba { data: button_color });
            }
        }
    }

    // draw the green minimize button
    if w >= 88 {
        let button_color = if let Location::Button(UIButton::Minimize) = ptr_location {
            GREEN_BUTTON_HOVER
        } else {
            GREEN_BUTTON_REGULAR
        };
        for xx in (w + ds - 88)..(w + ds - 64) {
            for yy in ds..(ds + 16) {
                canvas.put_pixel(xx, yy, Rgba { data: button_color });
            }
        }
    }
}
<|endoftext|>


<commit_before>use bus::Addressable;
use enum_primitive::FromPrimitive;
use log::warn;

const ADDR_DIV: u16  = 0xFF04;
const ADDR_TIMA: u16 = 0xFF05;
const ADDR_TMA: u16  = 0xFF06;
const ADDR_TAC: u16  = 0xFF07;

enum_from_primitive! {
    #[derive(Copy, Clone)]
    enum TacFrequency {
        Khz4 = 0,
        Khz262 = 1,
        Khz65 = 2,
        Khz16 = 3
    }
}

impl TacFrequency {
    fn as_cycles(&self) -> usize {
        match *self {
            TacFrequency::Khz4 => 1024,
            TacFrequency::Khz16 => 256,
            TacFrequency::Khz65 => 64,
            TacFrequency::Khz262 => 16
        }
    }
}

#[derive(Default)]
pub struct TimerResult {
    pub interrupt: bool
}

pub struct Timer {
    div: u16,
    tima: u8,
    tma: u8,
    tac_enabled: bool,
    tac_freq: TacFrequency,

    div_counter: usize,
    tima_counter: usize
}

impl Timer {
    pub fn new() -> Self {
        Self {
            div: 0xABCC,
            tima: 0,
            tma: 0,
            tac_enabled: false,
            tac_freq: TacFrequency::Khz4,
            div_counter: 0,
            tima_counter: 0
        }
    }

    // TODO: implement odd Timer behaviors
    pub fn step(&mut self, cycles: usize) -> TimerResult {
        let mut result = TimerResult::default();

        // DIV always counts at a constant interval even if the timer is disabled
        // DIV increments once every ~256 machine cycles
        self.div_counter += cycles;

        if self.div_counter >= 256 {
            self.div = self.div.wrapping_add(1);
            self.div_counter -= 256;
        }

        // TIMA counts if TAC is enabled. It counts at an interval set by TAC.
        if self.tac_enabled {
            self.tima_counter += cycles;

            let tac_cycles = self.tac_freq.as_cycles();

            if self.tima_counter >= tac_cycles {
                // When TIMA overflows, it is reset to TMA and an interrupt is raised.
                if self.tima == 0xFF {
                    self.tima = self.tma;
                    result.interrupt = true;
                } else {
                    self.tima += 1;
                }

                self.tima_counter -= tac_cycles;
            }
        }

        result
    }
}

impl Addressable for Timer {
    fn read(&self, addr: u16) -> u8 {
        match addr {
            ADDR_DIV => (self.div >> 8) as u8, // Retrieving DIV only returns the MSB,
            ADDR_TIMA => self.tima,
            ADDR_TMA => self.tma,
            ADDR_TAC => 0b1111_1000 | ((self.tac_enabled as u8) << 2) | (self.tac_freq as u8),
            _ => { warn!("Timer read unimplemented ({:#X})", addr); 0 }
        }
    }

    fn write(&mut self, addr: u16, val: u8) {
        match addr {
            // Writing any value to DIV resets it to 0
            ADDR_DIV => self.div = 0,
            ADDR_TIMA => self.tima = val,
            ADDR_TMA => self.tma = val,
            ADDR_TAC => {
                self.tac_enabled = (val & 0b100) == 0b100;
                self.tac_freq = TacFrequency::from_u8(val & 0b11).unwrap();
            },
            _ => warn!("Timer write unimplemented {:#X} -> {:#X}", val, addr)
        }
    }
}<commit_msg>Reset full timer on DIV write<commit_after>use bus::Addressable;
use enum_primitive::FromPrimitive;
use log::warn;

const ADDR_DIV: u16  = 0xFF04;
const ADDR_TIMA: u16 = 0xFF05;
const ADDR_TMA: u16  = 0xFF06;
const ADDR_TAC: u16  = 0xFF07;

enum_from_primitive! {
    #[derive(Copy, Clone)]
    enum TacFrequency {
        Khz4 = 0,
        Khz256 = 1,
        Khz64 = 2,
        Khz16 = 3
    }
}

impl TacFrequency {
    fn as_cycles(&self) -> usize {
        match *self {
            TacFrequency::Khz4 => 1024,
            TacFrequency::Khz16 => 256,
            TacFrequency::Khz64 => 64,
            TacFrequency::Khz256 => 16
        }
    }
}

#[derive(Default)]
pub struct TimerResult {
    pub interrupt: bool
}

pub struct Timer {
    div: u8,
    tima: u8,
    tma: u8,
    tac_enabled: bool,
    tac_freq: TacFrequency,

    div_cycles: usize,
    tima_cycles: usize
}

impl Timer {
    pub fn new() -> Self {
        Self {
            div: 0xAB,
            tima: 0,
            tma: 0,
            tac_enabled: false,
            tac_freq: TacFrequency::Khz4,
            div_cycles: 0,
            tima_cycles: 0
        }
    }

    // TODO: implement odd Timer behaviors
    pub fn step(&mut self, cycles: usize) -> TimerResult {
        let mut result = TimerResult::default();

        // DIV always counts at a constant interval even if the timer is disabled
        // DIV increments once every ~256 clock cycles
        self.div_cycles += cycles;

        if self.div_cycles >= 256 {
            self.div = self.div.wrapping_add(1);
            self.div_cycles -= 256;
        }

        // TIMA counts if TAC is enabled. It counts at an interval set by TAC.
        if self.tac_enabled {
            self.tima_cycles += cycles;

            let tac_cycles = self.tac_freq.as_cycles();

            if self.tima_cycles >= tac_cycles {
                // When TIMA overflows, it is reset to TMA and an interrupt is raised.
                if self.tima == 0xFF {
                    self.tima = self.tma;
                    result.interrupt = true;
                } else {
                    self.tima += 1;
                }

                self.tima_cycles -= tac_cycles;
            }
        }

        result
    }
}

impl Addressable for Timer {
    fn read(&self, addr: u16) -> u8 {
        match addr {
            ADDR_DIV => self.div,
            ADDR_TIMA => self.tima,
            ADDR_TMA => self.tma,
            ADDR_TAC => 0b1111_1000 | ((self.tac_enabled as u8) << 2) | (self.tac_freq as u8),
            _ => { warn!("Timer read unimplemented ({:#X})", addr); 0 }
        }
    }

    fn write(&mut self, addr: u16, val: u8) {
        match addr {
            // Writing any value to DIV resets the whole counter
            ADDR_DIV => {
                self.div = 0;
                self.div_cycles = 0;
                self.tima_cycles = 0;
            },
            ADDR_TIMA => self.tima = val,
            ADDR_TMA => self.tma = val,
            ADDR_TAC => {
                self.tac_enabled = (val & 0b100) == 0b100;
                self.tac_freq = TacFrequency::from_u8(val & 0b11).unwrap();
            },
            _ => warn!("Timer write unimplemented {:#X} -> {:#X}", val, addr)
        }
    }
}<|endoftext|>


<commit_before>#[cfg(not(target_arch = "wasm32"))]
use std::time::{Instant, Duration};

#[cfg(not(target_arch = "wasm32"))]
#[cfg_attr(any(feature = "test", test), allow(dead_code))]
pub struct Timer {
    timer: Instant,
}

#[cfg(not(target_arch = "wasm32"))]
impl Timer {
    pub fn start() -> Self {
        Self {
            timer: Instant::now(),
        }
    }

    #[cfg_attr(any(feature = "test", test), allow(dead_code))]
    pub fn elapsed_millis(&self) -> u64 {
        Self::as_millis(self.timer.elapsed())
    }

    /// Converts the given Duration into its value in milliseconds
    ///
    /// This used to be part of the API but it is easy enough to compute
    /// from the current one as well.
    fn as_millis(duration: Duration) -> u64 {
        //FIXME: Remove this function and just use `timer.elapsed().as_millis()` when
        // this issue is closed: https://github.com/rust-lang/rust/issues/50202
        duration.as_secs() * 1000 + u64::from(duration.subsec_nanos() / 1_000_000)
    }
}

// Functions preovided by JavaScript, to be called by the WebAssembly generated from Rust
#[cfg(all(target_arch = "wasm32", not(any(feature = "test", test))))]
extern "C" {
    fn now() -> u64;
}

#[cfg(all(target_arch = "wasm32", not(any(feature = "test", test))))]
pub struct Timer {
    start: u64,
}

#[cfg(all(target_arch = "wasm32", not(any(feature = "test", test))))]
impl Timer {
    pub fn start() -> Self {
        Self {
            start: Self::now(),
        }
    }

    pub fn elapsed_millis(&self) -> u64 {
        Self::now() - self.start
    }

    fn now() -> u64 {
        unsafe { now() }
    }
}
<commit_msg>No longer sending i64 to/from JavaScript<commit_after>#[cfg(not(target_arch = "wasm32"))]
use std::time::{Instant, Duration};

#[cfg(not(target_arch = "wasm32"))]
#[cfg_attr(any(feature = "test", test), allow(dead_code))]
pub struct Timer {
    timer: Instant,
}

#[cfg(not(target_arch = "wasm32"))]
impl Timer {
    pub fn start() -> Self {
        Self {
            timer: Instant::now(),
        }
    }

    #[cfg_attr(any(feature = "test", test), allow(dead_code))]
    pub fn elapsed_millis(&self) -> u64 {
        Self::as_millis(self.timer.elapsed())
    }

    /// Converts the given Duration into its value in milliseconds
    ///
    /// This used to be part of the API but it is easy enough to compute
    /// from the current one as well.
    fn as_millis(duration: Duration) -> u64 {
        //FIXME: Remove this function and just use `timer.elapsed().as_millis()` when
        // this issue is closed: https://github.com/rust-lang/rust/issues/50202
        duration.as_secs() * 1000 + u64::from(duration.subsec_nanos() / 1_000_000)
    }
}

// Functions preovided by JavaScript, to be called by the WebAssembly generated from Rust
#[cfg(all(target_arch = "wasm32", not(any(feature = "test", test))))]
extern "C" {
    // WASM doesn't support passing i64 between JavaScript, so we can only use u32 here, not u64
    fn now() -> u32;
}

#[cfg(all(target_arch = "wasm32", not(any(feature = "test", test))))]
pub struct Timer {
    start: u64,
}

#[cfg(all(target_arch = "wasm32", not(any(feature = "test", test))))]
impl Timer {
    pub fn start() -> Self {
        Self {
            start: Self::now(),
        }
    }

    pub fn elapsed_millis(&self) -> u64 {
        Self::now() - self.start
    }

    fn now() -> u64 {
        (unsafe { now() }) as u64
    }
}
<|endoftext|>


<commit_before>//! Timing and measurement functions.
//!
//! ggez does not try to do any framerate limitation by default. If
//! you want to run at anything other than full-bore max speed all the
//! time, calling `thread::yield_now()` (or `timer::yield_now()` which
//! does the same thing) yield to the OS
//! so it has a chance to breathe before continuing with your game.
//! This should prevent it from using 100% CPU unless it really needs
//! to.  Enabling vsync by setting `vsync` in your `Conf` object is
//! generally the best way to cap your displayed framerate.
//!
//! For a more detailed tutorial in how to handle frame timings in games,
//! see <http://gafferongames.com/game-physics/fix-your-timestep/>

use context::Context;

use std::cmp;
use std::time;
use std::thread;
use std::f64;

/// A simple buffer that fills
/// up to a limit and then holds the last
/// N items that have been inserted into it,
/// overwriting old ones in a round-robin fashion.
///
/// It's not quite a ring buffer 'cause you can't
/// remove items from it, it just holds the last N
/// things.
#[derive(Debug, Clone)]
struct LogBuffer<T>
where
    T: Clone,
{
    head: usize,
    size: usize,
    contents: Vec<T>,
}

impl<T> LogBuffer<T>
where
    T: Clone + Copy,
{
    fn new(size: usize, init_val: T) -> LogBuffer<T> {
        let mut v = Vec::with_capacity(size);
        v.resize(size, init_val);
        LogBuffer {
            head: 0,
            size,
            contents: v,
        }
    }

    /// Pushes a new item into the logbuffer, overwriting
    /// the oldest item in it.
    fn push(&mut self, item: T) {
        self.head = (self.head + 1) % self.contents.len();
        self.contents[self.head] = item;
        self.size = cmp::min(self.size + 1, self.contents.len());
    }

    /// Returns a slice pointing at the contents of the buffer.
    /// They are in *no particular order*, and if not all the
    /// slots are filled, the empty slots will be present but
    /// contain the initial value given to `new()`
    ///
    /// We're only using this to log FPS for a short time,
    /// so we don't care for the second or so when it's inaccurate.
    fn contents(&self) -> &[T] {
        &self.contents
    }

    /// Returns the most recent value in the buffer.
    fn latest(&self) -> T {
        self.contents[self.head]
    }
}

/// A structure that contains our time-tracking state.
#[derive(Debug)]
pub struct TimeContext {
    init_instant: time::Instant,
    last_instant: time::Instant,
    frame_durations: LogBuffer<time::Duration>,
    residual_update_dt: time::Duration,
    frame_count: usize,
}

// How many frames we log update times for.
const TIME_LOG_FRAMES: usize = 200;

impl TimeContext {
    /// Creates a new `TimeContext` and initializes the start to this instant.
    pub fn new() -> TimeContext {
        TimeContext {
            init_instant: time::Instant::now(),
            last_instant: time::Instant::now(),
            frame_durations: LogBuffer::new(TIME_LOG_FRAMES, time::Duration::new(0, 0)),
            residual_update_dt: time::Duration::from_secs(0),
            frame_count: 0,
        }
    }

    /// Update the state of the TimeContext to record that
    /// another frame has taken place.  Necessary for the FPS
    /// tracking and `check_update_time()` functions to work.
    ///
    /// It's usually not necessary to call this function yourself,
    /// `EventHandler::run()` will do it for you.
    pub fn tick(&mut self) {
        let now = time::Instant::now();
        let time_since_last = now - self.last_instant;
        self.frame_durations.push(time_since_last);
        self.last_instant = now;
        self.frame_count += 1;

        self.residual_update_dt += time_since_last;
    }
}

impl Default for TimeContext {
    fn default() -> Self {
        Self::new()
    }
}

/// Get the time between the start of the last frame and the current one;
/// in other words, the length of the last frame.
pub fn get_delta(ctx: &Context) -> time::Duration {
    let tc = &ctx.timer_context;
    tc.frame_durations.latest()
}

/// Gets the average time of a frame, averaged
/// over the last 200 frames.
pub fn get_average_delta(ctx: &Context) -> time::Duration {
    let tc = &ctx.timer_context;
    let init = time::Duration::new(0, 0);
    let sum = tc.frame_durations
        .contents()
        .iter()
        .fold(init, |d1, d2| d1 + *d2);
    sum / (tc.frame_durations.size as u32)
}

/// A convenience function to convert a Rust `Duration` type
/// to a (less precise but more useful) f64.
///
/// Does not make sure that the `Duration` is within the bounds
/// of the `f64`.
pub fn duration_to_f64(d: time::Duration) -> f64 {
    let seconds = d.as_secs() as f64;
    let nanos = f64::from(d.subsec_nanos());
    seconds + (nanos * 1e-9)
}

/// A convenience function to create a Rust `Duration` type
/// from a (less precise but more useful) f64.
///
/// Only handles positive numbers correctly.
pub fn f64_to_duration(t: f64) -> time::Duration {
    debug_assert!(t >= 0.0, "f64_to_duration passed a negative number!");
    let seconds = t.trunc();
    let nanos = t.fract() * 1e9;
    time::Duration::new(seconds as u64, nanos as u32)
}

/// Returns a `Duration` representing how long each
/// frame should be to match the given fps.
///
/// Approximately.
fn fps_as_duration(fps: u32) -> time::Duration {
    let target_dt_seconds = 1.0 / f64::from(fps);
    f64_to_duration(target_dt_seconds)
}

/// Gets the FPS of the game, averaged over the last
/// 200 frames.
pub fn get_fps(ctx: &Context) -> f64 {
    let duration_per_frame = get_average_delta(ctx);
    let seconds_per_frame = duration_to_f64(duration_per_frame);
    1.0 / seconds_per_frame
}

/// Returns the time since the game was initialized,
/// as reported by the system clock.
pub fn get_time_since_start(ctx: &Context) -> time::Duration {
    let tc = &ctx.timer_context;
    time::Instant::now() - tc.init_instant
}

/// This function will return true if the time since the
/// last `update()` call has been equal to or greater to
/// the update FPS indicated by the `target_fps`.
/// It keeps track of fractional frames, so if you want
/// 60 fps (16.67 ms/frame) and the game stutters so that
/// there is 40 ms between `update()` calls, this will return
/// `true` twice, and take the remaining 6.67 ms into account
/// in the next frame.
///
/// The intention is to for it to be called in a while loop
/// in your `update()` callback:
///
/// ```rust,ignore
/// fn update(&mut self, ctx: &mut Context) -> GameResult<()>
///     while(timer::check_update_time(ctx, 60)) {
///         update_game_physics()?;
///     }
///     Ok(())
/// }
/// ```
pub fn check_update_time(ctx: &mut Context, target_fps: u32) -> bool {
    let timedata = &mut ctx.timer_context;

    let target_dt = fps_as_duration(target_fps);
    if timedata.residual_update_dt > target_dt {
        timedata.residual_update_dt -= target_dt;
        true
    } else {
        false
    }
}

/// Pauses the current thread for the target duration.
/// Just calls `std::thread::sleep()` so it's as accurate
/// as that is (which is usually not very).
pub fn sleep(duration: time::Duration) {
    thread::sleep(duration);
}

/// Yields the current timeslice to the OS.
///
/// This just calls `std::thread::yield_now()` but it's
/// handy to have here.
pub fn yield_now() {
    thread::yield_now();
}

/// Gets the number of times the game has gone through its event loop.
///
/// Specifically, the number of times that `TimeContext::tick()` has been
/// called by it.
pub fn get_ticks(ctx: &Context) -> usize {
    ctx.timer_context.frame_count
}
<commit_msg>timer: add add get_update_time()<commit_after>//! Timing and measurement functions.
//!
//! ggez does not try to do any framerate limitation by default. If
//! you want to run at anything other than full-bore max speed all the
//! time, calling `thread::yield_now()` (or `timer::yield_now()` which
//! does the same thing) yield to the OS
//! so it has a chance to breathe before continuing with your game.
//! This should prevent it from using 100% CPU unless it really needs
//! to.  Enabling vsync by setting `vsync` in your `Conf` object is
//! generally the best way to cap your displayed framerate.
//!
//! For a more detailed tutorial in how to handle frame timings in games,
//! see <http://gafferongames.com/game-physics/fix-your-timestep/>

use context::Context;

use std::cmp;
use std::time;
use std::thread;
use std::f64;

/// A simple buffer that fills
/// up to a limit and then holds the last
/// N items that have been inserted into it,
/// overwriting old ones in a round-robin fashion.
///
/// It's not quite a ring buffer 'cause you can't
/// remove items from it, it just holds the last N
/// things.
#[derive(Debug, Clone)]
struct LogBuffer<T>
where
    T: Clone,
{
    head: usize,
    size: usize,
    contents: Vec<T>,
}

impl<T> LogBuffer<T>
where
    T: Clone + Copy,
{
    fn new(size: usize, init_val: T) -> LogBuffer<T> {
        let mut v = Vec::with_capacity(size);
        v.resize(size, init_val);
        LogBuffer {
            head: 0,
            size,
            contents: v,
        }
    }

    /// Pushes a new item into the logbuffer, overwriting
    /// the oldest item in it.
    fn push(&mut self, item: T) {
        self.head = (self.head + 1) % self.contents.len();
        self.contents[self.head] = item;
        self.size = cmp::min(self.size + 1, self.contents.len());
    }

    /// Returns a slice pointing at the contents of the buffer.
    /// They are in *no particular order*, and if not all the
    /// slots are filled, the empty slots will be present but
    /// contain the initial value given to `new()`
    ///
    /// We're only using this to log FPS for a short time,
    /// so we don't care for the second or so when it's inaccurate.
    fn contents(&self) -> &[T] {
        &self.contents
    }

    /// Returns the most recent value in the buffer.
    fn latest(&self) -> T {
        self.contents[self.head]
    }
}

/// A structure that contains our time-tracking state.
#[derive(Debug)]
pub struct TimeContext {
    init_instant: time::Instant,
    last_instant: time::Instant,
    frame_durations: LogBuffer<time::Duration>,
    residual_update_dt: time::Duration,
    frame_count: usize,
}

// How many frames we log update times for.
const TIME_LOG_FRAMES: usize = 200;

impl TimeContext {
    /// Creates a new `TimeContext` and initializes the start to this instant.
    pub fn new() -> TimeContext {
        TimeContext {
            init_instant: time::Instant::now(),
            last_instant: time::Instant::now(),
            frame_durations: LogBuffer::new(TIME_LOG_FRAMES, time::Duration::new(0, 0)),
            residual_update_dt: time::Duration::from_secs(0),
            frame_count: 0,
        }
    }

    /// Update the state of the TimeContext to record that
    /// another frame has taken place.  Necessary for the FPS
    /// tracking and `check_update_time()` functions to work.
    ///
    /// It's usually not necessary to call this function yourself,
    /// `EventHandler::run()` will do it for you.
    pub fn tick(&mut self) {
        let now = time::Instant::now();
        let time_since_last = now - self.last_instant;
        self.frame_durations.push(time_since_last);
        self.last_instant = now;
        self.frame_count += 1;

        self.residual_update_dt += time_since_last;
    }
}

impl Default for TimeContext {
    fn default() -> Self {
        Self::new()
    }
}

/// Get the time between the start of the last frame and the current one;
/// in other words, the length of the last frame.
pub fn get_delta(ctx: &Context) -> time::Duration {
    let tc = &ctx.timer_context;
    tc.frame_durations.latest()
}

/// Gets the average time of a frame, averaged
/// over the last 200 frames.
pub fn get_average_delta(ctx: &Context) -> time::Duration {
    let tc = &ctx.timer_context;
    let init = time::Duration::new(0, 0);
    let sum = tc.frame_durations
        .contents()
        .iter()
        .fold(init, |d1, d2| d1 + *d2);
    sum / (tc.frame_durations.size as u32)
}

/// A convenience function to convert a Rust `Duration` type
/// to a (less precise but more useful) f64.
///
/// Does not make sure that the `Duration` is within the bounds
/// of the `f64`.
pub fn duration_to_f64(d: time::Duration) -> f64 {
    let seconds = d.as_secs() as f64;
    let nanos = f64::from(d.subsec_nanos());
    seconds + (nanos * 1e-9)
}

/// A convenience function to create a Rust `Duration` type
/// from a (less precise but more useful) f64.
///
/// Only handles positive numbers correctly.
pub fn f64_to_duration(t: f64) -> time::Duration {
    debug_assert!(t >= 0.0, "f64_to_duration passed a negative number!");
    let seconds = t.trunc();
    let nanos = t.fract() * 1e9;
    time::Duration::new(seconds as u64, nanos as u32)
}

/// Returns a `Duration` representing how long each
/// frame should be to match the given fps.
///
/// Approximately.
fn fps_as_duration(fps: u32) -> time::Duration {
    let target_dt_seconds = 1.0 / f64::from(fps);
    f64_to_duration(target_dt_seconds)
}

/// Gets the FPS of the game, averaged over the last
/// 200 frames.
pub fn get_fps(ctx: &Context) -> f64 {
    let duration_per_frame = get_average_delta(ctx);
    let seconds_per_frame = duration_to_f64(duration_per_frame);
    1.0 / seconds_per_frame
}

/// Returns the time since the game was initialized,
/// as reported by the system clock.
pub fn get_time_since_start(ctx: &Context) -> time::Duration {
    let tc = &ctx.timer_context;
    time::Instant::now() - tc.init_instant
}

/// This function will return true if the time since the
/// last `update()` call has been equal to or greater to
/// the update FPS indicated by the `target_fps`.
/// It keeps track of fractional frames, so if you want
/// 60 fps (16.67 ms/frame) and the game stutters so that
/// there is 40 ms between `update()` calls, this will return
/// `true` twice, and take the remaining 6.67 ms into account
/// in the next frame.
///
/// The intention is to for it to be called in a while loop
/// in your `update()` callback:
///
/// ```rust,ignore
/// fn update(&mut self, ctx: &mut Context) -> GameResult<()>
///     while(timer::check_update_time(ctx, 60)) {
///         update_game_physics()?;
///     }
///     Ok(())
/// }
/// ```
pub fn check_update_time(ctx: &mut Context, target_fps: u32) -> bool {
    let timedata = &mut ctx.timer_context;

    let target_dt = fps_as_duration(target_fps);
    if timedata.residual_update_dt > target_dt {
        timedata.residual_update_dt -= target_dt;
        true
    } else {
        false
    }
}

/// Returns the total time not consumed by `check_update_time()`
/// (the remainder or unhandled time).
///
/// The intention is for it to be called in your `draw()` callback
/// to interpolate phyisics states for smooth rendering.
/// (see <http://gafferongames.com/game-physics/fix-your-timestep/>)
pub fn get_update_time(ctx: &mut Context) -> time::Duration {
    ctx.timer_context.residual_update_dt
}

/// Pauses the current thread for the target duration.
/// Just calls `std::thread::sleep()` so it's as accurate
/// as that is (which is usually not very).
pub fn sleep(duration: time::Duration) {
    thread::sleep(duration);
}

/// Yields the current timeslice to the OS.
///
/// This just calls `std::thread::yield_now()` but it's
/// handy to have here.
pub fn yield_now() {
    thread::yield_now();
}

/// Gets the number of times the game has gone through its event loop.
///
/// Specifically, the number of times that `TimeContext::tick()` has been
/// called by it.
pub fn get_ticks(ctx: &Context) -> usize {
    ctx.timer_context.frame_count
}
<|endoftext|>


<commit_before>#![crate_name = "uu_tr"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 * (c) kwantam <kwantam@gmail.com>
 *     20150428 created `expand` module to eliminate most allocs during setup
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate bit_set;
extern crate getopts;

#[macro_use]
extern crate uucore;

use bit_set::BitSet;
use getopts::Options;
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
use std::collections::HashMap;

use expand::ExpandSet;

mod expand;

static NAME: &'static str = "tr";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
const BUFFER_LEN: usize = 1024;

fn delete(set: ExpandSet, complement: bool) {
    let mut bset = BitSet::new();
    let mut stdout = stdout();
    let mut buf = String::with_capacity(BUFFER_LEN + 4);

    for c in set {
        bset.insert(c as usize);
    }

    let is_allowed = |c : char| {
        if complement {
            bset.contains(c as usize)
        } else {
            !bset.contains(c as usize)
        }
    };

    let mut reader = BufReader::new(stdin());

    while let Ok(length) = reader.read_to_string(&mut buf) {
        if length == 0 { break }

        let filtered = buf.chars()
                          .filter(|c| { is_allowed(*c) })
                          .collect::<String>();
        safe_unwrap!(stdout.write_all(filtered.as_bytes()));
        buf.clear();
    }
}

fn tr<'a>(set1: ExpandSet<'a>, mut set2: ExpandSet<'a>) {
    //let mut map = VecMap::new();
    let mut map = HashMap::new();
    let stdout = stdout();
    let mut buf = String::with_capacity(BUFFER_LEN + 4);

    let mut s2_prev = '_';
    for i in set1 {
        s2_prev = set2.next().unwrap_or(s2_prev);

        map.insert(i as usize, s2_prev);
    }

    let mut reader = BufReader::new(stdin());
    let mut writer = BufWriter::new(stdout);

    while let Ok(length) = reader.read_to_string(&mut buf) {
        if length == 0 { break }

        {
            let mut chars = buf.chars();

            while let Some(ch) = chars.next() {
                let trc = match map.get(&(ch as usize)) {
                    Some(t) => *t,
                    None => ch,
                };
                safe_unwrap!(writer.write_all(format!("{}", trc).as_ref()));
            }
        }

        buf.clear();
    }
}

fn usage(opts: &Options) {
    println!("{} {}", NAME, VERSION);
    println!("");
    println!("Usage:");
    println!("  {} [OPTIONS] SET1 [SET2]", NAME);
    println!("");
    println!("{}", opts.usage("Translate or delete characters."));
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "complement", "use the complement of SET1");
    opts.optflag("C", "", "same as -c");
    opts.optflag("d", "delete", "delete characters in SET1");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => {
            show_error!("{}", err);
            return 1;
        }
    };

    if matches.opt_present("help") {
        usage(&opts);
        return 0;
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.free.is_empty() {
        usage(&opts);
        return 1;
    }

    let dflag = matches.opt_present("d");
    let cflag = matches.opts_present(&["c".to_owned(), "C".to_owned()]);
    let sets = matches.free;

    if cflag && !dflag {
        show_error!("-c is only supported with -d");
        return 1;
    }

    if dflag {
        let set1 = ExpandSet::new(sets[0].as_ref());
        delete(set1, cflag);
    } else {
        let set1 = ExpandSet::new(sets[0].as_ref());
        let set2 = ExpandSet::new(sets[1].as_ref());
        tr(set1, set2);
    }

    0
}
<commit_msg>tr: use streaming instead of buffering the entire input and output<commit_after>#![crate_name = "uu_tr"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 * (c) kwantam <kwantam@gmail.com>
 *     20150428 created `expand` module to eliminate most allocs during setup
 * (c) Sergey "Shnatsel" Davidoff <shnatsel@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate bit_set;
extern crate getopts;

#[macro_use]
extern crate uucore;

use bit_set::BitSet;
use getopts::Options;
use std::io::{stdin, stdout, BufRead, BufWriter, Write};
use std::collections::HashMap;

use expand::ExpandSet;

mod expand;

static NAME: &'static str = "tr";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
const BUFFER_LEN: usize = 1024;

fn delete(set: ExpandSet, complement: bool) {
    let mut bset = BitSet::new();
    let stdin = stdin();
    let mut locked_stdin = stdin.lock();
    let mut buffered_stdout = BufWriter::new(stdout());
    let mut buf = String::with_capacity(BUFFER_LEN + 4);
    let mut char_output_buffer: [u8; 4] = [0;4];

    for c in set {
        bset.insert(c as usize);
    }

    let is_allowed = |c : char| {
        if complement {
            bset.contains(c as usize)
        } else {
            !bset.contains(c as usize)
        }
    };

    while let Ok(length) = locked_stdin.read_line(&mut buf) {
        if length == 0 { break }
        { // isolation to make borrow checker happy
            let filtered = buf.chars().filter(|c| is_allowed(*c));
            for c in filtered {
                let char_as_bytes = c.encode_utf8(&mut char_output_buffer);
                buffered_stdout.write_all(char_as_bytes.as_bytes()).unwrap();
            }
        }
        buf.clear();
    }
}

fn tr<'a>(set1: ExpandSet<'a>, mut set2: ExpandSet<'a>) {
    //let mut map = VecMap::new();
    let mut map = HashMap::new();
    let stdin = stdin();
    let mut locked_stdin = stdin.lock();
    let mut buffered_stdout = BufWriter::new(stdout());
    let mut buf = String::with_capacity(BUFFER_LEN + 4);
    let mut char_output_buffer: [u8; 4] = [0;4];

    let mut s2_prev = '_';
    for i in set1 {
        s2_prev = set2.next().unwrap_or(s2_prev);

        map.insert(i as usize, s2_prev);
    }

    while let Ok(length) = locked_stdin.read_line(&mut buf) {
        if length == 0 { break }

        { // isolation to make borrow checker happy
            let output_stream = buf.chars().map(|c| *map.get(&(c as usize)).unwrap_or(&c));
            for c in output_stream {
                let char_as_bytes = c.encode_utf8(&mut char_output_buffer);
                buffered_stdout.write_all(char_as_bytes.as_bytes()).unwrap();
            }
        }

        buf.clear();
    }
}

fn usage(opts: &Options) {
    println!("{} {}", NAME, VERSION);
    println!("");
    println!("Usage:");
    println!("  {} [OPTIONS] SET1 [SET2]", NAME);
    println!("");
    println!("{}", opts.usage("Translate or delete characters."));
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "complement", "use the complement of SET1");
    opts.optflag("C", "", "same as -c");
    opts.optflag("d", "delete", "delete characters in SET1");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => {
            show_error!("{}", err);
            return 1;
        }
    };

    if matches.opt_present("help") {
        usage(&opts);
        return 0;
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.free.is_empty() {
        usage(&opts);
        return 1;
    }

    let dflag = matches.opt_present("d");
    let cflag = matches.opts_present(&["c".to_owned(), "C".to_owned()]);
    let sets = matches.free;

    if cflag && !dflag {
        show_error!("-c is only supported with -d");
        return 1;
    }

    if dflag {
        let set1 = ExpandSet::new(sets[0].as_ref());
        delete(set1, cflag);
    } else {
        let set1 = ExpandSet::new(sets[0].as_ref());
        let set2 = ExpandSet::new(sets[1].as_ref());
        tr(set1, set2);
    }

    0
}
<|endoftext|>


<commit_before>
extern crate regex;
extern crate core;

use std::str;
use std::slice::SliceConcatExt;
use self::core::str::StrExt;
use self::regex::Regex;
use std::num::ToPrimitive;

pub fn score(choice: &str, query: &str) -> f64 {
    if choice == "" || query.char_len() > choice.char_len() {
        0f64
    } else if query == "" {
        1f64
    } else {
        let match_length = compute_match_length(choice, query);

        if match_length > 0 {
            return 1f64 / choice.char_len().to_f64().unwrap();
        } else {
            return 0f64;
        }
    }
}

// Find the length of the shortest substring matching the given characters.
fn compute_match_length(string: &str, query: &str) -> usize {
    let re_string = make_query_regex(query);
    let re = match Regex::new(re_string.as_slice()) {
        Ok(re)   => re,
        Err(err) => panic!("{}", err.msg),
    };

    if re.is_match(string) {
        let caps = re.captures(string).unwrap();
        match caps.at(0) {
            Some(s) => return s.char_len(),
            None    => return 0
        };
    } else {
        return 0;
    }
}

// Creates a regex for performing a non-greedy fuzzy match.
// Turns "abc" into "a.*?b.*?c.*?".
fn make_query_regex(query: &str) -> String {
    return query
        .chars()
        .map(|ch| ch.to_string())
        .collect::<Vec<String>>()
        .connect(".*?");
}

#[cfg(test)]
mod test {

    use super::core::str::StrExt;
    use std::num::ToPrimitive;

    #[test]
    fn scores_zero_when_the_choice_is_empty() {
        assert_eq!(super::score("", ""), 0f64);
    }

    #[test]
    fn scores_one_when_the_query_is_empty() {
        assert_eq!(super::score("a", ""), 1f64);
    }

    #[test]
    fn scores_zero_when_the_query_is_longer_than_the_choice() {
        assert_eq!(super::score("short", "longer"), 0f64);
    }

    #[test]
    fn scores_zero_when_only_a_prefix_of_the_query_matches() {
        assert_eq!(super::score("ab", "ac"), 0f64);
    }

    #[test]
    fn scores_greater_than_zero_when_it_matches() {
        assert!(super::score("a", "a") > 0f64);
        assert!(super::score("ab", "a") > 0f64);
        assert!(super::score("ba", "a") > 0f64);
        assert!(super::score("bab", "a") > 0f64);
        assert!(super::score("babababab", "aaaa") > 0f64);
    }

    #[test]
    fn scores_one_normalized_to_length_when_the_query_equals_the_choice() {
        assert_eq!(super::score("a", "a"), 1.0f64);
        assert_eq!(super::score("ab", "ab"), 0.5f64);
        assert_eq!(super::score("a long string", "a long string"),
            1.0f64 / ("a long string".char_len().to_f64().unwrap()));

        assert_eq!(super::score("spec/search_spec.rb", "sear"),
            1.0f64 / ("spec/search_spec.rb".char_len().to_f64().unwrap()));
    }
}

<commit_msg>Punctation and case-insensitive match handling.<commit_after>
extern crate regex;
extern crate core;

use std::str;
use std::slice::SliceConcatExt;
use self::core::str::StrExt;
use self::regex::Regex;
use std::num::ToPrimitive;

pub fn score(choice: &str, query: &str) -> f64 {
    if choice == "" || query.char_len() > choice.char_len() {
        0f64
    } else if query == "" {
        1f64
    } else {
        let match_length = compute_match_length(choice, query);

        if match_length > 0 {
            return 1f64 / choice.char_len().to_f64().unwrap();
        } else {
            return 0f64;
        }
    }
}

// Find the length of the shortest substring matching the given characters.
fn compute_match_length(string: &str, query: &str) -> usize {
    let re_string = make_query_regex(query);
    let re = match Regex::new(re_string.as_slice()) {
        Ok(re)   => { println!("RE: {}", re); re},
        Err(err) => panic!("{}", err.msg),
    };

    if re.is_match(string) {
        let caps = re.captures(string).unwrap();
        match caps.at(0) {
            Some(s) => return s.char_len(),
            None    => return 0
        };
    } else {
        return 0;
    }
}

// Creates a regex for performing a case-insensitive non-greedy fuzzy match.
// Turns "abc" into "(?i)a.*?b.*?c.*?".
fn make_query_regex(query: &str) -> String {
    let mut v = query
        .chars()
        .map(|ch| regex::quote(ch.to_string().as_slice()))
        .collect::<Vec<String>>();

    v.insert(0, String::from_str("(?i)"));

    return v.connect(".*?");
}

#[cfg(test)]
mod test {

    use super::core::str::StrExt;
    use std::num::ToPrimitive;

    #[test]
    fn scores_zero_when_the_choice_is_empty() {
        assert_eq!(super::score("", ""), 0f64);
    }

    #[test]
    fn scores_one_when_the_query_is_empty() {
        assert_eq!(super::score("a", ""), 1f64);
    }

    #[test]
    fn scores_zero_when_the_query_is_longer_than_the_choice() {
        assert_eq!(super::score("short", "longer"), 0f64);
    }

    #[test]
    fn scores_zero_when_only_a_prefix_of_the_query_matches() {
        assert_eq!(super::score("ab", "ac"), 0f64);
    }

    #[test]
    fn scores_greater_than_zero_when_it_matches() {
        assert!(super::score("a", "a") > 0f64);
        assert!(super::score("ab", "a") > 0f64);
        assert!(super::score("ba", "a") > 0f64);
        assert!(super::score("bab", "a") > 0f64);
        assert!(super::score("babababab", "aaaa") > 0f64);
    }

    #[test]
    fn scores_one_normalized_to_length_when_the_query_equals_the_choice() {
        assert_eq!(super::score("a", "a"), 1.0f64);
        assert_eq!(super::score("ab", "ab"), 0.5f64);
        assert_eq!(super::score("a long string", "a long string"),
            1.0f64 / ("a long string".char_len().to_f64().unwrap()));

        assert_eq!(super::score("spec/search_spec.rb", "sear"),
            1.0f64 / ("spec/search_spec.rb".char_len().to_f64().unwrap()));
    }

    // Character matching

    #[test]
    fn it_matches_punctuation() {
        assert!(super::score("/! symbols $^", "/!$^") > 0f64);
    }

    #[test]
    fn it_is_case_insensitive() {
      assert_eq!(super::score("a", "A"), 1f64);
      assert_eq!(super::score("A", "a"), 1f64);
    }
}

<|endoftext|>


<commit_before>use std::fmt;
use std::error;
use gl;

pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}

impl Color {
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
        Color { r: r, g: g, b: b, a: a}
    }
}

#[derive(Clone, Copy)]
pub struct Viewport {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32
}

impl Viewport {
    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
        Viewport {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

bitflags! {
    flags BufferBits: gl::types::GLbitfield {
        const COLOR_BUFFER_BIT = gl::COLOR_BUFFER_BIT,
        const DEPTH_BUFFER_BIT = gl::DEPTH_BUFFER_BIT,
        const STENCIL_BUFFER_BIT = gl::STENCIL_BUFFER_BIT
    }
}

#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    FramebufferError(GLFramebufferError),
    Message(String)
}

impl fmt::Display for GLError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLError::InvalidEnum => {
                write!(f, "Invalid enum")
            },
            GLError::InvalidValue => {
                write!(f, "Invalid value")
            },
            GLError::InvalidOperation => {
                write!(f, "Invalid operation")
            },
            GLError::InvalidFramebufferOperation => {
                write!(f, "Invalid framebuffer operation")
            },
            GLError::OutOfMemory => {
                write!(f, "Out of memory")
            },
            GLError::FramebufferError(ref e) => {
                write!(f, "{:?}", e)
            },
            GLError::Message(ref s) => {
                write!(f, "{}", s)
            }
        }
    }
}

impl error::Error for GLError {
    fn description(&self) -> &str {
        match *self {
            GLError::InvalidEnum => "Invalid enum variant in OpenGL call.",
            GLError::InvalidValue => "Out-of-range value in OpenGL call.",
            GLError::InvalidOperation => "The specified OpenGL operation is not allowed in the current state.",
            GLError::InvalidFramebufferOperation => "OpenGL command tried to read or write to an incomplete framebuffer.",
            GLError::OutOfMemory => "There is not enough memory left to execute the specified OpenGL command.",
            GLError::FramebufferError(ref e) => {
                error::Error::description(e)
            },
            GLError::Message(ref s) => &s
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            GLError::FramebufferError(ref e) => { Some(e) },
            _ => { None }
        }
    }
}

#[derive(Debug)]
pub enum GLFramebufferError {
    IncompleteAttachment,
    IncompleteDimensions,
    IncompleteMissingAttachment,
    Unsupported
}

impl fmt::Display for GLFramebufferError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLFramebufferError::IncompleteAttachment => {
                write!(f, "Incomplete attachment")
            },
            GLFramebufferError::IncompleteDimensions => {
                write!(f, "Incomplete dimensions")
            },
            GLFramebufferError::IncompleteMissingAttachment => {
                write!(f, "Missing attachments")
            },
            GLFramebufferError::Unsupported => {
                write!(f, "Unsupported")
            }
        }
    }
}

impl error::Error for GLFramebufferError {
    fn description(&self) -> &str {
        match *self {
            GLFramebufferError::IncompleteAttachment => "One or more framebuffer attachments are not complete",
            GLFramebufferError::IncompleteDimensions => "Not all images attached to the framebuffer have the same width and height",
            GLFramebufferError::IncompleteMissingAttachment => "The framebuffer has no images attached",
            GLFramebufferError::Unsupported => "The framebuffer contains an unsupported combination of attachments",
        }
    }
}

gl_enum! {
    pub gl_enum DrawingMode {
        Points as POINTS = gl::POINTS,
        LineStrip as LINE_STRIP = gl::LINE_STRIP,
        LineLoop as LINE_LOOP = gl::LINE_LOOP,
        Lines as LINES = gl::LINES,
        TriangleStrip as TRIANGLE_STRIP = gl::TRIANGLE_STRIP,
        TriangleFan as TRIANGLE_FAN = gl::TRIANGLE_FAN,
        Triangles as TRIANGLES = gl::TRIANGLES
    }
}

gl_enum! {
    pub gl_enum DataType {
        Byte as BYTE = gl::BYTE,
        UnsignedByte as UNSIGNED_BYTE = gl::UNSIGNED_BYTE,
        Short as SHORT = gl::SHORT,
        UnsignedShort as UNSIGNED_SHORT = gl::UNSIGNED_SHORT,
        Fixed as FIXED = gl::FIXED,
        Float as FLOAT = gl::FLOAT
    }
}
<commit_msg>Add `From` impl to convert from `GLFramebufferError` to `GLError`<commit_after>use std::fmt;
use std::error;
use gl;

pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}

impl Color {
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
        Color { r: r, g: g, b: b, a: a}
    }
}

#[derive(Clone, Copy)]
pub struct Viewport {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32
}

impl Viewport {
    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
        Viewport {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

bitflags! {
    flags BufferBits: gl::types::GLbitfield {
        const COLOR_BUFFER_BIT = gl::COLOR_BUFFER_BIT,
        const DEPTH_BUFFER_BIT = gl::DEPTH_BUFFER_BIT,
        const STENCIL_BUFFER_BIT = gl::STENCIL_BUFFER_BIT
    }
}

#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    FramebufferError(GLFramebufferError),
    Message(String)
}

impl fmt::Display for GLError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLError::InvalidEnum => {
                write!(f, "Invalid enum")
            },
            GLError::InvalidValue => {
                write!(f, "Invalid value")
            },
            GLError::InvalidOperation => {
                write!(f, "Invalid operation")
            },
            GLError::InvalidFramebufferOperation => {
                write!(f, "Invalid framebuffer operation")
            },
            GLError::OutOfMemory => {
                write!(f, "Out of memory")
            },
            GLError::FramebufferError(ref e) => {
                write!(f, "{:?}", e)
            },
            GLError::Message(ref s) => {
                write!(f, "{}", s)
            }
        }
    }
}

impl error::Error for GLError {
    fn description(&self) -> &str {
        match *self {
            GLError::InvalidEnum => "Invalid enum variant in OpenGL call.",
            GLError::InvalidValue => "Out-of-range value in OpenGL call.",
            GLError::InvalidOperation => "The specified OpenGL operation is not allowed in the current state.",
            GLError::InvalidFramebufferOperation => "OpenGL command tried to read or write to an incomplete framebuffer.",
            GLError::OutOfMemory => "There is not enough memory left to execute the specified OpenGL command.",
            GLError::FramebufferError(ref e) => {
                error::Error::description(e)
            },
            GLError::Message(ref s) => &s
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            GLError::FramebufferError(ref e) => { Some(e) },
            _ => { None }
        }
    }
}

#[derive(Debug)]
pub enum GLFramebufferError {
    IncompleteAttachment,
    IncompleteDimensions,
    IncompleteMissingAttachment,
    Unsupported
}

impl fmt::Display for GLFramebufferError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLFramebufferError::IncompleteAttachment => {
                write!(f, "Incomplete attachment")
            },
            GLFramebufferError::IncompleteDimensions => {
                write!(f, "Incomplete dimensions")
            },
            GLFramebufferError::IncompleteMissingAttachment => {
                write!(f, "Missing attachments")
            },
            GLFramebufferError::Unsupported => {
                write!(f, "Unsupported")
            }
        }
    }
}

impl error::Error for GLFramebufferError {
    fn description(&self) -> &str {
        match *self {
            GLFramebufferError::IncompleteAttachment => "One or more framebuffer attachments are not complete",
            GLFramebufferError::IncompleteDimensions => "Not all images attached to the framebuffer have the same width and height",
            GLFramebufferError::IncompleteMissingAttachment => "The framebuffer has no images attached",
            GLFramebufferError::Unsupported => "The framebuffer contains an unsupported combination of attachments",
        }
    }
}

impl From<GLFramebufferError> for GLError {
    fn from(e: GLFramebufferError) -> GLError {
        GLError::FramebufferError(e)
    }
}

gl_enum! {
    pub gl_enum DrawingMode {
        Points as POINTS = gl::POINTS,
        LineStrip as LINE_STRIP = gl::LINE_STRIP,
        LineLoop as LINE_LOOP = gl::LINE_LOOP,
        Lines as LINES = gl::LINES,
        TriangleStrip as TRIANGLE_STRIP = gl::TRIANGLE_STRIP,
        TriangleFan as TRIANGLE_FAN = gl::TRIANGLE_FAN,
        Triangles as TRIANGLES = gl::TRIANGLES
    }
}

gl_enum! {
    pub gl_enum DataType {
        Byte as BYTE = gl::BYTE,
        UnsignedByte as UNSIGNED_BYTE = gl::UNSIGNED_BYTE,
        Short as SHORT = gl::SHORT,
        UnsignedShort as UNSIGNED_SHORT = gl::UNSIGNED_SHORT,
        Fixed as FIXED = gl::FIXED,
        Float as FLOAT = gl::FLOAT
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use error::*;

#[derive(Debug, PartialEq)]
pub struct Coordinate {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Coordinate {
    fn new(x: f32, y: f32, z: f32) -> Self {
        Coordinate{ x: x, y: y, z: z }
    }
}

#[derive(Debug, PartialEq)]
pub struct Atom {
    pub element: String,
    pub coordinate: Coordinate
}

impl Atom {
    fn new(element: &str, x: f32, y: f32, z: f32) -> Self {
        Atom {
            element: element.to_string(),
            coordinate: Coordinate::new(x,y,z)
        }
    }
}

impl FromStr for Atom {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let splitted: Vec<&str> = s.split_whitespace().collect();
        if splitted.len() != 4 {
            return Err(Error::IllegalState(String::from("")));
        }
        Ok(Atom::new(splitted[0],
                     splitted[1].parse::<f32>()?,
                     splitted[2].parse::<f32>()?,
                     splitted[3].parse::<f32>()?))
    }
}

pub struct Snapshot {
    pub comment: String,
    pub atoms: Vec<Atom>
}

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

    #[test]
    fn test_parse_atom() {
        let success = "C 10.0 11.0 12.0".parse::<Atom>();
        assert!(success.is_ok());
        assert_eq!(
            Atom::new("C", 10.0, 11.0, 12.0),
            success.unwrap());

        let failure = "C 1.0 2.0 a".parse::<Atom>();
        assert!(failure.is_err());
    }
}

<commit_msg>the struct Coordiante derives the impl Clone and Copy<commit_after>use std::str::FromStr;
use error::*;

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Coordinate {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Coordinate {
    fn new(x: f32, y: f32, z: f32) -> Self {
        Coordinate{ x: x, y: y, z: z }
    }
}

#[derive(Debug, PartialEq)]
pub struct Atom {
    pub element: String,
    pub coordinate: Coordinate
}

impl Atom {
    fn new(element: &str, x: f32, y: f32, z: f32) -> Self {
        Atom {
            element: element.to_string(),
            coordinate: Coordinate::new(x,y,z)
        }
    }
}

impl FromStr for Atom {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let splitted: Vec<&str> = s.split_whitespace().collect();
        if splitted.len() != 4 {
            return Err(Error::IllegalState(String::from("")));
        }
        Ok(Atom::new(splitted[0],
                     splitted[1].parse::<f32>()?,
                     splitted[2].parse::<f32>()?,
                     splitted[3].parse::<f32>()?))
    }
}

pub struct Snapshot {
    pub comment: String,
    pub atoms: Vec<Atom>
}

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

    #[test]
    fn test_parse_atom() {
        let success = "C 10.0 11.0 12.0".parse::<Atom>();
        assert!(success.is_ok());
        assert_eq!(
            Atom::new("C", 10.0, 11.0, 12.0),
            success.unwrap());

        let failure = "C 1.0 2.0 a".parse::<Atom>();
        assert!(failure.is_err());
    }
}

<|endoftext|>


<commit_before>use std::convert::{From, Into};
use std::result;
use std::fmt;

use ffi;

pub type PortMidiDeviceId = i32;

/// PortMidi result type.
pub type Result<T> = result::Result<T, Error>;
impl From<ffi::PmError> for Result<()> {
    fn from(err: ffi::PmError) -> Self {
        match err {
            ffi::PmError::PmNoError | ffi::PmError::PmGotData => Ok(()),
            _ => Err(Error::PortMidi(err)),
        }
    }
}

/// PortMidi error type.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
    PortMidi(ffi::PmError),
    Unknown,
    Unimplemented,
    NoDefaultDevice,
    NotAnInputDevice,
    NotAnOutputDevice,
    Invalid,
}
impl From<ffi::PmError> for Error {
    fn from(err: ffi::PmError) -> Self {
        match err {
            err @ _ => Error::PortMidi(err),
        }
    }
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::PortMidi(pm_err) => write!(f, "{}", pm_err),
            err @ _ => write!(f, "{:?}", err),
        }
    }
}

/// Represents a Midi message.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}
impl From<[u8; 3]> for MidiMessage {
    fn from(raw: [u8; 3]) -> Self {
        MidiMessage {
            status: raw[0],
            data1: raw[1],
            data2: raw[2],
        }
    }
}
/// Converts a `PmMessage` to a `MidiMessage.
/// This can be used for `c_int` as well as `i32` because these are only type aliases.
impl From<ffi::PmMessage> for MidiMessage {
    fn from(raw: i32) -> Self {
        MidiMessage {
            status: ((raw & 0x00_FF_00_00) >> 16) as u8,
            data1: ((raw & 0x00_00_FF_00) >> 8) as u8,
            data2: (raw & 0x00_00_00_FF) as u8,
        }
    }
}
impl Into<ffi::PmMessage> for MidiMessage {
    fn into(self) -> i32 {
        (((self.data2 as i32) << 16)) | (((self.data1 as i32) << 8)) | self.status as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message: MidiMessage,
    pub timestamp: ffi::PmTimestamp,
}
impl From<ffi::PmEvent> for MidiEvent {
    fn from(raw: ffi::PmEvent) -> Self {
        MidiEvent {
            message: MidiMessage::from(raw.message),
            timestamp: raw.timestamp,
        }
    }
}
impl Into<ffi::PmEvent> for MidiEvent {
    fn into(self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: MidiMessage::into(self.message),
            timestamp: self.timestamp,
        }
    }
}
<commit_msg>Use a `c_int` for `PortMidiDeviceId`<commit_after>use std::os::raw::c_int;
use std::convert::{From, Into};
use std::result;
use std::fmt;

use ffi;

pub type PortMidiDeviceId = c_int;

/// PortMidi result type.
pub type Result<T> = result::Result<T, Error>;
impl From<ffi::PmError> for Result<()> {
    fn from(err: ffi::PmError) -> Self {
        match err {
            ffi::PmError::PmNoError | ffi::PmError::PmGotData => Ok(()),
            _ => Err(Error::PortMidi(err)),
        }
    }
}

/// PortMidi error type.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
    PortMidi(ffi::PmError),
    Unknown,
    Unimplemented,
    NoDefaultDevice,
    NotAnInputDevice,
    NotAnOutputDevice,
    Invalid,
}
impl From<ffi::PmError> for Error {
    fn from(err: ffi::PmError) -> Self {
        match err {
            err @ _ => Error::PortMidi(err),
        }
    }
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::PortMidi(pm_err) => write!(f, "{}", pm_err),
            err @ _ => write!(f, "{:?}", err),
        }
    }
}

/// Represents a Midi message.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}
impl From<[u8; 3]> for MidiMessage {
    fn from(raw: [u8; 3]) -> Self {
        MidiMessage {
            status: raw[0],
            data1: raw[1],
            data2: raw[2],
        }
    }
}
/// Converts a `PmMessage` to a `MidiMessage.
/// This can be used for `c_int` as well as `i32` because these are only type aliases.
impl From<ffi::PmMessage> for MidiMessage {
    fn from(raw: i32) -> Self {
        MidiMessage {
            status: ((raw & 0x00_FF_00_00) >> 16) as u8,
            data1: ((raw & 0x00_00_FF_00) >> 8) as u8,
            data2: (raw & 0x00_00_00_FF) as u8,
        }
    }
}
impl Into<ffi::PmMessage> for MidiMessage {
    fn into(self) -> i32 {
        (((self.data2 as i32) << 16)) | (((self.data1 as i32) << 8)) | self.status as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message: MidiMessage,
    pub timestamp: ffi::PmTimestamp,
}
impl From<ffi::PmEvent> for MidiEvent {
    fn from(raw: ffi::PmEvent) -> Self {
        MidiEvent {
            message: MidiMessage::from(raw.message),
            timestamp: raw.timestamp,
        }
    }
}
impl Into<ffi::PmEvent> for MidiEvent {
    fn into(self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: MidiMessage::into(self.message),
            timestamp: self.timestamp,
        }
    }
}
<|endoftext|>