<commit_before>extern crate libc;

use std::*;
use libc::*;

#[allow(dead_code, non_camel_case_types)]
mod bladerf;
use bladerf::*;

// Macro to simplify integer returns
macro_rules! handle_res {
    ($e:expr) => (
    	if $e >= 0 {
			return Ok($e as isize)
		} else {
			return Err($e as isize)
		}
	);
	($res:expr, $out:expr) => (
		if $res >= 0 {
			return Ok($out)
		} else {
			return Err($res as isize)
		}
	);
}

pub struct BladeRFDevice {
   pub device: *mut Struct_bladerf
}

#[repr(C)]
#[repr(packed)]
pub struct iq {
	pub i: i16,
	pub q: i16
}

//impl fmt::Display for Struct_bladerf_devinfo {
//    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//        write!(f, "serial: UNIMPLEMENTED, bus: {}, address: {})", self.usb_bus, self.usb_addr)
//    }
//}

pub fn get_device_list() -> Result<Vec<Struct_bladerf_devinfo>, isize> {

	unsafe{
		let devices: *mut Struct_bladerf_devinfo = mem::uninitialized();

		let n = bladerf_get_device_list(&devices) as isize;

		// Catch bladerf function errors
		if n > 0 {

			// Cast array to slice and create a safe array to return
			let device_slice = std::slice::from_raw_parts(devices, n as usize);
			let mut safe_device_list: Vec<Struct_bladerf_devinfo> = Vec::new();

			for i in 0..n {
				let local_device = device_slice[i as usize];
				//Safe if this is a copy, unsafe if it is not?
				safe_device_list.push(local_device);
			}
			bladerf_free_device_list(devices);

			// Return rust save device info array
			Ok(safe_device_list)

		} else {
			// Return error code
			Err(n)
		}
	}
}

pub fn set_usb_reset_on_open(enabled: bool) {
    unsafe{
    	bladerf_set_usb_reset_on_open(enabled as uint8_t);
    }
}

pub fn open_with_devinfo(devinfo: &Struct_bladerf_devinfo) -> Result<BladeRFDevice, isize> {

	let devinfo_ptr: *const Struct_bladerf_devinfo = devinfo as *const Struct_bladerf_devinfo;

	unsafe {
		let bladerf_device = BladeRFDevice { device: mem::uninitialized() };

		let res = bladerf_open_with_devinfo(&(bladerf_device.device), devinfo_ptr) as isize;

		handle_res!(res, bladerf_device);
	}
}

impl BladeRFDevice {

	pub fn fw_version(&self) -> Result<Struct_bladerf_version, isize> {
		unsafe {
			let mut version: Struct_bladerf_version = mem::uninitialized();

			let res = bladerf_fw_version(self.device, &mut version as *mut Struct_bladerf_version) as isize;

			handle_res!(res, version);
		}
	}

	pub fn fpga_version(&self) -> Result<Struct_bladerf_version, isize> {
		unsafe {
			let mut version: Struct_bladerf_version = mem::uninitialized();

			let res = bladerf_fpga_version(self.device, &mut version as *mut Struct_bladerf_version) as isize;

			handle_res!(res, version);
		}
	}

	pub fn get_serial(&self) -> Result<String, isize> {
		unsafe {
			// Create raw data array for serial return
			let serial_data : Vec<::libc::c_char> = vec![0; 33];

			// Call underlying c method
			let res = bladerf_get_serial(self.device, serial_data.as_ptr()) as isize;

			if res >= 0 {
				// Map ::libc::c_char back to u8 as required for string manipulation
				let serial_u8: Vec<u8>= serial_data.iter().map(|&x| x as u8).collect();

				// Build String
				let serial_cstr = ffi::CString::from_vec_unchecked(serial_u8);
				let serial_str = serial_cstr.into_string().unwrap();

				Ok(serial_str)
			} else {
				Err(res as isize)
			}
		}
	}

	pub fn get_fpga_size(&self) -> Result<bladerf_fpga_size, isize> {
		let mut fpga_size: bladerf_fpga_size = bladerf_fpga_size::BLADERF_FPGA_UNKNOWN;

		unsafe {
			let res = bladerf_get_fpga_size(self.device, &mut fpga_size as *mut bladerf_fpga_size);

			handle_res!(res, fpga_size);
		}
	}

	pub fn is_fpga_configured(&self) -> Result<bool, isize> {
		unsafe {
			let res = bladerf_is_fpga_configured(self.device);

			if res > 0 {
				Ok(true)
			} else if res == 0 {
				Ok(false)
			} else {
				Err(res as isize)
			}
		}
	}

	pub fn load_fpga(&self, file: String) {

		unsafe {
			//let res = bladerf_load_fpga(self.device, );

			//handle_res!(res);
		}
	}

	pub fn close(&self) {
		unsafe {
			bladerf_close(self.device)
		}
	}

	pub fn enable_module(&self, module: bladerf_module, enable: bool) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_enable_module(self.device, module, enable as u8) as isize;

			handle_res!(res);
		}
	}

	pub fn set_loopback(&self, loopback: bladerf_loopback) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_set_loopback(self.device, loopback) as isize;

			handle_res!(res);
		}
	}

	pub fn get_loopback(&self) -> Result<bladerf_loopback, isize> {
		unsafe {
			let mut loopback: bladerf_loopback = mem::uninitialized();

			let res = bladerf_get_loopback(self.device, &mut loopback as *mut bladerf_loopback) as isize;

			println!("get_loopback res: {:?} loopback: {:?}", res, loopback);

			handle_res!(res, loopback);
		}
	}

	pub fn select_band(&self, module: bladerf_module, frequency: u32) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_select_band(self.device, module, frequency) as isize;

			handle_res!(res);
		}
	}

	pub fn set_frequency(&self, module: bladerf_module, frequency: u32) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_set_frequency(self.device, module, frequency) as isize;

			handle_res!(res);
		}
	}

	pub fn get_frequency(&self, module: bladerf_module) -> Result<u32, isize> {
		unsafe {
			let mut freq: u32 = 0;

			let res = bladerf_get_frequency(self.device, module, &mut freq as *mut u32) as isize;

			handle_res!(res, freq);
		}
	}

	pub fn schedule_retune(&self, module: bladerf_module, time: u64, frequency: u32, quick_tune: Option<Struct_bladerf_quick_tune>) -> Result<isize, isize> {
		unsafe {

			let mut quick_tune_int: Struct_bladerf_quick_tune;
			let p: *mut Struct_bladerf_quick_tune;

			// Check whether quick tune exists and map pointer as appropriate
			match quick_tune {
				Some(qt) => {
					quick_tune_int = qt;
					p = &mut quick_tune_int;
				},
				None => {
					p = ptr::null_mut();
				}
			}

			// Call underlying function
			let res = bladerf_schedule_retune(self.device, module, time, frequency, p) as isize;

			// Process response
			handle_res!(res)
		}
	}

	pub fn cancel_scheduled_retune(&self, module: bladerf_module) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_cancel_scheduled_retunes(self.device, module) as isize;

			handle_res!(res);
		}
	}

	pub fn get_quick_tune(&self, module: bladerf_module) -> Result<Struct_bladerf_quick_tune, isize> {
		unsafe {
			let mut quick_tune: Struct_bladerf_quick_tune = mem::uninitialized();

			let res = bladerf_get_quick_tune(self.device, module, &mut quick_tune as *mut Struct_bladerf_quick_tune) as isize;

			handle_res!(res, quick_tune);
		}
	}

	pub fn set_tuning_mode(&self, mode: bladerf_tuning_mode) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_set_tuning_mode(self.device, mode) as isize;

			handle_res!(res);
		}
	}

	pub fn sync_config(&self, module: bladerf_module, format: bladerf_format,
					   num_buffers: u32, buffer_size: u32, num_transfers: Option<u32>, stream_timeout: u32)
					   -> Result<isize, isize> {

		let num_transfers = match num_transfers { Some(t) => t, None => 4};

		unsafe {
			let res = bladerf_sync_config(self.device, module, format, num_buffers, buffer_size, num_transfers, stream_timeout);

			handle_res!(res);
		}
	}

	pub fn sync_tx(&self, data: Vec<iq>, meta: Option<Struct_bladerf_metadata>, stream_timeout: u32)
		       -> Result<isize, isize> {

		// Handle optional meta argument
		let meta_ptr: *mut Struct_bladerf_metadata = match meta {
			Some(m) => {
				let mut meta_int = m;
				&mut meta_int
			}, None => {
				ptr::null_mut()
			}
		};

		let data_ptr: *mut libc::c_void = data.as_ptr() as *mut libc::c_void;

		unsafe {
			let res = bladerf_sync_tx(self.device, data_ptr, data.len() as u32, meta_ptr, stream_timeout);

			handle_res!(res);
		}
	}

	pub fn sync_rx(&self, data: &mut Vec<iq>, meta: Option<Struct_bladerf_metadata>, stream_timeout: u32)
		       -> Result<isize, isize> {

		// Handle optional meta argument
		let meta_ptr: *mut Struct_bladerf_metadata = match meta {
			Some(m) => {
				let mut meta_int = m;
				&mut meta_int
			}, None => {
				ptr::null_mut()
			}
		};

		let data_ptr: *mut libc::c_void = data.as_ptr() as *mut libc::c_void;

		unsafe {
			let res = bladerf_sync_rx(self.device, data_ptr, data.len() as u32, meta_ptr, stream_timeout);

			handle_res!(res);
		}
	}
}

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

	#[test]
	fn test_list_devices() {
		match super::get_device_list() {
			Ok(devices) => {
				println!("Discovered {:?} devices", devices.len());
			},
			Err(code) => {
				println!("Error {:?} listing devices", code);
				assert!(false);
			}
		}
	}

	#[test]
	fn test_get_fw_version() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let version = device.fw_version().unwrap();
		println!("FW Version {:?}", version);

		device.close();
	}

	#[test]
	fn test_get_fpga_version() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let version = device.fpga_version().unwrap();
		println!("FPGA Version {:?}", version);

		device.close();
	}

	#[test]
	fn test_get_serial() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let serial = device.get_serial().unwrap();
		println!("Serial: {:?}", serial);
		assert!(serial.len() == 33);

		device.close();
	}

	#[test]
	fn test_fpga_loaded() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let loaded = device.is_fpga_configured().unwrap();
		assert_eq!(true, loaded);

		device.close();
	}

	#[test]
	fn test_loopback_modes() {
		super::set_usb_reset_on_open(true);
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		// Check initial is none
		let loopback = device.get_loopback().unwrap();
		assert!(loopback == bladerf_loopback::BLADERF_LB_NONE);

		// Set and check loopback modes
		device.set_loopback(bladerf_loopback::BLADERF_LB_FIRMWARE).unwrap();
		let loopback = device.get_loopback().unwrap();
		assert!(loopback == bladerf_loopback::BLADERF_LB_FIRMWARE);

		// Reset
		device.set_loopback(bladerf_loopback::BLADERF_LB_NONE).unwrap();

		device.close();
	}
}
<commit_msg>Cleaning up<commit_after>extern crate libc;

