<commit_before>//! Histogram of oriented gradients and helpers for visualizing them.
//! http://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf

use image::{
	GenericImage,
	Luma
};
use gradients::{
	horizontal_sobel,
	vertical_sobel
};
use multiarray::{
	Array3d,
	element_at_mut,
	inner_dimension_slice,
	Mut3d,
	View3d
};
use math::l2_norm;
use std::f32;

/// Parameters for HoG descriptors.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct HogOptions {
	/// Number of gradient orientation bins.
	pub orientations: u32,

	/// Whether gradients in opposite directions
	/// are treated as equal.
    pub signed: bool,

	/// Width and height of cell in pixels.
	pub cell_side: u32,

	/// Width and height of block in cells.
	pub block_side: u32,

	/// Offset of the start of one block from the next in cells.
	pub block_stride: u32

	// TODO: choice of normalisation - for now we just scale
    // TODO: to unit L2 norm
}

impl HogOptions {
    pub fn new(orientations: u32, signed: bool, cell_side: u32,
        block_side: u32, block_stride: u32) -> HogOptions {

        HogOptions {
            orientations: orientations,
            signed: signed,
            cell_side: cell_side,
            block_side: block_side,
            block_stride: block_stride}
    }
}

/// Dimensions of a HoG descriptor. The descriptor for the whole
/// image is the concatenation of a blocks_wide * blocks_high grid
/// of block descriptors, each of size block_descriptor_size.
pub struct HogDimensions {
	/// Size of the descriptor for a single block.
	pub block_descriptor_size: u32,
	/// Number of (possibly overlapping) blocks used to tile the image width.
	pub blocks_wide: u32,
	/// Number of (possibly overlapping) blocks used to tile the image height.
	pub blocks_high: u32
}

impl HogDimensions {
	/// Size of a block descriptor using the given options, and number of blocks required
	/// to tile an image of given width and height.
	pub fn from_options(width: u32, height: u32, options: HogOptions) -> HogDimensions {
		let cells_wide = width / options.cell_side;
		let cells_high = height / options.cell_side;
		HogDimensions {
			block_descriptor_size: options.orientations * options.block_side.pow(2),
			blocks_wide: num_blocks(cells_wide, options.block_side, options.block_stride),
			blocks_high: num_blocks(cells_high, options.block_side, options.block_stride)
		}
	}

	/// The total size in floats of the HoG descriptor with these dimensions.
	pub fn descriptor_length(&self) -> u32 {
		self.block_descriptor_size * self.blocks_wide * self.blocks_high
	}
}

/// Computes the HoG descriptor of an image, or None if the provided
/// options are incompatible with the image size.
// TODO: produce a helpful error message if the options are invalid
// TODO: support color images by taking the channel with maximum gradient at each point
pub fn hog<I>(image: &I, options: HogOptions) -> Option<Vec<f32>>
	where I: GenericImage<Pixel=Luma<u8>> + 'static {

	let mut grid: Array3d<f32>;
	match cell_histograms(image, options) {
		None => return None,
		Some(array) => grid = array
	};

	let (width, height) = image.dimensions();
	let dimensions = HogDimensions::from_options(width, height, options);
	let cells_wide = width / options.cell_side;
	let cells_high = height / options.cell_side;
	let mut descriptor = Array3d::new(
		dimensions.block_descriptor_size as usize,
		dimensions.blocks_wide as usize,
		dimensions.blocks_high as usize);

	for by in 0..dimensions.blocks_high {
		for bx in 0..dimensions.blocks_wide {
			let mut block_data = inner_dimension_slice(&mut descriptor, bx as usize, by as usize);
			let mut block = View3d::from_raw(
				&mut block_data,
				options.orientations as usize,
				cells_wide as usize,
				cells_high as usize);

			for iy in 0..options.block_side {
				let cy = by * options.block_stride + iy;

				for ix in 0..options.block_side {
					let cx = bx * options.block_stride + ix;
					let mut slice = inner_dimension_slice(&mut block, ix as usize, iy as usize);
					let hist = inner_dimension_slice(&mut grid, cx as usize, cy as usize);
					for dir in 0..options.orientations {
						slice[dir as usize] = hist[dir as usize];
					}
					let norm = l2_norm(slice);
					for dir in 0..options.orientations {
						slice[dir as usize] /= norm;
					}
				}
			}
		}
	}

	Some(descriptor.data)
}

/// Computes orientation histograms for each cell of an image, or none if the
/// image dimensions are incompatible with the provided options.
// TODO: produce a helpful error message if the options are invalid
fn cell_histograms<I>(image: &I, options: HogOptions) -> Option<Array3d<f32>>
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let (width, height) = image.dimensions();
    if !is_valid_size(width, height, options) {
        return None;
    }

	let cells_wide = width / options.cell_side;
	let cells_high = height / options.cell_side;
	let mut grid = Array3d::new(
		options.orientations as usize, cells_wide as usize, cells_high as usize);
	let grid_dim = grid.dimensions();

	let horizontal = horizontal_sobel(image);
	let vertical = vertical_sobel(image);
	let cell_area = (options.cell_side * options.cell_side) as f32;

	let dir_range = if options.signed {2f32 * f32::consts::PI} else {f32::consts::PI};
	let dir_bin_width = dir_range / (options.orientations as f32);

	for y in 0..height {
		let y_inter = Interpolation::from_position(y as f32 / options.cell_side as f32);

		for x in 0..width {
			let x_inter = Interpolation::from_position(x as f32 / options.cell_side as f32);

			let h = horizontal.get_pixel(x, y)[0] as f32;
			let v = vertical.get_pixel(x, y)[0] as f32;
			let m = (h.powi(2) + v.powi(2)).sqrt();
			let d = v.atan2(h);

			let o_inter = Interpolation::from_position_wrapping(
				d / dir_bin_width, options.orientations);

			for iy in 0..2usize {
				for ix in 0..2usize {
					for io in 0..2usize {
						if ix >= grid_dim.len_1 || iy >= grid_dim.len_2 {
							continue;
						}

						let wy = y_inter.weights[iy];
						let wx = x_inter.weights[ix];
						let wo = o_inter.weights[io];
						let py = y_inter.indices[iy] as usize;
						let px = x_inter.indices[ix] as usize;
						let po = o_inter.indices[io] as usize;
						let up = wy * wx * wo * m / cell_area;
						let current = *element_at_mut(&mut grid, po, px, py);
					 	*element_at_mut(&mut grid, po, px, py) = current + up;
					}
				}
			}
		}
	}

	Some(grid)
}

/// Indices and weights for an interpolated value.
struct Interpolation {
	indices: [u32; 2],
	weights: [f32; 2]
}

impl Interpolation {
	/// Interpolates between two indices, without wrapping.
	fn from_position(pos: f32) -> Interpolation {
		let fraction = pos - pos.floor();
		Interpolation {
			indices: [pos as u32, pos as u32 + 1],
			weights: [1f32 - fraction, fraction]
		}
	}

	/// Interpolates between two indices, wrapping the right index.
	/// Assumes that the left index is within bounds.
	fn from_position_wrapping(pos: f32, length: u32) -> Interpolation {
		let mut right = (pos as u32) + 1;
		if right >= length {
			right = 0;
		}
		let fraction = pos - pos.floor();
		Interpolation {
			indices: [pos as u32, right],
			weights: [1f32 - fraction, fraction]
		}
	}
}

/// Number of blocks required to cover num_cells cells when each block is
/// block_side long and blocks are staggered by block_stride. Assumes that
/// options are compatible (see is_valid_size function).
fn num_blocks(num_cells: u32, block_side: u32, block_stride: u32) -> u32
{
	(num_cells + block_stride - block_side) / block_stride
}

/// Returns false if an image of the given size can't be evenly covered by
/// cells and blocks of the size and stride specified in options.
fn is_valid_size(width: u32, height: u32, options: HogOptions) -> bool {

    if width % options.cell_side != 0 {
        return false;
    }
    if height % options.cell_side != 0 {
        return false;
    }
    if (width - options.block_side) % options.block_stride != 0 {
        return false;
    }
    if (height - options.block_side) % options.block_stride != 0 {
        return false;
    }
    true
}

#[cfg(test)]
mod test {

    use super::{
        HogOptions,
        HogDimensions,
        num_blocks
    };

    #[test]
    fn test_num_blocks() {
        // -----
        // ***
        //   ***
        assert_eq!(num_blocks(5, 3, 2), 2);
        // -----
        // *****
        assert_eq!(num_blocks(5, 5, 2), 1);
        // ----
        // **
        //   **
        assert_eq!(num_blocks(4, 2, 2), 2);
        // ---
        // *
        //  *
        //   *
        assert_eq!(num_blocks(3, 1, 1), 3);
    }

    #[test]
    fn test_hog_dimensions() {
        assert_eq!(
			HogDimensions::from_options(40, 40, HogOptions::new(8, true, 5, 2, 1))
				.descriptor_length(), 1568);
        assert_eq!(
			HogDimensions::from_options(40, 40, HogOptions::new(9, true, 4, 2, 1))
				.descriptor_length(), 2916);
        assert_eq!(
			HogDimensions::from_options(40, 40, HogOptions::new(8, true, 4, 2, 1))
				.descriptor_length(), 2592);
    }
}
<commit_msg>Less casting<commit_after>//! Histogram of oriented gradients and helpers for visualizing them.
//! http://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf

use image::{
	GenericImage,
	Luma
};
use gradients::{
	horizontal_sobel,
	vertical_sobel
};
use multiarray::{
	Array3d,
	element_at_mut,
	inner_dimension_slice,
	Mut3d,
	View3d
};
use math::l2_norm;
use std::f32;

/// Parameters for HoG descriptors.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct HogOptions {
	/// Number of gradient orientation bins.
	pub orientations: usize,

	/// Whether gradients in opposite directions
	/// are treated as equal.
    pub signed: bool,

	/// Width and height of cell in pixels.
	pub cell_side: usize,

	/// Width and height of block in cells.
	pub block_side: usize,

	/// Offset of the start of one block from the next in cells.
	pub block_stride: usize

	// TODO: choice of normalisation - for now we just scale
    // TODO: to unit L2 norm
}

impl HogOptions {
    pub fn new(orientations: usize, signed: bool, cell_side: usize,
        block_side: usize, block_stride: usize) -> HogOptions {

        HogOptions {
            orientations: orientations,
            signed: signed,
            cell_side: cell_side,
            block_side: block_side,
            block_stride: block_stride}
    }
}

/// Dimensions of a HoG descriptor. The descriptor for the whole
/// image is the concatenation of a blocks_wide * blocks_high grid
/// of block descriptors, each of size block_descriptor_size.
pub struct HogDimensions {
	/// Size of the descriptor for a single block.
	pub block_descriptor_size: usize,
	/// Number of (possibly overlapping) blocks required to tile the image width.
	pub blocks_wide: usize,
	/// Number of (possibly overlapping) blocks required to tile the image height.
	pub blocks_high: usize,
	/// Number of non-overlapping cells required to tile the image width.
	pub cells_wide: usize,
	/// Number of non-overlapping cells required to tile the image height.
	pub cells_high: usize
}

impl HogDimensions {
	/// Size of a block descriptor using the given options, and number of blocks required
	/// to tile an image of given width and height.
	pub fn from_options(width: u32, height: u32, options: HogOptions) -> HogDimensions {
		let cells_wide = width as usize/ options.cell_side;
		let cells_high = height as usize/ options.cell_side;
		HogDimensions {
			block_descriptor_size: options.orientations * options.block_side.pow(2),
			blocks_wide: num_blocks(cells_wide, options.block_side, options.block_stride),
			blocks_high: num_blocks(cells_high, options.block_side, options.block_stride),
			cells_wide: cells_wide,
			cells_high: cells_high
		}
	}

	/// The total size in floats of the HoG descriptor with these dimensions.
	pub fn descriptor_length(&self) -> usize {
		self.blocks_wide * self.blocks_high * self.block_descriptor_size
	}
}

