<commit_before>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};
use std::default::Default;

#[link(name = "kleeRuntest")]
extern {
    fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
    fn klee_set_forking(state: bool);
}

pub unsafe fn any(data: *const raw::c_void, length: usize, name: &str) {
    klee_make_symbolic(data, length as libc::size_t, CString::new(name).unwrap().as_ptr());
}

pub fn set_forking(state: bool) {
    unsafe { klee_set_forking(state); }
}

pub fn some<T: Default>(name: &str) -> T {
    let new_symbol = T::default();
    symbol(&new_symbol, name);
    return new_symbol;
}

pub fn symbol<T>(data: &T, name: &str) {
    unsafe{ any(transmute(data as *const T), size_of::<T>(), name); }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};
use std::default::Default;

#[link(name = "kleeRuntest")]
extern {
    fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
    fn klee_set_forking(state: bool);
}

pub unsafe fn any(data: *const raw::c_void, length: usize, name: &str) {
    klee_make_symbolic(data, length as libc::size_t, CString::new(name).unwrap().as_ptr());
}

pub fn set_forking(state: bool) {
    unsafe { klee_set_forking(state); }
}

pub fn some<T: Default>(name: &str) -> T {
    let new_symbol = T::default();
    symbol(&new_symbol, name);
    return new_symbol;
}

pub fn symbol<T>(data: *const T, name: &str) {
    unsafe{ any(transmute(data), size_of::<T>(), name); }
}
<|endoftext|>


<commit_before>// The following was originally taken and adapated from exa source
// repo: https://github.com/ogham/exa
// commit: b9eb364823d0d4f9085eb220233c704a13d0f611
// license: MIT - Copyright (c) 2014 Benjamin Sago

//! System calls for getting the terminal size.
//!
//! Getting the terminal size is performed using an ioctl command that takes
//! the file handle to the terminal -- which in this case, is stdout -- and
//! populates a structure containing the values.
//!
//! The size is needed when the user wants the output formatted into columns:
//! the default grid view, or the hybrid grid-details view.

extern crate libc;

#[cfg(not(target_os = "windows"))]
use std::mem::zeroed;
#[cfg(not(target_os = "windows"))]
use libc::{STDOUT_FILENO, c_int, c_ulong, c_ushort};

/// The number of rows and columns of a terminal.
#[cfg(not(target_os = "windows"))]
#[repr(C)]
struct Winsize {
    ws_row: c_ushort,
    ws_col: c_ushort,
}

// Unfortunately the actual command is not standardised...
#[cfg(any(target_os = "linux", target_os = "android"))]
static TIOCGWINSZ: c_ulong = 0x5413;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "netbsd",
          target_os = "openbsd"))]
static TIOCGWINSZ: c_ulong = 0x40087468;

extern "C" {
#[cfg(not(target_os = "windows"))]
    pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
}

/// Runs the ioctl command. Returns (0, 0) if output is not to a terminal, or
/// there is an error. (0, 0) is an invalid size to have anyway, which is why
/// it can be used as a nil value.
#[cfg(not(target_os = "windows"))]
unsafe fn get_dimensions() -> Winsize {
    let mut window: Winsize = zeroed();
    let result = ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window);

    if result == -1 {
        zeroed()
    } else {
        window
    }
}

/// Query the current processes's output, returning its width and height as a
/// number of characters. Returns `None` if the output isn't to a terminal.
#[cfg(not(target_os = "windows"))]
pub fn dimensions() -> Option<(usize, usize)> {
    let w = unsafe { get_dimensions() };

    if w.ws_col == 0 || w.ws_row == 0 {
        None
    } else {
        Some((w.ws_col as usize, w.ws_row as usize))
    }
}

#[cfg(target_os = "windows")]
pub fn dimensions() -> Option<(usize, usize)> {
    None
}
<commit_msg>Add support for Solaris/Illumos<commit_after>// The following was originally taken and adapated from exa source
// repo: https://github.com/ogham/exa
// commit: b9eb364823d0d4f9085eb220233c704a13d0f611
// license: MIT - Copyright (c) 2014 Benjamin Sago

//! System calls for getting the terminal size.
//!
//! Getting the terminal size is performed using an ioctl command that takes
//! the file handle to the terminal -- which in this case, is stdout -- and
//! populates a structure containing the values.
//!
//! The size is needed when the user wants the output formatted into columns:
//! the default grid view, or the hybrid grid-details view.

extern crate libc;

#[cfg(not(target_os = "windows"))]
use std::mem::zeroed;
#[cfg(not(target_os = "windows"))]
use libc::{STDOUT_FILENO, c_int, c_ulong, c_ushort};

/// The number of rows and columns of a terminal.
#[cfg(not(target_os = "windows"))]
#[repr(C)]
struct Winsize {
    ws_row: c_ushort,
    ws_col: c_ushort,
}

// Unfortunately the actual command is not standardised...
#[cfg(any(target_os = "linux", target_os = "android"))]
static TIOCGWINSZ: c_ulong = 0x5413;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "bitrig",
          target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "netbsd",
          target_os = "openbsd"))]
static TIOCGWINSZ: c_ulong = 0x40087468;

#[cfg(target_os = "solaris")]
static TIOCGWINSZ: c_ulong = 0x5468;

extern "C" {
#[cfg(not(target_os = "windows"))]
    pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
}

/// Runs the ioctl command. Returns (0, 0) if output is not to a terminal, or
/// there is an error. (0, 0) is an invalid size to have anyway, which is why
/// it can be used as a nil value.
#[cfg(not(target_os = "windows"))]
unsafe fn get_dimensions() -> Winsize {
    let mut window: Winsize = zeroed();
    let result = ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut window);

    if result == -1 {
        zeroed()
    } else {
        window
    }
}

/// Query the current processes's output, returning its width and height as a
/// number of characters. Returns `None` if the output isn't to a terminal.
#[cfg(not(target_os = "windows"))]
pub fn dimensions() -> Option<(usize, usize)> {
    let w = unsafe { get_dimensions() };

    if w.ws_col == 0 || w.ws_row == 0 {
        None
    } else {
        Some((w.ws_col as usize, w.ws_row as usize))
    }
}

#[cfg(target_os = "windows")]
pub fn dimensions() -> Option<(usize, usize)> {
    None
}
<|endoftext|>


<commit_before>#![crate_name = "hashids"]
#![allow(unstable)]

extern crate regex;

use std::num::Float;
use std::collections::HashMap;
use regex::Regex;
use std::num;

const DEFAULT_ALPHABET: &'static str =  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
const DEFAULT_SEPARATORS: &'static str = "cfhistuCFHISTU";
const SEPARTOR_DIV: f32 = 3.5;
const GUARD_DIV: u32 = 12;
const MIN_ALPHABET_LENGTH: usize = 16;

pub enum HashIdsError { InvalidAlphabetLength }

pub struct HashIds {
  salt: String,
  pub alphabet: String,
  separators: String,
  min_hash_length: usize,
  guards: String
}

impl HashIds {
  pub fn new(salt: String, min_hash_length: usize, alphabet: String) -> Result<HashIds, HashIdsError>  {
    let min_length = HashIds::get_min_hash_length(min_hash_length);
    let unique_alphabet = HashIds::get_unique_alphabet(alphabet);

    if unique_alphabet.len() < MIN_ALPHABET_LENGTH {
      return Err(HashIdsError::InvalidAlphabetLength);
    }

    let (t_separators, mut t_alphabet) = HashIds::get_separators(unique_alphabet);
    let mut shuffled_separators = HashIds::hashids_shuffle(t_separators.clone(), salt.clone());

    if HashIds::need_manipulate(shuffled_separators.len(), t_alphabet.len()) == true {
      let mut seps_len =  ((t_alphabet.len() as f32) / SEPARTOR_DIV) as usize;
      if seps_len == 1 {
        seps_len += 1;
      }

      if seps_len > shuffled_separators.len() {
        let diff = seps_len - shuffled_separators.len();
        shuffled_separators.push_str(t_alphabet.slice(0,diff));
        t_alphabet = t_alphabet.slice_from(diff).to_string();
      } else {
        shuffled_separators = shuffled_separators.slice(0, seps_len).to_string();
      }
    }

    let mut shuffled_alphabet = HashIds::hashids_shuffle(t_alphabet.clone(), salt.clone());
    let guard_count = (shuffled_alphabet.len() as f32 / GUARD_DIV as f32).ceil() as usize;

    let mut t_guards;

    if shuffled_alphabet.len() < 3 {
      t_guards = shuffled_separators.slice(0, guard_count).to_string();
      shuffled_separators = shuffled_separators.slice_from(guard_count).to_string();
    } else {
      t_guards = shuffled_alphabet.slice(0, guard_count).to_string();
      shuffled_alphabet = shuffled_alphabet.slice_from(guard_count).to_string();
    }

    Ok(HashIds {
      salt: salt,
      min_hash_length: min_length,
      guards: t_guards,
      separators: shuffled_separators,
      alphabet: shuffled_alphabet
    })
  }

  pub fn new_with_salt_and_min_length(salt: String, min_hash_length: usize) -> Result<HashIds, HashIdsError> {
    HashIds::new(salt, min_hash_length, DEFAULT_ALPHABET.to_string())
  }

  pub fn new_with_salt(salt: String) -> Result<HashIds, HashIdsError> {
    HashIds::new_with_salt_and_min_length(salt, 0)
  }

  fn need_manipulate(slen: usize, alen: usize) -> bool {
    if slen <= 0 && (((alen/slen) as f32)> SEPARTOR_DIV) {
      return true;
    }

    false
  }

  fn get_min_hash_length(length: usize) -> usize {
    if length > 0 {
      return length;
    } else {
      return 0;
    }
  }

  fn get_separators(alphabet: String) -> (String, String) {
    HashIds::get_non_duplicated_string(DEFAULT_SEPARATORS.to_string(), alphabet)
  }

