<commit_before>#![cfg(target_os = "linux")]

pub mod ffi;

use std::fmt;
use std::ptr;
use std::rc::Rc;
use std::ffi::CString;

use error::{RuntimeError, ErrorKind};

use super::x11::ScreenID;

pub struct Connection {
   pub ptr: *mut ffi::xcb_connection_t
}

impl Connection {
   pub fn new(connection_ptr: *mut ffi::xcb_connection_t) -> Self {
      Connection {
         ptr: connection_ptr,
      }
   }

   pub fn screen_of_display(&self, screen_id: &ScreenID) -> Result<Screen, RuntimeError> {
      let setup = unsafe { ffi::xcb_get_setup(self.ptr) };

      if setup == ptr::null() {
         return Err(RuntimeError::new(
            ErrorKind::XCB,
            "Getting XCB connection setup failed".to_string()
         ));
      }

      let mut iter = unsafe {
         ffi::xcb_setup_roots_iterator(setup)
      };

      let mut screen_num = screen_id.screen;

      while screen_num > 0 && iter.rem != 0 {
         unsafe { ffi::xcb_screen_next(&mut iter) };
         screen_num -= 1;
      }

      Ok(Screen::new(iter.data))
   }

   pub fn generate_id(&self) -> Result<XID, RuntimeError> {
      let id = unsafe {
         ffi::xcb_generate_id(self.ptr)
      };

      if id == 0xffffffff {
         return Err(RuntimeError::new(
            ErrorKind::XCB,
            "Generating XID failed".to_string()
         ));
      }

      Ok(XID {
         id: id
      })
   }

   pub fn wait_for_event(&self) -> Option<Event> {
      let event_ptr = unsafe {
         ffi::xcb_wait_for_event(self.ptr)
      };

      if event_ptr.is_null() {
         return None;
      }

      Some(
         Event::new(event_ptr)
      )
   }

   pub fn poll_event_iter(&self) -> EventIterator {
      EventIterator::new(self.ptr)
   }

   pub fn flush(&self) {
      unsafe {
         ffi::xcb_flush(self.ptr);
      }
   }

   pub fn intern_atom(&self, name: &str, existing_only: bool) -> InternAtomCookie {
      let c_name = CString::new(name).unwrap();

      let xcb_cookie = unsafe {
         ffi::xcb_intern_atom(
               self.ptr,
               existing_only as ffi::c_uchar,
               name.len() as ffi::c_ushort,
               c_name.as_ptr()
         )
      };

      InternAtomCookie {
         xcb_cookie: xcb_cookie
      }
   }

   pub fn intern_atom_reply(&self, cookie: &InternAtomCookie) -> InternAtomReply {
      let xcb_reply = unsafe {
         ffi::xcb_intern_atom_reply(
            self.ptr,
            cookie.xcb_cookie,
            ptr::null_mut()
         )
      };

      InternAtomReply {
         xcb_reply: xcb_reply
      }
   }
}

#[derive(PartialEq)]
pub struct XID {
   pub id: ffi::c_uint
}

pub struct Screen {
   pub ptr: *mut ffi::xcb_screen_t
}

impl Screen {
   pub fn new(screen_ptr: *mut ffi::xcb_screen_t) -> Self {
      Screen {
         ptr: screen_ptr,
      }
   }

   getter!(root, ffi::xcb_window_t);

   getter!(default_colormap, ffi::xcb_colormap_t);

   getter!(white_pixel, ffi::c_uint);

   getter!(black_pixel, ffi::c_uint);

   getter!(current_input_masks, ffi::c_uint);

   getter!(width_in_pixels, ffi::c_ushort);

   getter!(height_in_pixels, ffi::c_ushort);

   getter!(width_in_millimeters, ffi::c_ushort);

   getter!(height_in_millimeters, ffi::c_ushort);

   getter!(min_installed_maps, ffi::c_ushort);

   getter!(max_installed_maps, ffi::c_ushort);

   getter!(root_visual, ffi::xcb_visualid_t);

   getter!(backing_stores, ffi::c_uchar);

   getter!(save_unders, ffi::c_uchar);

   getter!(root_depth, ffi::c_uchar);

   getter!(allowed_depths_len, ffi::c_uchar);
}

pub enum EventType {
   KeyPress,
   KeyRelease,
   ButtonPress,
   ButtonRelease,
   MotionNotify,
   EnterNotify,
   LeaveNotify,
   FocusIn,
   FocusOut,
   KeymapNotify,
   Expose,
   ClientMessage,
   ConfigureNotify,
   Empty,
   Unidentified,
}

impl EventType {
   pub fn new(xcb_type: ffi::c_uchar) -> Self {
      match xcb_type {
         ffi::XCB_KEY_PRESS => EventType::KeyPress,
         ffi::XCB_KEY_RELEASE => EventType::KeyRelease,
         ffi::XCB_BUTTON_PRESS => EventType::ButtonPress,
         ffi::XCB_BUTTON_RELEASE => EventType::ButtonRelease,
         ffi::XCB_MOTION_NOTIFY => EventType::MotionNotify,
         ffi::XCB_ENTER_NOTIFY => EventType::EnterNotify,
         ffi::XCB_LEAVE_NOTIFY => EventType::LeaveNotify,
         ffi::XCB_FOCUS_IN => EventType::FocusIn,
         ffi::XCB_FOCUS_OUT => EventType::FocusOut,
         ffi::XCB_KEYMAP_NOTIFY => EventType::KeymapNotify,
         ffi::XCB_EXPOSE => EventType::Expose,
         ffi::XCB_CLIENT_MESSAGE => EventType::ClientMessage,
         ffi::XCB_CONFIGURE_NOTIFY => EventType::ConfigureNotify,
         _ => EventType::Unidentified
      }
   }

   pub fn empty() -> Self {
      EventType::Empty
   }
}

impl fmt::Display for EventType {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      let type_str = match *self {
         EventType::KeyPress => "KeyPress",
         EventType::KeyRelease => "KeyRelease",
         EventType::ButtonPress => "ButtonPress",
         EventType::ButtonRelease => "ButtonRelease",
         EventType::MotionNotify => "MotionNotify",
         EventType::EnterNotify => "EnterNotify",
         EventType::LeaveNotify => "LeaveNotify",
         EventType::FocusIn => "FocusIn",
         EventType::FocusOut => "FocusOut",
         EventType::KeymapNotify => "KeymapNotify",
         EventType::Expose => "Expose",
         EventType::ClientMessage => "ClientMessage",
         EventType::ConfigureNotify => "ConfigureNotify",
         EventType::Empty => "Empty",
         EventType::Unidentified => "Unidentified",
      };

      write!(f, "{}", type_str)
   }
}

pub struct Event {
   pub ptr: *mut ffi::xcb_generic_event_t
}

impl Event {
   pub fn new(event_ptr: *mut ffi::xcb_generic_event_t) -> Self {
      Event {
         ptr: event_ptr,
      }
   }

   pub fn empty() -> Self {
      Event {
         ptr: ptr::null_mut(),
      }
   }

   pub fn event_type(&self) -> EventType {
      if self.ptr.is_null() {
         return EventType::empty();
      }

      EventType::new(
         unsafe {
            (*self.ptr).response_type & !0x80
         }
      )
   }

   pub fn is_close_event(
      &self,
      protocols_atom: &Atom,
      delete_window_atom: &Atom
   ) -> bool {
      unsafe {
         let ptr = self.ptr as *mut ffi::xcb_client_message_event_t;

         let data = (*ptr).data.data32();

         if (*ptr).format != 32 ||
            (*ptr)._type != protocols_atom.xcb_atom ||
            (*data)[0] != delete_window_atom.xcb_atom {
            return false;
         }

         true
      }
   }

   pub fn resize_properties(&self) -> (XID, u32, u32) {
      unsafe {
         let ptr = self.ptr as *mut ffi::xcb_configure_notify_event_t;

         let window_id = XID {
            id: (*ptr).window
         };

         (window_id, (*ptr).width as u32, (*ptr).height as u32)
      }
   }
}

impl Drop for Event {
   fn drop (&mut self) {
      unsafe {
         ffi::free(self.ptr as *mut _);
      }
   }
}

pub struct EventIterator {
   ptr: *mut ffi::xcb_connection_t,
   started: bool,
   completed: bool,
}

impl EventIterator {
   pub fn new(connection_ptr: *mut ffi::xcb_connection_t) -> Self {
      EventIterator {
         ptr: connection_ptr,
         started: false,
         completed: false,
      }
   }
}

impl Iterator for EventIterator {
   type Item = Result<Event, RuntimeError>;

   fn next(&mut self) -> Option<Result<Event, RuntimeError>> {
      if self.completed {
         return None;
      }

      let event_ptr = unsafe {
         if !self.started {
            self.started = true;
            ffi::xcb_poll_for_event(self.ptr)
         } else {
            ffi::xcb_poll_for_queued_event(self.ptr)
         }
      };

      if event_ptr.is_null() {
         self.completed = true;

         if unsafe { ffi::xcb_connection_has_error(self.ptr) } != 0 {
            return Some(
               Err(RuntimeError::new(
                  ErrorKind::XCB,
                  "Poll event failed".to_string()
               ))
            );
         }

         return Some(
            Ok(Event::empty())
         );
      }

      Some(
         Ok(Event::new(event_ptr))
      )
   }
}

pub struct Window {
   pub connection: Rc<Connection>,
   pub window_id: XID,
}

