<commit_before>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;
use frame::subframe::{CodingMethod, PartitionedRiceContents};

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000            => constant(input, bits_per_sample),
    0b000001            => verbatim(input, bits_per_sample, block_size),
    0b001000...0b001100 => fixed(input, subframe_type & 0b0111,
                                 bits_per_sample, block_size),
    0b100000...0b111111 => lpc(input, (subframe_type & 0b011111) + 1,
                               bits_per_sample, block_size),
    _                   => IResult::Error(Err::Position(
                             ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn fixed(input: (&[u8], usize),
         order: usize,
         bits_per_sample: usize,
         block_size: usize)
         -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup = [0; subframe::MAX_FIXED_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::Fixed(subframe::Fixed {
        entropy_coding_method: data.0,
        order: order as u8,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn qlp_coefficient_precision(input: (&[u8], usize))
                             -> IResult<(&[u8], usize), u8> {
  match take_bits!(input, u8, 4) {
    IResult::Done(i, precision) => {
      if precision == 0b1111 {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      } else {
        IResult::Done(i, precision + 1)
      }
    }
    IResult::Error(error)       => IResult::Error(error),
    IResult::Incomplete(need)   => IResult::Incomplete(need),
  }
}

fn lpc(input: (&[u8], usize),
       order: usize,
       bits_per_sample: usize,
       block_size: usize)
       -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup           = [0; subframe::MAX_LPC_ORDER];
  let mut qlp_coefficients = [0; subframe::MAX_LPC_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    qlp_coeff_precision: qlp_coefficient_precision ~
    quantization_level: take_bits!(i8, 5) ~
    count_slice!(
      take_bits!(i32, qlp_coeff_precision as usize),
      &mut qlp_coefficients[0..order]
    ) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::LPC(subframe::LPC {
        entropy_coding_method: data.0,
        order: order as u8,
        qlp_coeff_precision: qlp_coeff_precision,
        quantization_level: quantization_level,
        qlp_coefficients: qlp_coefficients,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn coding_method(input: (&[u8], usize))
                 -> IResult<(&[u8], usize), CodingMethod> {
  match take_bits!(input, u8, 2) {
    IResult::Done(i, method)  => {
      match method {
        0 => IResult::Done(i, CodingMethod::PartitionedRice),
        1 => IResult::Done(i, CodingMethod::PartitionedRice2),
        _ => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0)),
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn residual(input: (&[u8], usize),
            predictor_order: usize,
            block_size: usize)
            -> IResult<(&[u8], usize),
                       (subframe::EntropyCodingMethod, Vec<i32>)> {
  match pair!(input, coding_method, take_bits!(u32, 4)) {
    IResult::Done(i, data)    => {
      let (method, order) = data;

      rice_partition(i, order, predictor_order, block_size, method)
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn rice_partition(input: (&[u8], usize),
                  partition_order: u32,
                  predictor_order: usize,
                  block_size: usize,
                  method: CodingMethod)
                  -> IResult<(&[u8], usize),
                             (subframe::EntropyCodingMethod, Vec<i32>)> {
  let (param_size, escape_code) = match method {
    CodingMethod::PartitionedRice  => (4, 0b1111),
    CodingMethod::PartitionedRice2 => (5, 0b11111),
  };

  // Adjust block size to not include allocation for warm up samples
  let residual_size = block_size - predictor_order;

  let mut mut_input = input;
  let mut residual  = Vec::with_capacity(residual_size);
  let mut sample    = 0;
  let mut contents  = PartitionedRiceContents::new(partition_order);

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

  for partition in 0..partitions {
    let offset = if partition_order == 0 {
      block_size - predictor_order
    } else if partition > 0 {
      block_size / partitions
    } else {
      (block_size / partitions) - predictor_order
    };
    let start = sample;
    let end   = sample + offset;

    let result = chain!(mut_input,
      rice_parameter: take_bits!(u32, param_size) ~
      size: cond!(rice_parameter == escape_code, take_bits!(usize, 5)) ~
      data: apply!(residual_data,
        size, rice_parameter,
        &mut contents.raw_bits[partition],
        &mut residual[start..end]
      ),
      || { rice_parameter }
    );

    match result {
      IResult::Done(i, parameter) => {
        mut_input = i;
        sample    = end;

        contents.parameters[partition] = parameter;
      }
      IResult::Error(error)       => return IResult::Error(error),
      IResult::Incomplete(need)   => return IResult::Incomplete(need),
    }
  }

  let entropy_coding_method = subframe::EntropyCodingMethod {
    method_type: method,
    data: subframe::PartitionedRice {
      order: partition_order,
      contents: contents,
    },
  };

  IResult::Done(mut_input, (entropy_coding_method, residual))
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<commit_msg>Change type signature of subframe data parser<commit_after>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;
use frame::subframe::{CodingMethod, PartitionedRiceContents};

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (usize, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type as usize, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000            => constant(input, bits_per_sample),
    0b000001            => verbatim(input, bits_per_sample, block_size),
    0b001000...0b001100 => fixed(input, subframe_type & 0b0111,
                                 bits_per_sample, block_size),
    0b100000...0b111111 => lpc(input, (subframe_type & 0b011111) + 1,
                               bits_per_sample, block_size),
    _                   => IResult::Error(Err::Position(
                             ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn fixed(input: (&[u8], usize),
         order: usize,
         bits_per_sample: usize,
         block_size: usize)
         -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup = [0; subframe::MAX_FIXED_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::Fixed(subframe::Fixed {
        entropy_coding_method: data.0,
        order: order as u8,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn qlp_coefficient_precision(input: (&[u8], usize))
                             -> IResult<(&[u8], usize), u8> {
  match take_bits!(input, u8, 4) {
    IResult::Done(i, precision) => {
      if precision == 0b1111 {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      } else {
        IResult::Done(i, precision + 1)
      }
    }
    IResult::Error(error)       => IResult::Error(error),
    IResult::Incomplete(need)   => IResult::Incomplete(need),
  }
}

fn lpc(input: (&[u8], usize),
       order: usize,
       bits_per_sample: usize,
       block_size: usize)
       -> IResult<(&[u8], usize), subframe::Data> {
  let mut warmup           = [0; subframe::MAX_LPC_ORDER];
  let mut qlp_coefficients = [0; subframe::MAX_LPC_ORDER];

  chain!(input,
    count_slice!(take_bits!(i32, bits_per_sample), &mut warmup[0..order]) ~
    qlp_coeff_precision: qlp_coefficient_precision ~
    quantization_level: take_bits!(i8, 5) ~
    count_slice!(
      take_bits!(i32, qlp_coeff_precision as usize),
      &mut qlp_coefficients[0..order]
    ) ~
    tuple: apply!(residual, order, block_size),
    || {
      let data = tuple;

      subframe::Data::LPC(subframe::LPC {
        entropy_coding_method: data.0,
        order: order as u8,
        qlp_coeff_precision: qlp_coeff_precision,
        quantization_level: quantization_level,
        qlp_coefficients: qlp_coefficients,
        warmup: warmup,
        residual: data.1,
      })
    }
  )
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn coding_method(input: (&[u8], usize))
                 -> IResult<(&[u8], usize), CodingMethod> {
  match take_bits!(input, u8, 2) {
    IResult::Done(i, method)  => {
      match method {
        0 => IResult::Done(i, CodingMethod::PartitionedRice),
        1 => IResult::Done(i, CodingMethod::PartitionedRice2),
        _ => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0)),
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn residual(input: (&[u8], usize),
            predictor_order: usize,
            block_size: usize)
            -> IResult<(&[u8], usize),
                       (subframe::EntropyCodingMethod, Vec<i32>)> {
  match pair!(input, coding_method, take_bits!(u32, 4)) {
    IResult::Done(i, data)    => {
      let (method, order) = data;

      rice_partition(i, order, predictor_order, block_size, method)
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn rice_partition(input: (&[u8], usize),
                  partition_order: u32,
                  predictor_order: usize,
                  block_size: usize,
                  method: CodingMethod)
                  -> IResult<(&[u8], usize),
                             (subframe::EntropyCodingMethod, Vec<i32>)> {
  let (param_size, escape_code) = match method {
    CodingMethod::PartitionedRice  => (4, 0b1111),
    CodingMethod::PartitionedRice2 => (5, 0b11111),
  };

  // Adjust block size to not include allocation for warm up samples
  let residual_size = block_size - predictor_order;

  let mut mut_input = input;
  let mut residual  = Vec::with_capacity(residual_size);
  let mut sample    = 0;
  let mut contents  = PartitionedRiceContents::new(partition_order);

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

  for partition in 0..partitions {
    let offset = if partition_order == 0 {
      block_size - predictor_order
    } else if partition > 0 {
      block_size / partitions
    } else {
      (block_size / partitions) - predictor_order
    };
    let start = sample;
    let end   = sample + offset;

    let result = chain!(mut_input,
      rice_parameter: take_bits!(u32, param_size) ~
      size: cond!(rice_parameter == escape_code, take_bits!(usize, 5)) ~
      data: apply!(residual_data,
        size, rice_parameter,
        &mut contents.raw_bits[partition],
        &mut residual[start..end]
      ),
      || { rice_parameter }
    );

    match result {
      IResult::Done(i, parameter) => {
        mut_input = i;
        sample    = end;

        contents.parameters[partition] = parameter;
      }
      IResult::Error(error)       => return IResult::Error(error),
      IResult::Incomplete(need)   => return IResult::Incomplete(need),
    }
  }

  let entropy_coding_method = subframe::EntropyCodingMethod {
    method_type: method,
    data: subframe::PartitionedRice {
      order: partition_order,
      contents: contents,
    },
  };

  IResult::Done(mut_input, (entropy_coding_method, residual))
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use error::Error;
use libc::size_t;
use std::{convert, mem};

#[repr(C)]
pub struct Ffi__Array<T> {
    pub ptr: *mut T,
    pub length: size_t,
    pub capacity: size_t,
}

impl <T>convert::From<Vec<T>> for Ffi__Array<T> {
    fn from(item: Vec<T>) -> Ffi__Array<T> {
        let mut item = item;

        item.shrink_to_fit();

        let ffi_item = Ffi__Array {
            ptr: item.as_mut_ptr(),
            length: item.len() as size_t,
            capacity: item.capacity() as size_t,
        };

        mem::forget(item);

        ffi_item
    }
}

impl <T>convert::Into<Vec<T>> for Ffi__Array<T> {
    fn into(self) -> Vec<T> {
        if self.ptr.is_null() {
            panic!(Error::NullPtr("array"));
        }
        unsafe { Vec::from_raw_parts(self.ptr, self.length, self.capacity) }
    }
}

macro_rules! trynull {
    ($e:expr) => (match $e {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => {
            ::error::seterr(err);
            return ::std::ptr::null_mut()
        },
    });
}

macro_rules! tryrc {
    ($e:expr) => (tryrc!($e, 1));
    ($e:expr, $r:expr) => (match $e {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => {
            ::error::seterr(err);
            return $r
        },
    });
}

macro_rules! trypanic {
    ($e:expr) => (match $e {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => panic!(err),
    });
}

macro_rules! ptrtostr {
    ($p:expr, $e:expr) => ({
        let r = $p; // Evaluate $p before consuming the result
        if r.is_null() {
            ::std::result::Result::Err(::error::Error::NullPtr($e))
        } else {
            match unsafe { ::std::ffi::CStr::from_ptr(r).to_str() } {
                ::std::result::Result::Ok(s) => ::std::result::Result::Ok(s),
                ::std::result::Result::Err(e) => ::std::result::Result::Err(::std::convert::Into::into(e)),
            }
        }
    });
}

macro_rules! readptr {
    ($p:expr, $e:expr) => ({
        let r = $p; // Evaluate $p before consuming the result
        if r.is_null() {
            ::std::result::Result::Err(::error::Error::NullPtr($e))
        } else {
            match ::std::panic::catch_unwind(|| ::std::convert::Into::into(unsafe { ::std::ptr::read(r) })) {
                ::std::result::Result::Ok(val) => ::std::result::Result::Ok(val),
                ::std::result::Result::Err(e) => ::std::result::Result::Err(::std::convert::Into::into(e)),
            }
        }
    });
}

macro_rules! boxptr {
    ($p:expr, $e:expr) => ({
        let r = $p; // Evaluate $p before consuming the result
        if r.is_null() {
            ::std::result::Result::Err(::error::Error::NullPtr($e))
        } else {
            match ::std::panic::catch_unwind(|| ::std::convert::Into::into(unsafe { ::std::boxed::Box::from_raw(r) })) {
                ::std::result::Result::Ok(val) => ::std::result::Result::Ok(val),
                ::std::result::Result::Err(e) => ::std::result::Result::Err(::std::convert::Into::into(e)),
            }
        }
    });
}
<commit_msg>Trivial code cleanup<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use error::Error;
use libc::size_t;
use std::{convert, mem};

#[repr(C)]
pub struct Ffi__Array<T> {
    pub ptr: *mut T,
    pub length: size_t,
    pub capacity: size_t,
}

impl <T>convert::From<Vec<T>> for Ffi__Array<T> {
    fn from(mut item: Vec<T>) -> Ffi__Array<T> {
        item.shrink_to_fit();

        let ffi_item = Ffi__Array {
            ptr: item.as_mut_ptr(),
            length: item.len() as size_t,
            capacity: item.capacity() as size_t,
        };

        mem::forget(item);

        ffi_item
    }
}

impl <T>convert::Into<Vec<T>> for Ffi__Array<T> {
    fn into(self) -> Vec<T> {
        if self.ptr.is_null() {
            panic!(Error::NullPtr("array"));
        }
        unsafe { Vec::from_raw_parts(self.ptr, self.length, self.capacity) }
    }
}

macro_rules! trynull {
    ($e:expr) => (match $e {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => {
            ::error::seterr(err);
            return ::std::ptr::null_mut()
        },
    });
}

macro_rules! tryrc {
    ($e:expr) => (tryrc!($e, 1));
    ($e:expr, $r:expr) => (match $e {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => {
            ::error::seterr(err);
            return $r
        },
    });
}

macro_rules! trypanic {
    ($e:expr) => (match $e {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => panic!(err),
    });
}

macro_rules! ptrtostr {
    ($p:expr, $e:expr) => ({
        let r = $p; // Evaluate $p before consuming the result
        if r.is_null() {
            ::std::result::Result::Err(::error::Error::NullPtr($e))
        } else {
            match unsafe { ::std::ffi::CStr::from_ptr(r).to_str() } {
                ::std::result::Result::Ok(s) => ::std::result::Result::Ok(s),
                ::std::result::Result::Err(e) => ::std::result::Result::Err(::std::convert::Into::into(e)),
            }
        }
    });
}

macro_rules! readptr {
    ($p:expr, $e:expr) => ({
        let r = $p; // Evaluate $p before consuming the result
        if r.is_null() {
            ::std::result::Result::Err(::error::Error::NullPtr($e))
        } else {
            match ::std::panic::catch_unwind(|| ::std::convert::Into::into(unsafe { ::std::ptr::read(r) })) {
                ::std::result::Result::Ok(val) => ::std::result::Result::Ok(val),
                ::std::result::Result::Err(e) => ::std::result::Result::Err(::std::convert::Into::into(e)),
            }
        }
    });
}

macro_rules! boxptr {
    ($p:expr, $e:expr) => ({
        let r = $p; // Evaluate $p before consuming the result
        if r.is_null() {
            ::std::result::Result::Err(::error::Error::NullPtr($e))
        } else {
            match ::std::panic::catch_unwind(|| ::std::convert::Into::into(unsafe { ::std::boxed::Box::from_raw(r) })) {
                ::std::result::Result::Ok(val) => ::std::result::Result::Ok(val),
                ::std::result::Result::Err(e) => ::std::result::Result::Err(::std::convert::Into::into(e)),
            }
        }
    });
}
<|endoftext|>


<commit_before>pub trait NumberOps : Sized {
   fn rounding_div(self, other: Self) -> Self;
}

impl NumberOps for i64 {
   #[inline]
   fn rounding_div(self, other: i64) -> i64 {
      if (self < 0) ^ (other < 0) {
         (self - (other / 2)) / other
      } else {
         (self + (other / 2)) / other
      }
   }
}

#[cfg(test)]
mod tests {
   use test::{Bencher, black_box};

   use super::*;

   #[bench]
   fn bench_rounding_div(b: &mut Bencher) {
      b.iter(|| {
         for _ in 0..1000 {
            black_box(1900000_i64.rounding_div(black_box(700000_i64)));
         }
      });
   }
}
<commit_msg>Prime numbers for rounding_div benchmark<commit_after>pub trait NumberOps : Sized {
   fn rounding_div(self, other: Self) -> Self;
}

impl NumberOps for i64 {
   #[inline]
   fn rounding_div(self, other: i64) -> i64 {
      if (self < 0) ^ (other < 0) {
         (self - (other / 2)) / other
      } else {
         (self + (other / 2)) / other
      }
   }
}

#[cfg(test)]
mod tests {
   use test::{Bencher, black_box};

   use super::*;

   #[bench]
   fn bench_rounding_div(b: &mut Bencher) {
      b.iter(|| {
         for _ in 0..1000 {
            black_box(15023081_i64.rounding_div(black_box(108877_i64)));
         }
      });
   }
}
<|endoftext|>


<commit_before>use character::controls::CharacterControl;
use game::constants::{RESOLUTION_X, RESOLUTION_Y};
use gfx;
use gfx_app::controls::{Control, TilemapControls};
use gfx_device_gl;
use gfx_window_glutin;
use glutin;
use glutin::{GlContext, KeyboardInput, MouseButton};
use glutin::ElementState::{Pressed, Released};
use glutin::VirtualKeyCode::{Escape, Z, X, W, A, S, D, R};

pub mod init;
pub mod renderer;
pub mod system;
pub mod controls;
pub mod mouse_controls;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

pub struct WindowContext {
  window: glutin::GlWindow,
  controls: Option<controls::TilemapControls>,
  events_loop: glutin::EventsLoop,
  device: gfx_device_gl::Device,
  factory: gfx_device_gl::Factory,
  render_target_view: gfx::handle::RenderTargetView<gfx_device_gl::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<gfx_device_gl::Resources, DepthFormat>,
  mouse_pos: (f64, f64),
}

impl WindowContext {
  pub fn new() -> WindowContext {
    let events_loop = glutin::EventsLoop::new();

    let window_title = glutin::WindowBuilder::new()
      .with_title("Hinterland");

    let builder = if cfg!(feature = "windowed") {
      window_title
        .with_dimensions(RESOLUTION_X, RESOLUTION_Y)
        .with_min_dimensions(RESOLUTION_X, RESOLUTION_Y)
        .with_max_dimensions(RESOLUTION_X, RESOLUTION_Y)
    } else {
      let monitor = {
        events_loop.get_available_monitors().nth(0).expect("Please enter a valid ID")
      };
      window_title.with_fullscreen(Some(monitor))
                  .with_dimensions(RESOLUTION_X, RESOLUTION_Y)
                  .with_min_dimensions(RESOLUTION_X, RESOLUTION_Y)
                  .with_max_dimensions(RESOLUTION_X, RESOLUTION_Y)
    };

    let context = glutin::ContextBuilder::new()
      .with_vsync(true)
      .with_pixel_format(24, 8)
      .with_gl(glutin::GlRequest::GlThenGles {
        opengles_version: (3, 0),
        opengl_version: (4, 1),
      });

    let (window, device, factory, rtv, dsv) =
      gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder, context, &events_loop);

    WindowContext {
      window,
      controls: None,
      events_loop,
      device,
      factory,
      render_target_view: rtv,
      depth_stencil_view: dsv,
      mouse_pos: (0.0, 0.0),
    }
  }
}

#[derive(Debug, PartialEq, Eq)]
pub enum WindowStatus {
  Open,
  Close,
}

pub trait Window<D: gfx::Device, F: gfx::Factory<D::Resources>> {
  fn swap_window(&mut self);
  fn create_buffers(&mut self, count: usize) -> Vec<D::CommandBuffer>;
  fn set_controls(&mut self, controls: controls::TilemapControls);
  fn get_viewport_size(&mut self) -> (f32, f32);
  fn get_device(&mut self) -> &mut D;
  fn get_factory(&mut self) -> &mut F;
  fn get_hidpi_factor(&mut self) -> f32;
  fn get_render_target_view(&mut self) -> gfx::handle::RenderTargetView<D::Resources, ColorFormat>;
  fn get_depth_stencil_view(&mut self) -> gfx::handle::DepthStencilView<D::Resources, DepthFormat>;
  fn poll_events(&mut self) -> WindowStatus;
}

impl Window<gfx_device_gl::Device, gfx_device_gl::Factory> for WindowContext {
  fn swap_window(&mut self) {
    use gfx::Device;
    self.window
        .swap_buffers()
        .expect("Unable to swap buffers");
    self.device.cleanup();
  }

  fn create_buffers(&mut self, count: usize) -> Vec<gfx_device_gl::CommandBuffer> {
    let mut bufs = Vec::new();
    for _ in 0..count {
      bufs.push(self.factory.create_command_buffer());
    }
    bufs
  }

  fn set_controls(&mut self, controls: controls::TilemapControls) {
    self.controls = Some(controls);
  }

  fn get_viewport_size(&mut self) -> (f32, f32) {
    (RESOLUTION_X as f32, RESOLUTION_Y as f32)
  }

  fn get_device(&mut self) -> &mut gfx_device_gl::Device {
    &mut self.device
  }

  fn get_factory(&mut self) -> &mut gfx_device_gl::Factory {
    &mut self.factory
  }

  fn get_hidpi_factor(&mut self) -> f32 {
    self.window.hidpi_factor() as f32
  }

  fn get_render_target_view(&mut self) -> gfx::handle::RenderTargetView<gfx_device_gl::Resources, ColorFormat> {
    self.render_target_view.clone()
  }

  fn get_depth_stencil_view(&mut self) -> gfx::handle::DepthStencilView<gfx_device_gl::Resources, DepthFormat> {
    self.depth_stencil_view.clone()
  }

  fn poll_events(&mut self) -> WindowStatus {
    use glutin::WindowEvent::{CursorMoved, CloseRequested, MouseInput};

    let controls = match self.controls {
      Some(ref mut c) => c,
      None => panic!("Terrain controls have not been initialized"),
    };

    let m_pos = &mut self.mouse_pos;

    let mut game_status = WindowStatus::Open;

    self.events_loop.poll_events(|event| {
      game_status = if let glutin::Event::WindowEvent { event, .. } = event {
        match event {
          glutin::WindowEvent::KeyboardInput { input, .. } => {process_keyboard_input(input, controls)},
          MouseInput { state: Pressed, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(Some(*m_pos));
            WindowStatus::Open
          }
          MouseInput { state: Released, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(None);
            WindowStatus::Open
          }
          MouseInput { state: Pressed, button: MouseButton::Right, .. } => {
            controls.mouse_right_click(Some(*m_pos));
            WindowStatus::Open
          }
          MouseInput { state: Released, button: MouseButton::Right, .. } => {
            controls.mouse_right_click(None);
            WindowStatus::Open
          }
          CursorMoved { position, .. } => {
            *m_pos = position;
            WindowStatus::Open
          }
          CloseRequested => WindowStatus::Close,
          _ => WindowStatus::Open,
        }
      } else {
        WindowStatus::Open
      };
    });
    game_status
  }
}

fn process_keyboard_input(input: glutin::KeyboardInput, controls: &mut TilemapControls) -> WindowStatus {
  match input {
    KeyboardInput { virtual_keycode: Some(Escape), .. } => WindowStatus::Close,
    KeyboardInput { state: Pressed, virtual_keycode: Some(Z), .. } => {
      controls.zoom(&Control::Negative);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Plus);
      WindowStatus::Open
    }
    KeyboardInput { state: Released, virtual_keycode: Some(Z), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Released);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(W), .. } => {
      controls.move_character(CharacterControl::Up);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::Down);
      WindowStatus::Open
    }
    KeyboardInput { state: Released, virtual_keycode: Some(W), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::YMoveStop);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(A), .. } => {
      controls.move_character(CharacterControl::Left);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::Right);
      WindowStatus::Open
    }
    KeyboardInput { state: Released, virtual_keycode: Some(A), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::XMoveStop);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(true);
      WindowStatus::Open
    },
    KeyboardInput { state: Released, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(false);
      WindowStatus::Open
    },
    KeyboardInput { state: Pressed, modifiers, .. } => {
      if modifiers.ctrl {
        controls.ctrl_pressed(true);
      }
      WindowStatus::Open
    }
    KeyboardInput { state: Released, modifiers, .. } => {
      if !modifiers.ctrl {
        controls.ctrl_pressed(false);
      }
      WindowStatus::Open
    }
  }
}

<commit_msg>Detect screen resolution with right aspect ratio<commit_after>use character::controls::CharacterControl;
use game::constants::{RESOLUTION_X, RESOLUTION_Y};
use gfx;
use gfx_app::controls::{Control, TilemapControls};
use gfx_device_gl;
use gfx_window_glutin;
use glutin;
use glutin::{GlContext, KeyboardInput, MouseButton};
use glutin::ElementState::{Pressed, Released};
use glutin::VirtualKeyCode::{Escape, Z, X, W, A, S, D, R};

pub mod init;
pub mod renderer;
pub mod system;
pub mod controls;
pub mod mouse_controls;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

pub struct WindowContext {
  window: glutin::GlWindow,
  controls: Option<controls::TilemapControls>,
  events_loop: glutin::EventsLoop,
  device: gfx_device_gl::Device,
  factory: gfx_device_gl::Factory,
  render_target_view: gfx::handle::RenderTargetView<gfx_device_gl::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<gfx_device_gl::Resources, DepthFormat>,
  mouse_pos: (f64, f64),
}

impl WindowContext {
  pub fn new() -> WindowContext {
    let events_loop = glutin::EventsLoop::new();

    let window_title = glutin::WindowBuilder::new()
      .with_title("Hinterland");

    let builder = if cfg!(feature = "windowed") {
      window_title
        .with_dimensions(RESOLUTION_X, RESOLUTION_Y)
        .with_min_dimensions(RESOLUTION_X, RESOLUTION_Y)
        .with_max_dimensions(RESOLUTION_X, RESOLUTION_Y)
    } else {
      let monitor = {
        events_loop.get_available_monitors().nth(0).expect("No monitor found")
      };
      let monitor_resolution = monitor.get_dimensions();

      let resolution = ((monitor_resolution.1 as f32 * 16.0 / 9.0) as u32, monitor_resolution.1);
      window_title.with_fullscreen(Some(monitor))
                  .with_dimensions(resolution.0, resolution.1)
                  .with_min_dimensions(resolution.0, resolution.1)
                  .with_max_dimensions(resolution.0, resolution.1)
    };

    let context = glutin::ContextBuilder::new()
      .with_vsync(true)
      .with_pixel_format(24, 8)
      .with_gl(glutin::GlRequest::GlThenGles {
        opengles_version: (3, 0),
        opengl_version: (4, 1),
      });

    let (window, device, factory, rtv, dsv) =
      gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder, context, &events_loop);

    WindowContext {
      window,
      controls: None,
      events_loop,
      device,
      factory,
      render_target_view: rtv,
      depth_stencil_view: dsv,
      mouse_pos: (0.0, 0.0),
    }
  }
}

#[derive(Debug, PartialEq, Eq)]
pub enum WindowStatus {
  Open,
  Close,
}

pub trait Window<D: gfx::Device, F: gfx::Factory<D::Resources>> {
  fn swap_window(&mut self);
  fn create_buffers(&mut self, count: usize) -> Vec<D::CommandBuffer>;
  fn set_controls(&mut self, controls: controls::TilemapControls);
  fn get_viewport_size(&mut self) -> (f32, f32);
  fn get_device(&mut self) -> &mut D;
  fn get_factory(&mut self) -> &mut F;
  fn get_hidpi_factor(&mut self) -> f32;
  fn get_render_target_view(&mut self) -> gfx::handle::RenderTargetView<D::Resources, ColorFormat>;
  fn get_depth_stencil_view(&mut self) -> gfx::handle::DepthStencilView<D::Resources, DepthFormat>;
  fn poll_events(&mut self) -> WindowStatus;
}

impl Window<gfx_device_gl::Device, gfx_device_gl::Factory> for WindowContext {
  fn swap_window(&mut self) {
    use gfx::Device;
    self.window
        .swap_buffers()
        .expect("Unable to swap buffers");
    self.device.cleanup();
  }

  fn create_buffers(&mut self, count: usize) -> Vec<gfx_device_gl::CommandBuffer> {
    let mut bufs = Vec::new();
    for _ in 0..count {
      bufs.push(self.factory.create_command_buffer());
    }
    bufs
  }

  fn set_controls(&mut self, controls: controls::TilemapControls) {
    self.controls = Some(controls);
  }

  fn get_viewport_size(&mut self) -> (f32, f32) {
    if cfg!(feature = "windowed") {
      (RESOLUTION_X as f32, RESOLUTION_Y as f32)
    } else {
      let monitor = self.events_loop.get_available_monitors().nth(0).expect("No monitor found");
      let monitor_resolution = monitor.get_dimensions();
      ((monitor_resolution.1 as f32 * 16.0 / 9.0) as f32, monitor_resolution.1 as f32)
    }
  }

  fn get_device(&mut self) -> &mut gfx_device_gl::Device {
    &mut self.device
  }

  fn get_factory(&mut self) -> &mut gfx_device_gl::Factory {
    &mut self.factory
  }

  fn get_hidpi_factor(&mut self) -> f32 {
    self.window.hidpi_factor() as f32
  }

  fn get_render_target_view(&mut self) -> gfx::handle::RenderTargetView<gfx_device_gl::Resources, ColorFormat> {
    self.render_target_view.clone()
  }

  fn get_depth_stencil_view(&mut self) -> gfx::handle::DepthStencilView<gfx_device_gl::Resources, DepthFormat> {
    self.depth_stencil_view.clone()
  }

  fn poll_events(&mut self) -> WindowStatus {
    use glutin::WindowEvent::{CursorMoved, CloseRequested, MouseInput};

    let controls = match self.controls {
      Some(ref mut c) => c,
      None => panic!("Terrain controls have not been initialized"),
    };

    let m_pos = &mut self.mouse_pos;

    let mut game_status = WindowStatus::Open;

    self.events_loop.poll_events(|event| {
      game_status = if let glutin::Event::WindowEvent { event, .. } = event {
        match event {
          glutin::WindowEvent::KeyboardInput { input, .. } => {process_keyboard_input(input, controls)},
          MouseInput { state: Pressed, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(Some(*m_pos));
            WindowStatus::Open
          }
          MouseInput { state: Released, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(None);
            WindowStatus::Open
          }
          MouseInput { state: Pressed, button: MouseButton::Right, .. } => {
            controls.mouse_right_click(Some(*m_pos));
            WindowStatus::Open
          }
          MouseInput { state: Released, button: MouseButton::Right, .. } => {
            controls.mouse_right_click(None);
            WindowStatus::Open
          }
          CursorMoved { position, .. } => {
            *m_pos = position;
            WindowStatus::Open
          }
          CloseRequested => WindowStatus::Close,
          _ => WindowStatus::Open,
        }
      } else {
        WindowStatus::Open
      };
    });
    game_status
  }
}

fn process_keyboard_input(input: glutin::KeyboardInput, controls: &mut TilemapControls) -> WindowStatus {
  match input {
    KeyboardInput { virtual_keycode: Some(Escape), .. } => WindowStatus::Close,
    KeyboardInput { state: Pressed, virtual_keycode: Some(Z), .. } => {
      controls.zoom(&Control::Negative);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Plus);
      WindowStatus::Open
    }
    KeyboardInput { state: Released, virtual_keycode: Some(Z), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Released);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(W), .. } => {
      controls.move_character(CharacterControl::Up);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::Down);
      WindowStatus::Open
    }
    KeyboardInput { state: Released, virtual_keycode: Some(W), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::YMoveStop);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(A), .. } => {
      controls.move_character(CharacterControl::Left);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::Right);
      WindowStatus::Open
    }
    KeyboardInput { state: Released, virtual_keycode: Some(A), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::XMoveStop);
      WindowStatus::Open
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(true);
      WindowStatus::Open
    },
    KeyboardInput { state: Released, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(false);
      WindowStatus::Open
    },
    KeyboardInput { state: Pressed, modifiers, .. } => {
      if modifiers.ctrl {
        controls.ctrl_pressed(true);
      }
      WindowStatus::Open
    }
    KeyboardInput { state: Released, modifiers, .. } => {
      if !modifiers.ctrl {
        controls.ctrl_pressed(false);
      }
      WindowStatus::Open
    }
  }
}

<|endoftext|>


<commit_before>use std::fmt::{Show,Formatter};
use std::fmt;

pub fn as_byte_slice<'a, T>(x: &'a T) -> &'a [u8] {
    unsafe {
        ::std::slice::raw::buf_as_slice(
            x as *_ as *u8,
            ::std::mem::size_of::<T>(),
            |v| ::std::mem::transmute(v)
        )
    }
}

pub type GossipResult<T> = Result<T, GossipError>;

pub enum Error {
    NotImplemented
}

macro_rules! unimplemented(
    () => (
        return Err(GossipError::new("not implemented".to_owned(), None))
    )
)

/// A gossip error represents an error that happens typically during any I/O.
///
/// FIXME: Instead of a useless `code` property, it might be better to have
///        that be an enum instead. With things like `FailedToJoin`.
pub struct GossipError {
    message: String,
    error: Option<Error>
}

impl GossipError {
    pub fn new(message: String, error: Option<Error>) -> GossipError {
        GossipError {
            message: message,
            error: error
        }
    }
}

impl Show for GossipError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}
<commit_msg>Updated error handling<commit_after>use std::fmt::{Show,Formatter};
use std::fmt;
use std::io;

pub fn as_byte_slice<'a, T>(x: &'a T) -> &'a [u8] {
    unsafe {
        ::std::slice::raw::buf_as_slice(
            x as *_ as *u8,
            ::std::mem::size_of::<T>(),
            |v| ::std::mem::transmute(v)
        )
    }
}

pub type GossipResult<T> = Result<T, GossipError>;

/// Convert an IoError to a GossipError
pub fn to_gossip(io: io::IoError) -> GossipError {
    GossipError {
        kind: IoError(io.clone()),
        desc: StaticDescription(io.desc)
    }
}

/// A gossip error represents an error that happens typically during any I/O.
#[deriving(Show)]
pub struct GossipError {
    kind: GossipErrorKind,
    desc: GossipErrorDescription,
}

#[deriving(Show)]
pub enum GossipErrorDescription {
    StaticDescription(&'static str),
    BoxedDescription(String)
}

#[deriving(Show)]
pub enum GossipErrorKind {
    IoError(io::IoError)
}

impl GossipError {
    pub fn new<T: Show>(desc: T, kind: GossipErrorKind) -> GossipError {
        GossipError {
            desc: BoxedDescription(desc.to_str()),
            kind: kind
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use std::{ptr, mem};

use epoch::{self, Atomic, Owned};

/// Treiber's lock-free stack.
///
/// Usable with any number of producers and consumers.
#[derive(Debug)]
pub struct TreiberStack<T> {
    head: Atomic<Node<T>>,
}

#[derive(Debug)]
struct Node<T> {
    data: T,
    next: Atomic<Node<T>>,
}

impl<T> Node<T> {
    /// Deallocates the memory for this node without executing T's destructor.
    fn finalize(n: Node<T>) {
        mem::forget(n.data);
    }
}

impl<T> TreiberStack<T> {
    /// Create a new, empty stack.
    pub fn new() -> TreiberStack<T> {
        TreiberStack {
            head: Atomic::null(),
        }
    }

    /// Push `t` on top of the stack.
    pub fn push(&self, t: T) {
        let mut n = Owned::new(Node {
            data: t,
            next: Atomic::null(),
        });
        let guard = epoch::pin();
        loop {
            let head = self.head.load(Relaxed, &guard);
            n.next.store(head, Relaxed);
            match self.head.compare_and_set(head, n, Release, &guard) {
                Ok(_) => break,
                Err(e) => n = e.new,
            }
        }
    }

    /// Attempt to pop the top element of the stack.
    ///
    /// Returns `None` if the stack is observed to be empty.
    pub fn try_pop(&self) -> Option<T> {
        let guard = epoch::pin();
        loop {
            let head_shared = self.head.load(Acquire, &guard);
            match unsafe { head_shared.as_ref() } {
                Some(head) => {
                    let next = head.next.load(Relaxed, &guard);
                    if self.head
                        .compare_and_set(head_shared, next, Release, &guard)
                        .is_ok()
                    {
                        unsafe {
                            guard.defer(move || {
                                Node::<T>::finalize(*head_shared.into_owned().into_box())
                            } );
                            return Some(ptr::read(&(*head).data));
                        }
                    }
                }
                None => return None,
            }
        }
    }

    /// Check if this queue is empty.
    pub fn is_empty(&self) -> bool {
        let guard = epoch::pin();
        self.head.load(Acquire, &guard).is_null()
    }
}

impl<T> Drop for TreiberStack<T> {
    fn drop(&mut self) {
        while self.try_pop().is_some() {}
    }
}

impl<T> Default for TreiberStack<T> {
    fn default() -> Self {
        TreiberStack::new()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ::{thread, epoch};
    use std::sync::atomic::{Ordering, AtomicUsize};

    #[test]
    fn is_empty() {
        let q: TreiberStack<i64> = TreiberStack::new();
        assert!(q.is_empty());
        q.push(20);
        q.push(20);
        assert!(!q.is_empty());
        assert!(!q.is_empty());
        assert!(q.try_pop().is_some());
        assert!(q.try_pop().is_some());
        assert!(q.is_empty());
        q.push(25);
        assert!(!q.is_empty());
    }

    #[test]
    fn no_double_drop() {
        static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);

        struct Dropper;

        impl Drop for Dropper {
            fn drop(&mut self) {
                DROP_COUNT.fetch_add(1, Ordering::SeqCst);
            }
        }

        const N_THREADS: usize = 8;
        thread::scope(|s| {
            for _ in 0..N_THREADS {
                s.spawn(|| {
                    let q: TreiberStack<Dropper> = TreiberStack::new();
                    for _ in 0..4 { q.push(Dropper); }
                    drop(q);
                    epoch::pin().flush();
                } );
            }
        } );

        assert!(DROP_COUNT.load(Ordering::SeqCst) == N_THREADS * 4);
    }
}
<commit_msg>Use ManuallyDrop in TreiberStack<commit_after>use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use std::mem::ManuallyDrop;
use std::ptr;

use epoch::{self, Atomic, Owned};

/// Treiber's lock-free stack.
///
/// Usable with any number of producers and consumers.
#[derive(Debug)]
pub struct TreiberStack<T> {
    head: Atomic<Node<T>>,
}

#[derive(Debug)]
struct Node<T> {
    data: ManuallyDrop<T>,
    next: Atomic<Node<T>>,
}

impl<T> TreiberStack<T> {
    /// Create a new, empty stack.
    pub fn new() -> TreiberStack<T> {
        TreiberStack {
            head: Atomic::null(),
        }
    }

    /// Push `t` on top of the stack.
    pub fn push(&self, t: T) {
        let mut n = Owned::new(Node {
            data: ManuallyDrop::new(t),
            next: Atomic::null(),
        });
        let guard = epoch::pin();
        loop {
            let head = self.head.load(Relaxed, &guard);
            n.next.store(head, Relaxed);
            match self.head.compare_and_set(head, n, Release, &guard) {
                Ok(_) => break,
                Err(e) => n = e.new,
            }
        }
    }

    /// Attempt to pop the top element of the stack.
    ///
    /// Returns `None` if the stack is observed to be empty.
    pub fn try_pop(&self) -> Option<T> {
        let guard = epoch::pin();
        loop {
            let head_shared = self.head.load(Acquire, &guard);
            match unsafe { head_shared.as_ref() } {
                Some(head) => {
                    let next = head.next.load(Relaxed, &guard);
                    if self.head
                        .compare_and_set(head_shared, next, Release, &guard)
                        .is_ok()
                    {
                        unsafe {
                            guard.defer(move || drop(head_shared.into_owned()) );
                            return Some(ManuallyDrop::into_inner(ptr::read(&(*head).data)));
                        }
                    }
                }
                None => return None,
            }
        }
    }

    /// Check if this queue is empty.
    pub fn is_empty(&self) -> bool {
        let guard = epoch::pin();
        self.head.load(Acquire, &guard).is_null()
    }
}

impl<T> Drop for TreiberStack<T> {
    fn drop(&mut self) {
        while self.try_pop().is_some() {}
    }
}

impl<T> Default for TreiberStack<T> {
    fn default() -> Self {
        TreiberStack::new()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ::{thread, epoch};
    use std::sync::atomic::{Ordering, AtomicUsize};

    #[test]
    fn is_empty() {
        let q: TreiberStack<i64> = TreiberStack::new();
        assert!(q.is_empty());
        q.push(20);
        q.push(20);
        assert!(!q.is_empty());
        assert!(!q.is_empty());
        assert!(q.try_pop().is_some());
        assert!(q.try_pop().is_some());
        assert!(q.is_empty());
        q.push(25);
        assert!(!q.is_empty());
    }

    #[test]
    fn no_double_drop() {
        static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);

        struct Dropper;

        impl Drop for Dropper {
            fn drop(&mut self) {
                DROP_COUNT.fetch_add(1, Ordering::SeqCst);
            }
        }

        const N_THREADS: usize = 8;
        thread::scope(|s| {
            for _ in 0..N_THREADS {
                s.spawn(|| {
                    let q: TreiberStack<Dropper> = TreiberStack::new();
                    for _ in 0..4 { q.push(Dropper); }
                    drop(q);
                    epoch::pin().flush();
                } );
            }
        } );

        assert!(DROP_COUNT.load(Ordering::SeqCst) == N_THREADS * 4);
    }
}
<|endoftext|>


<commit_before>
extern crate rand;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use file_stream_iter::FileStream;
use std::io::Error;
use tftp_specific::PacketType;
use std::str::FromStr;
use std::net::AddrParseError;
use std::error;

pub struct EndPoint{
    local_connection : SocketAddrV4,
    remote_connection : SocketAddrV4
}

impl EndPoint{

    pub fn new(remote : &str) -> Result<EndPoint, AddrParseError>{

        let ipv4 = try!(get_ip_from(remote));
        Ok(EndPoint{
            local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 6900),
            remote_connection : SocketAddrV4::new(ipv4, 9990)
        })
    }

    fn start_listen(){

    }

    pub fn recv(&mut self) -> Result<(), Error> {
        // Define the local connection information
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO we want to use port 69 here
        //let connection = SocketAddrV4::new(ip, 6900);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Read from the socket
        let mut buf = [0u8; 516]; //UDP packet is 516 bytes
        let (amt, src) = try!(socket.recv_from(&mut buf));
        match buf[1]{
            3 =>{
                let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                let block_size = amt - 4;
                println!("{:?}", block_size);
                if block_size < 512{
                    println!("recvr recvd: {:?}", &buf[0 .. amt]);
                    println!("Last block of the file received");
                }
                //send ACK

                let low = block_num & 0x00FF;
                let high = (block_num & 0xFF00) >> 8;

                socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);
            },
            _ => {}
        }

        Ok(())
    }

    pub fn send(&mut self) -> Result<(), Error> {
        // Define the local connection (to send the data from)
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO generate port # using rand
        //let connection = SocketAddrV4::new(ip, 9992);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Define the remote connection (to send the data to)
        //let connection2 = SocketAddrV4::new(ip, 6900);

        // Send data via the socket
        let mut fs = FileStream::new("/home/abhi/code/rust/fei/target/debug/foo.txt".to_string()).unwrap();
        let (buf, num_bytes_read) = fs.next().unwrap();
        let mut v = Vec::with_capacity(num_bytes_read + 4);
        v.push(0);
        v.push(3);
        v.push(0xFF);
        let mut cnt = 0xFF;
        v.push(cnt);
        v.extend_from_slice(&buf[0..num_bytes_read]);
        try!(socket.send_to(v.as_slice(), self.remote_connection));

        let mut buf  = [0; 10];
        socket.recv_from(&mut buf);

        println!("sender recvd {:?}", buf);
        Ok(())
    }

    fn send_file(&mut self, filename : &str) {

    }

    fn create_rrq_wrq_packet(p_type: PacketType, file_name: String, mode : &'static str)->Vec<u8>{
        let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
        v.push(0);
        v.push(p_type as u8);
        v.extend(file_name.as_bytes());
        v.push(0);//zero terminator
        v.extend(mode.as_bytes());
        v.push(0);//zero terminator
        v
    }
}

fn get_ip_from(ip : &str) -> Result<Ipv4Addr, AddrParseError>{
    Ipv4Addr::from_str(ip)
}

<commit_msg>Add a get method to fetch files from the remote server<commit_after>
extern crate rand;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use file_stream_iter::FileStream;
use std::io::Error;
use tftp_specific::PacketType;
use std::str::FromStr;
use std::net::AddrParseError;
use std::error;

pub struct EndPoint{
    local_connection : SocketAddrV4,
    remote_connection : SocketAddrV4
}

impl EndPoint{

    pub fn new(remote : &str) -> Result<EndPoint, AddrParseError>{

        let ipv4 = try!(get_ip_from(remote));
        Ok(EndPoint{
            local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 6900),
            remote_connection : SocketAddrV4::new(ipv4, 9990)
        })
    }

    fn start_listen(){

    }

    pub fn recv(&mut self) -> Result<(), Error> {
        // Define the local connection information
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO we want to use port 69 here
        //let connection = SocketAddrV4::new(ip, 6900);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Read from the socket
        let mut buf = [0u8; 516]; //UDP packet is 516 bytes
        let (amt, src) = try!(socket.recv_from(&mut buf));
        match buf[1]{
            3 =>{
                let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                let block_size = amt - 4;
                println!("{:?}", block_size);
                if block_size < 512{
                    println!("recvr recvd: {:?}", &buf[0 .. amt]);
                    println!("Last block of the file received");
                }
                //send ACK

                let low = block_num & 0x00FF;
                let high = (block_num & 0xFF00) >> 8;

                socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);
            },
            _ => {}
        }

        Ok(())
    }

    pub fn send(&mut self) -> Result<(), Error> {
        // Define the local connection (to send the data from)
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO generate port # using rand
        //let connection = SocketAddrV4::new(ip, 9992);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Define the remote connection (to send the data to)
        //let connection2 = SocketAddrV4::new(ip, 6900);

        // Send data via the socket
        let mut fs = FileStream::new("/home/abhi/code/rust/fei/target/debug/foo.txt".to_string()).unwrap();
        let (buf, num_bytes_read) = fs.next().unwrap();
        let mut v = Vec::with_capacity(num_bytes_read + 4);
        v.push(0);
        v.push(3);
        v.push(0xFF);
        let mut cnt = 0xFF;
        v.push(cnt);
        v.extend_from_slice(&buf[0..num_bytes_read]);
        try!(socket.send_to(v.as_slice(), self.remote_connection));

        let mut buf  = [0; 10];
        socket.recv_from(&mut buf);

        println!("sender recvd {:?}", buf);
        Ok(())
    }

    fn send_file(&mut self, filename : &str) {

    }

    fn create_rrq_wrq_packet(&self, p_type: PacketType, file_name: &str, mode : &'static str)->Vec<u8>{
        let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
        v.push(0);
        v.push(p_type as u8);
        v.extend(file_name.as_bytes());
        v.push(0);//zero terminator
        v.extend(mode.as_bytes());
        v.push(0);//zero terminator
        v
    }

    fn get(&mut self, files : &[&str], mode : &'static str){
        let socket = try!(UdpSocket::bind(self.local_connection));
        let mut buf  = [0; 516];
        for file in files{
            //start with a RRQ
            let packet = self.create_rrq_wrq_packet(PacketType::RRQ, file, mode);
            try!(socket.send_to(packet.as_slice(), self.remote_connection));

            let (amt, src) = try!(socket.recv_from(&mut buf));
            match buf[1]{
                3 =>{
                    let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                    let block_size = amt - 4;
                    println!("{:?}", block_size);
                    if block_size < 512{
                        println!("recvr recvd: {:?}", &buf[0 .. amt]);
                        println!("Last block of the file received");
                    }
                    //send ACK

                    let low = block_num & 0x00FF;
                    let high = (block_num & 0xFF00) >> 8;

                    socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);
                },
                _ => {}
            }

        }
    }
}

fn get_ip_from(ip : &str) -> Result<Ipv4Addr, AddrParseError>{
    Ipv4Addr::from_str(ip)
}

<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Helpers for reading directory structures from the local filesystem.

use std::sync;
use std::os::{last_os_error};
use std::io::{TypeDirectory};
use std::io::fs::{lstat};

use std::c_str::CString;
use libc::funcs::posix88::dirent;
use libc::types::common::posix88::{DIR,dirent_t};
use libc::types::os::arch::c95::c_char;
use libc::{c_int};

pub struct DirIterator {
  fd: *DIR,
}

impl DirIterator {
  pub fn new(path: Path) -> Result<DirIterator, String> {
    let fd = path.with_c_str(|c_str| unsafe { dirent::opendir(c_str) });

    if fd as int > 0 { Ok(DirIterator{fd:fd}) }
    else { Err(last_os_error()) }
  }

  fn read(&mut self) -> String {
    extern {
      fn rust_dirent_t_size() -> c_int;
      fn rust_list_dir_val(ptr: *mut dirent_t) -> *c_char;
    }

    let mut entry_ptr = 0 as *mut dirent_t;

    let size = unsafe { rust_dirent_t_size() };
    let mut buf = Vec::<u8>::with_capacity(size as uint);
    let buf_ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t;

    let retval = unsafe {
      dirent::readdir_r(self.fd, buf_ptr, &mut entry_ptr) };

    if retval == 0 && !entry_ptr.is_null() {
      let cstr = unsafe { CString::new(rust_list_dir_val(entry_ptr), false) };
      cstr.as_str().expect("Path not UTF8.").clone().into_string()
    } else { "".to_owned() }

  }

}

impl Drop for DirIterator {
  fn drop(&mut self) {
    unsafe {
      dirent::closedir(self.fd)
    };
  }
}

impl Iterator<String> for DirIterator {
  fn next(&mut self) -> Option<String> {
    let name = self.read();
    if name.len() == 0 { None }
    else { Some(name) }
  }
}

pub trait PathHandler<D> {
  fn handlePath(&mut self, D, Path) -> Option<D>;
}

pub fn iterateRecursively<P: Send + Clone, W: PathHandler<P> + Send + Clone>
  (root: (Path, P), worker: &mut W)
{
  let threads = 10;

  let queue = sync::Arc::new(sync::Mutex::new(vec!(root)));
  let in_progress = sync::Arc::new(sync::Mutex::new(0));
  let done = sync::Arc::new(sync::Mutex::new(0));

  for _ in range(0u, threads) {
    let t_in_progress = in_progress.clone();
    let t_queue = queue.clone();
    let t_done = done.clone();
    let t_worker_imm = worker.clone();

    spawn(proc() {
      let mut t_worker = t_worker_imm.clone();

      loop {
        let mut next = None;
        let mut task_count = 0;
        {
          let mut guarded_tasks = t_in_progress.lock();
          let mut guarded_queue = t_queue.lock();
          if guarded_queue.len() > 0 {
            next = guarded_queue.pop();
            *guarded_tasks += 1;
          }
          task_count = *guarded_tasks;
        }

        match next {
          None => {
            if task_count == 0 {
              break;  // Stop when all workers are idle
            }
          },
          Some((root_, payload)) => {
            let mut root = root_;
            let res = DirIterator::new(root.clone());
            if res.is_ok() {
              let mut it = res.unwrap();
              for file in it {
                if file != ".".into_string() && file != "..".into_string() {
                  let rel_path = Path::new(file);
                  root.push(rel_path);
                  let dir_opt = t_worker.handlePath(payload.clone(), root.clone());
                  if dir_opt.is_some() {
                    let mut guarded_queue = t_queue.lock();
                    guarded_queue.push((root.clone(), dir_opt.unwrap()));
                  }
                  root.pop();
                }
              }
            }

            // Tell waiting threads that will not produce more
            {
              let mut guarded_tasks = t_in_progress.lock();
              *guarded_tasks -= 1;
            }
          }
        }
      }

      // Loop is over, thread is stopping
      {
        let mut guarded_tasks_done = t_done.lock();
        *guarded_tasks_done += 1;
        guarded_tasks_done.cond.signal();
      }
    });
  }

  // Wait for threads to complete
  {
    let guarded_done = done.lock();
    while *guarded_done < threads {
      guarded_done.cond.wait();
    }
  }
}

struct PrintPathHandler;

impl Clone for PrintPathHandler {
  fn clone(&self) -> PrintPathHandler { PrintPathHandler }
}

impl PathHandler<()> for PrintPathHandler {
  fn handlePath(&mut self, _: (), path: Path) -> Option<()> {
    let filename_opt = path.filename_str();
    println!("{}", path.display());
    match filename_opt {
      Some(".") | Some("..") | None => None,
      Some(_) =>
      match lstat(&path) {
        Ok(ref st) if st.kind == TypeDirectory => Some(()),
        _ => None,
      }
    }
  }
}
<commit_msg>Use as_mut_ptr() for Vec directory.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Helpers for reading directory structures from the local filesystem.

use std::sync;
use std::os::{last_os_error};
use std::io::{TypeDirectory};
use std::io::fs::{lstat};

use std::c_str::CString;
use libc::funcs::posix88::dirent;
use libc::types::common::posix88::{DIR,dirent_t};
use libc::types::os::arch::c95::c_char;
use libc::{c_int};

pub struct DirIterator {
  fd: *DIR,
}

impl DirIterator {
  pub fn new(path: Path) -> Result<DirIterator, String> {
    let fd = path.with_c_str(|c_str| unsafe { dirent::opendir(c_str) });

    if fd as int > 0 { Ok(DirIterator{fd:fd}) }
    else { Err(last_os_error()) }
  }

  fn read(&mut self) -> String {
    extern {
      fn rust_dirent_t_size() -> c_int;
      fn rust_list_dir_val(ptr: *mut dirent_t) -> *c_char;
    }

    let mut entry_ptr = 0 as *mut dirent_t;

    let size = unsafe { rust_dirent_t_size() };
    let mut buf = Vec::<u8>::with_capacity(size as uint);
    let buf_ptr = buf.as_mut_ptr() as *mut dirent_t;

    let retval = unsafe { dirent::readdir_r(self.fd, buf_ptr, &mut entry_ptr) };

    if retval == 0 && !entry_ptr.is_null() {
      let cstr = unsafe { CString::new(rust_list_dir_val(entry_ptr), false) };
      cstr.as_str().expect("Path not UTF8.").clone().into_string()
    } else { "".to_owned() }

  }

}

impl Drop for DirIterator {
  fn drop(&mut self) {
    unsafe {
      dirent::closedir(self.fd)
    };
  }
}

impl Iterator<String> for DirIterator {
  fn next(&mut self) -> Option<String> {
    let name = self.read();
    if name.len() == 0 { None }
    else { Some(name) }
  }
}

pub trait PathHandler<D> {
  fn handlePath(&mut self, D, Path) -> Option<D>;
}

pub fn iterateRecursively<P: Send + Clone, W: PathHandler<P> + Send + Clone>
  (root: (Path, P), worker: &mut W)
{
  let threads = 10;

  let queue = sync::Arc::new(sync::Mutex::new(vec!(root)));
  let in_progress = sync::Arc::new(sync::Mutex::new(0));
  let done = sync::Arc::new(sync::Mutex::new(0));

  for _ in range(0u, threads) {
    let t_in_progress = in_progress.clone();
    let t_queue = queue.clone();
    let t_done = done.clone();
    let t_worker_imm = worker.clone();

    spawn(proc() {
      let mut t_worker = t_worker_imm.clone();

      loop {
        let mut next = None;
        let mut task_count = 0;
        {
          let mut guarded_tasks = t_in_progress.lock();
          let mut guarded_queue = t_queue.lock();
          if guarded_queue.len() > 0 {
            next = guarded_queue.pop();
            *guarded_tasks += 1;
          }
          task_count = *guarded_tasks;
        }

        match next {
          None => {
            if task_count == 0 {
              break;  // Stop when all workers are idle
            }
          },
          Some((root_, payload)) => {
            let mut root = root_;
            let res = DirIterator::new(root.clone());
            if res.is_ok() {
              let mut it = res.unwrap();
              for file in it {
                if file != ".".into_string() && file != "..".into_string() {
                  let rel_path = Path::new(file);
                  root.push(rel_path);
                  let dir_opt = t_worker.handlePath(payload.clone(), root.clone());
                  if dir_opt.is_some() {
                    let mut guarded_queue = t_queue.lock();
                    guarded_queue.push((root.clone(), dir_opt.unwrap()));
                  }
                  root.pop();
                }
              }
            }

            // Tell waiting threads that will not produce more
            {
              let mut guarded_tasks = t_in_progress.lock();
              *guarded_tasks -= 1;
            }
          }
        }
      }

      // Loop is over, thread is stopping
      {
        let mut guarded_tasks_done = t_done.lock();
        *guarded_tasks_done += 1;
        guarded_tasks_done.cond.signal();
      }
    });
  }

  // Wait for threads to complete
  {
    let guarded_done = done.lock();
    while *guarded_done < threads {
      guarded_done.cond.wait();
    }
  }
}

struct PrintPathHandler;

impl Clone for PrintPathHandler {
  fn clone(&self) -> PrintPathHandler { PrintPathHandler }
}

impl PathHandler<()> for PrintPathHandler {
  fn handlePath(&mut self, _: (), path: Path) -> Option<()> {
    let filename_opt = path.filename_str();
    println!("{}", path.display());
    match filename_opt {
      Some(".") | Some("..") | None => None,
      Some(_) =>
      match lstat(&path) {
        Ok(ref st) if st.kind == TypeDirectory => Some(()),
        _ => None,
      }
    }
  }
}
<|endoftext|>


<commit_before>//! Types for Vec-based storage with stack-like pushable states.

use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::convert::From;
use std::default::Default;
use std::ops::{Deref, DerefMut, Index, Range, RangeFrom, RangeFull, RangeTo};

/// Vec-like type with support for saving and restoring states via stack-like
/// operations
///
///
#[derive(Clone)]
pub struct SplitVec<T> {
    data: Vec<T>,
    splits: Vec<usize>
}

impl<T> SplitVec<T> {

    /// Create a new, empty SplitVec instance.
    #[inline]
    pub fn new() -> Self {
        SplitVec{data: Vec::new(), splits: Vec::new()}
    }

    /// Create a new, empty SplitVec instance with space for the specified
    /// number of entries.
    #[inline]
    pub fn with_capacity(data_capacity: usize, splits_capacity: usize) -> Self {
        SplitVec{data: Vec::with_capacity(data_capacity), splits: Vec::with_capacity(splits_capacity)}
    }

    /// Determine the offset of the first item in the current state.
    #[inline]
    fn offset(&self) -> usize {
        self.splits.last().cloned().unwrap_or_else(|| 0)
    }

    /// Mark a split above the current working state.
    ///
    /// This creates a new, empty state at the top of the `SplitVec`'s stack;
    /// you can use `pop_state` to return to the previous state or
    /// `pop_and_merge_states` to merge the current state with the
    /// previous one.
    #[inline]
    pub fn push_state(&mut self) {
        self.splits.push(self.data.len());
    }

    /// Mark a split above the current working state, then copy the contents of
    /// that state into the new working area.
    pub fn push_and_copy_state(&mut self) where T: Copy {
        let ofs = self.offset();
        let count = self.len();
        self.push_state();
        self.data.reserve(count);
        unsafe {
            let src = self.data.as_ptr().offset(ofs as isize);
            let dst = self.data.as_mut_ptr().offset((ofs + count) as isize);
            ptr::copy_nonoverlapping(src,
                                     dst,
                                     count);
            self.data.set_len(ofs + 2 * count);
        }
    }

    /// Restore the most-recently-pushed state, discarding all data added to
    /// the working vector since the last call to `push_state`.
    #[inline]
    pub fn pop_state(&mut self) {
        self.data.truncate(self.splits.pop().expect("Call to `pop_state` without prior matching `push_state` call"));
    }

    /// Remove the split between the current and previous states; this has the
    /// effect of merging their contents into the previous state.
    ///
    /// Calling this method will have no effect if no prior state exists.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// s.extend_from_slice(&[4, 5, 6]);
    /// assert_eq!(&*s, &[4, 5, 6]);
    ///
    /// s.pop_and_merge_states();
    /// assert_eq!(&*s, &[1, 2, 3, 4, 5, 6]);
    /// # }
    /// ```
    #[inline]
    pub fn pop_and_merge_states(&mut self) {
        self.splits.pop();
    }

    /// Get the number of items in the working state.
    #[inline]
    pub fn len(&self) -> usize {
        self.data.len() - self.offset()
    }

    /// Truncate the working state to at most a given number of elements.
    #[inline]
    pub fn truncate(&mut self, len: usize) {
        let ofs = self.offset();
        self.data.truncate(ofs + len)
    }

    /// Push an item onto the end of the working state.
    pub fn push(&mut self, value: T) {
        self.data.push(value)
    }

    /// Remove the top-most item from the working state and return it.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::new();
    /// assert_eq!(None, s.pop());
    ///
    /// s.extend_from_slice(&[1, 2, 3]);
    /// assert_eq!(Some(3), s.pop());
    /// # }
    /// ```
    ///
    /// `pop` works only within the current state, and will return `None` if the
    /// current state is empty even if a prior state is not:
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// assert_eq!(None, s.pop());
    /// # }
    /// ```
    pub fn pop(&mut self) -> Option<T> {
        if self.len() > 0 { self.data.pop() }
        else { None }
    }

    /// Extend the current working state from a slice.
    #[inline]
    pub fn extend_from_slice<'a>(&mut self, slice: &'a [T]) where T: Copy {
        self.data.extend_from_slice(slice)
    }

    /// Get a reference to the current working state as a slice.
    #[inline]
    pub fn as_slice(&self) -> &[T] {
        self
    }

    /// Remove adjacent duplicates in the working state.
    pub fn dedup(&mut self) where T: PartialEq {
        unsafe {
            let ofs = self.offset();
            let ln = self.data.len();
            if ln <= ofs {
                return;
            }

            let p = self.data.as_mut_ptr();
            let mut r: usize = 1 + ofs;
            let mut w: usize = 1 + ofs;

            while r < ln {
                let p_r = p.offset(r as isize);
                let p_wm1 = p.offset((w - 1) as isize);
                if *p_r != *p_wm1 {
                    if r != w {
                        let p_w = p_wm1.offset(1);
                        mem::swap(&mut *p_r, &mut *p_w);
                    }
                    w += 1;
                }
                r += 1;
            }

            self.truncate(w - ofs);
        }
    }

    /// Iterate over all states contained within the SplitVec.
    ///
    /// The final state is guaranteed to be the current working state.
    pub fn iter_states<'a>(&'a self) -> StateIter<'a, T> {
        StateIter{splits_iter: self.splits.iter(), data: &self.data[..], last_split: Some(0)}
    }
}

/// Iterator over the states of a SplitVec as slices.
///
/// Instances of `StateIter` are obtained by calling `iter_states` on
/// a [`SplitVec`](struct.SplitVec.html).
pub struct StateIter<'a,T> where T: 'a {
    splits_iter: slice::Iter<'a,usize>,
    data: &'a [T],
    last_split: Option<usize>
}

impl<'a, T: 'a> Iterator for StateIter<'a, T> {
    type Item = &'a [T];
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(start) = self.last_split {
            if let Some(end) = self.splits_iter.next() {
                self.last_split = Some(*end);
                Some(&self.data[start..*end])
            } else {
                self.last_split = None;
                Some(&self.data[start..])
            }
        } else { None }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.splits_iter.size_hint()
    }
}

use itertools::Itertools;
impl<T> fmt::Debug for SplitVec<T> where T: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]",
               self.iter_states().map(|s| s.iter().map(|ref elt| format!("{:?}", elt)).join(", "))
               .join(" | "))
    }
}