  fn hashids_shuffle(alphabet: String, salt: String) -> String {
    if salt.len() <= 0 {
      return alphabet;
    }

    let salt_len = salt.len();
    let arr = salt.as_bytes();
    let len = alphabet.len();
    let mut bytes = alphabet.into_bytes();
    let mut shuffle = bytes.as_mut_slice();

    let mut i: usize = len-1;
    let mut v: usize = 0;
    let mut p: usize = 0;

    while i > 0 {
      v %= salt_len;
      let t = arr[v] as usize;
      p += t;
      let j = (t + v + p) % i;

      shuffle.swap(i,j);

      i=i-1;
      v=v+1;
    }

    let mut shuffled_alphabet = String::with_capacity(len);
    for i in (0..len) {
      shuffled_alphabet.push(shuffle[i] as char);
    }

    shuffled_alphabet
  }

  fn get_non_duplicated_string(separators: String, alphabet: String) -> (String, String) {
    let mut check_separator_map = HashMap::new();
    let mut check_alphabet_map = HashMap::new();

    let mut modified_separators = String::new();
    let mut modified_alphabet = String::new();

    for c in separators.chars() {
      check_separator_map.insert(c, 1);
    }

    for c in alphabet.chars() {
      check_alphabet_map.insert(c, 1);
    }

    for c in separators.chars() {
      if check_alphabet_map.contains_key(&c) {
        modified_separators.push(c);
      }
    }

    for c in alphabet.chars() {
      if !check_separator_map.contains_key(&c) {
        modified_alphabet.push(c);
      }
    }

    (modified_separators, modified_alphabet)
  }

  fn get_unique_alphabet(alphabet: String) -> String {
    let mut unique_alphabet: String = String::new();
    let mut check_map = HashMap::new();

    for c in alphabet.chars() {
      if !check_map.contains_key(&c) {
        unique_alphabet.push(c);
        check_map.insert(c, 1);
      }
    }

    unique_alphabet
  }

  pub fn encode_hex(&self, hex: String) -> String {
    let regex1 = Regex::new(r"^[0-9a-fA-F]+$").unwrap();
    if regex1.is_match(hex.as_slice()) == false {
      return String::new();
    }

    let mut numbers: Vec<i64> = Vec::new();
    let regex2 = Regex::new(r"[\w\W]{1,12}").unwrap();
    for matcher in regex2.find_iter(hex.as_slice()) {
      let mut num = String::new();
      num.push('1');
      num.push_str(hex.slice(matcher.0, matcher.1));
      let v: i64 = num::from_str_radix(num.as_slice(), 16).unwrap();
      numbers.push(v);
    }

    self.encode(&numbers)
  }

  pub fn decode_hex(&self, hash: String) -> String {
    let mut ret = String::new();
    let numbers = self.decode(hash);
    for number in numbers.iter() {
      let r = format!("{:x}", number);
      ret.push_str(r.slice_from(1));
    }

    ret
  }

  pub fn encode(&self, numbers: &Vec<i64>) -> String {
    if numbers.len() == 0 {
      return "".to_string();
    }

    for number in numbers.iter() {
      if *number > 9007199254740992 {
        return "".to_string();
      }
    }

    self._encode(numbers)
  }

  pub fn decode(&self, hash: String) -> Vec<i64> {
    let ret : Vec<i64> = Vec::new();
    if hash.len() == 0 {
      return ret;
    }

    self._decode(hash)
  }

  fn _decode(&self, hash: String) -> Vec<i64> {
    use regex::Regex;

    let mut regexp = String::new();
    regexp.push('[');
    regexp.push_str(self.guards.as_slice());
    regexp.push(']');

    let re = Regex::new(regexp.as_slice()).unwrap();
    let t_hash = re.replace_all(hash.as_slice(), " ");

    let mut split: Vec<&str> = t_hash.as_slice().split_str(" ").collect();
    let mut i = 0;

    let len = split.len();
    if len == 3 || len == 2 {
      i = 1;
    }
    let mut hash_breakdown = split[i].to_string();

    let lottery = hash_breakdown.slice(0,1).to_string();

    hash_breakdown = hash_breakdown.slice_from(1).to_string();

    let mut regexp2 = String::new();
    regexp2.push('[');
    regexp2.push_str(self.separators.as_slice());
    regexp2.push(']');

    let re2 = Regex::new(regexp2.as_slice()).unwrap();
    hash_breakdown  = re2.replace_all(hash_breakdown.as_slice(), " ");

    split = hash_breakdown.as_slice().split_str(" ").collect();

    let mut alphabet = self.alphabet.clone();

    let mut ret: Vec<i64> = Vec::new();

    for s in split.iter() {
      let sub_hash = s.to_string();
      let mut buffer = String::new();
      buffer.push_str(lottery.as_slice());
      buffer.push_str(self.salt.as_slice());
      buffer.push_str(alphabet.clone().as_slice());

      let alpha_len = alphabet.len();
      alphabet = HashIds::hashids_shuffle(alphabet, buffer.slice(0, alpha_len).to_string());
      ret.push(HashIds::unhash(sub_hash, alphabet.clone()));
    }

    let check_hash = self._encode(&ret);
    if check_hash != hash {
      return Vec::new();
    }

    ret
  }

  fn index_of(input :&[u8], v: u8) -> i64 {
    let mut i = 0;
    for s in input.iter() {
      if *s == v {
        return i;
      }

      i += 1;
    }

    return -1;
  }

  fn unhash(input: String, alphabet: String) -> i64 {
    use std::num::Int;

    let mut number: i64 = 0;
    let input_slice = input.as_bytes();
    let alpha_slice = alphabet.as_bytes();
    let len = input.len();
    let alpha_len = alphabet.len() as i64;
    let mut i: usize = 0;
    loop {
      if i >= len {
        break;
      }

      let v = input_slice[i] as usize;
      let pos = HashIds::index_of(alpha_slice, v as u8);
      let pow_size = (len - i - 1) as usize;
      number += (pos * alpha_len.pow(pow_size)) as i64;
      i += 1;
    }

    number
  }

  fn hash(input: i64, alphabet: String) -> String {
    let mut t_in = input;
    let mut hash = "".to_string();
    let len = alphabet.len() as i64;

    loop {
      let idx = (t_in % len) as usize;
      let mut t = alphabet.slice(idx, idx+1).to_string();
      t.push_str(hash.as_slice());
      hash = t;
      t_in /= len;

      if t_in <= 0 {
        break;
      }
    }

    hash
  }

  fn _encode(&self, numbers: &Vec<i64>) -> String {
    let mut number_hash_int  = 0;
    let mut count = 100;
    for number in numbers.iter() {
      number_hash_int += *number % count;
      count += 1;
    }

    let idx = (number_hash_int % (self.alphabet.len() as i64)) as usize;
    let ret = self.alphabet.slice(idx, idx+1).to_string();
    let mut ret_str = ret.clone();

    let mut t_alphabet = self.alphabet.clone();
    let mut i = 0;
    let len = self.separators.len() as i64;
    let last_len = count - 100;
    for number in numbers.iter() {
      let mut buffer = ret.clone();
      buffer.push_str(self.salt.as_slice());
      buffer.push_str(t_alphabet.as_slice());
      t_alphabet = HashIds::hashids_shuffle(t_alphabet.clone(), buffer.slice(0, t_alphabet.len()).to_string());
      let last = HashIds::hash(*number, t_alphabet.clone());

      ret_str.push_str(last.as_slice());

      if (i + 1) < last_len {
        let mut v = *number % (last.as_bytes()[0] as i64 + i);
        v = v % len;
        ret_str.push(self.separators.as_bytes()[v as usize] as char);
      }
      i += 1;
    }

    if ret_str.len() < self.min_hash_length {
      let guard_idx = (number_hash_int + ret_str.clone().into_bytes()[0] as i64) as usize % self.guards.len();
      let guard = self.guards.slice(guard_idx, guard_idx+1).to_string();
      let mut t = guard.clone();
      t.push_str(ret_str.as_slice());
      ret_str = t;

      if ret_str.len() < self.min_hash_length {
        let guard_idx = (number_hash_int + ret_str.clone().into_bytes()[2] as i64) as usize % self.guards.len();
        let guard = self.guards.slice(guard_idx, guard_idx+1);
        ret_str.push_str(guard);
      }
    }

    let half_len = t_alphabet.len() / 2;
    while ret_str.len() < self.min_hash_length {
      t_alphabet = HashIds::hashids_shuffle(t_alphabet.clone(), t_alphabet.clone());
      let mut t_ret = "".to_string();
      t_ret.push_str(t_alphabet.slice_from(half_len));
      t_ret.push_str(ret_str.as_slice());
      t_ret.push_str(t_alphabet.slice(0, half_len));
      ret_str = t_ret;

      let excess = ret_str.len() as i64 - self.min_hash_length as i64;
      if excess > 0 {
        let start_pos = (excess as i64 / 2) as usize;
        ret_str = ret_str.slice(start_pos, start_pos + self.min_hash_length).to_string();
      }
    }

    ret_str
  }
}
<commit_msg>Fix compile errors and warnings with latest rust compiler<commit_after>#![crate_name = "hashids"]

extern crate regex;

use std::collections::HashMap;
use regex::Regex;

const DEFAULT_ALPHABET: &'static str =  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
const DEFAULT_SEPARATORS: &'static str = "cfhistuCFHISTU";
const SEPARTOR_DIV: f32 = 3.5;
const GUARD_DIV: u32 = 12;
const MIN_ALPHABET_LENGTH: usize = 16;

pub enum HashIdsError { InvalidAlphabetLength }

pub struct HashIds {
  salt: String,
  pub alphabet: String,
  separators: String,
  min_hash_length: usize,
  guards: String
}