impl Window {
   pub fn create(
      connection: &Rc<Connection>,
      screen: &Screen,
      width: u32,
      height: u32,
   ) -> Result<Self, RuntimeError> {
      let window_id = match connection.generate_id() {
         Ok(window_id) => window_id,
         Err(e) => return Err(e)
      };

      let eventmask = ffi::XCB_EVENT_MASK_EXPOSURE |
         ffi::XCB_EVENT_MASK_KEY_PRESS |
         ffi::XCB_EVENT_MASK_STRUCTURE_NOTIFY;
      let valuelist = [eventmask, 0];
      let valuemask = ffi::XCB_CW_EVENT_MASK;

      let cookie = unsafe {
         ffi::xcb_create_window_checked(
            connection.ptr,
            ffi::XCB_COPY_FROM_PARENT as u8,
            window_id.id,
            screen.root(),
            0, 0,
            width as ffi::c_ushort, height as ffi::c_ushort,
            0,
            ffi::XCB_WINDOW_CLASS_INPUT_OUTPUT as u16,
            screen.root_visual(),
            valuemask,
            valuelist.as_ptr()
         )
      };

      match error_check(connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Create XCB window failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(Window {
         connection: connection.clone(),
         window_id: window_id,
      })
   }

   pub fn map(&self) -> Result<(), RuntimeError> {
      let cookie = unsafe {
         ffi::xcb_map_window_checked(self.connection.ptr, self.window_id.id)
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Mapping XCB window failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(())
   }

   pub fn position(&self, x: u32, y: u32) -> Result<(), RuntimeError> {
      let value_mask = ffi::XCB_CONFIG_WINDOW_X | ffi::XCB_CONFIG_WINDOW_Y;
      let value_list = [x as ffi::c_uint, y as ffi::c_uint, 0];

      let cookie = unsafe {
         ffi::xcb_configure_window_checked(
            self.connection.ptr,
            self.window_id.id,
            value_mask as ffi::c_ushort,
            value_list.as_ptr()
         )
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Setting XCB window position failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(())
   }

   pub fn register_close_event(&self) -> Result<(Atom, Atom), RuntimeError> {
      let protocols_cookie = self.connection.intern_atom("WM_PROTOCOLS", true);
      let protocols_reply = self.connection.intern_atom_reply(&protocols_cookie);

      let delete_window_cookie = self.connection.intern_atom("WM_DELETE_WINDOW", false);
      let delete_window_reply = self.connection.intern_atom_reply(&delete_window_cookie);

      let protocols_atom = protocols_reply.atom();
      let delete_window_atom = delete_window_reply.atom();

      let cookie = unsafe {
         ffi::xcb_change_property_checked(
            self.connection.ptr,
            ffi::XCB_PROP_MODE_REPLACE,
            self.window_id.id,
            protocols_atom.xcb_atom,
            ffi::XCB_ATOM_ATOM,
            32,
            1,
            &delete_window_atom.xcb_atom as *const u32 as *const _
         )
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Registering close event failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok((protocols_atom, delete_window_atom))
   }

   pub fn set_title(&self, title: &str) -> Result<(), RuntimeError> {
      let c_title = CString::new(title).unwrap();

      let cookie = unsafe {
         ffi::xcb_change_property_checked(
            self.connection.ptr,
            ffi::XCB_PROP_MODE_REPLACE,
            self.window_id.id,
            ffi::XCB_ATOM_WM_NAME,
            ffi::XCB_ATOM_STRING,
            8,
            title.len() as ffi::c_uint,
            c_title.as_ptr() as *const _
         )
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Setting window title failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(())
   }
}

fn error_check(
   c: *mut ffi::xcb_connection_t,
   cookie: ffi::xcb_void_cookie_t
) -> Option<ffi::c_uchar> {

   let error = unsafe {
      ffi::xcb_request_check(c, cookie)
   };

   if error != ptr::null_mut() {
      return Some(
         unsafe {
            (*error).error_code
         }
      )
   }

   None
}

impl Drop for Window {
   fn drop (&mut self) {
      unsafe {
         ffi::xcb_destroy_window(
            self.connection.ptr, self.window_id.id
         );
      }
   }
}

pub struct Atom {
   xcb_atom: ffi::xcb_atom_t
}

pub struct InternAtomCookie {
   xcb_cookie: ffi::xcb_intern_atom_cookie_t
}

pub struct InternAtomReply {
   xcb_reply: *mut ffi::xcb_intern_atom_reply_t
}

impl InternAtomReply {
   pub fn atom(&self) -> Atom {
      let xcb_atom = unsafe { (*(self.xcb_reply)).atom };
      Atom {
         xcb_atom: xcb_atom
      }
   }
}
<commit_msg>Purging XCB Empty event type<commit_after>#![cfg(target_os = "linux")]

pub mod ffi;

use std::fmt;
use std::ptr;
use std::rc::Rc;
use std::ffi::CString;

use error::{RuntimeError, ErrorKind};

use super::x11::ScreenID;

pub struct Connection {
   pub ptr: *mut ffi::xcb_connection_t
}

impl Connection {
   pub fn new(connection_ptr: *mut ffi::xcb_connection_t) -> Self {
      Connection {
         ptr: connection_ptr,
      }
   }

   pub fn screen_of_display(&self, screen_id: &ScreenID) -> Result<Screen, RuntimeError> {
      let setup = unsafe { ffi::xcb_get_setup(self.ptr) };

      if setup == ptr::null() {
         return Err(RuntimeError::new(
            ErrorKind::XCB,
            "Getting XCB connection setup failed".to_string()
         ));
      }

      let mut iter = unsafe {
         ffi::xcb_setup_roots_iterator(setup)
      };

      let mut screen_num = screen_id.screen;

      while screen_num > 0 && iter.rem != 0 {
         unsafe { ffi::xcb_screen_next(&mut iter) };
         screen_num -= 1;
      }

      Ok(Screen::new(iter.data))
   }

   pub fn generate_id(&self) -> Result<XID, RuntimeError> {
      let id = unsafe {
         ffi::xcb_generate_id(self.ptr)
      };

      if id == 0xffffffff {
         return Err(RuntimeError::new(
            ErrorKind::XCB,
            "Generating XID failed".to_string()
         ));
      }

      Ok(XID {
         id: id
      })
   }

   pub fn wait_for_event(&self) -> Option<Event> {
      let event_ptr = unsafe {
         ffi::xcb_wait_for_event(self.ptr)
      };

      if event_ptr.is_null() {
         return None;
      }

      Some(
         Event::new(event_ptr)
      )
   }

   pub fn poll_event_iter(&self) -> EventIterator {
      EventIterator::new(self.ptr)
   }

   pub fn flush(&self) {
      unsafe {
         ffi::xcb_flush(self.ptr);
      }
   }

   pub fn intern_atom(&self, name: &str, existing_only: bool) -> InternAtomCookie {
      let c_name = CString::new(name).unwrap();

      let xcb_cookie = unsafe {
         ffi::xcb_intern_atom(
               self.ptr,
               existing_only as ffi::c_uchar,
               name.len() as ffi::c_ushort,
               c_name.as_ptr()
         )
      };

      InternAtomCookie {
         xcb_cookie: xcb_cookie
      }
   }

   pub fn intern_atom_reply(&self, cookie: &InternAtomCookie) -> InternAtomReply {
      let xcb_reply = unsafe {
         ffi::xcb_intern_atom_reply(
            self.ptr,
            cookie.xcb_cookie,
            ptr::null_mut()
         )
      };

      InternAtomReply {
         xcb_reply: xcb_reply
      }
   }
}

#[derive(PartialEq)]
pub struct XID {
   pub id: ffi::c_uint
}

pub struct Screen {
   pub ptr: *mut ffi::xcb_screen_t
}

impl Screen {
   pub fn new(screen_ptr: *mut ffi::xcb_screen_t) -> Self {
      Screen {
         ptr: screen_ptr,
      }
   }

   getter!(root, ffi::xcb_window_t);

   getter!(default_colormap, ffi::xcb_colormap_t);

   getter!(white_pixel, ffi::c_uint);

   getter!(black_pixel, ffi::c_uint);

   getter!(current_input_masks, ffi::c_uint);

   getter!(width_in_pixels, ffi::c_ushort);

   getter!(height_in_pixels, ffi::c_ushort);

   getter!(width_in_millimeters, ffi::c_ushort);

   getter!(height_in_millimeters, ffi::c_ushort);

   getter!(min_installed_maps, ffi::c_ushort);

   getter!(max_installed_maps, ffi::c_ushort);

   getter!(root_visual, ffi::xcb_visualid_t);

   getter!(backing_stores, ffi::c_uchar);

   getter!(save_unders, ffi::c_uchar);

   getter!(root_depth, ffi::c_uchar);

   getter!(allowed_depths_len, ffi::c_uchar);
}

pub enum EventType {
   KeyPress,
   KeyRelease,
   ButtonPress,
   ButtonRelease,
   MotionNotify,
   EnterNotify,
   LeaveNotify,
   FocusIn,
   FocusOut,
   KeymapNotify,
   Expose,
   ClientMessage,
   ConfigureNotify,
   Unidentified,
}

impl EventType {
   pub fn new(xcb_type: ffi::c_uchar) -> Self {
      match xcb_type {
         ffi::XCB_KEY_PRESS => EventType::KeyPress,
         ffi::XCB_KEY_RELEASE => EventType::KeyRelease,
         ffi::XCB_BUTTON_PRESS => EventType::ButtonPress,
         ffi::XCB_BUTTON_RELEASE => EventType::ButtonRelease,
         ffi::XCB_MOTION_NOTIFY => EventType::MotionNotify,
         ffi::XCB_ENTER_NOTIFY => EventType::EnterNotify,
         ffi::XCB_LEAVE_NOTIFY => EventType::LeaveNotify,
         ffi::XCB_FOCUS_IN => EventType::FocusIn,
         ffi::XCB_FOCUS_OUT => EventType::FocusOut,
         ffi::XCB_KEYMAP_NOTIFY => EventType::KeymapNotify,
         ffi::XCB_EXPOSE => EventType::Expose,
         ffi::XCB_CLIENT_MESSAGE => EventType::ClientMessage,
         ffi::XCB_CONFIGURE_NOTIFY => EventType::ConfigureNotify,
         _ => EventType::Unidentified
      }
   }
}

impl fmt::Display for EventType {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      let type_str = match *self {
         EventType::KeyPress => "KeyPress",
         EventType::KeyRelease => "KeyRelease",
         EventType::ButtonPress => "ButtonPress",
         EventType::ButtonRelease => "ButtonRelease",
         EventType::MotionNotify => "MotionNotify",
         EventType::EnterNotify => "EnterNotify",
         EventType::LeaveNotify => "LeaveNotify",
         EventType::FocusIn => "FocusIn",
         EventType::FocusOut => "FocusOut",
         EventType::KeymapNotify => "KeymapNotify",
         EventType::Expose => "Expose",
         EventType::ClientMessage => "ClientMessage",
         EventType::ConfigureNotify => "ConfigureNotify",
         EventType::Unidentified => "Unidentified",
      };

      write!(f, "{}", type_str)
   }
}

pub struct Event {
   pub ptr: *mut ffi::xcb_generic_event_t
}

impl Event {
   pub fn new(event_ptr: *mut ffi::xcb_generic_event_t) -> Self {
      Event {
         ptr: event_ptr,
      }
   }

   pub fn event_type(&self) -> EventType {
      EventType::new(
         unsafe {
            (*self.ptr).response_type & !0x80
         }
      )
   }

   pub fn is_close_event(
      &self,
      protocols_atom: &Atom,
      delete_window_atom: &Atom
   ) -> bool {
      unsafe {
         let ptr = self.ptr as *mut ffi::xcb_client_message_event_t;

         let data = (*ptr).data.data32();

         if (*ptr).format != 32 ||
            (*ptr)._type != protocols_atom.xcb_atom ||
            (*data)[0] != delete_window_atom.xcb_atom {
            return false;
         }

         true
      }
   }

   pub fn resize_properties(&self) -> (XID, u32, u32) {
      unsafe {
         let ptr = self.ptr as *mut ffi::xcb_configure_notify_event_t;

         let window_id = XID {
            id: (*ptr).window
         };

         (window_id, (*ptr).width as u32, (*ptr).height as u32)
      }
   }
}

impl Drop for Event {
   fn drop (&mut self) {
      unsafe {
         ffi::free(self.ptr as *mut _);
      }
   }
}

pub struct EventIterator {
   ptr: *mut ffi::xcb_connection_t,
   started: bool,
}

impl EventIterator {
   pub fn new(connection_ptr: *mut ffi::xcb_connection_t) -> Self {
      EventIterator {
         ptr: connection_ptr,
         started: false,
      }
   }
}

impl Iterator for EventIterator {
   type Item = Result<Event, RuntimeError>;

   fn next(&mut self) -> Option<Result<Event, RuntimeError>> {
      let event_ptr = unsafe {
         if !self.started {
            self.started = true;
            ffi::xcb_poll_for_event(self.ptr)
         } else {
            ffi::xcb_poll_for_queued_event(self.ptr)
         }
      };

      if event_ptr.is_null() {
         if unsafe { ffi::xcb_connection_has_error(self.ptr) } != 0 {
            return Some(
               Err(RuntimeError::new(
                  ErrorKind::XCB,
                  "Poll event failed".to_string()
               ))
            );
         }

         return None;
      }

      Some(
         Ok(Event::new(event_ptr))
      )
   }
}

pub struct Window {
   pub connection: Rc<Connection>,
   pub window_id: XID,
}

impl Window {
   pub fn create(
      connection: &Rc<Connection>,
      screen: &Screen,
      width: u32,
      height: u32,
   ) -> Result<Self, RuntimeError> {
      let window_id = match connection.generate_id() {
         Ok(window_id) => window_id,
         Err(e) => return Err(e)
      };

      let eventmask = ffi::XCB_EVENT_MASK_EXPOSURE |
         ffi::XCB_EVENT_MASK_KEY_PRESS |
         ffi::XCB_EVENT_MASK_STRUCTURE_NOTIFY;
      let valuelist = [eventmask, 0];
      let valuemask = ffi::XCB_CW_EVENT_MASK;

      let cookie = unsafe {
         ffi::xcb_create_window_checked(
            connection.ptr,
            ffi::XCB_COPY_FROM_PARENT as u8,
            window_id.id,
            screen.root(),
            0, 0,
            width as ffi::c_ushort, height as ffi::c_ushort,
            0,
            ffi::XCB_WINDOW_CLASS_INPUT_OUTPUT as u16,
            screen.root_visual(),
            valuemask,
            valuelist.as_ptr()
         )
      };

      match error_check(connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Create XCB window failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(Window {
         connection: connection.clone(),
         window_id: window_id,
      })
   }

   pub fn map(&self) -> Result<(), RuntimeError> {
      let cookie = unsafe {
         ffi::xcb_map_window_checked(self.connection.ptr, self.window_id.id)
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Mapping XCB window failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(())
   }

   pub fn position(&self, x: u32, y: u32) -> Result<(), RuntimeError> {
      let value_mask = ffi::XCB_CONFIG_WINDOW_X | ffi::XCB_CONFIG_WINDOW_Y;
      let value_list = [x as ffi::c_uint, y as ffi::c_uint, 0];

      let cookie = unsafe {
         ffi::xcb_configure_window_checked(
            self.connection.ptr,
            self.window_id.id,
            value_mask as ffi::c_ushort,
            value_list.as_ptr()
         )
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Setting XCB window position failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(())
   }

   pub fn register_close_event(&self) -> Result<(Atom, Atom), RuntimeError> {
      let protocols_cookie = self.connection.intern_atom("WM_PROTOCOLS", true);
      let protocols_reply = self.connection.intern_atom_reply(&protocols_cookie);

      let delete_window_cookie = self.connection.intern_atom("WM_DELETE_WINDOW", false);
      let delete_window_reply = self.connection.intern_atom_reply(&delete_window_cookie);

      let protocols_atom = protocols_reply.atom();
      let delete_window_atom = delete_window_reply.atom();

      let cookie = unsafe {
         ffi::xcb_change_property_checked(
            self.connection.ptr,
            ffi::XCB_PROP_MODE_REPLACE,
            self.window_id.id,
            protocols_atom.xcb_atom,
            ffi::XCB_ATOM_ATOM,
            32,
            1,
            &delete_window_atom.xcb_atom as *const u32 as *const _
         )
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Registering close event failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok((protocols_atom, delete_window_atom))
   }

   pub fn set_title(&self, title: &str) -> Result<(), RuntimeError> {
      let c_title = CString::new(title).unwrap();

      let cookie = unsafe {
         ffi::xcb_change_property_checked(
            self.connection.ptr,
            ffi::XCB_PROP_MODE_REPLACE,
            self.window_id.id,
            ffi::XCB_ATOM_WM_NAME,
            ffi::XCB_ATOM_STRING,
            8,
            title.len() as ffi::c_uint,
            c_title.as_ptr() as *const _
         )
      };

      match error_check(self.connection.ptr, cookie) {
         Some(error_code) => {
            return Err(RuntimeError::new(
               ErrorKind::XCB,
               format!("Setting window title failed: {}", error_code)
            ));
         },
         None => {}
      }

      Ok(())
   }
}

fn error_check(
   c: *mut ffi::xcb_connection_t,
   cookie: ffi::xcb_void_cookie_t
) -> Option<ffi::c_uchar> {

   let error = unsafe {
      ffi::xcb_request_check(c, cookie)
   };

   if error != ptr::null_mut() {
      return Some(
         unsafe {
            (*error).error_code
         }
      )
   }

   None
}

impl Drop for Window {
   fn drop (&mut self) {
      unsafe {
         ffi::xcb_destroy_window(
            self.connection.ptr, self.window_id.id
         );
      }
   }
}

pub struct Atom {
   xcb_atom: ffi::xcb_atom_t
}

pub struct InternAtomCookie {
   xcb_cookie: ffi::xcb_intern_atom_cookie_t
}

pub struct InternAtomReply {
   xcb_reply: *mut ffi::xcb_intern_atom_reply_t
}

impl InternAtomReply {
   pub fn atom(&self) -> Atom {
      let xcb_atom = unsafe { (*(self.xcb_reply)).atom };
      Atom {
         xcb_atom: xcb_atom
      }
   }
}
<|endoftext|>


<commit_before><commit_msg>add test for deserializing room_member<commit_after><|endoftext|>


<commit_before>use crate::{RequestHelper, TestApp};
use cargo_registry::{
    models::ApiToken,
    schema::api_tokens,
    util::errors::TOKEN_FORMAT_ERROR,
    views::{EncodableApiTokenWithToken, EncodableMe},
};
use std::collections::HashSet;

use conduit::{header, StatusCode};
use diesel::prelude::*;

#[derive(Deserialize)]
struct DecodableApiToken {
    name: String,
}

#[derive(Deserialize)]
struct ListResponse {
    api_tokens: Vec<DecodableApiToken>,
}
#[derive(Deserialize)]
struct NewResponse {
    api_token: EncodableApiTokenWithToken,
}
#[derive(Deserialize)]
struct RevokedResponse {}

// Default values used by many tests
static URL: &str = "/api/v1/me/tokens";
static NEW_BAR: &[u8] = br#"{ "api_token": { "name": "bar" } }"#;

#[test]
fn list_logged_out() {
    let (_, anon) = TestApp::init().empty();
    anon.get(URL).assert_forbidden();
}

#[test]
fn list_with_api_token_is_forbidden() {
    let (_, _, _, token) = TestApp::init().with_token();
    token.get(URL).assert_forbidden();
}

#[test]
fn list_empty() {
    let (_, _, user) = TestApp::init().with_user();
    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), 0);
}

#[test]
fn list_tokens() {
    let (app, _, user) = TestApp::init().with_user();
    let id = user.as_model().id;
    let tokens = app.db(|conn| {
        vec![
            assert_ok!(ApiToken::insert(conn, id, "bar")),
            assert_ok!(ApiToken::insert(conn, id, "baz")),
        ]
    });

    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), tokens.len());
    assert_eq!(
        json.api_tokens
            .into_iter()
            .map(|t| t.name)
            .collect::<HashSet<_>>(),
        tokens
            .into_iter()
            .map(|t| t.model.name)
            .collect::<HashSet<_>>()
    );
}

#[test]
fn list_tokens_exclude_revoked() {
    let (app, _, user) = TestApp::init().with_user();
    let id = user.as_model().id;
    let tokens = app.db(|conn| {
        vec![
            assert_ok!(ApiToken::insert(conn, id, "bar")),
            assert_ok!(ApiToken::insert(conn, id, "baz")),
        ]
    });

    // List tokens expecting them all to be there.
    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), tokens.len());

    // Revoke the first token.
    let _json: RevokedResponse = user
        .delete(&format!("/api/v1/me/tokens/{}", tokens[0].model.id))
        .good();

    // Check that we now have one less token being listed.
    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), tokens.len() - 1);
    assert!(json
        .api_tokens
        .iter()
        .find(|token| token.name == tokens[0].model.name)
        .is_none());
}