impl<T> From<Vec<T>> for SplitVec<T> {
    fn from(v: Vec<T>) -> Self {
        SplitVec{data: v, splits: Vec::new()}
    }
}

impl<'a,T> From<&'a [T]> for SplitVec<T> where T: Clone {
    fn from(s: &'a [T]) -> Self {
        SplitVec{data: s.into(), splits: Vec::new()}
    }
}

impl<T> Default for SplitVec<T> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Extend<T> for SplitVec<T> {
    fn extend<I>(&mut self, iter: I) where I: IntoIterator<Item=T> {
        self.data.extend(iter);
    }
}

impl<T> Deref for SplitVec<T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        let o = self.offset();
        &self.data[o..]
    }
}

impl<T> DerefMut for SplitVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let o = self.offset();
        &mut self.data[o..]
    }
}

impl<T> Index<usize> for SplitVec<T> {
    type Output = T;
    #[inline]
    fn index<'a>(&'a self, idx: usize) -> &'a T {
        let o = self.offset();
        &self.data[idx + o]
    }
}

impl<T> Index<Range<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: Range<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..(o + r.end)]
    }
}
impl<T> Index<RangeFrom<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeFrom<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..]
    }
}
impl<T> Index<RangeTo<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeTo<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[..(o + r.end)]
    }
}
impl<T> Index<RangeFull> for SplitVec<T> {
    type Output = [T];
    #[inline(always)]
    fn index<'a>(&'a self, _: RangeFull) -> &'a [T] {
        &self.data[..]
    }
}
<commit_msg>util/splitvec: add AsRef/AsMut impls for SplitVec<commit_after>//! Types for Vec-based storage with stack-like pushable states.