/// Computes the HoG descriptor of an image, or None if the provided
/// options are incompatible with the image size.
// TODO: produce a helpful error message if the options are invalid
// TODO: support color images by taking the channel with maximum gradient at each point
pub fn hog<I>(image: &I, options: HogOptions) -> Option<Vec<f32>>
	where I: GenericImage<Pixel=Luma<u8>> + 'static {

	let mut grid: Array3d<f32>;
	match cell_histograms(image, options) {
		None => return None,
		Some(array) => grid = array
	};

	let (width, height) = image.dimensions();
	let hog_dim = HogDimensions::from_options(width, height, options);
	let mut descriptor = Array3d::new(
		hog_dim.block_descriptor_size,
		hog_dim.blocks_wide,
		hog_dim.blocks_high);

	for by in 0..hog_dim.blocks_high {
		for bx in 0..hog_dim.blocks_wide {
			let mut block_data = inner_dimension_slice(&mut descriptor, bx, by);
			let mut block = View3d::from_raw(&mut block_data, options.orientations,
				hog_dim.cells_wide, hog_dim.cells_high);

			for iy in 0..options.block_side {
				let cy = by * options.block_stride + iy;

				for ix in 0..options.block_side {
					let cx = bx * options.block_stride + ix;
					let mut slice = inner_dimension_slice(&mut block, ix, iy);
					let hist = inner_dimension_slice(&mut grid, cx, cy);
					for dir in 0..options.orientations {
						slice[dir] = hist[dir];
					}
					let norm = l2_norm(slice);
					for dir in 0..options.orientations {
						slice[dir] /= norm;
					}
				}
			}
		}
	}

	Some(descriptor.data)
}

/// Computes orientation histograms for each cell of an image, or none if the
/// image dimensions are incompatible with the provided options.
// TODO: produce a helpful error message if the options are invalid
fn cell_histograms<I>(image: &I, options: HogOptions) -> Option<Array3d<f32>>
    where I: GenericImage<Pixel=Luma<u8>> + 'static {

    let (width, height) = image.dimensions();
    if !is_valid_size(width, height, options) {
        return None;
    }

	let dimensions = HogDimensions::from_options(width, height, options);
	let mut grid = Array3d::new(options.orientations, dimensions.cells_wide, dimensions.cells_high);
	let grid_dim = grid.dimensions();

	let horizontal = horizontal_sobel(image);
	let vertical = vertical_sobel(image);
	let cell_area = (options.cell_side * options.cell_side) as f32;

	let dir_range = if options.signed {2f32 * f32::consts::PI} else {f32::consts::PI};
	let dir_bin_width = dir_range / (options.orientations as f32);

	for y in 0..height {
		let y_inter = Interpolation::from_position(y as f32 / options.cell_side as f32);

		for x in 0..width {
			let x_inter = Interpolation::from_position(x as f32 / options.cell_side as f32);

			let h = horizontal.get_pixel(x, y)[0] as f32;
			let v = vertical.get_pixel(x, y)[0] as f32;
			let m = (h.powi(2) + v.powi(2)).sqrt();
			let d = v.atan2(h);

			let o_inter = Interpolation::from_position_wrapping(
				d / dir_bin_width, options.orientations);

			for iy in 0..2usize {
				for ix in 0..2usize {
					for io in 0..2usize {
						if ix >= grid_dim.len_1 || iy >= grid_dim.len_2 {
							continue;
						}

						let wy = y_inter.weights[iy];
						let wx = x_inter.weights[ix];
						let wo = o_inter.weights[io];
						let py = y_inter.indices[iy];
						let px = x_inter.indices[ix];
						let po = o_inter.indices[io];
						let up = wy * wx * wo * m / cell_area;
						let current = *element_at_mut(&mut grid, po, px, py);
					 	*element_at_mut(&mut grid, po, px, py) = current + up;
					}
				}
			}
		}
	}

	Some(grid)
}

/// Indices and weights for an interpolated value.
struct Interpolation {
	indices: [usize; 2],
	weights: [f32; 2]
}

impl Interpolation {
	/// Interpolates between two indices, without wrapping.
	fn from_position(pos: f32) -> Interpolation {
		let fraction = pos - pos.floor();
		Interpolation {
			indices: [pos as usize, pos as usize + 1],
			weights: [1f32 - fraction, fraction]
		}
	}

	/// Interpolates between two indices, wrapping the right index.
	/// Assumes that the left index is within bounds.
	fn from_position_wrapping(pos: f32, length: usize) -> Interpolation {
		let mut right = (pos as usize) + 1;
		if right >= length {
			right = 0;
		}
		let fraction = pos - pos.floor();
		Interpolation {
			indices: [pos as usize, right],
			weights: [1f32 - fraction, fraction]
		}
	}
}

/// Number of blocks required to cover num_cells cells when each block is
/// block_side long and blocks are staggered by block_stride. Assumes that
/// options are compatible (see is_valid_size function).
fn num_blocks(num_cells: usize, block_side: usize, block_stride: usize) -> usize
{
	(num_cells + block_stride - block_side) / block_stride
}

/// Returns false if an image of the given size can't be evenly covered by
/// cells and blocks of the size and stride specified in options.
fn is_valid_size(width: u32, height: u32, options: HogOptions) -> bool {

    if width as usize % options.cell_side != 0 {
        return false;
    }
    if height as usize % options.cell_side != 0 {
        return false;
    }
    if (width as usize - options.block_side) % options.block_stride != 0 {
        return false;
    }
    if (height as usize - options.block_side) % options.block_stride != 0 {
        return false;
    }
    true
}

#[cfg(test)]
mod test {

    use super::{
        HogOptions,
        HogDimensions,
        num_blocks
    };

    #[test]
    fn test_num_blocks() {
        // -----
        // ***
        //   ***
        assert_eq!(num_blocks(5, 3, 2), 2);
        // -----
        // *****
        assert_eq!(num_blocks(5, 5, 2), 1);
        // ----
        // **
        //   **
        assert_eq!(num_blocks(4, 2, 2), 2);
        // ---
        // *
        //  *
        //   *
        assert_eq!(num_blocks(3, 1, 1), 3);
    }

    #[test]
    fn test_hog_dimensions() {
        assert_eq!(
			HogDimensions::from_options(40, 40, HogOptions::new(8, true, 5, 2, 1))
				.descriptor_length(), 1568);
        assert_eq!(
			HogDimensions::from_options(40, 40, HogOptions::new(9, true, 4, 2, 1))
				.descriptor_length(), 2916);
        assert_eq!(
			HogDimensions::from_options(40, 40, HogOptions::new(8, true, 4, 2, 1))
				.descriptor_length(), 2592);
    }
}
<|endoftext|>


<commit_before>//! # libgoblin
//!
//! ![say the right
//! words](https://s-media-cache-ak0.pinimg.com/736x/1b/6a/aa/1b6aaa2bae005e2fed84b1a7c32ecb1b.jpg)
//!
//! `libgoblin` is a cross-platform trifecta of binary parsing and loading fun.  Currently, it only
//! supports the ELF format, in both 32-bit and 64-bit variants.  The mach parser is in progress, and the PE format will follow.  `libgoblin` is
//! engineered to be tailored towards very different use-case scenarios, for example:
//!
//! * a no-std mode; just simply set default features to false
//! * a endian aware parsing and reading
//! * for binary loaders which don't require this, simply use `elf32` and `elf64` (and `std` of course)
//!
//! # Example Feature Usage
//! For example, if you are writing a 64-bit kernel, or just want a barebones C-like
//! header interface which defines the structures, just select `elf64`, `--cfg
//! feature=\"elf64\"`, which will compile without `std`.
//!
//! Similarly, if you want to use host endianness loading via the various `from_fd` methods, `--cfg
//! feature=\"std\"`, which will not use the `byteorder` extern crate, and read the bytes
//! from disk in the endianness of the host machine.
//!
//! If you want endian aware reading, and you don't use `default`, then you need to opt in as normal
//! via `endian_fd`

#![cfg_attr(not(feature = "std"), no_std)]

// if the no_endian feature flag is set the libary will only be able to
// process files with the same endianess as the machine.
#[cfg(feature = "endian_fd")]
extern crate scroll;

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

#[cfg(feature = "std")]
extern crate core;

#[macro_use]
mod macros;

#[cfg(any(feature = "elf64", feature = "elf32"))]
#[macro_use]
pub mod elf;

#[cfg(feature = "std")]
pub mod error;

// if racer gets path understanding, i think this is the way to go; it hides everything from the
// user w.r.t. module internals like _64, etc.  though i did like the more declarative version
// below, without using paths, i just for the life of me cannot get the compiler to reexport values
// two mods down while keeping the internal mod name private... and i don't see anyone else doing
// this
#[cfg(feature = "elf64")]
#[path = "elf/_64/mod.rs"]
pub mod elf64;

#[cfg(feature = "elf32")]
#[path = "elf/_32/mod.rs"]
pub mod elf32;

#[cfg(feature = "mach64")]
pub mod mach;

#[cfg(feature = "archive")]
pub mod archive;

#[cfg(feature = "pe32")]
pub mod pe;

#[cfg(feature = "std")]
pub use impure::*;

#[cfg(feature = "std")]
mod impure {
    use super::*;
    use std::io::{Read, Seek, SeekFrom};

    #[derive(Debug, Default)]
    /// Information obtained from a peek `Hint`
    pub struct HintData {
        pub is_lsb: bool,
        pub is_64: Option<bool>,
    }

    #[derive(Debug)]
    /// A hint at the underlying binary format for 16 bytes of arbitrary data
    pub enum Hint {
        Elf(HintData),
        Mach,
        PE,
        Archive,
        Unknown,
    }

    /// Peeks at the underlying Read object. Requires the underlying bytes to have at least 16 byte length. Resets the seek after reading.
    pub fn peek<R: Read + Seek>(fd: &mut R) -> error::Result<Hint> {
        use scroll::Pread;
        let mut bytes = [0u8; 16];
        fd.seek(SeekFrom::Start(0))?;
        fd.read_exact(&mut bytes)?;
        fd.seek(SeekFrom::Start(0))?;
        if &bytes[0..elf::header::SELFMAG] == elf::header::ELFMAG {
            let class = bytes[elf::header::EI_CLASS];
            let is_lsb = bytes[elf::header::EI_DATA] == elf::header::ELFDATA2LSB;
            let is_64 =
                if class == elf::header::ELFCLASS64 {
                    Some (true)
                } else if class == elf::header::ELFCLASS32 {
                    Some (false)
                } else { None };

            Ok(Hint::Elf(HintData { is_lsb: is_lsb, is_64: is_64 }))
        } else if &bytes[0..archive::SIZEOF_MAGIC] == archive::MAGIC {
            Ok(Hint::Archive)
        } else if (&bytes[0..2]).pread::<u16>(0)? == pe::header::DOS_MAGIC {
            Ok(Hint::PE)
        } else {
            Ok(Hint::Unknown)
        }
    }
}
<commit_msg>goblin: update top level docs and add example<commit_after>//! # libgoblin
//!
//! ![say the right
//! words](https://s-media-cache-ak0.pinimg.com/736x/1b/6a/aa/1b6aaa2bae005e2fed84b1a7c32ecb1b.jpg)
//!
//! `libgoblin` is a cross-platform trifecta of binary parsing and loading fun.  Currently, it supports:
//!
//! * the ELF32/64 formats
//! * A Unix archive parser and loader
//! * A PE 32-bit parser
//! * The mach parser is in progress
//!
//! # Example
//!
//! ```rust
//! use goblin::{error, Hint, pe, elf, mach, archive};
//! use std::path::Path;
//! use std::env;
//! use std::fs::File;
//!
//! fn run () -> error::Result<()> {
//!     for (i, arg) in env::args().enumerate() {
//!         if i == 1 {
//!             let path = Path::new(arg.as_str());
//!             let mut fd = File::open(path)?;
//!             match goblin::peek(&mut fd)? {
//!                 Hint::Elf(_) => {
//!                     let elf = elf::Elf::try_from(&mut fd)?;
//!                     println!("elf: {:#?}", &elf);
//!                 },
//!                 Hint::PE => {
//!                     let pe = pe::PE::try_from(&mut fd)?;
//!                     println!("pe: {:#?}", &pe);
//!                 },
//!                 // wip
//!                 Hint::Mach => {
//!                     let mach = mach::Mach::try_from(&mut fd)?;
//!                     println!("mach: {:#?}", &mach);
//!                 },
//!                 Hint::Archive => {
//!                     let archive = archive::Archive::try_from(&mut fd)?;
//!                     println!("archive: {:#?}", &archive);
//!                 },
//!                 _ => {}
//!             }
//!         }
//!     }
//!     Ok(())
//! }
//! ```
//!
//! # Feature Usage
//!
//! `libgoblin` is engineered to be tailored towards very different use-case scenarios, for example:
//!
//! * a no-std mode; just simply set default features to false
//! * a endian aware parsing and reading
//! * for binary loaders which don't require this, simply use `elf32` and `elf64` (and `std` of course)
//!
//! For example, if you are writing a 64-bit kernel, or just want a barebones C-like
//! header interface which defines the structures, just select `elf64`, `--cfg
//! feature=\"elf64\"`, which will compile without `std`.
//!
//! Similarly, if you want to use host endianness loading via the various `from_fd` methods, `--cfg
//! feature=\"std\"`, which will not use the `byteorder` extern crate, and read the bytes
//! from disk in the endianness of the host machine.
//!
//! If you want endian aware reading, and you don't use `default`, then you need to opt in as normal
//! via `endian_fd`