#[test]
fn create_token_logged_out() {
    let (_, anon) = TestApp::init().empty();
    anon.put(URL, NEW_BAR).assert_forbidden();
}

#[test]
fn create_token_invalid_request() {
    let (_, _, user) = TestApp::init().with_user();
    let invalid = br#"{ "name": "" }"#;
    let response = user.put::<()>(URL, invalid);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "invalid new token request: Error(\"missing field `api_token`\", line: 1, column: 14)" }] })
    );
}

#[test]
fn create_token_no_name() {
    let (_, _, user) = TestApp::init().with_user();
    let empty_name = br#"{ "api_token": { "name": "" } }"#;
    let response = user.put::<()>(URL, empty_name);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "name must have a value" }] })
    );
}

#[test]
fn create_token_long_body() {
    let (_, _, user) = TestApp::init().with_user();
    let too_big = &[5; 5192]; // Send a request with a 5kB body of 5's
    let response = user.put::<()>(URL, too_big);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "max content length is: 2000" }] })
    );
}

#[test]
fn create_token_exceeded_tokens_per_user() {
    let (app, _, user) = TestApp::init().with_user();
    let id = user.as_model().id;
    app.db(|conn| {
        for i in 0..1000 {
            assert_ok!(ApiToken::insert(conn, id, &format!("token {}", i)));
        }
    });
    let response = user.put::<()>(URL, NEW_BAR);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "maximum tokens per user is: 500" }] })
    );
}