impl HashIds {
  pub fn new(salt: String, min_hash_length: usize, alphabet: String) -> Result<HashIds, HashIdsError>  {
    let min_length = HashIds::get_min_hash_length(min_hash_length);
    let unique_alphabet = HashIds::get_unique_alphabet(alphabet);

    if unique_alphabet.len() < MIN_ALPHABET_LENGTH {
      return Err(HashIdsError::InvalidAlphabetLength);
    }

    let (t_separators, mut t_alphabet) = HashIds::get_separators(unique_alphabet);
    let mut shuffled_separators = HashIds::hashids_shuffle(t_separators.clone(), salt.clone());

    if HashIds::need_manipulate(shuffled_separators.len(), t_alphabet.len()) == true {
      let mut seps_len =  ((t_alphabet.len() as f32) / SEPARTOR_DIV) as usize;
      if seps_len == 1 {
        seps_len += 1;
      }

      if seps_len > shuffled_separators.len() {
        let diff = seps_len - shuffled_separators.len();

        shuffled_separators.push_str(&t_alphabet[..diff]);
        t_alphabet = t_alphabet[diff..].to_string();
      } else {
        shuffled_separators = shuffled_separators[..seps_len].to_string();
      }
    }

    let mut shuffled_alphabet = HashIds::hashids_shuffle(t_alphabet.clone(), salt.clone());
    let guard_count = (shuffled_alphabet.len() as f32 / GUARD_DIV as f32).ceil() as usize;

    let t_guards;

    if shuffled_alphabet.len() < 3 {
      t_guards = shuffled_separators[..guard_count].to_string();
      shuffled_separators = shuffled_separators[guard_count..].to_string();
    } else {
      t_guards = shuffled_alphabet[..guard_count].to_string();
      shuffled_alphabet = shuffled_alphabet[guard_count..].to_string();
    }

    Ok(HashIds {
      salt: salt,
      min_hash_length: min_length,
      guards: t_guards,
      separators: shuffled_separators,
      alphabet: shuffled_alphabet
    })
  }

  pub fn new_with_salt_and_min_length(salt: String, min_hash_length: usize) -> Result<HashIds, HashIdsError> {
    HashIds::new(salt, min_hash_length, DEFAULT_ALPHABET.to_string())
  }

  pub fn new_with_salt(salt: String) -> Result<HashIds, HashIdsError> {
    HashIds::new_with_salt_and_min_length(salt, 0)
  }

  fn need_manipulate(slen: usize, alen: usize) -> bool {
    if slen <= 0 && (((alen/slen) as f32)> SEPARTOR_DIV) {
      return true;
    }

    false
  }

  fn get_min_hash_length(length: usize) -> usize {
    if length > 0 {
      return length;
    } else {
      return 0;
    }
  }

  fn get_separators(alphabet: String) -> (String, String) {
    HashIds::get_non_duplicated_string(DEFAULT_SEPARATORS.to_string(), alphabet)
  }

  fn hashids_shuffle(alphabet: String, salt: String) -> String {
    if salt.len() <= 0 {
      return alphabet;
    }

    let salt_len = salt.len();
    let arr = salt.as_bytes();
    let len = alphabet.len();
    let mut bytes = alphabet.into_bytes();
    let mut shuffle = &mut bytes[..];

    let mut i: usize = len-1;
    let mut v: usize = 0;
    let mut p: usize = 0;

    while i > 0 {
      v %= salt_len;
      let t = arr[v] as usize;
      p += t;
      let j = (t + v + p) % i;

      shuffle.swap(i,j);

      i=i-1;
      v=v+1;
    }

    let mut shuffled_alphabet = String::with_capacity(len);
    for i in 0..len {
      shuffled_alphabet.push(shuffle[i] as char);
    }

    shuffled_alphabet
  }

  fn get_non_duplicated_string(separators: String, alphabet: String) -> (String, String) {
    let mut check_separator_map = HashMap::new();
    let mut check_alphabet_map = HashMap::new();

    let mut modified_separators = String::new();
    let mut modified_alphabet = String::new();

    for c in separators.chars() {
      check_separator_map.insert(c, 1);
    }

    for c in alphabet.chars() {
      check_alphabet_map.insert(c, 1);
    }

    for c in separators.chars() {
      if check_alphabet_map.contains_key(&c) {
        modified_separators.push(c);
      }
    }

    for c in alphabet.chars() {
      if !check_separator_map.contains_key(&c) {
        modified_alphabet.push(c);
      }
    }

    (modified_separators, modified_alphabet)
  }

  fn get_unique_alphabet(alphabet: String) -> String {
    let mut unique_alphabet: String = String::new();
    let mut check_map = HashMap::new();

    for c in alphabet.chars() {
      if !check_map.contains_key(&c) {
        unique_alphabet.push(c);
        check_map.insert(c, 1);
      }
    }

    unique_alphabet
  }

  pub fn encode_hex(&self, hex: String) -> String {
    let regex1 = Regex::new(r"^[0-9a-fA-F]+$").unwrap();
    if regex1.is_match(&hex.to_string()) == false {
      return String::new();
    }

    let mut numbers: Vec<i64> = Vec::new();
    let regex2 = Regex::new(r"[\w\W]{1,12}").unwrap();
    for matcher in regex2.find_iter(&hex.to_string()) {
      let mut num = String::new();
      num.push('1');
      num.push_str(&hex[matcher.0..matcher.1]);
      let v: i64 = i64::from_str_radix(&num.to_string(), 16).unwrap();
      numbers.push(v);
    }

    self.encode(&numbers)
  }

  pub fn decode_hex(&self, hash: String) -> String {
    let mut ret = String::new();
    let numbers = self.decode(hash);
    for number in numbers.iter() {
      let r = format!("{:x}", number);
      ret.push_str(&r[1..]);
    }

    ret
  }

  pub fn encode(&self, numbers: &Vec<i64>) -> String {
    if numbers.len() == 0 {
      return "".to_string();
    }

    for number in numbers.iter() {
      if *number > 9007199254740992 {
        return "".to_string();
      }
    }

    self._encode(numbers)
  }

  pub fn decode(&self, hash: String) -> Vec<i64> {
    let ret : Vec<i64> = Vec::new();
    if hash.len() == 0 {
      return ret;
    }

    self._decode(hash)
  }

  fn _decode(&self, hash: String) -> Vec<i64> {
    use regex::Regex;

    let mut regexp = String::new();
    regexp.push('[');
    regexp.push_str(&self.guards[..]);
    regexp.push(']');

    let re = Regex::new(&regexp[..]).unwrap();
    let t_hash = re.replace_all(&hash[..], " ");

    let split1: Vec<&str> = t_hash[..].split_whitespace().collect();
    let mut i = 0;

    let len = split1.len();
    if len == 3 || len == 2 {
      i = 1;
    }
    let mut hash_breakdown = split1[i].to_string();

    let lottery = hash_breakdown[0..1].to_string();
    hash_breakdown = hash_breakdown[1..].to_string();

    let mut regexp2 = String::new();
    regexp2.push('[');
    regexp2.push_str(&self.separators[..]);
    regexp2.push(']');

    let re2 = Regex::new(&regexp2[..]).unwrap();
    hash_breakdown = re2.replace_all(&hash_breakdown[..], " ");

    let split2: Vec<&str> = hash_breakdown[..].split_whitespace().collect();

    let mut alphabet = self.alphabet.clone();

    let mut ret: Vec<i64> = Vec::new();

    for s in split2 {
      let sub_hash = s.to_string();
      let mut buffer = String::new();
      buffer.push_str(&lottery[..]);
      buffer.push_str(&self.salt[..]);
      buffer.push_str(&alphabet.clone()[..]);

      let alpha_len = alphabet.len();
      alphabet = HashIds::hashids_shuffle(alphabet, buffer[0..alpha_len].to_string());
      ret.push(HashIds::unhash(sub_hash, alphabet.clone()));
    }

    let check_hash = self._encode(&ret);
    if check_hash != hash {
      return Vec::new();
    }

    ret
  }

  fn index_of(input :&[u8], v: u8) -> i64 {
    let mut i = 0;
    for s in input.iter() {
      if *s == v {
        return i;
      }

      i += 1;
    }

    return -1;
  }

  fn unhash(input: String, alphabet: String) -> i64 {
    let mut number: i64 = 0;
    let input_slice = input.as_bytes();
    let alpha_slice = alphabet.as_bytes();
    let len = input.len();
    let alpha_len = alphabet.len() as i64;
    let mut i: usize = 0;
    loop {
      if i >= len {
        break;
      }

      let v = input_slice[i] as usize;
      let pos = HashIds::index_of(alpha_slice, v as u8);
      let pow_size = (len - i - 1) as u32;
      number += (pos * alpha_len.pow(pow_size)) as i64;
      i += 1;
    }

    number
  }

  fn hash(input: i64, alphabet: String) -> String {
    let mut t_in = input;
    let mut hash = "".to_string();
    let len = alphabet.len() as i64;

    loop {
      let idx = (t_in % len) as usize;
      let mut t = alphabet[idx..idx+1].to_string();
      t.push_str(&hash[..]);
      hash = t;
      t_in /= len;

      if t_in <= 0 {
        break;
      }
    }

    hash
  }