use std::*;
use libc::*;

#[allow(dead_code, non_camel_case_types)]
mod bladerf;
use bladerf::*;

// Macro to simplify integer returns
macro_rules! handle_res {
    ($e:expr) => (
    	if $e >= 0 {
			return Ok($e as isize)
		} else {
			return Err($e as isize)
		}
	);
	($res:expr, $out:expr) => (
		if $res >= 0 {
			return Ok($out)
		} else {
			return Err($res as isize)
		}
	);
}

pub struct BladeRFDevice {
   pub device: *mut Struct_bladerf
}

#[repr(C)]
#[repr(packed)]
pub struct iq {
	pub i: i16,
	pub q: i16
}

//impl fmt::Display for Struct_bladerf_devinfo {
//    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//        write!(f, "serial: UNIMPLEMENTED, bus: {}, address: {})", self.usb_bus, self.usb_addr)
//    }
//}

pub fn get_device_list() -> Result<Vec<Struct_bladerf_devinfo>, isize> {

	unsafe{
		let devices: *mut Struct_bladerf_devinfo = mem::uninitialized();

		let n = bladerf_get_device_list(&devices) as isize;

		// Catch bladerf function errors
		if n > 0 {

			// Cast array to slice and create a safe array to return
			let device_slice = std::slice::from_raw_parts(devices, n as usize);
			let mut safe_device_list: Vec<Struct_bladerf_devinfo> = Vec::new();

			for i in 0..n {
				let local_device = device_slice[i as usize];
				//Safe if this is a copy, unsafe if it is not?
				safe_device_list.push(local_device);
			}
			bladerf_free_device_list(devices);

			// Return rust save device info array
			Ok(safe_device_list)

		} else {
			// Return error code
			Err(n)
		}
	}
}

pub fn set_usb_reset_on_open(enabled: bool) {
    unsafe{
    	bladerf_set_usb_reset_on_open(enabled as uint8_t);
    }
}

pub fn open_with_devinfo(devinfo: &Struct_bladerf_devinfo) -> Result<BladeRFDevice, isize> {

	let devinfo_ptr: *const Struct_bladerf_devinfo = devinfo as *const Struct_bladerf_devinfo;

	unsafe {
		let bladerf_device = BladeRFDevice { device: mem::uninitialized() };

		let res = bladerf_open_with_devinfo(&(bladerf_device.device), devinfo_ptr);

		handle_res!(res, bladerf_device);
	}
}

impl BladeRFDevice {

	pub fn fw_version(&self) -> Result<Struct_bladerf_version, isize> {
		unsafe {
			let mut version: Struct_bladerf_version = mem::uninitialized();

			let res = bladerf_fw_version(self.device, &mut version as *mut Struct_bladerf_version);

			handle_res!(res, version);
		}
	}

	pub fn fpga_version(&self) -> Result<Struct_bladerf_version, isize> {
		unsafe {
			let mut version: Struct_bladerf_version = mem::uninitialized();

			let res = bladerf_fpga_version(self.device, &mut version as *mut Struct_bladerf_version);

			handle_res!(res, version);
		}
	}

	pub fn get_serial(&self) -> Result<String, isize> {
		unsafe {
			// Create raw data array for serial return
			let serial_data : Vec<::libc::c_char> = vec![0; 33];

			// Call underlying c method
			let res = bladerf_get_serial(self.device, serial_data.as_ptr());

			if res >= 0 {
				// Map ::libc::c_char back to u8 as required for string manipulation
				let serial_u8: Vec<u8>= serial_data.iter().map(|&x| x as u8).collect();

				// Build String
				let serial_cstr = ffi::CString::from_vec_unchecked(serial_u8);
				let serial_str = serial_cstr.into_string().unwrap();

				Ok(serial_str)
			} else {
				Err(res as isize)
			}
		}
	}

	pub fn get_fpga_size(&self) -> Result<bladerf_fpga_size, isize> {
		let mut fpga_size: bladerf_fpga_size = bladerf_fpga_size::BLADERF_FPGA_UNKNOWN;

		unsafe {
			let res = bladerf_get_fpga_size(self.device, &mut fpga_size as *mut bladerf_fpga_size);

			handle_res!(res, fpga_size);
		}
	}

	pub fn is_fpga_configured(&self) -> Result<bool, isize> {
		unsafe {
			let res = bladerf_is_fpga_configured(self.device);

			if res > 0 {
				Ok(true)
			} else if res == 0 {
				Ok(false)
			} else {
				Err(res as isize)
			}
		}
	}

	pub fn load_fpga(&self, file: String) -> Result<isize, isize>  {
		let c_string = ffi::CString::new(file.into_bytes()).unwrap();

		unsafe {
			let res = bladerf_load_fpga(self.device, c_string.as_ptr());

			handle_res!(res)
		}
	}

	pub fn close(&self) {
		unsafe {
			bladerf_close(self.device)
		}
	}

	pub fn enable_module(&self, module: bladerf_module, enable: bool) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_enable_module(self.device, module, enable as u8);

			handle_res!(res);
		}
	}

	pub fn set_loopback(&self, loopback: bladerf_loopback) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_set_loopback(self.device, loopback);

			handle_res!(res);
		}
	}

	pub fn get_loopback(&self) -> Result<bladerf_loopback, isize> {
		unsafe {
			let mut loopback: bladerf_loopback = mem::uninitialized();

			let res = bladerf_get_loopback(self.device, &mut loopback as *mut bladerf_loopback);

			println!("get_loopback res: {:?} loopback: {:?}", res, loopback);

			handle_res!(res, loopback);
		}
	}

	pub fn select_band(&self, module: bladerf_module, frequency: u32) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_select_band(self.device, module, frequency);

			handle_res!(res);
		}
	}

	pub fn set_frequency(&self, module: bladerf_module, frequency: u32) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_set_frequency(self.device, module, frequency);

			handle_res!(res);
		}
	}

	pub fn get_frequency(&self, module: bladerf_module) -> Result<u32, isize> {
		unsafe {
			let mut freq: u32 = 0;

			let res = bladerf_get_frequency(self.device, module, &mut freq as *mut u32);

			handle_res!(res, freq);
		}
	}

	pub fn schedule_retune(&self, module: bladerf_module, time: u64, frequency: u32, quick_tune: Option<Struct_bladerf_quick_tune>) -> Result<isize, isize> {
		unsafe {

			let mut quick_tune_int: Struct_bladerf_quick_tune;
			let p: *mut Struct_bladerf_quick_tune;

			// Check whether quick tune exists and map pointer as appropriate
			match quick_tune {
				Some(qt) => {
					quick_tune_int = qt;
					p = &mut quick_tune_int;
				},
				None => {
					p = ptr::null_mut();
				}
			}

			// Call underlying function
			let res = bladerf_schedule_retune(self.device, module, time, frequency, p);

			// Process response
			handle_res!(res)
		}
	}

	pub fn cancel_scheduled_retune(&self, module: bladerf_module) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_cancel_scheduled_retunes(self.device, module) as isize;

			handle_res!(res);
		}
	}

	pub fn get_quick_tune(&self, module: bladerf_module) -> Result<Struct_bladerf_quick_tune, isize> {
		unsafe {
			let mut quick_tune: Struct_bladerf_quick_tune = mem::uninitialized();

			let res = bladerf_get_quick_tune(self.device, module, &mut quick_tune as *mut Struct_bladerf_quick_tune);

			handle_res!(res, quick_tune);
		}
	}

	pub fn set_tuning_mode(&self, mode: bladerf_tuning_mode) -> Result<isize, isize> {
		unsafe {
			let res = bladerf_set_tuning_mode(self.device, mode) as isize;

			handle_res!(res);
		}
	}

	pub fn sync_config(&self, module: bladerf_module, format: bladerf_format,
					   num_buffers: u32, buffer_size: u32, num_transfers: Option<u32>, stream_timeout: u32)
					   -> Result<isize, isize> {

		let num_transfers = match num_transfers { Some(t) => t, None => 4};

		unsafe {
			let res = bladerf_sync_config(self.device, module, format, num_buffers, buffer_size, num_transfers, stream_timeout);

			handle_res!(res);
		}
	}

	pub fn sync_tx(&self, data: Vec<iq>, meta: Option<Struct_bladerf_metadata>, stream_timeout: u32)
		       -> Result<isize, isize> {

		// Handle optional meta argument
		let meta_ptr: *mut Struct_bladerf_metadata = match meta {
			Some(m) => {
				let mut meta_int = m;
				&mut meta_int
			}, None => {
				ptr::null_mut()
			}
		};

		let data_ptr: *mut libc::c_void = data.as_ptr() as *mut libc::c_void;

		unsafe {
			let res = bladerf_sync_tx(self.device, data_ptr, data.len() as u32, meta_ptr, stream_timeout);

			handle_res!(res);
		}
	}

	pub fn sync_rx(&self, data: &mut Vec<iq>, meta: Option<Struct_bladerf_metadata>, stream_timeout: u32)
		       -> Result<isize, isize> {

		// Handle optional meta argument
		let meta_ptr: *mut Struct_bladerf_metadata = match meta {
			Some(m) => {
				let mut meta_int = m;
				&mut meta_int
			}, None => {
				ptr::null_mut()
			}
		};

		let data_ptr: *mut libc::c_void = data.as_ptr() as *mut libc::c_void;

		unsafe {
			let res = bladerf_sync_rx(self.device, data_ptr, data.len() as u32, meta_ptr, stream_timeout);

			handle_res!(res);
		}
	}
}

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

	#[test]
	fn test_list_devices() {
		match super::get_device_list() {
			Ok(devices) => {
				println!("Discovered {:?} devices", devices.len());
			},
			Err(code) => {
				println!("Error {:?} listing devices", code);
				assert!(false);
			}
		}
	}

	#[test]
	fn test_get_fw_version() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let version = device.fw_version().unwrap();
		println!("FW Version {:?}", version);

		device.close();
	}

	#[test]
	fn test_get_fpga_version() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let version = device.fpga_version().unwrap();
		println!("FPGA Version {:?}", version);

		device.close();
	}

	#[test]
	fn test_get_serial() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let serial = device.get_serial().unwrap();
		println!("Serial: {:?}", serial);
		assert!(serial.len() == 33);

		device.close();
	}

	#[test]
	fn test_fpga_loaded() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		let loaded = device.is_fpga_configured().unwrap();
		assert_eq!(true, loaded);

		device.close();
	}

	#[test]
	fn test_loopback_modes() {
		super::set_usb_reset_on_open(true);
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();

		// Check initial is none
		let loopback = device.get_loopback().unwrap();
		assert!(loopback == bladerf_loopback::BLADERF_LB_NONE);

		// Set and check loopback modes
		device.set_loopback(bladerf_loopback::BLADERF_LB_FIRMWARE).unwrap();
		let loopback = device.get_loopback().unwrap();
		assert!(loopback == bladerf_loopback::BLADERF_LB_FIRMWARE);

		// Reset
		device.set_loopback(bladerf_loopback::BLADERF_LB_NONE).unwrap();

		device.close();
	}
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