#[test]
fn create_token_success() {
    let (app, _, user) = TestApp::init().with_user();

    let json: NewResponse = user.put(URL, NEW_BAR).good();
    assert_eq!(json.api_token.name, "bar");
    assert!(!json.api_token.token.is_empty());

    let tokens: Vec<ApiToken> =
        app.db(|conn| assert_ok!(ApiToken::belonging_to(user.as_model()).load(conn)));
    assert_eq!(tokens.len(), 1);
    assert_eq!(tokens[0].name, "bar");
    assert_eq!(tokens[0].revoked, false);
    assert_eq!(tokens[0].last_used_at, None);
}

#[test]
fn create_token_multiple_have_different_values() {
    let (_, _, user) = TestApp::init().with_user();
    let first: NewResponse = user.put(URL, NEW_BAR).good();
    let second: NewResponse = user.put(URL, NEW_BAR).good();

    assert_ne!(first.api_token.token, second.api_token.token);
}

#[test]
fn create_token_multiple_users_have_different_values() {
    let (app, _, user1) = TestApp::init().with_user();
    let first_token: NewResponse = user1.put(URL, NEW_BAR).good();

    let user2 = app.db_new_user("bar");
    let second_token: NewResponse = user2.put(URL, NEW_BAR).good();

    assert_ne!(first_token.api_token.token, second_token.api_token.token);
}

#[test]
fn cannot_create_token_with_token() {
    let (_, _, _, token) = TestApp::init().with_token();
    let response = token.put::<()>(
        "/api/v1/me/tokens",
        br#"{ "api_token": { "name": "baz" } }"#,
    );
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "cannot use an API token to create a new API token" }] })
    );
}

#[test]
fn revoke_token_non_existing() {
    let (_, _, user) = TestApp::init().with_user();
    let _json: RevokedResponse = user.delete("/api/v1/me/tokens/5").good();
}

#[test]
fn revoke_token_doesnt_revoke_other_users_token() {
    let (app, _, user1, token) = TestApp::init().with_token();
    let user1 = user1.as_model();
    let token = token.as_model();
    let user2 = app.db_new_user("baz");

    // List tokens for first user contains the token
    app.db(|conn| {
        let tokens: Vec<ApiToken> = assert_ok!(ApiToken::belonging_to(user1).load(conn));
        assert_eq!(tokens.len(), 1);
        assert_eq!(tokens[0].name, token.name);
    });

    // Try revoke the token as second user
    let _json: RevokedResponse = user2
        .delete(&format!("/api/v1/me/tokens/{}", token.id))
        .good();

    // List tokens for first user still contains the token
    app.db(|conn| {
        let tokens: Vec<ApiToken> = assert_ok!(ApiToken::belonging_to(user1).load(conn));
        assert_eq!(tokens.len(), 1);
        assert_eq!(tokens[0].name, token.name);
    });
}

#[test]
fn revoke_token_success() {
    let (app, _, user, token) = TestApp::init().with_token();

    // List tokens contains the token
    app.db(|conn| {
        let tokens: Vec<ApiToken> = assert_ok!(ApiToken::belonging_to(user.as_model()).load(conn));
        assert_eq!(tokens.len(), 1);
        assert_eq!(tokens[0].name, token.as_model().name);
    });

    // Revoke the token
    let _json: RevokedResponse = user
        .delete(&format!("/api/v1/me/tokens/{}", token.as_model().id))
        .good();

    // List tokens no longer contains the token
    app.db(|conn| {
        let count = ApiToken::belonging_to(user.as_model())
            .filter(api_tokens::revoked.eq(false))
            .count()
            .get_result(conn);
        assert_eq!(count, Ok(0));
    });
}

#[test]
fn using_token_updates_last_used_at() {
    let url = "/api/v1/me";
    let (app, anon, user, token) = TestApp::init().with_token();

    anon.get(url).assert_forbidden();
    user.get::<EncodableMe>(url).good();
    assert_none!(token.as_model().last_used_at);

    // Use the token once
    token.search("following=1");

    let token: ApiToken =
        app.db(|conn| assert_ok!(ApiToken::belonging_to(user.as_model()).first(conn)));
    assert_some!(token.last_used_at);

    // Would check that it updates the timestamp here, but the timestamp is
    // based on the start of the database transaction so it doesn't work in
    // this test framework.
}

#[test]
fn old_tokens_give_specific_error_message() {
    let url = "/api/v1/me";
    let (_, anon) = TestApp::init().empty();

    let mut request = anon.get_request(url);
    request.header(header::AUTHORIZATION, "oldtoken");
    let response = anon.run::<()>(request);
    assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": TOKEN_FORMAT_ERROR }] })
    );
}
<commit_msg>Address clippy::search_is_some<commit_after>use crate::{RequestHelper, TestApp};
use cargo_registry::{
    models::ApiToken,
    schema::api_tokens,
    util::errors::TOKEN_FORMAT_ERROR,
    views::{EncodableApiTokenWithToken, EncodableMe},
};
use std::collections::HashSet;

use conduit::{header, StatusCode};
use diesel::prelude::*;

#[derive(Deserialize)]
struct DecodableApiToken {
    name: String,
}

#[derive(Deserialize)]
struct ListResponse {
    api_tokens: Vec<DecodableApiToken>,
}
#[derive(Deserialize)]
struct NewResponse {
    api_token: EncodableApiTokenWithToken,
}
#[derive(Deserialize)]
struct RevokedResponse {}

// Default values used by many tests
static URL: &str = "/api/v1/me/tokens";
static NEW_BAR: &[u8] = br#"{ "api_token": { "name": "bar" } }"#;

#[test]
fn list_logged_out() {
    let (_, anon) = TestApp::init().empty();
    anon.get(URL).assert_forbidden();
}

#[test]
fn list_with_api_token_is_forbidden() {
    let (_, _, _, token) = TestApp::init().with_token();
    token.get(URL).assert_forbidden();
}

#[test]
fn list_empty() {
    let (_, _, user) = TestApp::init().with_user();
    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), 0);
}

#[test]
fn list_tokens() {
    let (app, _, user) = TestApp::init().with_user();
    let id = user.as_model().id;
    let tokens = app.db(|conn| {
        vec![
            assert_ok!(ApiToken::insert(conn, id, "bar")),
            assert_ok!(ApiToken::insert(conn, id, "baz")),
        ]
    });

    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), tokens.len());
    assert_eq!(
        json.api_tokens
            .into_iter()
            .map(|t| t.name)
            .collect::<HashSet<_>>(),
        tokens
            .into_iter()
            .map(|t| t.model.name)
            .collect::<HashSet<_>>()
    );
}

#[test]
fn list_tokens_exclude_revoked() {
    let (app, _, user) = TestApp::init().with_user();
    let id = user.as_model().id;
    let tokens = app.db(|conn| {
        vec![
            assert_ok!(ApiToken::insert(conn, id, "bar")),
            assert_ok!(ApiToken::insert(conn, id, "baz")),
        ]
    });

    // List tokens expecting them all to be there.
    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), tokens.len());

    // Revoke the first token.
    let _json: RevokedResponse = user
        .delete(&format!("/api/v1/me/tokens/{}", tokens[0].model.id))
        .good();

    // Check that we now have one less token being listed.
    let json: ListResponse = user.get(URL).good();
    assert_eq!(json.api_tokens.len(), tokens.len() - 1);
    assert!(!json
        .api_tokens
        .iter()
        .any(|token| token.name == tokens[0].model.name));
}

#[test]
fn create_token_logged_out() {
    let (_, anon) = TestApp::init().empty();
    anon.put(URL, NEW_BAR).assert_forbidden();
}

#[test]
fn create_token_invalid_request() {
    let (_, _, user) = TestApp::init().with_user();
    let invalid = br#"{ "name": "" }"#;
    let response = user.put::<()>(URL, invalid);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "invalid new token request: Error(\"missing field `api_token`\", line: 1, column: 14)" }] })
    );
}

#[test]
fn create_token_no_name() {
    let (_, _, user) = TestApp::init().with_user();
    let empty_name = br#"{ "api_token": { "name": "" } }"#;
    let response = user.put::<()>(URL, empty_name);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "name must have a value" }] })
    );
}

#[test]
fn create_token_long_body() {
    let (_, _, user) = TestApp::init().with_user();
    let too_big = &[5; 5192]; // Send a request with a 5kB body of 5's
    let response = user.put::<()>(URL, too_big);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "max content length is: 2000" }] })
    );
}

#[test]
fn create_token_exceeded_tokens_per_user() {
    let (app, _, user) = TestApp::init().with_user();
    let id = user.as_model().id;
    app.db(|conn| {
        for i in 0..1000 {
            assert_ok!(ApiToken::insert(conn, id, &format!("token {}", i)));
        }
    });
    let response = user.put::<()>(URL, NEW_BAR);
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "maximum tokens per user is: 500" }] })
    );
}

#[test]
fn create_token_success() {
    let (app, _, user) = TestApp::init().with_user();

    let json: NewResponse = user.put(URL, NEW_BAR).good();
    assert_eq!(json.api_token.name, "bar");
    assert!(!json.api_token.token.is_empty());

    let tokens: Vec<ApiToken> =
        app.db(|conn| assert_ok!(ApiToken::belonging_to(user.as_model()).load(conn)));
    assert_eq!(tokens.len(), 1);
    assert_eq!(tokens[0].name, "bar");
    assert!(!tokens[0].revoked);
    assert_eq!(tokens[0].last_used_at, None);
}

#[test]
fn create_token_multiple_have_different_values() {
    let (_, _, user) = TestApp::init().with_user();
    let first: NewResponse = user.put(URL, NEW_BAR).good();
    let second: NewResponse = user.put(URL, NEW_BAR).good();

    assert_ne!(first.api_token.token, second.api_token.token);
}

#[test]
fn create_token_multiple_users_have_different_values() {
    let (app, _, user1) = TestApp::init().with_user();
    let first_token: NewResponse = user1.put(URL, NEW_BAR).good();

    let user2 = app.db_new_user("bar");
    let second_token: NewResponse = user2.put(URL, NEW_BAR).good();

    assert_ne!(first_token.api_token.token, second_token.api_token.token);
}

#[test]
fn cannot_create_token_with_token() {
    let (_, _, _, token) = TestApp::init().with_token();
    let response = token.put::<()>(
        "/api/v1/me/tokens",
        br#"{ "api_token": { "name": "baz" } }"#,
    );
    assert_eq!(response.status(), StatusCode::BAD_REQUEST);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "cannot use an API token to create a new API token" }] })
    );
}

#[test]
fn revoke_token_non_existing() {
    let (_, _, user) = TestApp::init().with_user();
    let _json: RevokedResponse = user.delete("/api/v1/me/tokens/5").good();
}

