<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

pub trait Sample: PartialEq + Eq {
  type Normal;

  fn size() -> usize;
  fn size_wide() -> usize;
  fn to_normal(sample: Self) -> Option<Self::Normal>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<commit_msg>Add documentation for Sample trait<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

/// An abstraction trait for keeping different sized integers.
pub trait Sample: PartialEq + Eq {
  type Normal;

  /// The size, in bits, for the `Sample::Normal`.
  fn size() -> usize;

  /// The size, in bits, for the `Sample`.
  fn size_wide() -> usize;

  /// Convert the extended `Sample` to the normal.
  fn to_normal(sample: Self) -> Option<Self::Normal>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<|endoftext|>


<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

use std::ops::{Add, AddAssign, BitAnd, BitOr, Mul, Sub, Shl, ShlAssign, Shr};
use std::io;

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

/// An abstraction trait for keeping different sized integers.
pub trait Sample: PartialEq + Eq + Sized + Clone + Copy +
                  Add<Output = Self> + AddAssign +
                  BitAnd<Self, Output = Self> + BitOr<Self, Output = Self> +
                  Mul<Output = Self> + Shl<u32, Output = Self>  +
                  ShlAssign<u32> + Shr<u32, Output = Self> +
                  Shr<i8, Output = Self> + Shr<i32, Output = Self> +
                  Sub<Output = Self> {
  /// The normal size for the current a `Sample`.
  type Normal;

  /// The size, in bits, for the `Sample::Normal`.
  fn size() -> usize;

  /// The size, in bits, for the `Sample`.
  fn size_extended() -> usize;

  /// Convert the extended `Sample` to the normal.
  fn to_normal(sample: Self) -> Option<Self::Normal>;

  /// Convert an i8 into a `Sample`.
  fn from_i8(sample: i8) -> Self;

  /// Convert an i16 into a `Sample`.
  fn from_i16(sample: i16) -> Self;

  /// Convert an i32 into a `Sample`.
  ///
  /// With `Sample` sometimes being smaller than a i32, there is a chance
  /// for this function to return an incorrect number. So when the number is
  /// larger of smaller than the current `Sample`, it returns `None`
  /// otherwise `Some(sample)`.
  fn from_i32(sample: i32) -> Option<Self>;

  /// Convert an i32 into a `Sample`.
  fn from_i32_lossy(sample: i32) -> Self;
}

/// A trait for defining the size of a sample.
pub trait SampleSize {
  /// The internal integer size used with `Stream::iter`.
  ///
  /// Rather than making the user of `Stream::iter` will remember what the
  /// extended size of the output sample will be, this is to map to the
  /// value based on the current integer size used.
  type Extended: Sample;
}

impl SampleSize for i8 {
  type Extended = i16;
}

impl SampleSize for i16 {
  type Extended = i32;
}

impl SampleSize for i32 {
  type Extended = i64;
}

pub trait WriteExtension: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()>;

  fn write_be_u16(&mut self, number: u16) -> io::Result<()>;
  fn write_le_u16(&mut self, number: u16) -> io::Result<()>;

  fn write_be_u24(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u24(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u32(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u32(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u64(&mut self, number: u64) -> io::Result<()>;
  fn write_le_u64(&mut self, number: u64) -> io::Result<()>;
}

impl<Write> WriteExtension for Write where Write: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()> {
    self.write_all(&[number])
  }

  fn write_be_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[0] = (number >> 8) as u8;
    buffer[1] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[2] = number as u8;
    buffer[1] = (number >> 8) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = (number >> 16) as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = (number >> 24) as u8;
    buffer[1] = (number >> 16) as u8;
    buffer[2] = (number >> 8) as u8;
    buffer[3] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = (number >> 56) as u8;
    buffer[1] = (number >> 48) as u8;
    buffer[2] = (number >> 40) as u8;
    buffer[3] = (number >> 32) as u8;
    buffer[4] = (number >> 24) as u8;
    buffer[5] = (number >> 16) as u8;
    buffer[6] = (number >> 8) as u8;
    buffer[7] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;
    buffer[4] = (number >> 32) as u8;
    buffer[5] = (number >> 40) as u8;
    buffer[6] = (number >> 48) as u8;
    buffer[7] = (number >> 56) as u8;

    self.write_all(&buffer)
  }
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }

  #[test]
  fn test_write_u8() {
    let mut buffer = [0; 1];

    assert!((&mut buffer[..]).write_u8(0xa0).is_ok());
    assert_eq!(buffer, [0xa0]);

    assert!((&mut buffer[..]).write_u8(0xff).is_ok());
    assert_eq!(buffer, [0xff]);

    assert!((&mut buffer[..]).write_u8(0x10).is_ok());
    assert_eq!(buffer, [0x10]);
  }
}
<commit_msg>Add test for `WriteExtension::write_*e_u8`<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

use std::ops::{Add, AddAssign, BitAnd, BitOr, Mul, Sub, Shl, ShlAssign, Shr};
use std::io;

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

/// An abstraction trait for keeping different sized integers.
pub trait Sample: PartialEq + Eq + Sized + Clone + Copy +
                  Add<Output = Self> + AddAssign +
                  BitAnd<Self, Output = Self> + BitOr<Self, Output = Self> +
                  Mul<Output = Self> + Shl<u32, Output = Self>  +
                  ShlAssign<u32> + Shr<u32, Output = Self> +
                  Shr<i8, Output = Self> + Shr<i32, Output = Self> +
                  Sub<Output = Self> {
  /// The normal size for the current a `Sample`.
  type Normal;

  /// The size, in bits, for the `Sample::Normal`.
  fn size() -> usize;

  /// The size, in bits, for the `Sample`.
  fn size_extended() -> usize;

  /// Convert the extended `Sample` to the normal.
  fn to_normal(sample: Self) -> Option<Self::Normal>;

  /// Convert an i8 into a `Sample`.
  fn from_i8(sample: i8) -> Self;

  /// Convert an i16 into a `Sample`.
  fn from_i16(sample: i16) -> Self;

  /// Convert an i32 into a `Sample`.
  ///
  /// With `Sample` sometimes being smaller than a i32, there is a chance
  /// for this function to return an incorrect number. So when the number is
  /// larger of smaller than the current `Sample`, it returns `None`
  /// otherwise `Some(sample)`.
  fn from_i32(sample: i32) -> Option<Self>;

  /// Convert an i32 into a `Sample`.
  fn from_i32_lossy(sample: i32) -> Self;
}

/// A trait for defining the size of a sample.
pub trait SampleSize {
  /// The internal integer size used with `Stream::iter`.
  ///
  /// Rather than making the user of `Stream::iter` will remember what the
  /// extended size of the output sample will be, this is to map to the
  /// value based on the current integer size used.
  type Extended: Sample;
}

impl SampleSize for i8 {
  type Extended = i16;
}

impl SampleSize for i16 {
  type Extended = i32;
}

impl SampleSize for i32 {
  type Extended = i64;
}

pub trait WriteExtension: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()>;

  fn write_be_u16(&mut self, number: u16) -> io::Result<()>;
  fn write_le_u16(&mut self, number: u16) -> io::Result<()>;

  fn write_be_u24(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u24(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u32(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u32(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u64(&mut self, number: u64) -> io::Result<()>;
  fn write_le_u64(&mut self, number: u64) -> io::Result<()>;
}

impl<Write> WriteExtension for Write where Write: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()> {
    self.write_all(&[number])
  }

  fn write_be_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[0] = (number >> 8) as u8;
    buffer[1] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[2] = number as u8;
    buffer[1] = (number >> 8) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = (number >> 16) as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = (number >> 24) as u8;
    buffer[1] = (number >> 16) as u8;
    buffer[2] = (number >> 8) as u8;
    buffer[3] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = (number >> 56) as u8;
    buffer[1] = (number >> 48) as u8;
    buffer[2] = (number >> 40) as u8;
    buffer[3] = (number >> 32) as u8;
    buffer[4] = (number >> 24) as u8;
    buffer[5] = (number >> 16) as u8;
    buffer[6] = (number >> 8) as u8;
    buffer[7] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;
    buffer[4] = (number >> 32) as u8;
    buffer[5] = (number >> 40) as u8;
    buffer[6] = (number >> 48) as u8;
    buffer[7] = (number >> 56) as u8;

    self.write_all(&buffer)
  }
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }

  #[test]
  fn test_write_u8() {
    let mut buffer = [0; 1];

    assert!((&mut buffer[..]).write_u8(0xa0).is_ok());
    assert_eq!(buffer, [0xa0]);

    assert!((&mut buffer[..]).write_u8(0xff).is_ok());
    assert_eq!(buffer, [0xff]);

    assert!((&mut buffer[..]).write_u8(0x10).is_ok());
    assert_eq!(buffer, [0x10]);
  }

  #[test]
  fn test_write_le_u16() {
    let mut buffer = [0; 2];

    assert!((&mut buffer[..]).write_le_u16(0xabcd).is_ok());
    assert_eq!(buffer, [0xcd, 0xab]);

    assert!((&mut buffer[..]).write_le_u16(0xff00).is_ok());
    assert_eq!(buffer, [0x00, 0xff]);

    assert!((&mut buffer[..]).write_le_u16(0x5e9a).is_ok());
    assert_eq!(buffer, [0x9a, 0x5e]);
  }

  #[test]
  fn test_write_be_u16() {
    let mut buffer = [0; 2];

    assert!((&mut buffer[..]).write_be_u16(0xabcd).is_ok());
    assert_eq!(buffer, [0xab, 0xcd]);

    assert!((&mut buffer[..]).write_be_u16(0xff00).is_ok());
    assert_eq!(buffer, [0xff, 0x00]);

    assert!((&mut buffer[..]).write_be_u16(0x5e9a).is_ok());
    assert_eq!(buffer, [0x5e, 0x9a]);
  }
}
<|endoftext|>


<commit_before>use std::iter;

pub struct DirectoryNode {
    pub name: String,
    pub children: Vec<FSNode>,
    pub size: u64,
}

impl DirectoryNode {
    pub fn new(name: String) -> DirectoryNode {
        DirectoryNode {
            name: name,
            children: Vec::new(),
            size: 0,
        }
    }
}

pub struct FileNode {
    pub name: String,
    pub size: u64,
}

pub enum FSNode {
    Directory(DirectoryNode),
    File(FileNode),
}

impl FSNode {
    pub fn children<'a>(&'a self) -> Box<iter::Iterator<Item = &FSNode> + 'a> {
        match *self {
            FSNode::Directory(ref d) => Box::new(d.children.iter()),
            FSNode::File(_) => Box::new(iter::empty()),
        }
    }
    pub fn name(&self) -> &String {
        match *self {
            FSNode::Directory(ref d) => &d.name,
            FSNode::File(ref f) => &f.name,
        }
    }