extern crate libc;
use libc::{
	c_void,
	c_char,
	c_uchar,
	c_int,
	c_uint,
	int8_t,
	int16_t,
	uint16_t,
	int32_t,
	uint32_t,
	c_double,
};

pub const FREENECT_COUNTS_PER_G: 		c_int = 829;
pub const FREENECT_DEPTH_MM_MAX_VALUE: 	c_int = 10000;
pub const FREENECT_DEPTH_MM_NO_VALUE: 	c_int = 0;
pub const FREENECT_DEPTH_RAW_MAX_VALUE: c_int = 2048;
pub const FREENECT_DEPTH_RAW_NO_VALUE: 	c_int = 2047;

#[repr(C)] pub enum freenect_device_flags {
	FREENECT_DEVICE_MOTOR  = 0x01,
	FREENECT_DEVICE_CAMERA = 0x02,
	FREENECT_DEVICE_AUDIO  = 0x04,
}

#[repr(C)] pub struct freenect_device_attributes {
	pub next: *mut freenect_device_attributes,
	pub camera_serial: *const c_char,
}

#[repr(C)] pub enum freenect_resolution {
	FREENECT_RESOLUTION_LOW    = 0, // QVGA - 320x240
	FREENECT_RESOLUTION_MEDIUM = 1, // VGA  - 640x480
	FREENECT_RESOLUTION_HIGH   = 2, // SXGA - 1280x1024
	FREENECT_RESOLUTION_DUMMY  = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_video_format {
	FREENECT_VIDEO_RGB             = 0, // Decompressed RGB mode (demosaicing done by libfreenect)
	FREENECT_VIDEO_BAYER           = 1, // Bayer compressed mode (raw information from camera)
	FREENECT_VIDEO_IR_8BIT         = 2, // 8-bit IR mode
	FREENECT_VIDEO_IR_10BIT        = 3, // 10-bit IR mode
	FREENECT_VIDEO_IR_10BIT_PACKED = 4, // 10-bit packed IR mode
	FREENECT_VIDEO_YUV_RGB         = 5, // YUV RGB mode
	FREENECT_VIDEO_YUV_RAW         = 6, // YUV Raw mode
	FREENECT_VIDEO_DUMMY           = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_depth_format {
	FREENECT_DEPTH_11BIT        = 0, // 11 bit depth information in one uint16_t/pixel
	FREENECT_DEPTH_10BIT        = 1, // 10 bit depth information in one uint16_t/pixel
	FREENECT_DEPTH_11BIT_PACKED = 2, // 11 bit packed depth information
	FREENECT_DEPTH_10BIT_PACKED = 3, // 10 bit packed depth information
	FREENECT_DEPTH_REGISTERED   = 4, // processed depth data in mm, aligned to 640x480 RGB
	FREENECT_DEPTH_MM           = 5, // depth to each pixel in mm, but left unaligned to RGB image
	FREENECT_DEPTH_DUMMY        = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_flag {
	FREENECT_AUTO_EXPOSURE      = 1 << 14,
	FREENECT_AUTO_WHITE_BALANCE = 1 << 1,
	FREENECT_RAW_COLOR          = 1 << 4,
	FREENECT_MIRROR_DEPTH       = 0x0017,
	FREENECT_MIRROR_VIDEO       = 0x0047,
}

#[repr(C)] pub enum freenect_flag_value {
	FREENECT_OFF = 0,
	FREENECT_ON  = 1,
}

#[repr(C)] pub struct freenect_frame_mode {
	pub reserved: uint32_t,              // unique ID used internally.  The meaning of values may change without notice.  Don't touch or depend on the contents of this field.  We mean it.
	pub resolution: freenect_resolution, // Resolution this freenect_frame_mode describes, should you want to find it again with freenect_find_*_frame_mode().
	pub dummy: int32_t,                  // The video or depth format that this freenect_frame_mode describes.  The caller should know which of video_format or depth_format to use, since they called freenect_get_*_frame_mode()
	pub bytes: int32_t,                  // Total buffer size in bytes to hold a single frame of data.  Should be equivalent to width * height * (data_bits_per_pixel+padding_bits_per_pixel) / 8
	pub width: int16_t,                  // Width of the frame, in pixels
	pub height: int16_t,                 // Height of the frame, in pixels
	pub data_bits_per_pixel: int8_t,     // Number of bits of information needed for each pixel
	pub padding_bits_per_pixel: int8_t,  // Number of bits of padding for alignment used for each pixel
	pub framerate: int8_t,               // Approximate expected frame rate, in Hz
	pub is_valid: int8_t,                // If 0, this freenect_frame_mode is invalid and does not describe a supported mode.  Otherwise, the frame_mode is valid.
}

#[repr(C)] pub enum freenect_led_option {
	LED_OFF              = 0, // Turn LED off
	LED_GREEN            = 1, // Turn LED to Green
	LED_RED              = 2, // Turn LED to Red
	LED_YELLOW           = 3, // Turn LED to Yellow
	LED_BLINK_GREEN      = 4, // Make LED blink Green
	// 5 is same as 4, LED blink Green
	LED_BLINK_RED_YELLOW = 6, // Make LED blink Red/Yellow
}

#[repr(C)] pub enum freenect_tilt_status_code {
	TILT_STATUS_STOPPED = 0x00, // Tilt motor is stopped
	TILT_STATUS_LIMIT   = 0x01, // Tilt motor has reached movement limit
	TILT_STATUS_MOVING  = 0x04, // Tilt motor is currently moving to new position
}

#[repr(C)] pub struct freenect_raw_tilt_state {
	pub accelerometer_x: int16_t                  , // Raw accelerometer data for X-axis, see FREENECT_COUNTS_PER_G for conversion
	pub accelerometer_y: int16_t                  , // Raw accelerometer data for Y-axis, see FREENECT_COUNTS_PER_G for conversion
	pub accelerometer_z: int16_t                  , // Raw accelerometer data for Z-axis, see FREENECT_COUNTS_PER_G for conversion
	pub tilt_angle:      int8_t                   , // Raw tilt motor angle encoder information
	pub tilt_status: 	 freenect_tilt_status_code, // State of the tilt motor (stopped, moving, etc...)
}

pub enum freenect_context {}

pub enum freenect_device {}

pub enum freenect_usb_context {}

#[repr(C)] pub enum freenect_loglevel {
	FREENECT_LOG_FATAL = 0,     // Log for crashing/non-recoverable errors
	FREENECT_LOG_ERROR,         // Log for major errors
	FREENECT_LOG_WARNING,       // Log for warning messages
	FREENECT_LOG_NOTICE,        // Log for important messages
	FREENECT_LOG_INFO,          // Log for normal messages
	FREENECT_LOG_DEBUG,         // Log for useful development messages
	FREENECT_LOG_SPEW,          // Log for slightly less useful messages
	FREENECT_LOG_FLOOD,         // Log EVERYTHING. May slow performance.
}

pub type freenect_log_cb   = extern fn(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char);
pub type freenect_depth_cb = extern fn(dev: *mut freenect_device, depth: *mut c_void, timestamp: uint32_t);
pub type freenect_video_cb = extern fn(dev: *mut freenect_device, video: *mut c_void, timestamp: uint32_t);