use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::convert::From;
use std::default::Default;
use std::ops::{Deref, DerefMut, Index, Range, RangeFrom, RangeFull, RangeTo};

/// Vec-like type with support for saving and restoring states via stack-like
/// operations
///
///
#[derive(Clone)]
pub struct SplitVec<T> {
    data: Vec<T>,
    splits: Vec<usize>
}

impl<T> SplitVec<T> {

    /// Create a new, empty SplitVec instance.
    #[inline]
    pub fn new() -> Self {
        SplitVec{data: Vec::new(), splits: Vec::new()}
    }

    /// Create a new, empty SplitVec instance with space for the specified
    /// number of entries.
    #[inline]
    pub fn with_capacity(data_capacity: usize, splits_capacity: usize) -> Self {
        SplitVec{data: Vec::with_capacity(data_capacity), splits: Vec::with_capacity(splits_capacity)}
    }

    /// Determine the offset of the first item in the current state.
    #[inline]
    fn offset(&self) -> usize {
        self.splits.last().cloned().unwrap_or_else(|| 0)
    }

    /// Mark a split above the current working state.
    ///
    /// This creates a new, empty state at the top of the `SplitVec`'s stack;
    /// you can use `pop_state` to return to the previous state or
    /// `pop_and_merge_states` to merge the current state with the
    /// previous one.
    #[inline]
    pub fn push_state(&mut self) {
        self.splits.push(self.data.len());
    }