#[test]
fn revoke_token_doesnt_revoke_other_users_token() {
    let (app, _, user1, token) = TestApp::init().with_token();
    let user1 = user1.as_model();
    let token = token.as_model();
    let user2 = app.db_new_user("baz");

    // List tokens for first user contains the token
    app.db(|conn| {
        let tokens: Vec<ApiToken> = assert_ok!(ApiToken::belonging_to(user1).load(conn));
        assert_eq!(tokens.len(), 1);
        assert_eq!(tokens[0].name, token.name);
    });

    // Try revoke the token as second user
    let _json: RevokedResponse = user2
        .delete(&format!("/api/v1/me/tokens/{}", token.id))
        .good();

    // List tokens for first user still contains the token
    app.db(|conn| {
        let tokens: Vec<ApiToken> = assert_ok!(ApiToken::belonging_to(user1).load(conn));
        assert_eq!(tokens.len(), 1);
        assert_eq!(tokens[0].name, token.name);
    });
}

#[test]
fn revoke_token_success() {
    let (app, _, user, token) = TestApp::init().with_token();

    // List tokens contains the token
    app.db(|conn| {
        let tokens: Vec<ApiToken> = assert_ok!(ApiToken::belonging_to(user.as_model()).load(conn));
        assert_eq!(tokens.len(), 1);
        assert_eq!(tokens[0].name, token.as_model().name);
    });

    // Revoke the token
    let _json: RevokedResponse = user
        .delete(&format!("/api/v1/me/tokens/{}", token.as_model().id))
        .good();

    // List tokens no longer contains the token
    app.db(|conn| {
        let count = ApiToken::belonging_to(user.as_model())
            .filter(api_tokens::revoked.eq(false))
            .count()
            .get_result(conn);
        assert_eq!(count, Ok(0));
    });
}

#[test]
fn using_token_updates_last_used_at() {
    let url = "/api/v1/me";
    let (app, anon, user, token) = TestApp::init().with_token();

    anon.get(url).assert_forbidden();
    user.get::<EncodableMe>(url).good();
    assert_none!(token.as_model().last_used_at);

    // Use the token once
    token.search("following=1");

    let token: ApiToken =
        app.db(|conn| assert_ok!(ApiToken::belonging_to(user.as_model()).first(conn)));
    assert_some!(token.last_used_at);

    // Would check that it updates the timestamp here, but the timestamp is
    // based on the start of the database transaction so it doesn't work in
    // this test framework.
}

#[test]
fn old_tokens_give_specific_error_message() {
    let url = "/api/v1/me";
    let (_, anon) = TestApp::init().empty();

    let mut request = anon.get_request(url);
    request.header(header::AUTHORIZATION, "oldtoken");
    let response = anon.run::<()>(request);
    assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": TOKEN_FORMAT_ERROR }] })
    );
}
<|endoftext|>


<commit_before>// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

use v1::Extras;

enum_number! {
    ComponentType {
        I8 = 5120,
        U8 = 5121,
        I16 = 5122,
        U16 = 5123,
        I32 = 5124,
        U32 = 5125,
        F32 = 5126,
        F64 = 5127,
    }
}

enum_string! {
    Kind {
        Scalar = "SCALAR",
        Vec2 = "VEC2",
        Vec3 = "VEC3",
        Vec4 = "VEC4",
        Mat2 = "MAT2",
        Mat3 = "MAT3",
        Mat4 = "MAT4",
    }
}

/// A typed view into a `BufferView`.
#[derive(Debug, Deserialize, Serialize)]
pub struct Accessor<E: Extras> {
    /// The ID of the bufferView.
    #[serde(rename = "bufferView")]
    pub buffer_view: String,

    /// The offset relative to the start of the `BufferView` in bytes.
    ///
    /// This must be a multiple of the size of the data type.
    #[serde(rename = "byteOffset")]
    pub byte_offset: u32,

    /// The stride, in bytes, between attributes referenced by this accessor.
    ///
    /// When this is zero, the attributes are assumed to be tightly packed.
    #[serde(rename = "byteStride")]
    #[serde(default)]
    pub byte_stride: u32,

    /// The data type of components in the attribute.
    #[serde(rename = "componentType")]
    pub component_type: ComponentType,

    /// The number of attributes referenced by this accessor, not to be confused
    /// with the number of bytes or number of components.
    pub count: u32,

    /// Specifies if the attribute is a scalar, vector, or matrix, and the
    /// number of elements in the vector or matrix.
    #[serde(rename = "type")]
    #[serde(default)]
    pub kind: Kind,

    /// Maximum value of each component in this attribute.
    ///
    /// When both min and max arrays are defined, they have the same length. The
    /// length is determined by the value of the type property; it can be 1, 2,
    /// 3, 4, 9, or 16.
    pub max: Option<Vec<f32>>,

    /// Minimum value of each component in this attribute.
    ///
    /// When both min and max arrays are defined, they have the same length. The
    /// length is determined by the value of the type property; it can be 1, 2,
    /// 3, 4, 9, or 16.
    pub min: Option<Vec<f32>>,

    /// Optional user-defined name of this object.
    pub name: Option<String>,

    /// Extension specific data.
    #[serde(default)]
    pub extensions: AccessorExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: <E as Extras>::Accessor,
}

/// Extension specific data for `Accessor`.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct AccessorExtensions {
    #[serde(default)]
    _allow_extra_fields: (),
}

impl Default for ComponentType {
    fn default() -> ComponentType {
        ComponentType::I8
    }
}

impl Default for Kind {
    fn default() -> Kind {
        Kind::Scalar
    }
}

#[cfg(test)]
mod test {
    extern crate serde_json;
    use super::*;
    use v1;

    #[test]
    fn invalid_component_type() {
        let data = r#"{
    "bufferView": "bufferViewWithVertices_id",
    "byteOffset": 0,
    "byteStride": 3,
    "componentType": 5128,
    "count": 1024,
    "type": "SCALAR"
}"#;

        let accessor = serde_json::from_str::<Accessor<v1::extras::Any>>(data);
        assert!(accessor.is_err());
    }

    #[test]
    fn it_deserializes_an_accessor() {
        let data = r#"{
    "bufferView": "bufferViewWithVertices_id",
    "byteOffset": 0,
    "byteStride": 3,
    "componentType": 5126,
    "count": 1024,
    "type": "SCALAR",
    "name": "user-defined accessor name",
    "max": [
        -1.0,
        -1.0,
        -1.0
    ],
    "min": [
        1.0,
        1.0,
        1.0
    ],
    "extensions": {
        "extension_name": {
            "extension specific": "value"
        }
    },
    "extras": {
        "Application specific": "The extra object can contain any properties."
    }
}"#;

        let accessor: Accessor<v1::extras::Any> = serde_json::from_str(data).unwrap();

        assert_eq!("bufferViewWithVertices_id", accessor.buffer_view);
        assert_eq!(0, accessor.byte_offset);
        assert_eq!(3, accessor.byte_stride);
        assert_eq!(ComponentType::F32, accessor.component_type);
        assert_eq!(1024, accessor.count);
        assert_eq!(Kind::Scalar, accessor.kind);
        assert_eq!(3, accessor.max.unwrap().len());
    }
}
<commit_msg>Ditto for v1<commit_after>// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

use v1::Extras;

enum_number! {
    ComponentType {
        I8 = 5120,
        U8 = 5121,
        I16 = 5122,
        U16 = 5123,
        I32 = 5124,
        U32 = 5125,
        F32 = 5126,
        F64 = 5127,
    }
}

enum_string! {
    Kind {
        Scalar = "SCALAR",
        Vec2 = "VEC2",
        Vec3 = "VEC3",
        Vec4 = "VEC4",
        Mat2 = "MAT2",
        Mat3 = "MAT3",
        Mat4 = "MAT4",
    }
}

/// A typed view into a `BufferView`.
#[derive(Debug, Deserialize, Serialize)]
pub struct Accessor<E: Extras> {
    /// The ID of the bufferView.
    #[serde(rename = "bufferView")]
    pub buffer_view: String,

    /// The offset relative to the start of the `BufferView` in bytes.
    ///
    /// This must be a multiple of the size of the data type.
    #[serde(default, rename = "byteOffset")]
    pub byte_offset: u32,

    /// The stride, in bytes, between attributes referenced by this accessor.
    ///
    /// When this is zero, the attributes are assumed to be tightly packed.
    #[serde(rename = "byteStride")]
    #[serde(default)]
    pub byte_stride: u32,

    /// The data type of components in the attribute.
    #[serde(rename = "componentType")]
    pub component_type: ComponentType,

    /// The number of attributes referenced by this accessor, not to be confused
    /// with the number of bytes or number of components.
    pub count: u32,

    /// Specifies if the attribute is a scalar, vector, or matrix, and the
    /// number of elements in the vector or matrix.
    #[serde(rename = "type")]
    #[serde(default)]
    pub kind: Kind,

    /// Maximum value of each component in this attribute.
    ///
    /// When both min and max arrays are defined, they have the same length. The
    /// length is determined by the value of the type property; it can be 1, 2,
    /// 3, 4, 9, or 16.
    pub max: Option<Vec<f32>>,

    /// Minimum value of each component in this attribute.
    ///
    /// When both min and max arrays are defined, they have the same length. The
    /// length is determined by the value of the type property; it can be 1, 2,
    /// 3, 4, 9, or 16.
    pub min: Option<Vec<f32>>,

    /// Optional user-defined name of this object.
    pub name: Option<String>,

    /// Extension specific data.
    #[serde(default)]
    pub extensions: AccessorExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: <E as Extras>::Accessor,
}

/// Extension specific data for `Accessor`.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct AccessorExtensions {
    #[serde(default)]
    _allow_extra_fields: (),
}

impl Default for ComponentType {
    fn default() -> ComponentType {
        ComponentType::I8
    }
}

impl Default for Kind {
    fn default() -> Kind {
        Kind::Scalar
    }
}

#[cfg(test)]
mod test {
    extern crate serde_json;
    use super::*;
    use v1;

    #[test]
    fn invalid_component_type() {
        let data = r#"{
    "bufferView": "bufferViewWithVertices_id",
    "byteOffset": 0,
    "byteStride": 3,
    "componentType": 5128,
    "count": 1024,
    "type": "SCALAR"
}"#;