  fn _encode(&self, numbers: &Vec<i64>) -> String {
    let mut number_hash_int  = 0;
    let mut count = 100;
    for number in numbers.iter() {
      number_hash_int += *number % count;
      count += 1;
    }

    let idx = (number_hash_int % (self.alphabet.len() as i64)) as usize;
    let ret = self.alphabet[idx..idx+1].to_string();
    let mut ret_str = ret.clone();

    let mut t_alphabet = self.alphabet.clone();
    let mut i = 0;
    let len = self.separators.len() as i64;
    let last_len = count - 100;
    for number in numbers.iter() {
      let mut buffer = ret.clone();
      buffer.push_str(&self.salt[..]);
      buffer.push_str(&t_alphabet[..]);
      t_alphabet = HashIds::hashids_shuffle(t_alphabet.clone(), buffer[0..t_alphabet.len()].to_string());
      let last = HashIds::hash(*number, t_alphabet.clone());

      ret_str.push_str(&last[..]);

      if (i + 1) < last_len {
        let mut v = *number % (last.as_bytes()[0] as i64 + i);
        v = v % len;
        ret_str.push(self.separators.as_bytes()[v as usize] as char);
      }
      i += 1;
    }

    if ret_str.len() < self.min_hash_length {
      let guard_idx = (number_hash_int + ret_str.clone().into_bytes()[0] as i64) as usize % self.guards.len();
      let guard = self.guards[guard_idx..guard_idx+1].to_string();
      let mut t = guard.clone();
      t.push_str(&ret_str[..]);
      ret_str = t;

      if ret_str.len() < self.min_hash_length {
        let guard_idx = (number_hash_int + ret_str.clone().into_bytes()[2] as i64) as usize % self.guards.len();
        ret_str.push_str(&self.guards[guard_idx..guard_idx+1]);
      }
    }

    let half_len = t_alphabet.len() / 2;
    while ret_str.len() < self.min_hash_length {
      t_alphabet = HashIds::hashids_shuffle(t_alphabet.clone(), t_alphabet.clone());
      let mut t_ret = "".to_string();
      t_ret.push_str(&t_alphabet[half_len..]);
      t_ret.push_str(&ret_str[..]);
      t_ret.push_str(&t_alphabet[0..half_len]);
      ret_str = t_ret;

      let excess = ret_str.len() as i64 - self.min_hash_length as i64;
      if excess > 0 {
        let start_pos = (excess as i64 / 2) as usize;
        ret_str = ret_str[start_pos..start_pos + self.min_hash_length].to_string();
      }
    }

    ret_str
  }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use byteorder::{WriteBytesExt, BigEndian};
use std::io::{Result, Read, Write, Seek, SeekFrom};
use std::fs::{File};

struct Header {
    magic: [u8; 4],
    orig_length: u32, // for some reasons the decrucnher asm checks if the first byte is a 0
                    // maybe it is a real u24?
    offset: u32, // unpacked_size-packed_data+1
}

enum Chunk {
    Unique {
        data: Vec<u8>,
    },
    Repeated {
        byte: u8,
        num: usize,
    },
}

fn write_chunk<T: WriteBytesExt>(chunk: Chunk, target: &mut T) -> Result<usize> {
    let written = match chunk {
        Chunk::Unique { data } => {
            // argh...negating without the compiler being a dingens
            try!(target.write_i8((data.len() as i32 * -1) as i8));
            for c in data.iter() {
                try!(target.write_u8(*c));
            }
            1 + data.len()
        },
        Chunk::Repeated { byte, num } => {
            try!(target.write_u8(num as u8 - 1));
            try!(target.write_u8(byte));
            2
        }
    };
    Ok(written)
}

fn write_header<T: WriteBytesExt>(length: u64, mut target: T) -> Result<usize> {
    let header = Header { magic: *b"RPck", orig_length: length as u32, offset: 0};
    for c in header.magic.iter() {
        try!(target.write_u8(*c));
    }

    try!(target.write_u32::<BigEndian>(header.orig_length));
    try!(target.write_u32::<BigEndian>(header.offset));
    Ok(1)
}

pub fn archive<T: Read>(rfile: T, size: u64, mut wfile: File) -> Result<()> {
    try!(write_header(size, &wfile));
    let packed_size = try!(write_data(rfile, &mut wfile));
    try!(wfile.seek(SeekFrom::Start(8)));
    try!(wfile.write_u32::<BigEndian>((size - packed_size as u64 + 1) as u32));
    Ok(())
}

fn write_data<TR: Read, TW: Write>(readable: TR, mut writeable: &mut TW) -> Result<usize> {
    let mut written:usize = 0;
    let mut current: Option<Chunk> = None;
    for byte in readable.bytes() {
        // this is all looking super fuzzy :S n00bish code is n00bish :D
        let b = byte.unwrap();
        current = match current {
            None => Some(Chunk::Unique { data: [b].to_vec()}),
            Some(current) => {
                let (chunk, len) = match current {
                    Chunk::Unique { mut data } => {
                        let len = data.len();
                        if len > 1 && data.ends_with(&[b, b]) {
                            if len > 2 {
                                data.split_off(len - 2);
                                written = written + try!(write_chunk(Chunk::Unique {
                                    data: data,
                                }, &mut writeable));
                            }
                            (Chunk::Repeated {
                                byte: b,
                                num: 3,
                            }, 3)
                        } else {
                            data.push(b);
                            (Chunk::Unique {
                                data: data,
                            }, len + 1)
                        }
                    },
                    Chunk::Repeated { byte, mut num } => {
                        if b == byte {
                            num += 1;
                            (Chunk::Repeated {
                                byte: b,
                                num: num,
                            }, num)
                        } else {
                            written = written + try!(write_chunk(current, &mut writeable));
                            (Chunk::Unique { data: [b].to_vec()}, 1)
                        }
                    }
                };

                if len == 128 {
                    written = written + try!(write_chunk(chunk, &mut writeable));
                    None
                } else {
                    Some(chunk)
                }
            }
        };
    }
    if current.is_some() {
        written = written + try!(write_chunk(current.unwrap(), &mut writeable));
    }
    Ok(written)
}

#[cfg(test)]
mod test;<commit_msg>Add a few comment<commit_after>extern crate byteorder;

use byteorder::{WriteBytesExt, BigEndian};
use std::io::{Result, Read, Write, Seek, SeekFrom};
use std::fs::{File};

struct Header {
    magic: [u8; 4],
    orig_length: u32, // for some reasons the decrucnher asm checks if the first byte is a 0
                    // maybe it is a real u24?
    offset: u32, // unpacked_size-packed_data+1
}

enum Chunk {
    Unique {
        data: Vec<u8>,
    },
    Repeated {
        byte: u8,
        num: usize,
    },
}

fn write_chunk<T: WriteBytesExt>(chunk: Chunk, target: &mut T) -> Result<usize> {
    let written = match chunk {
        Chunk::Unique { data } => {
            // argh...negating without the compiler being a dingens
            try!(target.write_i8((data.len() as i32 * -1) as i8));
            for c in data.iter() {
                try!(target.write_u8(*c));
            }
            1 + data.len()
        },
        Chunk::Repeated { byte, num } => {
            try!(target.write_u8(num as u8 - 1));
            try!(target.write_u8(byte));
            2
        }
    };
    Ok(written)
}

fn write_header<T: WriteBytesExt>(length: u64, mut target: T) -> Result<usize> {
    let header = Header { magic: *b"RPck", orig_length: length as u32, offset: 0};
    for c in header.magic.iter() {
        try!(target.write_u8(*c));
    }

    try!(target.write_u32::<BigEndian>(header.orig_length));
    try!(target.write_u32::<BigEndian>(header.offset));
    Ok(1)
}

pub fn archive<T: Read>(rfile: T, size: u64, mut wfile: File) -> Result<()> {
    try!(write_header(size, &wfile));
    let packed_size = try!(write_data(rfile, &mut wfile));
    try!(wfile.seek(SeekFrom::Start(8)));
    try!(wfile.write_u32::<BigEndian>((size - packed_size as u64 + 1) as u32));
    Ok(())
}

fn write_data<TR: Read, TW: Write>(readable: TR, mut writeable: &mut TW) -> Result<usize> {
    let mut written:usize = 0;
    let mut current: Option<Chunk> = None;
    for byte in readable.bytes() {
        // this is all looking super fuzzy :S n00bish code is n00bish :D
        let b = byte.unwrap();
        current = match current {
            // in the beginning everything is unique
            None => Some(Chunk::Unique { data: [b].to_vec()}),
            Some(current) => {
                let (chunk, len) = match current {
                    Chunk::Unique { mut data } => {
                        let len = data.len();
                        // here we check if we our most recent unique byte is repeating
                        // and eventually convert it to a repeated structure
                        // and write the unique bytes captured so far to disk (or whatever writable is)
                        if len > 1 && data.ends_with(&[b, b]) {
                            if len > 2 {
                                data.split_off(len - 2);
                                written = written + try!(write_chunk(Chunk::Unique {
                                    data: data,
                                }, &mut writeable));
                            }
                            (Chunk::Repeated {
                                byte: b,
                                num: 3,
                            }, 3)
                        } else {
                            data.push(b);
                            (Chunk::Unique {
                                data: data,
                            }, len + 1)
                        }
                    },
                    // capture until the byte changes...write the repeated chunk and create
                    // a new unique chunk
                    Chunk::Repeated { byte, mut num } => {
                        if b == byte {
                            num += 1;
                            (Chunk::Repeated {
                                byte: b,
                                num: num,
                            }, num)
                        } else {
                            written = written + try!(write_chunk(current, &mut writeable));
                            (Chunk::Unique { data: [b].to_vec()}, 1)
                        }
                    }
                };

                // due to the format this is the maximum size a chunk can have
                if len == 128 {
                    written = written + try!(write_chunk(chunk, &mut writeable));
                    None
                } else {
                    Some(chunk)
                }
            }
        };
    }
    if current.is_some() {
        written = written + try!(write_chunk(current.unwrap(), &mut writeable));
    }
    Ok(written)
}

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


<commit_before>extern crate libc;
use libc::c_char;

#[macro_use]
extern crate bitflags;

extern crate libfreenect_sys;
use libfreenect_sys::{
    freenect_context,
    freenect_init,
    freenect_shutdown,
    freenect_loglevel,
    freenect_set_log_level,
    freenect_process_events,
    freenect_num_devices,
    freenect_device_flags,
    freenect_device_attributes,
    freenect_list_device_attributes,
    freenect_free_device_attributes,
    freenect_supported_subdevices,
    freenect_device,
    freenect_open_device,
    freenect_open_device_by_camera_serial,
    freenect_close_device,
};

use std::ptr;
use std::ffi;
use std::sync::Arc;

enum FreenectError {
    LibraryReturnCode(i32),
    NullPtr,
}

pub type FreenectResult<T> = Result<T, FreenectError>;

pub enum LogLevel {
	Fatal,         // Log for crashing/non-recoverable errors
	Error,         // Log for major errors
	Warning,       // Log for warning messages
	Notice,        // Log for important messages
	Info,          // Log for normal messages
	Debug,         // Log for useful development messages
	Spew,          // Log for slightly less useful messages
	Flood,         // Log EVERYTHING. May slow performance.
}

impl LogLevel {
    fn to_lowlevel(self) -> freenect_loglevel {
        match self {
            LogLevel::Fatal => freenect_loglevel::FREENECT_LOG_FATAL,
            _ => freenect_loglevel::FREENECT_LOG_FATAL,
        }
    }