    /// Mark a split above the current working state, then copy the contents of
    /// that state into the new working area.
    pub fn push_and_copy_state(&mut self) where T: Copy {
        let ofs = self.offset();
        let count = self.len();
        self.push_state();
        self.data.reserve(count);
        unsafe {
            let src = self.data.as_ptr().offset(ofs as isize);
            let dst = self.data.as_mut_ptr().offset((ofs + count) as isize);
            ptr::copy_nonoverlapping(src,
                                     dst,
                                     count);
            self.data.set_len(ofs + 2 * count);
        }
    }

    /// Restore the most-recently-pushed state, discarding all data added to
    /// the working vector since the last call to `push_state`.
    #[inline]
    pub fn pop_state(&mut self) {
        self.data.truncate(self.splits.pop().expect("Call to `pop_state` without prior matching `push_state` call"));
    }

    /// Remove the split between the current and previous states; this has the
    /// effect of merging their contents into the previous state.
    ///
    /// Calling this method will have no effect if no prior state exists.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// s.extend_from_slice(&[4, 5, 6]);
    /// assert_eq!(&*s, &[4, 5, 6]);
    ///
    /// s.pop_and_merge_states();
    /// assert_eq!(&*s, &[1, 2, 3, 4, 5, 6]);
    /// # }
    /// ```
    #[inline]
    pub fn pop_and_merge_states(&mut self) {
        self.splits.pop();
    }

