<commit_before>use ffmpeg::format;
use gl;
use gl::types::*;
use ocl;

use super::*;
use capture;
use hooks::hw::FrameCapture;

pub struct SamplingConverter {
    /// Difference, in video frames, between how much time passed in-game and how much video we
    /// output.
    remainder: f64,

    /// The target time_base.
    time_base: f64,

    /// Data with a destructor.
    private: *mut SamplingConverterPrivate,
}

struct SamplingConverterPrivate {
    /// OpenCL buffer images.
    ocl_buffers: [ocl::Image<u8>; 2],

    /// OpenCL output image.
    ocl_output_image: ocl::Image<u8>,

    /// Index of the last written to OpenCL buffer.
    ocl_current_buffer_index: usize,
}

impl SamplingConverter {
    pub fn new(engine: &Engine, time_base: f64, video_resolution: (u32, u32)) -> Self {
        assert!(time_base > 0f64);

        Self {
            remainder: 0f64,
            time_base,
            private: Box::into_raw(Box::new(SamplingConverterPrivate::new(engine,
                                                                          video_resolution))),
        }
    }

    pub fn free(&mut self) {
        drop(unsafe { Box::from_raw(self.private) });
    }
}

impl FPSConverter for SamplingConverter {
    fn time_passed<F>(&mut self, engine: &Engine, frametime: f64, capture: F)
    where
        F: FnOnce(&Engine) -> FrameCapture,
    {
        assert!(frametime >= 0.0f64);

        let frame_capture = capture(engine);
        let mut private = unsafe { self.private.as_mut().unwrap() };

        let old_remainder = self.remainder;
        self.remainder += frametime / self.time_base;

        if self.remainder < 1f64 {
            let weight = self.remainder - old_remainder;

            match frame_capture {
                FrameCapture::OpenGL => {
                    unimplemented!();
                }

                FrameCapture::OpenCL(ocl_gl_texture) => {
                    weighted_image_add(engine,
                                       ocl_gl_texture.as_ref(),
                                       private.src_buffer(),
                                       private.dst_buffer(),
                                       weight as f32);

                    private.switch_buffer_index();
                }
            }
        } else {
            let weight = 1f64 - old_remainder;

            match frame_capture {
                FrameCapture::OpenGL => {
                    unimplemented!();
                }

                FrameCapture::OpenCL(ocl_gl_texture) => {
                    weighted_image_add(engine,
                                       ocl_gl_texture.as_ref(),
                                       private.src_buffer(),
                                       private.output_image(),
                                       weight as f32);

                    fill_with_black(engine, private.dst_buffer());

                    private.switch_buffer_index();

                    // Output the frame.
                    let (w, h) = hw::get_resolution(engine);
                    let mut buf = capture::get_buffer(engine, (w, h));
                    hw::read_ocl_image_into_buf(engine, private.output_image(), &mut buf);
                    capture::capture(engine, buf, 1);

                    self.remainder -= 1f64;

                    // Output it more times if needed.
                    let additional_frames = self.remainder as usize;
                    if additional_frames > 0 {
                        let mut buf = capture::get_buffer(engine, (w, h));
                        hw::read_ocl_image_into_buf(engine, ocl_gl_texture.as_ref(), &mut buf);
                        capture::capture(engine, buf, additional_frames);

                        self.remainder -= additional_frames as f64;
                    }

                    // Add the remaining image into the buffer.
                    weighted_image_add(engine,
                                       ocl_gl_texture.as_ref(),
                                       private.src_buffer(),
                                       private.dst_buffer(),
                                       self.remainder as f32);
                    private.switch_buffer_index();
                }
            }
        }

        // let (w, h) = hw::get_resolution(engine);
        // let mut buf = capture::get_buffer(engine, (w, h));
        //
        // match frame_capture {
        //     FrameCapture::OpenGL => {
        //         buf.set_format(format::Pixel::RGB24);
        //
        //         unsafe {
        //             // Our buffer expects 1-byte alignment.
        //             gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
        //
        //             // Get the pixels!
        //             gl::ReadPixels(0,
        //                            0,
        //                            w as GLsizei,
        //                            h as GLsizei,
        //                            gl::RGB,
        //                            gl::UNSIGNED_BYTE,
        //                            buf.as_mut_slice().as_mut_ptr() as _);
        //         }
        //     }
        //
        //     FrameCapture::OpenCL(ocl_gl_texture) => {
        //         hw::read_ocl_image_into_buf(engine, &ocl_gl_texture, &mut buf);
        //     }
        // }
        //
        // capture::capture(engine, buf, frames);
    }
}

impl SamplingConverterPrivate {
    fn new(engine: &Engine, (w, h): (u32, u32)) -> Self {
        let pro_que = hw::get_pro_que(engine).expect("sampling currently requires OpenCL");

        let rv = Self {
            ocl_buffers: [
                hw::build_ocl_image(engine,
                                    &pro_que,
                                    ocl::MemFlags::new().read_write().host_no_access(),
                                    ocl::enums::ImageChannelDataType::Float,
                                    (w, h).into())
                .expect("building an OpenCL image"),
                hw::build_ocl_image(engine,
                                    &pro_que,
                                    ocl::MemFlags::new().read_write().host_no_access(),
                                    ocl::enums::ImageChannelDataType::Float,
                                    (w, h).into())
                .expect("building an OpenCL image"),
            ],
            ocl_output_image: hw::build_ocl_image(engine,
                                                  &pro_que,
                                                  ocl::MemFlags::new()
                                                      .read_write()
                                                      .host_read_only(),
                                                  ocl::enums::ImageChannelDataType::Float,
                                                  (w, h).into())
                              .expect("building an OpenCL image"),
            ocl_current_buffer_index: 0,
        };

        fill_with_black(engine, rv.src_buffer());

        rv
    }

    fn src_buffer(&self) -> &ocl::Image<u8> {
        &self.ocl_buffers[self.ocl_current_buffer_index]
    }

    fn dst_buffer(&self) -> &ocl::Image<u8> {
        &self.ocl_buffers[self.ocl_current_buffer_index ^ 1]
    }

    fn output_image(&self) -> &ocl::Image<u8> {
        &self.ocl_output_image
    }

    fn switch_buffer_index(&mut self) {
        self.ocl_current_buffer_index ^= 1;
    }
}

fn weighted_image_add(engine: &Engine,
                      src: &ocl::Image<u8>,
                      buf: &ocl::Image<u8>,
                      dst: &ocl::Image<u8>,
                      weight: f32) {
    let pro_que = hw::get_pro_que(engine).unwrap();

    let kernel = pro_que.create_kernel("weighted_image_add")
                        .unwrap()
                        .gws(src.dims())
                        .arg_img(src)
                        .arg_img(buf)
                        .arg_img(dst)
                        .arg_scl(weight);

    kernel.enq().expect("sampling kernel enq()");
}

fn fill_with_black(engine: &Engine, image: &ocl::Image<u8>) {
    let pro_que = hw::get_pro_que(engine).unwrap();

    let kernel = pro_que.create_kernel("fill_with_black")
                        .unwrap()
                        .gws(image.dims())
                        .arg_img(image);

    kernel.enq().expect("sampling kernel enq()");
}
<commit_msg>Implement cap_exposure<commit_after>use ffmpeg::format;
use gl;
use gl::types::*;
use ocl;

use super::*;
use capture;
use hooks::hw::FrameCapture;

pub struct SamplingConverter {
    /// Difference, in video frames, between how much time passed in-game and how much video we
    /// output.
    remainder: f64,

    /// The target time_base.
    time_base: f64,

    /// Data with a destructor.
    private: *mut SamplingConverterPrivate,
}

struct SamplingConverterPrivate {
    /// OpenCL buffer images.
    ocl_buffers: [ocl::Image<u8>; 2],

    /// OpenCL output image.
    ocl_output_image: ocl::Image<u8>,

    /// Index of the last written to OpenCL buffer.
    ocl_current_buffer_index: usize,
}

impl SamplingConverter {
    pub fn new(engine: &Engine, time_base: f64, video_resolution: (u32, u32)) -> Self {
        assert!(time_base > 0f64);

        Self {
            remainder: 0f64,
            time_base,
            private: Box::into_raw(Box::new(SamplingConverterPrivate::new(engine,
                                                                          video_resolution))),
        }
    }

    pub fn free(&mut self) {
        drop(unsafe { Box::from_raw(self.private) });
    }
}