    pub fn size(&self) -> u64 {
        match *self {
            FSNode::Directory(ref d) => d.size,
            FSNode::File(ref f) => f.size,
        }
    }

    pub fn is_dir(&self) -> bool {
        match *self {
            FSNode::Directory(_) => true,
            FSNode::File(_) => false,
        }
    }
}
<commit_msg>fix dyn warning<commit_after>use std::iter;

pub struct DirectoryNode {
    pub name: String,
    pub children: Vec<FSNode>,
    pub size: u64,
}

impl DirectoryNode {
    pub fn new(name: String) -> DirectoryNode {
        DirectoryNode {
            name: name,
            children: Vec::new(),
            size: 0,
        }
    }
}

pub struct FileNode {
    pub name: String,
    pub size: u64,
}

pub enum FSNode {
    Directory(DirectoryNode),
    File(FileNode),
}

impl FSNode {
    pub fn children<'a>(&'a self) -> Box<dyn iter::Iterator<Item = &FSNode> + 'a> {
        match *self {
            FSNode::Directory(ref d) => Box::new(d.children.iter()),
            FSNode::File(_) => Box::new(iter::empty()),
        }
    }
    pub fn name(&self) -> &String {
        match *self {
            FSNode::Directory(ref d) => &d.name,
            FSNode::File(ref f) => &f.name,
        }
    }

    pub fn size(&self) -> u64 {
        match *self {
            FSNode::Directory(ref d) => d.size,
            FSNode::File(ref f) => f.size,
        }
    }

    pub fn is_dir(&self) -> bool {
        match *self {
            FSNode::Directory(_) => true,
            FSNode::File(_) => false,
        }
    }
}
<|endoftext|>


<commit_before>#![allow(deprecated)]

extern crate mio;
extern crate bytes;
extern crate net2;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate iovec;
extern crate slab;
extern crate tempdir;

#[cfg(target_os = "fuchsia")]
extern crate magenta;

pub use ports::localhost;

mod test_custom_evented;
mod test_close_on_drop;
mod test_double_register;
mod test_echo_server;
mod test_local_addr_ready;
mod test_multicast;
mod test_notify;
mod test_oneshot;
mod test_poll;
mod test_poll_channel;
mod test_register_deregister;
mod test_register_multiple_event_loops;
mod test_reregister_without_poll;
mod test_smoke;
mod test_tcp;
mod test_tcp_level;
mod test_tick;
mod test_udp_level;
mod test_udp_socket;
mod test_write_then_drop;

// The following tests are for deprecated features. Only run these tests on
// platforms that were supported from before the features were deprecated
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
mod test_timer;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
mod test_battery;

#[cfg(any(target_os = "macos", target_os = "linux"))]
mod test_unix_echo_server;
#[cfg(any(target_os = "macos", target_os = "linux"))]
mod test_unix_pass_fd;
#[cfg(any(target_os = "macos", target_os = "linux"))]
mod test_uds_shutdown;
#[cfg(any(target_os = "macos", target_os = "linux"))]
mod test_subprocess_pipe;
#[cfg(any(target_os = "macos", target_os = "linux"))]
mod test_broken_pipe;

#[cfg(any(target_os = "fuchsia"))]
mod test_fuchsia_handles;

use bytes::{Buf, MutBuf};
use std::io::{self, Read, Write};
use std::time::Duration;
use mio::{Event, Events, Poll};

pub trait TryRead {
    fn try_read_buf<B: MutBuf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
        where Self : Sized
    {
        // Reads the length of the slice supplied by buf.mut_bytes into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment (1532 bytes if not jumbo
        // frames)
        let res = self.try_read(unsafe { buf.mut_bytes() });

        if let Ok(Some(cnt)) = res {
            unsafe { buf.advance(cnt); }
        }

        res
    }

    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>;
}

pub trait TryWrite {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
        where Self : Sized
    {
        let res = self.try_write(buf.bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>;
}

impl<T: Read> TryRead for T {
    fn try_read(&mut self, dst: &mut [u8]) -> io::Result<Option<usize>> {
        self.read(dst).map_non_block()
    }
}

impl<T: Write> TryWrite for T {
    fn try_write(&mut self, src: &[u8]) -> io::Result<Option<usize>> {
        self.write(src).map_non_block()
    }
}

/*
 *
 * ===== Helpers =====
 *
 */

/// A helper trait to provide the map_non_block function on Results.
trait MapNonBlock<T> {
    /// Maps a `Result<T>` to a `Result<Option<T>>` by converting
    /// operation-would-block errors into `Ok(None)`.
    fn map_non_block(self) -> io::Result<Option<T>>;
}

impl<T> MapNonBlock<T> for io::Result<T> {
    fn map_non_block(self) -> io::Result<Option<T>> {
        use std::io::ErrorKind::WouldBlock;

        match self {
            Ok(value) => Ok(Some(value)),
            Err(err) => {
                if let WouldBlock = err.kind() {
                    Ok(None)
                } else {
                    Err(err)
                }
            }
        }
    }
}

mod ports {
    use std::net::SocketAddr;
    use std::str::FromStr;
    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
    use std::sync::atomic::Ordering::SeqCst;

    // Helper for getting a unique port for the task run
    // TODO: Reuse ports to not spam the system
    static mut NEXT_PORT: AtomicUsize = ATOMIC_USIZE_INIT;
    const FIRST_PORT: usize = 18080;

    fn next_port() -> usize {
        unsafe {
            // If the atomic was never used, set it to the initial port
            NEXT_PORT.compare_and_swap(0, FIRST_PORT, SeqCst);

            // Get and increment the port list
            NEXT_PORT.fetch_add(1, SeqCst)
        }
    }

    pub fn localhost() -> SocketAddr {
        let s = format!("127.0.0.1:{}", next_port());
        FromStr::from_str(&s).unwrap()
    }
}

pub fn sleep_ms(ms: u64) {
    use std::thread;
    use std::time::Duration;
    thread::sleep(Duration::from_millis(ms));
}

pub fn expect_events(poll: &Poll,
                     event_buffer: &mut Events,
                     poll_try_count: usize,
                     mut expected: Vec<Event>)
{
    const MS: u64 = 1_000;

    for _ in 0..poll_try_count {
        poll.poll(event_buffer, Some(Duration::from_millis(MS))).unwrap();
        for event in event_buffer.iter() {
            let pos_opt = match expected.iter().position(|exp_event| {
                (event.token() == exp_event.token()) &&
                event.readiness().contains(exp_event.readiness())
            }) {
                Some(x) => Some(x),
                None => None,
            };
            if let Some(pos) = pos_opt { expected.remove(pos); }
        }

        if expected.len() == 0 {
            break;
        }
    }

    assert!(expected.len() == 0, "The following expected events were not found: {:?}", expected);
}

<commit_msg>Only run tests for deprecated features when they are enabled. (#704)<commit_after>#![allow(deprecated)]

extern crate mio;
extern crate bytes;
extern crate net2;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate iovec;
extern crate slab;
extern crate tempdir;

#[cfg(target_os = "fuchsia")]
extern crate magenta;

pub use ports::localhost;

mod test_custom_evented;
mod test_close_on_drop;
mod test_double_register;
mod test_echo_server;
mod test_local_addr_ready;
mod test_multicast;
mod test_notify;
mod test_oneshot;
mod test_poll;
mod test_poll_channel;
mod test_register_deregister;
mod test_register_multiple_event_loops;
mod test_reregister_without_poll;
mod test_smoke;
mod test_tcp;
mod test_tcp_level;
mod test_tick;
mod test_udp_level;
mod test_udp_socket;
mod test_write_then_drop;

// The following tests are for deprecated features. Only run these tests on
// platforms that were supported from before the features were deprecated
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
#[cfg(feature = "with-deprecated")]
mod test_timer;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
#[cfg(feature = "with-deprecated")]
mod test_battery;

#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(feature = "with-deprecated")]
mod test_unix_echo_server;
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(feature = "with-deprecated")]
mod test_unix_pass_fd;
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(feature = "with-deprecated")]
mod test_uds_shutdown;
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(feature = "with-deprecated")]
mod test_subprocess_pipe;
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[cfg(feature = "with-deprecated")]
mod test_broken_pipe;

