<commit_before>//! Roundtrip (write-read) tests for supported LAS versions and attributes.

extern crate chrono;
extern crate las;

use las::{Header, Point, Reader, Writer};
use std::io::Cursor;

pub fn roundtrip(header: Header, point: Point, should_succeed: bool) {
    let mut cursor = Cursor::new(Vec::new());
    {
        match Writer::new(&mut cursor, header.clone()).and_then(
            |mut writer| {
                writer.write(point.clone())
            },
        ) {
            Ok(()) => if !should_succeed {
                panic!("Expected write to fail, but it succeeded");
            },
            Err(err) => {
                if should_succeed {
                    panic!("Write error: {}", err)
                } else {
                    return;
                }
            }
        }
    }
    cursor.set_position(0);
    let mut reader = Reader::new(cursor).unwrap();
    let other = reader
        .read()
        .expect("Error when reading the ont point")
        .unwrap();
    assert_eq!(point, other);
    assert_eq!(
        None,
        reader.read().expect("Error when reading past last point")
    );

    let other = reader.header();
    assert_eq!(header.file_source_id, other.file_source_id);
    assert_eq!(header.gps_time_type, other.gps_time_type);
    assert_eq!(
        header.has_synthetic_return_numbers,
        other.has_synthetic_return_numbers
    );
    assert_eq!(header.guid, other.guid);
    assert_eq!(header.version, other.version);
    assert_eq!(header.system_identifier, other.system_identifier);
    assert_eq!(header.generating_software, other.generating_software);
    assert_eq!(header.date, other.date);
    assert_eq!(header.padding, other.padding);
    assert_eq!(header.point_format, other.point_format);
    assert_eq!(header.transforms, other.transforms);
    assert_eq!(point.x, other.bounds.min.x);
    assert_eq!(point.x, other.bounds.max.x);
    assert_eq!(point.y, other.bounds.min.y);
    assert_eq!(point.y, other.bounds.max.y);
    assert_eq!(point.z, other.bounds.min.z);
    assert_eq!(point.z, other.bounds.max.z);
    assert_eq!(1, other.number_of_points);
    if point.return_number > 0 {
        assert_eq!(1, other.number_of_points_by_return[&point.return_number]);
    }
    assert_eq!(header.vlrs, other.vlrs);
}

macro_rules! roundtrip_point {
    ($name:ident, $modify_point:expr) => {
        roundtrip_point!($name, $modify_point, 0);
    };
    ($name:ident, $modify_point:expr, $min_version_minor:expr) => {
        roundtrip_point!($name, $modify_point, $min_version_minor, |_f| {});
    };
    ($name:ident, $modify_point:expr, $min_version_minor:expr, $modify_point_format:expr) => {
        #[test]
        fn $name() {
            use las::{Header, Point, Version};
            use las::point::Format;

            let version = super::version();
            let should_succeed = version >= Version::new(1, $min_version_minor);
            let mut point_format = Format::default();
            $modify_point_format(&mut point_format);
            let mut point = Point::default();
            $modify_point(&mut point);
            let header = Header { version: version, point_format: point_format, ..Default::default() };
            ::roundtrip(header, point, should_succeed);
        }
    };
}

macro_rules! roundtrip_header {
    ($name:ident, $modify_header:expr) => {
        roundtrip_header!($name, $modify_header, 0);
    };
    ($name:ident, $modify_header:expr, $min_version_minor:expr) => {
        #[test]
        fn $name() {
            use las::{Version, Header, Point};

            let version = super::version();
            let should_succeed = version >= Version::new(1, $min_version_minor);
            let mut header = Header { version: version, ..Default::default() };
            $modify_header(&mut header);
            ::roundtrip(header, Point::default(), should_succeed);
        }
    };
}

macro_rules! version {
    ($name:ident, $major:expr, $minor:expr) => {
        mod $name {
            use las::Version;

            fn version() -> Version {
                Version::new($major, $minor)
            }

            mod point {
                use las::Color;
                use las::point::{Classification, ScanDirection};

                roundtrip_point!(xyz, |p: &mut Point| { p.x = 1.; p.y = 2.; p.z = 3.; });
                roundtrip_point!(intensity, |p: &mut Point| p.intensity = 42);
                roundtrip_point!(return_number, |p: &mut Point| p.return_number = 2);
                roundtrip_point!(number_of_returns, |p: &mut Point| p.number_of_returns = 2);
                roundtrip_point!(scan_direction, |p: &mut Point| p.scan_direction = ScanDirection::LeftToRight);
                roundtrip_point!(is_edge_of_flight_line, |p: &mut Point| p.is_edge_of_flight_line = true);
                roundtrip_point!(classification, |p: &mut Point| p.classification = Classification::Ground);
                roundtrip_point!(is_synthetic, |p: &mut Point| p.is_synthetic = true);
                roundtrip_point!(is_key_point, |p: &mut Point| p.is_key_point = true);
                roundtrip_point!(is_withheld, |p: &mut Point| p.is_withheld = true);
                roundtrip_point!(is_overlap, |p: &mut Point| {
                    p.classification = Classification::Unclassified;
                    p.is_overlap = true;
                });
                roundtrip_point!(scanner_channel, |p: &mut Point| {
                    p.scanner_channel = 1;
                    p.gps_time = Some(42.);
                }, 4, |f: &mut Format| f.extend());
                roundtrip_point!(scan_angle_rank, |p: &mut Point| p.scan_angle = 3.);
                roundtrip_point!(user_data, |p: &mut Point| p.user_data = 42);
                roundtrip_point!(point_source_id, |p: &mut Point| p.point_source_id = 42);
                roundtrip_point!(gps_time, |p: &mut Point| p.gps_time = Some(42.), 0, |f: &mut Format| f.has_gps_time = true);
                roundtrip_point!(color, |p: &mut Point| p.color = Some(Color { red: 1, green: 2, blue: 3 }), 2, |f: &mut Format| f.has_color = true);
                // TODO waveform
                roundtrip_point!(nir, |p: &mut Point| {
                    p.color = Some(Color { red: 1, green: 2, blue: 3});
                    p.nir = Some(42);
                    p.gps_time = Some(42.);
                }, 4, |f: &mut Format| {
                    f.extend();
                    f.has_color = true;
                    f.has_nir = true;
                });
                roundtrip_point!(extra_bytes, |p: &mut Point| p.extra_bytes = vec![42], 0, |f: &mut Format| f.extra_bytes = 1);
            }

            mod header {
                use chrono::{Utc, TimeZone};
                use las::GpsTimeType;

                roundtrip_header!(file_source_id, |h: &mut Header| h.file_source_id = 42, 1);
                roundtrip_header!(gps_time_type, |h: &mut Header| h.gps_time_type = GpsTimeType::Standard, 2);
                roundtrip_header!(guid, |h: &mut Header| h.guid = [42; 16]);
                roundtrip_header!(system_identifier, |h: &mut Header| h.system_identifier = "roundtrip test".to_string());
                roundtrip_header!(generating_software, |h: &mut Header| h.generating_software = "roundtrip test".to_string());
                roundtrip_header!(date, |h: &mut Header| h.date = Some(Utc.ymd(2017, 10, 30)));
                roundtrip_header!(padding, |h: &mut Header| h.padding = b"You probably shouldn't do this".to_vec());
                roundtrip_header!(vlr_padding, |h: &mut Header| h.vlr_padding = b"You probably shouldn't do this either".to_vec());
                roundtrip_header!(transforms, |h: &mut Header| {
                    use las::{Transform, Vector};

                    let transform = Transform { scale: 0.1, offset: -1. };
                    h.transforms = Vector {
                        x: transform,
                        y: transform,
                        z: transform,
                    };
                });
                roundtrip_header!(vlrs, |h: &mut Header| h.vlrs = vec![Default::default()]);
                roundtrip_header!(evlrs, |h: &mut Header| {
                    use std::u16;
                    use las::Vlr;

                    let mut vlr = Vlr::default();
                    vlr.is_extended = true;
                    vlr.data = vec![42; u16::MAX as usize + 1];
                    h.vlrs = vec![vlr];
                }, 4);
                roundtrip_header!(has_synthetic_return_numbers, |h: &mut Header| h.has_synthetic_return_numbers = true, 3);
            }
        }
    }
}

version!(las_1_0, 1, 0);
version!(las_1_1, 1, 1);
version!(las_1_2, 1, 2);
version!(las_1_3, 1, 3);
version!(las_1_4, 1, 4);
<commit_msg>Re-indent roundtrip macro<commit_after>//! Roundtrip (write-read) tests for supported LAS versions and attributes.

extern crate chrono;
extern crate las;

