<commit_before>#![ crate_type = "lib" ]
#![ feature(globs) ]

extern crate libc;
extern crate native;
extern crate core;
extern crate sync;

use libusb::*;
use libusb::libusb_transfer_status::*;
use libusb::libusb_transfer_type::*;
use libc::{c_int, c_void, size_t, malloc, free};
use std::intrinsics;
use std::slice;
use std::result::Result;
use std::comm::{Receiver, Sender};
use std::mem::transmute;
use std::mem::size_of;
use std::vec::Vec;
use std::cell::UnsafeCell;

use sync::Arc;
use std::sync::atomic::{SeqCst, AtomicInt};
use std::task;

pub mod libusb;

pub struct ContextData {
	ctx: *mut libusb_context,
	open_device_count: AtomicInt
}

impl Drop for ContextData {
	fn drop(&mut self) {
		unsafe {
			assert!(self.open_device_count.load(SeqCst) == 0);
			// TODO: make sure backend thread is dead if the last device just closed
			libusb_exit(self.ctx);
		}
	}
}

pub struct Context {
	bx: Arc<UnsafeCell<ContextData>>
}

impl Context {
	pub fn new() -> Context {
		unsafe{
			let mut ctx: *mut libusb_context = intrinsics::init();
			let r = libusb_init(&mut ctx);

			Context{
				bx: Arc::new(UnsafeCell::new(ContextData{
					ctx: ctx,
					open_device_count: AtomicInt::new(0)
				}))
			}
		}
	}

	pub fn ptr(&self) -> *mut libusb_context {
		unsafe{
			(*self.bx.get()).ctx
		}
	}

	pub fn set_debug(&self, level: int) {
		unsafe{
			libusb_set_debug(self.ptr(), level as c_int);
		}
	}

	pub fn list_devices(&self) -> Vec<Device> {
		unsafe{
			let mut list: *mut *mut libusb_device = intrinsics::init();
			let num_devices = libusb_get_device_list(self.ptr(), &mut list);
			let r = slice::raw::mut_buf_as_slice(list, num_devices as uint, |l|{
				l.iter().map(|i| Device{dev: *i, ctx: (*self).clone()}).collect()
			});

			libusb_free_device_list(list, 0);
			r
		}
	}

	pub fn find_by_vid_pid(&self, vid: uint, pid: uint) -> Option<Device> {
		self.list_devices().into_iter().find(|d| {
			let desc = d.descriptor();
			desc.idVendor as uint == vid && desc.idProduct as uint == pid
		})
	}

	fn device_opened(&self) {
		let count = unsafe { &mut (*self.bx.get()).open_device_count };
		let old_count = count.fetch_add(1, SeqCst);

		if old_count == 0 {
			let bx = self.bx.clone();

			fn threadfn(tbx: &Arc<UnsafeCell<ContextData>>) {
				unsafe {
					let ctx = (*tbx.get()).ctx;
					let count = &(*tbx.get()).open_device_count;

					while (count.load(SeqCst) > 0) {
						libusb_handle_events(ctx);
					}
				}
			}

			task::spawn(proc() {threadfn(&bx);});
		}
	}

	fn device_closed(&self) {
		let count = unsafe { &mut (*self.bx.get()).open_device_count };
		count.fetch_sub(1, SeqCst);
	}
}

extern fn rust_usb_callback(transfer: *mut libusb_transfer) {
	unsafe {
		let chan: Box<Sender<()>> = transmute((*transfer).user_data);
		chan.send(());
	}
}

struct TH {
	t: *mut libusb_transfer,
	c: Sender<*mut libusb_transfer>,
}

impl Drop for TH{
	fn drop(&mut self) {
		unsafe {
			free((*self.t).buffer as *mut c_void);
			libusb_free_transfer(self.t);
		}
	}
}

extern fn rust_usb_stream_callback(transfer: *mut libusb_transfer) {
	unsafe {
		let chan: &Sender<*mut libusb_transfer> = transmute((*transfer).user_data);
		chan.send(transfer);
	}
}

impl Clone for Context{
	fn clone(&self) -> Context{
		Context{bx: self.bx.clone()}
	}
}

pub struct Device {
	dev: *mut libusb_device,
	ctx: Context
}

impl Device {
	pub fn descriptor(&self) -> Box<libusb_device_descriptor> {
		unsafe{
			let mut d: Box<libusb_device_descriptor> = box intrinsics::uninit();
			libusb_get_device_descriptor(self.dev, &mut *d as *mut libusb_device_descriptor);
			d
		}
	}

	pub fn bus(&self) -> int {
		unsafe {
			libusb_get_bus_number(self.dev) as int
		}
	}

	pub fn address(&self) -> int {
		unsafe {
			libusb_get_device_address(self.dev) as int
		}
	}

	pub fn open(&self) -> Result<DeviceHandle, int> {
		unsafe {
			let mut handle: *mut libusb_device_handle = intrinsics::uninit();
			let r = libusb_open(self.dev, &mut handle);
			if r == 0 {
				self.ctx.device_opened();
				Ok(DeviceHandle {
					bx: Arc::new(UnsafeCell::new(DeviceHandleData {
						dev: handle,
						ctx: self.ctx.clone()
					}))
				})
			}else{
				Err(r as int)
			}
		}
	}
}

impl Drop for Device {
	fn drop(&mut self) {
		unsafe {
			libusb_unref_device(self.dev);
		}
	}
}

impl Clone for Device {
	fn clone(&self) -> Device {
		unsafe {
			libusb_ref_device(self.dev);
		}
		Device{dev: self.dev, ctx: self.ctx.clone()}
	}
}

struct DeviceHandleData{
	dev: *mut libusb_device_handle,
	ctx: Context
}

impl Drop for DeviceHandleData {
	fn drop(&mut self) {
		unsafe {
			self.ctx.device_closed();
			libusb_close(self.dev);
		}
	}
}

pub struct DeviceHandle {
	bx: Arc<UnsafeCell<DeviceHandleData>>
}

impl DeviceHandle {
	pub fn ptr(&self) -> *mut libusb_device_handle {
		unsafe {
			(*self.bx.get()).dev
		}
	}

	pub fn claim_interface(&self,
		iface_num: uint) {
		unsafe {
		libusb_claim_interface(self.ptr(), iface_num as c_int);
		}
	}

	pub unsafe fn submit_transfer_sync(&self,
		endpoint: u8,
		transfer_type: libusb_transfer_type,
		length: uint,
		buffer: *mut u8) -> (libusb_transfer_status, uint) {

		let (chan, port) : (Sender<()>, Receiver<()>) = channel();

		let t = libusb_alloc_transfer(0);
		(*t).dev_handle = self.ptr();
		(*t).endpoint = endpoint;
		(*t).transfer_type = transfer_type as u8;
		(*t).timeout = 0;
		(*t).length = length as c_int;
		(*t).callback = rust_usb_callback;
		(*t).user_data = transmute(box chan);
		(*t).buffer = buffer;

		libusb_submit_transfer(t);
		port.recv();
		let r = ((*t).get_status(), (*t).actual_length as uint);
		libusb_free_transfer(t);
		return r;
	}

	pub fn read(&self,
			endpoint: u8,
			transfer_type: libusb_transfer_type,
			size: uint
			) -> Result<Vec<u8>, libusb_transfer_status> {
		let mut buf: Vec<u8> = Vec::from_elem(size, 0u8);
		unsafe {
			let ptr = buf.as_mut_ptr();
			let (status, actual_length) = self.submit_transfer_sync(
				endpoint, transfer_type, size, ptr);

			if status == LIBUSB_TRANSFER_COMPLETED {
				buf.truncate(actual_length);
				Ok(buf)
			} else {
				Err(status)
			}
		}
	}

	pub fn write(&self, endpoint: u8, transfer_type: libusb_transfer_type, buf: &[u8]) -> Result<(), libusb_transfer_status> {
		unsafe {
			let ptr = buf.as_ptr() as *mut u8;

			let (status, _) = self.submit_transfer_sync(
				endpoint, transfer_type, buf.len(), ptr);

			if status == LIBUSB_TRANSFER_COMPLETED {
				Ok(())
			} else {
				Err(status)
			}
		}
	}

	pub fn ctrl_read(&self, bmRequestType: u8, bRequest: u8,
		wValue:u16, wIndex: u16, length: uint) -> Result<Vec<u8>, libusb_transfer_status> {

		let setup_length = size_of::<libusb_control_setup>();
		let total_length = setup_length + length as uint;
		let mut buf: Vec<u8> = Vec::from_elem(total_length, 0u8);

		unsafe{
			let ptr = fill_setup_buf(buf.as_mut_slice(), bmRequestType, bRequest, wValue, wIndex, length);

			let (status, actual_length) = self.submit_transfer_sync(
				0, LIBUSB_TRANSFER_TYPE_CONTROL, total_length, ptr);

			if status == LIBUSB_TRANSFER_COMPLETED {
				Ok(buf.slice(setup_length, setup_length+actual_length).to_vec())
			} else {
				Err(status)
			}
		}
	}

	pub fn ctrl_write(&self, bmRequestType: u8, bRequest: u8,
		wValue:u16, wIndex: u16, buf: &[u8]) -> Result<(), libusb_transfer_status> {
		unsafe {
			let mut setup_buf = Vec::from_elem(size_of::<libusb_control_setup>(), 0u8);
			fill_setup_buf(setup_buf.as_mut_slice(), bmRequestType, bRequest, wValue, wIndex, buf.len());
			setup_buf.push_all(buf);
			self.write(0, LIBUSB_TRANSFER_TYPE_CONTROL, setup_buf.slice_from(0))
		}
	}