impl FPSConverter for SamplingConverter {
    fn time_passed<F>(&mut self, engine: &Engine, frametime: f64, capture: F)
    where
        F: FnOnce(&Engine) -> FrameCapture,
    {
        assert!(frametime >= 0.0f64);

        let frame_capture = capture(engine);
        let mut private = unsafe { self.private.as_mut().unwrap() };

        let old_remainder = self.remainder;
        self.remainder += frametime / self.time_base;

        let exposure = capture::get_capture_parameters(engine).sampling_exposure;

        if self.remainder <= (1f64 - exposure) {
            // Do nothing.
        } else if self.remainder < 1f64 {
            let weight = (self.remainder - old_remainder.max(1f64 - exposure)) * (1f64 / exposure);

            match frame_capture {
                FrameCapture::OpenGL => {
                    unimplemented!();
                }

                FrameCapture::OpenCL(ocl_gl_texture) => {
                    weighted_image_add(engine,
                                       ocl_gl_texture.as_ref(),
                                       private.src_buffer(),
                                       private.dst_buffer(),
                                       weight as f32);

                    private.switch_buffer_index();
                }
            }
        } else {
            let weight = (1f64 - old_remainder.max(1f64 - exposure)) * (1f64 / exposure);

            match frame_capture {
                FrameCapture::OpenGL => {
                    unimplemented!();
                }

                FrameCapture::OpenCL(ocl_gl_texture) => {
                    weighted_image_add(engine,
                                       ocl_gl_texture.as_ref(),
                                       private.src_buffer(),
                                       private.output_image(),
                                       weight as f32);

                    fill_with_black(engine, private.dst_buffer());

                    private.switch_buffer_index();

                    // Output the frame.
                    let (w, h) = hw::get_resolution(engine);
                    let mut buf = capture::get_buffer(engine, (w, h));
                    hw::read_ocl_image_into_buf(engine, private.output_image(), &mut buf);
                    capture::capture(engine, buf, 1);

                    self.remainder -= 1f64;

                    // Output it more times if needed.
                    let additional_frames = self.remainder as usize;
                    if additional_frames > 0 {
                        let mut buf = capture::get_buffer(engine, (w, h));
                        hw::read_ocl_image_into_buf(engine, ocl_gl_texture.as_ref(), &mut buf);
                        capture::capture(engine, buf, additional_frames);

                        self.remainder -= additional_frames as f64;
                    }

                    // Add the remaining image into the buffer.
                    if self.remainder > (1f64 - exposure) {
                        weighted_image_add(engine,
                                           ocl_gl_texture.as_ref(),
                                           private.src_buffer(),
                                           private.dst_buffer(),
                                           ((1f64 - exposure) - self.remainder) as f32);
                        private.switch_buffer_index();
                    }
                }
            }
        }

        // let (w, h) = hw::get_resolution(engine);
        // let mut buf = capture::get_buffer(engine, (w, h));
        //
        // match frame_capture {
        //     FrameCapture::OpenGL => {
        //         buf.set_format(format::Pixel::RGB24);
        //
        //         unsafe {
        //             // Our buffer expects 1-byte alignment.
        //             gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
        //
        //             // Get the pixels!
        //             gl::ReadPixels(0,
        //                            0,
        //                            w as GLsizei,
        //                            h as GLsizei,
        //                            gl::RGB,
        //                            gl::UNSIGNED_BYTE,
        //                            buf.as_mut_slice().as_mut_ptr() as _);
        //         }
        //     }
        //
        //     FrameCapture::OpenCL(ocl_gl_texture) => {
        //         hw::read_ocl_image_into_buf(engine, &ocl_gl_texture, &mut buf);
        //     }
        // }
        //
        // capture::capture(engine, buf, frames);
    }
}

impl SamplingConverterPrivate {
    fn new(engine: &Engine, (w, h): (u32, u32)) -> Self {
        let pro_que = hw::get_pro_que(engine).expect("sampling currently requires OpenCL");

        let rv = Self {
            ocl_buffers: [
                hw::build_ocl_image(engine,
                                    &pro_que,
                                    ocl::MemFlags::new().read_write().host_no_access(),
                                    ocl::enums::ImageChannelDataType::Float,
                                    (w, h).into())
                .expect("building an OpenCL image"),
                hw::build_ocl_image(engine,
                                    &pro_que,
                                    ocl::MemFlags::new().read_write().host_no_access(),
                                    ocl::enums::ImageChannelDataType::Float,
                                    (w, h).into())
                .expect("building an OpenCL image"),
            ],
            ocl_output_image: hw::build_ocl_image(engine,
                                                  &pro_que,
                                                  ocl::MemFlags::new()
                                                      .read_write()
                                                      .host_read_only(),
                                                  ocl::enums::ImageChannelDataType::Float,
                                                  (w, h).into())
                              .expect("building an OpenCL image"),
            ocl_current_buffer_index: 0,
        };

        fill_with_black(engine, rv.src_buffer());

        rv
    }

    fn src_buffer(&self) -> &ocl::Image<u8> {
        &self.ocl_buffers[self.ocl_current_buffer_index]
    }

    fn dst_buffer(&self) -> &ocl::Image<u8> {
        &self.ocl_buffers[self.ocl_current_buffer_index ^ 1]
    }

    fn output_image(&self) -> &ocl::Image<u8> {
        &self.ocl_output_image
    }

    fn switch_buffer_index(&mut self) {
        self.ocl_current_buffer_index ^= 1;
    }
}

fn weighted_image_add(engine: &Engine,
                      src: &ocl::Image<u8>,
                      buf: &ocl::Image<u8>,
                      dst: &ocl::Image<u8>,
                      weight: f32) {
    let pro_que = hw::get_pro_que(engine).unwrap();

    let kernel = pro_que.create_kernel("weighted_image_add")
                        .unwrap()
                        .gws(src.dims())
                        .arg_img(src)
                        .arg_img(buf)
                        .arg_img(dst)
                        .arg_scl(weight);

    kernel.enq().expect("sampling kernel enq()");
}

fn fill_with_black(engine: &Engine, image: &ocl::Image<u8>) {
    let pro_que = hw::get_pro_que(engine).unwrap();

    let kernel = pro_que.create_kernel("fill_with_black")
                        .unwrap()
                        .gws(image.dims())
                        .arg_img(image);

    kernel.enq().expect("sampling kernel enq()");
}
<|endoftext|>


<commit_before>use super::{seat, server::Server};
use wlroots::{self, Capability, Compositor, HandleResult, InputDevice, InputManagerHandler};

const DEFAULT_SEAT_NAME: &str = "seat0";

pub struct InputManager {
    seats: Vec<seat::Seat>
}

impl InputManagerHandler for InputManager {
    fn input_added(&mut self, compositor: &mut Compositor, input: &mut InputDevice) {
        let seat_name;
        {
            let state: &mut Server = compositor.into();
            seat_name = match state.config
                                   .devices
                                   .iter()
                                   .find(|dev_conf| dev_conf.name.as_str() == DEFAULT_SEAT_NAME)
            {
                None => DEFAULT_SEAT_NAME.into(),
                Some(dev) => dev.name.clone()
            };
        }
        let seat = self.get_seat(compositor, &*seat_name).expect("Could make a new seat");
        self.add_device_to_seat(compositor, seat, input).expect("Could not add a device to a seat");
    }
}

impl InputManager {
    pub fn new() -> Self {
        InputManager { seats: vec![] }
    }

    /// Gets the seat by name. If it doesn't exist yet, create it.
    fn get_seat(&mut self,
                compositor: &mut Compositor,
                seat_name: &str)
                -> HandleResult<wlroots::SeatHandle> {
        let found = &mut false;
        for seat in &mut self.seats {
            seat.seat.clone().run(|seat| {
                                       if seat.name().as_ref().map(|s| &**s) == Some(seat_name) {
                                           *found = true;
                                       }
                                   })?;
            if *found {
                return Ok(seat.seat.clone())
            }
        }
        let seat_handle = wlroots::Seat::create(compositor,
                                                seat_name.into(),
                                                Box::new(seat::SeatHandler::new()));
        let seat = seat::Seat::new(seat_handle);
        self.seats.push(seat);
        Ok(self.seats.last_mut().expect("impossible").seat.clone())
    }

    pub fn add_device_to_seat(&mut self,
                              compositor: &mut Compositor,
                              mut seat: wlroots::SeatHandle,
                              input: &mut InputDevice)
                              -> HandleResult<()> {
        use wlroots::wlr_input_device_type::*;
        match input.dev_type() {
            WLR_INPUT_DEVICE_KEYBOARD => {
                seat.run(|seat| {
                              seat.set_keyboard(input);
                          })?
            }
            WLR_INPUT_DEVICE_POINTER => {
                {
                    let roots_seat = self.roots_seat_from_handle(seat.clone());
                    if let Some(cursor) = roots_seat.cursor.as_mut() {
                        cursor.cursor.run(|cursor| {
                                               cursor.attach_input_device(input);
                                           })?;
                    }
                }
                self.configure_cursor(compositor, seat.clone())?;
                seat.run(|seat| {
                              let mut capabilities = seat.capabilities();
                              capabilities.insert(Capability::Pointer);
                              seat.set_capabilities(capabilities);
                          })?
            }
            WLR_INPUT_DEVICE_TOUCH | WLR_INPUT_DEVICE_TABLET_TOOL => {
                {
                    let roots_seat = self.roots_seat_from_handle(seat.clone());
                    if let Some(cursor) = roots_seat.cursor.as_mut() {
                        cursor.cursor.run(|cursor| {
                                               cursor.attach_input_device(input);
                                           })?;
                    }
                }
                self.configure_cursor(compositor, seat.clone())?;
                seat.run(|seat| {
                              let mut capabilities = seat.capabilities();
                              capabilities.insert(Capability::Touch);
                              seat.set_capabilities(capabilities);
                          })?
            }
            WLR_INPUT_DEVICE_TABLET_PAD => { /*TODO*/ }
        }
        Ok(())
    }