        let accessor = serde_json::from_str::<Accessor<v1::extras::Any>>(data);
        assert!(accessor.is_err());
    }

    #[test]
    fn it_deserializes_an_accessor() {
        let data = r#"{
    "bufferView": "bufferViewWithVertices_id",
    "byteOffset": 0,
    "byteStride": 3,
    "componentType": 5126,
    "count": 1024,
    "type": "SCALAR",
    "name": "user-defined accessor name",
    "max": [
        -1.0,
        -1.0,
        -1.0
    ],
    "min": [
        1.0,
        1.0,
        1.0
    ],
    "extensions": {
        "extension_name": {
            "extension specific": "value"
        }
    },
    "extras": {
        "Application specific": "The extra object can contain any properties."
    }
}"#;

        let accessor: Accessor<v1::extras::Any> = serde_json::from_str(data).unwrap();

        assert_eq!("bufferViewWithVertices_id", accessor.buffer_view);
        assert_eq!(0, accessor.byte_offset);
        assert_eq!(3, accessor.byte_stride);
        assert_eq!(ComponentType::F32, accessor.component_type);
        assert_eq!(1024, accessor.count);
        assert_eq!(Kind::Scalar, accessor.kind);
        assert_eq!(3, accessor.max.unwrap().len());
    }
}
<|endoftext|>


<commit_before>use super::gl;
use super::Context;
use std::mem;
use std::raw;

pub trait VertexData: Copy {
    type Binder;
}

pub trait VertexAttribBinder {
    type Builder;

    fn build() -> Self::Builder;

    fn bind(&mut self, gl: Context);
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy)]
pub enum DataType {
    BYTE = gl::BYTE as isize,
    UNSIGNED_BYTE = gl::UNSIGNED_BYTE as isize,
    SHORT = gl::SHORT as isize,
    UNSIGNED_SHORT = gl::UNSIGNED_SHORT as isize,
    FIXED = gl::FIXED as isize,
    FLOAT = gl::FLOAT as isize
}
pub use self::DataType::*;

pub trait VertexPrimitive {
    fn gl_type() -> DataType;
}

impl VertexPrimitive for i8 {
    fn gl_type() -> DataType { self::BYTE }
}

impl VertexPrimitive for u8 {
    fn gl_type() -> DataType { self::UNSIGNED_BYTE }
}

impl VertexPrimitive for i16 {
    fn gl_type() -> DataType { self::SHORT }
}

impl VertexPrimitive for u16 {
    fn gl_type() -> DataType { self::UNSIGNED_SHORT }
}

impl VertexPrimitive for f32 {
    fn gl_type() -> DataType { self::FLOAT }
}

pub trait VertexDatum {
    fn gl_type() -> DataType;
    fn components() -> i8;
    fn normalized() -> bool { false }
}

impl<T> VertexDatum for T where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

impl<T> VertexDatum for [T; 1] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

impl<T> VertexDatum for [T; 2] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 2 }
}

impl<T> VertexDatum for [T; 3] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 3 }
}

impl<T> VertexDatum for [T; 4] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 4 }
}

pub trait VertexBytes {
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            mem::transmute(raw::Slice::<Self> {
                data: self,
                len: mem::size_of::<Self>()
            })
        }
    }
}

#[macro_export]
macro_rules! vertex_data {
    ($(
        struct $name:ident {
            $($field_name:ident: $field_type:ty),*
        }
    )+) => {
        mod _glitter_vertex_data {
            $(
                #[allow(non_snake_case)]
                pub mod $name {
                    #[repr(C)]
                    #[derive(Debug, Clone, Copy)]
                    pub struct $name {
                        $($field_name: $field_type),*
                    }

                    pub struct Binder;

                    impl $crate::VertexData for $name {
                        type Binder = Binder;
                    }
                }
            )+
        }

        $(
            #[allow(unused_imports)]
            use self::_glitter_vertex_data::$name::$name;
        )+
    }
}
<commit_msg>Constrain `VertexData::Binder` to `VertexAttribBinder`<commit_after>use super::gl;
use super::Context;
use std::mem;
use std::raw;

pub trait VertexData: Copy {
    type Binder: VertexAttribBinder;
}

pub trait VertexAttribBinder {
    type Builder;

    fn build() -> Self::Builder;

    fn bind(&mut self, gl: Context);
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy)]
pub enum DataType {
    BYTE = gl::BYTE as isize,
    UNSIGNED_BYTE = gl::UNSIGNED_BYTE as isize,
    SHORT = gl::SHORT as isize,
    UNSIGNED_SHORT = gl::UNSIGNED_SHORT as isize,
    FIXED = gl::FIXED as isize,
    FLOAT = gl::FLOAT as isize
}
pub use self::DataType::*;

pub trait VertexPrimitive {
    fn gl_type() -> DataType;
}

impl VertexPrimitive for i8 {
    fn gl_type() -> DataType { self::BYTE }
}

impl VertexPrimitive for u8 {
    fn gl_type() -> DataType { self::UNSIGNED_BYTE }
}

impl VertexPrimitive for i16 {
    fn gl_type() -> DataType { self::SHORT }
}

impl VertexPrimitive for u16 {
    fn gl_type() -> DataType { self::UNSIGNED_SHORT }
}

impl VertexPrimitive for f32 {
    fn gl_type() -> DataType { self::FLOAT }
}

pub trait VertexDatum {
    fn gl_type() -> DataType;
    fn components() -> i8;
    fn normalized() -> bool { false }
}

impl<T> VertexDatum for T where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

impl<T> VertexDatum for [T; 1] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

impl<T> VertexDatum for [T; 2] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 2 }
}

impl<T> VertexDatum for [T; 3] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 3 }
}

impl<T> VertexDatum for [T; 4] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 4 }
}

pub trait VertexBytes {
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            mem::transmute(raw::Slice::<Self> {
                data: self,
                len: mem::size_of::<Self>()
            })
        }
    }
}