#![cfg_attr(not(feature = "std"), no_std)]

// if the no_endian feature flag is set the libary will only be able to
// process files with the same endianess as the machine.
#[cfg(feature = "endian_fd")]
extern crate scroll;

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

#[cfg(feature = "std")]
extern crate core;

#[macro_use]
mod macros;

#[cfg(any(feature = "elf64", feature = "elf32"))]
#[macro_use]
pub mod elf;

#[cfg(feature = "std")]
pub mod error;

// if racer gets path understanding, i think this is the way to go; it hides everything from the
// user w.r.t. module internals like _64, etc.  though i did like the more declarative version
// below, without using paths, i just for the life of me cannot get the compiler to reexport values
// two mods down while keeping the internal mod name private... and i don't see anyone else doing
// this
#[cfg(feature = "elf64")]
#[path = "elf/_64/mod.rs"]
pub mod elf64;

#[cfg(feature = "elf32")]
#[path = "elf/_32/mod.rs"]
pub mod elf32;

#[cfg(feature = "mach64")]
pub mod mach;

#[cfg(feature = "archive")]
pub mod archive;

#[cfg(feature = "pe32")]
pub mod pe;

#[cfg(feature = "std")]
pub use impure::*;

#[cfg(feature = "std")]
mod impure {
    use super::*;
    use std::io::{Read, Seek, SeekFrom};

    #[derive(Debug, Default)]
    /// Information obtained from a peek `Hint`
    pub struct HintData {
        pub is_lsb: bool,
        pub is_64: Option<bool>,
    }

    #[derive(Debug)]
    /// A hint at the underlying binary format for 16 bytes of arbitrary data
    pub enum Hint {
        Elf(HintData),
        Mach,
        PE,
        Archive,
        Unknown,
    }