	unsafe fn stream_transfers(&self, endpoint: u8,
			transfer_type: libusb_transfer_type, size: uint,
			num_transfers: uint) -> (Receiver<*mut libusb_transfer>, Vec<TH>) {

		let (chan, port) = channel();

		let transfers = Vec::from_fn(num_transfers, |_| { TH {
			t: libusb_alloc_transfer(0),
			c: chan.clone(),
		}});

		for th in transfers.iter() {
			(*th.t).dev_handle = self.ptr();
			(*th.t).endpoint = endpoint;
			(*th.t).transfer_type = transfer_type as u8;
			(*th.t).timeout = 0;
			(*th.t).length = size as i32;
			(*th.t).callback = rust_usb_stream_callback;
			(*th.t).buffer = malloc(size as size_t) as *mut u8;
			(*th.t).user_data = transmute(&th.c);
		}

		return (port, transfers);
	}

	pub fn read_stream(&self, endpoint: u8,
			transfer_type: libusb_transfer_type,
			size: uint, mut num_transfers: uint, cb: |Result<&[u8], libusb_transfer_status>| -> bool) {

		unsafe {
			let mut running = true;
			let (port, transfers) = self.stream_transfers(
				endpoint, transfer_type, size, num_transfers);

			for th in transfers.iter() {
				libusb_submit_transfer(th.t);
			}

			while (num_transfers > 0) {
				let transfer: *mut libusb_transfer = port.recv();

				if (*transfer).get_status() == LIBUSB_TRANSFER_COMPLETED {
					slice::raw::buf_as_slice((*transfer).buffer as *const u8, size, |b| {
						running &= cb(Ok(b))
					});
				} else {
					running = false;
					running &= cb(Err((*transfer).get_status()));
				}

				if running {
					let r = libusb_submit_transfer(transfer);
					assert!(r == 0);
				} else {
					num_transfers -= 1;
				}
			}
		}
	}

	pub fn write_stream(&self, endpoint: u8,
			transfer_type: libusb_transfer_type,
			size: uint, num_transfers: uint, cb: |Result<(&mut[u8]), libusb_transfer_status>| -> bool) {

		unsafe {
			let mut running = true;
			let mut running_transfers = 0u;
			let (port, transfers) = self.stream_transfers(
				endpoint, transfer_type, size, num_transfers);

			for th in transfers.iter() {
				slice::raw::mut_buf_as_slice((*th.t).buffer, size, |b| {
					running &= cb(Ok(b));
				});
				if running {
					libusb_submit_transfer(th.t);
					running_transfers += 1;
				} else {
					break;
				}
			}

			while (running_transfers > 0) {
				let transfer: *mut libusb_transfer = port.recv();

				if (*transfer).get_status() == LIBUSB_TRANSFER_COMPLETED {
					slice::raw::mut_buf_as_slice((*transfer).buffer, size, |b| {
						running &= cb(Ok(b))
					});
				} else {
					running = false;
					running &= cb(Err((*transfer).get_status()));
				}

				if running {
					let r = libusb_submit_transfer(transfer);
					assert!(r == 0);
				} else {
					running_transfers -= 1;
				}
			}
		}
	}
}

unsafe fn fill_setup_buf(buf: &mut [u8], bmRequestType: u8,
	bRequest: u8, wValue:u16, wIndex: u16, length: uint) -> *mut u8 {
	let ptr = buf.as_mut_ptr();
	let setup = ptr as *mut libusb_control_setup;

	// TODO: these are always little-endian
	(*setup).bmRequestType = bmRequestType;
	(*setup).bRequest = bRequest;
	(*setup).wValue = wValue;
	(*setup).wIndex = wIndex;
	(*setup).wLength = length as u16;

	return ptr;
}

impl Clone for DeviceHandle {
	fn clone(&self) -> DeviceHandle {
		DeviceHandle{bx: self.bx.clone()}
	}
}
<commit_msg>rust: libnative removed<commit_after>#![ crate_type = "lib" ]
#![ feature(globs) ]

extern crate libc;
extern crate core;
extern crate sync;

use libusb::*;
use libusb::libusb_transfer_status::*;
use libusb::libusb_transfer_type::*;
use libc::{c_int, c_void, size_t, malloc, free};
use std::intrinsics;
use std::slice;
use std::result::Result;
use std::comm::{Receiver, Sender};
use std::mem::transmute;
use std::mem::size_of;
use std::vec::Vec;
use std::cell::UnsafeCell;

use sync::Arc;
use std::sync::atomic::{SeqCst, AtomicInt};
use std::task;

pub mod libusb;

pub struct ContextData {
	ctx: *mut libusb_context,
	open_device_count: AtomicInt
}

impl Drop for ContextData {
	fn drop(&mut self) {
		unsafe {
			assert!(self.open_device_count.load(SeqCst) == 0);
			// TODO: make sure backend thread is dead if the last device just closed
			libusb_exit(self.ctx);
		}
	}
}

pub struct Context {
	bx: Arc<UnsafeCell<ContextData>>
}

impl Context {
	pub fn new() -> Context {
		unsafe{
			let mut ctx: *mut libusb_context = intrinsics::init();
			let r = libusb_init(&mut ctx);

			Context{
				bx: Arc::new(UnsafeCell::new(ContextData{
					ctx: ctx,
					open_device_count: AtomicInt::new(0)
				}))
			}
		}
	}

	pub fn ptr(&self) -> *mut libusb_context {
		unsafe{
			(*self.bx.get()).ctx
		}
	}

	pub fn set_debug(&self, level: int) {
		unsafe{
			libusb_set_debug(self.ptr(), level as c_int);
		}
	}

	pub fn list_devices(&self) -> Vec<Device> {
		unsafe{
			let mut list: *mut *mut libusb_device = intrinsics::init();
			let num_devices = libusb_get_device_list(self.ptr(), &mut list);
			let r = slice::raw::mut_buf_as_slice(list, num_devices as uint, |l|{
				l.iter().map(|i| Device{dev: *i, ctx: (*self).clone()}).collect()
			});

			libusb_free_device_list(list, 0);
			r
		}
	}

	pub fn find_by_vid_pid(&self, vid: uint, pid: uint) -> Option<Device> {
		self.list_devices().into_iter().find(|d| {
			let desc = d.descriptor();
			desc.idVendor as uint == vid && desc.idProduct as uint == pid
		})
	}

	fn device_opened(&self) {
		let count = unsafe { &mut (*self.bx.get()).open_device_count };
		let old_count = count.fetch_add(1, SeqCst);

		if old_count == 0 {
			let bx = self.bx.clone();

			fn threadfn(tbx: &Arc<UnsafeCell<ContextData>>) {
				unsafe {
					let ctx = (*tbx.get()).ctx;
					let count = &(*tbx.get()).open_device_count;

					while (count.load(SeqCst) > 0) {
						libusb_handle_events(ctx);
					}
				}
			}

			task::spawn(proc() {threadfn(&bx);});
		}
	}

	fn device_closed(&self) {
		let count = unsafe { &mut (*self.bx.get()).open_device_count };
		count.fetch_sub(1, SeqCst);
	}
}

extern fn rust_usb_callback(transfer: *mut libusb_transfer) {
	unsafe {
		let chan: Box<Sender<()>> = transmute((*transfer).user_data);
		chan.send(());
	}
}

struct TH {
	t: *mut libusb_transfer,
	c: Sender<*mut libusb_transfer>,
}

impl Drop for TH{
	fn drop(&mut self) {
		unsafe {
			free((*self.t).buffer as *mut c_void);
			libusb_free_transfer(self.t);
		}
	}
}

extern fn rust_usb_stream_callback(transfer: *mut libusb_transfer) {
	unsafe {
		let chan: &Sender<*mut libusb_transfer> = transmute((*transfer).user_data);
		chan.send(transfer);
	}
}

impl Clone for Context{
	fn clone(&self) -> Context{
		Context{bx: self.bx.clone()}
	}
}

pub struct Device {
	dev: *mut libusb_device,
	ctx: Context
}

impl Device {
	pub fn descriptor(&self) -> Box<libusb_device_descriptor> {
		unsafe{
			let mut d: Box<libusb_device_descriptor> = box intrinsics::uninit();
			libusb_get_device_descriptor(self.dev, &mut *d as *mut libusb_device_descriptor);
			d
		}
	}

	pub fn bus(&self) -> int {
		unsafe {
			libusb_get_bus_number(self.dev) as int
		}
	}

	pub fn address(&self) -> int {
		unsafe {
			libusb_get_device_address(self.dev) as int
		}
	}

	pub fn open(&self) -> Result<DeviceHandle, int> {
		unsafe {
			let mut handle: *mut libusb_device_handle = intrinsics::uninit();
			let r = libusb_open(self.dev, &mut handle);
			if r == 0 {
				self.ctx.device_opened();
				Ok(DeviceHandle {
					bx: Arc::new(UnsafeCell::new(DeviceHandleData {
						dev: handle,
						ctx: self.ctx.clone()
					}))
				})
			}else{
				Err(r as int)
			}
		}
	}
}

impl Drop for Device {
	fn drop(&mut self) {
		unsafe {
			libusb_unref_device(self.dev);
		}
	}
}

impl Clone for Device {
	fn clone(&self) -> Device {
		unsafe {
			libusb_ref_device(self.dev);
		}
		Device{dev: self.dev, ctx: self.ctx.clone()}
	}
}

struct DeviceHandleData{
	dev: *mut libusb_device_handle,
	ctx: Context
}