    /// Get the number of items in the working state.
    #[inline]
    pub fn len(&self) -> usize {
        self.data.len() - self.offset()
    }

    /// Truncate the working state to at most a given number of elements.
    #[inline]
    pub fn truncate(&mut self, len: usize) {
        let ofs = self.offset();
        self.data.truncate(ofs + len)
    }

    /// Push an item onto the end of the working state.
    pub fn push(&mut self, value: T) {
        self.data.push(value)
    }

    /// Remove the top-most item from the working state and return it.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::new();
    /// assert_eq!(None, s.pop());
    ///
    /// s.extend_from_slice(&[1, 2, 3]);
    /// assert_eq!(Some(3), s.pop());
    /// # }
    /// ```
    ///
    /// `pop` works only within the current state, and will return `None` if the
    /// current state is empty even if a prior state is not:
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// assert_eq!(None, s.pop());
    /// # }
    /// ```
    pub fn pop(&mut self) -> Option<T> {
        if self.len() > 0 { self.data.pop() }
        else { None }
    }

    /// Extend the current working state from a slice.
    #[inline]
    pub fn extend_from_slice<'a>(&mut self, slice: &'a [T]) where T: Copy {
        self.data.extend_from_slice(slice)
    }

    /// Get a reference to the current working state as a slice.
    #[inline]
    pub fn as_slice(&self) -> &[T] {
        self
    }

    /// Remove adjacent duplicates in the working state.
    pub fn dedup(&mut self) where T: PartialEq {
        unsafe {
            let ofs = self.offset();
            let ln = self.data.len();
            if ln <= ofs {
                return;
            }

            let p = self.data.as_mut_ptr();
            let mut r: usize = 1 + ofs;
            let mut w: usize = 1 + ofs;

            while r < ln {
                let p_r = p.offset(r as isize);
                let p_wm1 = p.offset((w - 1) as isize);
                if *p_r != *p_wm1 {
                    if r != w {
                        let p_w = p_wm1.offset(1);
                        mem::swap(&mut *p_r, &mut *p_w);
                    }
                    w += 1;
                }
                r += 1;
            }

            self.truncate(w - ofs);
        }
    }

    /// Iterate over all states contained within the SplitVec.
    ///
    /// The final state is guaranteed to be the current working state.
    pub fn iter_states<'a>(&'a self) -> StateIter<'a, T> {
        StateIter{splits_iter: self.splits.iter(), data: &self.data[..], last_split: Some(0)}
    }
}