#[macro_export]
macro_rules! vertex_data {
    ($(
        struct $name:ident {
            $($field_name:ident: $field_type:ty),*
        }
    )+) => {
        mod _glitter_vertex_data {
            $(
                #[allow(non_snake_case)]
                pub mod $name {
                    #[repr(C)]
                    #[derive(Debug, Clone, Copy)]
                    pub struct $name {
                        $($field_name: $field_type),*
                    }

                    pub struct Binder;

                    impl $crate::VertexData for $name {
                        type Binder = Binder;
                    }
                }
            )+
        }

        $(
            #[allow(unused_imports)]
            use self::_glitter_vertex_data::$name::$name;
        )+
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use vobject::Component;
use toml::Value;
use toml_query::read::TomlValueReadExt;

use libimagstore::store::Entry;
use libimagentryref::reference::Ref;

use error::ContactError as CE;
use error::ContactErrorKind as CEK;
use error::Result;
use util;

/// Trait to be implemented on ::libimagstore::store::Entry
///
/// Based on the functionality from libimagentryref, for fetching the Ical data from disk
pub trait Contact : Ref {

    fn is_contact(&self) -> Result<bool>;

    // getting data

    fn get_contact_data(&self) -> Result<ContactData>;

    // More convenience functionality may follow

}

impl Contact for Entry {

    fn is_contact(&self) -> Result<bool> {
        let location = "contact.marker";
        match self.get_header().read(location)? {
            Some(&Value::Boolean(b)) => Ok(b),
            Some(_) => Err(CE::from_kind(CEK::HeaderTypeError("boolean", location))),
            None    => Ok(false)
        }
    }

    fn get_contact_data(&self) -> Result<ContactData> {
        let component = self
            .fs_file()
            .map_err(From::from)
            .and_then(util::read_to_string)
            .and_then(util::parse)?;

        Ok(ContactData(component))
    }

}

pub struct ContactData(Component);

<commit_msg>Let ContactData be unpacked and derefd<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::ops::Deref;

use vobject::Component;
use toml::Value;
use toml_query::read::TomlValueReadExt;

use libimagstore::store::Entry;
use libimagentryref::reference::Ref;

use error::ContactError as CE;
use error::ContactErrorKind as CEK;
use error::Result;
use util;

/// Trait to be implemented on ::libimagstore::store::Entry
///
/// Based on the functionality from libimagentryref, for fetching the Ical data from disk
pub trait Contact : Ref {

    fn is_contact(&self) -> Result<bool>;

    // getting data

    fn get_contact_data(&self) -> Result<ContactData>;

    // More convenience functionality may follow

}

impl Contact for Entry {

    fn is_contact(&self) -> Result<bool> {
        let location = "contact.marker";
        match self.get_header().read(location)? {
            Some(&Value::Boolean(b)) => Ok(b),
            Some(_) => Err(CE::from_kind(CEK::HeaderTypeError("boolean", location))),
            None    => Ok(false)
        }
    }

    fn get_contact_data(&self) -> Result<ContactData> {
        let component = self
            .fs_file()
            .map_err(From::from)
            .and_then(util::read_to_string)
            .and_then(util::parse)?;

        Ok(ContactData(component))
    }

}

pub struct ContactData(Component);

impl ContactData {

    pub fn into_inner(self) -> Component {
        self.0
    }

}

impl Deref for ContactData {
    type Target = Component;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

<|endoftext|>


<commit_before>extern crate cgmath;
#[macro_use] extern crate enum_primitive;
extern crate time;
extern crate warp_horizon;

mod camera;
mod frontend;
mod input_state;

use cgmath::Vector2;
use time::Duration;
use warp_horizon::Grid;

pub use camera::{Camera};
pub use frontend::{FrontendEvent};
pub use input_state::{InputState, GameButton};

pub struct ClientState {
    main_grid: Grid,
    main_camera: Camera,
    input_state: InputState,
    controller: GameController,
}

impl ClientState {
    pub fn new() -> Self {
        let mut cam = Camera::new(Vector2::new(1280, 720));
        cam.set_position(Vector2::new(0.0, 0.0));
        cam.set_zoom(2);
        cam.set_move_speed(80.0);

        ClientState {
            main_grid: Grid::new(100, 100),
            main_camera: cam,
            input_state: InputState::new(),
            controller: GameController::new(),
        }
    }

    pub fn update(&mut self, delta: Duration, events: &[FrontendEvent]) {
        self.input_state.update(events);
        self.main_camera.update(&self.input_state, delta);
        self.controller.update(&self.input_state, &self.main_camera);
    }

    pub fn main_grid(&self) -> &Grid {
        &self.main_grid
    }

    pub fn main_camera(&self) -> &Camera {
        &self.main_camera
    }

    pub fn controller(&self) -> &GameController {
        &self.controller
    }
}

pub struct GameController {
    selected_tile: Vector2<i32>
}

impl GameController {
    pub fn new() -> Self {
        GameController {
            selected_tile: Vector2::new(0, 0)
        }
    }

    pub fn update(&mut self, input_state: &InputState, camera: &Camera) {
        self.selected_tile = camera.screen_to_world(input_state.mouse_position()).cast();
    }

    pub fn selected_tile(&self) -> Vector2<i32> {
        self.selected_tile
    }
}

#[cfg(test)]
mod tests {
    use cgmath::Vector2;
    use GameController;
    use camera::Camera;
    use input_state::InputState;

    #[test]
    fn controller_selected_tile_returns_correct_tile_after_mouse_move_event() {
        let mut controller = GameController::new();
        let mut input_state = InputState::new();
        input_state.set_mouse_position(Vector2::new(50, 26 + 15));
        let camera = Camera::new(Vector2::new(100, 50));

        controller.update(&input_state, &camera);

        assert_eq!(controller.selected_tile(), Vector2::new(1, 1));
    }
}
<commit_msg>Trivial fix with negative tile coordinates<commit_after>extern crate cgmath;
#[macro_use] extern crate enum_primitive;
extern crate time;
extern crate warp_horizon;

mod camera;
mod frontend;
mod input_state;

use cgmath::Vector2;
use time::Duration;
use warp_horizon::Grid;

pub use camera::{Camera};
pub use frontend::{FrontendEvent};
pub use input_state::{InputState, GameButton};

pub struct ClientState {
    main_grid: Grid,
    main_camera: Camera,
    input_state: InputState,
    controller: GameController,
}

impl ClientState {
    pub fn new() -> Self {
        let mut cam = Camera::new(Vector2::new(1280, 720));
        cam.set_position(Vector2::new(0.0, 0.0));
        cam.set_zoom(2);
        cam.set_move_speed(80.0);

        ClientState {
            main_grid: Grid::new(100, 100),
            main_camera: cam,
            input_state: InputState::new(),
            controller: GameController::new(),
        }
    }

    pub fn update(&mut self, delta: Duration, events: &[FrontendEvent]) {
        self.input_state.update(events);
        self.main_camera.update(&self.input_state, delta);
        self.controller.update(&self.input_state, &self.main_camera);
    }

    pub fn main_grid(&self) -> &Grid {
        &self.main_grid
    }

    pub fn main_camera(&self) -> &Camera {
        &self.main_camera
    }

    pub fn controller(&self) -> &GameController {
        &self.controller
    }
}

pub struct GameController {
    selected_tile: Vector2<i32>
}

impl GameController {
    pub fn new() -> Self {
        GameController {
            selected_tile: Vector2::new(0, 0)
        }
    }

    pub fn update(&mut self, input_state: &InputState, camera: &Camera) {
        let tile_f = camera.screen_to_world(input_state.mouse_position());
        self.selected_tile = Vector2::new(tile_f.x.floor() as i32, tile_f.y.floor() as i32);
    }

    pub fn selected_tile(&self) -> Vector2<i32> {
        self.selected_tile
    }
}

#[cfg(test)]
mod tests {
    use cgmath::Vector2;
    use GameController;
    use camera::Camera;
    use input_state::InputState;

    #[test]
    fn controller_selected_tile_returns_correct_tile_after_mouse_move_event() {
        let mut controller = GameController::new();
        let mut input_state = InputState::new();
        input_state.set_mouse_position(Vector2::new(50, 26 + 15));
        let camera = Camera::new(Vector2::new(100, 50));

        controller.update(&input_state, &camera);

        assert_eq!(controller.selected_tile(), Vector2::new(1, 1));
    }
}
<|endoftext|>


<commit_before>use if_chain::if_chain;
use rustc::hir::def::Res;
use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
use rustc::hir::{AssocItemKind, HirId, ImplItemKind, ImplItemRef, Item, ItemKind, Path};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};

use crate::utils::span_help_and_lint;

declare_clippy_lint! {
    /// **What it does:** Checks methods that contain a `self` argument but don't use it
    ///
    /// **Why is this bad?** It may be clearer to define the method as a static function instead
    /// of an instance method if it doesn't require `self`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// struct A;
    /// impl A {
    ///     fn method(&self) {}
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```rust,ignore
    /// struct A;
    /// impl A {
    ///     fn method() {}
    /// }
    /// ```
    pub UNUSED_SELF,
    complexity,
    "methods that contain a `self` argument but don't use it"
}

declare_lint_pass!(UnusedSelf => [UNUSED_SELF]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &Item) {
        if item.span.from_expansion() {
            return;
        }
        if let ItemKind::Impl(_, _, _, _, None, _, ref impl_item_refs) = item.kind {
            for impl_item_ref in impl_item_refs {
                if_chain! {
                    if let ImplItemRef {
                        kind: AssocItemKind::Method { has_self: true },
                        ..
                    } = impl_item_ref;
                    let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
                    if let ImplItemKind::Method(_, body_id) = &impl_item.kind;
                    then {
                        // println!("Visiting method: {:?}", impl_item);
                        let body = cx.tcx.hir().body(*body_id);
                        let self_param = &body.params[0];
                        let self_hir_id = self_param.pat.hir_id;
                        let visitor = &mut UnusedSelfVisitor {
                            cx,
                            uses_self: false,
                            self_hir_id: &self_hir_id,
                        };
                        visitor.visit_body(body);
                        if !visitor.uses_self {
                            // println!("LINTING SPAN: {:?}", &self_param.span);
                            span_help_and_lint(
                                cx,
                                UNUSED_SELF,
                                self_param.span,
                                "unused `self` argument",
                                "consider refactoring to a static method or function",
                            )
                        }
                    }
                }
            }
        };
    }
}

struct UnusedSelfVisitor<'a, 'tcx> {
    cx: &'a LateContext<'a, 'tcx>,
    uses_self: bool,
    self_hir_id: &'a HirId,
}

impl<'a, 'tcx> Visitor<'tcx> for UnusedSelfVisitor<'a, 'tcx> {
    fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
        if self.uses_self {
            // This function already uses `self`
            return;
        }
        if let Res::Local(hir_id) = &path.res {
            self.uses_self = self.self_hir_id == hir_id
        }
        walk_path(self, path);
    }

    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::All(&self.cx.tcx.hir())
    }
}
<commit_msg>Remove prints<commit_after>use if_chain::if_chain;
use rustc::hir::def::Res;
use rustc::hir::intravisit::{walk_path, NestedVisitorMap, Visitor};
use rustc::hir::{AssocItemKind, HirId, ImplItemKind, ImplItemRef, Item, ItemKind, Path};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};

use crate::utils::span_help_and_lint;

declare_clippy_lint! {
    /// **What it does:** Checks methods that contain a `self` argument but don't use it
    ///
    /// **Why is this bad?** It may be clearer to define the method as a static function instead
    /// of an instance method if it doesn't require `self`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// struct A;
    /// impl A {
    ///     fn method(&self) {}
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```rust,ignore
    /// struct A;
    /// impl A {
    ///     fn method() {}
    /// }
    /// ```
    pub UNUSED_SELF,
    complexity,
    "methods that contain a `self` argument but don't use it"
}

declare_lint_pass!(UnusedSelf => [UNUSED_SELF]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &Item) {
        if item.span.from_expansion() {
            return;
        }
        if let ItemKind::Impl(_, _, _, _, None, _, ref impl_item_refs) = item.kind {
            for impl_item_ref in impl_item_refs {
                if_chain! {
                    if let ImplItemRef {
                        kind: AssocItemKind::Method { has_self: true },
                        ..
                    } = impl_item_ref;
                    let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
                    if let ImplItemKind::Method(_, body_id) = &impl_item.kind;
                    then {
                        let body = cx.tcx.hir().body(*body_id);
                        let self_param = &body.params[0];
                        let self_hir_id = self_param.pat.hir_id;
                        let visitor = &mut UnusedSelfVisitor {
                            cx,
                            uses_self: false,
                            self_hir_id: &self_hir_id,
                        };
                        visitor.visit_body(body);
                        if !visitor.uses_self {
                            span_help_and_lint(
                                cx,
                                UNUSED_SELF,
                                self_param.span,
                                "unused `self` argument",
                                "consider refactoring to a static method or function",
                            )
                        }
                    }
                }
            }
        };
    }
}

struct UnusedSelfVisitor<'a, 'tcx> {
    cx: &'a LateContext<'a, 'tcx>,
    uses_self: bool,
    self_hir_id: &'a HirId,
}

impl<'a, 'tcx> Visitor<'tcx> for UnusedSelfVisitor<'a, 'tcx> {
    fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
        if self.uses_self {
            // This function already uses `self`
            return;
        }
        if let Res::Local(hir_id) = &path.res {
            self.uses_self = self.self_hir_id == hir_id
        }
        walk_path(self, path);
    }

    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::All(&self.cx.tcx.hir())
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Christopher Schröder, Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::ptr;
use std::slice;
use std::ffi;

use htslib;

pub struct Record {
    pub inner: *mut htslib::vcf::bcf1_t,
    pub header: *mut htslib::vcf::bcf_hdr_t,
    buffer: *mut ::libc::c_void,
}

impl Record {
    pub fn new() -> Self {
        let inner = unsafe { htslib::vcf::bcf_init() };
        Record { inner: inner, header: ptr::null_mut(), buffer: ptr::null_mut() }
    }

    #[inline]
    fn inner(&self) -> htslib::vcf::bcf1_t {
        unsafe { *self.inner }
    }

    pub fn rid(&self) -> Option<u32> {
        match self.inner().rid {
            -1  => None,
            rid => Some(rid as u32)
        }
    }

    // 0-based position.
    pub fn pos(&self) -> u32 {
        self.inner().pos as u32
    }

    pub fn alleles(&self) -> Vec<&[u8]> {
        unsafe { htslib::vcf::bcf_unpack(self.inner, htslib::vcf::BCF_UN_STR) };
        let n = self.inner().n_allele as usize;
        let dec = self.inner().d;
        let alleles = unsafe { slice::from_raw_parts(dec.allele, n) };
        (0..n).map(|i| unsafe { ffi::CStr::from_ptr(alleles[i]).to_bytes() }).collect()
    }

    pub fn qual(&self) -> f32 {
        self.inner().qual
    }

    /// Get the value of the given info tag.
    pub fn info<'a>(&'a mut self, tag: &'a [u8]) -> Info {
        Info { record: self, tag: tag }
    }

    /// Get the value of the given format tag for each sample.
    pub fn format<'a>(&'a mut self, tag: &'a [u8]) -> Format {
        Format { record: self, tag: tag }
    }
}

impl Drop for Record {
    fn drop(&mut self) {
        if !self.buffer.is_null() {
            unsafe { ::libc::free(self.buffer) };
        }
        unsafe { htslib::vcf::bcf_destroy(self.inner) };
    }
}

pub struct Info<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
}

impl<'a> Info<'a> {
    fn data(&mut self, data_type: i32) -> Result<(usize, i32), InfoError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_info_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(InfoError::UndefinedTag),
            -2 => Err(InfoError::UnexpectedType),
            -3 => Err(InfoError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<&[i32], InfoError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut i32, n) }
        })
    }

    pub fn float(&mut self) -> Result<&[f32], InfoError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut f32, n) }
        })
    }

    pub fn flag(&mut self) -> Result<bool, InfoError> {
        self.data(htslib::vcf::BCF_HT_FLAG).map(|(_, ret)| {
            ret == 1
        })
    }

    pub fn string(&mut self) -> Result<&[u8], InfoError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(_, ret)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut u8, ret as usize) }
        })
    }
}