use las::{Header, Point, Reader, Writer};
use std::io::Cursor;

pub fn roundtrip(header: Header, point: Point, should_succeed: bool) {
    let mut cursor = Cursor::new(Vec::new());
    {
        match Writer::new(&mut cursor, header.clone()).and_then(
            |mut writer| {
                writer.write(point.clone())
            },
        ) {
            Ok(()) => if !should_succeed {
                panic!("Expected write to fail, but it succeeded");
            },
            Err(err) => {
                if should_succeed {
                    panic!("Write error: {}", err)
                } else {
                    return;
                }
            }
        }
    }
    cursor.set_position(0);
    let mut reader = Reader::new(cursor).unwrap();
    let other = reader
        .read()
        .expect("Error when reading the ont point")
        .unwrap();
    assert_eq!(point, other);
    assert_eq!(
        None,
        reader.read().expect("Error when reading past last point")
    );

    let other = reader.header();
    assert_eq!(header.file_source_id, other.file_source_id);
    assert_eq!(header.gps_time_type, other.gps_time_type);
    assert_eq!(
        header.has_synthetic_return_numbers,
        other.has_synthetic_return_numbers
    );
    assert_eq!(header.guid, other.guid);
    assert_eq!(header.version, other.version);
    assert_eq!(header.system_identifier, other.system_identifier);
    assert_eq!(header.generating_software, other.generating_software);
    assert_eq!(header.date, other.date);
    assert_eq!(header.padding, other.padding);
    assert_eq!(header.point_format, other.point_format);
    assert_eq!(header.transforms, other.transforms);
    assert_eq!(point.x, other.bounds.min.x);
    assert_eq!(point.x, other.bounds.max.x);
    assert_eq!(point.y, other.bounds.min.y);
    assert_eq!(point.y, other.bounds.max.y);
    assert_eq!(point.z, other.bounds.min.z);
    assert_eq!(point.z, other.bounds.max.z);
    assert_eq!(1, other.number_of_points);
    if point.return_number > 0 {
        assert_eq!(1, other.number_of_points_by_return[&point.return_number]);
    }
    assert_eq!(header.vlrs, other.vlrs);
}

macro_rules! roundtrip_point {
    ($name:ident, $modify_point:expr) => {
        roundtrip_point!($name, $modify_point, 0);
    };
    ($name:ident, $modify_point:expr, $min_version_minor:expr) => {
        roundtrip_point!($name, $modify_point, $min_version_minor, |_f| {});
    };
    ($name:ident, $modify_point:expr, $min_version_minor:expr, $modify_point_format:expr) => {
        #[test]
        fn $name() {
            use las::{Header, Point, Version};
            use las::point::Format;

            let version = super::version();
            let should_succeed = version >= Version::new(1, $min_version_minor);
            let mut point_format = Format::default();
            $modify_point_format(&mut point_format);
            let mut point = Point::default();
            $modify_point(&mut point);
            let header = Header { version: version, point_format: point_format, ..Default::default() };
            ::roundtrip(header, point, should_succeed);
        }
    };
}

macro_rules! roundtrip_header {
    ($name:ident, $modify_header:expr) => {
        roundtrip_header!($name, $modify_header, 0);
    };
    ($name:ident, $modify_header:expr, $min_version_minor:expr) => {
        #[test]
        fn $name() {
            use las::{Version, Header, Point};

            let version = super::version();
            let should_succeed = version >= Version::new(1, $min_version_minor);
            let mut header = Header { version: version, ..Default::default() };
            $modify_header(&mut header);
            ::roundtrip(header, Point::default(), should_succeed);
        }
    };
}

macro_rules! version { ($name:ident, $major:expr, $minor:expr) => {
mod $name {
    use las::Version;

    fn version() -> Version {
        Version::new($major, $minor)
    }

    mod point {
        use las::Color;
        use las::point::{Classification, ScanDirection};

        roundtrip_point!(xyz, |p: &mut Point| { p.x = 1.; p.y = 2.; p.z = 3.; });
        roundtrip_point!(intensity, |p: &mut Point| p.intensity = 42);
        roundtrip_point!(return_number, |p: &mut Point| p.return_number = 2);
        roundtrip_point!(number_of_returns, |p: &mut Point| p.number_of_returns = 2);
        roundtrip_point!(scan_direction, |p: &mut Point| p.scan_direction = ScanDirection::LeftToRight);
        roundtrip_point!(is_edge_of_flight_line, |p: &mut Point| p.is_edge_of_flight_line = true);
        roundtrip_point!(classification, |p: &mut Point| p.classification = Classification::Ground);
        roundtrip_point!(is_synthetic, |p: &mut Point| p.is_synthetic = true);
        roundtrip_point!(is_key_point, |p: &mut Point| p.is_key_point = true);
        roundtrip_point!(is_withheld, |p: &mut Point| p.is_withheld = true);
        roundtrip_point!(is_overlap, |p: &mut Point| {
            p.classification = Classification::Unclassified;
            p.is_overlap = true;
        });
        roundtrip_point!(scanner_channel, |p: &mut Point| {
            p.scanner_channel = 1;
            p.gps_time = Some(42.);
        }, 4, |f: &mut Format| f.extend());
        roundtrip_point!(scan_angle_rank, |p: &mut Point| p.scan_angle = 3.);
        roundtrip_point!(user_data, |p: &mut Point| p.user_data = 42);
        roundtrip_point!(point_source_id, |p: &mut Point| p.point_source_id = 42);
        roundtrip_point!(gps_time, |p: &mut Point| p.gps_time = Some(42.), 0, |f: &mut Format| f.has_gps_time = true);
        roundtrip_point!(color, |p: &mut Point| p.color = Some(Color { red: 1, green: 2, blue: 3 }), 2, |f: &mut Format| f.has_color = true);
        // TODO waveform
        roundtrip_point!(nir, |p: &mut Point| {
            p.color = Some(Color { red: 1, green: 2, blue: 3});
            p.nir = Some(42);
            p.gps_time = Some(42.);
        }, 4, |f: &mut Format| {
            f.extend();
            f.has_color = true;
            f.has_nir = true;
        });
        roundtrip_point!(extra_bytes, |p: &mut Point| p.extra_bytes = vec![42], 0, |f: &mut Format| f.extra_bytes = 1);
    }

    mod header {
        use chrono::{Utc, TimeZone};
        use las::GpsTimeType;

        roundtrip_header!(file_source_id, |h: &mut Header| h.file_source_id = 42, 1);
        roundtrip_header!(gps_time_type, |h: &mut Header| h.gps_time_type = GpsTimeType::Standard, 2);
        roundtrip_header!(guid, |h: &mut Header| h.guid = [42; 16]);
        roundtrip_header!(system_identifier, |h: &mut Header| h.system_identifier = "roundtrip test".to_string());
        roundtrip_header!(generating_software, |h: &mut Header| h.generating_software = "roundtrip test".to_string());
        roundtrip_header!(date, |h: &mut Header| h.date = Some(Utc.ymd(2017, 10, 30)));
        roundtrip_header!(padding, |h: &mut Header| h.padding = b"You probably shouldn't do this".to_vec());
        roundtrip_header!(vlr_padding, |h: &mut Header| h.vlr_padding = b"You probably shouldn't do this either".to_vec());
        roundtrip_header!(transforms, |h: &mut Header| {
            use las::{Transform, Vector};

            let transform = Transform { scale: 0.1, offset: -1. };
            h.transforms = Vector {
                x: transform,
                y: transform,
                z: transform,
            };
        });
        roundtrip_header!(vlrs, |h: &mut Header| h.vlrs = vec![Default::default()]);
        roundtrip_header!(evlrs, |h: &mut Header| {
            use std::u16;
            use las::Vlr;

            let mut vlr = Vlr::default();
            vlr.is_extended = true;
            vlr.data = vec![42; u16::MAX as usize + 1];
            h.vlrs = vec![vlr];
        }, 4);
        roundtrip_header!(has_synthetic_return_numbers, |h: &mut Header| h.has_synthetic_return_numbers = true, 3);
    }
}
}}

version!(las_1_0, 1, 0);
version!(las_1_1, 1, 1);
version!(las_1_2, 1, 2);
version!(las_1_3, 1, 3);
version!(las_1_4, 1, 4);
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::mem;
use std::slice;
use libc::c_void;
use std::ffi::CString;

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi;
use ::enums::{
    Content,
    Status,
    SurfaceType,
};

#[derive(Debug)]
pub struct Surface(*mut ffi::cairo_surface_t, bool);