/// Iterator over the states of a SplitVec as slices.
///
/// Instances of `StateIter` are obtained by calling `iter_states` on
/// a [`SplitVec`](struct.SplitVec.html).
pub struct StateIter<'a,T> where T: 'a {
    splits_iter: slice::Iter<'a,usize>,
    data: &'a [T],
    last_split: Option<usize>
}

impl<'a, T: 'a> Iterator for StateIter<'a, T> {
    type Item = &'a [T];
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(start) = self.last_split {
            if let Some(end) = self.splits_iter.next() {
                self.last_split = Some(*end);
                Some(&self.data[start..*end])
            } else {
                self.last_split = None;
                Some(&self.data[start..])
            }
        } else { None }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.splits_iter.size_hint()
    }
}

use itertools::Itertools;
impl<T> fmt::Debug for SplitVec<T> where T: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]",
               self.iter_states().map(|s| s.iter().map(|ref elt| format!("{:?}", elt)).join(", "))
               .join(" | "))
    }
}

impl<T> AsRef<SplitVec<T>> for SplitVec<T> {
    fn as_ref(&self) -> &Self {
        self
    }
}
impl<T> AsMut<SplitVec<T>> for SplitVec<T> {
    fn as_mut(&mut self) -> &mut Self {
        self
    }
}