    /// Peeks at the underlying Read object. Requires the underlying bytes to have at least 16 byte length. Resets the seek after reading.
    pub fn peek<R: Read + Seek>(fd: &mut R) -> error::Result<Hint> {
        use scroll::Pread;
        let mut bytes = [0u8; 16];
        fd.seek(SeekFrom::Start(0))?;
        fd.read_exact(&mut bytes)?;
        fd.seek(SeekFrom::Start(0))?;
        if &bytes[0..elf::header::SELFMAG] == elf::header::ELFMAG {
            let class = bytes[elf::header::EI_CLASS];
            let is_lsb = bytes[elf::header::EI_DATA] == elf::header::ELFDATA2LSB;
            let is_64 =
                if class == elf::header::ELFCLASS64 {
                    Some (true)
                } else if class == elf::header::ELFCLASS32 {
                    Some (false)
                } else { None };

            Ok(Hint::Elf(HintData { is_lsb: is_lsb, is_64: is_64 }))
        } else if &bytes[0..archive::SIZEOF_MAGIC] == archive::MAGIC {
            Ok(Hint::Archive)
        } else if (&bytes[0..2]).pread::<u16>(0)? == pe::header::DOS_MAGIC {
            Ok(Hint::PE)
        } else {
            Ok(Hint::Unknown)
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate bitflags;
extern crate gl as gl_lib;

#[macro_use] mod context;
mod buffer;
mod shader;
mod program;
#[macro_use] mod vertex_data;
#[macro_use] mod vertex_buffer;
mod uniform_data;
mod types;

pub use gl_lib as gl;

pub use context::Context;
pub use buffer::{Buffer, BufferBinding, BufferDataUsage,
                 STREAM_DRAW, STATIC_DRAW, DYNAMIC_DRAW,
                 ArrayBufferBinder, ElementArrayBufferBinder,
                 ArrayBufferBinding, ElementArrayBufferBinding};
pub use shader::{Shader, ShaderType, VERTEX_SHADER, FRAGMENT_SHADER};
pub use program::{Program, ProgramAttrib, ProgramBinder, ProgramBinding};
pub use uniform_data::{UniformData, UniformDatum, UniformPrimitive,
                       UniformPrimitiveType, UniformDatumType};
pub use vertex_data::{VertexData, VertexDatum, VertexBytes, VertexAttribBinder,
                      DataType, BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT,
                      FIXED, FLOAT};
pub use vertex_buffer::{VertexBuffer, VertexBufferBinding};
pub use types::{Color, Viewport, GLError, BufferBits, DrawingMode,
                COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT, STENCIL_BUFFER_BIT,
                POINTS, LINE_STRIP, LINE_LOOP, LINES,
                TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES};
<commit_msg>Remove unnecessary `#[macro_use]`s<commit_after>#[macro_use] extern crate bitflags;
extern crate gl as gl_lib;

mod context;
mod buffer;
mod shader;
mod program;
mod vertex_data;
mod vertex_buffer;
mod uniform_data;
mod types;

pub use gl_lib as gl;

pub use context::Context;
pub use buffer::{Buffer, BufferBinding, BufferDataUsage,
                 STREAM_DRAW, STATIC_DRAW, DYNAMIC_DRAW,
                 ArrayBufferBinder, ElementArrayBufferBinder,
                 ArrayBufferBinding, ElementArrayBufferBinding};
pub use shader::{Shader, ShaderType, VERTEX_SHADER, FRAGMENT_SHADER};
pub use program::{Program, ProgramAttrib, ProgramBinder, ProgramBinding};
pub use uniform_data::{UniformData, UniformDatum, UniformPrimitive,
                       UniformPrimitiveType, UniformDatumType};
pub use vertex_data::{VertexData, VertexDatum, VertexBytes, VertexAttribBinder,
                      DataType, BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT,
                      FIXED, FLOAT};
pub use vertex_buffer::{VertexBuffer, VertexBufferBinding};
pub use types::{Color, Viewport, GLError, BufferBits, DrawingMode,
                COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT, STENCIL_BUFFER_BIT,
                POINTS, LINE_STRIP, LINE_LOOP, LINES,
                TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES};
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![crate_name = "hyperhyper"]
#![feature(lookup_host)]
#![feature(ip_addr)]
extern crate mio;

use mio::*;
use mio::tcp::*;
use std::str::FromStr;
use std::net::SocketAddr;
use mio::buf::{ByteBuf, MutByteBuf, SliceBuf};
// Define a handler to process the events
use std::{io, thread};
use std::net;
const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);

struct Echo {
    non_block_client: TcpStream,
    token: Option<Token>,
    mut_buf: Option<MutByteBuf>,

    buf: Option<ByteBuf>,
    interest: Interest
}

impl Echo {
    fn new(client: TcpStream) -> Echo {
        Echo {
            non_block_client: client,
            mut_buf: Some(ByteBuf::mut_with_capacity(2048)),
            interest: Interest::hup(),
            buf: None,
            token: None,
        }
    }
}
impl Handler for Echo {
    type Timeout = usize;
    type Message = String;

    fn readable(&mut self, event_loop: &mut EventLoop<Echo>, token: Token, hint: ReadHint) {
        let mut buf = ByteBuf::mut_with_capacity(2048);
        match self.non_block_client.read(&mut buf) {
            Ok(None) => {
                println!("We just got readable, but were unable to read from the socket?");
            }
            Ok(Some(r)) => {
                println!("CONN : we read {} bytes!", r);
                self.interest.remove(Interest::readable());
                if (r > 0) {
                    event_loop.reregister(&self.non_block_client, token, self.interest,
                                          PollOpt::edge() | PollOpt::oneshot());
                } else {
                    event_loop.shutdown();
                }
            }
            Err(e) => {
                println!("not implemented; client err={:?}", e);
                self.interest.remove(Interest::readable());
            }
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Echo>, token: Token) {
        let mut buf = ByteBuf::from_slice("GET /\n".as_bytes());

        match self.non_block_client.write(&mut buf) {
            Ok(None) => {
                println!("client flushing buf; WOULDBLOCK");

                self.buf = Some(buf);
                self.interest.insert(Interest::writable());
            }
            Ok(Some(r)) => {
                println!("CONN : we wrote {} bytes!", r);

                self.mut_buf = Some(buf.flip());

                self.interest.insert(Interest::readable());
                self.interest.remove(Interest::writable());
            }
            Err(e) => println!("not implemented; client err={:?}", e),
        }
        event_loop.reregister(&self.non_block_client, token, self.interest,
                              PollOpt::edge() | PollOpt::oneshot());
    }
    fn notify(&mut self, event_loop: &mut EventLoop<Echo>, msg: String) {
        println!("test3");
    }
}

pub fn google() -> SocketAddr {
    let s = format!("216.58.192.4:{}", 80);
    FromStr::from_str(&s).unwrap()
}

fn get_web_page(hostname: String, port: u16, get_resource: String) {
    let mut event_loop = EventLoop::new().unwrap();
    // == Create & setup client socket

    let url = String::new();

    // == Run test
    println!("Connecting");
    let ip = std::net::lookup_host(&hostname).unwrap().next().unwrap().unwrap();
    let address = SocketAddr::new(ip.ip(), port);
    let (sock, _) = TcpSocket::v4().unwrap().connect(&address).unwrap();
    event_loop.register_opt(&sock, CLIENT, Interest::writable(),
                            PollOpt::edge() | PollOpt::oneshot()).unwrap();
    event_loop.run(&mut Echo::new(sock));
}

#[test]
fn test() {
    println!("test");
    get_web_page("www.google.com".to_string(), 80, "/".to_string());
}
<commit_msg>I got a compiler bug here<commit_after>#![crate_type = "lib"]
#![crate_name = "hyperhyper"]
#![feature(lookup_host)]
#![feature(ip_addr)]
extern crate mio;

use mio::*;
use mio::tcp::*;
use std::str::FromStr;
use std::net::SocketAddr;
use mio::buf::{ByteBuf, MutByteBuf};
// Define a handler to process the events
const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);
enum HTTP_ACTION {
	Get(Into<String>),
}

struct Echo {
    non_block_client: TcpStream,
    action: Box<HTTP_ACTION>,
    token: Option<Token>,
    mut_buf: Option<MutByteBuf>,

    buf: Option<ByteBuf>,
    interest: Interest
}

impl Echo {
    fn new(client: TcpStream,
    	action: Box<HTTP_ACTION>) -> Echo {
        Echo {
            non_block_client: client,
            action: action,
            mut_buf: Some(ByteBuf::mut_with_capacity(2048)),
            interest: Interest::hup(),
            buf: None,
            token: None,
        }
    }
}
impl Handler for Echo {
    type Timeout = usize;
    type Message = String;

    fn readable(&mut self, event_loop: &mut EventLoop<Echo>, token: Token, hint: ReadHint) {
        let mut buf = ByteBuf::mut_with_capacity(2048);
        match self.non_block_client.read(&mut buf) {
            Ok(None) => {
                println!("We just got readable, but were unable to read from the socket?");
            }
            Ok(Some(r)) => {
                println!("CONN : we read {} bytes!", r);
                self.interest.remove(Interest::readable());
                if (r > 0) {
                    event_loop.reregister(&self.non_block_client, token, self.interest,
                                          PollOpt::edge() | PollOpt::oneshot());
                } else {
                    event_loop.shutdown();
                }
            }
            Err(e) => {
                println!("not implemented; client err={:?}", e);
                self.interest.remove(Interest::readable());
            }
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Echo>, token: Token) {
    	let ref foo = self.action;
        let mut buf = ByteBuf::from_slice("GET /\n".as_bytes());

        match self.non_block_client.write(&mut buf) {
            Ok(None) => {
                println!("client flushing buf; WOULDBLOCK");

                self.buf = Some(buf);
                self.interest.insert(Interest::writable());
            }
            Ok(Some(r)) => {
                println!("CONN : we wrote {} bytes!", r);

                self.mut_buf = Some(buf.flip());

                self.interest.insert(Interest::readable());
                self.interest.remove(Interest::writable());
            }
            Err(e) => println!("not implemented; client err={:?}", e),
        }
        event_loop.reregister(&self.non_block_client, token, self.interest,
                              PollOpt::edge() | PollOpt::oneshot());
    }
    fn notify(&mut self, event_loop: &mut EventLoop<Echo>, msg: String) {
        println!("test3");
    }
}

pub fn google() -> SocketAddr {
    let s = format!("216.58.192.4:{}", 80);
    FromStr::from_str(&s).unwrap()
}

fn get_web_page(hostname: String, port: u16, action: Box<HTTP_ACTION>) {
    let mut event_loop = EventLoop::new().unwrap();
    // == Create & setup client socket

    let url = String::new();

    // == Run test
    println!("Connecting");
    let ip = std::net::lookup_host(&hostname).unwrap().next().unwrap().unwrap();
    let address = SocketAddr::new(ip.ip(), port);
    let (sock, _) = TcpSocket::v4().unwrap().connect(&address).unwrap();
    event_loop.register_opt(&sock, CLIENT, Interest::writable(),
                            PollOpt::edge() | PollOpt::oneshot()).unwrap();
    event_loop.run(&mut Echo::new(sock, action));
}

#[test]
fn test() {
    println!("test");
    get_web_page("www.google.com".to_string(), 80, Box::new(Get("/")));
}
<|endoftext|>


<commit_before>extern crate walkdir;
extern crate regex;
extern crate url;

use std::process::Command;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

#[derive(Debug)]
struct Repository {
  root: String,
  path: String,
}

pub fn command_get(projects: Vec<String>, skip_pull: bool, shallow: bool) -> i32 {
  for project in projects {
    let (protocol, base_url, user, repo);
    if url::Url::parse(&project).is_ok() {
      let re = regex::Regex::new(r"([a-z]+)://([\w-\.]+)/([\w-.]+)/([\w-.]+)\.git").unwrap();
      let caps = re.captures(&project).unwrap();
      protocol = caps.at(1).unwrap().to_owned();
      base_url = caps.at(2).unwrap().to_owned();
      user = caps.at(3).unwrap().to_owned();
      repo = caps.at(4).unwrap().to_owned();
    } else {
      protocol = "https".to_owned();
      base_url = "github.com".to_owned();
      let re = regex::Regex::new(r"([\w-.]+)/([\w-.]+)").unwrap();
      if let Some(caps) = re.captures(&project) {
        user = caps.at(1).unwrap().to_owned();
        repo = caps.at(2).unwrap().to_owned();
      } else {
        user = project.clone();
        repo = project.clone();
      }
    }
    let url = url::Url::parse(&format!("{}://{}/{}/{}.git", protocol, base_url, user, repo))
      .unwrap();

    let mut dest = PathBuf::from(&get_local_repos_roots()[0]);
    dest.push(base_url);
    dest.push(user);
    dest.push(repo);

    git_clone_or_pull(url, dest.as_path(), skip_pull, shallow);
  }
  0
}

pub fn command_list(exact: bool, fullpath: bool, unique: bool, query: Option<String>) -> i32 {
  let filter: Box<Fn(&str) -> bool> = {
    if let Some(query) = query {
      if exact {
        Box::new(move |s: &str| s == query)
      } else {
        Box::new(move |s: &str| s.contains(&query))
      }
    } else {
      Box::new(|_| true)
    }
  };

  for repo in get_local_repositories(filter) {
    if fullpath {
      let mut repo_path = PathBuf::from(repo.root);
      repo_path.push(repo.path);
      println!("{}", repo_path.display());
    } else if unique {
      let repo_name = Path::new(&repo.path)
        .file_name()
        .unwrap()
        .to_str()
        .unwrap();
      println!("{}", repo_name);
    } else {
      println!("{}", repo.path);
    }
  }

  0
}

pub fn command_root(all: bool) -> i32 {
  let roots = get_local_repos_roots();
  if all {
    for root in roots {
      println!("{}", root);
    }
  } else {
    println!("{}", roots[0]);
  }
  0
}

fn git_clone_or_pull(url: url::Url, dest: &Path, skip_pull: bool, shallow: bool) {
  if dest.exists() {
    if !skip_pull {
      git_pull(dest);
    }
  } else {
    git_clone(url, dest, shallow);
  }
}

#[allow(unreachable_code)]
fn git_clone(url: url::Url, dest: &Path, shallow: bool) {
  println!("clone: {:?} -> {:?} ({})",
           url,
           dest,
           if shallow { "Shallow" } else { "" });
  return;

  let mut args = vec!["clone", url.as_str(), dest.to_str().unwrap()];
  if shallow {
    args.extend(&["--depth", "1"]);
  }

  let output = Command::new("git")
    .args(&args[..])
    .output()
    .expect("failed to clone repository");
  if !output.status.success() {
    panic!("git clone failed");
  }
}

struct ScopeExit<F: FnMut()> {
  caller: F,
}

impl<F: FnMut()> ScopeExit<F> {
  fn new(c: F) -> ScopeExit<F> {
    ScopeExit { caller: c }
  }
}

impl<F: FnMut()> Drop for ScopeExit<F> {
  fn drop(&mut self) {
    (self.caller)();
  }
}

#[allow(unreachable_code)]
fn git_pull(dest: &Path) {
  println!("pull: {:?}", dest);
  return;

  let curr_dir = std::env::current_dir().unwrap().to_str().unwrap().to_owned();
  std::env::set_current_dir(dest).unwrap();
  ScopeExit::new(|| {
    std::env::set_current_dir(curr_dir.clone()).unwrap();
  });

  let output = Command::new("git")
    .args(&["pull"])
    .output()
    .expect("failed to clone repository");
  if !output.status.success() {
    panic!("git pull failed");
  }
}

fn git_config(key: &str) -> String {
  let output = Command::new("git")
    .args(&["config", "--path", "--null", "--get-all", key])
    .output()
    .expect("failed to execute git");
  let len = output.stdout.len();
  String::from_utf8(Vec::from(&output.stdout[0..len - 1])).unwrap()
}

fn get_local_repositories(filter: Box<Fn(&str) -> bool>) -> Vec<Repository> {
  let mut dst = Vec::new();

  let roots = get_local_repos_roots();
  for root in roots {
    for entry in WalkDir::new(&root).follow_links(true).into_iter().filter_map(|e| e.ok()) {
      let path = format!("{}", entry.path().display()).replace(&format!("{}/", root), "");
      if entry.depth() == 3 {

        let entry = vec![".git", ".svn", ".hg", "_darcs"].into_iter().find(|&e| {
          let mut buf = PathBuf::from(format!("{}", entry.path().display()));
          if !filter(buf.file_name().unwrap().to_str().unwrap()) {
            return false;
          }
          buf.push(e);
          buf.exists()
        });

        if entry.is_some() {
          dst.push(Repository {
            root: root.clone(),
            path: path,
          });
        }
      }
    }
  }

  dst
}

fn get_local_repos_roots() -> Vec<String> {
  let mut local_repo_roots;

  let env_root: String = std::env::var("GHQ_ROOT").unwrap_or("".to_owned());
  if env_root == "" {
    local_repo_roots = vec![git_config("ghq.root")];
  } else {
    local_repo_roots = env_root.split(":").map(|s| s.to_owned()).collect();
  }

  if local_repo_roots.len() == 0 {
    let mut ghq_path = std::env::home_dir().unwrap();
    ghq_path.push(".ghq");
    local_repo_roots.push(format!("{}", ghq_path.display()));
  }

  assert!(local_repo_roots.len() >= 1);

  local_repo_roots
}
<commit_msg>separate parsing of cloned repository<commit_after>extern crate walkdir;
extern crate regex;
extern crate url;

use std::process::Command;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

#[derive(Debug)]
struct Repository {
  root: String,
  path: String,
}

pub fn command_get(projects: Vec<String>, skip_pull: bool, shallow: bool) -> i32 {
  for project in projects {
    let (protocol, base_url, user, repo) = parse_token(project);
    let url = url::Url::parse(&format!("{}://{}/{}/{}.git", protocol, base_url, user, repo))
      .unwrap();

    let mut dest = PathBuf::from(&get_local_repos_roots()[0]);
    dest.push(base_url);
    dest.push(user);
    dest.push(repo);

    git_clone_or_pull(url, dest.as_path(), skip_pull, shallow);
  }
  0
}

pub fn command_list(exact: bool, fullpath: bool, unique: bool, query: Option<String>) -> i32 {
  let filter: Box<Fn(&str) -> bool> = {
    if let Some(query) = query {
      if exact {
        Box::new(move |s: &str| s == query)
      } else {
        Box::new(move |s: &str| s.contains(&query))
      }
    } else {
      Box::new(|_| true)
    }
  };

  for repo in get_local_repositories(filter) {
    if fullpath {
      let mut repo_path = PathBuf::from(repo.root);
      repo_path.push(repo.path);
      println!("{}", repo_path.display());
    } else if unique {
      let repo_name = Path::new(&repo.path)
        .file_name()
        .unwrap()
        .to_str()
        .unwrap();
      println!("{}", repo_name);
    } else {
      println!("{}", repo.path);
    }
  }

  0
}

pub fn command_root(all: bool) -> i32 {
  let roots = get_local_repos_roots();
  if all {
    for root in roots {
      println!("{}", root);
    }
  } else {
    println!("{}", roots[0]);
  }
  0
}

fn git_clone_or_pull(url: url::Url, dest: &Path, skip_pull: bool, shallow: bool) {
  if dest.exists() {
    if !skip_pull {
      git_pull(dest);
    }
  } else {
    git_clone(url, dest, shallow);
  }
}

#[allow(unreachable_code)]
fn git_clone(url: url::Url, dest: &Path, shallow: bool) {
  println!("clone: {:?} -> {:?} ({})",
           url,
           dest,
           if shallow { "Shallow" } else { "" });
  return;

  let mut args = vec!["clone", url.as_str(), dest.to_str().unwrap()];
  if shallow {
    args.extend(&["--depth", "1"]);
  }

  let output = Command::new("git")
    .args(&args[..])
    .output()
    .expect("failed to clone repository");
  if !output.status.success() {
    panic!("git clone failed");
  }
}

struct ScopeExit<F: FnMut()> {
  caller: F,
}

impl<F: FnMut()> ScopeExit<F> {
  fn new(c: F) -> ScopeExit<F> {
    ScopeExit { caller: c }
  }
}

impl<F: FnMut()> Drop for ScopeExit<F> {
  fn drop(&mut self) {
    (self.caller)();
  }
}

#[allow(unreachable_code)]
fn git_pull(dest: &Path) {
  println!("pull: {:?}", dest);
  return;

  let curr_dir = std::env::current_dir().unwrap().to_str().unwrap().to_owned();
  std::env::set_current_dir(dest).unwrap();
  ScopeExit::new(|| {
    std::env::set_current_dir(curr_dir.clone()).unwrap();
  });

  let output = Command::new("git")
    .args(&["pull"])
    .output()
    .expect("failed to clone repository");
  if !output.status.success() {
    panic!("git pull failed");
  }
}

fn git_config(key: &str) -> String {
  let output = Command::new("git")
    .args(&["config", "--path", "--null", "--get-all", key])
    .output()
    .expect("failed to execute git");
  let len = output.stdout.len();
  String::from_utf8(Vec::from(&output.stdout[0..len - 1])).unwrap()
}

fn get_local_repositories(filter: Box<Fn(&str) -> bool>) -> Vec<Repository> {
  let mut dst = Vec::new();

  let roots = get_local_repos_roots();
  for root in roots {
    for entry in WalkDir::new(&root).follow_links(true).into_iter().filter_map(|e| e.ok()) {
      let path = format!("{}", entry.path().display()).replace(&format!("{}/", root), "");
      if entry.depth() == 3 {

        let entry = vec![".git", ".svn", ".hg", "_darcs"].into_iter().find(|&e| {
          let mut buf = PathBuf::from(format!("{}", entry.path().display()));
          if !filter(buf.file_name().unwrap().to_str().unwrap()) {
            return false;
          }
          buf.push(e);
          buf.exists()
        });

        if entry.is_some() {
          dst.push(Repository {
            root: root.clone(),
            path: path,
          });
        }
      }
    }
  }

  dst
}

fn get_local_repos_roots() -> Vec<String> {
  let mut local_repo_roots;

  let env_root: String = std::env::var("GHQ_ROOT").unwrap_or("".to_owned());
  if env_root == "" {
    local_repo_roots = vec![git_config("ghq.root")];
  } else {
    local_repo_roots = env_root.split(":").map(|s| s.to_owned()).collect();
  }

  if local_repo_roots.len() == 0 {
    let mut ghq_path = std::env::home_dir().unwrap();
    ghq_path.push(".ghq");
    local_repo_roots.push(format!("{}", ghq_path.display()));
  }

  assert!(local_repo_roots.len() >= 1);

  local_repo_roots
}

fn parse_token(project: String) -> (String, String, String, String) {
  let (protocol, base_url, user, repo): (String, String, String, String);
  match url::Url::parse(&project) {
    Ok(url) => {
      protocol = url.scheme().to_owned();
      base_url = url.host_str().unwrap().to_owned();

      let paths: Vec<_> = url.path_segments().unwrap().map(ToOwned::to_owned).collect();
      user = paths[0].clone();
      repo = paths[1].trim_right_matches(".git").to_owned();
    }
    Err(_) => {
      protocol = "https".to_owned();
      let paths: Vec<String> = project.split("/").map(ToOwned::to_owned).collect();
      if paths.len() == 3 {
        base_url = paths[0].clone();
        user = paths[1].clone();
        repo = paths[2].clone();
      } else if paths.len() == 2 {
        base_url = "github.com".to_owned();
        user = paths[0].clone();
        repo = paths[1].clone();
      } else {
        base_url = "github.com".to_owned();
        user = project.clone();
        repo = project.clone();
      }
    }
  };

  (protocol, base_url, user, repo)
}

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

  #[test]
  fn user_project() {
    let input = "hoge/fuga";
    let output = parse_token(input.to_owned());
    assert_eq!(output,
               ("https".to_owned(), "github.com".to_owned(), "hoge".to_owned(), "fuga".to_owned()));
  }

  #[test]
  fn domain_user_project() {
    let input = "github.com/hoge/fuga";
    let output = parse_token(input.to_owned());
    assert_eq!(output,
               ("https".to_owned(), "github.com".to_owned(), "hoge".to_owned(), "fuga".to_owned()));
  }

  #[test]
  fn only_project_name() {
    let input = "fuga";
    let output = parse_token(input.to_owned());
    assert_eq!(output,
               ("https".to_owned(), "github.com".to_owned(), "fuga".to_owned(), "fuga".to_owned()));
  }

  #[test]
  fn repository_url() {
    let input = "https://gitlab.com/funga-/pecopeco.git";
    let output = parse_token(input.to_owned());
    assert_eq!(output,
               ("https".to_owned(),
                "gitlab.com".to_owned(),
                "funga-".to_owned(),
                "pecopeco".to_owned()));
  }
}
<|endoftext|>


<commit_before>#[macro_use(rotor_compose)]
extern crate rotor;
extern crate rotor_http;
extern crate rotor_tools;
extern crate quire;
extern crate rustc_serialize;
extern crate regex;

pub mod server;
pub mod handler;
pub mod config;
pub mod builder;
pub mod context;
mod http_status;

pub use server::Responder;
pub use handler::Handler;
pub use context::Context;

pub use config::read_config;
pub use builder::build_context;
<commit_msg>Change module visibility<commit_after>#[macro_use(rotor_compose)]
extern crate rotor;
extern crate rotor_http;
extern crate rotor_tools;
extern crate quire;
extern crate rustc_serialize;
extern crate regex;

pub mod server;
pub mod handler;
pub mod config;
pub mod builder;
pub mod context;
pub mod http_status;

pub use server::Responder;
pub use handler::Handler;
pub use context::Context;

pub use config::read_config;
pub use builder::build_context;
<|endoftext|>


<commit_before>//! Edo is a VERY simple templating language. It allows you to register handlers that are executed when their matching names are found in the template.
//!
//! For example, with the template `"Hello {name}"`, the `name` handler would be executed and the string it returns would be substituted in place of the original `{name}`. Handler functions can also accept arguments, which are passed in as a `Vec<str>`.
//!
//! # Examples
//!
//! ### Simple example
//! ```
//! use edo::Edo;
//! let mut template = Edo::new("Hello {name}").unwrap();
//! template.register_handler("name", |_| String::from("World!"));
//! let output = template.render();
//! assert_eq!(output, "Hello World!");
//! ```
//!
//! ### With arguments
//! ```
//! use edo::Edo;
//! let mut template = Edo::new("{say_hello(World)}").unwrap();
//! template.register_handler("say_hello", |args| format!("Hello {}", args[0]));
//! let output = template.render();
//! assert_eq!(output, "Hello World");
//! ```
#![deny(missing_docs)]

#[macro_use]
extern crate nom;

mod error;
mod parse;

use std::str;
use std::collections::HashMap;

use error::EdoError;
use parse::Expression;

/// A single template. Allows registering of handlers and rendering
pub struct Edo<'a> {
    #[doc(hidden)]
    handlers: HashMap<&'a str, Box<Fn(Vec<&'a str>) -> String>>,
    template: Vec<Expression<'a>>,
}