    fn from_lowlevel(lvl: freenect_loglevel) -> LogLevel {
        match lvl {
            freenect_loglevel::FREENECT_LOG_FATAL => LogLevel::Fatal,
            _ => LogLevel::Fatal
        }
    }
}

bitflags! {
    flags DeviceFlags: u32 {
        const DEVICE_MOTOR  = freenect_device_flags::FREENECT_DEVICE_MOTOR  as u32,
        const DEVICE_CAMERA = freenect_device_flags::FREENECT_DEVICE_CAMERA as u32,
        const DEVICE_AUDIO  = freenect_device_flags::FREENECT_DEVICE_AUDIO  as u32,
    }
}

pub struct DeviceAttributes {
    camera_serial: String,
}

struct InnerContext {
    ctx: *mut freenect_context,
}

impl InnerContext {
    fn new() -> FreenectResult<InnerContext> {
        let mut ctx = InnerContext{ctx: ptr::null_mut()};

        match unsafe { freenect_init(&mut ctx.ctx, ptr::null_mut()) } {
            0 => {
                if ctx.ctx != ptr::null_mut() {
                    Ok(ctx)
                } else {
                    Err(FreenectError::NullPtr)
                }
            },
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }
}

impl Drop for InnerContext {
    fn drop(&mut self) {
        let ret = unsafe { freenect_shutdown(self.ctx) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub struct Context {
    ctx: Arc<InnerContext>,
}

impl Context {
    pub fn new() -> FreenectResult<Context> {
        let inner_ctx = try!(InnerContext::new());

        Ok(Context{ctx: Arc::new(inner_ctx)})
    }

    pub fn set_log_level(&mut self, level: LogLevel) {
        unsafe { freenect_set_log_level(self.ctx.ctx, level.to_lowlevel()); }
    }

    pub fn set_log_callback(&mut self) {

    }

    // Convert C callback parameters to rustified versions, then call user callback
    fn callback_trampoline(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char) {
        let level = LogLevel::from_lowlevel(level);
        let msg = unsafe { ffi::CStr::from_ptr(msg) };
    }

    pub fn process_events(&mut self) -> FreenectResult<()> {
        match unsafe { freenect_process_events(self.ctx.ctx) } {
            0 => Ok(()),
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }

    pub fn num_devices(&mut self) -> FreenectResult<u32> {
        let ret = unsafe { freenect_num_devices(self.ctx.ctx) };
        if ret < 0 {
            Err(FreenectError::LibraryReturnCode(ret))
        } else {
            Ok(ret as u32)
        }
    }

    pub fn list_device_attributes(&mut self) -> FreenectResult<Vec<DeviceAttributes>> {
        let mut lowlevel_list: *mut freenect_device_attributes = ptr::null_mut();

        let ret = unsafe { freenect_list_device_attributes(self.ctx.ctx, &mut lowlevel_list) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret));
        }

        let mut device_list: Vec<DeviceAttributes> = Vec::new();

        let mut curr_item = lowlevel_list;
        while curr_item != ptr::null_mut() {
            let serial_cstr = unsafe { ffi::CStr::from_ptr((*curr_item).camera_serial) };
            let serial = String::from_utf8_lossy(serial_cstr.to_bytes()).to_string();

            device_list.push(DeviceAttributes{camera_serial: serial});
            unsafe { curr_item = (*curr_item).next };
        }

        unsafe { freenect_free_device_attributes(self.ctx.ctx, lowlevel_list) };

        Ok(device_list)
    }

    pub fn open_device(&mut self, index: u32) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        let ret = unsafe { freenect_open_device(self.ctx.ctx, &mut dev, index as i32) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device{ctx: self.ctx.clone(), dev: dev});
    }

    pub fn open_device_by_camera_serial(&mut self, serial: &str) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        let serial_cstring = ffi::CString::new(serial).unwrap();

        let ret = unsafe { freenect_open_device_by_camera_serial(self.ctx.ctx, &mut dev, serial_cstring.as_ptr()) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device::from_raw_device(self.ctx.clone(), dev));
    }
}

pub struct Device {
    ctx: Arc<InnerContext>, // Handle to prevent underlying context being free'd before device
    dev: *mut freenect_device,
}

impl Device {
    fn from_raw_device(ctx: Arc<InnerContext>, dev: *mut freenect_device) -> Device {
        Device{ctx: ctx, dev: dev}
    }
}

impl Drop for Device {
    fn drop(&mut self) {
        let ret = unsafe { freenect_close_device(self.dev) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub fn supported_subdevices() -> DeviceFlags {
    let bits = unsafe { freenect_supported_subdevices() as u32 };
    return DeviceFlags::from_bits(bits).unwrap();
}
<commit_msg>Breakout subdevices into separate structs to allow type-based representation of subdevice presence<commit_after>extern crate libc;
use libc::c_char;

#[macro_use]
extern crate bitflags;

extern crate libfreenect_sys;
use libfreenect_sys::{
    freenect_context,
    freenect_init,
    freenect_shutdown,
    freenect_loglevel,
    freenect_set_log_level,
    freenect_process_events,
    freenect_num_devices,
    freenect_device_flags,
    freenect_device_attributes,
    freenect_list_device_attributes,
    freenect_free_device_attributes,
    freenect_supported_subdevices,
    freenect_select_subdevices,
    freenect_enabled_subdevices,
    freenect_device,
    freenect_open_device,
    freenect_open_device_by_camera_serial,
    freenect_close_device,
};

use std::ptr;
use std::ffi;
use std::sync::Arc;

enum FreenectError {
    LibraryReturnCode(i32),
    NullPtr,
}

pub type FreenectResult<T> = Result<T, FreenectError>;

pub enum LogLevel {
	Fatal,         // Log for crashing/non-recoverable errors
	Error,         // Log for major errors
	Warning,       // Log for warning messages
	Notice,        // Log for important messages
	Info,          // Log for normal messages
	Debug,         // Log for useful development messages
	Spew,          // Log for slightly less useful messages
	Flood,         // Log EVERYTHING. May slow performance.
}

impl LogLevel {
    fn to_lowlevel(self) -> freenect_loglevel {
        match self {
            LogLevel::Fatal => freenect_loglevel::FREENECT_LOG_FATAL,
            _ => freenect_loglevel::FREENECT_LOG_FATAL,
        }
    }

    fn from_lowlevel(lvl: freenect_loglevel) -> LogLevel {
        match lvl {
            freenect_loglevel::FREENECT_LOG_FATAL => LogLevel::Fatal,
            _ => LogLevel::Fatal
        }
    }
}

bitflags! {
    flags DeviceFlags: u32 {
        const DEVICE_MOTOR  = freenect_device_flags::FREENECT_DEVICE_MOTOR  as u32,
        const DEVICE_CAMERA = freenect_device_flags::FREENECT_DEVICE_CAMERA as u32,
        const DEVICE_AUDIO  = freenect_device_flags::FREENECT_DEVICE_AUDIO  as u32,
    }
}

pub struct DeviceAttributes {
    camera_serial: String,
}

struct InnerContext {
    ctx: *mut freenect_context,
}

impl InnerContext {
    fn new() -> FreenectResult<InnerContext> {
        let mut ctx = InnerContext{ctx: ptr::null_mut()};

        match unsafe { freenect_init(&mut ctx.ctx, ptr::null_mut()) } {
            0 => {
                if ctx.ctx != ptr::null_mut() {
                    Ok(ctx)
                } else {
                    Err(FreenectError::NullPtr)
                }
            },
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }
}

impl Drop for InnerContext {
    fn drop(&mut self) {
        let ret = unsafe { freenect_shutdown(self.ctx) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub struct Context {
    ctx: Arc<InnerContext>,
}

impl Context {
    pub fn new() -> FreenectResult<Context> {
        let inner_ctx = try!(InnerContext::new());

        Ok(Context{ctx: Arc::new(inner_ctx)})
    }

    pub fn set_log_level(&mut self, level: LogLevel) {
        unsafe { freenect_set_log_level(self.ctx.ctx, level.to_lowlevel()); }
    }

    // pub fn set_log_callback(&mut self) {
    //
    // }
    //
    // // Convert C callback parameters to rustified versions, then call user callback
    // fn callback_trampoline(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char) {
    //     let level = LogLevel::from_lowlevel(level);
    //     let msg = unsafe { ffi::CStr::from_ptr(msg) };
    // }

    pub fn process_events(&mut self) -> FreenectResult<()> {
        match unsafe { freenect_process_events(self.ctx.ctx) } {
            0 => Ok(()),
            x => Err(FreenectError::LibraryReturnCode(x)),
        }
    }

    pub fn num_devices(&mut self) -> FreenectResult<u32> {
        let ret = unsafe { freenect_num_devices(self.ctx.ctx) };
        if ret < 0 {
            Err(FreenectError::LibraryReturnCode(ret))
        } else {
            Ok(ret as u32)
        }
    }

    pub fn list_device_attributes(&mut self) -> FreenectResult<Vec<DeviceAttributes>> {
        let mut lowlevel_list: *mut freenect_device_attributes = ptr::null_mut();

        let ret = unsafe { freenect_list_device_attributes(self.ctx.ctx, &mut lowlevel_list) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret));
        }

        let mut device_list: Vec<DeviceAttributes> = Vec::new();

        let mut curr_item = lowlevel_list;
        while curr_item != ptr::null_mut() {
            let serial_cstr = unsafe { ffi::CStr::from_ptr((*curr_item).camera_serial) };
            let serial = String::from_utf8_lossy(serial_cstr.to_bytes()).to_string();

            device_list.push(DeviceAttributes{camera_serial: serial});
            unsafe { curr_item = (*curr_item).next };
        }

        unsafe { freenect_free_device_attributes(self.ctx.ctx, lowlevel_list) };

        Ok(device_list)
    }

    fn select_subdevices(&mut self, subdevs: DeviceFlags) {
        unsafe { freenect_select_subdevices(self.ctx.ctx, subdevs.bits) };
    }

    fn enabled_subdevices(&mut self) -> DeviceFlags {
        let ret = unsafe { freenect_enabled_subdevices(self.ctx.ctx) };

        return DeviceFlags::from_bits(ret as u32).unwrap();
    }

    pub fn open_device(&mut self, index: u32, subdevs: DeviceFlags) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        self.select_subdevices(subdevs);

        let ret = unsafe { freenect_open_device(self.ctx.ctx, &mut dev, index as i32) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device::from_raw_device(self.ctx.clone(), dev, self.enabled_subdevices()));
    }

    pub fn open_device_by_camera_serial(&mut self, serial: &str, subdevs: DeviceFlags) -> FreenectResult<Device> {
        let mut dev: *mut freenect_device = ptr::null_mut();

        let serial_cstring = ffi::CString::new(serial).unwrap();

        self.select_subdevices(subdevs);

        let ret = unsafe { freenect_open_device_by_camera_serial(self.ctx.ctx, &mut dev, serial_cstring.as_ptr()) };
        if ret < 0 {
            return Err(FreenectError::LibraryReturnCode(ret))
        }

        return Ok(Device::from_raw_device(self.ctx.clone(), dev, self.enabled_subdevices()));
    }
}

pub struct MotorSubdevice {
    dev: *mut freenect_device,
}

pub struct CameraSubdevice {
    dev: *mut freenect_device,
}

pub struct AudioSubdevice {
    dev: *mut freenect_device,
}

pub struct Device {
    ctx: Arc<InnerContext>, // Handle to prevent underlying context being free'd before device
    dev: *mut freenect_device,
    pub motor:  Option<MotorSubdevice>,
    pub camera: Option<CameraSubdevice>,
    pub audio:  Option<AudioSubdevice>,
}

impl Device {
    fn from_raw_device(ctx: Arc<InnerContext>, dev: *mut freenect_device, subdevs: DeviceFlags) -> Device {
        Device {
            ctx: ctx,
            dev: dev,
            motor:  if subdevs.contains(DEVICE_MOTOR)  { Some(MotorSubdevice{dev: dev})  } else { None },
            camera: if subdevs.contains(DEVICE_CAMERA) { Some(CameraSubdevice{dev: dev}) } else { None },
            audio:  if subdevs.contains(DEVICE_AUDIO)  { Some(AudioSubdevice{dev: dev})  } else { None },
        }
    }
}

impl Drop for Device {
    fn drop(&mut self) {
        let ret = unsafe { freenect_close_device(self.dev) };

        if ret < 0 {
            panic!(ret)
        }
    }
}

pub fn supported_subdevices() -> DeviceFlags {
    let bits = unsafe { freenect_supported_subdevices() as u32 };
    return DeviceFlags::from_bits(bits).unwrap();
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, box_syntax)]

extern crate rustc;
extern crate rustc_driver;
extern crate syntax;

use std::io::Command;
use std::io::fs::PathExtensions;
use std::os;
use std::str;
use std::sync::{Once, ONCE_INIT};

use rustc::plugin::Registry;
use syntax::abi;
use syntax::ast;
use syntax::attr;
use syntax::ptr::P;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, DummyResult};
use syntax::ext::base::MacResult;
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::parse::token::{special_idents, InternedString};
use syntax::print::pprust;
use syntax::util::small_vector::SmallVector;

use self::State::*;
use self::SystemDeps::*;
use self::Favor::*;

struct LibInfo {
    lib: String,
    state: State,
    deps: Vec<(String, bool)>, // (name, static)
    locs: Vec<Path>,
}

struct MacItems {
    items: Vec<P<ast::Item>>,
}

#[derive(Copy)]
enum State { Dynamic, Static(SystemDeps) }
#[derive(Copy)]
enum SystemDeps { SystemDynamic, SystemStatic }
#[derive(Copy)]
enum Favor { FavorDynamic, FavorStatic }

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("link_config", expand_link_config);
}

fn expand_link_config(ecx: &mut ExtCtxt, span: Span,
                      tts: &[ast::TokenTree]) -> Box<MacResult+'static> {
    macro_rules! try_dummy( ($e:expr) => (
        match $e { Ok(s) => s, Err(()) => return DummyResult::any(span) }
    ) );