// TODO implement format.
pub struct Format<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
}

impl<'a> Format<'a> {
    fn data(&mut self, data_type: i32) -> Result<(usize, i32), InfoError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_format_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(InfoError::UndefinedTag),
            -2 => Err(InfoError::UnexpectedType),
            -3 => Err(InfoError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<&[i32], InfoError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut i32, n) }
        })
    }

    pub fn float(&mut self) -> Result<&[f32], InfoError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut f32, n) }
        })
    }
}

pub enum InfoError {
    UndefinedTag,
    UnexpectedType,
    MissingTag,
}
<commit_msg>Fixed author line.<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::ptr;
use std::slice;
use std::ffi;

use htslib;

pub struct Record {
    pub inner: *mut htslib::vcf::bcf1_t,
    pub header: *mut htslib::vcf::bcf_hdr_t,
    buffer: *mut ::libc::c_void,
}

impl Record {
    pub fn new() -> Self {
        let inner = unsafe { htslib::vcf::bcf_init() };
        Record { inner: inner, header: ptr::null_mut(), buffer: ptr::null_mut() }
    }

    #[inline]
    fn inner(&self) -> htslib::vcf::bcf1_t {
        unsafe { *self.inner }
    }

    pub fn rid(&self) -> Option<u32> {
        match self.inner().rid {
            -1  => None,
            rid => Some(rid as u32)
        }
    }

    // 0-based position.
    pub fn pos(&self) -> u32 {
        self.inner().pos as u32
    }

    pub fn alleles(&self) -> Vec<&[u8]> {
        unsafe { htslib::vcf::bcf_unpack(self.inner, htslib::vcf::BCF_UN_STR) };
        let n = self.inner().n_allele as usize;
        let dec = self.inner().d;
        let alleles = unsafe { slice::from_raw_parts(dec.allele, n) };
        (0..n).map(|i| unsafe { ffi::CStr::from_ptr(alleles[i]).to_bytes() }).collect()
    }

    pub fn qual(&self) -> f32 {
        self.inner().qual
    }

    /// Get the value of the given info tag.
    pub fn info<'a>(&'a mut self, tag: &'a [u8]) -> Info {
        Info { record: self, tag: tag }
    }

    /// Get the value of the given format tag for each sample.
    pub fn format<'a>(&'a mut self, tag: &'a [u8]) -> Format {
        Format { record: self, tag: tag }
    }
}

impl Drop for Record {
    fn drop(&mut self) {
        if !self.buffer.is_null() {
            unsafe { ::libc::free(self.buffer) };
        }
        unsafe { htslib::vcf::bcf_destroy(self.inner) };
    }
}

pub struct Info<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
}

impl<'a> Info<'a> {
    fn data(&mut self, data_type: i32) -> Result<(usize, i32), InfoError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_info_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(InfoError::UndefinedTag),
            -2 => Err(InfoError::UnexpectedType),
            -3 => Err(InfoError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<&[i32], InfoError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut i32, n) }
        })
    }

    pub fn float(&mut self) -> Result<&[f32], InfoError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut f32, n) }
        })
    }

    pub fn flag(&mut self) -> Result<bool, InfoError> {
        self.data(htslib::vcf::BCF_HT_FLAG).map(|(_, ret)| {
            ret == 1
        })
    }

    pub fn string(&mut self) -> Result<&[u8], InfoError> {
        self.data(htslib::vcf::BCF_HT_STR).map(|(_, ret)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut u8, ret as usize) }
        })
    }
}

// TODO implement format.
pub struct Format<'a> {
    record: &'a mut Record,
    tag: &'a [u8],
}

impl<'a> Format<'a> {
    fn data(&mut self, data_type: i32) -> Result<(usize, i32), InfoError> {
        let mut n: i32 = 0;
        match unsafe {
            htslib::vcf::bcf_get_format_values(
                self.record.header,
                self.record.inner,
                ffi::CString::new(self.tag).unwrap().as_ptr() as *mut i8,
                &mut self.record.buffer,
                &mut n,
                data_type
            )
        } {
            -1 => Err(InfoError::UndefinedTag),
            -2 => Err(InfoError::UnexpectedType),
            -3 => Err(InfoError::MissingTag),
            ret  => Ok((n as usize, ret)),
        }
    }

    pub fn integer(&mut self) -> Result<&[i32], InfoError> {
        self.data(htslib::vcf::BCF_HT_INT).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut i32, n) }
        })
    }

    pub fn float(&mut self) -> Result<&[f32], InfoError> {
        self.data(htslib::vcf::BCF_HT_REAL).map(|(n, _)| {
            unsafe { slice::from_raw_parts(self.record.buffer as *mut f32, n) }
        })
    }
}

pub enum InfoError {
    UndefinedTag,
    UnexpectedType,
    MissingTag,
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate hubris;
extern crate env_logger;
extern crate rustc_serialize;
extern crate docopt;

use docopt::Docopt;
use std::path::PathBuf;

const USAGE: &'static str = r#"
Hubris, version 0.0.1.

  ___ ___      ___.         .__
 /   |   \ __ _\_ |_________|__| ______
/    ~    \  |  \ __ \_  __ \  |/  ___/
\    Y    /  |  / \_\ \  | \/  |\___ \
 \___|_  /|____/|___  /__|  |__/____  >
       \/           \/              \/

Usage:
    hubris <file> [--output=<exe>]
    hubris (-r | --interactive) <file>
    hubris (-s | --server)
    hubris (-h | --help)
    hubris --version

Options:
    -s --server  Launch compiler in server mode.
    -h --help    Show this screen.
    --version    Show version.
"#;

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    flag_output: Option<String>,
    flag_server: bool,
    flag_interactive: bool,
}

fn main() {
    env_logger::init().unwrap();

    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    if args.flag_server {
        hubris::server::server_main();
    } else if args.flag_interactive {
        let repl = hubris::repl::Repl::from_path(&Some(PathBuf::from(args.arg_file))).unwrap();
        repl.start().unwrap();
    } else {
        debug!("main: compiling {} output to {:?}",
               &args.arg_file[..],
               args.arg_file);

        let result = hubris::compile_file(&args.arg_file[..],
                                          args.flag_output.map(|p| PathBuf::from(p)));

        match result {
            Err(e) => panic!("failed with {:?}", e),
            Ok(_) => {}
        }
    }
}
<commit_msg>Interactive no longer panics when file doesn't exist<commit_after>#[macro_use]
extern crate log;
extern crate hubris;
extern crate env_logger;
extern crate rustc_serialize;
extern crate docopt;

use docopt::Docopt;
use std::path::PathBuf;

const USAGE: &'static str = r#"
Hubris, version 0.0.1.

  ___ ___      ___.         .__
 /   |   \ __ _\_ |_________|__| ______
/    ~    \  |  \ __ \_  __ \  |/  ___/
\    Y    /  |  / \_\ \  | \/  |\___ \
 \___|_  /|____/|___  /__|  |__/____  >
       \/           \/              \/

Usage:
    hubris <file> [--output=<exe>]
    hubris (-r | --interactive) <file>
    hubris (-s | --server)
    hubris (-h | --help)
    hubris --version

Options:
    -s --server  Launch compiler in server mode.
    -h --help    Show this screen.
    --version    Show version.
"#;

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    flag_output: Option<String>,
    flag_server: bool,
    flag_interactive: bool,
}

fn main() {
    env_logger::init().unwrap();

    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    if args.flag_server {
        hubris::server::server_main();
    } else if args.flag_interactive {
        let pb = PathBuf::from(args.arg_file);
        if !pb.is_file() {
            println!("Hubris: file {} does not exist", pb.to_str().unwrap());
            return;
        }
        let repl = hubris::repl::Repl::from_path(&Some(pb)).unwrap();
        repl.start().unwrap();
    } else {
        debug!("main: compiling {} output to {:?}",
               &args.arg_file[..],
               args.arg_file);

        let result = hubris::compile_file(&args.arg_file[..],
                                          args.flag_output.map(|p| PathBuf::from(p)));

        match result {
            Err(e) => panic!("failed with {:?}", e),
            Ok(_) => {}
        }
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate cql_ffi_safe;

use cql_ffi_safe::CassStatement;
use cql_ffi_safe::CassSession;
use cql_ffi_safe::CassCluster;
use cql_ffi_safe::FromCol;
use cql_ffi_safe::CassError;
use cql_ffi_safe::CassString;

static SELECT_QUERY_CMD:&'static str = "SELECT keyspace_name,durable_writes FROM system.schema_keyspaces;";
static CONTACT_POINTS:&'static str = "127.0.0.1,127.0.0.2,127.0.0.3";

fn main() {
    match CassCluster::new().set_contact_points(CONTACT_POINTS) {
        Err(err) => println!("{:?}",err),
        Ok(cluster) => {
            let mut session = CassSession::new();
            session.connect(cluster).wait();
            let mut future = session.execute(&CassStatement::new(SELECT_QUERY_CMD,0));
            future.wait();
            for row in future.get_result().unwrap().iter() {
                let value:Result<bool,CassError> = FromCol::from_col(row.get_column(1));
                let value:Result<CassString,CassError> = row.get_column(0).get_string();
                match value {
                    Ok(ks) => {
                        println!("ks: {:?}",ks);
                        let mut close_future = session.close();
                        close_future.wait();
                    },
                    Err(err) => println!("Error: {:?}", err)
                }
            }
        }
    }
}
<commit_msg>made simple.rs reflect upstream intent<commit_after>#![feature(core)]
extern crate cql_ffi_safe;

use cql_ffi_safe::CassStatement;
use cql_ffi_safe::CassSession;
use cql_ffi_safe::CassCluster;
use cql_ffi_safe::FromCol;
use cql_ffi_safe::CassError;

static SELECT_QUERY_CMD:&'static str = "SELECT keyspace_name,durable_writes FROM system.schema_keyspaces;";
static CONTACT_POINTS:&'static str = "127.0.0.1,127.0.0.2,127.0.0.3";

fn main() {
    match CassCluster::new().set_contact_points(CONTACT_POINTS) {
        Err(err) => println!("{:?}",err),
        Ok(cluster) => {
            let mut session = CassSession::new();
            session.connect(cluster).wait();
            let mut future = session.execute(&CassStatement::new(SELECT_QUERY_CMD,0));
            future.wait();
            for row in future.get_result().unwrap().iter() {
                let value:Result<String,CassError> = FromCol::from_col(row.get_column(0));
                match value {
                    Ok(ks) => {
                        println!("ks: {:?}",ks);
                        let mut close_future = session.close();
                        close_future.wait();
                    },
                    Err(err) => println!("Error: {:?}", err)
                }
            }
        }
    }
}
<|endoftext|>