impl<'a> Edo<'a> {
    /// Creates a new template instance.
    ///
    /// # Examples
    /// ```no_run
    /// # #![allow(unused_variables)]
    /// # use edo::Edo;
    /// let template = Edo::new("Hello {name}");
    /// ```
    pub fn new(template_string: &'a str) -> Result<Edo<'a>, EdoError> {
        Ok(Edo {
            handlers: HashMap::new(),
            template: try!(parse::parse(template_string)),
        })
    }

    /// Register a new function handler
    ///
    /// # Examples
    /// ```no_run
    /// # #![allow(unused_variables)]
    /// # use edo::Edo;
    /// let mut template = Edo::new("Hello {name}").unwrap();
    /// template.register_handler("name", |_| String::from("World!"));
    /// ```
    pub fn register_handler<F>(&mut self, name: &'a str, handler: F) where
        F: 'static + Fn(Vec<&'a str>) -> String {
        self.handlers.insert(name, Box::new(handler));
    }

    /// Render template into a string
    ///
    /// # Examples
    /// ```
    /// # use edo::Edo;
    /// let mut template = Edo::new("Hello {name}").unwrap();
    /// template.register_handler("name", |_| String::from("World!"));
    /// let output = template.render();
    /// assert_eq!(output, "Hello World!");
    /// ```
    // TODO: add a strict mode that errors when there is no handler
    pub fn render(self) -> String {
        // Iterate over the template and
        // 1. Leave literals untouched
        // 2. Call the handlers for each function call and replace within the output
        self.template.iter()
            .map(|expression| match *expression {
                Expression::Literal(text) => String::from(text),
                Expression::Function { name, ref arguments } => {
                    match self.handlers.get(name) {
                        None => String::from(""),
                        Some(handler) => handler(arguments.clone()),
                    }
                }
            })
            .collect::<Vec<String>>()
            .concat()
    }
}

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

    #[test]
    fn create_new_edo() {
        let edo = Edo::new("Hello {name}");
        assert!(edo.is_ok());
    }