    let mut parser = ecx.new_parser_from_tts(tts);
    let (pkg, sp) = try_dummy!(parse_string(ecx, &mut parser));
    let mut favor_dynamic = FavorDynamic;
    let mut dylib_state = Some(Dynamic);
    let mut static_state = Some(Static(SystemDynamic));
    if parser.eat(&token::Comma) && parser.eat(&token::OpenDelim(token::Bracket)) {
        while !parser.eat(&token::CloseDelim(token::Bracket)) {
            parser.eat(&token::Comma);
            let (modifier, sp) = try_dummy!(parse_string(ecx, &mut parser));
            match modifier.as_slice() {
                "only_static" => {
                    dylib_state = None;
                    favor_dynamic = FavorStatic;
                }
                "only_dylib" => {
                    static_state = None;
                    favor_dynamic = FavorDynamic;
                }
                "system_static" => static_state = Some(Static(SystemStatic)),
                "favor_static" => favor_dynamic = FavorStatic,
                s => ecx.span_err(sp, format!("unknown modifier: `{}`",
                                              s).as_slice()),
            }
        }
    }
    if !parser.eat(&token::Eof) {
        ecx.span_err(parser.span, "only one string literal allowed");
        return DummyResult::any(span);
    }

    let dyn = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), dylib_state));
    let statik = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), static_state));

    let mut items = Vec::new();
    match dyn {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    match statik {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    box MacItems { items: items } as Box<MacResult>
}

fn system_pkgconfig(ecx: &mut ExtCtxt, sp: Span, pkg: &str,
                    state: Option<State>) -> Result<Option<LibInfo>, ()> {
    let state = match state {
        Some(state) => state,
        None => return Ok(None),
    };
    add_cargo_pkg_config_paths();

    let mut cmd = Command::new("pkg-config");
    cmd.arg(pkg).arg("--libs").env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
    match state {
        Static(..) => { cmd.arg("--static"); }
        Dynamic => {}
    }
    let out = match cmd.output() {
        Ok(out) => out,
        Err(e) => {
            ecx.span_err(sp, format!("could not run pkg-config: {}", e).as_slice());
            return Err(())
        }
    };
    let stdout = str::from_utf8(out.output.as_slice()).unwrap();
    let stderr = str::from_utf8(out.error.as_slice()).unwrap();
    if !out.status.success() {
        let mut msg = format!("pkg-config did not exit successfully: {}",
                              out.status);
        if stdout.len() > 0 {
            msg.push_str("\n--- stdout\n");
            msg.push_str(stdout);
        }
        if stderr.len() > 0 {
            msg.push_str("\n--- stderr\n");
            msg.push_str(stderr);
        }
        ecx.span_err(sp, msg.as_slice());
        return Err(())
    }

    let mut libs = Vec::new();
    let mut locs = Vec::new();
    for arg in stdout.split(' ').filter(|l| !l.is_empty()) {
        if arg.starts_with("-l") {
            libs.push(arg.slice_from(2));
        } else if arg.starts_with("-L") {
            locs.push(Path::new(arg.slice_from(2).to_string()));
        }
    }

    let allow_static = match state {
        Static(..) => true,
        _ => false,
    };
    let allow_static_system = match state {
        Static(SystemStatic) => true,
        _ => false,
    };

    let cargo_locs = cargo_native_dirs();
    let libs = libs.into_iter().map(|lib| {
        let mut candidates = cargo_locs.iter().chain(locs.iter());
        (lib.to_string(), allow_static && candidates.any(|base| {
            (allow_static_system || !base.as_vec().starts_with(b"/usr")) &&
                (base.join(format!("lib{}.a", lib)).exists() ||
                 base.join(format!("{}.lib", lib)).exists() ||
                 base.join(format!("lib{}.lib", lib)).exists())
        }))
    }).collect();
    Ok(Some(LibInfo {
        lib: pkg.to_string(),
        deps: libs,
        locs: locs,
        state: state,
    }))
}

fn block(ecx: &mut ExtCtxt, sp: Span, info: &LibInfo,
         favor: Favor) -> P<ast::Item> {
    let lib = token::intern_and_get_ident(info.lib.as_slice());
    let s = match favor {
        FavorDynamic => InternedString::new("statik"),
        FavorStatic => InternedString::new("dylib"),
    };
    let cfg = ecx.meta_name_value(sp, s, ast::LitStr(lib, ast::CookedStr));
    let cfg = match (info.state, favor) {
        (Static(..), FavorDynamic) |
        (Dynamic, FavorStatic) => cfg,
        (Dynamic, FavorDynamic) |
        (Static(..), FavorStatic) => {
            ecx.meta_list(sp, InternedString::new("not"), vec![cfg])
        }
    };
    let cfg = ecx.meta_list(sp, InternedString::new("cfg"), vec![cfg]);

    let attrs = vec![ecx.attribute(sp, cfg)].into_iter();
    let attrs = attrs.chain(info.deps.iter().map(|&(ref l, statik)| {
        // Build #[link(name = <l>)]
        let l = token::intern_and_get_ident(l.as_slice());
        let mut items = Vec::new();
        items.push(ecx.meta_name_value(sp, InternedString::new("name"),
                                       ast::LitStr(l, ast::CookedStr)));
        if statik {
            let l = InternedString::new("static");
            items.push(ecx.meta_name_value(sp, InternedString::new("kind"),
                                           ast::LitStr(l, ast::CookedStr)));
        }
        let list = ecx.meta_list(sp, InternedString::new("link"), items);
        ecx.attribute(sp, list)
    }));
    let attrs = attrs.chain(info.locs.iter().map(|l| {
        let l = token::intern_and_get_ident(format!("-L{}", l.display()).as_slice());
        let args = ecx.meta_name_value(sp, InternedString::new("link_args"),
                                       ast::LitStr(l, ast::CookedStr));
        ecx.attribute(sp, args)
    }));
    let attrs = attrs.map(|attr| {
        attr::mark_used(&attr);
        attr
    });

    ecx.item(sp, special_idents::invalid, attrs.collect(),
             ast::ItemForeignMod(ast::ForeignMod {
        abi: abi::C,
        items: Vec::new(),
    }))
}

fn parse_string(ecx: &mut ExtCtxt,
                parser: &mut Parser) -> Result<(String, Span), ()> {
    let entry = ecx.expander().fold_expr(parser.parse_expr());
    match entry.node {
        ast::ExprLit(ref lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => return Ok((s.to_string(), entry.span)),
                _ => {}
            }
        }
        _ => {}
    }
    ecx.span_err(entry.span, format!(
        "expected string literal but got `{}`",
        pprust::expr_to_string(&*entry)).as_slice());
    Err(())
}

impl MacResult for MacItems {
    fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
        Some(self.items.into_iter().collect())
    }
}

// lol hax
fn cargo_native_dirs() -> Vec<Path> {
    match rustc_driver::handle_options(os::args()) {
        Some(matches) => {
            matches.opt_strs("L").into_iter().filter_map(|s| {
                if s.as_slice().contains("native") {
                    Some(Path::new(s))
                } else {
                    None
                }
            }).collect()
        }
        None => Vec::new()
    }
}