#[cfg(any(target_os = "fuchsia"))]
mod test_fuchsia_handles;

use bytes::{Buf, MutBuf};
use std::io::{self, Read, Write};
use std::time::Duration;
use mio::{Event, Events, Poll};

pub trait TryRead {
    fn try_read_buf<B: MutBuf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
        where Self : Sized
    {
        // Reads the length of the slice supplied by buf.mut_bytes into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment (1532 bytes if not jumbo
        // frames)
        let res = self.try_read(unsafe { buf.mut_bytes() });

        if let Ok(Some(cnt)) = res {
            unsafe { buf.advance(cnt); }
        }

        res
    }

    fn try_read(&mut self, buf: &mut [u8]) -> io::Result<Option<usize>>;
}

pub trait TryWrite {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
        where Self : Sized
    {
        let res = self.try_write(buf.bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_write(&mut self, buf: &[u8]) -> io::Result<Option<usize>>;
}

impl<T: Read> TryRead for T {
    fn try_read(&mut self, dst: &mut [u8]) -> io::Result<Option<usize>> {
        self.read(dst).map_non_block()
    }
}

impl<T: Write> TryWrite for T {
    fn try_write(&mut self, src: &[u8]) -> io::Result<Option<usize>> {
        self.write(src).map_non_block()
    }
}

/*
 *
 * ===== Helpers =====
 *
 */

/// A helper trait to provide the map_non_block function on Results.
trait MapNonBlock<T> {
    /// Maps a `Result<T>` to a `Result<Option<T>>` by converting
    /// operation-would-block errors into `Ok(None)`.
    fn map_non_block(self) -> io::Result<Option<T>>;
}

impl<T> MapNonBlock<T> for io::Result<T> {
    fn map_non_block(self) -> io::Result<Option<T>> {
        use std::io::ErrorKind::WouldBlock;

        match self {
            Ok(value) => Ok(Some(value)),
            Err(err) => {
                if let WouldBlock = err.kind() {
                    Ok(None)
                } else {
                    Err(err)
                }
            }
        }
    }
}

mod ports {
    use std::net::SocketAddr;
    use std::str::FromStr;
    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
    use std::sync::atomic::Ordering::SeqCst;

    // Helper for getting a unique port for the task run
    // TODO: Reuse ports to not spam the system
    static mut NEXT_PORT: AtomicUsize = ATOMIC_USIZE_INIT;
    const FIRST_PORT: usize = 18080;

    fn next_port() -> usize {
        unsafe {
            // If the atomic was never used, set it to the initial port
            NEXT_PORT.compare_and_swap(0, FIRST_PORT, SeqCst);

            // Get and increment the port list
            NEXT_PORT.fetch_add(1, SeqCst)
        }
    }

    pub fn localhost() -> SocketAddr {
        let s = format!("127.0.0.1:{}", next_port());
        FromStr::from_str(&s).unwrap()
    }
}

pub fn sleep_ms(ms: u64) {
    use std::thread;
    use std::time::Duration;
    thread::sleep(Duration::from_millis(ms));
}

pub fn expect_events(poll: &Poll,
                     event_buffer: &mut Events,
                     poll_try_count: usize,
                     mut expected: Vec<Event>)
{
    const MS: u64 = 1_000;

    for _ in 0..poll_try_count {
        poll.poll(event_buffer, Some(Duration::from_millis(MS))).unwrap();
        for event in event_buffer.iter() {
            let pos_opt = match expected.iter().position(|exp_event| {
                (event.token() == exp_event.token()) &&
                event.readiness().contains(exp_event.readiness())
            }) {
                Some(x) => Some(x),
                None => None,
            };
            if let Some(pos) = pos_opt { expected.remove(pos); }
        }

        if expected.len() == 0 {
            break;
        }
    }

    assert!(expected.len() == 0, "The following expected events were not found: {:?}", expected);
}

<|endoftext|>


<commit_before>use std::path::{Path, PathBuf};

use xdg;
use rustc_version;

fn xdg_dir() -> xdg::BaseDirectories {
    // TODO incorporate crate version?
    let prefix = Path::new("afl.rs")
        .join(rustc_version::version().unwrap().to_string());
    xdg::BaseDirectories::with_prefix(prefix).unwrap()
}

pub fn afl() -> PathBuf {
    xdg_dir().create_data_directory("afl").unwrap()
}

pub fn afl_llvm_rt() -> PathBuf {
    xdg_dir().create_data_directory("afl-llvm-rt").unwrap()
}
<commit_msg>Incorporate package version into directory structure.<commit_after>use std::path::{Path, PathBuf};

use xdg;
use rustc_version;

fn xdg_dir() -> xdg::BaseDirectories {
    let prefix = Path::new("afl.rs")
        .join(rustc_version::version().unwrap().to_string())
        .join(pkg_version());
    xdg::BaseDirectories::with_prefix(prefix).unwrap()
}

fn pkg_version() -> &'static str {
    let version = env!("CARGO_PKG_VERSION");
    assert!(!version.is_empty());
    version
}

pub fn afl() -> PathBuf {
    xdg_dir().create_data_directory("afl").unwrap()
}

pub fn afl_llvm_rt() -> PathBuf {
    xdg_dir().create_data_directory("afl-llvm-rt").unwrap()
}
<|endoftext|>


<commit_before>extern crate bson;
extern crate mongodb;

use std::error::Error as ErrorTrait;
use std::ops::Deref;
use linear_map::LinearMap;
use self::bson::{Bson, Document};
use self::mongodb::{Client, ThreadedClient, Error as MongoDBError};
use self::mongodb::connstring;
use self::mongodb::db::{Database, ThreadedDatabase};
use schema::{Definition, Schema};
use driver::Driver;
use error::{Error, ErrorCode};
use patch::Patch;
use query::{Query, Selection};
use value::Value;

struct MongoDriver {
  db: Database
}

impl Driver for MongoDriver {
  fn connect(uri: &str) -> Result<Self, Error> {
    let config = try!(connstring::parse(uri));
    if let Some(db_name) = config.clone().database {
      Ok(MongoDriver {
        db: try!(Client::with_config(config, None, None)).db(&db_name)
      })
    } else {
      Err(Error::validation(
        format!("Database name not provided in connection path '{}'.", uri),
        "Include the database name you are connecting to as the connection URI path."
      ))
    }
  }

  fn validate_definition(definition: &Definition) -> Result<(), Error> {
    match &definition.data {
      &Schema::Object{ref properties,..} => {
        for (key, value) in properties {
          match value {
            &Schema::Array{ref items} => {
              match items.deref() {
                &Schema::Object{..} => (),
                _ => return Err(Error::validation(
                  format!("Items for collection '{}' must be an object.", key),
                  format!("The MongoDB driver only supports inserting objects into collections, try changing the schema type of the '{}' collection to reflect this.", key)
                ))
              }
            },
            _ => return Err(Error::validation(
              format!("Schema type for the '{}' property must be an array.", key),
              format!("The MongoDB driver only supports array collections as the first level data types, try changing the '{}' property in your schema to reflect this.", key)
            ))
          }
        }
      },
      _ => return Err(Error::validation(
        "Root data schema is not object.",
        "The MongoDB driver only supports an object as the root data type, try changing your schema to reflect this."
      ))
    }
    Ok(())
  }

  // TODO: Better inline documentation.
  fn query(&self, query: Query) -> Result<Value, Error> {
    match query {
      Query::Value => Err(Error::new(
        ErrorCode::Forbidden,
        "Can’t query the entire MongoDB database.",
        Some("Query something more specfic instead of the entire database.")
      )),
      Query::Object(collection_queries) => {
        // First level is the collection.
        let mut object = LinearMap::new();
        for (Selection::Key(coll_name), query) in collection_queries {
          // if let Selection::Key(coll_name) = selection {
            let collection = self.db.collection(&coll_name);
            match query {
              // TODO: Make this a range error when implementing selection by
              // range.
              Query::Value => {
                let mut cursor = try!(collection.find(None, None));
                let mut values = Vec::new();
                if let Some(Err(error)) = cursor.find(|entry| match entry {
                  &Ok(ref document) => { values.push(Value::from(document.clone())); false },
                  &Err(_) => true
                }) {
                  return Err(Error::from(error));
                } else {
                  object.insert(coll_name, Value::Array(values));
                }
              },
              // TODO: When implementing collections consider not using the
              // MongoDB `_id` property as the key.
              Query::Object(_) => {

              }
            }
          // } else {
          //   return Err(Error::new(
          //     ErrorCode::Forbidden,
          //     "Can‘t query a selection of MongoDB collections.",
          //     Some("Query specific collections instead of a range of collections.")
          //   );
          // }
        }
        Ok(Value::Object(object))
      }
    }
  }