#[link(name = "freenect")]
extern "C" {
    pub fn freenect_init(ctx: *mut *mut freenect_context, usb_ctx: *mut freenect_usb_context) -> c_int;
	pub fn freenect_shutdown(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_set_log_level(ctx: *mut freenect_context, level: freenect_loglevel);
	pub fn freenect_set_log_callback(ctx: *mut freenect_context, cb: freenect_log_cb);
	pub fn freenect_process_events(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_process_events_timeout(ctx: *mut freenect_context, timeout: libc::timeval) -> c_int;
	pub fn freenect_num_devices(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_list_device_attributes(ctx: *mut freenect_context, attribute_list: *mut *mut freenect_device_attributes) -> c_int;
	pub fn freenect_free_device_attributes(attribute_list: *mut freenect_device_attributes);
	pub fn freenect_supported_subdevices() -> c_int;
	pub fn freenect_select_subdevices(ctx: *mut freenect_context, subdevs: u32); // Not enum type as bitfield can have multiple choices
	pub fn freenect_enabled_subdevices(ctx: *mut freenect_context) -> freenect_device_flags;
	pub fn freenect_open_device(ctx: *mut freenect_context, dev: *mut *mut freenect_device, index: c_int) -> c_int;
	pub fn freenect_open_device_by_camera_serial(ctx: *mut freenect_context, dev: *mut *mut freenect_device, camera_serial: *const c_char) -> c_int;
	pub fn freenect_close_device(dev: *mut freenect_device) -> c_int;
	pub fn freenect_set_user(dev: *mut freenect_device, user: *mut c_void);
	pub fn freenect_get_user(dev: *mut freenect_device) -> *mut c_void;
	pub fn freenect_set_depth_callback(dev: *mut freenect_device, cb: freenect_depth_cb);
	pub fn freenect_set_video_callback(dev: *mut freenect_device, cb: freenect_video_cb);
	pub fn freenect_set_depth_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
	pub fn freenect_set_video_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
	pub fn freenect_start_depth(dev: *mut freenect_device) -> c_int;
	pub fn freenect_start_video(dev: *mut freenect_device) -> c_int;
	pub fn freenect_stop_depth(dev: *mut freenect_device) -> c_int;
	pub fn freenect_stop_video(dev: *mut freenect_device) -> c_int;
	pub fn freenect_update_tilt_state(dev: *mut freenect_device) -> c_int;
	pub fn freenect_get_tilt_state(dev: *mut freenect_device) -> *mut freenect_raw_tilt_state;
	pub fn freenect_get_tilt_degs(state: *mut freenect_raw_tilt_state) -> c_double;
	pub fn freenect_set_tilt_degs(dev: *mut freenect_device, angle: c_double) -> c_int;
	pub fn freenect_get_tilt_status(state: *mut freenect_raw_tilt_state) -> freenect_tilt_status_code;
	pub fn freenect_set_led(dev: *mut freenect_device, option: freenect_led_option) -> c_int;
	pub fn freenect_get_mks_accel(state: *mut freenect_raw_tilt_state, x: *mut c_double, y: *mut c_double, z: *mut c_double);
	pub fn freenect_get_video_mode_count() -> c_int;
	pub fn freenect_get_video_mode(mode_num: c_int) -> freenect_frame_mode;
	pub fn freenect_get_current_video_mode(dev: *mut freenect_device) -> freenect_frame_mode;
	pub fn freenect_find_video_mode(res: freenect_resolution, fmt: freenect_video_format) -> freenect_frame_mode;
	pub fn freenect_set_video_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
	pub fn freenect_get_depth_mode_count() -> c_int;
	pub fn freenect_get_depth_mode(mode_num: c_int) -> freenect_frame_mode;
	pub fn freenect_get_current_depth_mode(dev: *mut freenect_device) -> freenect_frame_mode;
	pub fn freenect_find_depth_mode(res: freenect_resolution, fmt: freenect_depth_format) -> freenect_frame_mode;
	pub fn freenect_set_depth_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
	pub fn freenect_set_flag(dev: *mut freenect_device, flag: freenect_flag, value: freenect_flag_value) -> c_int;
}
<commit_msg>Convert tabs to spaces<commit_after>#![allow(non_camel_case_types)]

extern crate libc;
use libc::{
    c_void,
    c_char,
    c_uchar,
    c_int,
    c_uint,
    int8_t,
    int16_t,
    uint16_t,
    int32_t,
    uint32_t,
    c_double,
};

pub const FREENECT_COUNTS_PER_G: 		c_int = 819;
pub const FREENECT_DEPTH_MM_MAX_VALUE: 	c_int = 10000;
pub const FREENECT_DEPTH_MM_NO_VALUE: 	c_int = 0;
pub const FREENECT_DEPTH_RAW_MAX_VALUE: c_int = 2048;
pub const FREENECT_DEPTH_RAW_NO_VALUE: 	c_int = 2047;

#[repr(C)] pub enum freenect_device_flags {
    FREENECT_DEVICE_MOTOR  = 0x01,
    FREENECT_DEVICE_CAMERA = 0x02,
    FREENECT_DEVICE_AUDIO  = 0x04,
}

#[repr(C)] pub struct freenect_device_attributes {
    pub next: *mut freenect_device_attributes,
    pub camera_serial: *const c_char,
}

#[repr(C)] pub enum freenect_resolution {
    FREENECT_RESOLUTION_LOW    = 0, // QVGA - 320x240
    FREENECT_RESOLUTION_MEDIUM = 1, // VGA  - 640x480
    FREENECT_RESOLUTION_HIGH   = 2, // SXGA - 1280x1024
    FREENECT_RESOLUTION_DUMMY  = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_video_format {
    FREENECT_VIDEO_RGB             = 0, // Decompressed RGB mode (demosaicing done by libfreenect)
    FREENECT_VIDEO_BAYER           = 1, // Bayer compressed mode (raw information from camera)
    FREENECT_VIDEO_IR_8BIT         = 2, // 8-bit IR mode
    FREENECT_VIDEO_IR_10BIT        = 3, // 10-bit IR mode
    FREENECT_VIDEO_IR_10BIT_PACKED = 4, // 10-bit packed IR mode
    FREENECT_VIDEO_YUV_RGB         = 5, // YUV RGB mode
    FREENECT_VIDEO_YUV_RAW         = 6, // YUV Raw mode
    FREENECT_VIDEO_DUMMY           = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_depth_format {
    FREENECT_DEPTH_11BIT        = 0, // 11 bit depth information in one uint16_t/pixel
    FREENECT_DEPTH_10BIT        = 1, // 10 bit depth information in one uint16_t/pixel
    FREENECT_DEPTH_11BIT_PACKED = 2, // 11 bit packed depth information
    FREENECT_DEPTH_10BIT_PACKED = 3, // 10 bit packed depth information
    FREENECT_DEPTH_REGISTERED   = 4, // processed depth data in mm, aligned to 640x480 RGB
    FREENECT_DEPTH_MM           = 5, // depth to each pixel in mm, but left unaligned to RGB image
    FREENECT_DEPTH_DUMMY        = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_flag {
    FREENECT_AUTO_EXPOSURE      = 1 << 14,
    FREENECT_AUTO_WHITE_BALANCE = 1 << 1,
    FREENECT_RAW_COLOR          = 1 << 4,
    FREENECT_MIRROR_DEPTH       = 0x0017,
    FREENECT_MIRROR_VIDEO       = 0x0047,
}

#[repr(C)] pub enum freenect_flag_value {
    FREENECT_OFF = 0,
    FREENECT_ON  = 1,
}

#[repr(C)] pub struct freenect_frame_mode {
    pub reserved: uint32_t,              // unique ID used internally.  The meaning of values may change without notice.  Don't touch or depend on the contents of this field.  We mean it.
    pub resolution: freenect_resolution, // Resolution this freenect_frame_mode describes, should you want to find it again with freenect_find_*_frame_mode().
    pub dummy: int32_t,                  // The video or depth format that this freenect_frame_mode describes.  The caller should know which of video_format or depth_format to use, since they called freenect_get_*_frame_mode()
    pub bytes: int32_t,                  // Total buffer size in bytes to hold a single frame of data.  Should be equivalent to width * height * (data_bits_per_pixel+padding_bits_per_pixel) / 8
    pub width: int16_t,                  // Width of the frame, in pixels
    pub height: int16_t,                 // Height of the frame, in pixels
    pub data_bits_per_pixel: int8_t,     // Number of bits of information needed for each pixel
    pub padding_bits_per_pixel: int8_t,  // Number of bits of padding for alignment used for each pixel
    pub framerate: int8_t,               // Approximate expected frame rate, in Hz
    pub is_valid: int8_t,                // If 0, this freenect_frame_mode is invalid and does not describe a supported mode.  Otherwise, the frame_mode is valid.
}

#[repr(C)] pub enum freenect_led_option {
    LED_OFF              = 0, // Turn LED off
    LED_GREEN            = 1, // Turn LED to Green
    LED_RED              = 2, // Turn LED to Red
    LED_YELLOW           = 3, // Turn LED to Yellow
    LED_BLINK_GREEN      = 4, // Make LED blink Green
    // 5 is same as 4, LED blink Green
    LED_BLINK_RED_YELLOW = 6, // Make LED blink Red/Yellow
}

#[repr(C)] pub enum freenect_tilt_status_code {
    TILT_STATUS_STOPPED = 0x00, // Tilt motor is stopped
    TILT_STATUS_LIMIT   = 0x01, // Tilt motor has reached movement limit
    TILT_STATUS_MOVING  = 0x04, // Tilt motor is currently moving to new position
}

#[repr(C)] pub struct freenect_raw_tilt_state {
    pub accelerometer_x: int16_t                  , // Raw accelerometer data for X-axis, see FREENECT_COUNTS_PER_G for conversion
    pub accelerometer_y: int16_t                  , // Raw accelerometer data for Y-axis, see FREENECT_COUNTS_PER_G for conversion
    pub accelerometer_z: int16_t                  , // Raw accelerometer data for Z-axis, see FREENECT_COUNTS_PER_G for conversion
    pub tilt_angle:      int8_t                   , // Raw tilt motor angle encoder information
    pub tilt_status: 	 freenect_tilt_status_code, // State of the tilt motor (stopped, moving, etc...)
}

pub enum freenect_context {}

pub enum freenect_device {}

pub enum freenect_usb_context {}

#[repr(C)] pub enum freenect_loglevel {
    FREENECT_LOG_FATAL = 0,     // Log for crashing/non-recoverable errors
    FREENECT_LOG_ERROR,         // Log for major errors
    FREENECT_LOG_WARNING,       // Log for warning messages
    FREENECT_LOG_NOTICE,        // Log for important messages
    FREENECT_LOG_INFO,          // Log for normal messages
    FREENECT_LOG_DEBUG,         // Log for useful development messages
    FREENECT_LOG_SPEW,          // Log for slightly less useful messages
    FREENECT_LOG_FLOOD,         // Log EVERYTHING. May slow performance.
}

pub type freenect_log_cb   = extern fn(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char);
pub type freenect_depth_cb = extern fn(dev: *mut freenect_device, depth: *mut c_void, timestamp: uint32_t);
pub type freenect_video_cb = extern fn(dev: *mut freenect_device, video: *mut c_void, timestamp: uint32_t);