impl Surface {
    pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        ffi::cairo_surface_reference(ptr);
        Surface(ptr, false)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, true)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, false)
    }

    pub fn to_raw_none(&self) -> *mut ffi::cairo_surface_t {
        self.0
    }

    pub fn create_similar(&self, content: Content, width: i32, height: i32) -> Surface {
        unsafe {
            Self::from_raw_full(ffi::cairo_surface_create_similar(self.0,
                                                                  content.into(),
                                                                  width,
                                                                  height))
        }
    }

    pub fn get_mime_data(&self, mime_type: &str) -> Option<Vec<u8>> {
        let mut data_ptr: *mut u8 = std::ptr::null_mut();
        let mut length = 0u64;
        unsafe {
            let mime_type = CString::new(mime_type).unwrap();
            ffi::cairo_surface_get_mime_data(
                self.to_raw_none(),
                mime_type.as_ptr(),
                &mut data_ptr,
                &mut length,
            );
            if !data_ptr.is_null() && length != 0 {
                Some(slice::from_raw_parts(
                    data_ptr as *const u8,
                    length as usize,
                ).to_vec())
            } else {
                None
            }
        }
    }

    pub fn set_mime_data<T: AsRef<[u8]> + Send + 'static>(
        &self,
        mime_type: &str,
        slice: T) -> Result<(), Status> {
        let b = Box::new(slice);
        let (size, data) = {
            let slice = (*b).as_ref();
            (slice.len(), slice.as_ptr())
        };

        let user_data = Box::into_raw(b);

        let status = unsafe {
            let mime_type = CString::new(mime_type).unwrap();
            ffi::cairo_surface_set_mime_data(self.to_raw_none(),
                mime_type.as_ptr(),
                data,
                size as u64,
                Some(unbox::<T>),
                user_data as *mut _,
            )
        };

        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }

    pub fn supports_mime_type(&self, mime_type: &str) -> bool {
        unsafe {
            let mime_type = CString::new(mime_type).unwrap();
            ffi::cairo_surface_supports_mime_type(self.0, mime_type.as_ptr()).as_bool()
        }
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for Surface {
    type Storage = &'a Surface;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> {
        Stash(self.to_raw_none(), self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_surface_t {
        unsafe {
            ffi::cairo_surface_reference(self.to_raw_none())
        }
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Surface, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type);

impl AsRef<Surface> for Surface {
    fn as_ref(&self) -> &Surface {
        self
    }
}

impl Clone for Surface {
    fn clone(&self) -> Surface {
        unsafe { Self::from_raw_none(self.0) }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_surface_destroy(self.0); }
        }
    }
}

pub trait SurfaceExt {
    fn flush(&self);
    fn finish(&self);
    fn get_type(&self) -> SurfaceType;
    fn status(&self) -> Status;
}

impl<O: AsRef<Surface>> SurfaceExt for O {
    fn flush(&self) {
        unsafe { ffi::cairo_surface_flush(self.as_ref().0); }
    }

    fn finish(&self) {
        unsafe { ffi::cairo_surface_finish(self.as_ref().0); }
    }

    fn get_type(&self) -> SurfaceType {
        unsafe { SurfaceType::from(ffi::cairo_surface_get_type(self.as_ref().0)) }
    }

    fn status(&self) -> Status {
        unsafe { Status::from(ffi::cairo_surface_status(self.as_ref().0)) }
    }
}

pub(crate) trait SurfacePriv {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status>;
}

impl<O: AsRef<Surface>> SurfacePriv for O {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status> {
        let ptr: *mut T = Box::into_raw(data);

        assert_eq!(mem::size_of::<*mut c_void>(), mem::size_of_val(&ptr));

        let status = ffi::cairo_surface_set_user_data(self.as_ref().0, key as *const _ as *mut _,
            ptr as *mut c_void, Some(unbox::<T>));
        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }
}

unsafe extern "C" fn unbox<T>(data: *mut c_void) {
    let data: Box<T> = Box::from_raw(data as *mut T);
    drop(data);
}

#[cfg(test)]
mod tests {
    use Format;
    use ImageSurface;
    use constants::MIME_TYPE_PNG;

    #[test]
    fn mime_data() {
        let surface = ImageSurface::create(Format::ARgb32, 500, 500).unwrap();
        let data = surface.get_mime_data(MIME_TYPE_PNG);
        /* Initially the data for any mime type has to be none */
        assert!(data.is_none());

        assert!(surface.set_mime_data(MIME_TYPE_PNG, &[1u8, 10u8]).is_ok());
        let data = surface.get_mime_data(MIME_TYPE_PNG).unwrap();
        assert_eq!(data, &[1u8, 10u8]);
    }
}
<commit_msg>surface: fix build error on windows<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::mem;
use std::slice;
use libc::{c_ulong, c_void};
use std::ffi::CString;

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi;
use ::enums::{
    Content,
    Status,
    SurfaceType,
};

#[derive(Debug)]
pub struct Surface(*mut ffi::cairo_surface_t, bool);

impl Surface {
    pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        ffi::cairo_surface_reference(ptr);
        Surface(ptr, false)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, true)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, false)
    }

    pub fn to_raw_none(&self) -> *mut ffi::cairo_surface_t {
        self.0
    }

    pub fn create_similar(&self, content: Content, width: i32, height: i32) -> Surface {
        unsafe {
            Self::from_raw_full(ffi::cairo_surface_create_similar(self.0,
                                                                  content.into(),
                                                                  width,
                                                                  height))
        }
    }

    pub fn get_mime_data(&self, mime_type: &str) -> Option<Vec<u8>> {
        let mut data_ptr: *mut u8 = std::ptr::null_mut();
        let mut length: c_ulong = 0;
        unsafe {
            let mime_type = CString::new(mime_type).unwrap();
            ffi::cairo_surface_get_mime_data(
                self.to_raw_none(),
                mime_type.as_ptr(),
                &mut data_ptr,
                &mut length,
            );
            if !data_ptr.is_null() && length != 0 {
                Some(slice::from_raw_parts(
                    data_ptr as *const u8,
                    length as usize,
                ).to_vec())
            } else {
                None
            }
        }
    }

    pub fn set_mime_data<T: AsRef<[u8]> + Send + 'static>(
        &self,
        mime_type: &str,
        slice: T) -> Result<(), Status> {
        let b = Box::new(slice);
        let (size, data) = {
            let slice = (*b).as_ref();
            (slice.len(), slice.as_ptr())
        };

        let user_data = Box::into_raw(b);

        let status = unsafe {
            let mime_type = CString::new(mime_type).unwrap();
            ffi::cairo_surface_set_mime_data(self.to_raw_none(),
                mime_type.as_ptr(),
                data,
                size as c_ulong,
                Some(unbox::<T>),
                user_data as *mut _,
            )
        };

        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }

    pub fn supports_mime_type(&self, mime_type: &str) -> bool {
        unsafe {
            let mime_type = CString::new(mime_type).unwrap();
            ffi::cairo_surface_supports_mime_type(self.0, mime_type.as_ptr()).as_bool()
        }
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for Surface {
    type Storage = &'a Surface;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> {
        Stash(self.to_raw_none(), self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_surface_t {
        unsafe {
            ffi::cairo_surface_reference(self.to_raw_none())
        }
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Surface, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type);

impl AsRef<Surface> for Surface {
    fn as_ref(&self) -> &Surface {
        self
    }
}

impl Clone for Surface {
    fn clone(&self) -> Surface {
        unsafe { Self::from_raw_none(self.0) }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_surface_destroy(self.0); }
        }
    }
}

pub trait SurfaceExt {
    fn flush(&self);
    fn finish(&self);
    fn get_type(&self) -> SurfaceType;
    fn status(&self) -> Status;
}

impl<O: AsRef<Surface>> SurfaceExt for O {
    fn flush(&self) {
        unsafe { ffi::cairo_surface_flush(self.as_ref().0); }
    }

    fn finish(&self) {
        unsafe { ffi::cairo_surface_finish(self.as_ref().0); }
    }

    fn get_type(&self) -> SurfaceType {
        unsafe { SurfaceType::from(ffi::cairo_surface_get_type(self.as_ref().0)) }
    }

    fn status(&self) -> Status {
        unsafe { Status::from(ffi::cairo_surface_status(self.as_ref().0)) }
    }
}

pub(crate) trait SurfacePriv {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status>;
}

impl<O: AsRef<Surface>> SurfacePriv for O {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status> {
        let ptr: *mut T = Box::into_raw(data);

        assert_eq!(mem::size_of::<*mut c_void>(), mem::size_of_val(&ptr));

        let status = ffi::cairo_surface_set_user_data(self.as_ref().0, key as *const _ as *mut _,
            ptr as *mut c_void, Some(unbox::<T>));
        match Status::from(status) {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }
}

unsafe extern "C" fn unbox<T>(data: *mut c_void) {
    let data: Box<T> = Box::from_raw(data as *mut T);
    drop(data);
}

#[cfg(test)]
mod tests {
    use Format;
    use ImageSurface;
    use constants::MIME_TYPE_PNG;

    #[test]
    fn mime_data() {
        let surface = ImageSurface::create(Format::ARgb32, 500, 500).unwrap();
        let data = surface.get_mime_data(MIME_TYPE_PNG);
        /* Initially the data for any mime type has to be none */
        assert!(data.is_none());

        assert!(surface.set_mime_data(MIME_TYPE_PNG, &[1u8, 10u8]).is_ok());
        let data = surface.get_mime_data(MIME_TYPE_PNG).unwrap();
        assert_eq!(data, &[1u8, 10u8]);
    }
}
<|endoftext|>


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

use serde::{Serialize, Deserialize};

#[cfg(feature = "msgpack_serialization")]
use msgpack::{Serializer, Deserializer};
#[cfg(feature = "msgpack_serialization")]
use msgpack::decode::Error as DeserializeError;
#[cfg(feature = "msgpack_serialization")]
use msgpack::encode::Error as SerializeError;

#[cfg(feature = "json_serialization")]
use serde_json;

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

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

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

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

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

#[cfg(feature = "msgpack_serialization")]
impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(Box::new(err))
    }
}