  fn patch(&self, _: Vec<Patch>) -> Result<Value, Error> {
    Err(Error::unimplemented("Patching not implemented for MongoDB driver."))
  }
}

impl From<MongoDBError> for Error {
  fn from(error: MongoDBError) -> Self {
    Error::internal(error.description())
  }
}

impl From<Document> for Value {
  fn from(document: Document) -> Self {
    let mut map = LinearMap::new();
    for key in &document.keys {
      if let Some(value) = document.get(key) {
        map.insert(key.clone(), Value::from(value.clone()));
      }
    }
    Value::Object(map)
  }
}

impl From<Bson> for Value {
  fn from(bson: Bson) -> Self {
    match bson {
      Bson::FloatingPoint(value) => Value::F64(f64::from(value)),
      Bson::String(value) => Value::String(value),
      Bson::Array(values) => Value::Array(values.into_iter().map(|v| Value::from(v)).collect()),
      Bson::Document(document) => Value::from(document),
      Bson::Boolean(value) => Value::Boolean(value),
      Bson::Null => Value::Null,
      Bson::RegExp(value, _) => Value::String(value),
      Bson::JavaScriptCode(value) => Value::String(value),
      Bson::JavaScriptCodeWithScope(value, _) => Value::String(value),
      Bson::I32(value) => Value::I64(i64::from(value)),
      Bson::I64(value) => Value::I64(i64::from(value)),
      Bson::TimeStamp(value) => Value::I64(i64::from(value)),
      // TODO: Actual transformation of binary type.
      Bson::Binary(_, _) => Value::Null,
      Bson::ObjectId(object_id) => Value::String(object_id.to_string()),
      Bson::UtcDatetime(time) => Value::String(time.to_rfc3339())
    }
  }
}

#[cfg(test)]
mod tests {
  use super::bson::{Bson, Document};
  use super::mongodb::db::{ThreadedDatabase};
  use definition::Definition;
  use definition::schema::Schema;
  use driver::Driver;
  use driver::mongodb::MongoDriver;
  use query::{Query, Selection};
  use value::Value;

  #[test]
  fn test_validate_definition() {
    assert!(MongoDriver::validate_definition(&Definition { data: Schema::Boolean }).is_err());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {}
      }
    }).is_ok());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {
          S!("foo") => Schema::Boolean
        }
      }
    }).is_err());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {
          S!("foo") => Schema::Array {
            items: Box::new(Schema::Boolean)
          }
        }
      }
    }).is_err());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {
          S!("foo") => Schema::Array {
            items: Box::new(Schema::Object {
              required: vec![],
              additional_properties: true,
              properties: linear_map! {}
            })
          }
        }
      }
    }).is_ok());
  }

  #[test]
  fn test_database() {
    let driver = MongoDriver::connect("mongodb://localhost:27017/ardite_test").unwrap();
    let coll_name = "ardite_test_collection";
    driver.db.drop_collection(coll_name).unwrap();
    let collection = driver.db.collection(coll_name);
    let mut doc1 = Document::new();
    doc1.insert(S!("title"), Bson::String(S!("Back to the future!")));
    doc1.insert(S!("foo"), Bson::String(S!("bar")));
    let mut doc2 = Document::new();
    doc2.insert(S!("buz"), Bson::String(S!("baz")));
    let id1 = collection.insert_one(doc1, None).unwrap().inserted_id.unwrap();
    let id2 = collection.insert_one(doc2, None).unwrap().inserted_id.unwrap();
    assert!(driver.query(Query::Value).is_err());
    assert_eq!(driver.query(Query::Object(linear_map! {
      Selection::Key(coll_name.to_string()) => Query::Value
    })).unwrap(), vobject! {
      coll_name => varray![
        vobject! {
          "_id" => Value::from(id1),
          "title" => vstring!("Back to the future!"),
          "foo" => vstring!("bar")
        }, vobject! {
          "_id" => Value::from(id2),
          "buz" => vstring!("baz")
        }
      ]
    });
    driver.db.drop_collection(coll_name).unwrap();
  }
}
<commit_msg>style: remove dead code<commit_after>extern crate bson;
extern crate mongodb;

use std::error::Error as ErrorTrait;
use std::ops::Deref;
use linear_map::LinearMap;
use self::bson::{Bson, Document};
use self::mongodb::{Client, ThreadedClient, Error as MongoDBError};
use self::mongodb::connstring;
use self::mongodb::db::{Database, ThreadedDatabase};
use schema::{Definition, Schema};
use driver::Driver;
use error::{Error, ErrorCode};
use patch::Patch;
use query::{Query, Selection};
use value::Value;

struct MongoDriver {
  db: Database
}

impl Driver for MongoDriver {
  fn connect(uri: &str) -> Result<Self, Error> {
    let config = try!(connstring::parse(uri));
    if let Some(db_name) = config.clone().database {
      Ok(MongoDriver {
        db: try!(Client::with_config(config, None, None)).db(&db_name)
      })
    } else {
      Err(Error::validation(
        format!("Database name not provided in connection path '{}'.", uri),
        "Include the database name you are connecting to as the connection URI path."
      ))
    }
  }

  fn validate_definition(definition: &Definition) -> Result<(), Error> {
    match &definition.data {
      &Schema::Object{ref properties,..} => {
        for (key, value) in properties {
          match value {
            &Schema::Array{ref items} => {
              match items.deref() {
                &Schema::Object{..} => (),
                _ => return Err(Error::validation(
                  format!("Items for collection '{}' must be an object.", key),
                  format!("The MongoDB driver only supports inserting objects into collections, try changing the schema type of the '{}' collection to reflect this.", key)
                ))
              }
            },
            _ => return Err(Error::validation(
              format!("Schema type for the '{}' property must be an array.", key),
              format!("The MongoDB driver only supports array collections as the first level data types, try changing the '{}' property in your schema to reflect this.", key)
            ))
          }
        }
      },
      _ => return Err(Error::validation(
        "Root data schema is not object.",
        "The MongoDB driver only supports an object as the root data type, try changing your schema to reflect this."
      ))
    }
    Ok(())
  }

  // TODO: Better inline documentation.
  fn query(&self, query: Query) -> Result<Value, Error> {
    match query {
      Query::Value => Err(Error::new(
        ErrorCode::Forbidden,
        "Can’t query the entire MongoDB database.",
        Some("Query something more specfic instead of the entire database.")
      )),
      Query::Object(collection_queries) => {
        // First level is the collection.
        let mut object = LinearMap::new();
        for (Selection::Key(coll_name), query) in collection_queries {
          let collection = self.db.collection(&coll_name);
          match query {
            // TODO: Make this a range error when implementing selection by
            // range.
            Query::Value => {
              let mut cursor = try!(collection.find(None, None));
              let mut values = Vec::new();
              if let Some(Err(error)) = cursor.find(|entry| match entry {
                &Ok(ref document) => { values.push(Value::from(document.clone())); false },
                &Err(_) => true
              }) {
                return Err(Error::from(error));
              } else {
                object.insert(coll_name, Value::Array(values));
              }
            },
            // TODO: When implementing collections consider not using the
            // MongoDB `_id` property as the key.
            Query::Object(_) => {

            }
          }
        }
        Ok(Value::Object(object))
      }
    }
  }

  fn patch(&self, _: Vec<Patch>) -> Result<Value, Error> {
    Err(Error::unimplemented("Patching not implemented for MongoDB driver."))
  }
}

impl From<MongoDBError> for Error {
  fn from(error: MongoDBError) -> Self {
    Error::internal(error.description())
  }
}

impl From<Document> for Value {
  fn from(document: Document) -> Self {
    let mut map = LinearMap::new();
    for key in &document.keys {
      if let Some(value) = document.get(key) {
        map.insert(key.clone(), Value::from(value.clone()));
      }
    }
    Value::Object(map)
  }
}

impl From<Bson> for Value {
  fn from(bson: Bson) -> Self {
    match bson {
      Bson::FloatingPoint(value) => Value::F64(f64::from(value)),
      Bson::String(value) => Value::String(value),
      Bson::Array(values) => Value::Array(values.into_iter().map(|v| Value::from(v)).collect()),
      Bson::Document(document) => Value::from(document),
      Bson::Boolean(value) => Value::Boolean(value),
      Bson::Null => Value::Null,
      Bson::RegExp(value, _) => Value::String(value),
      Bson::JavaScriptCode(value) => Value::String(value),
      Bson::JavaScriptCodeWithScope(value, _) => Value::String(value),
      Bson::I32(value) => Value::I64(i64::from(value)),
      Bson::I64(value) => Value::I64(i64::from(value)),
      Bson::TimeStamp(value) => Value::I64(i64::from(value)),
      // TODO: Actual transformation of binary type.
      Bson::Binary(_, _) => Value::Null,
      Bson::ObjectId(object_id) => Value::String(object_id.to_string()),
      Bson::UtcDatetime(time) => Value::String(time.to_rfc3339())
    }
  }
}

#[cfg(test)]
mod tests {
  use super::bson::{Bson, Document};
  use super::mongodb::db::{ThreadedDatabase};
  use definition::Definition;
  use definition::schema::Schema;
  use driver::Driver;
  use driver::mongodb::MongoDriver;
  use query::{Query, Selection};
  use value::Value;