impl<T> AsRef<[T]> for SplitVec<T> {
    fn as_ref(&self) -> &[T] {
        self
    }
}
impl<T> AsMut<[T]> for SplitVec<T> {
    fn as_mut(&mut self) -> &mut [T] {
        self
    }
}

impl<T> From<Vec<T>> for SplitVec<T> {
    fn from(v: Vec<T>) -> Self {
        SplitVec{data: v, splits: Vec::new()}
    }
}

impl<'a,T> From<&'a [T]> for SplitVec<T> where T: Clone {
    fn from(s: &'a [T]) -> Self {
        SplitVec{data: s.into(), splits: Vec::new()}
    }
}

impl<T> Default for SplitVec<T> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Extend<T> for SplitVec<T> {
    fn extend<I>(&mut self, iter: I) where I: IntoIterator<Item=T> {
        self.data.extend(iter);
    }
}

impl<T> Deref for SplitVec<T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        let o = self.offset();
        &self.data[o..]
    }
}

impl<T> DerefMut for SplitVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let o = self.offset();
        &mut self.data[o..]
    }
}

impl<T> Index<usize> for SplitVec<T> {
    type Output = T;
    #[inline]
    fn index<'a>(&'a self, idx: usize) -> &'a T {
        let o = self.offset();
        &self.data[idx + o]
    }
}

impl<T> Index<Range<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: Range<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..(o + r.end)]
    }
}
impl<T> Index<RangeFrom<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeFrom<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..]
    }
}
impl<T> Index<RangeTo<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeTo<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[..(o + r.end)]
    }
}
impl<T> Index<RangeFull> for SplitVec<T> {
    type Output = [T];
    #[inline(always)]
    fn index<'a>(&'a self, _: RangeFull) -> &'a [T] {
        &self.data[..]
    }
}
<|endoftext|>