    pub fn configure_cursor(&mut self,
                            // TODO Remove?
                            compositor: &mut Compositor,
                            seat: wlroots::SeatHandle)
                            -> HandleResult<()> {
        let state: &mut Server = compositor.into();
        let roots_seat = self.roots_seat_from_handle(seat.clone());
        if let Some(cursor) = roots_seat.cursor.as_mut() {
            let pointers = &mut roots_seat.pointers;
            let touches = &mut roots_seat.touch;
            run_handles!([(seat: {seat}), (cursor: {cursor.cursor.clone()})] => {
                // reset mappings
                cursor.map_to_output(None);
                for pointer in pointers {
                    cursor.map_input_to_output(pointer.input_device(),
                                               None)
                }
                // TODO Also map input to region if part of config
                for touch in touches {
                    cursor.map_input_to_output(touch.input_device(), None)
                }
                // TODO table tool
                let outputs = &mut state.outputs;
                let seat_name = seat.name().unwrap_or_else(|| "".into());
                match state.config
                    .cursors
                    .iter()
                    .find(|cursor| cursor.seat == seat_name)
                {
                    None => {},
                    Some(cursor_config) => {
                        if let Some(mapped_output_name) =
                            cursor_config.mapped_output.as_ref()
                        {
                            for output in outputs {
                                output.run(|output| {
                                    if output.name() == *mapped_output_name
                                    {
                                        cursor.map_to_output(output)
                                    }
                                }).unwrap();
                            }
                        }
                    }
                }
            })?;
            //                                         Some(cursor)
            //                                     })
            //                                .ok()?;
            //                          Some(seat)
            //                      })?;
        }

        // configure device to output mappings
        Ok(())
    }

    fn roots_seat_from_handle(&mut self, handle: wlroots::SeatHandle) -> &mut seat::Seat {
        for seat in &mut self.seats {
            if seat.seat == handle {
                return seat
            }
        }
        panic!("{:?} not found", handle);
    }
}
<commit_msg>Fixed rootston build<commit_after>use super::{seat, server::Server};
use wlroots::{self, Capability, Compositor, HandleResult, InputDevice, InputManagerHandler};

const DEFAULT_SEAT_NAME: &str = "seat0";

pub struct InputManager {
    seats: Vec<seat::Seat>
}

impl InputManagerHandler for InputManager {
    fn input_added(&mut self, compositor: &mut Compositor, input: &mut InputDevice) {
        let seat_name;
        {
            let state: &mut Server = compositor.into();
            seat_name = match state.config
                                   .devices
                                   .iter()
                                   .find(|dev_conf| dev_conf.name.as_str() == DEFAULT_SEAT_NAME)
            {
                None => DEFAULT_SEAT_NAME.into(),
                Some(dev) => dev.name.clone()
            };
        }
        let seat = self.get_seat(compositor, &*seat_name).expect("Could make a new seat");
        self.add_device_to_seat(compositor, seat, input).expect("Could not add a device to a seat");
    }
}

impl InputManager {
    pub fn new() -> Self {
        InputManager { seats: vec![] }
    }

    /// Gets the seat by name. If it doesn't exist yet, create it.
    fn get_seat(&mut self,
                compositor: &mut Compositor,
                seat_name: &str)
                -> HandleResult<wlroots::SeatHandle> {
        let found = &mut false;
        for seat in &mut self.seats {
            seat.seat.clone().run(|seat| {
                                       if seat.name().as_ref().map(|s| &**s) == Some(seat_name) {
                                           *found = true;
                                       }
                                   })?;
            if *found {
                return Ok(seat.seat.clone())
            }
        }
        let seat_handle = wlroots::Seat::create(compositor,
                                                seat_name.into(),
                                                Box::new(seat::SeatHandler::new()));
        let seat = seat::Seat::new(seat_handle);
        self.seats.push(seat);
        Ok(self.seats.last_mut().expect("impossible").seat.clone())
    }

    pub fn add_device_to_seat(&mut self,
                              compositor: &mut Compositor,
                              mut seat: wlroots::SeatHandle,
                              input: &mut InputDevice)
                              -> HandleResult<()> {
        use wlroots::wlr_input_device_type::*;
        match input.dev_type() {
            WLR_INPUT_DEVICE_KEYBOARD => {
                seat.run(|seat| {
                              seat.set_keyboard(input);
                          })?
            }
            WLR_INPUT_DEVICE_POINTER => {
                {
                    let roots_seat = self.roots_seat_from_handle(seat.clone());
                    if let Some(cursor) = roots_seat.cursor.as_mut() {
                        cursor.cursor.run(|cursor| {
                                               cursor.attach_input_device(input);
                                           })?;
                    }
                }
                self.configure_cursor(compositor, seat.clone())?;
                seat.run(|seat| {
                              let mut capabilities = seat.capabilities();
                              capabilities.insert(Capability::Pointer);
                              seat.set_capabilities(capabilities);
                          })?
            }
            WLR_INPUT_DEVICE_TOUCH | WLR_INPUT_DEVICE_TABLET_TOOL => {
                {
                    let roots_seat = self.roots_seat_from_handle(seat.clone());
                    if let Some(cursor) = roots_seat.cursor.as_mut() {
                        cursor.cursor.run(|cursor| {
                                               cursor.attach_input_device(input);
                                           })?;
                    }
                }
                self.configure_cursor(compositor, seat.clone())?;
                seat.run(|seat| {
                              let mut capabilities = seat.capabilities();
                              capabilities.insert(Capability::Touch);
                              seat.set_capabilities(capabilities);
                          })?
            }
            WLR_INPUT_DEVICE_TABLET_PAD => { /*TODO*/ }
        }
        Ok(())
    }

    pub fn configure_cursor(&mut self,
                            // TODO Remove?
                            compositor: &mut Compositor,
                            seat: wlroots::SeatHandle)
                            -> HandleResult<()> {
        let state: &mut Server = compositor.into();
        let roots_seat = self.roots_seat_from_handle(seat.clone());
        if let Some(cursor) = roots_seat.cursor.as_mut() {
            let pointers = &mut roots_seat.pointers;
            let touches = &mut roots_seat.touch;
            run_handles!([(seat: {seat}), (cursor: {cursor.cursor.clone()})] => {
                // reset mappings
                cursor.map_to_output(None);
                for pointer in pointers {
                    cursor.map_input_to_output(pointer.input_device()?,
                                               None)
                }
                // TODO Also map input to region if part of config
                for touch in touches {
                    cursor.map_input_to_output(touch.input_device()?, None)
                }
                // TODO table tool
                let outputs = &mut state.outputs;
                let seat_name = seat.name().unwrap_or_else(|| "".into());
                match state.config
                    .cursors
                    .iter()
                    .find(|cursor| cursor.seat == seat_name)
                {
                    None => {},
                    Some(cursor_config) => {
                        if let Some(mapped_output_name) =
                            cursor_config.mapped_output.as_ref()
                        {
                            for output in outputs {
                                output.run(|output| {
                                    if output.name() == *mapped_output_name
                                    {
                                        cursor.map_to_output(output)
                                    }
                                }).unwrap();
                            }
                        }
                    }
                }
            })?;
            //                                         Some(cursor)
            //                                     })
            //                                .ok()?;
            //                          Some(seat)
            //                      })?;
        }

        // configure device to output mappings
        Ok(())
    }

    fn roots_seat_from_handle(&mut self, handle: wlroots::SeatHandle) -> &mut seat::Seat {
        for seat in &mut self.seats {
            if seat.seat == handle {
                return seat
            }
        }
        panic!("{:?} not found", handle);
    }
}
<|endoftext|>


<commit_before>use value::Value;

type Id = String;

// K is the unique key
type KV<K, V> = Hashtable<K, V>;

// two columns - no unique keys
type VV<K,V> = Hashtable<K, V>;

// two columns - first two are the unique key
type KKV<K1, K2, V> = Hashtable<K1, Hashtable<K2, V>>;