  #[test]
  fn test_validate_definition() {
    assert!(MongoDriver::validate_definition(&Definition { data: Schema::Boolean }).is_err());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {}
      }
    }).is_ok());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {
          S!("foo") => Schema::Boolean
        }
      }
    }).is_err());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {
          S!("foo") => Schema::Array {
            items: Box::new(Schema::Boolean)
          }
        }
      }
    }).is_err());
    assert!(MongoDriver::validate_definition(&Definition {
      data: Schema::Object {
        required: vec![],
        additional_properties: false,
        properties: linear_map! {
          S!("foo") => Schema::Array {
            items: Box::new(Schema::Object {
              required: vec![],
              additional_properties: true,
              properties: linear_map! {}
            })
          }
        }
      }
    }).is_ok());
  }

  #[test]
  fn test_database() {
    let driver = MongoDriver::connect("mongodb://localhost:27017/ardite_test").unwrap();
    let coll_name = "ardite_test_collection";
    driver.db.drop_collection(coll_name).unwrap();
    let collection = driver.db.collection(coll_name);
    let mut doc1 = Document::new();
    doc1.insert(S!("title"), Bson::String(S!("Back to the future!")));
    doc1.insert(S!("foo"), Bson::String(S!("bar")));
    let mut doc2 = Document::new();
    doc2.insert(S!("buz"), Bson::String(S!("baz")));
    let id1 = collection.insert_one(doc1, None).unwrap().inserted_id.unwrap();
    let id2 = collection.insert_one(doc2, None).unwrap().inserted_id.unwrap();
    assert!(driver.query(Query::Value).is_err());
    assert_eq!(driver.query(Query::Object(linear_map! {
      Selection::Key(coll_name.to_string()) => Query::Value
    })).unwrap(), vobject! {
      coll_name => varray![
        vobject! {
          "_id" => Value::from(id1),
          "title" => vstring!("Back to the future!"),
          "foo" => vstring!("bar")
        }, vobject! {
          "_id" => Value::from(id2),
          "buz" => vstring!("baz")
        }
      ]
    });
    driver.db.drop_collection(coll_name).unwrap();
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Fabian Schuiki

//! Multi-type arena allocation

#![deny(missing_docs)]

use std::borrow::Cow;

/// Allocates objects.
pub trait Alloc<'a, 't, T> {
    /// Allocate an object of type `T`.
    fn alloc(&'a self, value: T) -> &'t mut T;
}

impl<'z, 'a, 'p: 'a, 't, T> Alloc<'z, 't, T> for &'p Alloc<'a, 't, T> {
    fn alloc(&'z self, value: T) -> &'t mut T {
        Alloc::alloc(*self, value)
    }
}

// /// Allocates objects into itself.
// pub trait AllocSelf<T>: for<'a> Alloc<'a, 'a, T> {}

// // Implement `AllocSelf` for anything that supports the proper `Alloc`.
// impl<T, A: for<'a> Alloc<'a, 'a, T>> AllocSelf<T> for A {}

// /// Allocates objects into some arena.
// ///
// /// In contrast to `AllocSelf`, the lifetime of the references returned by this
// /// trait are not bound to the trait itself. Rather, the lifetime is a parameter
// /// of the trait itself. This allows context objects to be created that hold a
// /// reference to an arena, and allow for direct allocation into that arena.
// pub trait AllocInto<'t, T>: for<'a> Alloc<'a, 't, T> {}

// /// Implement `AllocInto` for anything that supports the proper `Alloc`.
// impl<'t, T, A: for<'a> Alloc<'a, 't, T>> AllocInto<'t, T> for A {}

/// Allocates objects into an arena.
pub trait Allok<'a, 't, T> {
    /// Allocate an object of type `T` into this arena.
    fn allok(&'a self, value: T) -> &'t mut T;
}

/// Allocates objects into an arena.
pub trait AllokOwned<'a, 't, T: ToOwned + ?Sized> {
    /// Allocate an object of type `T` into this arena.
    fn allok_owned(&'a self, value: <T as ToOwned>::Owned) -> &'t mut T;
}

impl<'a, 't, T: ToOwned<Owned = T>> AllokOwned<'a, 't, T> for Allok<'a, 't, T> {
    fn allok_owned(&'a self, value: T) -> &'t mut T {
        self.allok(value)
    }
}

/// Allocates objects into an arena.
pub trait AllokCow<'a, 't, T: ToOwned + ?Sized>: AllokOwned<'a, 't, T> {
    /// Conditionally allocate a CoW object of type `T`.
    fn maybe_allok(&'a self, value: Cow<'t, T>) -> &'t T {
        match value {
            Cow::Borrowed(x) => x,
            Cow::Owned(x) => self.allok_owned(x),
        }
    }

    /// Forcefully allocate a CoW object of type `T`.
    fn force_allok(&'a self, value: Cow<T>) -> &'t T {
        self.allok_owned(value.into_owned())
    }
}

/// Generate a collection of arenas for different types.
#[macro_export]
macro_rules! make_arenas {
    ($(#[$arena_attr:meta])* pub struct $arena_name:ident { $($name:ident: $type:ty,)* }) => {
        make_arenas!{ IMPL $($arena_attr),*; $arena_name; []; $($name: $type,)* }
    };

    ($(#[$arena_attr:meta])* pub struct $arena_name:ident<$($lt:tt),+> { $($name:ident: $type:ty,)* }) => {
        make_arenas!{ IMPL $($arena_attr),*; $arena_name; [$($lt),+]; $($name: $type,)* }
    };

    (IMPL $($arena_attr:meta),*; $arena_name:ident; [$($lt:tt),*]; $($name:ident: $type:ty,)*) => {
        $(#[$arena_attr])*
        #[allow(missing_docs)]
        pub struct $arena_name<$($lt),*> {
            $(pub $name: ::typed_arena::Arena<$type>,)*
        }

        make_arenas!(STRUCT_IMPL $arena_name; [$($lt),*]; $($name: $type,)*);
    };

    (STRUCT_IMPL $arena_name:ident; [$($lt:tt),*]; $($name:ident: $type:ty,)*) => {
        impl<$($lt),*> $arena_name<$($lt),*> {
            /// Create a new arena.
            pub fn new() -> $arena_name<$($lt),*> {
                $arena_name {
                    $($name: ::typed_arena::Arena::new(),)*
                }
            }
        }

        impl<$($lt),*> Default for $arena_name<$($lt),*> {
            fn default() -> $arena_name<$($lt),*> {
                $arena_name::new()
            }
        }

        make_arenas!(TRAIT_IMPL $arena_name; [$($lt),*]; $($name: $type,)*);
    };

    (TRAIT_IMPL $arena_name:ident; [$($lt:tt),*]; $name:ident: $type:ty, $($tail_name:ident: $tail_type:ty,)*) => {
        impl<'a, $($lt),*> $crate::arenas::Alloc<'a, 'a, $type> for $arena_name<$($lt),*> where $($lt: 'a),* {
            fn alloc(&'a self, value: $type) -> &'a mut $type {
                self.$name.alloc(value)
            }
        }

        impl<'a, $($lt),*> $crate::arenas::Allok<'a, 'a, $type> for $arena_name<$($lt),*> where $($lt: 'a),* {
            fn allok(&'a self, value: $type) -> &'a mut $type {
                self.$name.alloc(value)
            }
        }

        make_arenas!(TRAIT_IMPL $arena_name; [$($lt),*]; $($tail_name: $tail_type,)*);
    };

    (TRAIT_IMPL $arena_name:ident; [$($lt:tt),*];) => {}
}
<commit_msg>vhdl: refactor alloc and document<commit_after>// Copyright (c) 2018 Fabian Schuiki

//! Multi-type arena allocation

#![deny(missing_docs)]

use std::borrow::Cow;

/// Allocates values.
pub trait Alloc<'a, 't, T> {
    /// Allocate a value of type `T`.
    fn alloc(&'a self, value: T) -> &'t mut T;
}

impl<'z, 'a, 'p: 'a, 't, T> Alloc<'z, 't, T> for &'p Alloc<'a, 't, T> {
    fn alloc(&'z self, value: T) -> &'t mut T {
        Alloc::alloc(*self, value)
    }
}

/// Allocates values into itself.
///
/// This is merely a marker trait that you should not implement yourself. It is
/// implemented automatically on anything that supports `Alloc<'a, 'a, T>` for
/// any `'a`. The allocated values have the same lifetime as `&self`.
pub trait AllocSelf<T>: for<'a> Alloc<'a, 'a, T> {}

// Implement `AllocSelf` for anything that supports the proper `Alloc`.
impl<T, A: for<'a> Alloc<'a, 'a, T>> AllocSelf<T> for A {}

/// Allocates values into some arena.
///
/// This is merely a marker trait that you should not implement yourself. It is
/// implemented automatically on anything that supports `Alloc<'a, 't, T>` for
/// any `'a`. The allocated values have the lifetime `'t`.
pub trait AllocInto<'t, T>: for<'a> Alloc<'a, 't, T> {}

/// Implement `AllocInto` for anything that supports the proper `Alloc`.
impl<'t, T, A: for<'a> Alloc<'a, 't, T>> AllocInto<'t, T> for A {}

/// Allocates values implementing `ToOwned`.
///
/// This is merely a marker trait that you should not implement yourself. It is
/// implemented automatically on anything that supports `Alloc`.
pub trait AllocOwned<'a, 't, T: ToOwned + ?Sized> {
    /// Allocate a value of type `T: ToOwned` into this arena.
    ///
    /// This function differs from `Alloc::alloc` in that it takes `T::Owned`
    /// and returns `&T`.
    fn alloc_owned(&'a self, value: <T as ToOwned>::Owned) -> &'t mut T;

    /// Conditionally allocate a value of type `Cow<T>`.
    ///
    /// If the value is `Cow::Owned`, allocates and returns a reference to it;
    /// if it is `Cow::Borrowed`, returns the reference without allocation. This
    /// requires that the borrow in `Cow` has the same lifetime as the allocated
    /// reference will have, as indicated by the type `Cow<'t, T> -> &'t T`. Use
    /// `force_alloc` if you don't have such a lifetime guarantee.
    fn maybe_alloc(&'a self, value: Cow<'t, T>) -> &'t T {
        match value {
            Cow::Borrowed(x) => x,
            Cow::Owned(x) => self.alloc_owned(x),
        }
    }

    /// Forcefully allocate a value of type `Cow<T>`.
    ///
    /// Regardless of whether the value is `Cow::Owned` or `Cow::Borrowed`, it
    /// is converted to the owned value via `ToOwned::into_owned()` and
    /// allocated. This function is useful if you have no guarantee that the
    /// lifetime of the borrow in `Cow` has the same lifetime as the allocated
    /// reference, as indicated by the type `Cow<T> -> &'t T'. Use `maybe_alloc`
    /// if you do have such a lifetime guarantee.
    fn force_alloc(&'a self, value: Cow<T>) -> &'t T {
        self.alloc_owned(value.into_owned())
    }
}

// Implement `AllocOwned` for anything that supports the proper `Alloc` and for
// any types that implement `ToOwned` with `Owned` equal to the type.
impl<'a, 't, T: ToOwned<Owned = T>> AllocOwned<'a, 't, T> for Alloc<'a, 't, T> {
    fn alloc_owned(&'a self, value: T) -> &'t mut T {
        self.alloc(value)
    }
}

// /// Conditionally allocates objects.
// pub trait AllocCow<'a, 't, T: ToOwned + ?Sized>: AllokOwned<'a, 't, T> {
// }

/// Allocates objects into an arena.
pub trait Allok<'a, 't, T> {
    /// Allocate an object of type `T` into this arena.
    fn allok(&'a self, value: T) -> &'t mut T;
}

/// Allocates objects into an arena.
pub trait AllokOwned<'a, 't, T: ToOwned + ?Sized> {
    /// Allocate an object of type `T` into this arena.
    fn allok_owned(&'a self, value: <T as ToOwned>::Owned) -> &'t mut T;
}

impl<'a, 't, T: ToOwned<Owned = T>> AllokOwned<'a, 't, T> for Allok<'a, 't, T> {
    fn allok_owned(&'a self, value: T) -> &'t mut T {
        self.allok(value)
    }
}

/// Allocates objects into an arena.
pub trait AllokCow<'a, 't, T: ToOwned + ?Sized>: AllokOwned<'a, 't, T> {
    /// Conditionally allocate a CoW object of type `T`.
    fn maybe_allok(&'a self, value: Cow<'t, T>) -> &'t T {
        match value {
            Cow::Borrowed(x) => x,
            Cow::Owned(x) => self.allok_owned(x),
        }
    }

    /// Forcefully allocate a CoW object of type `T`.
    fn force_allok(&'a self, value: Cow<T>) -> &'t T {
        self.allok_owned(value.into_owned())
    }
}

/// Generate a collection of arenas for different types.
#[macro_export]
macro_rules! make_arenas {
    ($(#[$arena_attr:meta])* pub struct $arena_name:ident { $($name:ident: $type:ty,)* }) => {
        make_arenas!{ IMPL $($arena_attr),*; $arena_name; []; $($name: $type,)* }
    };

    ($(#[$arena_attr:meta])* pub struct $arena_name:ident<$($lt:tt),+> { $($name:ident: $type:ty,)* }) => {
        make_arenas!{ IMPL $($arena_attr),*; $arena_name; [$($lt),+]; $($name: $type,)* }
    };

    (IMPL $($arena_attr:meta),*; $arena_name:ident; [$($lt:tt),*]; $($name:ident: $type:ty,)*) => {
        $(#[$arena_attr])*
        #[allow(missing_docs)]
        pub struct $arena_name<$($lt),*> {
            $(pub $name: ::typed_arena::Arena<$type>,)*
        }

        make_arenas!(STRUCT_IMPL $arena_name; [$($lt),*]; $($name: $type,)*);
    };

    (STRUCT_IMPL $arena_name:ident; [$($lt:tt),*]; $($name:ident: $type:ty,)*) => {
        impl<$($lt),*> $arena_name<$($lt),*> {
            /// Create a new arena.
            pub fn new() -> $arena_name<$($lt),*> {
                $arena_name {
                    $($name: ::typed_arena::Arena::new(),)*
                }
            }
        }

        impl<$($lt),*> Default for $arena_name<$($lt),*> {
            fn default() -> $arena_name<$($lt),*> {
                $arena_name::new()
            }
        }

        make_arenas!(TRAIT_IMPL $arena_name; [$($lt),*]; $($name: $type,)*);
    };

    (TRAIT_IMPL $arena_name:ident; [$($lt:tt),*]; $name:ident: $type:ty, $($tail_name:ident: $tail_type:ty,)*) => {
        impl<'a, $($lt),*> $crate::arenas::Alloc<'a, 'a, $type> for $arena_name<$($lt),*> where $($lt: 'a),* {
            fn alloc(&'a self, value: $type) -> &'a mut $type {
                self.$name.alloc(value)
            }
        }

        impl<'a, $($lt),*> $crate::arenas::Allok<'a, 'a, $type> for $arena_name<$($lt),*> where $($lt: 'a),* {
            fn allok(&'a self, value: $type) -> &'a mut $type {
                self.$name.alloc(value)
            }
        }

        make_arenas!(TRAIT_IMPL $arena_name; [$($lt),*]; $($tail_name: $tail_type,)*);
    };

    (TRAIT_IMPL $arena_name:ident; [$($lt:tt),*];) => {}
}
<|endoftext|>


<commit_before>//! Game loop.

use glfw;
use glfw::Context;
use gl = opengles::gl2;

use game_window::GameWindow;

/// Basic settings for window behavior.
pub struct Settings {
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
    /// The color to use as background.
    pub background_color: [f32, ..4],
}

impl Settings {
    /// Gets default settings.
    pub fn default() -> Settings {
        Settings {
            exit_on_esc: true,
            background_color: [0.0, 0.0, 0.0, 1.0],
        }
    }

    /// Creates a new Settings.
    pub fn new(exit_on_esc: bool, background_color: [f32, ..4]) -> Settings {
        Settings {
            exit_on_esc: exit_on_esc,
            background_color: background_color,
        }
    }
}

/// Implement default behavior for a game.
pub trait Game {
    /// Get the game window.
    fn get_game_window<'a>(&'a self) -> &'a GameWindow;

    /// Read settings.
    fn get_settings<'a>(&'a self) -> &'a Settings;

    /// Render graphics.
    fn render(&self);

    /// Update the physical state of the game.
    fn update(&mut self);

    /// Perform tasks for loading before showing anything.
    fn load(&mut self);

    /// Clears the background with color from settings.
    #[inline(always)]
    fn clear_background(&self) {
        let rgb  = self.get_settings().background_color;
        gl::clear_color(rgb[0], rgb[1], rgb[2], rgb[3]);
        gl::clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
    }

    /// Sets up viewport.
    #[inline(always)]
    fn viewport(&self) {
        let game_window = self.get_game_window();
        let (w, h) = game_window.window.get_size();
        gl::viewport(0, 0, w as gl::GLint, h as gl::GLint);
        self.clear_background();
    }

    /// Whether the window should be closed.
    fn should_close(&self) -> bool {
        self.get_game_window().window.should_close()
    }

    /// Swaps the front buffer with the back buffer.
    /// This shows the next frame.
    fn swap_buffers(&self) {
        self.get_game_window().window.swap_buffers()
    }

    /// Handles events with default settings..
    fn handle_events(&self) {
        let game_window = self.get_game_window();
        let glfw = &game_window.glfw;
        let settings = self.get_settings();
        glfw.poll_events();
        for (_, event) in
        glfw::flush_messages(&game_window.events) {
            match event {
                // Close with Esc.
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                if settings.exit_on_esc  => {
                    game_window.window.set_should_close(true)
                },
                _ => {},
            }
        }
    }

    /// Executes a game loop.
    fn run(&mut self) {
        self.load();
        while !self.should_close() {
            self.viewport();
            self.clear_background();
            self.render();
            self.swap_buffers();
            self.update();
            self.handle_events();
        }
    }
}

<commit_msg>Using the `clear` from Rust-Graphics<commit_after>//! Game loop.

use glfw;
use glfw::Context;
use gl = opengles::gl2;
use graphics;
use Gl = gl::Gl;

use game_window::GameWindow;

/// Basic settings for window behavior.
pub struct Settings {
    /// If true, exit when pressing Esc.
    pub exit_on_esc: bool,
    /// The color to use as background.
    pub background_color: [f32, ..4],
}

impl Settings {
    /// Gets default settings.
    pub fn default() -> Settings {
        Settings {
            exit_on_esc: true,
            background_color: [0.0, 0.0, 0.0, 1.0],
        }
    }

    /// Creates a new Settings.
    pub fn new(exit_on_esc: bool, background_color: [f32, ..4]) -> Settings {
        Settings {
            exit_on_esc: exit_on_esc,
            background_color: background_color,
        }
    }
}

/// Implement default behavior for a game.
pub trait Game {
    /// Get the game window.
    fn get_game_window<'a>(&'a self) -> &'a GameWindow;

    /// Read settings.
    fn get_settings<'a>(&'a self) -> &'a Settings;

    /// Render graphics.
    fn render(&self, context: &graphics::Context, gl: &mut Gl);

    /// Update the physical state of the game.
    fn update(&mut self);

    /// Perform tasks for loading before showing anything.
    fn load(&mut self);

    /// Sets up viewport.
    #[inline(always)]
    fn viewport(&self) {
        let game_window = self.get_game_window();
        let (w, h) = game_window.window.get_size();
        gl::viewport(0, 0, w as gl::GLint, h as gl::GLint);
    }

    /// Whether the window should be closed.
    fn should_close(&self) -> bool {
        self.get_game_window().window.should_close()
    }

    /// Swaps the front buffer with the back buffer.
    /// This shows the next frame.
    fn swap_buffers(&self) {
        self.get_game_window().window.swap_buffers()
    }

    /// Handles events with default settings..
    fn handle_events(&self) {
        let game_window = self.get_game_window();
        let glfw = &game_window.glfw;
        let settings = self.get_settings();
        glfw.poll_events();
        for (_, event) in
        glfw::flush_messages(&game_window.events) {
            match event {
                // Close with Esc.
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                if settings.exit_on_esc  => {
                    game_window.window.set_should_close(true)
                },
                _ => {},
            }
        }
    }

    /// Executes a game loop.
    fn run(&mut self) {
        use graphics::{Clear, AddColor};
        use gl::Gl;

        self.load();
        let mut gl = Gl::new();
        let context = graphics::Context::new();
        let bg = self.get_settings().background_color;
        let bg = context.rgba(bg[0], bg[1], bg[2], bg[3]);
        while !self.should_close() {
            self.viewport();
            bg.clear(&mut gl);
            self.render(&context, &mut gl);
            self.swap_buffers();
            self.update();
            self.handle_events();
        }
    }
}

<|endoftext|>


<commit_before>use Parameter;
use ndarray::{ArrayBase, Array1};
use std::ops::{AddAssign, MulAssign};

pub enum Trace {
    Accumulating {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    Replacing {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    // TODO: Dutch traces (need to be able to share alpha parameter)
}

impl Trace {
    pub fn get(&self) -> &Array1<f64> {
        match self {
            &Trace::Accumulating { ref eligibility, .. } |
                &Trace::Replacing { ref eligibility, .. } => eligibility,
        }
    }

    pub fn decay(&mut self, rate: f64) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, lambda } |
                &mut Trace::Replacing { ref mut eligibility, lambda } =>
            {
                eligibility.mul_assign(rate*lambda);
            },
        }
    }

    pub fn update(&mut self, phi: &Array1<f64>) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, lambda } =>
            {
                eligibility.add_assign(phi);
            },
            &mut Trace::Replacing { ref mut eligibility, lambda } =>
            {
                eligibility.add_assign(phi);
                eligibility.map_inplace(|val| *val = val.min(1.0));
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Trace;
    use ndarray::{ArrayBase, arr1};

    #[test]
    fn test_accumulating() {
        let mut trace = Trace::Accumulating {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10])
        };

        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.95f64; 10]));
    }

    #[test]
    fn test_replacing() {
        let mut trace = Trace::Replacing {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10])
        };

        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.0f64; 10]));
    }
}
<commit_msg>Minor cleanup in Trace enum<commit_after>use Parameter;
use ndarray::Array1;

pub enum Trace {
    Accumulating {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    Replacing {
        lambda: Parameter,
        eligibility: Array1<f64>,
    },
    // TODO: Dutch traces (need to be able to share alpha parameter)
}

impl Trace {
    pub fn get(&self) -> &Array1<f64> {
        match self {
            &Trace::Accumulating { ref eligibility, .. } |
                &Trace::Replacing { ref eligibility, .. } => eligibility,
        }
    }

    pub fn decay(&mut self, rate: f64) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, lambda } |
                &mut Trace::Replacing { ref mut eligibility, lambda } =>
            {
                *eligibility *= rate*lambda;
            },
        }
    }

    pub fn update(&mut self, phi: &Array1<f64>) {
        match self {
            &mut Trace::Accumulating { ref mut eligibility, lambda } =>
            {
                *eligibility += phi;
            },
            &mut Trace::Replacing { ref mut eligibility, lambda } =>
            {
                eligibility.zip_mut_with(phi, |val, &p| {
                    *val = f64::min(1.0, *val + p);
                });
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Trace;
    use ndarray::{ArrayBase, arr1};

    #[test]
    fn test_accumulating() {
        let mut trace = Trace::Accumulating {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10])
        };

        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.95f64; 10]));
    }

    #[test]
    fn test_replacing() {
        let mut trace = Trace::Replacing {
            lambda: 0.95.into(),
            eligibility: arr1(&[0.0f64; 10])
        };

        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.0f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.0f64; 10]));

        trace.decay(1.0);
        assert_eq!(trace.get(), &arr1(&[0.95f64; 10]));

        trace.update(&arr1(&[1.0f64; 10]));
        assert_eq!(trace.get(), &arr1(&[1.0f64; 10]));
    }
}
<|endoftext|>


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