impl Drop for DeviceHandleData {
	fn drop(&mut self) {
		unsafe {
			self.ctx.device_closed();
			libusb_close(self.dev);
		}
	}
}

pub struct DeviceHandle {
	bx: Arc<UnsafeCell<DeviceHandleData>>
}

impl DeviceHandle {
	pub fn ptr(&self) -> *mut libusb_device_handle {
		unsafe {
			(*self.bx.get()).dev
		}
	}

	pub fn claim_interface(&self,
		iface_num: uint) {
		unsafe {
		libusb_claim_interface(self.ptr(), iface_num as c_int);
		}
	}

	pub unsafe fn submit_transfer_sync(&self,
		endpoint: u8,
		transfer_type: libusb_transfer_type,
		length: uint,
		buffer: *mut u8) -> (libusb_transfer_status, uint) {

		let (chan, port) : (Sender<()>, Receiver<()>) = channel();

		let t = libusb_alloc_transfer(0);
		(*t).dev_handle = self.ptr();
		(*t).endpoint = endpoint;
		(*t).transfer_type = transfer_type as u8;
		(*t).timeout = 0;
		(*t).length = length as c_int;
		(*t).callback = rust_usb_callback;
		(*t).user_data = transmute(box chan);
		(*t).buffer = buffer;

		libusb_submit_transfer(t);
		port.recv();
		let r = ((*t).get_status(), (*t).actual_length as uint);
		libusb_free_transfer(t);
		return r;
	}

	pub fn read(&self,
			endpoint: u8,
			transfer_type: libusb_transfer_type,
			size: uint
			) -> Result<Vec<u8>, libusb_transfer_status> {
		let mut buf: Vec<u8> = Vec::from_elem(size, 0u8);
		unsafe {
			let ptr = buf.as_mut_ptr();
			let (status, actual_length) = self.submit_transfer_sync(
				endpoint, transfer_type, size, ptr);

			if status == LIBUSB_TRANSFER_COMPLETED {
				buf.truncate(actual_length);
				Ok(buf)
			} else {
				Err(status)
			}
		}
	}

	pub fn write(&self, endpoint: u8, transfer_type: libusb_transfer_type, buf: &[u8]) -> Result<(), libusb_transfer_status> {
		unsafe {
			let ptr = buf.as_ptr() as *mut u8;

			let (status, _) = self.submit_transfer_sync(
				endpoint, transfer_type, buf.len(), ptr);

			if status == LIBUSB_TRANSFER_COMPLETED {
				Ok(())
			} else {
				Err(status)
			}
		}
	}

	pub fn ctrl_read(&self, bmRequestType: u8, bRequest: u8,
		wValue:u16, wIndex: u16, length: uint) -> Result<Vec<u8>, libusb_transfer_status> {

		let setup_length = size_of::<libusb_control_setup>();
		let total_length = setup_length + length as uint;
		let mut buf: Vec<u8> = Vec::from_elem(total_length, 0u8);

		unsafe{
			let ptr = fill_setup_buf(buf.as_mut_slice(), bmRequestType, bRequest, wValue, wIndex, length);

			let (status, actual_length) = self.submit_transfer_sync(
				0, LIBUSB_TRANSFER_TYPE_CONTROL, total_length, ptr);

			if status == LIBUSB_TRANSFER_COMPLETED {
				Ok(buf.slice(setup_length, setup_length+actual_length).to_vec())
			} else {
				Err(status)
			}
		}
	}

	pub fn ctrl_write(&self, bmRequestType: u8, bRequest: u8,
		wValue:u16, wIndex: u16, buf: &[u8]) -> Result<(), libusb_transfer_status> {
		unsafe {
			let mut setup_buf = Vec::from_elem(size_of::<libusb_control_setup>(), 0u8);
			fill_setup_buf(setup_buf.as_mut_slice(), bmRequestType, bRequest, wValue, wIndex, buf.len());
			setup_buf.push_all(buf);
			self.write(0, LIBUSB_TRANSFER_TYPE_CONTROL, setup_buf.slice_from(0))
		}
	}

	unsafe fn stream_transfers(&self, endpoint: u8,
			transfer_type: libusb_transfer_type, size: uint,
			num_transfers: uint) -> (Receiver<*mut libusb_transfer>, Vec<TH>) {

		let (chan, port) = channel();

		let transfers = Vec::from_fn(num_transfers, |_| { TH {
			t: libusb_alloc_transfer(0),
			c: chan.clone(),
		}});

		for th in transfers.iter() {
			(*th.t).dev_handle = self.ptr();
			(*th.t).endpoint = endpoint;
			(*th.t).transfer_type = transfer_type as u8;
			(*th.t).timeout = 0;
			(*th.t).length = size as i32;
			(*th.t).callback = rust_usb_stream_callback;
			(*th.t).buffer = malloc(size as size_t) as *mut u8;
			(*th.t).user_data = transmute(&th.c);
		}

		return (port, transfers);
	}

	pub fn read_stream(&self, endpoint: u8,
			transfer_type: libusb_transfer_type,
			size: uint, mut num_transfers: uint, cb: |Result<&[u8], libusb_transfer_status>| -> bool) {

		unsafe {
			let mut running = true;
			let (port, transfers) = self.stream_transfers(
				endpoint, transfer_type, size, num_transfers);

			for th in transfers.iter() {
				libusb_submit_transfer(th.t);
			}

			while (num_transfers > 0) {
				let transfer: *mut libusb_transfer = port.recv();

				if (*transfer).get_status() == LIBUSB_TRANSFER_COMPLETED {
					slice::raw::buf_as_slice((*transfer).buffer as *const u8, size, |b| {
						running &= cb(Ok(b))
					});
				} else {
					running = false;
					running &= cb(Err((*transfer).get_status()));
				}

				if running {
					let r = libusb_submit_transfer(transfer);
					assert!(r == 0);
				} else {
					num_transfers -= 1;
				}
			}
		}
	}

	pub fn write_stream(&self, endpoint: u8,
			transfer_type: libusb_transfer_type,
			size: uint, num_transfers: uint, cb: |Result<(&mut[u8]), libusb_transfer_status>| -> bool) {

		unsafe {
			let mut running = true;
			let mut running_transfers = 0u;
			let (port, transfers) = self.stream_transfers(
				endpoint, transfer_type, size, num_transfers);

			for th in transfers.iter() {
				slice::raw::mut_buf_as_slice((*th.t).buffer, size, |b| {
					running &= cb(Ok(b));
				});
				if running {
					libusb_submit_transfer(th.t);
					running_transfers += 1;
				} else {
					break;
				}
			}

			while (running_transfers > 0) {
				let transfer: *mut libusb_transfer = port.recv();

				if (*transfer).get_status() == LIBUSB_TRANSFER_COMPLETED {
					slice::raw::mut_buf_as_slice((*transfer).buffer, size, |b| {
						running &= cb(Ok(b))
					});
				} else {
					running = false;
					running &= cb(Err((*transfer).get_status()));
				}

				if running {
					let r = libusb_submit_transfer(transfer);
					assert!(r == 0);
				} else {
					running_transfers -= 1;
				}
			}
		}
	}
}

unsafe fn fill_setup_buf(buf: &mut [u8], bmRequestType: u8,
	bRequest: u8, wValue:u16, wIndex: u16, length: uint) -> *mut u8 {
	let ptr = buf.as_mut_ptr();
	let setup = ptr as *mut libusb_control_setup;

	// TODO: these are always little-endian
	(*setup).bmRequestType = bmRequestType;
	(*setup).bRequest = bRequest;
	(*setup).wValue = wValue;
	(*setup).wIndex = wIndex;
	(*setup).wLength = length as u16;

	return ptr;
}

impl Clone for DeviceHandle {
	fn clone(&self) -> DeviceHandle {
		DeviceHandle{bx: self.bx.clone()}
	}
}
<|endoftext|>


<commit_before>use super::command::Command;
use super::command::Command::Select;
use std::iter::IntoIterator;
use std::collections::HashMap;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelectCommand {
    command: Command,
    arguments: HashMap<String, String>,
    table: String,
}

impl Default for SelectCommand {
    fn default() -> SelectCommand {
        SelectCommand {
            command: Select,
            arguments: HashMap::new(),
            table: "".to_string(),
        }
    }
}

impl SelectCommand {
    pub fn new(table: String) -> SelectCommand {
        let default: SelectCommand = Default::default();
        SelectCommand {
            command: default.command,
            arguments: default.arguments,
            table: table
        }
    }

    pub fn filter(mut self, filter: String) -> SelectCommand {
        let encoded = format!("'{}'", filter);
        self.arguments.insert("filter".to_string(), encoded.clone());
        self
    }

    #[inline]
    fn split_columns_vec(&mut self, columns: Vec<String>) -> String {
        let string = columns.into_iter().collect::<Vec<String>>()
            .join(",").to_owned();
        string.clone()
    }