type Program = {
    // all state lives in a view of some kind
    view_kind: KV<Id, ViewKind>,

    // views have fields, fields may belong to multiple views
    field_view: VV<Id, Id>,

    // a table has an insert view and a remove view
    table_insert: KV<Id, Id>,
    table_remove: KV<Id, Id>,

    // a query just indirects to another view
    query_view: KV<Id, Id>,

    // sources uniquely identify a copy of a child view inside a parent view
    // eg a parent join can have multiple copies of some child view, with different source ids
    source_parent: KV<Id, Id>,
    source_child: KV<Id, Id>,

    // constraints belong to a join view
    // the left and right are references which are compared using the operation
    constraint_parent: KV<Id, Id>,
    constraint_left: KV<Id, Id>,
    constraint_operation: KV<Id, ConstraintOperation>,
    constraint_right: KV<Id, Id>,

    // aggregates group an inner view by the rows of an outer view
    // the groups are reduced using some primitive
    aggregate_primitive: KV<Id, Id>,
    aggregate_outer: KV<Id, Id>,
    aggregate_inner: KV<Id, Id>,

    // the aggregate grouping is determined by binding outer fields to inner fields
    // bound fields can optionally be passed to the aggregate primitive as arguments
    aggregate_outerfield_binding: KKV<Id, Id, Id>,
    binding_innerfield: KV<Id, Id>,
    binding_primitivefield: KV<Id, ID>,

    // primitives are used to access built-in operations
    primitive: K<Id>,

    // constant references just refer to some value
    reference_value: KV<Id, Value>,

    // field references refer to a field in either a source (for join) or TODO
    reference_field: KV<Id, Id>,
    reference_source: KV<Id, Id>,

    // things that live in an ordered list are sorted by some f64
    thing_order: KV<Id, f64>,

    // things can have human readable names
    thing_name: KV<Id, String>,

    // TODO functions
    // TODO function and aggregate arguments (FieldKind?)
    // TODO select
    // TODO union
    // TODO negate
}

enum ViewKind {
    Table, // a view which can depend on the past
    Query, // a wrapper around some workspace full of views
    Join, // take the product of multiple views and filter the results
    Union, // take the union of multiple views
    Aggregate, // group one view by the contents of another and run some primitive on the groups
}

enum ConstraintOperation {
    Equal,
    NotEqual,
    LessThan,
    LessThanOrEqual,
    GreaterThan,
    GreaterThanOrEqual,
}

enum PrimitiveKind {
    Function,
    Aggregate,
}<commit_msg>Progress on ast<commit_after>use value::Value;

type Id = String;

// a table with a single unique key K
type KV<K, V> = Hashtable<K, V>;

// every record in this struct represents a table
// the tables are named by their fields, separated by underscores
// eg view_kind is a table with two fields: view and kind
type Program = {
    // all state lives in a view of some kind
    view_kind: KV<Id, ViewKind>,

    // views have fields which are globally unique
    field_view: KV<Id, Id>,
    // some fields have constraints on how they can be queried
    field_kind: KV<Id, FieldKind>,

    // a table has an insert view and a remove view
    table_insert: KV<Id, Id>,
    table_remove: KV<Id, Id>,

    // sources uniquely identify a copy of a child view inside a parent join or union
    // eg a parent join can have multiple copies of some child view, with different source ids
    parent_source_child: KV<(Id, Id), Id>,
    // every view also has an implicit "constant" source
    // anywhere a source-field pair is expected, you can instead use "constant"-id
    constant_value: KV<Id, Value>,

    // constraints belong to a join view
    // the left and right fields are compared using the operation
    constraint_parent: KV<Id, Id>,
    constraint_leftsource_leftfield: KV<Id, (Id, Id)>,
    constraint_operation: KV<Id, ConstraintOperation>,
    constraint_rightsource_rightfield: KV<Id, (Id, Id)>,

    // aggregates group an "inner" source by the rows of an "outer" source
    // the groups are reduced by joining against a "primitive" source
    // the grouping is determined by binding inner fields to outer fields or constants
    aggregate_innerfield_source_sourcefield: KV<(Id, Id), (Id, Id)>,
    // inner fields and constants can also be used as arguments to the aggregate function
    aggregate_primitivefield_source_sourcefield: KV<(Id, Id), (Id, Id)>,

    // views produce output by binding fields from sources
    // each join field is bound exactly once
    join_joinfield_source_sourcefield: KV<(Id, Id), (Id, Id)>,
    // each union field is bound exactly once per source
    union_unionfield_source_sourcefield: KV<(Id, Id, Id), Id>,
    // each aggregate field is bound exactly once and cannot bind "outer"
    aggregate_aggregatefield_source_sourcefield: KV<(Id, Id), (Id, Id)>,

    // things that live in an ordered list are sorted by some f64
    thing_order: KV<Id, f64>,

    // things can have human readable names
    thing_name: KV<Id, String>,

    // TODO primitives cannot represent limit
    // TODO want multiple primitives per aggregate?
    // TODO sort order for aggregates?
}

enum ViewKind {
    Table, // a view which can depend on the past
    Join, // take the product of multiple views and filter the results
    Union, // take the union of multiple views
    Aggregate, // group one view by the contents of another and run some primitive on the groups
    Primitive, // a built-in function, represented as a view with one or more non-Data fields
}

enum FieldKind {
    Data, // a normal field
    ScalarInput, // a field that must be constrained to a single scalar value
    VectorInput, // a field that must be constrained to a single vector value (in an aggregate)
}

enum ConstraintOperation {
    Equal,
    NotEqual,
    LessThan,
    LessThanOrEqual,
    GreaterThan,
    GreaterThanOrEqual,
}<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;
use websocket::{Server, Message, Sender, Receiver};
use websocket::server::sender;
use websocket::stream::WebSocketStream;
use std::collections::{HashMap, BitSet};
use std::io::prelude::*;
use std::fs::OpenOptions;
use std::num::ToPrimitive;
use rustc_serialize::json::{Json, ToJson};

use value::{Value, Tuple};
use index;
use flow::{Changes, FlowState, Flow};
use compiler::{compile, World};

trait FromJson {
    fn from_json(json: &Json, next_eid: &mut usize) -> Self;
}

impl ToJson for Value {
    fn to_json(&self) -> Json {
        match *self {
            Value::Bool(bool) => Json::Boolean(bool),
            Value::String(ref string) => Json::String(string.clone()),
            Value::Float(float) => Json::F64(float),
            Value::Tuple(ref tuple) => tuple.to_json(),
            Value::Relation(ref relation) => Json::Object(vec![
                ("relation".to_string(), relation.iter().map(ToJson::to_json).collect::<Vec<_>>().to_json())
                ].into_iter().collect()),
        }
    }
}

impl FromJson for Value {
    fn from_json(json: &Json, next_eid: &mut usize) -> Self {
        match *json {
            Json::Boolean(bool) => Value::Bool(bool),
            Json::String(ref string) => Value::String(string.clone()),
            Json::F64(float) => Value::Float(float),
            Json::I64(int) => Value::Float(int.to_f64().unwrap()),
            Json::U64(uint) => Value::Float(uint.to_f64().unwrap()),
            Json::Array(ref array) => Value::Tuple(array.iter().map(|j| Value::from_json(j, next_eid)).collect()),
            Json::Object(ref object) => {
                assert!(object.len() == 1);
                match object.get("eid") {
                    Some(value) => {
                        assert_eq!(value.as_string().unwrap(), "auto");
                        let eid = next_eid.to_f64().unwrap();
                        *next_eid += 1;
                        Value::Float(eid)
                    }
                    None => {
                        let relation: Vec<Tuple> = FromJson::from_json(&object["relation"], next_eid);
                        Value::Relation(relation.into_iter().collect())
                    }
                }
            },
            _ => panic!("Cannot decode {:?} as Value", json),
        }
    }
}

impl<T: FromJson> FromJson for Vec<T> {
    fn from_json(json: &Json, next_eid: &mut usize) -> Self {
        json.as_array().unwrap().iter().map(|t| FromJson::from_json(t, next_eid)).collect()
    }
}

pub struct Event {
    changes: Changes,
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("changes".to_string(), Json::Object(
                self.changes.iter().map(|&(ref view_id, ref view_changes)| {
                    (view_id.to_string(), Json::Object(vec![
                        ("inserted".to_string(), view_changes.inserted.to_json()),
                        ("removed".to_string(), view_changes.removed.to_json()),
                        ].into_iter().collect()))
                }).collect()))].into_iter().collect())
    }
}

impl FromJson for Event {
    fn from_json(json: &Json, next_eid: &mut usize) -> Self {
        Event{
            changes: json.as_object().unwrap()["changes"]
            .as_object().unwrap().iter().map(|(view_id, view_changes)| {
                (view_id.to_string(), index::Changes{
                    inserted: FromJson::from_json(&view_changes.as_object().unwrap()["inserted"], next_eid),
                    removed: FromJson::from_json(&view_changes.as_object().unwrap()["removed"], next_eid),
                })
            }).collect()
        }
    }
}

struct Instance {
    input: World,
    flow: Flow,
    output: FlowState,
    next_eid: usize,
}

impl Instance {
    pub fn change(&mut self, changes: Changes) -> Changes {
        self.input.change(changes);
        let mut input_clone = self.input.clone();
        let (flow, mut output) = compile(&mut input_clone);
        flow.run(&mut output);
        let changes = flow.changes_since(&output, &self.flow, &self.output);
        self.flow = flow;
        self.output = output;
        changes
    }
}

pub enum ServerEvent {
    Message(String),
    NewClient(sender::Sender<WebSocketStream>),
}