use uuid::Uuid;

pub type DevUuid = Uuid;
pub type FilesystemUuid = Uuid;
pub type PoolUuid = Uuid;

#[derive(Debug)]
pub enum RenameAction {
    Identity,
    NoSource,
    Renamed,
}

/// Redundancy classifications which the engine allows for pools.
custom_derive! {
    #[derive(Debug, Eq, PartialEq, EnumDisplay,
             IterVariants(RedundancyVariants))]
    #[allow(non_camel_case_types)]
    /// Redundancy specification for a pool.
    pub enum Redundancy {
        NONE,
    }
}

/// Get the u16 value of this Redundancy constructor.
impl From<Redundancy> for u16 {
    fn from(r: Redundancy) -> u16 {
        r as u16
    }
}
<commit_msg>Define equality for RenameAction<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use uuid::Uuid;

pub type DevUuid = Uuid;
pub type FilesystemUuid = Uuid;
pub type PoolUuid = Uuid;

#[derive(Debug, PartialEq, Eq)]
pub enum RenameAction {
    Identity,
    NoSource,
    Renamed,
}

/// Redundancy classifications which the engine allows for pools.
custom_derive! {
    #[derive(Debug, Eq, PartialEq, EnumDisplay,
             IterVariants(RedundancyVariants))]
    #[allow(non_camel_case_types)]
    /// Redundancy specification for a pool.
    pub enum Redundancy {
        NONE,
    }
}