    pub fn match_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("match_columns".to_string(), string.clone());
        self
    }

    pub fn output_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("output_columns".to_string(), string.clone());
        self
    }

    pub fn offset(mut self, offset: u64) -> SelectCommand {
        let offset = format!("{}", offset);
        self.arguments.insert("offset".to_string(), offset.clone());
        self
    }

    pub fn limit(mut self, limit: u64) -> SelectCommand {
        let limit = format!("{}", limit);
        self.arguments.insert("limit".to_string(), limit.clone());
        self
    }

    pub fn cache(mut self, cache: bool) -> SelectCommand {
        let flag = match cache {
            true => "yes",
            false => "no"
        };
        self.arguments.insert("cache".to_string(), flag.to_string());
        self
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use command::Command::Select;
    use std::collections::HashMap;

    #[test]
    fn test_new() {
        let vanilla_select = SelectCommand::new("test".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: HashMap::new(),
            table: "test".to_string(),
        };
        assert_eq!(expected, vanilla_select);
    }

    #[test]
    fn test_filter() {
        let select = SelectCommand::new("test".to_string())
            .filter("output_column @ \"type_safe\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("filter".to_string(),
                   "'output_column @ \"type_safe\"'".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_match_columns() {
        let select = SelectCommand::new("test".to_string())
            .match_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("match_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_output_columns() {
        let select = SelectCommand::new("test".to_string())
            .output_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("output_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_offset() {
        let select = SelectCommand::new("test".to_string())
            .offset(100);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("offset".to_string(), "100".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_limit() {
        let select = SelectCommand::new("test".to_string())
            .limit(50);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("limit".to_string(), "50".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_cache() {
        let select_yes = SelectCommand::new("test".to_string())
            .cache(true);
        let mut arg_yes: HashMap<String, String> = HashMap::new();
        arg_yes.insert("cache".to_string(), "yes".to_string());
        let expected_yes = SelectCommand {
            command: Select,
            arguments: arg_yes,
            table: "test".to_string(),
        };
        assert_eq!(expected_yes, select_yes);
        let select_no = SelectCommand::new("test".to_string())
            .cache(false);
        let mut arg_no: HashMap<String, String> = HashMap::new();
        arg_no.insert("cache".to_string(), "no".to_string());
        let expected_no = SelectCommand {
            command: Select,
            arguments: arg_no,
            table: "test".to_string(),
        };
        assert_eq!(expected_no, select_no);
    }
}
<commit_msg>select: Align<commit_after>use super::command::Command;
use super::command::Command::Select;
use std::iter::IntoIterator;
use std::collections::HashMap;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelectCommand {
    command: Command,
    table: String,
    arguments: HashMap<String, String>,
}

impl Default for SelectCommand {
    fn default() -> SelectCommand {
        SelectCommand {
            command: Select,
            table: "".to_string(),
            arguments: HashMap::new(),
        }
    }
}

impl SelectCommand {
    pub fn new(table: String) -> SelectCommand {
        let default: SelectCommand = Default::default();
        SelectCommand {
            command: default.command,
            table: table,
            arguments: default.arguments,
        }
    }

    pub fn filter(mut self, filter: String) -> SelectCommand {
        let encoded = format!("'{}'", filter);
        self.arguments.insert("filter".to_string(), encoded.clone());
        self
    }

    #[inline]
    fn split_columns_vec(&mut self, columns: Vec<String>) -> String {
        let string = columns.into_iter().collect::<Vec<String>>()
            .join(",").to_owned();
        string.clone()
    }

    pub fn match_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("match_columns".to_string(), string.clone());
        self
    }

    pub fn output_columns(mut self, columns: Vec<String>) -> SelectCommand {
        let string = self.split_columns_vec(columns);
        self.arguments.insert("output_columns".to_string(), string.clone());
        self
    }

    pub fn offset(mut self, offset: u64) -> SelectCommand {
        let offset = format!("{}", offset);
        self.arguments.insert("offset".to_string(), offset.clone());
        self
    }

    pub fn limit(mut self, limit: u64) -> SelectCommand {
        let limit = format!("{}", limit);
        self.arguments.insert("limit".to_string(), limit.clone());
        self
    }

    pub fn cache(mut self, cache: bool) -> SelectCommand {
        let flag = match cache {
            true => "yes",
            false => "no"
        };
        self.arguments.insert("cache".to_string(), flag.to_string());
        self
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use command::Command::Select;
    use std::collections::HashMap;

    #[test]
    fn test_new() {
        let vanilla_select = SelectCommand::new("test".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: HashMap::new(),
        };
        assert_eq!(expected, vanilla_select);
    }

    #[test]
    fn test_filter() {
        let select = SelectCommand::new("test".to_string())
            .filter("output_column @ \"type_safe\"".to_string());
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("filter".to_string(),
                   "'output_column @ \"type_safe\"'".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_match_columns() {
        let select = SelectCommand::new("test".to_string())
            .match_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("match_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_output_columns() {
        let select = SelectCommand::new("test".to_string())
            .output_columns(vec!["test".to_string(), "piyo".to_string()]);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("output_columns".to_string(), "test,piyo".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_offset() {
        let select = SelectCommand::new("test".to_string())
            .offset(100);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("offset".to_string(), "100".to_string());
        let expected = SelectCommand {
            command: Select,
            arguments: arg,
            table: "test".to_string(),
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_limit() {
        let select = SelectCommand::new("test".to_string())
            .limit(50);
        let mut arg: HashMap<String, String> = HashMap::new();
        arg.insert("limit".to_string(), "50".to_string());
        let expected = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg,
        };
        assert_eq!(expected, select);
    }

    #[test]
    fn test_cache() {
        let select_yes = SelectCommand::new("test".to_string())
            .cache(true);
        let mut arg_yes: HashMap<String, String> = HashMap::new();
        arg_yes.insert("cache".to_string(), "yes".to_string());
        let expected_yes = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_yes,
        };
        assert_eq!(expected_yes, select_yes);
        let select_no = SelectCommand::new("test".to_string())
            .cache(false);
        let mut arg_no: HashMap<String, String> = HashMap::new();
        arg_no.insert("cache".to_string(), "no".to_string());
        let expected_no = SelectCommand {
            command: Select,
            table: "test".to_string(),
            arguments: arg_no,
        };
        assert_eq!(expected_no, select_no);
    }
}
<|endoftext|>


<commit_before>//! A library for creating General Game Playing (GGP) players. This library is based off of
//! [GGP Base](https://github.com/ggp-org/ggp-base). While GGP Base allows the creation of
//! players backed by a propositional network or a logic prover, this library currently only
//! supports logic prover based players.
//!
//! # Example
//!
//! To create your own player, simply implement the `Player` trait for your struct and pass the
//! host/port you want the player to run at and the player itself to the `run` function.
//!
//! The following example implements a RandomPlayer, which plays random legal moves each turn.
//!
//! ```ignore
//! extern crate rand;
//! extern crate ggp_rs;
//!
//! use ggp_rs::{Player, Game, Move};
//! use std::net::Ipv4Addr;
//!
//! struct RandomPlayer;
//!
//! impl Player for RandomPlayer {
//!     fn get_name(&self) -> String {
//!         "RandomPlayer".to_string()
//!     }
//!
//!     fn select_move(&self, game: &Game) -> Move {
//!         let state = game.get_current_state();
//!         let role = game.get_role();
//!         let mut moves = game.get_legal_moves(state, role);
//!         let r = rand::random::<usize>() % moves.len();
//!         moves.swap_remove(r)
//!     }
//! }
//!
//! fn main() {
//!     ggp_rs::run((Ipv4Addr::new(0,0,0,0), 9147), RandomPlayer);
//! }
//! ```

#![feature(std_misc, plugin)]
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#![plugin(regex_macros)]

extern crate time;
extern crate gdl_parser;
extern crate hyper;
extern crate regex;
extern crate unicase;

#[macro_use]
extern crate log;

#[macro_use]
extern crate lazy_static;

mod util;
mod game_manager;
mod gdl;
mod prover;

use unicase::UniCase;

use hyper::Server;
use hyper::error::HttpError::HttpIoError;
use hyper::server::{Request, Response, Handler};
use hyper::header::{ContentLength, ContentType, AccessControlAllowOrigin,
                    AccessControlAllowHeaders};
use hyper::net::Fresh;
use hyper::version::HttpVersion;

use std::net::ToSocketAddrs;
use std::io::{Read, Write};
use std::ascii::OwnedAsciiExt;
use std::sync::Mutex;

use game_manager::GameManager;

pub use game_manager::{Game, State};
pub use gdl::{constants, Move, Role, Score};

pub type MoveResult<T> = Result<T, Move>;

#[macro_export]
macro_rules! check_time {
    ($self_:ident, $game:ident) => (
        if $game.move_start_time().to(time::PreciseTime::now()) >
            time::Duration::milliseconds(
                (1000 * $game.get_start_clock() - $self_.cutoff()) as i64) {
            return $self_.out_of_time($game);
        });
}

#[macro_export]
macro_rules! check_time_result {
    ($self_:ident, $game:ident) => (
        if $game.move_start_time().to(time::PreciseTime::now()) >
            time::Duration::milliseconds(
                (1000 * $game.get_start_clock() - $self_.cutoff()) as i64) {
            return Err($self_.out_of_time($game));
        });
}

/// A GGP player
pub trait Player {
    /// Returns the name of this player
    fn get_name(&self) -> String;

    /// Called after receiving a `start` message. Used to perform any computation before the start
    /// of the game.
    fn meta_game(&mut self, _: &Game) {}

    /// Called after receiving a `play` message. Returns a `Move` for this turn.
    fn select_move(&mut self, game: &Game) -> Move;

    /// The cutoff for the remaining time for the start or play clock in milliseconds, after which
    /// `out_of_time` should be called. Note that this function does not call `out_of_time`, but is
    /// simply used by other functions when deciding whether to call it. Defaults to 500
    /// milliseconds.
    fn cutoff(&self) -> u32 { 500 }

    /// Gets a move to play when there is no more time left for computation.
    fn out_of_time(&mut self, _: &Game) -> Move { unimplemented!() }

    /// Called when a game is finished or aborted
    fn stop(&mut self, _: &Game) {}
}

/// Starts a GGP player listening at `host`
pub fn run<T: ToSocketAddrs + 'static, P: Player + Sync + Send + 'static>(host: T, player: P) {
    let handler = GameHandler::new(player);
    match Server::http(handler).listen(host) {
        Err(HttpIoError(e)) => panic!("{}", e),
        Err(e) => panic!("{}", e),
        _ => ()
    }
}

struct GameHandler<P: Player + Send> {
    pub gm: Mutex<GameManager<P>>
}

impl<P: Player + Send> GameHandler<P> {
    pub fn new(player: P) -> GameHandler<P> {
        GameHandler { gm: Mutex::new(GameManager::new(player)) }
    }
}

impl<P: Player + Sync + Send> Handler for GameHandler<P> {
    fn handle(&self, mut req: Request, mut res: Response<Fresh>) {
        let mut req_str = String::new();
        req.read_to_string(&mut req_str).unwrap();
        let req_str = req_str.into_ascii_lowercase();
        info!("Got request: {}", req_str);

        let response = {
            let mut gm = self.gm.lock().unwrap();
            gm.handle(req_str)
        };
        let response = response.into_bytes();
        res.headers_mut().set(ContentLength(response.len() as u64));
        res.headers_mut().set(ContentType("text/acl".parse().unwrap()));
        res.headers_mut().set(AccessControlAllowOrigin::Any);
        res.headers_mut().set(AccessControlAllowHeaders(
            vec![UniCase("Content-Type".to_string())]));
        res.version = HttpVersion::Http10;
        let mut res = res.start().unwrap();
        res.write_all(&response).unwrap();
        res.end().unwrap();
    }
}
<commit_msg>Removed std_misc unstable feature<commit_after>//! A library for creating General Game Playing (GGP) players. This library is based off of
//! [GGP Base](https://github.com/ggp-org/ggp-base). While GGP Base allows the creation of
//! players backed by a propositional network or a logic prover, this library currently only
//! supports logic prover based players.
//!
//! # Example
//!
//! To create your own player, simply implement the `Player` trait for your struct and pass the
//! host/port you want the player to run at and the player itself to the `run` function.
//!
//! The following example implements a RandomPlayer, which plays random legal moves each turn.
//!
//! ```ignore
//! extern crate rand;
//! extern crate ggp_rs;
//!
//! use ggp_rs::{Player, Game, Move};
//! use std::net::Ipv4Addr;
//!
//! struct RandomPlayer;
//!
//! impl Player for RandomPlayer {
//!     fn get_name(&self) -> String {
//!         "RandomPlayer".to_string()
//!     }
//!
//!     fn select_move(&self, game: &Game) -> Move {
//!         let state = game.get_current_state();
//!         let role = game.get_role();
//!         let mut moves = game.get_legal_moves(state, role);
//!         let r = rand::random::<usize>() % moves.len();
//!         moves.swap_remove(r)
//!     }
//! }
//!
//! fn main() {
//!     ggp_rs::run((Ipv4Addr::new(0,0,0,0), 9147), RandomPlayer);
//! }
//! ```

#![feature(plugin)]
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#![plugin(regex_macros)]

extern crate time;
extern crate gdl_parser;
extern crate hyper;
extern crate regex;
extern crate unicase;

#[macro_use]
extern crate log;

#[macro_use]
extern crate lazy_static;

mod util;
mod game_manager;
mod gdl;
mod prover;

use unicase::UniCase;

use hyper::Server;
use hyper::error::HttpError::HttpIoError;
use hyper::server::{Request, Response, Handler};
use hyper::header::{ContentLength, ContentType, AccessControlAllowOrigin,
                    AccessControlAllowHeaders};
use hyper::net::Fresh;
use hyper::version::HttpVersion;

use std::net::ToSocketAddrs;
use std::io::{Read, Write};
use std::sync::Mutex;
use std::ascii::AsciiExt;

use game_manager::GameManager;

pub use game_manager::{Game, State};
pub use gdl::{constants, Move, Role, Score};

pub type MoveResult<T> = Result<T, Move>;

#[macro_export]
macro_rules! check_time {
    ($self_:ident, $game:ident) => (
        if $game.move_start_time().to(time::PreciseTime::now()) >
            time::Duration::milliseconds(
                (1000 * $game.get_start_clock() - $self_.cutoff()) as i64) {
            return $self_.out_of_time($game);
        });
}

#[macro_export]
macro_rules! check_time_result {
    ($self_:ident, $game:ident) => (
        if $game.move_start_time().to(time::PreciseTime::now()) >
            time::Duration::milliseconds(
                (1000 * $game.get_start_clock() - $self_.cutoff()) as i64) {
            return Err($self_.out_of_time($game));
        });
}

/// A GGP player
pub trait Player {
    /// Returns the name of this player
    fn get_name(&self) -> String;

    /// Called after receiving a `start` message. Used to perform any computation before the start
    /// of the game.
    fn meta_game(&mut self, _: &Game) {}

    /// Called after receiving a `play` message. Returns a `Move` for this turn.
    fn select_move(&mut self, game: &Game) -> Move;

    /// The cutoff for the remaining time for the start or play clock in milliseconds, after which
    /// `out_of_time` should be called. Note that this function does not call `out_of_time`, but is
    /// simply used by other functions when deciding whether to call it. Defaults to 500
    /// milliseconds.
    fn cutoff(&self) -> u32 { 500 }

    /// Gets a move to play when there is no more time left for computation.
    fn out_of_time(&mut self, _: &Game) -> Move { unimplemented!() }

    /// Called when a game is finished or aborted
    fn stop(&mut self, _: &Game) {}
}

/// Starts a GGP player listening at `host`
pub fn run<T: ToSocketAddrs + 'static, P: Player + Sync + Send + 'static>(host: T, player: P) {
    let handler = GameHandler::new(player);
    match Server::http(handler).listen(host) {
        Err(HttpIoError(e)) => panic!("{}", e),
        Err(e) => panic!("{}", e),
        _ => ()
    }
}

struct GameHandler<P: Player + Send> {
    pub gm: Mutex<GameManager<P>>
}

impl<P: Player + Send> GameHandler<P> {
    pub fn new(player: P) -> GameHandler<P> {
        GameHandler { gm: Mutex::new(GameManager::new(player)) }
    }
}

impl<P: Player + Sync + Send> Handler for GameHandler<P> {
    fn handle(&self, mut req: Request, mut res: Response<Fresh>) {
        let mut req_str = String::new();
        req.read_to_string(&mut req_str).unwrap();
        let req_str = req_str.to_ascii_lowercase(); // TODO: Avoid allocation
        info!("Got request: {}", req_str);

        let response = {
            let mut gm = self.gm.lock().unwrap();
            gm.handle(req_str)
        };
        let response = response.into_bytes();
        res.headers_mut().set(ContentLength(response.len() as u64));
        res.headers_mut().set(ContentType("text/acl".parse().unwrap()));
        res.headers_mut().set(AccessControlAllowOrigin::Any);
        res.headers_mut().set(AccessControlAllowHeaders(
            vec![UniCase("Content-Type".to_string())]));
        res.version = HttpVersion::Http10;
        let mut res = res.start().unwrap();
        res.write_all(&response).unwrap();
        res.end().unwrap();
    }
}
<|endoftext|>


<commit_before>//! TODO: dox

#![deny(missing_docs)]

extern crate curl_sys;
extern crate libc;

use std::ffi::CStr;
use std::str;
use std::sync::{Once, ONCE_INIT};

pub use error::{Error, ShareError, MultiError};
mod error;

pub use version::{Version, Protocols};
mod version;

mod panic;
pub mod easy;

/// Initializes the underlying libcurl library.
///
/// It's not required to call this before the library is used, but it's
/// recommended to do so as soon as the program starts.
pub fn init() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        unsafe {
            curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL);
            libc::atexit(cleanup);
        }
    });

    extern fn cleanup() {
        unsafe { curl_sys::curl_global_cleanup(); }
    }
}

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}
<commit_msg>Add some crate docs<commit_after>//! Rust bindings to the libcurl C library
//!
//! This crate contains bindings for an HTTP/HTTPS client which is powered by
//! [libcurl], the same library behind the `curl` command line tool. The API
//! currently closely matches that of libcurl itself, except that a Rustic layer
//! of safety is applied on top.
//!
//! [libcurl]: https://curl.haxx.se/libcurl/
//!
//! # The "Easy" API
//!
//! The easiest way to send a request is to use the `Easy` api which corresponds
//! to `CURL` in libcurl. This handle supports a wide variety of options and can
//! be used to make a single blocking request in a thread. Callbacks can be
//! specified to deal with data as it arrives and a handle can be reused to
//! cache connections and such.
//!
//! ```rust,no_run
//! use curl::easy::Easy;
//!
//! // Write the contents of rust-lang.org to stdout
//! let mut easy = Easy::new();
//! easy.url("https://www.rust-lang.org/").unwrap();
//! easy.perform().unwrap();
//! ```
//!
//! # What about multiple concurrent HTTP requests?
//!
//! One option you have currently is to send multiple requests in multiple
//! threads, but otherwise libcurl has a "multi" interface for doing this
//! operation. This unfortunately has not yet been bound in this crate, but
//! those should be coming soon!
//!
//! # Where does libcurl come from?
//!
//! This crate links to the `curl-sys` crate which is in turn responsible for
//! acquiring and linking to the libcurl library. Currently this crate will
//! build libcurl from source if one is not already detected on the system.
//!
//! There is a large number of releases for libcurl, all with different sets of
//! capabilities. Robust programs may wish to inspect `Version::get()` to test
//! what features are implemented in the linked build of libcurl at runtime.

#![deny(missing_docs)]

extern crate curl_sys;
extern crate libc;

use std::ffi::CStr;
use std::str;
use std::sync::{Once, ONCE_INIT};

pub use error::{Error, ShareError, MultiError};
mod error;

pub use version::{Version, Protocols};
mod version;

mod panic;
pub mod easy;

/// Initializes the underlying libcurl library.
///
/// It's not required to call this before the library is used, but it's
/// recommended to do so as soon as the program starts.
pub fn init() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        unsafe {
            curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL);
            libc::atexit(cleanup);
        }
    });

    extern fn cleanup() {
        unsafe { curl_sys::curl_global_cleanup(); }
    }
}

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}
<|endoftext|>


<commit_before>#![feature(core, std_misc)]
#![cfg_attr(test, feature(io))]

extern crate "route-recognizer" as router;
extern crate conduit;

use std::collections::hash_map::{HashMap, Entry};
use std::error::Error;
use std::fmt;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler + Send + Sync>>>
}

pub struct RouterError(String);

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler + Send + Sync>>,
                                   RouterError>
    {
        match self.routers.get(method) {
            Some(router) => router.recognize(path),
            None => Err(format!("No router found for {:?}", method)),
        }.map_err(RouterError)
    }

    pub fn map<'a, H: Handler>(&'a mut self, method: Method, pattern: &str,
                               handler: H) -> &'a mut RouteBuilder {
        {
            let router = match self.routers.entry(method) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Router::new()),
            };
            router.add(pattern, Box::new(handler));
        }
        self
    }

    pub fn get<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(Method::Get, pattern, handler)
    }

    pub fn post<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(Method::Post, pattern, handler)
    }

    pub fn put<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(Method::Put, pattern, handler)
    }

    pub fn delete<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                  -> &'a mut RouteBuilder {
        self.map(Method::Delete, pattern, handler)
    }

    pub fn head<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(Method::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>> {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => return Err(Box::new(e) as Box<Error+Send>)
            }
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert(m.params.clone());
        }

        (*m.handler).call(request)
    }
}