// TODO holy crap why is everything blocking? this is a mess
pub fn serve() -> mpsc::Receiver<ServerEvent> {
    let (event_sender, event_receiver) = mpsc::channel();
    thread::spawn(move || {
        let server = Server::bind("0.0.0.0:2794").unwrap();
        for connection in server {
            let event_sender = event_sender.clone();
            thread::spawn(move || {
                // accept request
                let request = connection.unwrap().read_request().unwrap();
                request.validate().unwrap();
                let response = request.accept();
                let (mut sender, mut receiver) = response.send().unwrap().split();

                let ip = sender.get_mut().peer_addr().unwrap();
                println!("Connection from {}", ip);
                ::std::io::stdout().flush().unwrap(); // TODO is this actually necessary?

                // hand over sender
                event_sender.send(ServerEvent::NewClient(sender)).unwrap();

                // handle messages
                for message in receiver.incoming_messages() {
                    let message = message.unwrap();
                    match message {
                        Message::Text(text) => {
                            event_sender.send(ServerEvent::Message(text)).unwrap();
                        }
                        _ => println!("Unknown message: {:?}", message)
                    }
                }
            });
        }
    });
    event_receiver
}

pub fn run() {
    let empty_world = World{views: HashMap::new()};
    let empty_flow = Flow{nodes: Vec::new()};
    let empty_output = FlowState{outputs: Vec::new(), dirty: BitSet::new()};
    let mut instance = Instance{
        input: empty_world,
        flow: empty_flow.clone(),
        output: empty_output.clone(),
        next_eid: 0,
    };

    time!("reading saved state", {
        let mut events = OpenOptions::new().create(true).open("./events").unwrap();
        let mut old_events = String::new();
        events.read_to_string(&mut old_events).unwrap();
        for line in old_events.lines() {
            let event: Event = {
                let Instance {ref mut next_eid, ..} = instance;
                let json = Json::from_str(&line).unwrap();
                FromJson::from_json(&json, next_eid)
            };
            instance.change(event.changes);
        }
        drop(events);
        });
    let mut events = OpenOptions::new().write(true).append(true).open("./events").unwrap();

    let mut senders: Vec<sender::Sender<_>> = Vec::new();
    let event_receiver = serve();
    for event in event_receiver.iter() {
        match event {
            ServerEvent::NewClient(mut sender) => {
                time!("sending initial state", {
                    let changes = instance.flow.changes_since(&instance.output, &empty_flow, &empty_output);
                    let text = format!("{}", Event{changes: changes}.to_json());
                    match sender.send_message(Message::Text(text)) {
                        Ok(_) => (),
                        Err(error) => println!("Send error: {}", error),
                    };
                    senders.push(sender)
                })
            }
            ServerEvent::Message(input_text) => {
                time!("sending update", {
                    let input_event: Event = {
                        let Instance {ref mut next_eid, ..} = instance;
                        let json = Json::from_str(&input_text).unwrap();
                        FromJson::from_json(&json, next_eid)
                    };
                    let output_event = Event{changes: instance.change(input_event.changes)};
                    let output_text = format!("{}", output_event.to_json());
                    events.write_all(input_text.as_bytes()).unwrap();
                    events.write_all("\n".as_bytes()).unwrap();
                    events.flush().unwrap();
                    for sender in senders.iter_mut() {
                        match sender.send_message(Message::Text(output_text.clone())) {
                            Ok(_) => (),
                            Err(error) => println!("Send error: {}", error),
                        };
                    }
                })
            }
        }
    }
}
<commit_msg>usize -> u64<commit_after>use std::thread;
use std::sync::mpsc;
use websocket::{Server, Message, Sender, Receiver};
use websocket::server::sender;
use websocket::stream::WebSocketStream;
use std::collections::{HashMap, BitSet};
use std::io::prelude::*;
use std::fs::OpenOptions;
use std::num::ToPrimitive;
use rustc_serialize::json::{Json, ToJson};

use value::{Value, Tuple};
use index;
use flow::{Changes, FlowState, Flow};
use compiler::{compile, World};

trait FromJson {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self;
}

impl ToJson for Value {
    fn to_json(&self) -> Json {
        match *self {
            Value::Bool(bool) => Json::Boolean(bool),
            Value::String(ref string) => Json::String(string.clone()),
            Value::Float(float) => Json::F64(float),
            Value::Tuple(ref tuple) => tuple.to_json(),
            Value::Relation(ref relation) => Json::Object(vec![
                ("relation".to_string(), relation.iter().map(ToJson::to_json).collect::<Vec<_>>().to_json())
                ].into_iter().collect()),
        }
    }
}

impl FromJson for Value {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        match *json {
            Json::Boolean(bool) => Value::Bool(bool),
            Json::String(ref string) => Value::String(string.clone()),
            Json::F64(float) => Value::Float(float),
            Json::I64(int) => Value::Float(int.to_f64().unwrap()),
            Json::U64(uint) => Value::Float(uint.to_f64().unwrap()),
            Json::Array(ref array) => Value::Tuple(array.iter().map(|j| Value::from_json(j, next_eid)).collect()),
            Json::Object(ref object) => {
                assert!(object.len() == 1);
                match object.get("eid") {
                    Some(value) => {
                        assert_eq!(value.as_string().unwrap(), "auto");
                        let eid = next_eid.to_f64().unwrap();
                        *next_eid += 1;
                        Value::Float(eid)
                    }
                    None => {
                        let relation: Vec<Tuple> = FromJson::from_json(&object["relation"], next_eid);
                        Value::Relation(relation.into_iter().collect())
                    }
                }
            },
            _ => panic!("Cannot decode {:?} as Value", json),
        }
    }
}

impl<T: FromJson> FromJson for Vec<T> {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        json.as_array().unwrap().iter().map(|t| FromJson::from_json(t, next_eid)).collect()
    }
}

pub struct Event {
    changes: Changes,
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        Json::Object(vec![
            ("changes".to_string(), Json::Object(
                self.changes.iter().map(|&(ref view_id, ref view_changes)| {
                    (view_id.to_string(), Json::Object(vec![
                        ("inserted".to_string(), view_changes.inserted.to_json()),
                        ("removed".to_string(), view_changes.removed.to_json()),
                        ].into_iter().collect()))
                }).collect()))].into_iter().collect())
    }
}

impl FromJson for Event {
    fn from_json(json: &Json, next_eid: &mut u64) -> Self {
        Event{
            changes: json.as_object().unwrap()["changes"]
            .as_object().unwrap().iter().map(|(view_id, view_changes)| {
                (view_id.to_string(), index::Changes{
                    inserted: FromJson::from_json(&view_changes.as_object().unwrap()["inserted"], next_eid),
                    removed: FromJson::from_json(&view_changes.as_object().unwrap()["removed"], next_eid),
                })
            }).collect()
        }
    }
}

struct Instance {
    input: World,
    flow: Flow,
    output: FlowState,
    next_eid: u64,
}

impl Instance {
    pub fn change(&mut self, changes: Changes) -> Changes {
        self.input.change(changes);
        let mut input_clone = self.input.clone();
        let (flow, mut output) = compile(&mut input_clone);
        flow.run(&mut output);
        let changes = flow.changes_since(&output, &self.flow, &self.output);
        self.flow = flow;
        self.output = output;
        changes
    }
}

pub enum ServerEvent {
    Message(String),
    NewClient(sender::Sender<WebSocketStream>),
}

// TODO holy crap why is everything blocking? this is a mess
pub fn serve() -> mpsc::Receiver<ServerEvent> {
    let (event_sender, event_receiver) = mpsc::channel();
    thread::spawn(move || {
        let server = Server::bind("0.0.0.0:2794").unwrap();
        for connection in server {
            let event_sender = event_sender.clone();
            thread::spawn(move || {
                // accept request
                let request = connection.unwrap().read_request().unwrap();
                request.validate().unwrap();
                let response = request.accept();
                let (mut sender, mut receiver) = response.send().unwrap().split();

                let ip = sender.get_mut().peer_addr().unwrap();
                println!("Connection from {}", ip);
                ::std::io::stdout().flush().unwrap(); // TODO is this actually necessary?

                // hand over sender
                event_sender.send(ServerEvent::NewClient(sender)).unwrap();

                // handle messages
                for message in receiver.incoming_messages() {
                    let message = message.unwrap();
                    match message {
                        Message::Text(text) => {
                            event_sender.send(ServerEvent::Message(text)).unwrap();
                        }
                        _ => println!("Unknown message: {:?}", message)
                    }
                }
            });
        }
    });
    event_receiver
}