fn add_cargo_pkg_config_paths() {
    static mut DONE: Once = ONCE_INIT;
    unsafe { DONE.call_once(add_cargo_pkg_config_paths) }

    fn add_cargo_pkg_config_paths() {
        let path = os::getenv_as_bytes("PKG_CONFIG_PATH").unwrap_or(Vec::new());
        let mut pkg_config_path = os::split_paths(path.as_slice());
        pkg_config_path.push_all(cargo_native_dirs().as_slice());
        let pkg_config_path = os::join_paths(pkg_config_path.as_slice())
                                 .unwrap();
        os::setenv("PKG_CONFIG_PATH", pkg_config_path.as_slice());
    }
}
<commit_msg>Fixes buid against rustc 1.0.0-nightly (c5961ad06 2015-01-28)<commit_after>#![feature(plugin_registrar, box_syntax)]

extern crate rustc;
extern crate rustc_driver;
extern crate syntax;

use std::old_io::Command;
use std::old_io::fs::PathExtensions;
use std::os;
use std::str;
use std::sync::{Once, ONCE_INIT};

use rustc::plugin::Registry;
use syntax::abi;
use syntax::ast;
use syntax::attr;
use syntax::ptr::P;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, DummyResult};
use syntax::ext::base::MacResult;
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::parse::token::{special_idents, InternedString};
use syntax::print::pprust;
use syntax::util::small_vector::SmallVector;

use self::State::*;
use self::SystemDeps::*;
use self::Favor::*;

struct LibInfo {
    lib: String,
    state: State,
    deps: Vec<(String, bool)>, // (name, static)
    locs: Vec<Path>,
}

struct MacItems {
    items: Vec<P<ast::Item>>,
}

#[derive(Copy)]
enum State { Dynamic, Static(SystemDeps) }
#[derive(Copy)]
enum SystemDeps { SystemDynamic, SystemStatic }
#[derive(Copy)]
enum Favor { FavorDynamic, FavorStatic }

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("link_config", expand_link_config);
}

fn expand_link_config(ecx: &mut ExtCtxt, span: Span,
                      tts: &[ast::TokenTree]) -> Box<MacResult+'static> {
    macro_rules! try_dummy( ($e:expr) => (
        match $e { Ok(s) => s, Err(()) => return DummyResult::any(span) }
    ) );

    let mut parser = ecx.new_parser_from_tts(tts);
    let (pkg, sp) = try_dummy!(parse_string(ecx, &mut parser));
    let mut favor_dynamic = FavorDynamic;
    let mut dylib_state = Some(Dynamic);
    let mut static_state = Some(Static(SystemDynamic));
    if parser.eat(&token::Comma) && parser.eat(&token::OpenDelim(token::Bracket)) {
        while !parser.eat(&token::CloseDelim(token::Bracket)) {
            parser.eat(&token::Comma);
            let (modifier, sp) = try_dummy!(parse_string(ecx, &mut parser));
            match modifier.as_slice() {
                "only_static" => {
                    dylib_state = None;
                    favor_dynamic = FavorStatic;
                }
                "only_dylib" => {
                    static_state = None;
                    favor_dynamic = FavorDynamic;
                }
                "system_static" => static_state = Some(Static(SystemStatic)),
                "favor_static" => favor_dynamic = FavorStatic,
                s => ecx.span_err(sp, format!("unknown modifier: `{}`",
                                              s).as_slice()),
            }
        }
    }
    if !parser.eat(&token::Eof) {
        ecx.span_err(parser.span, "only one string literal allowed");
        return DummyResult::any(span);
    }

    let dyn = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), dylib_state));
    let statik = try_dummy!(system_pkgconfig(ecx, sp, pkg.as_slice(), static_state));

    let mut items = Vec::new();
    match dyn {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    match statik {
        Some(info) => items.push(block(ecx, sp, &info, favor_dynamic)),
        None => {}
    }
    box MacItems { items: items } as Box<MacResult>
}

fn system_pkgconfig(ecx: &mut ExtCtxt, sp: Span, pkg: &str,
                    state: Option<State>) -> Result<Option<LibInfo>, ()> {
    let state = match state {
        Some(state) => state,
        None => return Ok(None),
    };
    add_cargo_pkg_config_paths();

    let mut cmd = Command::new("pkg-config");
    cmd.arg(pkg).arg("--libs").env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
    match state {
        Static(..) => { cmd.arg("--static"); }
        Dynamic => {}
    }
    let out = match cmd.output() {
        Ok(out) => out,
        Err(e) => {
            ecx.span_err(sp, format!("could not run pkg-config: {}", e).as_slice());
            return Err(())
        }
    };
    let stdout = str::from_utf8(out.output.as_slice()).unwrap();
    let stderr = str::from_utf8(out.error.as_slice()).unwrap();
    if !out.status.success() {
        let mut msg = format!("pkg-config did not exit successfully: {}",
                              out.status);
        if stdout.len() > 0 {
            msg.push_str("\n--- stdout\n");
            msg.push_str(stdout);
        }
        if stderr.len() > 0 {
            msg.push_str("\n--- stderr\n");
            msg.push_str(stderr);
        }
        ecx.span_err(sp, msg.as_slice());
        return Err(())
    }

    let mut libs = Vec::new();
    let mut locs = Vec::new();
    for arg in stdout.split(' ').filter(|l| !l.is_empty()) {
        if arg.starts_with("-l") {
            libs.push(arg.slice_from(2));
        } else if arg.starts_with("-L") {
            locs.push(Path::new(arg.slice_from(2).to_string()));
        }
    }

    let allow_static = match state {
        Static(..) => true,
        _ => false,
    };
    let allow_static_system = match state {
        Static(SystemStatic) => true,
        _ => false,
    };

    let cargo_locs = cargo_native_dirs();
    let libs = libs.into_iter().map(|lib| {
        let mut candidates = cargo_locs.iter().chain(locs.iter());
        (lib.to_string(), allow_static && candidates.any(|base| {
            (allow_static_system || !base.as_vec().starts_with(b"/usr")) &&
                (base.join(format!("lib{}.a", lib)).exists() ||
                 base.join(format!("{}.lib", lib)).exists() ||
                 base.join(format!("lib{}.lib", lib)).exists())
        }))
    }).collect();
    Ok(Some(LibInfo {
        lib: pkg.to_string(),
        deps: libs,
        locs: locs,
        state: state,
    }))
}

fn block(ecx: &mut ExtCtxt, sp: Span, info: &LibInfo,
         favor: Favor) -> P<ast::Item> {
    let lib = token::intern_and_get_ident(info.lib.as_slice());
    let s = match favor {
        FavorDynamic => InternedString::new("statik"),
        FavorStatic => InternedString::new("dylib"),
    };
    let cfg = ecx.meta_name_value(sp, s, ast::LitStr(lib, ast::CookedStr));
    let cfg = match (info.state, favor) {
        (Static(..), FavorDynamic) |
        (Dynamic, FavorStatic) => cfg,
        (Dynamic, FavorDynamic) |
        (Static(..), FavorStatic) => {
            ecx.meta_list(sp, InternedString::new("not"), vec![cfg])
        }
    };
    let cfg = ecx.meta_list(sp, InternedString::new("cfg"), vec![cfg]);

    let attrs = vec![ecx.attribute(sp, cfg)].into_iter();
    let attrs = attrs.chain(info.deps.iter().map(|&(ref l, statik)| {
        // Build #[link(name = <l>)]
        let l = token::intern_and_get_ident(l.as_slice());
        let mut items = Vec::new();
        items.push(ecx.meta_name_value(sp, InternedString::new("name"),
                                       ast::LitStr(l, ast::CookedStr)));
        if statik {
            let l = InternedString::new("static");
            items.push(ecx.meta_name_value(sp, InternedString::new("kind"),
                                           ast::LitStr(l, ast::CookedStr)));
        }
        let list = ecx.meta_list(sp, InternedString::new("link"), items);
        ecx.attribute(sp, list)
    }));
    let attrs = attrs.chain(info.locs.iter().map(|l| {
        let l = token::intern_and_get_ident(format!("-L{}", l.display()).as_slice());
        let args = ecx.meta_name_value(sp, InternedString::new("link_args"),
                                       ast::LitStr(l, ast::CookedStr));
        ecx.attribute(sp, args)
    }));
    let attrs = attrs.map(|attr| {
        attr::mark_used(&attr);
        attr
    });

    ecx.item(sp, special_idents::invalid, attrs.collect(),
             ast::ItemForeignMod(ast::ForeignMod {
        abi: abi::C,
        items: Vec::new(),
    }))
}

fn parse_string(ecx: &mut ExtCtxt,
                parser: &mut Parser) -> Result<(String, Span), ()> {
    let entry = ecx.expander().fold_expr(parser.parse_expr());
    match entry.node {
        ast::ExprLit(ref lit) => {
            match lit.node {
                ast::LitStr(ref s, _) => return Ok((s.to_string(), entry.span)),
                _ => {}
            }
        }
        _ => {}
    }
    ecx.span_err(entry.span, format!(
        "expected string literal but got `{}`",
        pprust::expr_to_string(&*entry)).as_slice());
    Err(())
}

impl MacResult for MacItems {
    fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
        Some(self.items.into_iter().collect())
    }
}

// lol hax
fn cargo_native_dirs() -> Vec<Path> {
    match rustc_driver::handle_options(os::args()) {
        Some(matches) => {
            matches.opt_strs("L").into_iter().filter_map(|s| {
                if s.as_slice().contains("native") {
                    Some(Path::new(s))
                } else {
                    None
                }
            }).collect()
        }
        None => Vec::new()
    }
}

fn add_cargo_pkg_config_paths() {
    static mut DONE: Once = ONCE_INIT;
    unsafe { DONE.call_once(add_cargo_pkg_config_paths) }

    fn add_cargo_pkg_config_paths() {
        let path = os::getenv_as_bytes("PKG_CONFIG_PATH").unwrap_or(Vec::new());
        let mut pkg_config_path = os::split_paths(path.as_slice());
        pkg_config_path.push_all(cargo_native_dirs().as_slice());
        let pkg_config_path = os::join_paths(pkg_config_path.as_slice())
                                 .unwrap();
        os::setenv("PKG_CONFIG_PATH", pkg_config_path.as_slice());
    }
}
<|endoftext|>


<commit_before>pub mod ffi;
pub mod hl;