#[link(name = "freenect")]
extern "C" {
    pub fn freenect_init(ctx: *mut *mut freenect_context, usb_ctx: *mut freenect_usb_context) -> c_int;
    pub fn freenect_shutdown(ctx: *mut freenect_context) -> c_int;
    pub fn freenect_set_log_level(ctx: *mut freenect_context, level: freenect_loglevel);
    pub fn freenect_set_log_callback(ctx: *mut freenect_context, cb: freenect_log_cb);
    pub fn freenect_process_events(ctx: *mut freenect_context) -> c_int;
    pub fn freenect_process_events_timeout(ctx: *mut freenect_context, timeout: libc::timeval) -> c_int;
    pub fn freenect_num_devices(ctx: *mut freenect_context) -> c_int;
    pub fn freenect_list_device_attributes(ctx: *mut freenect_context, attribute_list: *mut *mut freenect_device_attributes) -> c_int;
    pub fn freenect_free_device_attributes(attribute_list: *mut freenect_device_attributes);
    pub fn freenect_supported_subdevices() -> c_int;
    pub fn freenect_select_subdevices(ctx: *mut freenect_context, subdevs: u32); // Not enum type as bitfield can have multiple choices
    pub fn freenect_enabled_subdevices(ctx: *mut freenect_context) -> freenect_device_flags;
    pub fn freenect_open_device(ctx: *mut freenect_context, dev: *mut *mut freenect_device, index: c_int) -> c_int;
    pub fn freenect_open_device_by_camera_serial(ctx: *mut freenect_context, dev: *mut *mut freenect_device, camera_serial: *const c_char) -> c_int;
    pub fn freenect_close_device(dev: *mut freenect_device) -> c_int;
    pub fn freenect_set_user(dev: *mut freenect_device, user: *mut c_void);
    pub fn freenect_get_user(dev: *mut freenect_device) -> *mut c_void;
    pub fn freenect_set_depth_callback(dev: *mut freenect_device, cb: freenect_depth_cb);
    pub fn freenect_set_video_callback(dev: *mut freenect_device, cb: freenect_video_cb);
    pub fn freenect_set_depth_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
    pub fn freenect_set_video_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
    pub fn freenect_start_depth(dev: *mut freenect_device) -> c_int;
    pub fn freenect_start_video(dev: *mut freenect_device) -> c_int;
    pub fn freenect_stop_depth(dev: *mut freenect_device) -> c_int;
    pub fn freenect_stop_video(dev: *mut freenect_device) -> c_int;
    pub fn freenect_update_tilt_state(dev: *mut freenect_device) -> c_int;
    pub fn freenect_get_tilt_state(dev: *mut freenect_device) -> *mut freenect_raw_tilt_state;
    pub fn freenect_get_tilt_degs(state: *mut freenect_raw_tilt_state) -> c_double;
    pub fn freenect_set_tilt_degs(dev: *mut freenect_device, angle: c_double) -> c_int;
    pub fn freenect_get_tilt_status(state: *mut freenect_raw_tilt_state) -> freenect_tilt_status_code;
    pub fn freenect_set_led(dev: *mut freenect_device, option: freenect_led_option) -> c_int;
    pub fn freenect_get_mks_accel(state: *mut freenect_raw_tilt_state, x: *mut c_double, y: *mut c_double, z: *mut c_double);
    pub fn freenect_get_video_mode_count() -> c_int;
    pub fn freenect_get_video_mode(mode_num: c_int) -> freenect_frame_mode;
    pub fn freenect_get_current_video_mode(dev: *mut freenect_device) -> freenect_frame_mode;
    pub fn freenect_find_video_mode(res: freenect_resolution, fmt: freenect_video_format) -> freenect_frame_mode;
    pub fn freenect_set_video_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
    pub fn freenect_get_depth_mode_count() -> c_int;
    pub fn freenect_get_depth_mode(mode_num: c_int) -> freenect_frame_mode;
    pub fn freenect_get_current_depth_mode(dev: *mut freenect_device) -> freenect_frame_mode;
    pub fn freenect_find_depth_mode(res: freenect_resolution, fmt: freenect_depth_format) -> freenect_frame_mode;
    pub fn freenect_set_depth_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
    pub fn freenect_set_flag(dev: *mut freenect_device, flag: freenect_flag, value: freenect_flag_value) -> c_int;
}
<|endoftext|>


<commit_before>//! Algorithmia client library
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Algorithmia;
//! use algorithmia::algo::{Algorithm, AlgoOutput, Version};
//!
//! // Initialize with an API key
//! let client = Algorithmia::client("111112222233333444445555566");
//! let moving_avg = client.algo("timeseries", "SimpleMovingAverage", Version::Minor(0,1));
//!
//! // Run the algorithm using a type safe decoding of the output to Vec<int>
//! //   since this algorithm outputs results as a JSON array of integers
//! let input = (vec![0,1,2,3,15,4,5,6,7], 3);
//! let output: AlgoOutput<Vec<f64>> = moving_avg.pipe(&input).unwrap();
//! println!("Completed in {} seconds with result: {:?}", output.metadata.duration, output.result);
//! ```

#![doc(html_logo_url = "https://algorithmia.com/assets/images/apple-touch-icon.png")]

extern crate hyper;
extern crate rustc_serialize;

pub mod algo;
pub mod data;

use algo::{Algorithm, Version};
use data::{DataDir, DataFile};

use hyper::{Client, Url};
use hyper::client::RequestBuilder;
use hyper::header::{Authorization, UserAgent};
use hyper::method::Method;
use rustc_serialize::{json, Decodable};
use self::AlgorithmiaError::*;
use std::{io, env};
use std::rc::Rc;

static DEFAULT_API_BASE_URL: &'static str = "https://api.algorithmia.com";

/// The top-level struct for instantiating Algorithmia client endpoints
pub struct Algorithmia {
    pub api_key: String,
    pub base_url: String,
    client: Rc<Client>,
}

/// Internal HttpClient to build requests: wraps `hyper` client
struct HttpClient<'a>{
    api_key: String,
    client: &'a Client,
    user_agent: String,
}

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum AlgorithmiaError {
    /// Errors returned by the Algorithmia API, Optional Stacktrace
    AlgorithmiaApiError(ApiError),
    /// HTTP errors encountered by the hyper client
    HttpError(hyper::error::Error),
    /// Errors decoding response json
    DecoderError(json::DecoderError),
    /// Errors decoding response json with additional debugging context
    DecoderErrorWithContext(json::DecoderError, String),
    /// Errors encoding the request
    EncoderError(json::EncoderError),
    /// General IO errors
    IoError(io::Error),
}

#[derive(RustcDecodable, Debug)]
pub struct ApiError {
    pub message: String,
    pub stacktrace: Option<String>,
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: ApiError,
}

impl<'a, 'c> Algorithmia {
    /// Instantiate a new client
    pub fn client(api_key: &str) -> Algorithmia {
        Algorithmia {
            api_key: api_key.to_string(),
            base_url: Self::get_base_url(),
            client: Rc::new(Client::new()),
        }
    }

    fn get_base_url() -> String {
        // TODO: memoize
        match env::var("ALGORITHMIA_API") {
            Ok(url) => url,
            Err(_) => DEFAULT_API_BASE_URL.to_string(),
        }
    }

    /// Instantiate a new hyper client - used internally by instantiating new api_client for every request
    fn http_client(&self) -> HttpClient {
        HttpClient::new(self.api_key.clone(), &self.client)
    }

    /// Instantiate an `Algorithm` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// use algorithmia::algo::Version;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let factor = client.algo("anowell", "Dijkstra", Version::Latest);
    /// ```
    pub fn algo(self, user: &str, algoname: &str, version: Version<'a>) -> Algorithm {
        let algo_uri = match version {
            Version::Latest => format!("{}/{}", user, algoname),
            ref ver => format!("{}/{}/{}", user, algoname, ver),
        };

        Algorithm::new(self, &*algo_uri)
    }

    /// Instantiate an `Algorithm` from this client using the algorithm's URI
    ///
    /// # Examples
    /// ```
    /// use algorithmia::Algorithmia;
    /// use algorithmia::algo::Version;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let factor = client.algo_from_str("anowell/Dijkstra/0.1");
    /// ```
    pub fn algo_from_str(self, algo_uri: &str) -> Algorithm {
        Algorithm::new(self, algo_uri)
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.dir("data://.my/rustfoo");
    /// ```
    pub fn dir(self, path: &'a str) -> DataDir {
        DataDir::new(self, path)
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.file("data://.my/rustfoo");
    /// ```
    pub fn file(self, path: &'a str) -> DataFile {
        DataFile::new(self, path)
    }

    /// Helper to standardize decoding to a specific Algorithmia Result type
    pub fn decode_to_result<T: Decodable>(res_json: String) -> Result<T, AlgorithmiaError> {
        match json::decode::<T>(&res_json) {
            Ok(result) => Ok(result),
            Err(why) => match json::decode::<ApiErrorResponse>(&res_json) {
                Ok(err_res) => Err(AlgorithmiaError::AlgorithmiaApiError(err_res.error)),
                Err(_) => Err(AlgorithmiaError::DecoderErrorWithContext(why, res_json)),
            }
        }
    }

    pub fn decode_to_error(res_json: String) -> AlgorithmiaError {
        match json::decode::<ApiErrorResponse>(&res_json) {
            Ok(err_res) => AlgorithmiaError::AlgorithmiaApiError(err_res.error),
            Err(why) => AlgorithmiaError::DecoderErrorWithContext(why, res_json),
        }
    }

}

impl <'a> HttpClient<'a> {
    /// Instantiate an HttpClient - creates a new `hyper` client
    fn new(api_key: String, client: &'a Client) -> HttpClient {
        HttpClient {
            api_key: api_key,
            client: client,
            user_agent: format!("rust/{} algorithmia.rs/{}", option_env!("CFG_RELEASE").unwrap_or("unknown"), option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")),
        }
    }

    /// Helper to make Algorithmia GET requests with the API key
    fn get(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Get, url)
    }

    /// Helper to make Algorithmia POST requests with the API key
    fn post(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Post, url)
    }

    /// Helper to make Algorithmia PUT requests with the API key
    fn put(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Put, url)
    }

    /// Helper to make Algorithmia POST requests with the API key
    fn delete(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Delete, url)
    }

    fn build_request(&self, verb: Method, url: Url) -> RequestBuilder<Url> {
        let req = self.client.request(verb, url);

        // TODO: Support Secure Auth
        req.header(UserAgent(self.user_agent.clone()))
           .header(Authorization(format!("Simple {}", self.api_key)))
    }
}