#[cfg(feature = "msgpack_serialization")]
impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(Box::new(err))
    }
}

#[cfg(feature = "json_serialization")]
impl From<serde_json::Error> for TransitError {
    fn from(err: serde_json::Error) -> TransitError {
        TransitError::Error(Box::new(err))
    }
}

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

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

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

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<T, A>(&mut self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let n = {
            let bytes = &mut self.buffer[..];
            let mut buf = ByteCounter::new(bytes);
            try!(serialize(&mut buf, pkt));
            buf.write_count()
        };
        try!(self.socket.send_to(&self.buffer[..n], addr));
        Ok(())
    }

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

fn udp_buffer() -> Box<[u8]> {
    (0..MAX_UDP_SIZE as usize)
        .map(|_x| 0u8)
        .collect::<Vec<u8>>()
        .into_boxed_slice()
}

#[cfg(feature = "msgpack_serialization")]
fn serialize<W, T>(mut buf: W, val: &T) -> Result<(), TransitError> where W: Write, T: Serialize {
    try!(val.serialize(&mut Serializer::new(&mut buf)));
    Ok(())
}

#[cfg(feature = "json_serialization")]
fn serialize<W, T>(mut buf: W, val: &T) -> Result<(), TransitError> where W: Write, T: Serialize {
    try!(serde_json::to_writer(&mut buf, &val));
    Ok(())
}

#[cfg(not(any(feature = "json_serialization", feature = "msgpack_serialization")))]
fn serialize<W, T>(mut _buf: W, _val: &T) -> Result<(), TransitError> where W: Write, T: Serialize {
    panic!("Need either json or msgpack feature")
}

#[cfg(feature = "msgpack_serialization")]
fn deserialize<R, T>(buf: R) -> Result<T, TransitError> where R: Read, T: Deserialize {
    let data = try!(Deserialize::deserialize(&mut Deserializer::new(buf)));
    Ok(data)
}

#[cfg(feature = "json_serialization")]
fn deserialize<R, T>(buf: R) -> Result<T, TransitError> where R: Read, T: Deserialize {
    let data = try!(serde_json::de::from_reader(buf));
    Ok(data)
}

#[cfg(not(any(feature = "json_serialization", feature = "msgpack_serialization")))]
fn deserialize<R, T>(_buf: R) -> Result<T, TransitError> where R: Read, T: Deserialize {
    panic!("Need either json or msgpack feature")
}

struct ByteCounter<W> {
    counter: usize,
    writer: W,
}

impl<W> ByteCounter<W> {
    fn new(writer: W) -> ByteCounter<W> {
        ByteCounter {
            counter: 0,
            writer: writer,
        }
    }

    fn write_count(&self) -> usize {
        self.counter
    }
}

impl<W: Write> Write for ByteCounter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = try!(self.writer.write(buf));
        self.counter += n;
        Ok(n)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.writer.flush()
    }
}

#[cfg(test)]
mod test {
    use test::Bencher;
    use std::thread::{spawn};
    use std::sync::{Arc};
    use std::sync::atomic::{Ordering, AtomicBool};
    use udp::*;

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

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

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

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

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

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

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

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());

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

    #[test]
    fn test_packet_type() {
        let addr1 = "127.0.0.1:62001";
        let addr2 = "127.0.0.1:62002";
        let mut transit1 = Transit::new(addr1).unwrap();
        let mut transit2 = Transit::new(addr2).unwrap();
        let test = Another { data: String::from("Hello") };

        let res = transit1.send_to(&test, addr2);
        assert!(res.is_ok());
        let res: Result<(Test, _), TransitError> = transit2.recv_from();
        assert!(res.is_err());
    }

    // FIXME: rmp-serde does not current support enums, see issue #42
    #[cfg(feature = "json_serialization")]
    #[test]
    fn test_enum() {
        #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
        enum Custom {
            First,
            Second(String),
        }
        let addr1 = "127.0.0.1:50001";
        let addr2 = "127.0.0.1:50002";
        let mut transit1 = Transit::new(addr1).unwrap();
        let mut transit2 = Transit::new(addr2).unwrap();
        let test = Custom::Second(String::from("Hello"));

        let res = transit1.send_to(&test, addr2);
        assert!(res.is_ok());
        let res: Result<(Custom, _), TransitError> = transit2.recv_from();
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[bench]
    fn bench_send_to(b: &mut Bencher) {
        #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
        struct Custom {
            integer: isize,
            string: String,
        }
        let addr1 = "127.0.0.1:50003";
        let addr2 = "127.0.0.1:50004";
        let mut transit1 = Transit::new(addr1).unwrap();

        let stop = Arc::new(AtomicBool::new(false));
        let test = Custom { integer: 123456, string: String::from("Hello world.") };

        let addr2_c = addr2.clone();
        let stop_c = stop.clone();
        let thread = spawn(move || {
            let mut transit2 = Transit::new(addr2_c).unwrap();
            loop {
                if stop_c.load(Ordering::SeqCst) {
                    break
                }
                let res: Result<(Custom, _), TransitError> = transit2.recv_from();
                assert!(res.is_ok());
            }
        });

        b.iter(|| {
            let _r = transit1.send_to(&test, addr2);
        });

        stop.store(true, Ordering::SeqCst);
        thread.join().unwrap();
    }
}
<commit_msg>Use ':0' port in tests and remove test recv'er from benchmark<commit_after>use std::io::{self, Write, Read};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use serde::{Serialize, Deserialize};

#[cfg(feature = "msgpack_serialization")]
use msgpack::{Serializer, Deserializer};
#[cfg(feature = "msgpack_serialization")]
use msgpack::decode::Error as DeserializeError;
#[cfg(feature = "msgpack_serialization")]
use msgpack::encode::Error as SerializeError;

#[cfg(feature = "json_serialization")]
use serde_json;

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

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

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

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

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

#[cfg(feature = "msgpack_serialization")]
impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(Box::new(err))
    }
}

#[cfg(feature = "msgpack_serialization")]
impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(Box::new(err))
    }
}

#[cfg(feature = "json_serialization")]
impl From<serde_json::Error> for TransitError {
    fn from(err: serde_json::Error) -> TransitError {
        TransitError::Error(Box::new(err))
    }
}

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

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

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

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<T, A>(&mut self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let n = {
            let bytes = &mut self.buffer[..];
            let mut buf = ByteCounter::new(bytes);
            try!(serialize(&mut buf, pkt));
            buf.write_count()
        };
        try!(self.socket.send_to(&self.buffer[..n], addr));
        Ok(())
    }

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

fn udp_buffer() -> Box<[u8]> {
    (0..MAX_UDP_SIZE as usize)
        .map(|_x| 0u8)
        .collect::<Vec<u8>>()
        .into_boxed_slice()
}

#[cfg(feature = "msgpack_serialization")]
fn serialize<W, T>(mut buf: W, val: &T) -> Result<(), TransitError> where W: Write, T: Serialize {
    try!(val.serialize(&mut Serializer::new(&mut buf)));
    Ok(())
}

#[cfg(feature = "json_serialization")]
fn serialize<W, T>(mut buf: W, val: &T) -> Result<(), TransitError> where W: Write, T: Serialize {
    try!(serde_json::to_writer(&mut buf, &val));
    Ok(())
}