pub fn run() {
    let empty_world = World{views: HashMap::new()};
    let empty_flow = Flow{nodes: Vec::new()};
    let empty_output = FlowState{outputs: Vec::new(), dirty: BitSet::new()};
    let mut instance = Instance{
        input: empty_world,
        flow: empty_flow.clone(),
        output: empty_output.clone(),
        next_eid: 0,
    };

    time!("reading saved state", {
        let mut events = OpenOptions::new().create(true).open("./events").unwrap();
        let mut old_events = String::new();
        events.read_to_string(&mut old_events).unwrap();
        for line in old_events.lines() {
            let event: Event = {
                let Instance {ref mut next_eid, ..} = instance;
                let json = Json::from_str(&line).unwrap();
                FromJson::from_json(&json, next_eid)
            };
            instance.change(event.changes);
        }
        drop(events);
        });
    let mut events = OpenOptions::new().write(true).append(true).open("./events").unwrap();

    let mut senders: Vec<sender::Sender<_>> = Vec::new();
    let event_receiver = serve();
    for event in event_receiver.iter() {
        match event {
            ServerEvent::NewClient(mut sender) => {
                time!("sending initial state", {
                    let changes = instance.flow.changes_since(&instance.output, &empty_flow, &empty_output);
                    let text = format!("{}", Event{changes: changes}.to_json());
                    match sender.send_message(Message::Text(text)) {
                        Ok(_) => (),
                        Err(error) => println!("Send error: {}", error),
                    };
                    senders.push(sender)
                })
            }
            ServerEvent::Message(input_text) => {
                time!("sending update", {
                    let input_event: Event = {
                        let Instance {ref mut next_eid, ..} = instance;
                        let json = Json::from_str(&input_text).unwrap();
                        FromJson::from_json(&json, next_eid)
                    };
                    let output_event = Event{changes: instance.change(input_event.changes)};
                    let output_text = format!("{}", output_event.to_json());
                    events.write_all(input_text.as_bytes()).unwrap();
                    events.write_all("\n".as_bytes()).unwrap();
                    events.flush().unwrap();
                    for sender in senders.iter_mut() {
                        match sender.send_message(Message::Text(output_text.clone())) {
                            Ok(_) => (),
                            Err(error) => println!("Send error: {}", error),
                        };
                    }
                })
            }
        }
    }
}
<|endoftext|>


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

pub mod array;
pub mod array_data;
pub mod bitmap;
pub mod buffer;
pub mod builder;
pub mod csv;
pub mod datatypes;
pub mod error;
pub mod memory;
pub mod record_batch;
pub mod tensor;
<commit_msg>ARROW-4586: [Rust] Remove arrow/mod.rs as it is not needed<commit_after><|endoftext|>


<commit_before>extern crate cairo;
use self::cairo::MatrixTrait;

use std::f64::consts::*;