/*
* Trait implementations
*/
/// Allow cloning a client in order to reuse the API key for multiple connections
impl std::clone::Clone for Algorithmia {
    fn clone(&self) -> Algorithmia {
        Algorithmia {
            api_key: self.api_key.clone(),
            base_url: self.base_url.clone(),
            client: self.client.clone(),
        }
    }
}

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

impl From<hyper::error::Error> for AlgorithmiaError {
    fn from(err: hyper::error::Error) -> AlgorithmiaError {
        HttpError(err)
    }
}

impl From<json::DecoderError> for AlgorithmiaError {
    fn from(err: json::DecoderError) -> AlgorithmiaError {
        DecoderError(err)
    }
}

impl From<json::EncoderError> for AlgorithmiaError {
    fn from(err: json::EncoderError) -> AlgorithmiaError {
        EncoderError(err)
    }
}<commit_msg>Make Algorithmia Sync<commit_after>//! Algorithmia client library
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Algorithmia;
//! use algorithmia::algo::{Algorithm, AlgoOutput, Version};
//!
//! // Initialize with an API key
//! let client = Algorithmia::client("111112222233333444445555566");
//! let moving_avg = client.algo("timeseries", "SimpleMovingAverage", Version::Minor(0,1));
//!
//! // Run the algorithm using a type safe decoding of the output to Vec<int>
//! //   since this algorithm outputs results as a JSON array of integers
//! let input = (vec![0,1,2,3,15,4,5,6,7], 3);
//! let output: AlgoOutput<Vec<f64>> = moving_avg.pipe(&input).unwrap();
//! println!("Completed in {} seconds with result: {:?}", output.metadata.duration, output.result);
//! ```

#![doc(html_logo_url = "https://algorithmia.com/assets/images/apple-touch-icon.png")]

extern crate hyper;
extern crate rustc_serialize;

pub mod algo;
pub mod data;

use algo::{Algorithm, Version};
use data::{DataDir, DataFile};

use hyper::{Client, Url};
use hyper::client::RequestBuilder;
use hyper::header::{Authorization, UserAgent};
use hyper::method::Method;
use rustc_serialize::{json, Decodable};
use self::AlgorithmiaError::*;
use std::{io, env};
use std::sync::Arc;

static DEFAULT_API_BASE_URL: &'static str = "https://api.algorithmia.com";

/// The top-level struct for instantiating Algorithmia client endpoints
pub struct Algorithmia {
    pub api_key: String,
    pub base_url: String,
    client: Arc<Client>, // Arc to ensure Algorithmia is still marked Send + Sync
}

/// Internal HttpClient to build requests: wraps `hyper` client
struct HttpClient<'a>{
    api_key: String,
    client: &'a Client,
    user_agent: String,
}

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum AlgorithmiaError {
    /// Errors returned by the Algorithmia API, Optional Stacktrace
    AlgorithmiaApiError(ApiError),
    /// HTTP errors encountered by the hyper client
    HttpError(hyper::error::Error),
    /// Errors decoding response json
    DecoderError(json::DecoderError),
    /// Errors decoding response json with additional debugging context
    DecoderErrorWithContext(json::DecoderError, String),
    /// Errors encoding the request
    EncoderError(json::EncoderError),
    /// General IO errors
    IoError(io::Error),
}

#[derive(RustcDecodable, Debug)]
pub struct ApiError {
    pub message: String,
    pub stacktrace: Option<String>,
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: ApiError,
}

impl<'a, 'c> Algorithmia {
    /// Instantiate a new client
    pub fn client(api_key: &str) -> Algorithmia {
        Algorithmia {
            api_key: api_key.to_string(),
            base_url: Self::get_base_url(),
            client: Arc::new(Client::new()),
        }
    }

    fn get_base_url() -> String {
        // TODO: memoize
        match env::var("ALGORITHMIA_API") {
            Ok(url) => url,
            Err(_) => DEFAULT_API_BASE_URL.to_string(),
        }
    }

    /// Instantiate a new hyper client - used internally by instantiating new api_client for every request
    fn http_client(&self) -> HttpClient {
        HttpClient::new(self.api_key.clone(), &self.client)
    }

    /// Instantiate an `Algorithm` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// use algorithmia::algo::Version;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let factor = client.algo("anowell", "Dijkstra", Version::Latest);
    /// ```
    pub fn algo(self, user: &str, algoname: &str, version: Version<'a>) -> Algorithm {
        let algo_uri = match version {
            Version::Latest => format!("{}/{}", user, algoname),
            ref ver => format!("{}/{}/{}", user, algoname, ver),
        };

        Algorithm::new(self, &*algo_uri)
    }

    /// Instantiate an `Algorithm` from this client using the algorithm's URI
    ///
    /// # Examples
    /// ```
    /// use algorithmia::Algorithmia;
    /// use algorithmia::algo::Version;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let factor = client.algo_from_str("anowell/Dijkstra/0.1");
    /// ```
    pub fn algo_from_str(self, algo_uri: &str) -> Algorithm {
        Algorithm::new(self, algo_uri)
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.dir("data://.my/rustfoo");
    /// ```
    pub fn dir(self, path: &'a str) -> DataDir {
        DataDir::new(self, path)
    }

    /// Instantiate a `DataDirectory` from this client
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let rustfoo = client.file("data://.my/rustfoo");
    /// ```
    pub fn file(self, path: &'a str) -> DataFile {
        DataFile::new(self, path)
    }

    /// Helper to standardize decoding to a specific Algorithmia Result type
    pub fn decode_to_result<T: Decodable>(res_json: String) -> Result<T, AlgorithmiaError> {
        match json::decode::<T>(&res_json) {
            Ok(result) => Ok(result),
            Err(why) => match json::decode::<ApiErrorResponse>(&res_json) {
                Ok(err_res) => Err(AlgorithmiaError::AlgorithmiaApiError(err_res.error)),
                Err(_) => Err(AlgorithmiaError::DecoderErrorWithContext(why, res_json)),
            }
        }
    }

    pub fn decode_to_error(res_json: String) -> AlgorithmiaError {
        match json::decode::<ApiErrorResponse>(&res_json) {
            Ok(err_res) => AlgorithmiaError::AlgorithmiaApiError(err_res.error),
            Err(why) => AlgorithmiaError::DecoderErrorWithContext(why, res_json),
        }
    }

}

impl <'a> HttpClient<'a> {
    /// Instantiate an HttpClient - creates a new `hyper` client
    fn new(api_key: String, client: &'a Client) -> HttpClient {
        HttpClient {
            api_key: api_key,
            client: client,
            user_agent: format!("rust/{} algorithmia.rs/{}", option_env!("CFG_RELEASE").unwrap_or("unknown"), option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")),
        }
    }

    /// Helper to make Algorithmia GET requests with the API key
    fn get(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Get, url)
    }

    /// Helper to make Algorithmia POST requests with the API key
    fn post(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Post, url)
    }

    /// Helper to make Algorithmia PUT requests with the API key
    fn put(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Put, url)
    }

    /// Helper to make Algorithmia POST requests with the API key
    fn delete(&self, url: Url) -> RequestBuilder<Url> {
        self.build_request(Method::Delete, url)
    }

    fn build_request(&self, verb: Method, url: Url) -> RequestBuilder<Url> {
        let req = self.client.request(verb, url);

        // TODO: Support Secure Auth
        req.header(UserAgent(self.user_agent.clone()))
           .header(Authorization(format!("Simple {}", self.api_key)))
    }
}

/*
* Trait implementations
*/
/// Allow cloning a client in order to reuse the API key for multiple connections
impl std::clone::Clone for Algorithmia {
    fn clone(&self) -> Algorithmia {
        Algorithmia {
            api_key: self.api_key.clone(),
            base_url: self.base_url.clone(),
            client: self.client.clone(),
        }
    }
}

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

impl From<hyper::error::Error> for AlgorithmiaError {
    fn from(err: hyper::error::Error) -> AlgorithmiaError {
        HttpError(err)
    }
}

impl From<json::DecoderError> for AlgorithmiaError {
    fn from(err: json::DecoderError) -> AlgorithmiaError {
        DecoderError(err)
    }
}

impl From<json::EncoderError> for AlgorithmiaError {
    fn from(err: json::EncoderError) -> AlgorithmiaError {
        EncoderError(err)
    }
}<|endoftext|>


<commit_before>//! MC Named Binary Tag type.

extern crate byteorder;
extern crate flate2;

/* Re-export the core API from submodules. */
pub use blob::Blob;
pub use error::{Error, Result};
pub use value::Value;

mod raw;
mod blob;
mod error;
mod value;

#[cfg(feature = "serde")] #[macro_use] extern crate serde;

#[cfg(feature = "serde")] #[macro_use] mod macros;
#[cfg(feature = "serde")] pub mod de;
#[cfg(feature = "serde")] pub mod ser;

#[cfg(test)] mod tests;
<commit_msg>Re-exports the ser/de functions to match the usual API.<commit_after>//! MC Named Binary Tag type.

extern crate byteorder;
extern crate flate2;

/* Re-export the core API from submodules. */
pub use blob::Blob;
pub use error::{Error, Result};
pub use value::Value;

#[cfg(feature = "serde")]
#[doc(inline)]
pub use de::{from_reader, from_gzip_reader, from_zlib_reader};
#[cfg(feature = "serde")]
#[doc(inline)]
pub use ser::{to_writer, to_gzip_writer, to_zlib_writer};

mod raw;
mod blob;
mod error;
mod value;

#[cfg(feature = "serde")] #[macro_use] extern crate serde;

#[cfg(feature = "serde")] #[macro_use] mod macros;
#[cfg(feature = "serde")] pub mod de;
#[cfg(feature = "serde")] pub mod ser;

#[cfg(test)] mod tests;
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

extern crate libc;

use libc::{c_int, c_ulonglong, c_char, c_void};

/// Typedef for initialization function.
pub type em_init_func = extern fn(*mut em_impl) -> c_int;
/// Typedef for read function.
pub type em_read_total_func = extern fn(*const em_impl) -> c_ulonglong;
/// Typedef for cleanup function.
pub type em_finish_func = extern fn(*mut em_impl) -> c_int;
/// Typedef for function to get human-readable name.
pub type em_get_source_func = extern fn(*mut c_char) -> *mut c_char;
/// Typedef for function to get refresh interval.
pub type em_get_interval_func = extern fn(*const em_impl) -> c_ulonglong;