#[cfg(not(any(feature = "json_serialization", feature = "msgpack_serialization")))]
fn serialize<W, T>(mut _buf: W, _val: &T) -> Result<(), TransitError> where W: Write, T: Serialize {
    panic!("Need either json or msgpack feature")
}

#[cfg(feature = "msgpack_serialization")]
fn deserialize<R, T>(buf: R) -> Result<T, TransitError> where R: Read, T: Deserialize {
    let data = try!(Deserialize::deserialize(&mut Deserializer::new(buf)));
    Ok(data)
}

#[cfg(feature = "json_serialization")]
fn deserialize<R, T>(buf: R) -> Result<T, TransitError> where R: Read, T: Deserialize {
    let data = try!(serde_json::de::from_reader(buf));
    Ok(data)
}

#[cfg(not(any(feature = "json_serialization", feature = "msgpack_serialization")))]
fn deserialize<R, T>(_buf: R) -> Result<T, TransitError> where R: Read, T: Deserialize {
    panic!("Need either json or msgpack feature")
}

struct ByteCounter<W> {
    counter: usize,
    writer: W,
}

impl<W> ByteCounter<W> {
    fn new(writer: W) -> ByteCounter<W> {
        ByteCounter {
            counter: 0,
            writer: writer,
        }
    }

    fn write_count(&self) -> usize {
        self.counter
    }
}

impl<W: Write> Write for ByteCounter<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = try!(self.writer.write(buf));
        self.counter += n;
        Ok(n)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.writer.flush()
    }
}

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

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

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

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

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

    #[test]
    fn test_send_recv_string() {
        let mut transit1 = Transit::new("127.0.0.1:0").unwrap();
        let mut transit2 = Transit::new("127.0.0.1:0").unwrap();
        let test = String::from("hello");

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

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

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());

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

    #[test]
    fn test_packet_type() {
        let addr1 = "127.0.0.1:0";
        let addr2 = "127.0.0.1:0";
        let mut transit1 = Transit::new(addr1).unwrap();
        let mut transit2 = Transit::new(addr2).unwrap();
        let test = Another { data: String::from("Hello") };

        let res = transit1.send_to(&test, transit2.local_addr().unwrap());
        assert!(res.is_ok());
        let res: Result<(Test, _), TransitError> = transit2.recv_from();
        assert!(res.is_err());
    }

    // FIXME: rmp-serde does not current support enums, see issue #42
    #[cfg(feature = "json_serialization")]
    #[test]
    fn test_enum() {
        #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
        enum Custom {
            First,
            Second(String),
        }
        let addr1 = "127.0.0.1:0";
        let addr2 = "127.0.0.1:0";
        let mut transit1 = Transit::new(addr1).unwrap();
        let mut transit2 = Transit::new(addr2).unwrap();
        let test = Custom::Second(String::from("Hello"));

        let res = transit1.send_to(&test, transit2.local_addr().unwrap());
        assert!(res.is_ok());
        let res: Result<(Custom, _), TransitError> = transit2.recv_from();
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[bench]
    fn bench_send_to(b: &mut Bencher) {
        #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
        struct Custom {
            integer: isize,
            string: String,
        }
        let mut transit1 = Transit::new("127.0.0.1:0").unwrap();

        let test = Custom { integer: 123456, string: String::from("Hello world.") };

        b.iter(|| {
            let _r = transit1.send_to(&test, "127.0.0.1:60000");
        });
    }
}
<|endoftext|>


<commit_before>// xfail-test
// xfail-fast
#[legacy_modes];

fn impure(_i: int) {}

// check that unchecked alone does not override borrowck:
fn foo(v: &const Option<int>) {
    match *v {
      Some(ref i) => {
        //~^ ERROR illegal borrow unless pure
        unsafe {
            impure(*i); //~ NOTE impure due to access to impure function
        }
      }
      None => {
      }
    }
}

fn bar(v: &const Option<int>) {
    match *v {
      Some(ref i) => {
        unsafe {
            impure(*i);
        }
      }
      None => {
      }
    }
}

fn main() {
}
<commit_msg>Remove test that tested behavior of unchecked blocks<commit_after><|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate aster;
extern crate syntax;

use syntax::abi::Abi;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Spanned, respan};
use syntax::parse::token;
use syntax::ptr::P;

use aster::AstBuilder;
use aster::ident::ToIdent;