    #[test]
    fn register_handler() {
        let mut edo = match Edo::new("Hello {name}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        edo.register_handler("name", |_| String::from("World!"));
        assert!(edo.handlers.get("name").is_some());
    }

    #[test]
    fn render_template() {
        let mut edo = match Edo::new("Hello {name}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        edo.register_handler("name", |_| String::from("World!"));
        assert_eq!(
            edo.render(),
            "Hello World!"
        );
    }

    #[test]
    fn render_template_with_missing_handler() {
        let edo = match Edo::new("Hello {name}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        assert_eq!(
            edo.render(),
            "Hello "
        );
    }

    #[test]
    fn render_template_with_arguments() {
        let mut edo = match Edo::new("Hello {name(Gio, yes)}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        edo.register_handler("name", |args|
            format!("{}{}", args[0], if args[1] == "yes" { "!" } else { "" })
        );
        assert_eq!(
            edo.render(),
            "Hello Gio!"
        );
    }
}
<commit_msg>Create function to register static values<commit_after>//! Edo is a VERY simple templating language. It allows you to register handlers that are executed when their matching names are found in the template.
//!
//! For example, with the template `"Hello {name}"`, the `name` handler would be executed and the string it returns would be substituted in place of the original `{name}`. Handler functions can also accept arguments, which are passed in as a `Vec<str>`.
//!
//! # Examples
//!
//! ### Static input
//! ```
//! use edo::Edo;
//! let mut template = Edo::new("Hello {name}").unwrap();
//! template.register_static("name", String::from("World!"));
//! let output = template.render();
//! assert_eq!(output, "Hello World!");
//! ```
//!
//! ### Simple Handler
//! ```
//! use edo::Edo;
//! let mut template = Edo::new("Hello {name}").unwrap();
//! template.register_handler("name", |_| String::from("World!"));
//! let output = template.render();
//! assert_eq!(output, "Hello World!");
//! ```
//!
//! ### Handler With Arguments
//! ```
//! use edo::Edo;
//! let mut template = Edo::new("{say_hello(World)}").unwrap();
//! template.register_handler("say_hello", |args| format!("Hello {}", args[0]));
//! let output = template.render();
//! assert_eq!(output, "Hello World");
//! ```
#![deny(missing_docs)]

#[macro_use]
extern crate nom;

mod error;
mod parse;

use std::str;
use std::collections::HashMap;

use error::EdoError;
use parse::Expression;

enum ValueProducer<'a> {
    Handler(Box<Fn(Vec<&'a str>) -> String>),
    Static(String),
}

/// A single template. Allows registering of handlers and rendering
pub struct Edo<'a> {
    #[doc(hidden)]
    value_producers: HashMap<&'a str, ValueProducer<'a>>,
    template: Vec<Expression<'a>>,
}

impl<'a> Edo<'a> {
    /// Creates a new template instance.
    ///
    /// # Examples
    /// ```no_run
    /// # #![allow(unused_variables)]
    /// # use edo::Edo;
    /// let template = Edo::new("Hello {name}");
    /// ```
    pub fn new(template_string: &'a str) -> Result<Edo<'a>, EdoError> {
        Ok(Edo {
            value_producers: HashMap::new(),
            template: try!(parse::parse(template_string)),
        })
    }

    /// Register a new function handler
    ///
    /// # Examples
    /// ```no_run
    /// # #![allow(unused_variables)]
    /// # use edo::Edo;
    /// let mut template = Edo::new("Hello {name}").unwrap();
    /// template.register_handler("name", |_| String::from("World!"));
    /// ```
    pub fn register_handler<F>(&mut self, name: &'a str, handler: F) where
        F: 'static + Fn(Vec<&'a str>) -> String {
        self.value_producers.insert(name, ValueProducer::Handler(Box::new(handler)));
    }

    /// Register a static replacement
    ///
    /// # Examples
    /// ```no_run
    /// # #![allow(unused_variables)]
    /// # use edo::Edo;
    /// let mut template = Edo::new("Hello {name}").unwrap();
    /// template.register_static("name", String::from("World!"));
    /// ```
    pub fn register_static(&mut self, name: &'a str, input: String) {
        self.value_producers.insert(name, ValueProducer::Static(input));
    }

    /// Render template into a string
    ///
    /// # Examples
    /// ```
    /// # use edo::Edo;
    /// let mut template = Edo::new("Hello {name}").unwrap();
    /// template.register_handler("name", |_| String::from("World!"));
    /// let output = template.render();
    /// assert_eq!(output, "Hello World!");
    /// ```
    // TODO: add a strict mode that errors when there is no handler
    pub fn render(self) -> String {
        // Iterate over the template and
        // 1. Leave literals untouched
        // 2. Call the handlers for each function call and replace within the output
        self.template.iter()
            .map(|expression| match *expression {
                Expression::Literal(text) => String::from(text),
                Expression::Function { name, ref arguments } => {
                    match self.value_producers.get(name) {
                        None => String::from(""),
                        Some(value_producer) => match value_producer {
                            &ValueProducer::Handler(ref handler) => handler(arguments.clone()),
                            &ValueProducer::Static(ref value) => value.clone(),
                        },
                    }
                }
            })
            .collect::<Vec<String>>()
            .concat()
    }
}

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

    #[test]
    fn create_new_edo() {
        let edo = Edo::new("Hello {name}");
        assert!(edo.is_ok());
    }

    #[test]
    fn register_handler() {
        let mut edo = match Edo::new("Hello {name}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        edo.register_handler("name", |_| String::from("World!"));
        assert!(edo.value_producers.get("name").is_some());
    }

    #[test]
    fn register_static() {
        let mut edo = match Edo::new("Hello {name}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        edo.register_static("name", String::from("World!"));
        assert!(edo.value_producers.get("name").is_some());
    }

    #[test]
    fn render_template() {
        let mut edo = match Edo::new("Hello {name}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        edo.register_handler("name", |_| String::from("World!"));
        assert_eq!(
            edo.render(),
            "Hello World!"
        );
    }

    #[test]
    fn render_template_with_missing_handler() {
        let edo = match Edo::new("Hello {name}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        assert_eq!(
            edo.render(),
            "Hello "
        );
    }

    #[test]
    fn render_template_with_arguments() {
        let mut edo = match Edo::new("Hello {name(Gio, yes)}") {
            Ok(edo) => edo,
            Err(err) => panic!(err),
        };
        edo.register_handler("name", |args|
            format!("{}{}", args[0], if args[1] == "yes" { "!" } else { "" })
        );
        assert_eq!(
            edo.render(),
            "Hello Gio!"
        );
    }
}
<|endoftext|>


<commit_before>extern crate cocoa;
extern crate metal_sys;
#[macro_use]
extern crate objc;

mod device;
mod command_queue;
mod value_types;

pub mod sys {
    pub use metal_sys::*;
}

pub use device::{Device, DeviceError};
pub use command_queue::{CommandQueue, CommandQueueError};
pub use value_types::{ClearColor, Origin, Region, ScissorRect, Size, Viewport};
<commit_msg>Export DeviceRef<commit_after>extern crate cocoa;
extern crate metal_sys;
#[macro_use]
extern crate objc;

mod device;
mod command_queue;
mod value_types;

pub mod sys {
    pub use metal_sys::*;
}

pub use device::{Device, DeviceError, DeviceRef};
pub use command_queue::{CommandQueue, CommandQueueError};
pub use value_types::{ClearColor, Origin, Region, ScissorRect, Size, Viewport};
<|endoftext|>


<commit_before>// Copyright 2016 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

//! Fast and lightweight Slab Allocator.

extern crate libc;

use std::{mem, ptr};
use std::ops::{Drop, Index};
use std::iter::{Iterator, IntoIterator};

pub struct Slab<T> {
    capacity: usize,
    len: usize,
    mem: *mut T
}

pub struct SlabIter<'a, T: 'a> {
    slab: &'a Slab<T>,
    current_offset: usize
}

pub struct SlabMutIter<'a, T: 'a> {
    iter: SlabIter<'a, T>
}

impl<T> Slab<T> {
    /// Creates a new Slab
    pub fn new() -> Slab<T> { Slab::with_capacity(1) }

    /// Creates a new, empty Slab with room for `capacity` elems
    ///
    /// # Panics
    ///
    /// * If the host system is out of memory
    pub fn with_capacity(capacity: usize) -> Slab<T> {
        let maybe_ptr = unsafe {
            libc::malloc((mem::size_of::<T>() * capacity)) as *mut T
        };

        // malloc will return NULL if called with zero
        if maybe_ptr.is_null() && capacity != 0 {
            panic!("Unable to allocate requested capacity")
        }

        return Slab {
            capacity: capacity,
            len: 0,
            mem: maybe_ptr
        }
    }

    /// Inserts a new element into the slab, re-allocating if neccessary.
    ///
    /// # Panics
    ///
    /// * If the host system is out of memory.
    #[inline]
    pub fn insert(&mut self, elem: T) {
        if self.len == self.capacity { self.reallocate(); }

        unsafe {
            let ptr = self.mem.offset(self.len as isize);
            ptr::write(ptr, elem);
        }

        self.len += 1;
    }

    /// Removes the element at `offset`.
    ///
    /// # Panics
    ///
    /// * If `offset` is out of bounds.
    #[inline]
    pub fn remove(&mut self, offset: usize) -> T {
        assert!(offset < self.len, "Offset out of bounds");

        let elem: T;
        let last_elem: T;
        let elem_ptr: *mut T;
        let last_elem_ptr: *mut T;

        unsafe {
            elem_ptr = self.mem.offset(offset as isize);
            last_elem_ptr = self.mem.offset(self.len as isize);

            elem = ptr::read(elem_ptr);
            last_elem = ptr::read(last_elem_ptr);

            ptr::write(elem_ptr, last_elem);
        }

        self.len -= 1;
        return elem;
    }

    /// Returns the number of elements in the slab
    #[inline]
    pub fn len(&self) -> usize { self.len }

    /// Returns an iterator over the slab
    #[inline]
    pub fn iter(&self) -> SlabIter<T> {
        SlabIter {
            slab: self,
            current_offset: 0
        }
    }

    /// Returns a mutable iterator over the slab
    #[inline]
    pub fn iter_mut(&mut self) -> SlabMutIter<T> {
        SlabMutIter { iter: self.iter() }
    }

    /// Reserves capacity * 2 extra space in this slab
    ///
    /// # Panics
    ///
    /// Panics if the host system is out of memory
    #[inline]
    fn reallocate(&mut self) {
        let new_capacity = if self.capacity != 0 {
            self.capacity * 2
        } else { 1 };

        let maybe_ptr = unsafe {
            libc::realloc(self.mem as *mut libc::c_void,
                          (mem::size_of::<T>() * new_capacity)) as *mut T
        };

        assert!(maybe_ptr.is_null(), "Out of Memory");

        self.capacity = new_capacity;
        self.mem = maybe_ptr;
    }
}

impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        for x in 0..self.len() {
            unsafe {
                let elem_ptr = self.mem.offset(x as isize);
                ptr::drop_in_place(elem_ptr);
            }
        }

        unsafe { libc::free(self.mem as *mut _ as *mut libc::c_void) };
    }
}

impl<T> Index<usize> for Slab<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output {
        unsafe { &(*(self.mem.offset(index as isize))) }
    }
}

impl<'a, T> Iterator for SlabIter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        while self.current_offset < self.slab.len() {
            let offset = self.current_offset;
            self.current_offset += 1;
            unsafe {
                return Some(&(*self.slab.mem.offset(offset as isize)));
            }
        }

        None
    }
}

impl<'a, T> Iterator for SlabMutIter<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<&'a mut T> {
        unsafe { mem::transmute(self.iter.next()) }
    }
}

impl<'a, T> IntoIterator for &'a Slab<T> {
    type Item = &'a T;
    type IntoIter = SlabIter<'a, T>;
    fn into_iter(self) -> SlabIter<'a, T> { self.iter() }
}

impl<'a, T> IntoIterator for &'a mut Slab<T> {
    type Item = &'a mut T;
    type IntoIter = SlabMutIter<'a, T>;
    fn into_iter(self) -> SlabMutIter<'a, T> { self.iter_mut() }
}
<commit_msg>Fixed assert.<commit_after>// Copyright 2016 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

//! Fast and lightweight Slab Allocator.

extern crate libc;

use std::{mem, ptr};
use std::ops::{Drop, Index};
use std::iter::{Iterator, IntoIterator};

pub struct Slab<T> {
    capacity: usize,
    len: usize,
    mem: *mut T
}

pub struct SlabIter<'a, T: 'a> {
    slab: &'a Slab<T>,
    current_offset: usize
}

pub struct SlabMutIter<'a, T: 'a> {
    iter: SlabIter<'a, T>
}

impl<T> Slab<T> {
    /// Creates a new Slab
    pub fn new() -> Slab<T> { Slab::with_capacity(1) }

    /// Creates a new, empty Slab with room for `capacity` elems
    ///
    /// # Panics
    ///
    /// * If the host system is out of memory
    pub fn with_capacity(capacity: usize) -> Slab<T> {
        let maybe_ptr = unsafe {
            libc::malloc((mem::size_of::<T>() * capacity)) as *mut T
        };

        // malloc will return NULL if called with zero
        if maybe_ptr.is_null() && capacity != 0 {
            panic!("Unable to allocate requested capacity")
        }

        return Slab {
            capacity: capacity,
            len: 0,
            mem: maybe_ptr
        }
    }

    /// Inserts a new element into the slab, re-allocating if neccessary.
    ///
    /// # Panics
    ///
    /// * If the host system is out of memory.
    #[inline]
    pub fn insert(&mut self, elem: T) {
        if self.len == self.capacity { self.reallocate(); }

        unsafe {
            let ptr = self.mem.offset(self.len as isize);
            ptr::write(ptr, elem);
        }

        self.len += 1;
    }

    /// Removes the element at `offset`.
    ///
    /// # Panics
    ///
    /// * If `offset` is out of bounds.
    #[inline]
    pub fn remove(&mut self, offset: usize) -> T {
        assert!(offset < self.len, "Offset out of bounds");

        let elem: T;
        let last_elem: T;
        let elem_ptr: *mut T;
        let last_elem_ptr: *mut T;

        unsafe {
            elem_ptr = self.mem.offset(offset as isize);
            last_elem_ptr = self.mem.offset(self.len as isize);

            elem = ptr::read(elem_ptr);
            last_elem = ptr::read(last_elem_ptr);

            ptr::write(elem_ptr, last_elem);
        }

        self.len -= 1;
        return elem;
    }

    /// Returns the number of elements in the slab
    #[inline]
    pub fn len(&self) -> usize { self.len }