#[cfg(test)]
mod tests {
    use ffi::*;
    use hl::*;
    use std::sync::{ONCE_INIT, Once};
    static GLSLANG_INITIALIZATION: Once = ONCE_INIT;

    fn init() {
        GLSLANG_INITIALIZATION.call_once(|| initialize().unwrap());
    }

    #[test]
    fn test_linkage() {
        init();
    }

    #[test]
    fn test_translation_complex() {
        init();
        const FRAGMENT_SHADER: u32 = 0x8B30;
        let source = "
   precision mediump float;
   varying vec2 vTextureCoord;

   uniform sampler2D uSampler;

   void main() {
      gl_FragColor = texture2D(uSampler, vTextureCoord);
   }
";
        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        assert!(compiler.compile_and_translate(&[source]).is_ok());
    }

    #[test]
    fn test_translation() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }

    // TODO(emilio): run this test. We can't actually run it because travis machines can't output
    // essl.
    fn test_translation_essl() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Essl,
                                                  &BuiltInResources::default()).expect("Failed to create a validator for essl");

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }
}
<commit_msg>Auto merge of #19 - servo:test-essl, r=nox<commit_after>pub mod ffi;
pub mod hl;

#[cfg(test)]
mod tests {
    use ffi::*;
    use hl::*;
    use std::sync::{ONCE_INIT, Once};
    static GLSLANG_INITIALIZATION: Once = ONCE_INIT;

    fn init() {
        GLSLANG_INITIALIZATION.call_once(|| initialize().unwrap());
    }

    #[test]
    fn test_linkage() {
        init();
    }

    #[test]
    fn test_translation_complex() {
        init();
        const FRAGMENT_SHADER: u32 = 0x8B30;
        let source = "
   precision mediump float;
   varying vec2 vTextureCoord;

   uniform sampler2D uSampler;

   void main() {
      gl_FragColor = texture2D(uSampler, vTextureCoord);
   }
";
        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        assert!(compiler.compile_and_translate(&[source]).is_ok());
    }

    #[test]
    fn test_translation() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }

    #[test]
    fn test_translation_essl() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Essl,
                                                  &BuiltInResources::default()).expect("Failed to create a validator for essl");

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }
}
<|endoftext|>


<commit_before>//! This is a library for controlling a cursor and a screen,
//! on ANSI terminals.
//!
//!
//! ## Example
//!
//!     use ansi_control::*;
//!

use std::cmp::{self, Ordering};

/// A Pos is position of clearing (display|line) from cursor.
pub enum Pos {
    Back,
    Front,
    Both,
}

/// Moves the cursor _i_ (row), _j_ (column) cells. If the cursor
/// is already at the edge of the screen, this has no effect.
pub fn move_cursor(i: i32, j: i32) -> String {
    let code0 = match i.cmp(&0) {
        Ordering::Less      => format!("\x1B[{}B", -i),
        Ordering::Equal     => format!(""),
        Ordering::Greater   => format!("\x1B[{}A", i),
    };
    let code1 = match j.cmp(&0) {
        Ordering::Less      => format!("\x1B[{}D", -j),
        Ordering::Equal     => format!(""),
        Ordering::Greater   => format!("\x1B[{}C", j),
    };
    format!("{}{}", code0, code1)
}

/// Moves the cursor to beginning of the line _n_ lines down.
/// If _n_ is a negative number, this function moves the cursor
/// _|n|_ lines up.
pub fn move_line(n: i32) -> String {
    match n.cmp(&0) {
        Ordering::Less      => format!("\x1B[{}F", -n),
        Ordering::Equal     => format!(""),
        Ordering::Greater   => format!("\x1B[{}E", n),
    }
}

/// Sets the column of the cursor. (n: column)
pub fn set_column(n: u32) -> String {
    format!("\x1B[{}G", cmp::max(1, n))
}

/// Sets the position of the cursor. (i: row, j: column)
pub fn set_position(i: u32, j: u32) -> String {
    format!("")
}

/// Clears part of screen. If pos is Pos::Back, clear from cursor
/// to the end of the screen. If pos is Pos::Front, clear from
/// cursor to beginning of the screen. If pos is Pos::Both, clear
/// entire screen.
pub fn clear_display(pos: Pos) -> String {
    format!("")
}

/// Clears part of line. If pos is Pos::Back, clear from cursor
/// to the end of the line. If pos is Pos::Front, clear from
/// cursor to beginning of the line. If pos is Pos::Both, clear
/// entire line.
pub fn clear_line(pos: Pos) -> String {
    format!("")
}

/// Scroll whole page up by _n_ lines. If _n_ is a negative
/// number, this function scroll whole page down by _|n|_ lines.
pub fn scroll(n: i32) -> String {
    format!("")
}

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

    macro_rules! test {
        ($name: ident; $ctrl: expr => $result: expr) => {
            #[test]
            fn $name() {
                assert_eq!($result, $ctrl)
            }
        };
    }

    test!(move_cursor0; move_cursor(2, -4) => "\x1B[2A\x1B[4D");
    test!(move_cursor1; move_cursor(-2, 0) => "\x1B[2B");
    test!(move_cursor2; move_cursor(0, 6) => "\x1B[6C");
    test!(move_cursor3; move_cursor(0, 0) => "");

    test!(move_line0; move_line(4) => "\x1B[4E");
    test!(move_line1; move_line(-4) => "\x1B[4F");

    test!(set_column0; set_column(3) => "\x1B[3G");
    test!(set_column1; set_column(0) => "\x1B[1G");

    test!(set_position0; set_position(3, 5) => "\x1B[3;5H");
    test!(set_position1; set_position(0, 0) => "\x1B[1;1H");

    test!(clear_display0; clear_display(Pos::Back) => "\x1B[0J");
    test!(clear_display1; clear_display(Pos::Front) => "\x1B[1J");
    test!(clear_display2; clear_display(Pos::Both) => "\x1B[2J");

    test!(clear_line0; clear_line(Pos::Back) => "\x1B[0K");
    test!(clear_line1; clear_line(Pos::Front) => "\x1B[1K");
    test!(clear_line2; clear_line(Pos::Both) => "\x1B[2K");

    test!(scroll0; scroll(7) => "\x1B[7S");
    test!(scroll1; scroll(-5) => "\x1B[5T");
}
<commit_msg>Improve set_position<commit_after>//! This is a library for controlling a cursor and a screen,
//! on ANSI terminals.
//!
//!
//! ## Example
//!
//!     use ansi_control::*;
//!

use std::cmp::{self, Ordering};

/// A Pos is position of clearing (display|line) from cursor.
pub enum Pos {
    Back,
    Front,
    Both,
}

/// Moves the cursor _i_ (row), _j_ (column) cells. If the cursor
/// is already at the edge of the screen, this has no effect.
pub fn move_cursor(i: i32, j: i32) -> String {
    let code0 = match i.cmp(&0) {
        Ordering::Less      => format!("\x1B[{}B", -i),
        Ordering::Equal     => format!(""),
        Ordering::Greater   => format!("\x1B[{}A", i),
    };
    let code1 = match j.cmp(&0) {
        Ordering::Less      => format!("\x1B[{}D", -j),
        Ordering::Equal     => format!(""),
        Ordering::Greater   => format!("\x1B[{}C", j),
    };
    format!("{}{}", code0, code1)
}

/// Moves the cursor to beginning of the line _n_ lines down.
/// If _n_ is a negative number, this function moves the cursor
/// _|n|_ lines up.
pub fn move_line(n: i32) -> String {
    match n.cmp(&0) {
        Ordering::Less      => format!("\x1B[{}F", -n),
        Ordering::Equal     => format!(""),
        Ordering::Greater   => format!("\x1B[{}E", n),
    }
}

/// Sets the column of the cursor. (n: column)
pub fn set_column(n: u32) -> String {
    format!("\x1B[{}G", cmp::max(1, n))
}

/// Sets the position of the cursor. (i: row, j: column)
pub fn set_position(i: u32, j: u32) -> String {
    format!("\x1B[{};{}H", cmp::max(1, i), cmp::max(1, j))
}

/// Clears part of screen. If pos is Pos::Back, clear from cursor
/// to the end of the screen. If pos is Pos::Front, clear from
/// cursor to beginning of the screen. If pos is Pos::Both, clear
/// entire screen.
pub fn clear_display(pos: Pos) -> String {
    format!("")
}

/// Clears part of line. If pos is Pos::Back, clear from cursor
/// to the end of the line. If pos is Pos::Front, clear from
/// cursor to beginning of the line. If pos is Pos::Both, clear
/// entire line.
pub fn clear_line(pos: Pos) -> String {
    format!("")
}

/// Scroll whole page up by _n_ lines. If _n_ is a negative
/// number, this function scroll whole page down by _|n|_ lines.
pub fn scroll(n: i32) -> String {
    format!("")
}

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

    macro_rules! test {
        ($name: ident; $ctrl: expr => $result: expr) => {
            #[test]
            fn $name() {
                assert_eq!($result, $ctrl)
            }
        };
    }

    test!(move_cursor0; move_cursor(2, -4) => "\x1B[2A\x1B[4D");
    test!(move_cursor1; move_cursor(-2, 0) => "\x1B[2B");
    test!(move_cursor2; move_cursor(0, 6) => "\x1B[6C");
    test!(move_cursor3; move_cursor(0, 0) => "");

    test!(move_line0; move_line(4) => "\x1B[4E");
    test!(move_line1; move_line(-4) => "\x1B[4F");

    test!(set_column0; set_column(3) => "\x1B[3G");
    test!(set_column1; set_column(0) => "\x1B[1G");

    test!(set_position0; set_position(3, 5) => "\x1B[3;5H");
    test!(set_position1; set_position(0, 0) => "\x1B[1;1H");

    test!(clear_display0; clear_display(Pos::Back) => "\x1B[0J");
    test!(clear_display1; clear_display(Pos::Front) => "\x1B[1J");
    test!(clear_display2; clear_display(Pos::Both) => "\x1B[2J");

    test!(clear_line0; clear_line(Pos::Back) => "\x1B[0K");
    test!(clear_line1; clear_line(Pos::Front) => "\x1B[1K");
    test!(clear_line2; clear_line(Pos::Both) => "\x1B[2K");

    test!(scroll0; scroll(7) => "\x1B[7S");
    test!(scroll1; scroll(-5) => "\x1B[5T");
}
<|endoftext|>