impl Error for RouterError {
    fn description(&self) -> &str { self.0.as_slice() }
}

impl fmt::Display for RouterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a Request) -> &'a router::Params {
    req.extensions().find::<router::Params>()
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a (Request + 'a) {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::collections::HashMap;
    use std::old_io::{MemReader, IoError};
    use std::old_io::net::ip::IpAddr;

    use {RouteBuilder, RequestParams};

    use conduit;
    use conduit::{Handler, Method, Scheme, Host, Headers, Extensions, TypeMap};

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_string(),
                extensions: TypeMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<u64> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn basic_get() {
        let router = test_router();
        let mut req = RequestSentinel::new(Method::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "1, Get".to_string());
    }

    #[test]
    fn basic_post() {
        let router = test_router();
        let mut req = RequestSentinel::new(Method::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "10, Post".to_string());
    }

    #[test]
    fn nonexistent_route() {
        let router = test_router();
        let mut req = RequestSentinel::new(Method::Post, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    fn test_router() -> RouteBuilder {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", test_handler);
        router.get("/posts/:id", test_handler);
        router
    }

    fn test_handler(req: &mut conduit::Request)
                    -> Result<conduit::Response, IoError> {
        let mut res = vec!();
        res.push(req.params()["id"].clone());
        res.push(format!("{:?}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: Box::new(MemReader::new(res.connect(", ").into_bytes()))
        })
    }
}
<commit_msg>Update to rust master<commit_after>#![feature(core, std_misc)]
#![cfg_attr(test, feature(old_io))]

extern crate "route-recognizer" as router;
extern crate conduit;

use std::collections::hash_map::{HashMap, Entry};
use std::error::Error;
use std::fmt;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler>>>,
}

// FIXME(#22655) these should not be necessary
unsafe impl Sync for RouteBuilder {}
unsafe impl Send for RouteBuilder {}

pub struct RouterError(String);

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler>>,
                                   RouterError>
    {
        match self.routers.get(method) {
            Some(router) => router.recognize(path),
            None => Err(format!("No router found for {:?}", method)),
        }.map_err(RouterError)
    }

    pub fn map<'a, H: Handler>(&'a mut self, method: Method, pattern: &str,
                               handler: H) -> &'a mut RouteBuilder {
        {
            let router = match self.routers.entry(method) {
                Entry::Occupied(e) => e.into_mut(),
                Entry::Vacant(e) => e.insert(Router::new()),
            };
            router.add(pattern, Box::new(handler));
        }
        self
    }

    pub fn get<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(Method::Get, pattern, handler)
    }

    pub fn post<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(Method::Post, pattern, handler)
    }

    pub fn put<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(Method::Put, pattern, handler)
    }

    pub fn delete<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                  -> &'a mut RouteBuilder {
        self.map(Method::Delete, pattern, handler)
    }

    pub fn head<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(Method::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Error+Send>> {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => return Err(Box::new(e) as Box<Error+Send>)
            }
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert(m.params.clone());
        }

        (*m.handler).call(request)
    }
}