#[test]
fn test_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics().build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_generic_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .generics()
            .lifetime("'a").build()
            .lifetime("'b").bound("'a").build()
            .ty_param("T").build()
            .build()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics()
                    .lifetime("'a").build()
                    .lifetime("'b").bound("'a").build()
                    .ty_param("T").build()
                    .build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct").build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def().build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct")
        .field("x").ty().isize()
        .field("y").ty().isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def()
                    .field("x").ty().isize()
                    .field("y").ty().isize()
                    .build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_tuple_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().tuple_struct("Struct")
        .ty().isize()
        .ty().isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                P(ast::StructDef {
                    fields: vec![
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                    ],
                    ctor_id: Some(ast::DUMMY_NODE_ID),
                }),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum").build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum")
        .id("A")
        .tuple("B").build()
        .tuple("C")
            .ty().isize()
            .build()
        .tuple("D")
            .ty().isize()
            .ty().isize()
            .build()
        .struct_("E")
            .field("a").ty().isize()
            .build()
        .struct_("F")
            .field("a").ty().isize()
            .field("b").ty().isize()
            .build()
        .build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![
                        builder.variant("A").tuple().build(),
                        builder.variant("B").tuple().build(),
                        builder.variant("C").tuple()
                            .ty().isize()
                            .build(),
                        builder.variant("D").tuple()
                            .ty().isize()
                            .ty().isize()
                            .build(),
                        builder.variant("E").struct_()
                            .field("a").ty().isize()
                            .build(),
                        builder.variant("F").struct_()
                            .field("a").ty().isize()
                            .field("b").ty().isize()
                            .build(),
                    ],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_use() {
    fn check(item: P<ast::Item>, view_path: ast::ViewPath_) {
        assert_eq!(
            item,
            P(ast::Item {
                ident: token::special_idents::invalid,
                attrs: vec![],
                id: ast::DUMMY_NODE_ID,
                node: ast::ItemUse(
                    P(respan(DUMMY_SP, view_path))
                ),
                vis: ast::Inherited,
                span: DUMMY_SP,
            })
        );
    }

    let builder = AstBuilder::new();

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .build();

    check(
        item,
        ast::ViewPathSimple(
            "Vec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .as_("MyVec");

    check(
        item,
        ast::ViewPathSimple(
            "MyVec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .glob();

    check(
        item,
        ast::ViewPathGlob(
            builder.path().ids(&["std", "vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![],
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .self_()
        .id("Vec")
        .id("IntoIter")
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![
                respan(DUMMY_SP, ast::PathListMod {
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "Vec".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "IntoIter".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
            ],
        )
    );
}
<commit_msg>Add a test for item attributes<commit_after>#![feature(rustc_private)]

extern crate aster;
extern crate syntax;

use syntax::abi::Abi;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Spanned, respan};
use syntax::parse::token;
use syntax::ptr::P;

use aster::AstBuilder;
use aster::ident::ToIdent;

#[test]
fn test_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics().build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_generic_fn() {
    let builder = AstBuilder::new();

    let block = builder.block()
        .stmt().let_id("x").isize(1)
        .stmt().let_id("y").isize(2)
        .expr().add().id("x").id("y");

    let fn_ = builder.item().fn_("foo")
        .return_().isize()
        .generics()
            .lifetime("'a").build()
            .lifetime("'b").bound("'a").build()
            .ty_param("T").build()
            .build()
        .build(block.clone());

    assert_eq!(
        fn_,
        P(ast::Item {
            ident: builder.id("foo"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemFn(
                builder.fn_decl().return_().isize(),
                ast::Unsafety::Normal,
                Abi::Rust,
                builder.generics()
                    .lifetime("'a").build()
                    .lifetime("'b").bound("'a").build()
                    .ty_param("T").build()
                    .build(),
                block
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct").build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def().build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().struct_("Struct")
        .field("x").ty().isize()
        .field("y").ty().isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def()
                    .field("x").ty().isize()
                    .field("y").ty().isize()
                    .build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_tuple_struct() {
    let builder = AstBuilder::new();
    let struct_ = builder.item().tuple_struct("Struct")
        .ty().isize()
        .ty().isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                P(ast::StructDef {
                    fields: vec![
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                        Spanned {
                            span: DUMMY_SP,
                            node: ast::StructField_ {
                                kind: ast::UnnamedField(
                                    ast::Inherited,
                                ),
                                id: ast::DUMMY_NODE_ID,
                                ty: builder.ty().isize(),
                                attrs: vec![],
                            },
                        },
                    ],
                    ctor_id: Some(ast::DUMMY_NODE_ID),
                }),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_empty_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum").build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_enum() {
    let builder = AstBuilder::new();
    let enum_= builder.item().enum_("Enum")
        .id("A")
        .tuple("B").build()
        .tuple("C")
            .ty().isize()
            .build()
        .tuple("D")
            .ty().isize()
            .ty().isize()
            .build()
        .struct_("E")
            .field("a").ty().isize()
            .build()
        .struct_("F")
            .field("a").ty().isize()
            .field("b").ty().isize()
            .build()
        .build();

    assert_eq!(
        enum_,
        P(ast::Item {
            ident: builder.id("Enum"),
            attrs: vec![],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemEnum(
                ast::EnumDef {
                    variants: vec![
                        builder.variant("A").tuple().build(),
                        builder.variant("B").tuple().build(),
                        builder.variant("C").tuple()
                            .ty().isize()
                            .build(),
                        builder.variant("D").tuple()
                            .ty().isize()
                            .ty().isize()
                            .build(),
                        builder.variant("E").struct_()
                            .field("a").ty().isize()
                            .build(),
                        builder.variant("F").struct_()
                            .field("a").ty().isize()
                            .field("b").ty().isize()
                            .build(),
                    ],
                },
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}

#[test]
fn test_use() {
    fn check(item: P<ast::Item>, view_path: ast::ViewPath_) {
        assert_eq!(
            item,
            P(ast::Item {
                ident: token::special_idents::invalid,
                attrs: vec![],
                id: ast::DUMMY_NODE_ID,
                node: ast::ItemUse(
                    P(respan(DUMMY_SP, view_path))
                ),
                vis: ast::Inherited,
                span: DUMMY_SP,
            })
        );
    }

    let builder = AstBuilder::new();

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .build();

    check(
        item,
        ast::ViewPathSimple(
            "Vec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec", "Vec"]).build()
        .as_("MyVec");

    check(
        item,
        ast::ViewPathSimple(
            "MyVec".to_ident(),
            builder.path().ids(&["std", "vec", "Vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .glob();

    check(
        item,
        ast::ViewPathGlob(
            builder.path().ids(&["std", "vec"]).build()
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![],
        )
    );

    let item = builder.item().use_()
        .ids(&["std", "vec"]).build()
        .list()
        .self_()
        .id("Vec")
        .id("IntoIter")
        .build();

    check(
        item,
        ast::ViewPathList(
            builder.path().ids(&["std", "vec"]).build(),
            vec![
                respan(DUMMY_SP, ast::PathListMod {
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "Vec".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
                respan(DUMMY_SP, ast::PathListIdent {
                    name: "IntoIter".to_ident(),
                    id: ast::DUMMY_NODE_ID,
                }),
            ],
        )
    );
}

#[test]
fn test_attr() {
    let builder = AstBuilder::new();
    let struct_ = builder.item()
        .attr().doc("/// doc string")
        .struct_("Struct")
        .field("x").ty().isize()
        .field("y").ty().isize()
        .build();

    assert_eq!(
        struct_,
        P(ast::Item {
            ident: builder.id("Struct"),
            attrs: vec![
                respan(
                    DUMMY_SP,
                    ast::Attribute_ {
                        id: ast::AttrId(0),
                        style: ast::AttrOuter,
                        value: P(respan(
                            DUMMY_SP,
                            ast::MetaNameValue(
                                builder.interned_string("doc"),
                                (*builder.lit().str("/// doc string")).clone(),
                            ),
                        )),
                        is_sugared_doc: true,
                    }
                ),
            ],
            id: ast::DUMMY_NODE_ID,
            node: ast::ItemStruct(
                builder.struct_def()
                    .field("x").ty().isize()
                    .field("y").ty().isize()
                    .build(),
                builder.generics().build(),
            ),
            vis: ast::Inherited,
            span: DUMMY_SP,
        })
    );
}
<|endoftext|>


<commit_before>extern crate lua;
extern crate libc;

use lua::ffi::lua_State;
use lua::{State, Function};
use libc::c_int;

struct VecWrapper {
  data: Vec<i64>
}

impl VecWrapper {
  fn new() -> VecWrapper {
    VecWrapper {
      data: Vec::new()
    }
  }

  /// Constructs a new VecWrapper and pushes it onto the Lua stack.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_new(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    // construct new userdata in lua space and initialize it
    let v: *mut VecWrapper = state.new_userdata_typed();
    std::ptr::write(v, VecWrapper::new());
    // set the userdata's metatable so we can call methods on it
    state.set_metatable_from_registry("VecWrapper");
    // return the userdata on top of the stack
    1
  }

  /// Returns the value in the underlying Vec at index `i`. If the index is out
  /// of bounds, this function returns nil instead.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_get(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    let i = state.check_integer(2) as usize;
    // push integer if index is not out of bounds, otherwise nil
    match (*v).data.get(i) {
      Some(value) => state.push_integer(*value),
      None        => state.push_nil()
    };
    1
  }

  /// Pushes a value into the underlying Vec.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_push(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    let i = state.check_integer(2);
    (*v).data.push(i);
    1
  }

  /// Returns the length of the underlying Vec.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_len(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    state.push_integer((*v).data.len() as i64);
    1
  }

  /// Garbage collects a VecWrapper.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_gc(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    std::ptr::drop_in_place(v);
    0
  }
}

const VECWRAPPER_LIB: [(&'static str, Function); 4] = [
    ("new",  Some(VecWrapper::lua_new)),
    ("get",  Some(VecWrapper::lua_get)),
    ("push", Some(VecWrapper::lua_push)),
    ("len",  Some(VecWrapper::lua_len))
];

fn main() {
    let mut state = lua::State::new();

    state.open_libs();

    // make a VecWrapper table globally available to the lua state and register
    // our functions there:
    state.new_table();
    state.set_fns(&VECWRAPPER_LIB, 0);
    // copy reference to VecWrapper table so we can keep the original reference
    // on the stack for later
    state.push_value(-1);
    state.set_global("VecWrapper");

    // create a metatable for VecWrapper in the lua registry that refers to the
    // global VecWrapper table:
    state.new_metatable("VecWrapper");
    // copy reference to VecWrapper table
    state.push_value(-2);
    // VecWrappermetatable.__index = VecWrapper
    state.set_field(-2, "__index");
    // VecWrappermetatable.__gc = lua_gc
    state.push_fn(Some(VecWrapper::lua_gc));
    state.set_field(-2, "__gc");

    // pop metatable and VecWrapper table from the stack
    state.pop(2);

    // try it out:
    state.do_string("local v = VecWrapper.new()
                     v:push(12)
                     v:push(34)
                     -- should print 2
                     print('length of vec is', v:len())
                     -- should print 12 34 nil
                     print(v:get(0), v:get(1), v:get(2))");
}
<commit_msg>Add missing license text<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate lua;
extern crate libc;

use lua::ffi::lua_State;
use lua::{State, Function};
use libc::c_int;

struct VecWrapper {
  data: Vec<i64>
}

impl VecWrapper {
  fn new() -> VecWrapper {
    VecWrapper {
      data: Vec::new()
    }
  }

  /// Constructs a new VecWrapper and pushes it onto the Lua stack.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_new(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    // construct new userdata in lua space and initialize it
    let v: *mut VecWrapper = state.new_userdata_typed();
    std::ptr::write(v, VecWrapper::new());
    // set the userdata's metatable so we can call methods on it
    state.set_metatable_from_registry("VecWrapper");
    // return the userdata on top of the stack
    1
  }

  /// Returns the value in the underlying Vec at index `i`. If the index is out
  /// of bounds, this function returns nil instead.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_get(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    let i = state.check_integer(2) as usize;
    // push integer if index is not out of bounds, otherwise nil
    match (*v).data.get(i) {
      Some(value) => state.push_integer(*value),
      None        => state.push_nil()
    };
    1
  }

  /// Pushes a value into the underlying Vec.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_push(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    let i = state.check_integer(2);
    (*v).data.push(i);
    1
  }

  /// Returns the length of the underlying Vec.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_len(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    state.push_integer((*v).data.len() as i64);
    1
  }

  /// Garbage collects a VecWrapper.
  #[allow(non_snake_case)]
  unsafe extern "C" fn lua_gc(L: *mut lua_State) -> c_int {
    let mut state = State::from_ptr(L);
    let v = state.check_userdata(1, "VecWrapper") as *mut VecWrapper;
    std::ptr::drop_in_place(v);
    0
  }
}

const VECWRAPPER_LIB: [(&'static str, Function); 4] = [
    ("new",  Some(VecWrapper::lua_new)),
    ("get",  Some(VecWrapper::lua_get)),
    ("push", Some(VecWrapper::lua_push)),
    ("len",  Some(VecWrapper::lua_len))
];

fn main() {
    let mut state = lua::State::new();

    state.open_libs();

    // make a VecWrapper table globally available to the lua state and register
    // our functions there:
    state.new_table();
    state.set_fns(&VECWRAPPER_LIB, 0);
    // copy reference to VecWrapper table so we can keep the original reference
    // on the stack for later
    state.push_value(-1);
    state.set_global("VecWrapper");

    // create a metatable for VecWrapper in the lua registry that refers to the
    // global VecWrapper table:
    state.new_metatable("VecWrapper");
    // copy reference to VecWrapper table
    state.push_value(-2);
    // VecWrappermetatable.__index = VecWrapper
    state.set_field(-2, "__index");
    // VecWrappermetatable.__gc = lua_gc
    state.push_fn(Some(VecWrapper::lua_gc));
    state.set_field(-2, "__gc");

    // pop metatable and VecWrapper table from the stack
    state.pop(2);

    // try it out:
    state.do_string("local v = VecWrapper.new()
                     v:push(12)
                     v:push(34)
                     -- should print 2
                     print('length of vec is', v:len())
                     -- should print 12 34 nil
                     print(v:get(0), v:get(1), v:get(2))");
}
<|endoftext|>


<commit_before>use proc_macro::{self, Span};
use {Arg, ToComma, Opt, Args, KvPair};
use proc_macro2::TokenStream;
use syn::token::Comma;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{self, Expr, ExprClosure, FnArg, ArgCaptured};

pub fn process(stream: proc_macro::TokenStream) -> TokenStream {
    let input = stream.to_string();
    let mut body = TokenStream::new();

    match syn::parse(stream) {
        Ok(Args(args)) => {
            for arg in args {
                if let Some(arg) = arg.process() {
                    body.extend(arg);
                }
            }
        }
        Err(_) => {
            Span::call_site()
                .error("failed to parse argument")
                .note("this is a bug, please report it")
                .emit();
        }
    }

    quote!({
        let mut args = Arg::new();
        args.set_string(&format!("args!({})", #input));
        #body
        args
    })
}

impl Arg {
    fn process(self) -> Option<TokenStream> {
        let mut body = TokenStream::new();

        match self {
            Arg::Expr(expr) => process_expr(expr, &mut body),
            Arg::Opt(opts) => {
                let Opt(opts) = opts;
                process_opts(opts, &mut body);
            }
            Arg::Bad(bad) => {
                let ToComma(arg) = bad;
                arg.span().unstable()
                    .error("unsupported argument")
                    .note("expected an argument, option or closure")
                    .emit();
                return None;
            }
        }

        Some(body)
    }
}

fn process_expr(expr: Expr, body: &mut TokenStream) {
    if let Expr::Closure(closure) = expr {
        process_closure(closure, body);
        return;
    }
    body.extend(quote! {
        args.add_arg(#expr.into_arg());
    });
}

fn _process_list(exprs: impl IntoIterator<Item=Expr>, body: &mut TokenStream) {
    let mut arg = quote! {
        let mut list_arg = Arg::new();
    };
    for expr in exprs {
        arg.extend(quote! {
            list_arg.add_arg(#expr.into_arg());
        });
    }
    arg.extend(quote! {
        args.add_arg(list_arg.into_arg());
    });
    body.extend(arg);
}

fn process_opts(opts: impl IntoIterator<Item=KvPair>, body: &mut TokenStream) {
    for KvPair(key, val) in opts {
        let key = key.to_string();
        body.extend(quote! {
            match Arg::create_term_pair(#key, #val) {
                Ok(pair) => args.add_opt(pair),
                Err(error) => args.set_term(Err(error)),
            }
        });
    }
}

fn process_closure(mut closure: ExprClosure, body: &mut TokenStream) {
    let mut ids = quote! {
        #[allow(unused_mut)]
        let mut ids = Vec::new();
    };
    let mut args = Punctuated::new();
    for (i, mut arg) in closure.inputs.iter_mut().enumerate() {
        let var = var(i);
        ids.extend(quote! {
            for t in #var.term().unwrap().get_args() {
                ids.push(t.get_datum().clone());
            }
        });
        args.push(syn::parse(var.into()).expect("a closure arg"));
        match arg {
            FnArg::Inferred(pat) => {
                let captured = ArgCaptured {
                    pat: pat.clone(),
                    colon_token: Default::default(),
                    ty: syn::parse_str("Client").expect("add Client annotation"),
                };
                *arg = FnArg::Captured(captured);
            }
            arg => {
                arg.span().unstable()
                    .error("unsupported ReQL closure argument")
                    .note("only arguments with no type annotations are supported")
                    .emit();
            }
        }
    }
    ids.extend(quote!(ids));
    let func = func(closure, args, ids);
    body.extend(quote! {
        use reql::{Client, RepeatedField, Term, Datum, TT, DT};

        args.add_arg(#func.into_arg());
    });
}

fn func(closure: ExprClosure, args: Punctuated<Expr, Comma>, ids: TokenStream) -> TokenStream {
    quote! {{
        let res: Client = (#closure)(#args);
        let mut closure = Client::new();
        match res.term() {
            Ok(res) => {
                // ARRAY
                let mut array = Datum::new();
                array.set_field_type(DT::R_ARRAY);
                let args = RepeatedField::from_vec({#ids});
                array.set_r_array(args);
                // DATUM
                let mut datum = Term::new();
                datum.set_field_type(TT::DATUM);
                datum.set_datum(array);
                // FUNC
                let mut func = Term::new();
                func.set_field_type(TT::FUNC);
                let args = RepeatedField::from_vec(vec![datum, res.clone()]);
                func.set_args(args);
                closure.set_term(Ok(func));
            }
            Err(error) => {
                closure.set_term(Err(error));
            }
        }
        closure
    }}
}

fn var(idx: usize) -> TokenStream {
    quote! {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(#idx as f64);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(id);
        // VAR
        let mut var = Term::new();
        var.set_field_type(TT::VAR);
        let args = RepeatedField::from_vec(vec![datum]);
        var.set_args(args);
        let mut client = Client::new();
        client.set_term(Ok(var));
        client
    }}
}
<commit_msg>fix assignment to borrowed arg<commit_after>use proc_macro::{self, Span};
use {Arg, ToComma, Opt, Args, KvPair};
use proc_macro2::TokenStream;
use syn::token::Comma;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{self, Expr, ExprClosure, FnArg, ArgCaptured};

pub fn process(stream: proc_macro::TokenStream) -> TokenStream {
    let input = stream.to_string();
    let mut body = TokenStream::new();

    match syn::parse(stream) {
        Ok(Args(args)) => {
            for arg in args {
                if let Some(arg) = arg.process() {
                    body.extend(arg);
                }
            }
        }
        Err(_) => {
            Span::call_site()
                .error("failed to parse argument")
                .note("this is a bug, please report it")
                .emit();
        }
    }

    quote!({
        let mut args = Arg::new();
        args.set_string(&format!("args!({})", #input));
        #body
        args
    })
}

impl Arg {
    fn process(self) -> Option<TokenStream> {
        let mut body = TokenStream::new();

        match self {
            Arg::Expr(expr) => process_expr(expr, &mut body),
            Arg::Opt(opts) => {
                let Opt(opts) = opts;
                process_opts(opts, &mut body);
            }
            Arg::Bad(bad) => {
                let ToComma(arg) = bad;
                arg.span().unstable()
                    .error("unsupported argument")
                    .note("expected an argument, option or closure")
                    .emit();
                return None;
            }
        }

        Some(body)
    }
}

fn process_expr(expr: Expr, body: &mut TokenStream) {
    if let Expr::Closure(closure) = expr {
        process_closure(closure, body);
        return;
    }
    body.extend(quote! {
        args.add_arg(#expr.into_arg());
    });
}

fn _process_list(exprs: impl IntoIterator<Item=Expr>, body: &mut TokenStream) {
    let mut arg = quote! {
        let mut list_arg = Arg::new();
    };
    for expr in exprs {
        arg.extend(quote! {
            list_arg.add_arg(#expr.into_arg());
        });
    }
    arg.extend(quote! {
        args.add_arg(list_arg.into_arg());
    });
    body.extend(arg);
}

fn process_opts(opts: impl IntoIterator<Item=KvPair>, body: &mut TokenStream) {
    for KvPair(key, val) in opts {
        let key = key.to_string();
        body.extend(quote! {
            match Arg::create_term_pair(#key, #val) {
                Ok(pair) => args.add_opt(pair),
                Err(error) => args.set_term(Err(error)),
            }
        });
    }
}

fn process_closure(mut closure: ExprClosure, body: &mut TokenStream) {
    let mut ids = quote! {
        #[allow(unused_mut)]
        let mut ids = Vec::new();
    };
    let mut args = Punctuated::new();
    for (i, mut arg) in closure.inputs.iter_mut().enumerate() {
        let var = var(i);
        ids.extend(quote! {
            for t in #var.term().unwrap().get_args() {
                ids.push(t.get_datum().clone());
            }
        });
        args.push(syn::parse(var.into()).expect("a closure arg"));
        match arg.clone() {
            FnArg::Inferred(pat) => {
                let captured = ArgCaptured {
                    pat: pat.clone(),
                    colon_token: Default::default(),
                    ty: syn::parse_str("Client").expect("add Client annotation"),
                };
                *arg = FnArg::Captured(captured);
            }
            arg => {
                arg.span().unstable()
                    .error("unsupported ReQL closure argument")
                    .note("only arguments with no type annotations are supported")
                    .emit();
            }
        }
    }
    ids.extend(quote!(ids));
    let func = func(closure, args, ids);
    body.extend(quote! {
        use reql::{Client, RepeatedField, Term, Datum, TT, DT};

        args.add_arg(#func.into_arg());
    });
}

fn func(closure: ExprClosure, args: Punctuated<Expr, Comma>, ids: TokenStream) -> TokenStream {
    quote! {{
        let res: Client = (#closure)(#args);
        let mut closure = Client::new();
        match res.term() {
            Ok(res) => {
                // ARRAY
                let mut array = Datum::new();
                array.set_field_type(DT::R_ARRAY);
                let args = RepeatedField::from_vec({#ids});
                array.set_r_array(args);
                // DATUM
                let mut datum = Term::new();
                datum.set_field_type(TT::DATUM);
                datum.set_datum(array);
                // FUNC
                let mut func = Term::new();
                func.set_field_type(TT::FUNC);
                let args = RepeatedField::from_vec(vec![datum, res.clone()]);
                func.set_args(args);
                closure.set_term(Ok(func));
            }
            Err(error) => {
                closure.set_term(Err(error));
            }
        }
        closure
    }}
}

fn var(idx: usize) -> TokenStream {
    quote! {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(#idx as f64);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(id);
        // VAR
        let mut var = Term::new();
        var.set_field_type(TT::VAR);
        let args = RepeatedField::from_vec(vec![datum]);
        var.set_args(args);
        let mut client = Client::new();
        client.set_term(Ok(var));
        client
    }}
}
<|endoftext|>


<commit_before>use libc::*;
use std::mem;
// I tried
// It's a bit hard to write this without a Windows pc on hand...
extern "stdcall" {
	fn XInputGetCapabilities(index: u32, flags: u32, capabilities: *mut Capabilities) -> i32;
	fn XInputGetState(index: u32, state: *mut State) -> i32;
}

#[repr(C)]
struct State {
	packet_number: i32,
	gamepad: Gamepad
}

#[repr(C)]
struct Capabilities {
	_type: u8,
	sub_type: u8,
	flags: u32,
	gamepad: Gamepad,
	vibration: Vibration
}

bitflags!(
	flags Buttons: u32 {
		const DPAD_UP = 0x0001,
		const DPAD_DOWN = 0x0002,
		const DPAD_LEFT = 0x0004,
		const DPAD_RIGHT = 0x0008,
		const START = 0x0010,
		const BACK = 0x0020,
		const LEFT_THUMB = 0x0040,
		const RIGHT_THUMB = 0x0080,
		const LEFT_SHOULDER = 0x0100,
		const RIGHT_SHOULDER = 0x0200,
		const A = 0x1000,
		const B = 0x2000,
		const X = 0x4000,
		const Y = 0x8000,
	}
);
#[repr(C)]
#[derive(Copy)]
struct Gamepad {
	buttons: Buttons,
	left_trigger: u8,
	right_trigger: u8,
	thumb_lx: i16,
	thumb_ly: i16,
	thumb_rx: i16,
	thumb_ry: i16
}
#[repr(C)]
struct Vibration {
	left_motor_speed: i32,
	right_motor_speed: i32
}

pub struct NativeJoystick {
	index: u8,
	last: Gamepad
}
impl ::Joystick for NativeJoystick {
	fn new(index: u8) -> Result<NativeJoystick, &'static str> {
		unsafe {
			let mut caps:Capabilities = mem::uninitialized();
			XInputGetCapabilities(index as u32, 0, &mut caps);
			Ok(NativeJoystick {
				index: index,
				last: caps.gamepad
			})
		}
	}
	fn get_index(&self) -> u8 {
		self.index
	}
}
impl NativeJoystick {
	pub fn get_axis(&self, index: usize) -> Option<i16> {
		match index {
			0 => Some(self.last.thumb_lx),
			1 => Some(self.last.thumb_ly),
			2 => Some(self.last.thumb_rx),
			3 => Some(self.last.thumb_ry),
			_ => None
		}
	}
	/// Get the value of a specific axis normalised to between -1.0 and 1.0
	pub fn get_normalised_axis(&self, index: usize) -> Option<f32> {
		self.get_axis(index).map(|v| v as f32 / ::MAX_JOYSTICK_VALUE as f32)
	}
	pub fn get_button(&self, index: usize) -> Option<bool> {
		let bits = match index {
			0 => Some(A),
			1 => Some(B),
			2 => Some(X),
			3 => Some(Y),
			_ => None
		};
		bits.map(|v| self.last.buttons.contains(v))
	}
}
<commit_msg>Explicitly link in windows<commit_after>use libc::*;
use std::mem;
// I tried
// It's a bit hard to write this without a Windows pc on hand...
#[link(name = "XINPUT9_1_0")]
extern "stdcall" {
	fn XInputGetCapabilities(index: u32, flags: u32, capabilities: *mut Capabilities) -> i32;
	fn XInputGetState(index: u32, state: *mut State) -> i32;
}

#[repr(C)]
struct State {
	packet_number: i32,
	gamepad: Gamepad
}

#[repr(C)]
struct Capabilities {
	_type: u8,
	sub_type: u8,
	flags: u32,
	gamepad: Gamepad,
	vibration: Vibration
}

bitflags!(
	flags Buttons: u32 {
		const DPAD_UP = 0x0001,
		const DPAD_DOWN = 0x0002,
		const DPAD_LEFT = 0x0004,
		const DPAD_RIGHT = 0x0008,
		const START = 0x0010,
		const BACK = 0x0020,
		const LEFT_THUMB = 0x0040,
		const RIGHT_THUMB = 0x0080,
		const LEFT_SHOULDER = 0x0100,
		const RIGHT_SHOULDER = 0x0200,
		const A = 0x1000,
		const B = 0x2000,
		const X = 0x4000,
		const Y = 0x8000,
	}
);
#[repr(C)]
#[derive(Copy)]
struct Gamepad {
	buttons: Buttons,
	left_trigger: u8,
	right_trigger: u8,
	thumb_lx: i16,
	thumb_ly: i16,
	thumb_rx: i16,
	thumb_ry: i16
}
#[repr(C)]
struct Vibration {
	left_motor_speed: i32,
	right_motor_speed: i32
}

pub struct NativeJoystick {
	index: u8,
	last: Gamepad
}
impl ::Joystick for NativeJoystick {
	fn new(index: u8) -> Result<NativeJoystick, &'static str> {
		unsafe {
			let mut caps:Capabilities = mem::uninitialized();
			XInputGetCapabilities(index as u32, 0, &mut caps);
			Ok(NativeJoystick {
				index: index,
				last: caps.gamepad
			})
		}
	}
	fn get_index(&self) -> u8 {
		self.index
	}
}
impl ::StatefulJoystick for NativeJoystick {
	fn get_axis(&self, index: usize) -> Option<i16> {
		match index {
			0 => Some(self.last.thumb_lx),
			1 => Some(self.last.thumb_ly),
			2 => Some(self.last.thumb_rx),
			3 => Some(self.last.thumb_ry),
			_ => None
		}
	}
	fn get_button(&self, index: usize) -> Option<bool> {
		let bits = match index {
			0 => Some(A),
			1 => Some(B),
			2 => Some(X),
			3 => Some(Y),
			_ => None
		};
		bits.map(|v| self.last.buttons.contains(v))
	}
}
<|endoftext|>