/// Get the u16 value of this Redundancy constructor.
impl From<Redundancy> for u16 {
    fn from(r: Redundancy) -> u16 {
        r as u16
    }
}
<|endoftext|>


<commit_before>use engine::{Actor, Map};
use util::units::{Direction, Point};

use std::path::Path;

pub struct World {
    pub player: Actor,
    pub actors: Vec<Actor>,
    pub map: Map,
}

impl World {

    pub fn new() -> World {
        World {
            player: Actor::new("Player", Point::new(10, 10), 100, '@'),
            actors: Vec::new(),
            map: Map::from_file(Path::new("assets/maps/test.map")),
        }
    }

    pub fn walk(&mut self, direction: Direction) {
        if !self.map.is_walkable(self.player.pos.move_dir(direction)) { return; }

        self.player.walk(direction);
    }

}
<commit_msg>Remove unnecessary Path::new, and use AsPath overloading instead<commit_after>use engine::{Actor, Map};
use util::units::{Direction, Point};

pub struct World {
    pub player: Actor,
    pub actors: Vec<Actor>,
    pub map: Map,
}

impl World {

    pub fn new() -> World {
        World {
            player: Actor::new("Player", Point::new(10, 10), 100, '@'),
            actors: Vec::new(),
            map: Map::from_file("assets/maps/test.map"),
        }
    }

    pub fn walk(&mut self, direction: Direction) {
        if !self.map.is_walkable(self.player.pos.move_dir(direction)) { return; }

        self.player.walk(direction);
    }

}
<|endoftext|>


<commit_before>use std::str::raw;
use std::os::getenv;
use std::path::Path;
use std::libc::{c_int, c_char};
use sync::mutex::{StaticMutex, MUTEX_INIT};

static mut LOCK: StaticMutex = MUTEX_INIT;

static mut registered_drivers: bool = false;

struct Dataset {
    c_dataset: *(),
}

struct Driver {
    c_driver: *(),
}

#[link(name = "gdal")]
extern {
    fn GDALVersionInfo(key: *c_char) -> *c_char;
    fn GDALOpen(pszFilename: *c_char, eAccess: c_int) -> *();
    fn GDALClose(hDS: *());
    fn GDALGetDatasetDriver(hDataset: *()) -> *();
    fn GDALGetRasterXSize(hDataset: *()) -> c_int;
    fn GDALGetRasterYSize(hDataset: *()) -> c_int;
    fn GDALGetRasterCount(hDataset: *()) -> c_int;
    fn GDALGetProjectionRef(hDS: *()) -> *c_char;
    fn GDALSetProjection(hDS: *(), pszProjection: *c_char) -> c_int;
    fn GDALAllRegister();
    fn GDALGetDriverByName(pszName: *c_char) -> *();
    fn GDALGetDriverShortName(hDriver: *()) -> *c_char;
    fn GDALGetDriverLongName(hDriver: *()) -> *c_char;
}
static GA_ReadOnly: c_int = 0;
static GA_Update: c_int = 1;

pub fn version_info(key: &str) -> ~str {
    let info = key.with_c_str(|c_key| {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALVersionInfo(c_key));
        };
    });
    return info;
}

pub fn open(path: &Path) -> Option<Dataset> {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            GDALAllRegister();
            registered_drivers = true;
        }
    }
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        unsafe {
            let _g = LOCK.lock();
            return GDALOpen(c_filename, GA_ReadOnly);
        };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(Dataset{c_dataset: c_dataset}),
    };
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe {
            let _g = LOCK.lock();
            GDALClose(self.c_dataset);
        }
    }
}

impl Dataset {
    pub fn get_raster_size(&self) -> (int, int) {
        unsafe {
            let _g = LOCK.lock();
            let size_x = GDALGetRasterXSize(self.c_dataset) as int;
            let size_y = GDALGetRasterYSize(self.c_dataset) as int;
            return (size_x, size_y);
        }
    }