use parse_transform::*;

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

    #[test]
    fn parses_numbers () {
        assert_eq! (parse_Num ("0"),          Ok (0.0));
        assert_eq! (parse_Num ("12345"),      Ok (12345.0));
        assert_eq! (parse_Num ("-123"),       Ok (-123.0));
        assert_eq! (parse_Num ("-123.25"),    Ok (-123.25));
        assert_eq! (parse_Num ("123.25"),     Ok (123.25));
        assert_eq! (parse_Num ("-.25"),       Ok (-0.25));
        assert_eq! (parse_Num (".25"),        Ok (0.25));
        assert_eq! (parse_Num ("-25."),       Ok (-25.0));
        assert_eq! (parse_Num ("25."),        Ok (25.0));
        assert_eq! (parse_Num ("22.5e1"),     Ok (225.0));
        assert_eq! (parse_Num ("-22.5e1"),    Ok (-225.0));
        assert_eq! (parse_Num ("-123.45e2"),  Ok (-12345.0));
        assert_eq! (parse_Num ("123.45E2"),   Ok (12345.0));
        assert_eq! (parse_Num ("-123.25e-2"), Ok (-1.2325));
        assert_eq! (parse_Num ("123.25E-2"),  Ok (1.2325));
    }

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_Matrix ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_Translate ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1, -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale () {
        assert_eq! (parse_Scale ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
    }

    fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
        let angle = angle_degrees * PI / 180.0;

        let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

        let mut r = cairo::Matrix::identity ();
        r.rotate (angle);
        m = cairo::Matrix::multiply (&r, &m);

        m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
        m
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_Rotate ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_Rotate ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_Rotate ("rotate (30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x () {
        assert_eq! (parse_SkewX ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    fn parses_skew_y () {
        assert_eq! (parse_SkewY ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_TransformList ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_TransformList ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_TransformList ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<commit_msg>transform.rs: New public function parse_transform()<commit_after>extern crate lalrpop_util;

extern crate cairo;
use self::cairo::MatrixTrait;

use std::f64::consts::*;

use parse_transform::*;

use error::*;
use parsers::ParseError;

pub fn parse_transform (s: &str) -> Result <cairo::Matrix, AttributeError> {
    let r = parse_TransformList (s);

    match r {
        Ok (m) => {
            m.try_invert ().map (|_| m)
                .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
        },

        Err (e) => {
            Err (AttributeError::Parse (ParseError::new (format! ("{:?}", e))))
        }
    }
}

fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity ();
    r.rotate (angle);
    m = cairo::Matrix::multiply (&r, &m);

    m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

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

    #[test]
    fn parses_valid_transform () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }

    #[test]
    fn syntax_error_yields_parse_error () {
        match parse_transform ("foo") {
            Err (AttributeError::Parse (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("matrix (1 2 3 4 5)") {
            Err (AttributeError::Parse (_)) => {},
            _ => { panic! (); }
        }
    }

    #[test]
    fn invalid_transform_yields_value_error () {
        match parse_transform ("matrix (0 0 0 0 0 0)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), translate (10, 10)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), skewX (90)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }
    }
}

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

    #[test]
    fn parses_numbers () {
        assert_eq! (parse_Num ("0"),          Ok (0.0));
        assert_eq! (parse_Num ("12345"),      Ok (12345.0));
        assert_eq! (parse_Num ("-123"),       Ok (-123.0));
        assert_eq! (parse_Num ("-123.25"),    Ok (-123.25));
        assert_eq! (parse_Num ("123.25"),     Ok (123.25));
        assert_eq! (parse_Num ("-.25"),       Ok (-0.25));
        assert_eq! (parse_Num (".25"),        Ok (0.25));
        assert_eq! (parse_Num ("-25."),       Ok (-25.0));
        assert_eq! (parse_Num ("25."),        Ok (25.0));
        assert_eq! (parse_Num ("22.5e1"),     Ok (225.0));
        assert_eq! (parse_Num ("-22.5e1"),    Ok (-225.0));
        assert_eq! (parse_Num ("-123.45e2"),  Ok (-12345.0));
        assert_eq! (parse_Num ("123.45E2"),   Ok (12345.0));
        assert_eq! (parse_Num ("-123.25e-2"), Ok (-1.2325));
        assert_eq! (parse_Num ("123.25E-2"),  Ok (1.2325));
    }

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_Matrix ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_Translate ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1, -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale () {
        assert_eq! (parse_Scale ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_Rotate ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_Rotate ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_Rotate ("rotate (30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x () {
        assert_eq! (parse_SkewX ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    fn parses_skew_y () {
        assert_eq! (parse_SkewY ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_TransformList ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_TransformList ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_TransformList ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<|endoftext|>


<commit_before>use std::string::String;
use std::slice::Iter;

pub struct MessageList {
    messages: Vec<Message>,
}

pub enum MessageType {
    Info,
    Error,
}

pub struct Message {
    text: String,
    ty: MessageType,
}

impl Message {
    pub fn text(&self) -> &str {
        &self.text
    }

    pub fn ty(&self) -> &MessageType {
        &self.ty
    }
}

impl MessageList {

    pub fn new() -> MessageList {
        MessageList { messages: vec![] }
    }

    pub fn info(&mut self, text: &str) {
        self.messages.push(Message { text: String::from_str(text), ty: MessageType::Info });
    }

    pub fn error(&mut self, text: &str) {
        self.messages.push(Message { text: String::from_str(text), ty: MessageType::Error });
    }

    pub fn items(&self) -> Iter<Message> {
        self.messages.iter()
    }

}
<commit_msg>Insert new messages at the start of the Vec<commit_after>use std::string::String;
use std::slice::Iter;

pub struct MessageList {
    messages: Vec<Message>,
}

pub enum MessageType {
    Info,
    Error,
}

pub struct Message {
    text: String,
    ty: MessageType,
}

impl Message {
    pub fn text(&self) -> &str {
        &self.text
    }

    pub fn ty(&self) -> &MessageType {
        &self.ty
    }
}

impl MessageList {

    pub fn new() -> MessageList {
        MessageList { messages: vec![] }
    }

    pub fn info(&mut self, text: &str) {
        self.messages.insert(0, Message { text: String::from_str(text), ty: MessageType::Info });
    }

    pub fn error(&mut self, text: &str) {
        self.messages.insert(0, Message { text: String::from_str(text), ty: MessageType::Error });
    }

    pub fn items(&self) -> Iter<Message> {
        self.messages.iter()
    }

}
<|endoftext|>


<commit_before>use std::convert::From;

use structs::Point;
use traits::HasValues;

/// Enum describing positions in relation to a point
#[derive(Debug, PartialEq)]
pub enum Direction {
  East,
  Southeast,
  Southwest,
  West,
  Northwest,
  Northeast,
  Up,
  Down,
}

impl Direction {

  /// Get a vector of directions
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::{Direction};
  ///
  /// let vec: Vec<Direction> = Direction::to_vec();
  ///
  /// assert_eq!(Direction::East, vec[0]);
  /// ```
  pub fn to_vec() -> Vec<Direction> {
    vec![
      Direction::East,
      Direction::Southeast,
      Direction::Southwest,
      Direction::West,
      Direction::Northwest,
      Direction::Northeast,
      Direction::Up,
      Direction::Down,
    ]
  }

  /// Return the opposite direction
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::Direction;
  ///
  /// let east: Direction = Direction::East;
  ///
  /// assert_eq!(Direction::West, east.opposite());
  pub fn opposite(&self) -> Direction {

    match self {
      &Direction::East      => Direction::West,
      &Direction::Southeast => Direction::Northwest,
      &Direction::Southwest => Direction::Northeast,
      &Direction::West      => Direction::East,
      &Direction::Northwest => Direction::Southeast,
      &Direction::Northeast => Direction::Southwest,
      &Direction::Up        => Direction::Down,
      &Direction::Down      => Direction::Up,
    }

  }

}

impl <'a, 'b, T> From<(&'a T, &'b T)> for Direction where T: HasValues {

  /// Get the direction from one point to another
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::{Direction, Point};
  ///
  /// let point:     Point = Point::new(1, 2, 5);
  /// let east:      Point = Point::new(2, 2, 5);
  /// let southeast: Point = Point::new(1, 3, 5);
  /// let southwest: Point = Point::new(0, 3, 5);
  /// let west:      Point = Point::new(0, 2, 5);
  /// let northwest: Point = Point::new(1, 1, 5);
  /// let northeast: Point = Point::new(2, 1, 5);
  /// let up:        Point = Point::new(1, 2, 6);
  /// let down:      Point = Point::new(1, 2, 4);
  ///
  /// let from = Direction::from;
  ///
  /// assert_eq!(Direction::East,      from((&point, &east)));
  /// assert_eq!(Direction::Southeast, from((&point, &southeast)));
  /// assert_eq!(Direction::Southwest, from((&point, &southwest)));
  /// assert_eq!(Direction::West,      from((&point, &west)));
  /// assert_eq!(Direction::Northwest, from((&point, &northwest)));
  /// assert_eq!(Direction::Northeast, from((&point, &northeast)));
  /// assert_eq!(Direction::Up,        from((&point, &up)));
  /// assert_eq!(Direction::Down,      from((&point, &down)));
  /// ```
  fn from((p0, p1): (&'a T, &'b T)) -> Direction {

    let p0: Point = p0.values().into();
    let p1: Point = p1.values().into();
    let diff: Point = &p1 - &p0;

    let (dq, dr, dt) = diff.values();

    match dt.signum() {
       1 => return Direction::Up,
      -1 => return Direction::Down,
       _ => (),
    }

    return match (dq.signum(), dr.signum()) {
      ( 1,  0) => Direction::East,
      ( 0,  1) => Direction::Southeast,
      (-1,  1) => Direction::Southwest,
      (-1,  0) => Direction::West,
      ( 0, -1) => Direction::Northwest,
      ( 1, -1) => Direction::Northeast,
      _ => panic!(),
    }

  }

}
<commit_msg>Issue #33: Refactor direction for faster tests<commit_after>use std::convert::From;

use structs::Point;
use traits::HasValues;

use Direction::*;

/// Enum describing positions in relation to a point
#[derive(Debug, PartialEq)]
pub enum Direction {
  East,
  Southeast,
  Southwest,
  West,
  Northwest,
  Northeast,
  Up,
  Down,
}

impl Direction {

  /// Get a vector of directions
  pub fn to_vec() -> Vec<Direction> {
    vec![ East, Southeast, Southwest, West, Northwest, Northeast, Up, Down ]
  }

  /// Return the opposite direction
    pub fn opposite(&self) -> Direction {

    match self {
      &East      => West,
      &Southeast => Northwest,
      &Southwest => Northeast,
      &West      => East,
      &Northwest => Southeast,
      &Northeast => Southwest,
      &Up        => Down,
      &Down      => Up,
    }

  }

}

impl <'a, 'b, T> From<(&'a T, &'b T)> for Direction where T: HasValues {

  /// Get the direction from one point to another
  fn from((p0, p1): (&'a T, &'b T)) -> Direction {

    let p0: Point = p0.values().into();
    let p1: Point = p1.values().into();
    let diff: Point = &p1 - &p0;

    let (dq, dr, dt) = diff.values();

    match dt.signum() {
       1 => return Up,
      -1 => return Down,
       _ => (),
    }

    return match (dq.signum(), dr.signum()) {
      ( 1,  0) => East,
      ( 0,  1) => Southeast,
      (-1,  1) => Southwest,
      (-1,  0) => West,
      ( 0, -1) => Northwest,
      ( 1, -1) => Northeast,
      _ => panic!(),
    }

  }

}

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

  #[test]
  fn to_vec() {
    let vec: Vec<Direction> = Direction::to_vec();

    assert!(vec[0] == East);
    assert!(vec[1] == Southeast);
    assert!(vec[2] == Southwest);
    assert!(vec[3] == West);
    assert!(vec[4] == Northwest);
    assert!(vec[5] == Northeast);
    assert!(vec[6] == Up);
    assert!(vec[7] == Down);
    assert!(vec.len() == 8)
  }

  #[test]
  fn opposite() {
    assert!(East.opposite()      == West);
    assert!(Southeast.opposite() == Northwest);
    assert!(Southwest.opposite() == Northeast);
    assert!(West.opposite()      == East);
    assert!(Northwest.opposite() == Southeast);
    assert!(Northeast.opposite() == Southwest);
    assert!(Up.opposite()        == Down);
    assert!(Down.opposite()      == Up);
  }

  #[test]
  fn from() {
    let point:     Point = Point::new(1, 2, 5);
    let east:      Point = Point::new(2, 2, 5);
    let southeast: Point = Point::new(1, 3, 5);
    let southwest: Point = Point::new(0, 3, 5);
    let west:      Point = Point::new(0, 2, 5);
    let northwest: Point = Point::new(1, 1, 5);
    let northeast: Point = Point::new(2, 1, 5);
    let up:        Point = Point::new(1, 2, 6);
    let down:      Point = Point::new(1, 2, 4);

    let from = Direction::from;

    assert!(East      == from((&point, &east)));
    assert!(Southeast == from((&point, &southeast)));
    assert!(Southwest == from((&point, &southwest)));
    assert!(West      == from((&point, &west)));
    assert!(Northwest == from((&point, &northwest)));
    assert!(Northeast == from((&point, &northeast)));
    assert!(Up        == from((&point, &up)));
    assert!(Down      == from((&point, &down)));
  }
}
<|endoftext|>


<commit_before>// Copyright 2018 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This library provides type-safe and fully-featured `Mutex` and `RwLock`
//! types which wrap a simple raw mutex or rwlock type. This has several
//! benefits: not only does it eliminate a large portion of the work in
//! implementing custom lock types, it also allows users to write code which is
//! generic with regards to different lock implementations.
//!
//! Basic usage of this crate is very straightforward:
//!
//! 1. Create a raw lock type. This should only contain the lock state, not any
//!    data protected by the lock.
//! 2. Implement the `RawMutex` trait for your custom lock type.
//! 3. Export your mutex as a type alias for `lock_api::Mutex`, and
//!    your mutex guard as a type alias for `lock_api::MutexGuard`.
//!    See the [example](#example) below for details.
//!
//! This process is similar for RwLocks, except that two guards need to be
//! exported instead of one. (Or 3 guards if your type supports upgradable read
//! locks, see [extension traits](#extension-traits) below for details)
//!
//! # Example
//!
//! ```
//! use lock_api::{RawMutex, Mutex, GuardSend};
//! use std::sync::atomic::{AtomicBool, Ordering};
//!
//! // 1. Define our raw lock type
//! pub struct RawSpinlock(AtomicBool);
//!
//! // 2. Implement RawMutex for this type
//! unsafe impl RawMutex for RawSpinlock {
//!     const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
//!
//!     // A spinlock guard can be sent to another thread and unlocked there
//!     type GuardMarker = GuardSend;
//!
//!     fn lock(&self) {
//!         // Note: This isn't the best way of implementing a spinlock, but it
//!         // suffices for the sake of this example.
//!         while !self.try_lock() {}
//!     }
//!
//!     fn try_lock(&self) -> bool {
//!         self.0
//!             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
//!             .is_ok()
//!     }
//!
//!     unsafe fn unlock(&self) {
//!         self.0.store(false, Ordering::Release);
//!     }
//! }
//!
//! // 3. Export the wrappers. This are the types that your users will actually use.
//! pub type Spinlock<T> = lock_api::Mutex<RawSpinlock, T>;
//! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>;
//! ```
//!
//! # Extension traits
//!
//! In addition to basic locking & unlocking functionality, you have the option
//! of exposing additional functionality in your lock types by implementing
//! additional traits for it. Examples of extension features include:
//!
//! - Fair unlocking (`RawMutexFair`, `RawRwLockFair`)
//! - Lock timeouts (`RawMutexTimed`, `RawRwLockTimed`)
//! - Downgradable write locks (`RawRwLockDowngradable`)
//! - Recursive read locks (`RawRwLockRecursive`)
//! - Upgradable read locks (`RawRwLockUpgrade`)
//!
//! The `Mutex` and `RwLock` wrappers will automatically expose this additional
//! functionality if the raw lock type implements these extension traits.
//!
//! # Cargo features
//!
//! This crate supports two cargo features:
//!
//! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate.
//! - `nightly`: Enables nightly-only features. At the moment the only such
//!   feature is `const fn` constructors for lock types.

#![no_std]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![cfg_attr(feature = "nightly", feature(const_fn, const_fn_trait_bound))]

#[macro_use]
extern crate scopeguard;

/// Marker type which indicates that the Guard type for a lock is `Send`.
pub struct GuardSend(());

/// Marker type which indicates that the Guard type for a lock is not `Send`.
pub struct GuardNoSend(*mut ());

unsafe impl Sync for GuardNoSend {}

mod mutex;
pub use crate::mutex::*;

mod remutex;
pub use crate::remutex::*;

mod rwlock;
pub use crate::rwlock::*;
<commit_msg>Remove const_fn feature<commit_after>// Copyright 2018 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This library provides type-safe and fully-featured `Mutex` and `RwLock`
//! types which wrap a simple raw mutex or rwlock type. This has several
//! benefits: not only does it eliminate a large portion of the work in
//! implementing custom lock types, it also allows users to write code which is
//! generic with regards to different lock implementations.
//!
//! Basic usage of this crate is very straightforward:
//!
//! 1. Create a raw lock type. This should only contain the lock state, not any
//!    data protected by the lock.
//! 2. Implement the `RawMutex` trait for your custom lock type.
//! 3. Export your mutex as a type alias for `lock_api::Mutex`, and
//!    your mutex guard as a type alias for `lock_api::MutexGuard`.
//!    See the [example](#example) below for details.
//!
//! This process is similar for RwLocks, except that two guards need to be
//! exported instead of one. (Or 3 guards if your type supports upgradable read
//! locks, see [extension traits](#extension-traits) below for details)
//!
//! # Example
//!
//! ```
//! use lock_api::{RawMutex, Mutex, GuardSend};
//! use std::sync::atomic::{AtomicBool, Ordering};
//!
//! // 1. Define our raw lock type
//! pub struct RawSpinlock(AtomicBool);
//!
//! // 2. Implement RawMutex for this type
//! unsafe impl RawMutex for RawSpinlock {
//!     const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
//!
//!     // A spinlock guard can be sent to another thread and unlocked there
//!     type GuardMarker = GuardSend;
//!
//!     fn lock(&self) {
//!         // Note: This isn't the best way of implementing a spinlock, but it
//!         // suffices for the sake of this example.
//!         while !self.try_lock() {}
//!     }
//!
//!     fn try_lock(&self) -> bool {
//!         self.0
//!             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
//!             .is_ok()
//!     }
//!
//!     unsafe fn unlock(&self) {
//!         self.0.store(false, Ordering::Release);
//!     }
//! }
//!
//! // 3. Export the wrappers. This are the types that your users will actually use.
//! pub type Spinlock<T> = lock_api::Mutex<RawSpinlock, T>;
//! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>;
//! ```
//!
//! # Extension traits
//!
//! In addition to basic locking & unlocking functionality, you have the option
//! of exposing additional functionality in your lock types by implementing
//! additional traits for it. Examples of extension features include:
//!
//! - Fair unlocking (`RawMutexFair`, `RawRwLockFair`)
//! - Lock timeouts (`RawMutexTimed`, `RawRwLockTimed`)
//! - Downgradable write locks (`RawRwLockDowngradable`)
//! - Recursive read locks (`RawRwLockRecursive`)
//! - Upgradable read locks (`RawRwLockUpgrade`)
//!
//! The `Mutex` and `RwLock` wrappers will automatically expose this additional
//! functionality if the raw lock type implements these extension traits.
//!
//! # Cargo features
//!
//! This crate supports two cargo features:
//!
//! - `owning_ref`: Allows your lock types to be used with the `owning_ref` crate.
//! - `nightly`: Enables nightly-only features. At the moment the only such
//!   feature is `const fn` constructors for lock types.

#![no_std]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![cfg_attr(feature = "nightly", feature(const_fn_trait_bound))]

#[macro_use]
extern crate scopeguard;

/// Marker type which indicates that the Guard type for a lock is `Send`.
pub struct GuardSend(());

/// Marker type which indicates that the Guard type for a lock is not `Send`.
pub struct GuardNoSend(*mut ());

unsafe impl Sync for GuardNoSend {}

mod mutex;
pub use crate::mutex::*;

mod remutex;
pub use crate::remutex::*;

mod rwlock;
pub use crate::rwlock::*;
<|endoftext|>


<commit_before>use funs::trig::*;
use angle::Angle;
use mat::Mat4;
use num::cast::cast;
use num::consts::pi;
use num::ext::FloatExt;

//
//  Create a perspective projection matrix
//
//  fov is in degrees
//  http://www.opengl.org/wiki/GluPerspective_code
//
#[inline(always)]
pure fn perspective<T:Copy FloatExt>(fovy: Radians<T>, aspectRatio: T, near: T, far: T) -> Mat4<T> {
    let ymax = near * tan(&fovy);
    let xmax = ymax * aspectRatio;
    return frustum(-xmax, xmax, -ymax, ymax, near, far);
}

//
//  Define a view frustrum
//  http://www.felixgers.de/teaching/jogl/perspectiveProjection.html
//  http://www.opengl.org/wiki/GluPerspective_code
//
//  TODO: double check algorithm
//
#[inline(always)]
pure fn frustum<T:Copy FloatExt>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
    let _0: T = cast(0);
    let _2: T = cast(2);
    let neg_1 = cast(-1);

    let c0r0 = (_2 * near) / (right - left);
    let c0r1 = _0;
    let c0r2 = _0;
    let c0r3 = _0;
    let c1r0 = _0;
    let c1r1 = (_2 * near) / (top - bottom);
    let c1r2 = _0;
    let c1r3 = _0;
    let c2r0 = (right + left) / (right - left);
    let c2r1 = (top + bottom) / (top - bottom);
    let c2r2 = -(far + near) / (far - near);
    let c2r3 = neg_1;
    let c3r0 = _0;
    let c3r1 = _0;
    let c3r2 = -(_2 * far * near) / (far - near);
    let c3r3 = _0;

    return Mat4::new(c0r0, c0r1, c0r2, c0r3,
                     c1r0, c1r1, c1r2, c1r3,
                     c2r0, c2r1, c2r2, c2r3,
                     c3r0, c3r1, c3r2, c3r3);
}<commit_msg>Remove returns<commit_after>use funs::trig::*;
use angle::Angle;
use mat::Mat4;
use num::cast::cast;
use num::consts::pi;
use num::ext::FloatExt;

//
//  Create a perspective projection matrix
//
//  fov is in degrees
//  http://www.opengl.org/wiki/GluPerspective_code
//
#[inline(always)]
pure fn perspective<T:Copy FloatExt>(fovy: Radians<T>, aspectRatio: T, near: T, far: T) -> Mat4<T> {
    let ymax = near * tan(&fovy);
    let xmax = ymax * aspectRatio;

    frustum(-xmax, xmax, -ymax, ymax, near, far)
}

//
//  Define a view frustrum
//  http://www.felixgers.de/teaching/jogl/perspectiveProjection.html
//  http://www.opengl.org/wiki/GluPerspective_code
//
//  TODO: double check algorithm
//
#[inline(always)]
pure fn frustum<T:Copy FloatExt>(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Mat4<T> {
    let _0: T = cast(0);
    let _2: T = cast(2);
    let neg_1 = cast(-1);

    let c0r0 = (_2 * near) / (right - left);
    let c0r1 = _0;
    let c0r2 = _0;
    let c0r3 = _0;
    let c1r0 = _0;
    let c1r1 = (_2 * near) / (top - bottom);
    let c1r2 = _0;
    let c1r3 = _0;
    let c2r0 = (right + left) / (right - left);
    let c2r1 = (top + bottom) / (top - bottom);
    let c2r2 = -(far + near) / (far - near);
    let c2r3 = neg_1;
    let c3r0 = _0;
    let c3r1 = _0;
    let c3r2 = -(_2 * far * near) / (far - near);
    let c3r3 = _0;

    Mat4::new(c0r0, c0r1, c0r2, c0r3,
              c1r0, c1r1, c1r2, c1r3,
              c2r0, c2r1, c2r2, c2r3,
              c3r0, c3r1, c3r2, c3r3)
}<|endoftext|>