#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
#[repr(C)]
/// Representation of native C struct `em_impl`.
pub struct em_impl {
    /// Native C function type signature that initializes the `em_impl`.
    pub finit: em_init_func,
    /// Native C function type signature that reads energy data from the `em_impl`.
    pub fread: em_read_total_func,
    /// Native C function type signature that cleans up the `em_impl`.
    pub ffinish: em_finish_func,
    /// Native C function type signature that gets the `em_impl`'s human-readable name.
    pub fsource: em_get_source_func,
    /// Native C function type signature that gets the `em_impl`'s refresh interval.
    pub finterval: em_get_interval_func,
    /// Native C pointer used by the underlying `em_impl` implementation for storing state.
    pub state: *mut c_void,
}

extern "C" {
    /// Native C function that fills in the em_impl struct values and may allocate other resources.
    pub fn em_impl_get(em: *mut em_impl) -> c_int;
}
<commit_msg>Remove Clone/Copy derive<commit_after>#![allow(non_camel_case_types)]

extern crate libc;

use libc::{c_int, c_ulonglong, c_char, c_void};

/// Typedef for initialization function.
pub type em_init_func = extern fn(*mut em_impl) -> c_int;
/// Typedef for read function.
pub type em_read_total_func = extern fn(*const em_impl) -> c_ulonglong;
/// Typedef for cleanup function.
pub type em_finish_func = extern fn(*mut em_impl) -> c_int;
/// Typedef for function to get human-readable name.
pub type em_get_source_func = extern fn(*mut c_char) -> *mut c_char;
/// Typedef for function to get refresh interval.
pub type em_get_interval_func = extern fn(*const em_impl) -> c_ulonglong;

#[repr(C)]
/// Representation of native C struct `em_impl`.
pub struct em_impl {
    /// Native C function type signature that initializes the `em_impl`.
    pub finit: em_init_func,
    /// Native C function type signature that reads energy data from the `em_impl`.
    pub fread: em_read_total_func,
    /// Native C function type signature that cleans up the `em_impl`.
    pub ffinish: em_finish_func,
    /// Native C function type signature that gets the `em_impl`'s human-readable name.
    pub fsource: em_get_source_func,
    /// Native C function type signature that gets the `em_impl`'s refresh interval.
    pub finterval: em_get_interval_func,
    /// Native C pointer used by the underlying `em_impl` implementation for storing state.
    pub state: *mut c_void,
}

extern "C" {
    /// Native C function that fills in the em_impl struct values and may allocate other resources.
    pub fn em_impl_get(em: *mut em_impl) -> c_int;
}
<|endoftext|>


<commit_before>#![feature(test)]
// This is silly...
#![allow(unused_features)]

#[macro_use]
extern crate log;
extern crate crc;
extern crate memmap;
extern crate byteorder;
extern crate env_logger;

#[cfg(test)]
extern crate test;
#[cfg(test)]
extern crate rand;

use std::path::{Path, PathBuf};
use std::fs;
use std::io;

mod segment;
mod index;
#[cfg(test)]
mod testutil;

/// Offset of an appended log segment.
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub struct Offset(u64);

#[derive(Debug)]
pub enum AppendError {
    IoError(io::Error),
    IndexAppendError,
}

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

/// Commit log options allow customization of the commit
/// log behavior.
#[derive(Clone, Debug)]
pub struct LogOptions {
    log_dir: PathBuf,
    log_max_bytes: usize,
    index_max_bytes: usize,
}

impl LogOptions {
    pub fn new<P>(log_dir: P) -> LogOptions
        where P: AsRef<Path>
    {
        LogOptions {
            log_dir: log_dir.as_ref().to_owned(),
            log_max_bytes: 100 * 1024 * 1024,
            index_max_bytes: 800_000,
        }
    }

    /// Bounds the size of a log segment to a number of bytes.
    #[inline]
    pub fn max_bytes_log(&mut self, bytes: usize) -> &mut LogOptions {
        self.log_max_bytes = bytes;
        self
    }

    /// Bounds the size of an individual memory-mapped index file.
    #[inline]
    pub fn max_log_items(&mut self, items: usize) -> &mut LogOptions {
        self.index_max_bytes = items * index::INDEX_ENTRY_BYTES;
        self
    }
}

/// The commit log is an append-only data structure that can be used in a variety
/// of use-cases, such as tracking sequences of events, logging transactions in a
/// local database, or replicated state machines.
///
/// This implementation of the commit log data structure uses log segments
/// that roll over at pre-defined maximum size boundaries. The messages appended
/// to the log have a unique, monotonically incrasing offset that can be used as
/// a pointer to a log entry.
///
/// The index of the commit log logically stores the offset to a position in the
/// log segment corresponding. The index and segments are separated, in that a
/// segment file does not necessarily correspond to one particular segment file,
/// it could contain file pointers to many index files. In addition, index files
/// are memory-mapped for efficient read and write access.
pub struct CommitLog {
    active_segment: segment::Segment,
    active_index: index::Index,
    options: LogOptions,
}

impl CommitLog {
    pub fn new(opts: LogOptions) -> io::Result<CommitLog> {
        // TODO: figure out what's already been written to
        fs::create_dir_all(&opts.log_dir).unwrap_or(());

        info!("Opening log at path {:?}", &opts.log_dir.to_str());
        let seg = try!(segment::Segment::new(&opts.log_dir, 0u64, opts.log_max_bytes));
        let ind = try!(index::Index::new(&opts.log_dir, 0u64, opts.index_max_bytes));

        Ok(CommitLog {
            active_segment: seg,
            active_index: ind,
            options: opts,
        })
    }

    /// Appends a log entry to the commit log. The offset of the appended entry
    /// is the result of the comutation.
    pub fn append(&mut self, payload: &[u8]) -> Result<Offset, AppendError> {
        let meta = match self.active_segment.append(payload) {
            Ok(meta) => {
                trace!("Successfully appended message {:?}", meta);
                meta
            }
            Err(segment::SegmentAppendError::LogFull) => {
                // close segment
                try!(self.active_segment.flush_sync());
                let next_offset = self.active_segment.next_offset();
                info!("Closing segment at offset {}", next_offset);
                self.active_segment = try!(segment::Segment::new(&self.options.log_dir,
                                                                 next_offset,
                                                                 self.options.log_max_bytes));

                // try again
                return self.append(payload);
            }
            Err(segment::SegmentAppendError::IoError(e)) => {
                return Err(AppendError::IoError(e));
            }
        };

        // write to the index
        self.active_index.append(meta.offset(), meta.file_pos())
            .or_else(|e| match e {
                // if the index is full, close the current index and open a new index
                index::IndexWriteError::IndexFull => {
                    try!(self.active_index.set_readonly());
                    self.active_index =
                        try!(index::Index::new(&self.options.log_dir, meta.offset(), self.options.index_max_bytes));

                    // if the new index cannot append, we're out of luck
                    self.active_index.append(meta.offset(), meta.file_pos())
                        .map_err(|_| AppendError::IndexAppendError)
                },
                index::IndexWriteError::OffsetLessThanBase => unreachable!(),
            })
            .map(|_| Offset(meta.offset()))
    }

    pub fn flush(&mut self) -> io::Result<()> {
        try!(self.active_segment.flush_sync());
        self.active_index.flush_sync()
    }
}

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

    #[test]
    pub fn append() {
        let dir = TestDir::new();
        let mut log = CommitLog::new(LogOptions::new(&dir)).unwrap();
        assert_eq!(log.append(b"123456").unwrap(), Offset(0));
        assert_eq!(log.append(b"abcdefg").unwrap(), Offset(1));
        assert_eq!(log.append(b"foobarbaz").unwrap(), Offset(2));
        assert_eq!(log.append(b"bing").unwrap(), Offset(3));
        log.flush().unwrap();
    }
}
<commit_msg>Code cleanup<commit_after>#![feature(test)]
// This is silly...
#![allow(unused_features)]

#[macro_use]
extern crate log;
extern crate crc;
extern crate memmap;
extern crate byteorder;
extern crate env_logger;

#[cfg(test)]
extern crate test;
#[cfg(test)]
extern crate rand;

mod segment;
mod index;
#[cfg(test)]
mod testutil;

use std::path::{Path, PathBuf};
use std::fs;
use std::io;
use segment::*;
use index::*;

/// Offset of an appended log segment.
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub struct Offset(u64);

#[derive(Debug)]
pub enum AppendError {
    IoError(io::Error),
    NewIndexAppendError,
    NewSegmentAppendError,
}

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

/// Commit log options allow customization of the commit
/// log behavior.
#[derive(Clone, Debug)]
pub struct LogOptions {
    log_dir: PathBuf,
    log_max_bytes: usize,
    index_max_bytes: usize,
}

impl LogOptions {
    pub fn new<P>(log_dir: P) -> LogOptions
        where P: AsRef<Path>
    {
        LogOptions {
            log_dir: log_dir.as_ref().to_owned(),
            log_max_bytes: 100 * 1024 * 1024,
            index_max_bytes: 800_000,
        }
    }

    /// Bounds the size of a log segment to a number of bytes.
    #[inline]
    pub fn max_bytes_log(&mut self, bytes: usize) -> &mut LogOptions {
        self.log_max_bytes = bytes;
        self
    }

    /// Bounds the size of an individual memory-mapped index file.
    #[inline]
    pub fn max_log_items(&mut self, items: usize) -> &mut LogOptions {
        self.index_max_bytes = items * INDEX_ENTRY_BYTES;
        self
    }
}

/// The commit log is an append-only data structure that can be used in a variety
/// of use-cases, such as tracking sequences of events, logging transactions in a
/// local database, or replicated state machines.
///
/// This implementation of the commit log data structure uses log segments
/// that roll over at pre-defined maximum size boundaries. The messages appended
/// to the log have a unique, monotonically incrasing offset that can be used as
/// a pointer to a log entry.
///
/// The index of the commit log logically stores the offset to a position in the
/// log segment corresponding. The index and segments are separated, in that a
/// segment file does not necessarily correspond to one particular segment file,
/// it could contain file pointers to many index files. In addition, index files
/// are memory-mapped for efficient read and write access.
pub struct CommitLog {
    active_segment: Segment,
    active_index: Index,
    options: LogOptions,
}