    /// Returns an iterator over the slab
    #[inline]
    pub fn iter(&self) -> SlabIter<T> {
        SlabIter {
            slab: self,
            current_offset: 0
        }
    }

    /// Returns a mutable iterator over the slab
    #[inline]
    pub fn iter_mut(&mut self) -> SlabMutIter<T> {
        SlabMutIter { iter: self.iter() }
    }

    /// Reserves capacity * 2 extra space in this slab
    ///
    /// # Panics
    ///
    /// Panics if the host system is out of memory
    #[inline]
    fn reallocate(&mut self) {
        let new_capacity = if self.capacity != 0 {
            self.capacity * 2
        } else { 1 };

        let maybe_ptr = unsafe {
            libc::realloc(self.mem as *mut libc::c_void,
                          (mem::size_of::<T>() * new_capacity)) as *mut T
        };

        assert!(!maybe_ptr.is_null(), "Out of Memory");

        self.capacity = new_capacity;
        self.mem = maybe_ptr;
    }
}

impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        for x in 0..self.len() {
            unsafe {
                let elem_ptr = self.mem.offset(x as isize);
                ptr::drop_in_place(elem_ptr);
            }
        }

        unsafe { libc::free(self.mem as *mut _ as *mut libc::c_void) };
    }
}

impl<T> Index<usize> for Slab<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output {
        unsafe { &(*(self.mem.offset(index as isize))) }
    }
}

impl<'a, T> Iterator for SlabIter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        while self.current_offset < self.slab.len() {
            let offset = self.current_offset;
            self.current_offset += 1;
            unsafe {
                return Some(&(*self.slab.mem.offset(offset as isize)));
            }
        }

        None
    }
}

impl<'a, T> Iterator for SlabMutIter<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<&'a mut T> {
        unsafe { mem::transmute(self.iter.next()) }
    }
}

impl<'a, T> IntoIterator for &'a Slab<T> {
    type Item = &'a T;
    type IntoIter = SlabIter<'a, T>;
    fn into_iter(self) -> SlabIter<'a, T> { self.iter() }
}

impl<'a, T> IntoIterator for &'a mut Slab<T> {
    type Item = &'a mut T;
    type IntoIter = SlabMutIter<'a, T>;
    fn into_iter(self) -> SlabMutIter<'a, T> { self.iter_mut() }
}
<|endoftext|>


<commit_before>// A microframework for Rust.

//! Pencil is a microframework for Rust inspired by [Flask](http://flask.pocoo.org/).
//!
//! # Installation
//!
//! This crate is called `pencil` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.pencil]
//! git = "https://github.com/fengsp/pencil.git"
//! ```
//!
//! # Quickstart
//!
//! A short introduction to Pencil.
//!
//! ## A Minimal Application
//!
//! A minimal Pencil application looks something like this:
//!
//! ```rust,no_run
//! extern crate pencil;
//!
//! use pencil::Pencil;
//! use pencil::{Request, PencilResult, PenString};
//!
//!
//! fn hello(_: &Request) -> PencilResult {
//!     Ok(PenString(String::from("Hello World!")))
//! }
//!
//!
//! fn main() {
//!     let mut app = Pencil::new("/web/hello");
//!     app.route("/", &["GET"], "hello", hello);
//!     app.run();
//! }
//! ```

#![allow(unused_attributes)]
#![crate_name = "pencil"]
#![crate_type = "lib"]
#![doc(html_logo_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/pencil.png",
       html_favicon_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/favicon.ico",
       html_root_url = "http://fengsp.github.io/pencil/")]

#![deny(non_camel_case_types)]

#[macro_use]
extern crate log;
extern crate hyper;
extern crate rustc_serialize;
extern crate regex;
extern crate url;
extern crate formdata;
extern crate handlebars;

/* public api */
pub use app::Pencil;
pub use types::{
    PencilValue,
        PenString,
        PenResponse,
    PencilError,
        PenHTTPError,
        PenUserError,
    UserError,
    PencilResult,
    ViewArgs,
    ViewFunc,
    UserErrorHandler,
    HTTPErrorHandler,
    BeforeRequestFunc,
    AfterRequestFunc,
    TeardownRequestFunc,
};
pub use datastructures::{
    MultiDict,
        MultiDictIter,
        MultiDictValues,
};
pub use wrappers::{
    Request,
    Response,
};
pub use json::jsonify;
pub use config::{
    Config,
};
pub use helpers::{
    PathBound,
    safe_join,
    abort,
    redirect,
    escape,
    send_file,
    send_from_directory,
};
pub use serving::{
    run_server,
};
pub use http_errors::{
    HTTPError,
        BadRequest,
        Unauthorized,
        Forbidden,
        NotFound,
        MethodNotAllowed,
        NotAcceptable,
        RequestTimeout,
        Conflict,
        Gone,
        LengthRequired,
        PreconditionFailed,
        RequestEntityTooLarge,
        RequestURITooLarge,
        UnsupportedMediaType,
        RequestedRangeNotSatisfiable,
        ExpectationFailed,
        ImATeapot,
        UnprocessableEntity,
        PreconditionRequired,
        TooManyRequests,
        RequestHeaderFieldsTooLarge,
        InternalServerError,
        NotImplemented,
        BadGateway,
        ServiceUnavailable,
};
pub use testing::PencilClient;

#[macro_use]
mod utils;
mod app;
mod types;
mod datastructures;
mod wrappers;
mod json;
mod config;
mod logging;
mod helpers;
mod serving;
mod http_errors;
mod routing;
mod testing;
mod httputils;
mod templating;
mod formparser;
<commit_msg>Make datastructures module public<commit_after>// A microframework for Rust.

//! Pencil is a microframework for Rust inspired by [Flask](http://flask.pocoo.org/).
//!
//! # Installation
//!
//! This crate is called `pencil` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.pencil]
//! git = "https://github.com/fengsp/pencil.git"
//! ```
//!
//! # Quickstart
//!
//! A short introduction to Pencil.
//!
//! ## A Minimal Application
//!
//! A minimal Pencil application looks something like this:
//!
//! ```rust,no_run
//! extern crate pencil;
//!
//! use pencil::Pencil;
//! use pencil::{Request, PencilResult, PenString};
//!
//!
//! fn hello(_: &Request) -> PencilResult {
//!     Ok(PenString(String::from("Hello World!")))
//! }
//!
//!
//! fn main() {
//!     let mut app = Pencil::new("/web/hello");
//!     app.route("/", &["GET"], "hello", hello);
//!     app.run();
//! }
//! ```

#![allow(unused_attributes)]
#![crate_name = "pencil"]
#![crate_type = "lib"]
#![doc(html_logo_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/pencil.png",
       html_favicon_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/favicon.ico",
       html_root_url = "http://fengsp.github.io/pencil/")]

#![deny(non_camel_case_types)]

#[macro_use]
extern crate log;
extern crate hyper;
extern crate rustc_serialize;
extern crate regex;
extern crate url;
extern crate formdata;
extern crate handlebars;

/* public api */
pub use app::Pencil;
pub use types::{
    PencilValue,
        PenString,
        PenResponse,
    PencilError,
        PenHTTPError,
        PenUserError,
    UserError,
    PencilResult,
    ViewArgs,
    ViewFunc,
    UserErrorHandler,
    HTTPErrorHandler,
    BeforeRequestFunc,
    AfterRequestFunc,
    TeardownRequestFunc,
};
pub use wrappers::{
    Request,
    Response,
};
pub use json::jsonify;
pub use config::{
    Config,
};
pub use helpers::{
    PathBound,
    safe_join,
    abort,
    redirect,
    escape,
    send_file,
    send_from_directory,
};
pub use serving::{
    run_server,
};
pub use http_errors::{
    HTTPError,
        BadRequest,
        Unauthorized,
        Forbidden,
        NotFound,
        MethodNotAllowed,
        NotAcceptable,
        RequestTimeout,
        Conflict,
        Gone,
        LengthRequired,
        PreconditionFailed,
        RequestEntityTooLarge,
        RequestURITooLarge,
        UnsupportedMediaType,
        RequestedRangeNotSatisfiable,
        ExpectationFailed,
        ImATeapot,
        UnprocessableEntity,
        PreconditionRequired,
        TooManyRequests,
        RequestHeaderFieldsTooLarge,
        InternalServerError,
        NotImplemented,
        BadGateway,
        ServiceUnavailable,
};
pub use testing::PencilClient;

#[macro_use]
mod utils;
mod app;
mod types;
pub mod datastructures;
mod wrappers;
mod json;
mod config;
mod logging;
mod helpers;
mod serving;
mod http_errors;
mod routing;
mod testing;
mod httputils;
mod templating;
mod formparser;
<|endoftext|>


<commit_before>// DOCS

#![allow(unstable)]
use std::old_io;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

pub struct AtomicFile {
    pub path: Path,
    pub overwrite: OverwriteBehavior,
    pub tmpdir: Path
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.  The `tmpdir` will be used for temporary files, and must reside on the same
    /// filesystem. It defaults to creating temporary files in the same directory as `path`.
    pub fn new(path: &Path, overwrite: OverwriteBehavior, tmpdir: Option<&Path>) -> AtomicFile {
        AtomicFile {
            path: path.clone(),
            overwrite: overwrite,
            tmpdir: match tmpdir {
                Some(x) => x.clone(),
                None => path.dir_path()
            }
        }
    }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<F: FnMut(&mut old_io::File) -> old_io::IoResult<()>>(&self, mut f: F) -> old_io::IoResult<()> {
        let tmpdir = try!(old_io::TempDir::new_in(&self.tmpdir, ".atomicwrite"));
        let tmppath = tmpdir.path().join(Path::new("tmpfile.tmp"));
        {
            let mut tmpfile = try!(old_io::File::create(&tmppath));
            try!(f(&mut tmpfile));
        };
        try!(self.commit(&tmppath));

        Ok(())
    }

    /// Atomically move/copy the file to self.path.
    fn commit(&self, tmppath: &Path) -> old_io::IoResult<()> {
        match self.overwrite {
            AllowOverwrite => old_io::fs::rename(tmppath, &self.path),
            DisallowOverwrite => old_io::fs::link(tmppath, &self.path)
        }
    }
}

#[derive(Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}
<commit_msg>Fix warnings<commit_after>// DOCS

#![feature(path,io)]
use std::old_io;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

pub struct AtomicFile {
    pub path: Path,
    pub overwrite: OverwriteBehavior,
    pub tmpdir: Path
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.  The `tmpdir` will be used for temporary files, and must reside on the same
    /// filesystem. It defaults to creating temporary files in the same directory as `path`.
    pub fn new(path: &Path, overwrite: OverwriteBehavior, tmpdir: Option<&Path>) -> AtomicFile {
        AtomicFile {
            path: path.clone(),
            overwrite: overwrite,
            tmpdir: match tmpdir {
                Some(x) => x.clone(),
                None => path.dir_path()
            }
        }
    }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<F: FnMut(&mut old_io::File) -> old_io::IoResult<()>>(&self, mut f: F) -> old_io::IoResult<()> {
        let tmpdir = try!(old_io::TempDir::new_in(&self.tmpdir, ".atomicwrite"));
        let tmppath = tmpdir.path().join(Path::new("tmpfile.tmp"));
        {
            let mut tmpfile = try!(old_io::File::create(&tmppath));
            try!(f(&mut tmpfile));
        };
        try!(self.commit(&tmppath));

        Ok(())
    }

    /// Atomically move/copy the file to self.path.
    fn commit(&self, tmppath: &Path) -> old_io::IoResult<()> {
        match self.overwrite {
            AllowOverwrite => old_io::fs::rename(tmppath, &self.path),
            DisallowOverwrite => old_io::fs::link(tmppath, &self.path)
        }
    }
}

#[derive(Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}
<|endoftext|>