impl Error for RouterError {
    fn description(&self) -> &str { self.0.as_slice() }
}

impl fmt::Display for RouterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a Request) -> &'a router::Params {
    req.extensions().find::<router::Params>()
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a (Request + 'a) {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::collections::HashMap;
    use std::old_io::{MemReader, IoError};
    use std::old_io::net::ip::IpAddr;

    use {RouteBuilder, RequestParams};

    use conduit;
    use conduit::{Handler, Method, Scheme, Host, Headers, Extensions, TypeMap};

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_string(),
                extensions: TypeMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<u64> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn basic_get() {
        let router = test_router();
        let mut req = RequestSentinel::new(Method::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "1, Get".to_string());
    }

    #[test]
    fn basic_post() {
        let router = test_router();
        let mut req = RequestSentinel::new(Method::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "10, Post".to_string());
    }

    #[test]
    fn nonexistent_route() {
        let router = test_router();
        let mut req = RequestSentinel::new(Method::Post, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    fn test_router() -> RouteBuilder {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", test_handler);
        router.get("/posts/:id", test_handler);
        router
    }

    fn test_handler(req: &mut conduit::Request)
                    -> Result<conduit::Response, IoError> {
        let mut res = vec!();
        res.push(req.params()["id"].clone());
        res.push(format!("{:?}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: Box::new(MemReader::new(res.connect(", ").into_bytes()))
        })
    }
}
<|endoftext|>


<commit_before>// Copyright(C) 2016 Chris Liebert
#![crate_type = "dylib"]
#![crate_name = "quick3d"]
#![allow(dead_code)]
#[macro_use]
extern crate glium;

pub mod common;

pub mod loader;
#[macro_use]
pub mod renderer;

extern crate nalgebra;
extern crate libc;

use std::ffi::CStr;
use std::os::raw::c_char;

use glium::glutin;
use glium::glutin::{ElementState, Event, MouseButton, VirtualKeyCode};
use glium::DisplayBuild;
use glium::backend::glutin_backend::GlutinFacade;

use common::Camera;
use loader::DBLoader;
use renderer::Renderer;

#[no_mangle]
pub extern "C" fn camera_aim(camera: &Camera, x: libc::c_double, y: libc::c_double) {
	camera.aim(x as f64, y as f64);
}

#[no_mangle]
pub extern "C" fn camera_move_forward(camera: &Camera, amount: libc::c_float) {
	camera.move_forward(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_move_backward(camera: &Camera, amount: libc::c_float) {
	camera.move_backward(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_move_left(camera: &Camera, amount: libc::c_float) {
	camera.move_left(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_move_right(camera: &Camera, amount: libc::c_float) {
	camera.move_right(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_update(camera: &Camera) {
	camera.update();
}

#[no_mangle]
pub extern "C" fn create_camera(screen_width: f32, screen_height: f32) -> Box<Camera> {
    Box::new(Camera::new(screen_width, screen_height))
}

#[no_mangle]
pub extern "C" fn create_db_loader(filename_cstr: *const c_char) -> Box<DBLoader> {
    unsafe {
        let filename: String = CStr::from_ptr(filename_cstr).to_string_lossy().into_owned();
        let dbloader: DBLoader = DBLoader::new(&filename);
        println!("Loaded {}", &filename);
        Box::new(dbloader)
    }
}

#[no_mangle]
pub extern "C" fn create_display(screen_width: libc::int32_t,
                                 screen_height: libc::int32_t,
                                 title: *const c_char)
                                 -> Box<GlutinFacade> {
    let w: u32 = screen_width as u32;
    let h: u32 = screen_height as u32;
    let window_title: String;

    unsafe {
        window_title = CStr::from_ptr(title).to_string_lossy().into_owned();
        let display: GlutinFacade = glutin::WindowBuilder::new()
	        //.resizable()
	        //.with_vsync()
	        .with_gl_debug_flag(true)
	        .with_title(window_title)
	        .with_visibility(true)
	        .with_dimensions(w, h)
	        .build_glium()
	        .unwrap();
        return Box::new(display);
    }
}

#[no_mangle]
pub extern "C" fn create_renderer_from_db_loader(dbloader: &DBLoader,
                                                 display: &GlutinFacade)
                                                 -> Box<Renderer> {
    Box::new(renderer::Renderer::new(display, dbloader.load_scene()))
}

#[no_mangle]
pub extern "C" fn free_camera(ptr: *mut Camera) {
    let box_ptr: Box<Camera> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_db_loader(ptr: *mut DBLoader) {
    let box_ptr: Box<DBLoader> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_display(ptr: *mut GlutinFacade) {
    let box_ptr: Box<GlutinFacade> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_renderer(ptr: *mut Renderer) {
    let box_ptr: Box<Renderer> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_shader(ptr: *mut glium::program::Program) {
    let box_ptr: Box<glium::program::Program> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn get_shader_from_db_loader(shader_name_cstr: *const c_char,
                                            dbloader: &DBLoader,
                                            renderer: &Renderer,
                                            display: &GlutinFacade)
                                            -> Box<glium::program::Program> {
    unsafe {
        let shader_name: String = CStr::from_ptr(shader_name_cstr).to_string_lossy().into_owned();
        let shader_program = renderer.create_shader_program(&shader_name, dbloader, display);
        return Box::new(shader_program);
    }
}

#[repr(C)]
pub struct Mouse {
    pub dx: i32,
    pub dy: i32,
    pub last_x: i32,
    pub last_y: i32,
    pub left_button_pressed: bool,
    pub right_button_pressed: bool,
}

#[repr(C)]
pub struct Input {
    pub mouse: Mouse,
    pub closed: bool,
}

#[no_mangle]
pub unsafe extern "C" fn poll_event(display: &GlutinFacade) -> Input {
	static mut mouse_last_x: i32 = 0;
	static mut mouse_last_y: i32 = 0;
	static mut _mouse_dx: i32 = 0;
	static mut _mouse_dy: i32 = 0;
	static mut left_button_pressed: bool = false;
	static mut right_button_pressed: bool = false;

    // Get the screen width and height in pixels
    let pixel_dimensions: (u32, u32) = match display.get_window() {
        Some(window) => window.get_inner_size_pixels().unwrap(),
        None => {
            panic!("Error retrieving window when querying display size.");
        }
    };
    let screen_width: u32 = pixel_dimensions.0;
    let screen_height: u32 = pixel_dimensions.1;
    let screen_center_x: i32 = (screen_width / 2) as i32;
    let screen_center_y: i32 = (screen_height / 2) as i32;

    // The margin from the edge of the screen to allow before
	// mouse cursor is moved to center

    let mouse_grab_margin: i32 = screen_center_y / 2;

    let mut closed = false;

    for event in display.poll_events() {
        match event {
        	Event::Closed => closed = true,
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Escape)) => {
                closed = true
            }
            Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                left_button_pressed = true;
            }
            Event::MouseInput(ElementState::Released, MouseButton::Left) => {
                left_button_pressed = false;
            }
            Event::MouseInput(ElementState::Pressed, MouseButton::Right) => {
                right_button_pressed = true;
            }
            Event::MouseInput(ElementState::Released, MouseButton::Right) => {
                right_button_pressed = false;
            }
            Event::MouseMoved(x, y) => {
                _mouse_dx = mouse_last_x - x;
                _mouse_dy = mouse_last_y - y;
                mouse_last_x = x;
		        mouse_last_y = y;
                if left_button_pressed {
                    if x + mouse_grab_margin >= screen_width as i32 || x <= mouse_grab_margin {
                        let _ =
                            display.get_window().unwrap().set_cursor_position(screen_center_x, y);
                            _mouse_dx = 0;
                            mouse_last_x = screen_center_x;
                    } else if y + mouse_grab_margin >= screen_height as i32 || y <= mouse_grab_margin {
                        let _ =
                            display.get_window().unwrap().set_cursor_position(x, screen_center_y);
                            _mouse_dy = 0;
                            mouse_last_y = screen_center_y;
                    }
                }
            }
            _ => ()
        }
    }
    Input {
	    mouse: Mouse {
	        dx: _mouse_dx,
	        dy: _mouse_dy,
	        last_x: mouse_last_x,
	        last_y: mouse_last_y,
	        left_button_pressed: left_button_pressed,
	        right_button_pressed: right_button_pressed,
	    },
	    closed: closed,
    }
}

#[no_mangle]
pub extern "C" fn render(renderer: &Renderer,
                         shader_program: &glium::program::Program,
                         camera: &Camera,
                         display: &GlutinFacade) {
    renderer.render(display, shader_program, camera);
}

use std::sync::{Arc, Mutex};

#[repr(C)]
pub struct ConsoleInput {
    pub thread_handle: std::thread::JoinHandle<i32>,
    pub buffer: Arc<Mutex<String>>,
    pub finished: Arc<Mutex<bool>>,
}

#[no_mangle]
pub extern "C" fn create_console_reader() -> Box<ConsoleInput> {
	use std::thread;
	let buffer_arc: Arc<Mutex<String>> = Arc::new(Mutex::new(String::new()));
	let buffer_arc_copy = buffer_arc.clone();
	let finished_arc: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));
	let finished_arc_copy = finished_arc.clone();
	{
		// Initialize the finished value
		let finished = finished_arc.clone();
		let mut finished_lock = finished.lock().unwrap();
		*finished_lock = false;
	}

	let child = thread::spawn(move || {
		println!("Enter command, or return to close console");
		'console: loop {
			let mut buffer = String::new();
			match std::io::stdin().read_line(&mut buffer) {
				Ok(_) => {
					buffer = buffer
						.replace("\r", "")
						.replace("\n", " ");
					if 1 == buffer.len() { break 'console };
					let arc = buffer_arc.clone();
					let mut writer = arc.lock().unwrap();
					let mut new_string: String = (*writer).clone();
					new_string.push_str(&buffer);
					*writer = new_string;
					std::thread::yield_now();
				},
				Err(e) => println!("Error: {:?}", e),
			}
		}
		println!("Console closed");
		let finished = finished_arc.clone();
		let mut finished_lock = finished.lock().unwrap();
		*finished_lock = true;
	    return 0;
	});

	std::thread::yield_now();
	Box::new(ConsoleInput{thread_handle: child, buffer: buffer_arc_copy, finished: finished_arc_copy})
}

#[no_mangle]
pub extern "C" fn console_is_closed(console: &ConsoleInput) -> bool {
	let arc = console.finished.clone();
	let mutex = arc.lock().unwrap();
	let retval: bool = mutex.clone();
	retval
}

#[cfg(target_os = "windows")]
#[no_mangle]
pub extern "C" fn read_console_buffer(console: &ConsoleInput) -> *const u8 {
	let mut retval: String;
	let arc = console.buffer.clone();
	let mut mutex = arc.lock().unwrap();
	retval = (*mutex).clone();
	retval.push('\0');
	*mutex = String::new();
	retval.as_ptr()
}

use std::ffi::CString;

#[cfg(not(target_os = "windows"))]
#[no_mangle]
pub extern "C" fn read_console_buffer(console: &ConsoleInput) -> CString {
	let mut retval: String;
	let arc = console.buffer.clone();
	let mut mutex = arc.lock().unwrap();
	retval = (*mutex).clone();
	*mutex = String::new();
	CString::new(retval).unwrap()
}

#[no_mangle]
pub extern "C" fn wait_console_quit(handle: *mut ConsoleInput) {
	let child: Box<ConsoleInput> = unsafe { Box::from_raw(handle) };
	match child.thread_handle.join() {
		Ok(_) => {},
		Err(e) => println!("Console thread did not return: {:?}", e),
	}
}

#[no_mangle]
pub extern "C" fn hide_window(display: &GlutinFacade) {
	 match display.get_window() {
        Some(w) => {
            w.hide();
        }
        None => {
            panic!("Error retrieving window");
        }
    };
}

#[cfg(test)]
mod tests {
    use glium::glutin;
    use glium::backend::glutin_backend::GlutinFacade;
    use glium::DisplayBuild;
    use loader;
    use common::Scene;

    fn create_test_display() -> GlutinFacade {
        let display = glutin::WindowBuilder::new()
            .with_visibility(false)
            .with_gl_debug_flag(true)
            .build_glium()
            .unwrap();
        return display;
    }

    fn load_test_scene() -> Scene {
        let dbloader: loader::DBLoader = loader::DBLoader::new("test.db");
        return dbloader.load_scene();
    }

    #[test]
    fn loader_load_db_not_empty() {
        println!("Running loader_load_db_not_empty test");
        let scene: Scene = load_test_scene();
        assert!(scene.meshes.len() > 0);
        assert!(scene.materials.len() > 0);
    }

}
<commit_msg>Replaced conditional compilation logic with unified CString::into_raw() method<commit_after>// Copyright(C) 2016 Chris Liebert
#![crate_type = "dylib"]
#![crate_name = "quick3d"]
#![allow(dead_code)]
#[macro_use]
extern crate glium;

pub mod common;

pub mod loader;
#[macro_use]
pub mod renderer;

extern crate nalgebra;
extern crate libc;

use std::ffi::CStr;
use std::os::raw::c_char;

use glium::glutin;
use glium::glutin::{ElementState, Event, MouseButton, VirtualKeyCode};
use glium::DisplayBuild;
use glium::backend::glutin_backend::GlutinFacade;

use common::Camera;
use loader::DBLoader;
use renderer::Renderer;

#[no_mangle]
pub extern "C" fn camera_aim(camera: &Camera, x: libc::c_double, y: libc::c_double) {
	camera.aim(x as f64, y as f64);
}

#[no_mangle]
pub extern "C" fn camera_move_forward(camera: &Camera, amount: libc::c_float) {
	camera.move_forward(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_move_backward(camera: &Camera, amount: libc::c_float) {
	camera.move_backward(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_move_left(camera: &Camera, amount: libc::c_float) {
	camera.move_left(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_move_right(camera: &Camera, amount: libc::c_float) {
	camera.move_right(amount as f32);
}

#[no_mangle]
pub extern "C" fn camera_update(camera: &Camera) {
	camera.update();
}

#[no_mangle]
pub extern "C" fn create_camera(screen_width: f32, screen_height: f32) -> Box<Camera> {
    Box::new(Camera::new(screen_width, screen_height))
}

#[no_mangle]
pub extern "C" fn create_db_loader(filename_cstr: *const c_char) -> Box<DBLoader> {
    unsafe {
        let filename: String = CStr::from_ptr(filename_cstr).to_string_lossy().into_owned();
        let dbloader: DBLoader = DBLoader::new(&filename);
        println!("Loaded {}", &filename);
        Box::new(dbloader)
    }
}

#[no_mangle]
pub extern "C" fn create_display(screen_width: libc::int32_t,
                                 screen_height: libc::int32_t,
                                 title: *const c_char)
                                 -> Box<GlutinFacade> {
    let w: u32 = screen_width as u32;
    let h: u32 = screen_height as u32;
    let window_title: String;

    unsafe {
        window_title = CStr::from_ptr(title).to_string_lossy().into_owned();
        let display: GlutinFacade = glutin::WindowBuilder::new()
	        //.resizable()
	        //.with_vsync()
	        .with_gl_debug_flag(true)
	        .with_title(window_title)
	        .with_visibility(true)
	        .with_dimensions(w, h)
	        .build_glium()
	        .unwrap();
        return Box::new(display);
    }
}

#[no_mangle]
pub extern "C" fn create_renderer_from_db_loader(dbloader: &DBLoader,
                                                 display: &GlutinFacade)
                                                 -> Box<Renderer> {
    Box::new(renderer::Renderer::new(display, dbloader.load_scene()))
}

#[no_mangle]
pub extern "C" fn free_camera(ptr: *mut Camera) {
    let box_ptr: Box<Camera> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_db_loader(ptr: *mut DBLoader) {
    let box_ptr: Box<DBLoader> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_display(ptr: *mut GlutinFacade) {
    let box_ptr: Box<GlutinFacade> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_renderer(ptr: *mut Renderer) {
    let box_ptr: Box<Renderer> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn free_shader(ptr: *mut glium::program::Program) {
    let box_ptr: Box<glium::program::Program> = unsafe { Box::from_raw(ptr) };
    Box::into_raw(box_ptr);
}

#[no_mangle]
pub extern "C" fn get_shader_from_db_loader(shader_name_cstr: *const c_char,
                                            dbloader: &DBLoader,
                                            renderer: &Renderer,
                                            display: &GlutinFacade)
                                            -> Box<glium::program::Program> {
    unsafe {
        let shader_name: String = CStr::from_ptr(shader_name_cstr).to_string_lossy().into_owned();
        let shader_program = renderer.create_shader_program(&shader_name, dbloader, display);
        return Box::new(shader_program);
    }
}

#[repr(C)]
pub struct Mouse {
    pub dx: i32,
    pub dy: i32,
    pub last_x: i32,
    pub last_y: i32,
    pub left_button_pressed: bool,
    pub right_button_pressed: bool,
}

#[repr(C)]
pub struct Input {
    pub mouse: Mouse,
    pub closed: bool,
}

#[no_mangle]
pub unsafe extern "C" fn poll_event(display: &GlutinFacade) -> Input {
	static mut mouse_last_x: i32 = 0;
	static mut mouse_last_y: i32 = 0;
	static mut _mouse_dx: i32 = 0;
	static mut _mouse_dy: i32 = 0;
	static mut left_button_pressed: bool = false;
	static mut right_button_pressed: bool = false;

    // Get the screen width and height in pixels
    let pixel_dimensions: (u32, u32) = match display.get_window() {
        Some(window) => window.get_inner_size_pixels().unwrap(),
        None => {
            panic!("Error retrieving window when querying display size.");
        }
    };
    let screen_width: u32 = pixel_dimensions.0;
    let screen_height: u32 = pixel_dimensions.1;
    let screen_center_x: i32 = (screen_width / 2) as i32;
    let screen_center_y: i32 = (screen_height / 2) as i32;

    // The margin from the edge of the screen to allow before
	// mouse cursor is moved to center

    let mouse_grab_margin: i32 = screen_center_y / 2;

    let mut closed = false;

    for event in display.poll_events() {
        match event {
        	Event::Closed => closed = true,
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Escape)) => {
                closed = true
            }
            Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                left_button_pressed = true;
            }
            Event::MouseInput(ElementState::Released, MouseButton::Left) => {
                left_button_pressed = false;
            }
            Event::MouseInput(ElementState::Pressed, MouseButton::Right) => {
                right_button_pressed = true;
            }
            Event::MouseInput(ElementState::Released, MouseButton::Right) => {
                right_button_pressed = false;
            }
            Event::MouseMoved(x, y) => {
                _mouse_dx = mouse_last_x - x;
                _mouse_dy = mouse_last_y - y;
                mouse_last_x = x;
		        mouse_last_y = y;
                if left_button_pressed {
                    if x + mouse_grab_margin >= screen_width as i32 || x <= mouse_grab_margin {
                        let _ =
                            display.get_window().unwrap().set_cursor_position(screen_center_x, y);
                            _mouse_dx = 0;
                            mouse_last_x = screen_center_x;
                    } else if y + mouse_grab_margin >= screen_height as i32 || y <= mouse_grab_margin {
                        let _ =
                            display.get_window().unwrap().set_cursor_position(x, screen_center_y);
                            _mouse_dy = 0;
                            mouse_last_y = screen_center_y;
                    }
                }
            }
            _ => ()
        }
    }
    Input {
	    mouse: Mouse {
	        dx: _mouse_dx,
	        dy: _mouse_dy,
	        last_x: mouse_last_x,
	        last_y: mouse_last_y,
	        left_button_pressed: left_button_pressed,
	        right_button_pressed: right_button_pressed,
	    },
	    closed: closed,
    }
}

#[no_mangle]
pub extern "C" fn render(renderer: &Renderer,
                         shader_program: &glium::program::Program,
                         camera: &Camera,
                         display: &GlutinFacade) {
    renderer.render(display, shader_program, camera);
}

use std::sync::{Arc, Mutex};

#[repr(C)]
pub struct ConsoleInput {
    pub thread_handle: std::thread::JoinHandle<i32>,
    pub buffer: Arc<Mutex<String>>,
    pub finished: Arc<Mutex<bool>>,
}

#[no_mangle]
pub extern "C" fn create_console_reader() -> Box<ConsoleInput> {
	use std::thread;
	let buffer_arc: Arc<Mutex<String>> = Arc::new(Mutex::new(String::new()));
	let buffer_arc_copy = buffer_arc.clone();
	let finished_arc: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));
	let finished_arc_copy = finished_arc.clone();
	{
		// Initialize the finished value
		let finished = finished_arc.clone();
		let mut finished_lock = finished.lock().unwrap();
		*finished_lock = false;
	}

	let child = thread::spawn(move || {
		println!("Enter command, or return to close console");
		'console: loop {
			let mut buffer = String::new();
			match std::io::stdin().read_line(&mut buffer) {
				Ok(_) => {
					buffer = buffer
						.replace("\r", "")
						.replace("\n", " ");
					if 1 == buffer.len() { break 'console };
					let arc = buffer_arc.clone();
					let mut writer = arc.lock().unwrap();
					let mut new_string: String = (*writer).clone();
					new_string.push_str(&buffer);
					*writer = new_string;
					std::thread::yield_now();
				},
				Err(e) => println!("Error: {:?}", e),
			}
		}
		println!("Console closed");
		let finished = finished_arc.clone();
		let mut finished_lock = finished.lock().unwrap();
		*finished_lock = true;
	    return 0;
	});

	std::thread::yield_now();
	Box::new(ConsoleInput{thread_handle: child, buffer: buffer_arc_copy, finished: finished_arc_copy})
}

#[no_mangle]
pub extern "C" fn console_is_closed(console: &ConsoleInput) -> bool {
	let arc = console.finished.clone();
	let mutex = arc.lock().unwrap();
	mutex.clone()
}

use std::ffi::CString;

#[no_mangle]
pub extern "C" fn read_console_buffer(console: &ConsoleInput) -> *mut libc::c_char {
	let mut retval: String;
	let arc = console.buffer.clone();
	let mut mutex = arc.lock().unwrap();
	retval = (*mutex).clone();
	*mutex = String::new();
	CString::new(retval).unwrap().into_raw()
}

#[no_mangle]
pub extern "C" fn wait_console_quit(handle: *mut ConsoleInput) {
	let child: Box<ConsoleInput> = unsafe { Box::from_raw(handle) };
	match child.thread_handle.join() {
		Ok(_) => {},
		Err(e) => println!("Console thread did not return: {:?}", e),
	}
}

#[no_mangle]
pub extern "C" fn hide_window(display: &GlutinFacade) {
	 match display.get_window() {
        Some(w) => {
            w.hide();
        }
        None => {
            panic!("Error retrieving window");
        }
    };
}

#[cfg(test)]
mod tests {
    use glium::glutin;
    use glium::backend::glutin_backend::GlutinFacade;
    use glium::DisplayBuild;
    use loader;
    use common::Scene;

    fn create_test_display() -> GlutinFacade {
        let display = glutin::WindowBuilder::new()
            .with_visibility(false)
            .with_gl_debug_flag(true)
            .build_glium()
            .unwrap();
        return display;
    }

    fn load_test_scene() -> Scene {
        let dbloader: loader::DBLoader = loader::DBLoader::new("test.db");
        return dbloader.load_scene();
    }

    #[test]
    fn loader_load_db_not_empty() {
        println!("Running loader_load_db_not_empty test");
        let scene: Scene = load_test_scene();
        assert!(scene.meshes.len() > 0);
        assert!(scene.materials.len() > 0);
    }

}
<|endoftext|>