impl CommitLog {
    pub fn new(opts: LogOptions) -> io::Result<CommitLog> {
        // TODO: figure out what's already been written to
        fs::create_dir_all(&opts.log_dir).unwrap_or(());

        info!("Opening log at path {:?}", &opts.log_dir.to_str());
        let seg = try!(Segment::new(&opts.log_dir, 0u64, opts.log_max_bytes));
        let ind = try!(Index::new(&opts.log_dir, 0u64, opts.index_max_bytes));

        Ok(CommitLog {
            active_segment: seg,
            active_index: ind,
            options: opts,
        })
    }

    /// Appends a log entry to the commit log. The offset of the appended entry
    /// is the result of the comutation.
    pub fn append(&mut self, payload: &[u8]) -> Result<Offset, AppendError> {
        // first write to the current segment
        let meta = try!(self.active_segment
            .append(payload)
            .or_else(|e| {
                match e {
                    // if the log is full, gracefully close the current segment
                    // and create new one starting from the new offset
                    SegmentAppendError::LogFull => {
                        try!(self.active_segment.flush_sync());
                        let next_offset = self.active_segment.next_offset();
                        info!("Closing active segment at offset {}", next_offset);
                        self.active_segment = try!(Segment::new(&self.options.log_dir,
                                                                next_offset,
                                                                self.options.log_max_bytes));

                        // try again, giving up if we have to
                        self.active_segment
                            .append(payload)
                            .map_err(|_| AppendError::NewIndexAppendError)
                    }
                    SegmentAppendError::IoError(e) => Err(AppendError::IoError(e)),
                }
            }));

        // write to the index
        try!(self.active_index
            .append(meta.offset(), meta.file_pos())
            .or_else(|e| {
                match e {
                    // if the index is full, close the current index and open a new index
                    IndexWriteError::IndexFull => {
                        try!(self.active_index.set_readonly());
                        self.active_index = try!(Index::new(&self.options.log_dir,
                                                            meta.offset(),
                                                            self.options.index_max_bytes));

                        // if the new index cannot append, we're out of luck
                        self.active_index
                            .append(meta.offset(), meta.file_pos())
                            .map_err(|_| AppendError::NewIndexAppendError)
                    }
                    IndexWriteError::OffsetLessThanBase => unreachable!(),
                }
            }));

        Ok(Offset(meta.offset()))
    }

    pub fn flush(&mut self) -> io::Result<()> {
        try!(self.active_segment.flush_sync());
        self.active_index.flush_sync()
    }
}

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

    #[test]
    pub fn append() {
        let dir = TestDir::new();
        let mut log = CommitLog::new(LogOptions::new(&dir)).unwrap();
        assert_eq!(log.append(b"123456").unwrap(), Offset(0));
        assert_eq!(log.append(b"abcdefg").unwrap(), Offset(1));
        assert_eq!(log.append(b"foobarbaz").unwrap(), Offset(2));
        assert_eq!(log.append(b"bing").unwrap(), Offset(3));
        log.flush().unwrap();
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules, plugin_registrar, quote, phase)]

#[phase(plugin,link)]
extern crate syntax;
#[phase(plugin, link)]
extern crate rustc;

use syntax::ast;
use rustc::lint::LintPassObject;
use rustc::plugin::Registry;
use rustc::lint::{Context, LintPass, LintArray};
use rustc::middle::def;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit::FnKind;

declare_lint!(EXCESSIVE_BOOL_USAGE_STRUCTS, Warn,
              "Warn about exessive use of boolean members in structs.")
declare_lint!(EXCESSIVE_BOOL_USAGE_FUNCS, Warn,
              "Warn about exessive use of boolean arguments in functions.")

struct Pass;

fn node_is_bool(cx: &Context, ty: &ast::Ty) -> bool {
    match ty.node {
        ast::TyPath(_, _, id) => {
            match cx.tcx.def_map.borrow().get_copy(&id) {
                def::DefPrimTy(ast::TyBool) => true,
                _ => false,
            }
        },
        _ => false,
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXCESSIVE_BOOL_USAGE_STRUCTS, EXCESSIVE_BOOL_USAGE_FUNCS)
    }

    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef,
            _i: ast::Ident, _gen: &ast::Generics, id: ast::NodeId) {
        let mut bools = vec![];
        let mut spans = vec![];

        for field in def.fields.iter() {
            if node_is_bool(cx, &*field.node.ty) {
                match field.node {
                    ast::StructField_ { kind: ast::NamedField(ident, _), .. } => {
                        spans.push(field.span);
                        bools.push(token::get_ident(ident).get().to_string())
                    },
                    _ => {},
                }
            }
        }

        if bools.len() >= 3 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_STRUCTS, cx.tcx.map.span(id),
                format!("Struct contains an excessive number ({}) of bools ({}).  \
                    Did you want to create a state machine?",
                    bools.len(),
                    bools.connect(", ")).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean field defined here");
            }
        }
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &ast::FnDecl, _: &ast::Block, sp: Span, _: ast::NodeId) {
        let mut spans = vec![];
        for arg in decl.inputs.iter() {
            if node_is_bool(cx, &*arg.ty) {
                spans.push(cx.tcx.map.span(arg.id));
            }
        }

        if spans.len() >= 3 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_FUNCS, sp,
                format!("Funtion contains an excessive number ({}) of bools.  \
                    Perhaps you should use enumerated arguments?",
                    spans.len()).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean field defined here");
            }
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_lint_pass(box Pass as LintPassObject);
}
<commit_msg>Improved an error message<commit_after>#![feature(macro_rules, plugin_registrar, quote, phase)]

#[phase(plugin,link)]
extern crate syntax;
#[phase(plugin, link)]
extern crate rustc;

use syntax::ast;
use rustc::lint::LintPassObject;
use rustc::plugin::Registry;
use rustc::lint::{Context, LintPass, LintArray};
use rustc::middle::def;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit::FnKind;

declare_lint!(EXCESSIVE_BOOL_USAGE_STRUCTS, Warn,
              "Warn about exessive use of boolean members in structs.")
declare_lint!(EXCESSIVE_BOOL_USAGE_FUNCS, Warn,
              "Warn about exessive use of boolean arguments in functions.")

struct Pass;

fn node_is_bool(cx: &Context, ty: &ast::Ty) -> bool {
    match ty.node {
        ast::TyPath(_, _, id) => {
            match cx.tcx.def_map.borrow().get_copy(&id) {
                def::DefPrimTy(ast::TyBool) => true,
                _ => false,
            }
        },
        _ => false,
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXCESSIVE_BOOL_USAGE_STRUCTS, EXCESSIVE_BOOL_USAGE_FUNCS)
    }

    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef,
            _i: ast::Ident, _gen: &ast::Generics, id: ast::NodeId) {
        let mut bools = vec![];
        let mut spans = vec![];

        for field in def.fields.iter() {
            if node_is_bool(cx, &*field.node.ty) {
                match field.node {
                    ast::StructField_ { kind: ast::NamedField(ident, _), .. } => {
                        spans.push(field.span);
                        bools.push(token::get_ident(ident).get().to_string())
                    },
                    _ => {},
                }
            }
        }

        if bools.len() >= 3 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_STRUCTS, cx.tcx.map.span(id),
                format!("Struct contains an excessive number ({}) of bools ({}).  \
                    Did you want to create a state machine?",
                    bools.len(),
                    bools.connect(", ")).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean field defined here");
            }
        }
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &ast::FnDecl, _: &ast::Block, sp: Span, _: ast::NodeId) {
        let mut spans = vec![];
        for arg in decl.inputs.iter() {
            if node_is_bool(cx, &*arg.ty) {
                spans.push(cx.tcx.map.span(arg.id));
            }
        }

        if spans.len() >= 3 {
            cx.span_lint(EXCESSIVE_BOOL_USAGE_FUNCS, sp,
                format!("Funtion contains an excessive number ({}) of bools.  \
                    Perhaps you should use enumerated arguments?",
                    spans.len()).as_slice());
            for span in spans.iter() {
                cx.tcx.sess.span_note(*span, "boolean argument defined here");
            }
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_lint_pass(box Pass as LintPassObject);
}
<|endoftext|>


<commit_before>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.
//!
//! The code is available on [GitHub](https://github.com/sourrust/flac).
//!
//! # Examples
//!
//! Basic decoding from a file.
//!
//! ```
//! use flac::StreamReader;
//! use std::fs::File;
//!
//! match StreamReader::<File>::from_file("path/to/file.flac") {
//!   Ok(mut stream) => {
//!     // Copy of `StreamInfo` to help convert to a different audio format.
//!     let info = stream.info();
//!
//!     for sample in stream.iter() {
//!       // Iterate over each decoded sample
//!     }
//!   }
//!   Err(error)     => println!("{}", error),
//! }
//! ```

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
mod frame;
mod subframe;
pub mod metadata;
pub mod stream;

pub use metadata::Metadata;
pub use stream::{Stream, StreamBuffer, StreamReader};
pub use utility::{StreamProducer, ReadStream, ByteStream, ErrorKind};
<commit_msg>Update documentation<commit_after>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.
//!
//! The code is available on [GitHub](https://github.com/sourrust/flac).
//!
//! # Examples
//!
//! Basic decoding from a file.
//!
//! ```
//! use flac::StreamReader;
//! use std::fs::File;
//!
//! match StreamReader::<File>::from_file("path/to/file.flac") {
//!   Ok(mut stream) => {
//!     // Copy of `StreamInfo` to help convert to a different audio format.
//!     let info = stream.info();
//!
//!     for sample in stream.iter() {
//!       // Iterate over each decoded sample
//!     }
//!   }
//!   Err(error)     => println!("{:?}", error),
//! }
//! ```

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
mod frame;
mod subframe;
pub mod metadata;
pub mod stream;

pub use metadata::Metadata;
pub use stream::{Stream, StreamBuffer, StreamReader};
pub use utility::{StreamProducer, ReadStream, ByteStream, ErrorKind};
<|endoftext|>