<commit_before>//! Defines "provider" traits and implementations for different types of I/O operations, enabling
//! dependency injection that's very helpful for testing.
//!
//! A number of different I/O types are supported:
//!
//! * Process environment (variables, working directy etc), via [`Env`](env/trait.Env.html)
//! * Standard streams (stdin, stdout and stderr), via [`StdStreams`](std_streams/trait.StdStreams.html)
//! * Filesystem access, via [`Fs`](fs/trait.Fs.html)
//!
//! In addition to "native" implementations for each trait, "simulated" implementations are also
//! built-in:
//!
//! * [`SimulatedEnv`](env/trait.SimulatedEnv.html) for faking process environment state
//! * [`SimulatedStdStreams`](std_streams/trait.SimulatedStdStreams.html) for faking standard
//!   stream input and inspecting output
//! * [`TempFs`](fs/trait.TempFs.html) for performing filesystem access in a `chroot`-like sandbox
//!   isolated from the rest of the filesystem
//!
//! Each provider trait can be used independently, however there is also the all-encompassing
//! [`Io`](trait.Io.html) which provides access to all of them. If you have a variety of I/O
//! dependencies, it might be easiest to create and pass around a single `&mut Io`.
//!
//! # Examples
//!
//! ```
//! extern crate io_providers;
//!
//! use std::io::Write;
//! use std::path::Path;
//! use io_providers::{Env, Io, NativeIo, SimulatedIo, StdStreams};
//!
//! /// Gets the current working directory and prints it to stdout.
//! fn do_work<I: Io>(io: &mut I) {
//!     let cur_dir = io.env().current_dir().unwrap();
//!     let stdout = io.std_streams().output();
//!     writeln!(stdout, "The current directory is: {}", cur_dir.to_str().unwrap()).unwrap();
//! }
//!
//! fn main() {
//!     // Test `do_work()` using a simulated I/O environment
//!     let mut simulated_io = SimulatedIo::new().unwrap();
//!     simulated_io.env().set_current_dir(Path::new("/foo/bar")).unwrap();
//!     do_work(&mut simulated_io);
//!     assert_eq!(
//!         "The current directory is: /foo/bar\n",
//!         ::std::str::from_utf8(simulated_io.std_streams().read_output()).unwrap());
//!
//!     // Now use a native I/O provided to access the real system
//!     let mut real_io = NativeIo::new();
//!     do_work(&mut real_io);
//! }
//! ```

extern crate tempfile;

use std::io;

pub mod env;
pub mod fs;
pub mod std_streams;

pub use env::{Env, NativeEnv, SimulatedEnv};
pub use fs::{Fs, NativeFs, OpenOptions, TempFs};
pub use std_streams::{NativeStdStreams, SimulatedStdStreams, StdStreams};

/// Provides access to the process environment, filesystem, and standard streams.
///
/// See [`env::Env`](env/trait.Env.html),
/// [`std_streams::StdStreams`](std_streams/trait.StdStreams.html) and
/// [`fs::Fs`](fs/trait.Fs.html) for details.
pub trait Io {
    // The type of the environment provider.
    type E: env::Env;

    // The type of the filesystem provider.
    type F: fs::Fs;

    // The type of the stream provider.
    type S: std_streams::StdStreams;

    /// Gets the [`env::Env`](env/trait.Env.html) provider.
    fn env(&mut self) -> &mut Self::E;

    /// Gets the [`fs::Fs`](fs/trait.Fs.html) provider.
    fn fs(&mut self) -> &mut Self::F;

    /// Gets the [`std_streams::StdStreams`](std_streams/trait.StdStreams.html).
    fn std_streams(&mut self) -> &mut Self::S;
}

/// `Io` implementation using the native system.
///
/// See `env::NativeEnv` and `std_streams::NativeStdStreams` for more information.
#[derive(Default)]
pub struct NativeIo {
    env: env::NativeEnv,
    fs: fs::NativeFs,
    stream: std_streams::NativeStdStreams,
}

impl NativeIo {
    /// Creates a new `LocalIoProvider`.
    pub fn new() -> NativeIo {
        NativeIo {
            env: env::NativeEnv,
            fs: fs::NativeFs,
            stream: std_streams::NativeStdStreams::new(),
        }
    }
}

impl Io for NativeIo {
    type E = env::NativeEnv;
    type F = fs::NativeFs;
    type S = std_streams::NativeStdStreams;

    fn env(&mut self) -> &mut env::NativeEnv {
        &mut self.env
    }

    fn fs(&mut self) -> &mut fs::NativeFs {
        &mut self.fs
    }

    fn std_streams(&mut self) -> &mut std_streams::NativeStdStreams {
        &mut self.stream
    }
}

/// `Io` implementation using a simulated environment.
///
/// See `env::SimulatedEnv` and `std_streams::SimulatedStdStreams` for more information.
pub struct SimulatedIo {
    env: env::SimulatedEnv,
    fs: fs::TempFs,
    stream: std_streams::SimulatedStdStreams,
}

impl SimulatedIo {
    /// Creates a new `SimulatedIo`.
    pub fn new() -> io::Result<SimulatedIo> {
        Ok(SimulatedIo {
            env: env::SimulatedEnv::new(),
            fs: fs::TempFs::new()?,
            stream: std_streams::SimulatedStdStreams::new(),
        })
    }
}

impl Io for SimulatedIo {
    type E = env::SimulatedEnv;
    type F = fs::TempFs;
    type S = std_streams::SimulatedStdStreams;

    fn env(&mut self) -> &mut env::SimulatedEnv {
        &mut self.env
    }

    fn fs(&mut self) -> &mut fs::TempFs {
        &mut self.fs
    }

    fn std_streams(&mut self) -> &mut std_streams::SimulatedStdStreams {
        &mut self.stream
    }
}
<commit_msg>Add _mut variants to Io methods<commit_after>//! Defines "provider" traits and implementations for different types of I/O operations, enabling
//! dependency injection that's very helpful for testing.
//!
//! A number of different I/O types are supported:
//!
//! * Process environment (variables, working directy etc), via [`Env`](env/trait.Env.html)
//! * Standard streams (stdin, stdout and stderr), via [`StdStreams`](std_streams/trait.StdStreams.html)
//! * Filesystem access, via [`Fs`](fs/trait.Fs.html)
//!
//! In addition to "native" implementations for each trait, "simulated" implementations are also
//! built-in:
//!
//! * [`SimulatedEnv`](env/trait.SimulatedEnv.html) for faking process environment state
//! * [`SimulatedStdStreams`](std_streams/trait.SimulatedStdStreams.html) for faking standard
//!   stream input and inspecting output
//! * [`TempFs`](fs/trait.TempFs.html) for performing filesystem access in a `chroot`-like sandbox
//!   isolated from the rest of the filesystem
//!
//! Each provider trait can be used independently, however there is also the all-encompassing
//! [`Io`](trait.Io.html) which provides access to all of them. If you have a variety of I/O
//! dependencies, it might be easiest to create and pass around a single `&mut Io`.
//!
//! # Examples
//!
//! ```
//! extern crate io_providers;
//!
//! use std::io::Write;
//! use std::path::Path;
//! use io_providers::{Env, Io, NativeIo, SimulatedIo, StdStreams};
//!
//! /// Gets the current working directory and prints it to stdout.
//! fn do_work<I: Io>(io: &mut I) {
//!     let cur_dir = io.env().current_dir().unwrap();
//!     let stdout = io.std_streams().output();
//!     writeln!(stdout, "The current directory is: {}", cur_dir.to_str().unwrap()).unwrap();
//! }
//!
//! fn main() {
//!     // Test `do_work()` using a simulated I/O environment
//!     let mut simulated_io = SimulatedIo::new().unwrap();
//!     simulated_io.env_mut().set_current_dir(Path::new("/foo/bar")).unwrap();
//!     do_work(&mut simulated_io);
//!     assert_eq!(
//!         "The current directory is: /foo/bar\n",
//!         ::std::str::from_utf8(simulated_io.std_streams().read_output()).unwrap());
//!
//!     // Now use a native I/O provided to access the real system
//!     let mut real_io = NativeIo::new();
//!     do_work(&mut real_io);
//! }
//! ```

extern crate tempfile;

use std::io;

pub mod env;
pub mod fs;
pub mod std_streams;

pub use env::{Env, NativeEnv, SimulatedEnv};
pub use fs::{Fs, NativeFs, OpenOptions, TempFs};
pub use std_streams::{NativeStdStreams, SimulatedStdStreams, StdStreams};

/// Provides access to the process environment, filesystem, and standard streams.
///
/// See [`env::Env`](env/trait.Env.html),
/// [`std_streams::StdStreams`](std_streams/trait.StdStreams.html) and
/// [`fs::Fs`](fs/trait.Fs.html) for details.
pub trait Io {
    // The type of the environment provider.
    type E: env::Env;

    // The type of the filesystem provider.
    type F: fs::Fs;

    // The type of the stream provider.
    type S: std_streams::StdStreams;

    /// Gets a reference to the [`env::Env`](env/trait.Env.html) provider.
    fn env(&self) -> &Self::E;

    /// Gets a mutable reference to the [`env::Env`](env/trait.Env.html) provider.
    fn env_mut(&mut self) -> &mut Self::E;

    /// Gets a reference to the [`fs::Fs`](fs/trait.Fs.html) provider.
    fn fs(&self) -> &Self::F;

    /// Gets a mutable reference to the [`fs::Fs`](fs/trait.Fs.html) provider.
    fn fs_mut(&mut self) -> &mut Self::F;

    /// Gets a mutable reference to the [`std_streams::StdStreams`](std_streams/trait.StdStreams.html).
    fn std_streams(&mut self) -> &mut Self::S;
}

/// `Io` implementation using the native system.
///
/// See `env::NativeEnv` and `std_streams::NativeStdStreams` for more information.
#[derive(Default)]
pub struct NativeIo {
    env: env::NativeEnv,
    fs: fs::NativeFs,
    stream: std_streams::NativeStdStreams,
}

impl NativeIo {
    /// Creates a new `LocalIoProvider`.
    pub fn new() -> NativeIo {
        NativeIo {
            env: env::NativeEnv,
            fs: fs::NativeFs,
            stream: std_streams::NativeStdStreams::new(),
        }
    }
}

impl Io for NativeIo {
    type E = env::NativeEnv;
    type F = fs::NativeFs;
    type S = std_streams::NativeStdStreams;

    fn env(&self) -> &env::NativeEnv {
        &self.env
    }

    fn env_mut(&mut self) -> &mut env::NativeEnv {
        &mut self.env
    }

    fn fs(&self) -> &fs::NativeFs {
        &self.fs
    }

    fn fs_mut(&mut self) -> &mut fs::NativeFs {
        &mut self.fs
    }

    fn std_streams(&mut self) -> &mut std_streams::NativeStdStreams {
        &mut self.stream
    }
}

/// `Io` implementation using a simulated environment.
///
/// See `env::SimulatedEnv` and `std_streams::SimulatedStdStreams` for more information.
pub struct SimulatedIo {
    env: env::SimulatedEnv,
    fs: fs::TempFs,
    stream: std_streams::SimulatedStdStreams,
}

impl SimulatedIo {
    /// Creates a new `SimulatedIo`.
    pub fn new() -> io::Result<SimulatedIo> {
        Ok(SimulatedIo {
            env: env::SimulatedEnv::new(),
            fs: fs::TempFs::new()?,
            stream: std_streams::SimulatedStdStreams::new(),
        })
    }
}

impl Io for SimulatedIo {
    type E = env::SimulatedEnv;
    type F = fs::TempFs;
    type S = std_streams::SimulatedStdStreams;

    fn env(&self) -> &env::SimulatedEnv {
        &self.env
    }

    fn env_mut(&mut self) -> &mut env::SimulatedEnv {
        &mut self.env
    }

    fn fs(&self) -> &fs::TempFs {
        &self.fs
    }

    fn fs_mut(&mut self) -> &mut fs::TempFs {
        &mut self.fs
    }

    fn std_streams(&mut self) -> &mut std_streams::SimulatedStdStreams {
        &mut self.stream
    }
}
<|endoftext|>