    pub fn get_driver(&self) -> Driver {
        let mut c_driver;
        unsafe {
            let _g = LOCK.lock();
            c_driver = GDALGetDatasetDriver(self.c_dataset);
        };
        return Driver{c_driver: c_driver};
    }

    pub fn get_raster_count(&self) -> int {
        unsafe {
            let _g = LOCK.lock();
            return GDALGetRasterCount(self.c_dataset) as int;
        }
    }

    pub fn get_projection(&self) -> ~str {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALGetProjectionRef(self.c_dataset));
        }
    }

    pub fn set_projection(&self, projection: &str) {
        projection.with_c_str(|c_projection| {
            unsafe {
                let _g = LOCK.lock();
                GDALSetProjection(self.c_dataset, c_projection);
            }
        });
    }
}

pub fn get_driver(name: &str) -> Option<Driver> {
    let c_driver = name.with_c_str(|c_name| {
        unsafe {
            let _g = LOCK.lock();
            return GDALGetDriverByName(c_name);
        }
    });
    return match c_driver.is_null() {
        true  => None,
        false => Some(Driver{c_driver: c_driver}),
    };
}

impl Driver {
    pub fn get_short_name(&self) -> ~str {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALGetDriverShortName(self.c_driver));
        }
    }

    pub fn get_long_name(&self) -> ~str {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALGetDriverLongName(self.c_driver));
        }
    }
}

#[test]
fn test_version_info() {
    let release_date = version_info("RELEASE_DATE");
    let release_name = version_info("RELEASE_NAME");
    let version_text = version_info("--version");

    let expected_text: ~str = "GDAL " + release_name + ", " +
        "released " + release_date.slice(0, 4) + "/" +
        release_date.slice(4, 6) + "/" + release_date.slice(6, 8);

    assert_eq!(version_text.into_owned(), expected_text);
}

fn fixture_path(name: &str) -> Path {
    let envvar = "RUSTILES_TEST_FIXTURES";
    let fixtures = match getenv(envvar) {
        Some(p) => Path::new(p),
        None => fail!("Environment variable {} not set", envvar)
    };
    let rv = fixtures.join(name);
    return rv;
}

#[test]
fn test_open() {
    let dataset = open(&fixture_path("tinymarble.jpeg"));
    assert!(dataset.is_some());

    let missing_dataset = open(&fixture_path("no_such_file.jpeg"));
    assert!(missing_dataset.is_none());
}

#[test]
fn test_get_raster_size() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let (size_x, size_y) = dataset.get_raster_size();
    assert_eq!(size_x, 100);
    assert_eq!(size_y, 50);
}

#[test]
fn test_get_raster_count() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let count = dataset.get_raster_count();
    assert_eq!(count, 3);
}

#[test]
fn test_get_projection() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    //dataset.set_projection("WGS84");
    let projection = dataset.get_projection();
    assert_eq!(projection.slice(0, 16), "GEOGCS[\"WGS 84\",");
}

#[test]
fn test_get_dataset_driver() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let driver = dataset.get_driver();
    assert_eq!(driver.get_short_name(), ~"JPEG");
    assert_eq!(driver.get_long_name(), ~"JPEG JFIF");
}

#[test]
fn test_get_driver_by_name() {
    let missing_driver = get_driver("wtf");
    assert!(missing_driver.is_none());

    let ok_driver = get_driver("GTiff");
    assert!(ok_driver.is_some());
    let driver = ok_driver.unwrap();
    assert_eq!(driver.get_short_name(), ~"GTiff");
    assert_eq!(driver.get_long_name(), ~"GeoTIFF");
}
<commit_msg>extract `register_drivers` function<commit_after>use std::str::raw;
use std::os::getenv;
use std::path::Path;
use std::libc::{c_int, c_char};
use sync::mutex::{StaticMutex, MUTEX_INIT};

static mut LOCK: StaticMutex = MUTEX_INIT;

static mut registered_drivers: bool = false;

struct Dataset {
    c_dataset: *(),
}

struct Driver {
    c_driver: *(),
}

#[link(name = "gdal")]
extern {
    fn GDALVersionInfo(key: *c_char) -> *c_char;
    fn GDALOpen(pszFilename: *c_char, eAccess: c_int) -> *();
    fn GDALClose(hDS: *());
    fn GDALGetDatasetDriver(hDataset: *()) -> *();
    fn GDALGetRasterXSize(hDataset: *()) -> c_int;
    fn GDALGetRasterYSize(hDataset: *()) -> c_int;
    fn GDALGetRasterCount(hDataset: *()) -> c_int;
    fn GDALGetProjectionRef(hDS: *()) -> *c_char;
    fn GDALSetProjection(hDS: *(), pszProjection: *c_char) -> c_int;
    fn GDALAllRegister();
    fn GDALGetDriverByName(pszName: *c_char) -> *();
    fn GDALGetDriverShortName(hDriver: *()) -> *c_char;
    fn GDALGetDriverLongName(hDriver: *()) -> *c_char;
}
static GA_ReadOnly: c_int = 0;
static GA_Update: c_int = 1;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            GDALAllRegister();
            registered_drivers = true;
        }
    }
}

pub fn version_info(key: &str) -> ~str {
    let info = key.with_c_str(|c_key| {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALVersionInfo(c_key));
        };
    });
    return info;
}

pub fn open(path: &Path) -> Option<Dataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        unsafe {
            let _g = LOCK.lock();
            return GDALOpen(c_filename, GA_ReadOnly);
        };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(Dataset{c_dataset: c_dataset}),
    };
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe {
            let _g = LOCK.lock();
            GDALClose(self.c_dataset);
        }
    }
}

impl Dataset {
    pub fn get_raster_size(&self) -> (int, int) {
        unsafe {
            let _g = LOCK.lock();
            let size_x = GDALGetRasterXSize(self.c_dataset) as int;
            let size_y = GDALGetRasterYSize(self.c_dataset) as int;
            return (size_x, size_y);
        }
    }

    pub fn get_driver(&self) -> Driver {
        let mut c_driver;
        unsafe {
            let _g = LOCK.lock();
            c_driver = GDALGetDatasetDriver(self.c_dataset);
        };
        return Driver{c_driver: c_driver};
    }

    pub fn get_raster_count(&self) -> int {
        unsafe {
            let _g = LOCK.lock();
            return GDALGetRasterCount(self.c_dataset) as int;
        }
    }

    pub fn get_projection(&self) -> ~str {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALGetProjectionRef(self.c_dataset));
        }
    }

    pub fn set_projection(&self, projection: &str) {
        projection.with_c_str(|c_projection| {
            unsafe {
                let _g = LOCK.lock();
                GDALSetProjection(self.c_dataset, c_projection);
            }
        });
    }
}

pub fn get_driver(name: &str) -> Option<Driver> {
    let c_driver = name.with_c_str(|c_name| {
        unsafe {
            let _g = LOCK.lock();
            return GDALGetDriverByName(c_name);
        }
    });
    return match c_driver.is_null() {
        true  => None,
        false => Some(Driver{c_driver: c_driver}),
    };
}

impl Driver {
    pub fn get_short_name(&self) -> ~str {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALGetDriverShortName(self.c_driver));
        }
    }

    pub fn get_long_name(&self) -> ~str {
        unsafe {
            let _g = LOCK.lock();
            return raw::from_c_str(GDALGetDriverLongName(self.c_driver));
        }
    }
}

#[test]
fn test_version_info() {
    let release_date = version_info("RELEASE_DATE");
    let release_name = version_info("RELEASE_NAME");
    let version_text = version_info("--version");

    let expected_text: ~str = "GDAL " + release_name + ", " +
        "released " + release_date.slice(0, 4) + "/" +
        release_date.slice(4, 6) + "/" + release_date.slice(6, 8);

    assert_eq!(version_text.into_owned(), expected_text);
}

fn fixture_path(name: &str) -> Path {
    let envvar = "RUSTILES_TEST_FIXTURES";
    let fixtures = match getenv(envvar) {
        Some(p) => Path::new(p),
        None => fail!("Environment variable {} not set", envvar)
    };
    let rv = fixtures.join(name);
    return rv;
}

#[test]
fn test_open() {
    let dataset = open(&fixture_path("tinymarble.jpeg"));
    assert!(dataset.is_some());

    let missing_dataset = open(&fixture_path("no_such_file.jpeg"));
    assert!(missing_dataset.is_none());
}

#[test]
fn test_get_raster_size() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let (size_x, size_y) = dataset.get_raster_size();
    assert_eq!(size_x, 100);
    assert_eq!(size_y, 50);
}

#[test]
fn test_get_raster_count() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let count = dataset.get_raster_count();
    assert_eq!(count, 3);
}

#[test]
fn test_get_projection() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    //dataset.set_projection("WGS84");
    let projection = dataset.get_projection();
    assert_eq!(projection.slice(0, 16), "GEOGCS[\"WGS 84\",");
}

#[test]
fn test_get_dataset_driver() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let driver = dataset.get_driver();
    assert_eq!(driver.get_short_name(), ~"JPEG");
    assert_eq!(driver.get_long_name(), ~"JPEG JFIF");
}

#[test]
fn test_get_driver_by_name() {
    let missing_driver = get_driver("wtf");
    assert!(missing_driver.is_none());

    let ok_driver = get_driver("GTiff");
    assert!(ok_driver.is_some());
    let driver = ok_driver.unwrap();
    assert_eq!(driver.get_short_name(), ~"GTiff");
    assert_eq!(driver.get_long_name(), ~"GeoTIFF");
}
<|endoftext|>