<commit_before>use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::error::Error;
use std::panic;

macro_rules! fetch_tag {
  ($tiff:expr, $tag:expr) => (try!($tiff.find_entry($tag).ok_or(format!("Couldn't find tag {}",stringify!($tag)).to_string())););
}

extern crate toml;
mod basics;
mod tiff;
mod mrw;
mod arw;
mod mef;
mod orf;
mod srw;
mod erf;
mod kdc;
mod dcs;
mod rw2;
use self::basics::*;
use self::tiff::*;

pub static CAMERAS_TOML: &'static str = include_str!("../../data/cameras/all.toml");

pub trait Decoder {
  fn image(&self) -> Result<Image, String>;
}

#[derive(Debug, Clone)]
pub struct Buffer {
  buf: Vec<u8>,
}

impl Buffer {
  pub fn new(reader: &mut Read) -> Result<Buffer, String> {
    let mut buffer = Vec::new();
    if let Err(err) = reader.read_to_end(&mut buffer) {
      return Err(format!("IOError: {}", err).to_string())
    }
    buffer.extend([0;16].iter().cloned());
    Ok(Buffer {
      buf: buffer,
    })
  }
}

#[derive(Debug, Clone)]
pub struct Image {
  pub make: String,
  pub model: String,
  pub canonical_make: String,
  pub canonical_model: String,
  pub width: usize,
  pub height: usize,
  pub wb_coeffs: [f32;4],
  pub data: Box<[u16]>,
  pub whitelevels: [i64;4],
  pub blacklevels: [i64;4],
  pub color_matrix: [i64;12],
  pub dcraw_filters: u32,
  pub crops: [i64;4],
}

#[derive(Debug, Clone)]
pub struct Camera {
  pub make: String,
  pub model: String,
  pub canonical_make: String,
  pub canonical_model: String,
  whitelevels: [i64;4],
  blacklevels: [i64;4],
  color_matrix: [i64;12],
  dcraw_filters: u32,
  crops: [i64;4],
  bps: u32,
  hints: Vec<String>,
}

impl Camera {
  pub fn find_hint(&self, hint: &str) -> bool {
    self.hints.contains(&(hint.to_string()))
  }
}

pub fn ok_image(camera: &Camera, width: u32, height: u32, wb_coeffs: [f32;4], image: Vec<u16>) -> Result<Image,String> {
  Ok(Image {
    make: camera.make.clone(),
    model: camera.model.clone(),
    canonical_make: camera.canonical_make.clone(),
    canonical_model: camera.canonical_model.clone(),
    width: width as usize,
    height: height as usize,
    wb_coeffs: wb_coeffs,
    data: image.into_boxed_slice(),
    blacklevels: camera.blacklevels,
    whitelevels: camera.whitelevels,
    color_matrix: camera.color_matrix,
    dcraw_filters: camera.dcraw_filters,
    crops: camera.crops,
  })
}

//pub fn ok_image_with_levels(camera: &Camera, width: u32, height: u32, wb_coeffs: [f32;4], whites: [i64;4], blacks: [i64;4], image: Vec<u16>) -> Result<Image,String> {
//  Ok(Image {
//    make: camera.make.clone(),
//    model: camera.model.clone(),
//    canonical_make: camera.canonical_make.clone(),
//    canonical_model: camera.canonical_model.clone(),
//    width: width,
//    height: height,
//    wb_coeffs: wb_coeffs,
//    data: image.into_boxed_slice(),
//    blacklevels: blacks,
//    whitelevels: whites,
//    color_matrix: camera.color_matrix,
//    dcraw_filters: camera.dcraw_filters,
//    crops: camera.crops,
//  })
//}

#[derive(Debug, Clone)]
pub struct RawLoader {
  pub cameras: HashMap<(String,String),Camera>,
}

impl RawLoader {
  pub fn new() -> RawLoader {
    let mut map = HashMap::new();

    let mut parser = toml::Parser::new(&CAMERAS_TOML);
    let toml = match parser.parse() {
      Some(val) => val,
      None => panic!(format!("Error parsing all.toml: {:?}", parser.errors)),
    };
    for camera in toml.get("cameras").unwrap().as_slice().unwrap() {
      let ct = camera.as_table().unwrap();
      let make = ct.get("make").unwrap().as_str().unwrap().to_string();
      let model = ct.get("model").unwrap().as_str().unwrap().to_string();
      let canonical_make = ct.get("canonical_make").unwrap().as_str().unwrap().to_string();
      let canonical_model = ct.get("canonical_model").unwrap().as_str().unwrap().to_string();
      let white = ct.get("whitepoint").unwrap().as_integer().unwrap();
      let black = ct.get("blackpoint").unwrap().as_integer().unwrap();
      let matrix = ct.get("color_matrix").unwrap().as_slice().unwrap();
      let mut cmatrix: [i64;12] = [0,0,0,0,0,0,0,0,0,0,0,0];
      for (i, val) in matrix.into_iter().enumerate() {
        cmatrix[i] = val.as_integer().unwrap();
      }
      let crop_vals = ct.get("crops").unwrap().as_slice().unwrap();
      let mut crops: [i64;4] = [0,0,0,0];
      for (i, val) in crop_vals.into_iter().enumerate() {
        crops[i] = val.as_integer().unwrap();
      }
      let color_pattern = ct.get("color_pattern").unwrap().as_str().unwrap().to_string();
      let bps: u32 = match ct.get("bps") {
        Some(x) => x.as_integer().unwrap() as u32,
        None => 0,
      };
      let mut hints: Vec<String> = Vec::new();
      match ct.get("hints") {
        None => {},
        Some(x) => {
          for val in x.as_slice().unwrap() {
            hints.push(val.as_str().unwrap().to_string());
          }
        },
      }
      let cam = Camera{
        make: make.clone(),
        model: model.clone(),
        canonical_make: canonical_make.clone(),
        canonical_model: canonical_model.clone(),
        whitelevels: [white, white, white, white],
        blacklevels: [black, black, black, black],
        color_matrix : cmatrix,
        dcraw_filters: RawLoader::dcraw_filters(&color_pattern),
        crops: crops,
        bps: bps,
        hints: hints,
      };
      map.insert((make.clone(),model.clone()), cam);
    }

    RawLoader{
      cameras: map,
    }
  }

  pub fn get_decoder<'b>(&'b self, buf: &'b Buffer) -> Result<Box<Decoder+'b>, String> {
    let buffer = &buf.buf;

    if mrw::is_mrw(buffer) {
      let dec = Box::new(mrw::MrwDecoder::new(buffer, &self));
      return Ok(dec as Box<Decoder>);
    }

    let endian = match LEu16(&buffer, 0) {
      0x4949 => LITTLE_ENDIAN,
      0x4d4d => BIG_ENDIAN,
      x => {return Err(format!("Couldn't find decoder for marker 0x{:x}", x).to_string())},
    };

    macro_rules! use_decoder {
        ($dec:ty, $buf:ident, $tiff:ident, $rawdec:ident) => (Ok(Box::new(<$dec>::new($buf, $tiff, $rawdec)) as Box<Decoder>));
    }

    let tiff = TiffIFD::new_root(buffer, 4, 0, endian);
    let make: &str = &(try!(tiff.find_entry(Tag::Make).ok_or("Couldn't find Make".to_string())).get_str().to_string());

    match make {
      "SONY"                    => use_decoder!(arw::ArwDecoder, buffer, tiff, self),
      "Mamiya-OP Co.,Ltd."      => use_decoder!(mef::MefDecoder, buffer, tiff, self),
      "OLYMPUS IMAGING CORP."   => use_decoder!(orf::OrfDecoder, buffer, tiff, self),
      "OLYMPUS CORPORATION"     => use_decoder!(orf::OrfDecoder, buffer, tiff, self),
      "OLYMPUS OPTICAL CO.,LTD" => use_decoder!(orf::OrfDecoder, buffer, tiff, self),
      "SAMSUNG"                 => use_decoder!(srw::SrwDecoder, buffer, tiff, self),
      "SEIKO EPSON CORP."       => use_decoder!(erf::ErfDecoder, buffer, tiff, self),
      "EASTMAN KODAK COMPANY"   => use_decoder!(kdc::KdcDecoder, buffer, tiff, self),
      "KODAK"                   => use_decoder!(dcs::DcsDecoder, buffer, tiff, self),
      "Panasonic"               => use_decoder!(rw2::Rw2Decoder, buffer, tiff, self),
      make => Err(format!("Couldn't find a decoder for make \"{}\"", make).to_string()),
    }
  }

  pub fn check_supported<'a>(&'a self, tiff: &'a TiffIFD) -> Result<&Camera, String> {
    let make = fetch_tag!(tiff, Tag::Make).get_str();
    let model = fetch_tag!(tiff, Tag::Model).get_str();

    match self.cameras.get(&(make.to_string(),model.to_string())) {
      Some(cam) => Ok(cam),
      None => Err(format!("Couldn't find camera \"{}\" \"{}\"", make, model)),
    }
  }

  fn dcraw_filters(pattern: &str) -> u32 {
    match pattern {
      "BGGR" => 0x16161616,
      "GRBG" => 0x61616161,
      "GBRG" => 0x49494949,
      "RGGB" => 0x94949494,
      "ERBG" => 0x63636363,
      _ => 0,
    }
  }

  pub fn decode(&self, reader: &mut Read) -> Result<Image, String> {
    let buffer = try!(Buffer::new(reader));
    let decoder = try!(self.get_decoder(&buffer));
    decoder.image()
  }

  pub fn decode_safe(&self, path: &str) -> Result<Image, String> {
    match panic::catch_unwind(|| {
      let mut f = match File::open(path) {
        Ok(val) => val,
        Err(e) => {return Err(e.description().to_string())},
      };
      self.decode(&mut f)
    }) {
      Ok(val) => val,
      Err(_) => Err("Caught a panic while decoding, please file a bug and attach a sample file".to_string()),
    }
  }
}
<commit_msg>Add camera modes to the defs<commit_after>use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::error::Error;
use std::panic;

macro_rules! fetch_tag {
  ($tiff:expr, $tag:expr) => (try!($tiff.find_entry($tag).ok_or(format!("Couldn't find tag {}",stringify!($tag)).to_string())););
}

extern crate toml;
mod basics;
mod tiff;
mod mrw;
mod arw;
mod mef;
mod orf;
mod srw;
mod erf;
mod kdc;
mod dcs;
mod rw2;
use self::basics::*;
use self::tiff::*;

pub static CAMERAS_TOML: &'static str = include_str!("../../data/cameras/all.toml");

pub trait Decoder {
  fn image(&self) -> Result<Image, String>;
}

#[derive(Debug, Clone)]
pub struct Buffer {
  buf: Vec<u8>,
}

impl Buffer {
  pub fn new(reader: &mut Read) -> Result<Buffer, String> {
    let mut buffer = Vec::new();
    if let Err(err) = reader.read_to_end(&mut buffer) {
      return Err(format!("IOError: {}", err).to_string())
    }
    buffer.extend([0;16].iter().cloned());
    Ok(Buffer {
      buf: buffer,
    })
  }
}

#[derive(Debug, Clone)]
pub struct Image {
  pub make: String,
  pub model: String,
  pub canonical_make: String,
  pub canonical_model: String,
  pub width: usize,
  pub height: usize,
  pub wb_coeffs: [f32;4],
  pub data: Box<[u16]>,
  pub whitelevels: [i64;4],
  pub blacklevels: [i64;4],
  pub color_matrix: [i64;12],
  pub dcraw_filters: u32,
  pub crops: [i64;4],
}

#[derive(Debug, Clone)]
pub struct Camera {
  pub make: String,
  pub model: String,
  pub mode: String,
  pub canonical_make: String,
  pub canonical_model: String,
  whitelevels: [i64;4],
  blacklevels: [i64;4],
  color_matrix: [i64;12],
  dcraw_filters: u32,
  crops: [i64;4],
  bps: u32,
  hints: Vec<String>,
}

impl Camera {
  pub fn find_hint(&self, hint: &str) -> bool {
    self.hints.contains(&(hint.to_string()))
  }

  pub fn update_from_toml(&mut self, ct: &toml::Table) {
    for (name, val) in ct {
      match name.as_ref() {
        "make" => {self.make = val.as_str().unwrap().to_string().clone();},
        "model" => {self.model = val.as_str().unwrap().to_string().clone();},
        "mode" => {self.mode = val.as_str().unwrap().to_string().clone();},
        "canonical_name" => {self.canonical_make = val.as_str().unwrap().to_string().clone();},
        "canonical_model" => {self.canonical_model = val.as_str().unwrap().to_string().clone();},
        "whitepoint" => {let white = val.as_integer().unwrap(); self.whitelevels = [white, white, white, white];},
        "blackpoint" => {let black = val.as_integer().unwrap(); self.blacklevels = [black, black, black, black];},
        "color_matrix" => {
          let matrix = val.as_slice().unwrap();
          for (i, val) in matrix.into_iter().enumerate() {
            self.color_matrix[i] = val.as_integer().unwrap();
          }
        },
        "crops" => {
          let crop_vals = val.as_slice().unwrap();
          for (i, val) in crop_vals.into_iter().enumerate() {
            self.crops[i] = val.as_integer().unwrap();
          }
        },
        "color_pattern" => {self.dcraw_filters = RawLoader::dcraw_filters(&val.as_str().unwrap().to_string());},
        "bps" => {self.bps = val.as_integer().unwrap() as u32;},
        "hints" => {
          self.hints = Vec::new();
          for hint in val.as_slice().unwrap() {
            self.hints.push(hint.as_str().unwrap().to_string());
          }
        },
        _ => {},
      }
    }
  }

  pub fn new() -> Camera {
    Camera {
      make: "".to_string(),
      model: "".to_string(),
      mode: "".to_string(),
      canonical_make: "".to_string(),
      canonical_model: "".to_string(),
      whitelevels: [0;4],
      blacklevels: [0;4],
      color_matrix : [0;12],
      dcraw_filters: 0,
      crops: [0,0,0,0],
      bps: 0,
      hints: Vec::new(),
    }
  }
}

pub fn ok_image(camera: &Camera, width: u32, height: u32, wb_coeffs: [f32;4], image: Vec<u16>) -> Result<Image,String> {
  Ok(Image {
    make: camera.make.clone(),
    model: camera.model.clone(),
    canonical_make: camera.canonical_make.clone(),
    canonical_model: camera.canonical_model.clone(),
    width: width as usize,
    height: height as usize,
    wb_coeffs: wb_coeffs,
    data: image.into_boxed_slice(),
    blacklevels: camera.blacklevels,
    whitelevels: camera.whitelevels,
    color_matrix: camera.color_matrix,
    dcraw_filters: camera.dcraw_filters,
    crops: camera.crops,
  })
}

//pub fn ok_image_with_levels(camera: &Camera, width: u32, height: u32, wb_coeffs: [f32;4], whites: [i64;4], blacks: [i64;4], image: Vec<u16>) -> Result<Image,String> {
//  Ok(Image {
//    make: camera.make.clone(),
//    model: camera.model.clone(),
//    canonical_make: camera.canonical_make.clone(),
//    canonical_model: camera.canonical_model.clone(),
//    width: width,
//    height: height,
//    wb_coeffs: wb_coeffs,
//    data: image.into_boxed_slice(),
//    blacklevels: blacks,
//    whitelevels: whites,
//    color_matrix: camera.color_matrix,
//    dcraw_filters: camera.dcraw_filters,
//    crops: camera.crops,
//  })
//}

#[derive(Debug, Clone)]
pub struct RawLoader {
  pub cameras: HashMap<(String,String,String),Camera>,
}

impl RawLoader {
  pub fn new() -> RawLoader {
    let mut parser = toml::Parser::new(&CAMERAS_TOML);
    let toml = match parser.parse() {
      Some(val) => val,
      None => panic!(format!("Error parsing all.toml: {:?}", parser.errors)),
    };
    let mut cams = Vec::new();
    for camera in toml.get("cameras").unwrap().as_slice().unwrap() {
      let ct = camera.as_table().unwrap();
      let mut cam = Camera::new();
      cam.update_from_toml(ct);
      let basecam = cam.clone();
      cams.push(cam);

      match ct.get("modes") {
        Some(val) => {
          for mode in val.as_slice().unwrap() {
            let cmt = mode.as_table().unwrap();
            let mut mcam = basecam.clone();
            mcam.update_from_toml(cmt);
            cams.push(mcam);
          }
        },
        None => {},
      }
    }

    let mut map = HashMap::new();
    for cam in cams {
      map.insert((cam.make.clone(),cam.model.clone(),cam.mode.clone()), cam);
    }

    RawLoader{
      cameras: map,
    }
  }

  pub fn get_decoder<'b>(&'b self, buf: &'b Buffer) -> Result<Box<Decoder+'b>, String> {
    let buffer = &buf.buf;

    if mrw::is_mrw(buffer) {
      let dec = Box::new(mrw::MrwDecoder::new(buffer, &self));
      return Ok(dec as Box<Decoder>);
    }

    let endian = match LEu16(&buffer, 0) {
      0x4949 => LITTLE_ENDIAN,
      0x4d4d => BIG_ENDIAN,
      x => {return Err(format!("Couldn't find decoder for marker 0x{:x}", x).to_string())},
    };

    macro_rules! use_decoder {
        ($dec:ty, $buf:ident, $tiff:ident, $rawdec:ident) => (Ok(Box::new(<$dec>::new($buf, $tiff, $rawdec)) as Box<Decoder>));
    }

    let tiff = TiffIFD::new_root(buffer, 4, 0, endian);
    let make: &str = &(try!(tiff.find_entry(Tag::Make).ok_or("Couldn't find Make".to_string())).get_str().to_string());

    match make {
      "SONY"                    => use_decoder!(arw::ArwDecoder, buffer, tiff, self),
      "Mamiya-OP Co.,Ltd."      => use_decoder!(mef::MefDecoder, buffer, tiff, self),
      "OLYMPUS IMAGING CORP."   => use_decoder!(orf::OrfDecoder, buffer, tiff, self),
      "OLYMPUS CORPORATION"     => use_decoder!(orf::OrfDecoder, buffer, tiff, self),
      "OLYMPUS OPTICAL CO.,LTD" => use_decoder!(orf::OrfDecoder, buffer, tiff, self),
      "SAMSUNG"                 => use_decoder!(srw::SrwDecoder, buffer, tiff, self),
      "SEIKO EPSON CORP."       => use_decoder!(erf::ErfDecoder, buffer, tiff, self),
      "EASTMAN KODAK COMPANY"   => use_decoder!(kdc::KdcDecoder, buffer, tiff, self),
      "KODAK"                   => use_decoder!(dcs::DcsDecoder, buffer, tiff, self),
      "Panasonic"               => use_decoder!(rw2::Rw2Decoder, buffer, tiff, self),
      make => Err(format!("Couldn't find a decoder for make \"{}\"", make).to_string()),
    }
  }

  pub fn check_supported<'a>(&'a self, tiff: &'a TiffIFD) -> Result<&Camera, String> {
    let make = fetch_tag!(tiff, Tag::Make).get_str();
    let model = fetch_tag!(tiff, Tag::Model).get_str();

    match self.cameras.get(&(make.to_string(),model.to_string(),"".to_string())) {
      Some(cam) => Ok(cam),
      None => Err(format!("Couldn't find camera \"{}\" \"{}\"", make, model)),
    }
  }

  fn dcraw_filters(pattern: &str) -> u32 {
    match pattern {
      "BGGR" => 0x16161616,
      "GRBG" => 0x61616161,
      "GBRG" => 0x49494949,
      "RGGB" => 0x94949494,
      "ERBG" => 0x63636363,
      _ => 0,
    }
  }

  pub fn decode(&self, reader: &mut Read) -> Result<Image, String> {
    let buffer = try!(Buffer::new(reader));
    let decoder = try!(self.get_decoder(&buffer));
    decoder.image()
  }

  pub fn decode_safe(&self, path: &str) -> Result<Image, String> {
    match panic::catch_unwind(|| {
      let mut f = match File::open(path) {
        Ok(val) => val,
        Err(e) => {return Err(e.description().to_string())},
      };
      self.decode(&mut f)
    }) {
      Ok(val) => val,
      Err(_) => Err("Caught a panic while decoding, please file a bug and attach a sample file".to_string()),
    }
  }
}
<|endoftext|>


<commit_before>use std::{fmt, io};

use AsyncRead;
use framed::Fuse;

use futures::{Async, Poll, Stream, Sink, StartSend};
use bytes::BytesMut;

/// Decoding of frames via buffers.
///
/// This trait is used when constructing an instance of `Framed` or
/// `FramedRead`. An implementation of `Decoder` takes a byte stream that has
/// already been buffered in `src` and decodes the data into a stream of
/// `Self::Item` frames.
///
/// Implementations are able to track state on `self`, which enables
/// implementing stateful streaming parsers. In many cases, though, this type
/// will simply be a unit struct (e.g. `struct HttpDecoder`).
pub trait Decoder {
    /// The type of decoded frames.
    type Item;

    /// The type of unrecoverable frame decoding errors.
    ///
    /// If an individual message is ill-formed but can be ignored without
    /// interfering with the processing of future messages, it may be more
    /// useful to report the failure as an `Item`.
    ///
    /// `From<io::Error>` is required in the interest of making `Error` suitable
    /// for returning directly from a `FramedRead`, and to enable the default
    /// implementation of `decode_eof` to yield an `io::Error` when the decoder
    /// fails to consume all available data.
    ///
    /// Note that implementors of this trait can simply indicate `type Error =
    /// io::Error` to use I/O errors as this type.
    type Error: From<io::Error>;

    /// Attempts to decode a frame from the provided buffer of bytes.
    ///
    /// This method is called by `FramedRead` whenever bytes are ready to be
    /// parsed.  The provided buffer of bytes is what's been read so far, and
    /// this instance of `Decode` can determine whether an entire frame is in
    /// the buffer and is ready to be returned.
    ///
    /// If an entire frame is available, then this instance will remove those
    /// bytes from the buffer provided and return them as a decoded
    /// frame. Note that removing bytes from the provided buffer doesn't always
    /// necessarily copy the bytes, so this should be an efficient operation in
    /// most circumstances.
    ///
    /// If the bytes look valid, but a frame isn't fully available yet, then
    /// `Ok(None)` is returned. This indicates to the `Framed` instance that
    /// it needs to read some more bytes before calling this method again.
    ///
    /// Note that the bytes provided may be empty. If a previous call to
    /// `decode` consumed all the bytes in the buffer then `decode` will be
    /// called again until it returns `None`, indicating that more bytes need to
    /// be read.
    ///
    /// Finally, if the bytes in the buffer are malformed then an error is
    /// returned indicating why. This informs `Framed` that the stream is now
    /// corrupt and should be terminated.
    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error>;

    /// A default method available to be called when there are no more bytes
    /// available to be read from the underlying I/O.
    ///
    /// This method defaults to calling `decode` and returns an error if
    /// `Ok(None)` is returned while there is unconsumed data in `buf`.
    /// Typically this doesn't need to be implemented unless the framing
    /// protocol differs near the end of the stream.
    ///
    /// Note that the `buf` argument may be empty. If a previous call to
    /// `decode_eof` consumed all the bytes in the bufer, `decode_eof` will be
    /// called again until it returns `None`, indicating that there are no more
    /// frames to yield. This behavior enables returning finalization frames
    /// that may not be based on inbound data.
    fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        match try!(self.decode(buf)) {
            Some(frame) => Ok(Some(frame)),
            None => {
                if buf.is_empty() {
                    Ok(None)
                } else {
                    Err(io::Error::new(io::ErrorKind::Other,
                                       "bytes remaining on stream").into())
                }
            }
        }
    }
}

/// A `Stream` of messages decoded from an `AsyncRead`.
pub struct FramedRead<T, D> {
    inner: FramedRead2<Fuse<T, D>>,
}

pub struct FramedRead2<T> {
    inner: T,
    eof: bool,
    is_readable: bool,
    buffer: BytesMut,
}

const INITIAL_CAPACITY: usize = 8 * 1024;

// ===== impl FramedRead =====

impl<T, D> FramedRead<T, D>
    where T: AsyncRead,
          D: Decoder,
{
    /// Creates a new `FramedRead` with the given `decoder`.
    pub fn new(inner: T, decoder: D) -> FramedRead<T, D> {
        FramedRead {
            inner: framed_read2(Fuse(inner, decoder)),
        }
    }
}

impl<T, D> FramedRead<T, D> {
    /// Returns a reference to the underlying I/O stream wrapped by
    /// `FramedRead`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.inner.0
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `FramedRead`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.inner.0
    }

    /// Consumes the `FramedRead`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.inner.0
    }

    /// Returns a reference to the underlying decoder.
    pub fn decoder(&self) -> &D {
        &self.inner.inner.1
    }

    /// Returns a mutable reference to the underlying decoder.
    pub fn decoder_mut(&mut self) -> &mut D {
        &mut self.inner.inner.1
    }
}

impl<T, D> Stream for FramedRead<T, D>
    where T: AsyncRead,
          D: Decoder,
{
    type Item = D::Item;
    type Error = D::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.inner.poll()
    }
}

impl<T, D> Sink for FramedRead<T, D>
    where T: Sink,
{
    type SinkItem = T::SinkItem;
    type SinkError = T::SinkError;

    fn start_send(&mut self,
                  item: Self::SinkItem)
                  -> StartSend<Self::SinkItem, Self::SinkError>
    {
        self.inner.inner.0.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.inner.0.poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.inner.0.close()
    }
}

impl<T, D> fmt::Debug for FramedRead<T, D>
    where T: fmt::Debug,
          D: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FramedRead")
            .field("inner", &self.inner.inner.0)
            .field("decoder", &self.inner.inner.1)
            .field("eof", &self.inner.eof)
            .field("is_readable", &self.inner.is_readable)
            .field("buffer", &self.inner.buffer)
            .finish()
    }
}

// ===== impl FramedRead2 =====

pub fn framed_read2<T>(inner: T) -> FramedRead2<T> {
    FramedRead2 {
        inner: inner,
        eof: false,
        is_readable: false,
        buffer: BytesMut::with_capacity(INITIAL_CAPACITY),
    }
}

impl<T> FramedRead2<T> {
    pub fn get_ref(&self) -> &T {
        &self.inner
    }

    pub fn into_inner(self) -> T {
        self.inner
    }

    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner
    }
}

impl<T> Stream for FramedRead2<T>
    where T: AsyncRead + Decoder,
{
    type Item = T::Item;
    type Error = T::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            // Repeatedly call `decode` or `decode_eof` as long as it is
            // "readable". Readable is defined as not having returned `None`. If
            // the upstream has returned EOF, and the decoder is no longer
            // readable, it can be assumed that the decoder will never become
            // readable again, at which point the stream is terminated.
            if self.is_readable {
                if self.eof {
                    let frame = try!(self.inner.decode_eof(&mut self.buffer));
                    return Ok(Async::Ready(frame));
                }

                trace!("attempting to decode a frame");

                if let Some(frame) = try!(self.inner.decode(&mut self.buffer)) {
                    trace!("frame decoded from buffer");
                    return Ok(Async::Ready(Some(frame)));
                }

                self.is_readable = false;
            }

            assert!(!self.eof);

            // Otherwise, try to read more data and try again. Make sure we've
            // got room for at least one byte to read to ensure that we don't
            // get a spurious 0 that looks like EF
            self.buffer.reserve(1);
            if 0 == try_ready!(self.inner.read_buf(&mut self.buffer)) {
                self.eof = true;
            }

            self.is_readable = true;
        }
    }
}
<commit_msg>Correct a minor spelling error in framed_read.rs: "EF" → "EOF"<commit_after>use std::{fmt, io};

use AsyncRead;
use framed::Fuse;

use futures::{Async, Poll, Stream, Sink, StartSend};
use bytes::BytesMut;

/// Decoding of frames via buffers.
///
/// This trait is used when constructing an instance of `Framed` or
/// `FramedRead`. An implementation of `Decoder` takes a byte stream that has
/// already been buffered in `src` and decodes the data into a stream of
/// `Self::Item` frames.
///
/// Implementations are able to track state on `self`, which enables
/// implementing stateful streaming parsers. In many cases, though, this type
/// will simply be a unit struct (e.g. `struct HttpDecoder`).
pub trait Decoder {
    /// The type of decoded frames.
    type Item;

    /// The type of unrecoverable frame decoding errors.
    ///
    /// If an individual message is ill-formed but can be ignored without
    /// interfering with the processing of future messages, it may be more
    /// useful to report the failure as an `Item`.
    ///
    /// `From<io::Error>` is required in the interest of making `Error` suitable
    /// for returning directly from a `FramedRead`, and to enable the default
    /// implementation of `decode_eof` to yield an `io::Error` when the decoder
    /// fails to consume all available data.
    ///
    /// Note that implementors of this trait can simply indicate `type Error =
    /// io::Error` to use I/O errors as this type.
    type Error: From<io::Error>;

    /// Attempts to decode a frame from the provided buffer of bytes.
    ///
    /// This method is called by `FramedRead` whenever bytes are ready to be
    /// parsed.  The provided buffer of bytes is what's been read so far, and
    /// this instance of `Decode` can determine whether an entire frame is in
    /// the buffer and is ready to be returned.
    ///
    /// If an entire frame is available, then this instance will remove those
    /// bytes from the buffer provided and return them as a decoded
    /// frame. Note that removing bytes from the provided buffer doesn't always
    /// necessarily copy the bytes, so this should be an efficient operation in
    /// most circumstances.
    ///
    /// If the bytes look valid, but a frame isn't fully available yet, then
    /// `Ok(None)` is returned. This indicates to the `Framed` instance that
    /// it needs to read some more bytes before calling this method again.
    ///
    /// Note that the bytes provided may be empty. If a previous call to
    /// `decode` consumed all the bytes in the buffer then `decode` will be
    /// called again until it returns `None`, indicating that more bytes need to
    /// be read.
    ///
    /// Finally, if the bytes in the buffer are malformed then an error is
    /// returned indicating why. This informs `Framed` that the stream is now
    /// corrupt and should be terminated.
    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error>;

    /// A default method available to be called when there are no more bytes
    /// available to be read from the underlying I/O.
    ///
    /// This method defaults to calling `decode` and returns an error if
    /// `Ok(None)` is returned while there is unconsumed data in `buf`.
    /// Typically this doesn't need to be implemented unless the framing
    /// protocol differs near the end of the stream.
    ///
    /// Note that the `buf` argument may be empty. If a previous call to
    /// `decode_eof` consumed all the bytes in the bufer, `decode_eof` will be
    /// called again until it returns `None`, indicating that there are no more
    /// frames to yield. This behavior enables returning finalization frames
    /// that may not be based on inbound data.
    fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        match try!(self.decode(buf)) {
            Some(frame) => Ok(Some(frame)),
            None => {
                if buf.is_empty() {
                    Ok(None)
                } else {
                    Err(io::Error::new(io::ErrorKind::Other,
                                       "bytes remaining on stream").into())
                }
            }
        }
    }
}

/// A `Stream` of messages decoded from an `AsyncRead`.
pub struct FramedRead<T, D> {
    inner: FramedRead2<Fuse<T, D>>,
}

pub struct FramedRead2<T> {
    inner: T,
    eof: bool,
    is_readable: bool,
    buffer: BytesMut,
}

const INITIAL_CAPACITY: usize = 8 * 1024;

// ===== impl FramedRead =====

impl<T, D> FramedRead<T, D>
    where T: AsyncRead,
          D: Decoder,
{
    /// Creates a new `FramedRead` with the given `decoder`.
    pub fn new(inner: T, decoder: D) -> FramedRead<T, D> {
        FramedRead {
            inner: framed_read2(Fuse(inner, decoder)),
        }
    }
}

impl<T, D> FramedRead<T, D> {
    /// Returns a reference to the underlying I/O stream wrapped by
    /// `FramedRead`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.inner.0
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `FramedRead`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.inner.0
    }

    /// Consumes the `FramedRead`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.inner.0
    }

    /// Returns a reference to the underlying decoder.
    pub fn decoder(&self) -> &D {
        &self.inner.inner.1
    }

    /// Returns a mutable reference to the underlying decoder.
    pub fn decoder_mut(&mut self) -> &mut D {
        &mut self.inner.inner.1
    }
}

impl<T, D> Stream for FramedRead<T, D>
    where T: AsyncRead,
          D: Decoder,
{
    type Item = D::Item;
    type Error = D::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.inner.poll()
    }
}

impl<T, D> Sink for FramedRead<T, D>
    where T: Sink,
{
    type SinkItem = T::SinkItem;
    type SinkError = T::SinkError;

    fn start_send(&mut self,
                  item: Self::SinkItem)
                  -> StartSend<Self::SinkItem, Self::SinkError>
    {
        self.inner.inner.0.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.inner.0.poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.inner.0.close()
    }
}

impl<T, D> fmt::Debug for FramedRead<T, D>
    where T: fmt::Debug,
          D: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FramedRead")
            .field("inner", &self.inner.inner.0)
            .field("decoder", &self.inner.inner.1)
            .field("eof", &self.inner.eof)
            .field("is_readable", &self.inner.is_readable)
            .field("buffer", &self.inner.buffer)
            .finish()
    }
}

// ===== impl FramedRead2 =====

pub fn framed_read2<T>(inner: T) -> FramedRead2<T> {
    FramedRead2 {
        inner: inner,
        eof: false,
        is_readable: false,
        buffer: BytesMut::with_capacity(INITIAL_CAPACITY),
    }
}

impl<T> FramedRead2<T> {
    pub fn get_ref(&self) -> &T {
        &self.inner
    }

    pub fn into_inner(self) -> T {
        self.inner
    }

    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner
    }
}

impl<T> Stream for FramedRead2<T>
    where T: AsyncRead + Decoder,
{
    type Item = T::Item;
    type Error = T::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            // Repeatedly call `decode` or `decode_eof` as long as it is
            // "readable". Readable is defined as not having returned `None`. If
            // the upstream has returned EOF, and the decoder is no longer
            // readable, it can be assumed that the decoder will never become
            // readable again, at which point the stream is terminated.
            if self.is_readable {
                if self.eof {
                    let frame = try!(self.inner.decode_eof(&mut self.buffer));
                    return Ok(Async::Ready(frame));
                }

                trace!("attempting to decode a frame");

                if let Some(frame) = try!(self.inner.decode(&mut self.buffer)) {
                    trace!("frame decoded from buffer");
                    return Ok(Async::Ready(Some(frame)));
                }

                self.is_readable = false;
            }

            assert!(!self.eof);

            // Otherwise, try to read more data and try again. Make sure we've
            // got room for at least one byte to read to ensure that we don't
            // get a spurious 0 that looks like EOF
            self.buffer.reserve(1);
            if 0 == try_ready!(self.inner.read_buf(&mut self.buffer)) {
                self.eof = true;
            }

            self.is_readable = true;
        }
    }
}
<|endoftext|>


<commit_before>use std;
use std::io::Read;
use gltf::v2::{ import, Root };

pub fn load_file(path: &str) {
    let root = import(path);
    match root {
        Ok(root) => {
            println!("glTF version 2.0");
            println!("{:#?}", root);
            load_box(&root);
        }
        Err(err) => {
            println!("Error: {:#?}", err);
        }
    }
}

pub fn load_box(root: &Root) {
    let buffer = &root.buffers()[0];

    // TODO!: determine base directory...
    let mut file = std::fs::File::open(format!("src/data/{}", buffer.uri)).unwrap();
    let mut buffer_contents = Vec::with_capacity(buffer.byte_length as usize);
    file.read_to_end(&mut buffer_contents).unwrap();
    assert_eq!(buffer_contents.len(), buffer.byte_length as usize)
}
<commit_msg>parse position data<commit_after>use std;
use std::io::Read;
use gltf::v2::{ import, Root };
use gltf::v2::accessor::ComponentType;
use gltf::v2::buffer::Target;
use gltf::v2::mesh::Mode;

pub fn load_file(path: &str) {
    let root = import(path);
    match root {
        Ok(root) => {
            println!("glTF version 2.0");
            println!("{:#?}", root);
            load_box(&root);
        }
        Err(err) => {
            println!("Error: {:#?}", err);
        }
    }
}

pub fn load_box(root: &Root) {
    let buffer = &root.buffers()[0];

    // TODO!: determine base directory...
    let mut file = std::fs::File::open(format!("src/data/{}", buffer.uri)).unwrap();
    let mut buffer_contents = Vec::with_capacity(buffer.byte_length as usize);
    file.read_to_end(&mut buffer_contents).unwrap();
    assert_eq!(buffer_contents.len(), buffer.byte_length as usize);

    let mesh = &root.meshes()[0];
    let primitive = &mesh.primitives[0];
    assert_eq!(primitive.mode, Mode::Triangles);

    let posAccessorIndex = primitive.attributes["POSITION"].value() as usize;
    let posAccessor = &root.accessors()[posAccessorIndex];
    let posBufferView = &root.buffer_views()[posAccessor.buffer_view.value() as usize];

    let positionData = &buffer_contents[
        posBufferView.byte_offset as usize .. (posBufferView.byte_offset + posBufferView.byte_length) as usize];

}
<|endoftext|>


<commit_before>/*!
 * Entity component system
 */

extern crate rustc_serialize;

use std::default::{Default};
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::collections::{HashMap, HashSet};
use std::collections::hash_set;

/// Entity unique identifier type.
type Uid = i32;

/// Handle for an entity in the entity component system.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, RustcDecodable, RustcEncodable)]
pub struct Entity {
    /// Unique identifier for the entity.
    ///
    /// No two entities should get the same UID during the lifetime of the ECS.
    /// UIDs for regular entities are increasing positive integers. UIDs for
    /// prototype entities are negative integers.
    uid: Uid,
}

pub trait AnyComponent {
    /// Remove an entity's component.
    fn remove(&mut self, e: Entity);
}

/// Storage for a single component type.
#[derive(RustcEncodable, RustcDecodable)]
pub struct ComponentData<C> {
    // TODO: Add reused index fields to entities and use VecMap with the
    // index field instead of HashMap with the UID here for more
    // efficient access.
    data: HashMap<Uid, C>,
}

impl<C> ComponentData<C> {
    pub fn new() -> ComponentData<C> {
        ComponentData {
            data: HashMap::new()
        }
    }

    /// Insert a component to an entity.
    pub fn insert(&mut self, e: Entity, comp: C) {
        self.data.insert(e.uid, comp);
    }

    /// Return whether an entity contains this component.
    pub fn contains(&self, e: Entity) -> bool {
        self.data.contains_key(&e.uid)
    }
}

impl<C> Index<Entity> for ComponentData<C> {
    type Output = C;

    fn index<'a>(&'a self, e: Entity) -> &'a C {
        self.data.get(&e.uid).unwrap()
    }
}

impl<C> IndexMut<Entity> for ComponentData<C> {
    fn index_mut<'a>(&'a mut self, e: Entity) -> &'a mut C {
        self.data.get_mut(&e.uid).unwrap()
    }
}

impl<C> AnyComponent for ComponentData<C> {
    fn remove(&mut self, e: Entity) {
        self.data.remove(&e.uid);
    }
}

pub trait Store {
    /// Perform an operation for each component container.
    fn for_each_component<F>(&mut self, f: F)
        where F: FnMut(&mut AnyComponent);
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct Ecs<S> {
    next_uid: Uid,
    active: HashSet<Entity>,
    store: S,
}

impl<S: Default+Store> Ecs<S> {
    pub fn new() -> Ecs<S> {
        Ecs {
            next_uid: 1,
            active: HashSet::new(),
            store: Default::default(),
        }
    }

    /// Create a new empty entity.
    pub fn make(&mut self) -> Entity {
        let next = self.next_uid;
        self.next_uid += 1;
        let ret = Entity { uid: next };
        self.active.insert(ret);
        ret
    }

    /// Remove an entity from the system and clear its components.
    pub fn remove(&mut self, e: Entity) {
        self.active.remove(&e);
        self.store.for_each_component(|c| c.remove(e));
    }

    /// Return whether the system contains an entity.
    pub fn contains(&self, e: Entity) -> bool {
        self.active.contains(&e)
    }

    pub fn iter(&self) -> hash_set::Iter<Entity> {
        self.active.iter()
    }
}

impl<S> Deref for Ecs<S> {
    type Target = S;

    fn deref(&self) -> &S { &self.store }
}

impl<S> DerefMut for Ecs<S> {
    fn deref_mut(&mut self) -> &mut S {&mut self.store}
}

/// Entity component system builder macro.
///
/// Defines a local `Ecs` type that's parametrized with a custom component
/// store type with the component types you specify. Will also define a trait
/// `Component` which will be implemented for the component types.
#[macro_export]
macro_rules! Ecs {
    {
        // Declare the type of the (plain old data) component and the
        // identifier to use for it in the ECS.
        //
        // Component paths must be absolute.
        $($compname:ident: $comptype:ty,)+
    } => {
        mod _ecs_inner {
            // Use the enum to convert components to numbers for component bit masks etc.
            #[allow(non_camel_case_types)]
            pub enum ComponentNum {
                $($compname,)+
            }

        }

        pub use self::_ecs_inner::ComponentNum;

        pub struct _ComponentStore {
            $(pub $compname: ::calx_ecs::ComponentData<$comptype>),+
        }

        impl ::std::default::Default for _ComponentStore {
            fn default() -> _ComponentStore {
                _ComponentStore {
                    $($compname: ::calx_ecs::ComponentData::new()),+
                }
            }
        }

        impl ::calx_ecs::Store for _ComponentStore {
            fn for_each_component<F>(&mut self, mut f: F)
                where F: FnMut(&mut ::calx_ecs::AnyComponent)
            {
                $(f(&mut self.$compname as &mut ::calx_ecs::AnyComponent);)+
            }
        }

        pub fn matches_mask(ecs: &::calx_ecs::Ecs<_ComponentStore>, e: ::calx_ecs::Entity, mask: u64) -> bool {
            $(if mask & (1 << ComponentNum::$compname as u8) != 0 && !ecs.$compname.contains(e) {
                return false;
            })+
            return true;
        }

        /// Common operations for ECS component value types.
        pub trait Component {
            /// Add a clone of the component value to an entity in an ECS.
            ///
            /// Can't move the component itself since we might be using this
            /// through a trait object.
            fn add_to(&self, ecs: &mut ::calx_ecs::Ecs<_ComponentStore>, e: ::calx_ecs::Entity);
        }

        $(impl Component for $comptype {
            fn add_to(&self, ecs: &mut ::calx_ecs::Ecs<_ComponentStore>, e: ::calx_ecs::Entity) {
                ecs.$compname.insert(e, self.clone());
            }
        })+

        pub type Ecs = ::calx_ecs::Ecs<_ComponentStore>;
    }
}

/// Build a vector of Component trait objects from component values.
///
/// Use to set up prototype templates for entities.
#[macro_export]
macro_rules! loadout {
    [ $($comp:expr),+ ] => {
        vec![
            $(Box::new($comp) as Box<Component>),+
        ]
    }
}

/// Build a component type mask to match component iteration with.
///
/// You must have ComponentNum enum from the Ecs! macro expansion in scope
/// when using this.
#[macro_export]
macro_rules! build_mask {
    ( $($compname:ident),+ ) => {
        0u64 $(| (1u64 << ComponentNum::$compname as u8))+
    }
}
<commit_msg>Disable dead code warnings from generated ECS code<commit_after>/*!
 * Entity component system
 */

extern crate rustc_serialize;

use std::default::{Default};
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::collections::{HashMap, HashSet};
use std::collections::hash_set;

/// Entity unique identifier type.
type Uid = i32;

/// Handle for an entity in the entity component system.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, RustcDecodable, RustcEncodable)]
pub struct Entity {
    /// Unique identifier for the entity.
    ///
    /// No two entities should get the same UID during the lifetime of the ECS.
    /// UIDs for regular entities are increasing positive integers. UIDs for
    /// prototype entities are negative integers.
    uid: Uid,
}

pub trait AnyComponent {
    /// Remove an entity's component.
    fn remove(&mut self, e: Entity);
}

/// Storage for a single component type.
#[derive(RustcEncodable, RustcDecodable)]
pub struct ComponentData<C> {
    // TODO: Add reused index fields to entities and use VecMap with the
    // index field instead of HashMap with the UID here for more
    // efficient access.
    data: HashMap<Uid, C>,
}

impl<C> ComponentData<C> {
    pub fn new() -> ComponentData<C> {
        ComponentData {
            data: HashMap::new()
        }
    }

    /// Insert a component to an entity.
    pub fn insert(&mut self, e: Entity, comp: C) {
        self.data.insert(e.uid, comp);
    }

    /// Return whether an entity contains this component.
    pub fn contains(&self, e: Entity) -> bool {
        self.data.contains_key(&e.uid)
    }
}

impl<C> Index<Entity> for ComponentData<C> {
    type Output = C;

    fn index<'a>(&'a self, e: Entity) -> &'a C {
        self.data.get(&e.uid).unwrap()
    }
}

impl<C> IndexMut<Entity> for ComponentData<C> {
    fn index_mut<'a>(&'a mut self, e: Entity) -> &'a mut C {
        self.data.get_mut(&e.uid).unwrap()
    }
}

impl<C> AnyComponent for ComponentData<C> {
    fn remove(&mut self, e: Entity) {
        self.data.remove(&e.uid);
    }
}

pub trait Store {
    /// Perform an operation for each component container.
    fn for_each_component<F>(&mut self, f: F)
        where F: FnMut(&mut AnyComponent);
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct Ecs<S> {
    next_uid: Uid,
    active: HashSet<Entity>,
    store: S,
}

impl<S: Default+Store> Ecs<S> {
    pub fn new() -> Ecs<S> {
        Ecs {
            next_uid: 1,
            active: HashSet::new(),
            store: Default::default(),
        }
    }

    /// Create a new empty entity.
    pub fn make(&mut self) -> Entity {
        let next = self.next_uid;
        self.next_uid += 1;
        let ret = Entity { uid: next };
        self.active.insert(ret);
        ret
    }

    /// Remove an entity from the system and clear its components.
    pub fn remove(&mut self, e: Entity) {
        self.active.remove(&e);
        self.store.for_each_component(|c| c.remove(e));
    }

    /// Return whether the system contains an entity.
    pub fn contains(&self, e: Entity) -> bool {
        self.active.contains(&e)
    }

    pub fn iter(&self) -> hash_set::Iter<Entity> {
        self.active.iter()
    }
}

impl<S> Deref for Ecs<S> {
    type Target = S;

    fn deref(&self) -> &S { &self.store }
}

impl<S> DerefMut for Ecs<S> {
    fn deref_mut(&mut self) -> &mut S {&mut self.store}
}

/// Entity component system builder macro.
///
/// Defines a local `Ecs` type that's parametrized with a custom component
/// store type with the component types you specify. Will also define a trait
/// `Component` which will be implemented for the component types.
#[macro_export]
macro_rules! Ecs {
    {
        // Declare the type of the (plain old data) component and the
        // identifier to use for it in the ECS.
        //
        // Component paths must be absolute.
        $($compname:ident: $comptype:ty,)+
    } => {
        mod _ecs_inner {
            // Use the enum to convert components to numbers for component bit masks etc.
            #[allow(non_camel_case_types, dead_code)]
            pub enum ComponentNum {
                $($compname,)+
            }

        }

        pub use self::_ecs_inner::ComponentNum;

        pub struct _ComponentStore {
            $(pub $compname: ::calx_ecs::ComponentData<$comptype>),+
        }

        impl ::std::default::Default for _ComponentStore {
            fn default() -> _ComponentStore {
                _ComponentStore {
                    $($compname: ::calx_ecs::ComponentData::new()),+
                }
            }
        }

        impl ::calx_ecs::Store for _ComponentStore {
            fn for_each_component<F>(&mut self, mut f: F)
                where F: FnMut(&mut ::calx_ecs::AnyComponent)
            {
                $(f(&mut self.$compname as &mut ::calx_ecs::AnyComponent);)+
            }
        }

#[allow(dead_code)]
        pub fn matches_mask(ecs: &::calx_ecs::Ecs<_ComponentStore>, e: ::calx_ecs::Entity, mask: u64) -> bool {
            $(if mask & (1 << ComponentNum::$compname as u8) != 0 && !ecs.$compname.contains(e) {
                return false;
            })+
            return true;
        }

        /// Common operations for ECS component value types.
        pub trait Component {
            /// Add a clone of the component value to an entity in an ECS.
            ///
            /// Can't move the component itself since we might be using this
            /// through a trait object.
            fn add_to(&self, ecs: &mut ::calx_ecs::Ecs<_ComponentStore>, e: ::calx_ecs::Entity);
        }

        $(impl Component for $comptype {
            fn add_to(&self, ecs: &mut ::calx_ecs::Ecs<_ComponentStore>, e: ::calx_ecs::Entity) {
                ecs.$compname.insert(e, self.clone());
            }
        })+

        pub type Ecs = ::calx_ecs::Ecs<_ComponentStore>;
    }
}

/// Build a vector of Component trait objects from component values.
///
/// Use to set up prototype templates for entities.
#[macro_export]
macro_rules! loadout {
    [ $($comp:expr),+ ] => {
        vec![
            $(Box::new($comp) as Box<Component>),+
        ]
    }
}

/// Build a component type mask to match component iteration with.
///
/// You must have ComponentNum enum from the Ecs! macro expansion in scope
/// when using this.
#[macro_export]
macro_rules! build_mask {
    ( $($compname:ident),+ ) => {
        0u64 $(| (1u64 << ComponentNum::$compname as u8))+
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::path::Path;

fn main() {
    let target = env::var("TARGET").unwrap();
    println!("target={}", target);

//    let sodium_static = env::var("CARGO_FEATURE_SODIUM_STATIC").ok();
//    println!("sodium_static={:?}", sodium_static);
//
//    if sodium_static.is_some() {
//        println!("cargo:rustc-link-lib=static=sodium");
//    }

    if target.find("-windows-").is_some() {
        // do not build c-code on windows, use binaries
        let output_dir = env::var("OUT_DIR").unwrap();
        let prebuilt_dir = env::var("INDY_PREBUILT_DEPS_DIR").unwrap();

        let dst = Path::new(&output_dir[..]).join("..\\..\\..");
        let prebuilt_lib = Path::new(&prebuilt_dir[..]).join("lib");

        println!("cargo:rustc-link-search=native={}", prebuilt_dir);
        println!("cargo:rustc-flags=-L {}\\lib", prebuilt_dir);
        println!("cargo:include={}\\include", prebuilt_dir);

        let files = vec!["libeay32md.dll", "libsodium.dll", "libzmq.dll", "ssleay32md.dll"];
        for f in files.iter() {
            if let Ok(_) = fs::copy(&prebuilt_lib.join(f), &dst.join(f)) {
                println!("copy {} -> {}", &prebuilt_lib.join(f).display(), &dst.join(f).display());
            }
        }
    } else if target.find("linux-android").is_some() {
        //statically link files
        let openssl = match env::var("OPENSSL_LIB_DIR") {
            Ok(val) => val,
            Err(..) => match env::var("OPENSSL_DIR") {
                Ok(dir) => Path::new(&dir[..]).join("lib").to_string_lossy().into_owned(),
                Err(..) => panic!("Missing required environment variables OPENSSL_DIR or OPENSSL_LIB_DIR")
            }
        };

        let sodium = match env::var("SODIUM_LIB_DIR") {
            Ok(val) => val,
            Err(..) => panic!("Missing required environment variable SODIUM_LIB_DIR")
        };

        let zmq = match env::var("LIBZMQ_LIB_DIR") {
            Ok(val) => val,
            Err(..) => match env::var("LIBZMQ_PREFIX") {
                Ok(dir) => Path::new(&dir[..]).join("lib").to_string_lossy().into_owned(),
                Err(..) => panic!("Missing required environment variables LIBZMQ_PREFIX or LIBZMQ_LIB_DIR")
            }
        };

        println!("cargo:rustc-link-search=native={}", openssl);
        println!("cargo:rustc-link-lib=static=crypto");
        println!("cargo:rustc-link-lib=static=ssl");
        println!("cargo:rustc-link-search=native={}", sodium);
        println!("cargo:rustc-link-lib=static=sodium");
        println!("cargo:rustc-link-search=native={}", zmq);
        println!("cargo:rustc-link-lib=static=zmq");
    }
}
<commit_msg>code clean up<commit_after>use std::env;
use std::fs;
use std::path::Path;

fn main() {
    let target = env::var("TARGET").unwrap();
    println!("target={}", target);

    let sodium_static = env::var("CARGO_FEATURE_SODIUM_STATIC").ok();
    println!("sodium_static={:?}", sodium_static);

    if sodium_static.is_some() {
        println!("cargo:rustc-link-lib=static=sodium");
    }

    if target.find("-windows-").is_some() {
        // do not build c-code on windows, use binaries
        let output_dir = env::var("OUT_DIR").unwrap();
        let prebuilt_dir = env::var("INDY_PREBUILT_DEPS_DIR").unwrap();

        let dst = Path::new(&output_dir[..]).join("..\\..\\..");
        let prebuilt_lib = Path::new(&prebuilt_dir[..]).join("lib");

        println!("cargo:rustc-link-search=native={}", prebuilt_dir);
        println!("cargo:rustc-flags=-L {}\\lib", prebuilt_dir);
        println!("cargo:include={}\\include", prebuilt_dir);

        let files = vec!["libeay32md.dll", "libsodium.dll", "libzmq.dll", "ssleay32md.dll"];
        for f in files.iter() {
            if let Ok(_) = fs::copy(&prebuilt_lib.join(f), &dst.join(f)) {
                println!("copy {} -> {}", &prebuilt_lib.join(f).display(), &dst.join(f).display());
            }
        }
    } else if target.find("linux-android").is_some() {
        //statically link files
        let openssl = match env::var("OPENSSL_LIB_DIR") {
            Ok(val) => val,
            Err(..) => match env::var("OPENSSL_DIR") {
                Ok(dir) => Path::new(&dir[..]).join("lib").to_string_lossy().into_owned(),
                Err(..) => panic!("Missing required environment variables OPENSSL_DIR or OPENSSL_LIB_DIR")
            }
        };

        let sodium = match env::var("SODIUM_LIB_DIR") {
            Ok(val) => val,
            Err(..) => panic!("Missing required environment variable SODIUM_LIB_DIR")
        };

        let zmq = match env::var("LIBZMQ_LIB_DIR") {
            Ok(val) => val,
            Err(..) => match env::var("LIBZMQ_PREFIX") {
                Ok(dir) => Path::new(&dir[..]).join("lib").to_string_lossy().into_owned(),
                Err(..) => panic!("Missing required environment variables LIBZMQ_PREFIX or LIBZMQ_LIB_DIR")
            }
        };

        println!("cargo:rustc-link-search=native={}", openssl);
        println!("cargo:rustc-link-lib=static=crypto");
        println!("cargo:rustc-link-lib=static=ssl");
        println!("cargo:rustc-link-search=native={}", sodium);
        println!("cargo:rustc-link-lib=static=sodium");
        println!("cargo:rustc-link-search=native={}", zmq);
        println!("cargo:rustc-link-lib=static=zmq");
    }
}
<|endoftext|>


<commit_before>use nalgebra::Point2;
use std::collections::HashSet;

use event::{ElementState, Event, MouseButton, Reactor};
use super::state::{Element, InputState, ToInputState};

impl Element for MouseButton {
    type State = ElementState;
}

pub struct Mouse {
    position: Point2<u32>,
    buttons: MouseState,
}

impl Mouse {
    pub fn new() -> Self {
        Mouse {
            position: Point2::origin(),
            buttons: MouseState::new(),
        }
    }

    pub fn position(&self) -> &Point2<u32> {
        &self.position
    }
}

impl InputState<MouseButton> for Mouse {
    fn state(&self, button: MouseButton) -> ElementState {
        self.buttons.state(button)
    }
}

impl Reactor for Mouse {
    fn react(&mut self, event: &Event) {
        match *event {
            Event::MouseInput(ElementState::Pressed, button) => {
                self.buttons.0.insert(button);
            }
            Event::MouseInput(ElementState::Released, button) => {
                self.buttons.0.remove(&button);
            }
            Event::MouseMoved(x, y) => {
                self.position = Point2::new(x as u32, y as u32);
            }
            _ => {}
        }
    }
}

impl ToInputState for Mouse {
    type Element = MouseButton;
    type InputState = MouseState;

    fn to_state(&self) -> Self::InputState {
        self.buttons.clone()
    }
}

#[derive(Clone)]
pub struct MouseState(HashSet<MouseButton>);

impl MouseState {
    pub fn new() -> Self {
        MouseState(HashSet::new())
    }
}

impl InputState<MouseButton> for MouseState {
    fn state(&self, button: MouseButton) -> ElementState {
        if self.0.contains(&button) {
            ElementState::Pressed
        }
        else {
            ElementState::Released
        }
    }
}
<commit_msg>Track mouse proximity in `MouseState`.<commit_after>use nalgebra::Point2;
use std::collections::HashSet;

use event::{ElementState, Event, MouseButton, Reactor};
use super::state::{Element, InputState, ToInputState};

impl Element for MouseButton {
    type State = ElementState;
}

#[derive(Clone, Copy)]
pub struct MouseProximity;

impl Element for MouseProximity {
    type State = bool;
}

pub struct Mouse {
    position: Point2<u32>,
    state: MouseState,
}

impl Mouse {
    pub fn new() -> Self {
        Mouse {
            position: Point2::origin(),
            state: MouseState::new(),
        }
    }

    pub fn position(&self) -> &Point2<u32> {
        &self.position
    }
}

impl InputState<MouseButton> for Mouse {
    fn state(&self, button: MouseButton) -> ElementState {
        self.state.state(button)
    }
}

impl Reactor for Mouse {
    fn react(&mut self, event: &Event) {
        match *event {
            Event::MouseEntered => {
                self.state.proximity = true;
            }
            Event::MouseInput(ElementState::Pressed, button) => {
                self.state.buttons.insert(button);
            }
            Event::MouseInput(ElementState::Released, button) => {
                self.state.buttons.remove(&button);
            }
            Event::MouseLeft => {
                self.state.proximity = false;
            }
            Event::MouseMoved(x, y) => {
                self.position = Point2::new(x as u32, y as u32);
            }
            _ => {}
        }
    }
}

impl ToInputState for Mouse {
    type Element = MouseButton;
    type InputState = MouseState;

    fn to_state(&self) -> Self::InputState {
        self.state.clone()
    }
}

#[derive(Clone)]
pub struct MouseState {
    buttons: HashSet<MouseButton>,
    proximity: bool,
}

impl MouseState {
    pub fn new() -> Self {
        MouseState {
            buttons: HashSet::new(),
            proximity: false,
        }
    }
}

impl InputState<MouseButton> for MouseState {
    fn state(&self, button: MouseButton) -> ElementState {
        if self.buttons.contains(&button) {
            ElementState::Pressed
        }
        else {
            ElementState::Released
        }
    }
}

impl InputState<MouseProximity> for MouseState {
    fn state(&self, _: MouseProximity) -> bool {
        self.proximity
    }
}
<|endoftext|>


<commit_before>//! Extracts JSON data by interpreting a JMESPath AST

extern crate rustc_serialize;

use self::rustc_serialize::json::Json;
use std::collections::BTreeMap;

use ast::Ast;
use utils;

pub fn interpret(data: &Json, node: &Ast) -> Result<Json, String> {
    match node {
        &Ast::CurrentNode => Ok(data.clone()),
        &Ast::Literal(ref json) => Ok(json.clone()),
        &Ast::Subexpr(ref lhs, ref rhs) => {
            let result = try!(interpret(data, lhs));
            interpret(&result, rhs)
        },
        &Ast::Identifier(ref f) => {
            match data.find(f) {
                Some(j) => Ok(j.clone()),
                _ => Ok(Json::Null)
            }
        },
        &Ast::Index(ref i) => {
            match data.as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let result = if *i >= 0 {
                        a.get(*i as usize)
                    } else {
                        utils::negative_offset(a, i)
                    };
                    match result {
                        Some(result) => Ok(result.clone()),
                        None => Ok(Json::Null)
                    }
                }
            }
        },
        &Ast::Or(ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            if utils::is_truthy(&left) {
                Ok(left)
            } else {
                interpret(data, rhs)
            }
        },
        // Returns the resut of RHS if cond yields truthy value.
        &Ast::Condition(ref cond, ref cond_rhs) => {
            let cond_result = try!(interpret(data, cond));
            if utils::is_truthy(&cond_result) {
                interpret(data, cond_rhs)
            } else {
                Ok(Json::Null)
            }
        },
        &Ast::Comparison(ref cmp, ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            let right = try!(interpret(data, rhs));
            Ok(utils::comparison(cmp, &left, &right))
        },
        // Converts an object into a JSON array of its values.
        &Ast::ObjectValues(ref predicate) => {
            let result = try!(interpret(data, predicate));
            Ok(utils::object_to_array(&result))
        },
        // Passes the results of lhs into rhs if lhs yields an array and
        // each node of lhs that passes through rhs yields a non-null value.
        &Ast::Projection(ref lhs, ref rhs) => {
            match try!(interpret(data, lhs)).as_array() {
                None => Ok(Json::Null),
                Some(left) => {
                    let mut collected = vec!();
                    for element in left {
                        let current = try!(interpret(element, rhs));
                        if !current.is_null() {
                            collected.push(current);
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::Flatten(ref node) => {
            match try!(interpret(data, node)).as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let mut collected = vec!();
                    for element in a {
                        match element {
                            &Json::Array(ref a) => collected.extend(a.iter().cloned()),
                            _ => collected.push(element.clone())
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::MultiList(ref nodes) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = vec!();
            for node in nodes {
                collected.push(try!(interpret(data, node)));
            }
            Ok(Json::Array(collected))
        },
        &Ast::MultiHash(ref kvp_list) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = BTreeMap::new();
            for kvp in kvp_list {
                let key = try!(interpret(data, &kvp.key));
                let value = try!(interpret(data, &kvp.value));
                collected.insert(key.as_string().unwrap().to_string(), value);
            }
            Ok(Json::Object(collected))
        },
        ref node @ _ => panic!(format!("not implemented yet: {:?}", node))
    }
}

#[cfg(test)]
mod tests {
    extern crate rustc_serialize;
    use self::rustc_serialize::json::Json;
    use super::*;
    use ast::{Ast, Comparator};

    #[test] fn interprets_identifier() {
        let ast = Ast::Identifier("foo".to_string());
        let data = Json::from_str("{\"foo\":\"baz\"}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_current_node() {
        let ast = Ast::CurrentNode;
        let data = Json::Boolean(true);
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_literal() {
        let ast = Ast::Literal(Json::Boolean(true));
        let data = Json::from_str("{}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_subexpr() {
        let ast = Ast::Subexpr(Box::new(Ast::Identifier("foo".to_string())),
                               Box::new(Ast::Identifier("bar".to_string())));
        let data = Json::from_str("{\"foo\":{\"bar\":\"baz\"}}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index_when_not_array_as_null() {
        let ast = Ast::Index(1);
        let data = Json::String("foo".to_string());
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or_expr() {
        let ast = Ast::Or(Box::new(Ast::Identifier("bar".to_string())),
                          Box::new(Ast::Identifier("foo".to_string())));
        let data = Json::from_str("{\"foo\":true}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(true))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::String("foo".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr_negative() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(false))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_comparison() {
        // Left, right, result, comparator.
        let cases = vec!(vec!["true", "true", "true", "=="],
                         vec!["true", "false", "false", "=="],
                         vec!["true", "null", "false", "=="],
                         vec!["null", "null", "true", "=="],
                         vec!["10", "20", "false", ">"],
                         vec!["10", "20", "true", "<"]);
        for test_case in cases {
            let cmp = match test_case[3] {
                "==" => Comparator::Eq,
                ">" => Comparator::Gt,
                _ => Comparator::Lt,
            };
            let ast = Ast::Comparison(
                cmp,
                Box::new(Ast::Literal(Json::from_str(test_case[0]).unwrap())),
                Box::new(Ast::Literal(Json::from_str(test_case[1]).unwrap())));
            let result = Json::from_str(test_case[2]).unwrap();
            assert_eq!(result, interpret(&Json::Null, &ast).unwrap());
        }
    }

    #[test] fn interprets_object_values_negative() {
        let ast = Ast::ObjectValues(Box::new(Ast::Literal(Json::Boolean(false))));
        let data = Json::Null;
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_object_values_affirmative() {
        let json_value = Json::from_str("{\"foo\": \"bar\"}").unwrap();
        let ast = Ast::ObjectValues(Box::new(Ast::Literal(json_value)));
        let data = Json::Null;
        assert_eq!(Json::from_str("[\"bar\"]").unwrap(),
                   interpret(&data, &ast).unwrap());
    }
}
<commit_msg>Adding some interpreter tests<commit_after>//! Extracts JSON data by interpreting a JMESPath AST

extern crate rustc_serialize;

use self::rustc_serialize::json::Json;
use std::collections::BTreeMap;

use ast::Ast;
use utils;

pub fn interpret(data: &Json, node: &Ast) -> Result<Json, String> {
    match node {
        &Ast::CurrentNode => Ok(data.clone()),
        &Ast::Literal(ref json) => Ok(json.clone()),
        &Ast::Subexpr(ref lhs, ref rhs) => {
            let result = try!(interpret(data, lhs));
            interpret(&result, rhs)
        },
        &Ast::Identifier(ref f) => {
            match data.find(f) {
                Some(j) => Ok(j.clone()),
                _ => Ok(Json::Null)
            }
        },
        &Ast::Index(ref i) => {
            match data.as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let result = if *i >= 0 {
                        a.get(*i as usize)
                    } else {
                        utils::negative_offset(a, i)
                    };
                    match result {
                        Some(result) => Ok(result.clone()),
                        None => Ok(Json::Null)
                    }
                }
            }
        },
        &Ast::Or(ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            if utils::is_truthy(&left) {
                Ok(left)
            } else {
                interpret(data, rhs)
            }
        },
        // Returns the resut of RHS if cond yields truthy value.
        &Ast::Condition(ref cond, ref cond_rhs) => {
            let cond_result = try!(interpret(data, cond));
            if utils::is_truthy(&cond_result) {
                interpret(data, cond_rhs)
            } else {
                Ok(Json::Null)
            }
        },
        &Ast::Comparison(ref cmp, ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            let right = try!(interpret(data, rhs));
            Ok(utils::comparison(cmp, &left, &right))
        },
        // Converts an object into a JSON array of its values.
        &Ast::ObjectValues(ref predicate) => {
            let result = try!(interpret(data, predicate));
            Ok(utils::object_to_array(&result))
        },
        // Passes the results of lhs into rhs if lhs yields an array and
        // each node of lhs that passes through rhs yields a non-null value.
        &Ast::Projection(ref lhs, ref rhs) => {
            match try!(interpret(data, lhs)).as_array() {
                None => Ok(Json::Null),
                Some(left) => {
                    let mut collected = vec!();
                    for element in left {
                        let current = try!(interpret(element, rhs));
                        if !current.is_null() {
                            collected.push(current);
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::Flatten(ref node) => {
            match try!(interpret(data, node)).as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let mut collected = vec!();
                    for element in a {
                        match element {
                            &Json::Array(ref a) => collected.extend(a.iter().cloned()),
                            _ => collected.push(element.clone())
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::MultiList(ref nodes) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = vec!();
            for node in nodes {
                collected.push(try!(interpret(data, node)));
            }
            Ok(Json::Array(collected))
        },
        &Ast::MultiHash(ref kvp_list) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = BTreeMap::new();
            for kvp in kvp_list {
                let key = try!(interpret(data, &kvp.key));
                let value = try!(interpret(data, &kvp.value));
                collected.insert(key.as_string().unwrap().to_string(), value);
            }
            Ok(Json::Object(collected))
        },
        ref node @ _ => panic!(format!("not implemented yet: {:?}", node))
    }
}

#[cfg(test)]
mod tests {
    extern crate rustc_serialize;
    use self::rustc_serialize::json::Json;
    use super::*;
    use ast::{Ast, Comparator, KeyValuePair};

    #[test] fn interprets_identifier() {
        let ast = Ast::Identifier("foo".to_string());
        let data = Json::from_str("{\"foo\":\"baz\"}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_current_node() {
        let ast = Ast::CurrentNode;
        let data = Json::Boolean(true);
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_literal() {
        let ast = Ast::Literal(Json::Boolean(true));
        let data = Json::from_str("{}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_subexpr() {
        let ast = Ast::Subexpr(Box::new(Ast::Identifier("foo".to_string())),
                               Box::new(Ast::Identifier("bar".to_string())));
        let data = Json::from_str("{\"foo\":{\"bar\":\"baz\"}}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index_when_not_array_as_null() {
        let ast = Ast::Index(1);
        let data = Json::String("foo".to_string());
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or_expr() {
        let ast = Ast::Or(Box::new(Ast::Identifier("bar".to_string())),
                          Box::new(Ast::Identifier("foo".to_string())));
        let data = Json::from_str("{\"foo\":true}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(true))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::String("foo".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr_negative() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(false))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_comparison() {
        // Left, right, result, comparator.
        let cases = vec!(vec!["true", "true", "true", "=="],
                         vec!["true", "false", "false", "=="],
                         vec!["true", "null", "false", "=="],
                         vec!["null", "null", "true", "=="],
                         vec!["10", "20", "false", ">"],
                         vec!["10", "20", "true", "<"]);
        for test_case in cases {
            let cmp = match test_case[3] {
                "==" => Comparator::Eq,
                ">" => Comparator::Gt,
                _ => Comparator::Lt,
            };
            let ast = Ast::Comparison(
                cmp,
                Box::new(Ast::Literal(Json::from_str(test_case[0]).unwrap())),
                Box::new(Ast::Literal(Json::from_str(test_case[1]).unwrap())));
            let result = Json::from_str(test_case[2]).unwrap();
            assert_eq!(result, interpret(&Json::Null, &ast).unwrap());
        }
    }

    #[test] fn interprets_object_values_negative() {
        let ast = Ast::ObjectValues(Box::new(Ast::Literal(Json::Boolean(false))));
        let data = Json::Null;
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_object_values_affirmative() {
        let json_value = Json::from_str("{\"foo\": \"bar\"}").unwrap();
        let ast = Ast::ObjectValues(Box::new(Ast::Literal(json_value)));
        let data = Json::Null;
        assert_eq!(Json::from_str("[\"bar\"]").unwrap(),
                   interpret(&data, &ast).unwrap());
    }

    #[test] fn projection_on_non_array_returns_null() {
        let ast = Ast::Projection(
            Box::new(Ast::Identifier("a".to_string())),
            Box::new(Ast::Identifier("b".to_string())));
        let data = Json::Boolean(true);
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn projection_applies_to_array() {
        let data = Json::from_str("{\"a\": [{\"b\":1},{\"b\":2}]}").unwrap();
        let ast = Ast::Projection(
            Box::new(Ast::Identifier("a".to_string())),
            Box::new(Ast::Identifier("b".to_string())));
        assert_eq!(Json::from_str("[1, 2]").unwrap(),
                   interpret(&data, &ast).unwrap());
    }

    #[test] fn flatten_of_non_array_is_null() {
        let data = Json::from_str("{\"a\": true}").unwrap();
        let ast = Ast::Flatten(Box::new(Ast::Identifier("a".to_string())));
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn flattens_arrays() {
        let data = Json::from_str("{\"a\": [1, [2, 3], 4, [[5]]]}").unwrap();
        let ast = Ast::Flatten(Box::new(Ast::Identifier("a".to_string())));
        assert_eq!(Json::from_str("[1, 2, 3, 4, [5]]").unwrap(),
                   interpret(&data, &ast).unwrap());
    }

    #[test] fn multi_list_on_null_is_null() {
        let ast = Ast::MultiList(vec!());
        assert_eq!(Json::Null, interpret(&Json::Null, &ast).unwrap());
    }

    #[test] fn multi_list_creates_array() {
        let data = Json::from_str("{\"a\": 1, \"b\": 2}").unwrap();
        let ast = Ast::MultiList(vec!(Ast::Identifier("a".to_string()),
                                      Ast::Identifier("b".to_string())));
        assert_eq!(Json::from_str("[1, 2]").unwrap(), interpret(&data, &ast).unwrap());
    }

    #[test] fn multi_hash_on_null_is_null() {
        let ast = Ast::MultiHash(vec!());
        assert_eq!(Json::Null, interpret(&Json::Null, &ast).unwrap());
    }

    #[test] fn multi_hash_creates_object() {
        let data = Json::from_str("{\"aye\": 1, \"bee\": 2}").unwrap();
        let ast = Ast::MultiHash(
            vec!(KeyValuePair { key: Ast::Literal(Json::String("a".to_string())),
                                value: Ast::Identifier("aye".to_string()) },
                 KeyValuePair { key: Ast::Literal(Json::String("b".to_string())),
                                value: Ast::Identifier("bee".to_string()) }));
        assert_eq!(Json::from_str("{\"a\": 1, \"b\": 2}").unwrap(),
                   interpret(&data, &ast).unwrap());
    }
}
<|endoftext|>


<commit_before>use token;

pub struct Interpreter {
    tokenizer: token::Tokenizer,
    current: Option<token::Token>
}

impl Interpreter {
    pub fn new(text: token::Tokenizer) -> Self {
        Interpreter {
            tokenizer: text,
            current: None
        }
    }

    pub fn next(&mut self) -> Option<token::Token> {
        if self.current.is_some() { return self.current.clone() }
        self.current = self.tokenizer.next();
        self.current.clone()
    }

    pub fn consume_next(&mut self, expected_kind: token::Kind) -> Option<token::Token> {
        let token = match self.current {
            Some(_) => {
                let curr = self.current.clone();
                self.current = None;
                curr
            },
            None => {
                let next = self.next();
                self.current = None;
                next.clone()
            }
        };

        if token.clone().unwrap().kind == expected_kind {
            return token;
        } else {
            panic!(
                "Sintax error: expected token kind {:?} found {:?} at position {}",
                expected_kind,
                token,
                self.tokenizer.position
                )
        }
    }

    fn factor(&mut self) -> token::Token {
        match self.next() {
            Some(token::Token{ kind: token::Kind::GroupStart , .. }) => {
                self.consume_next(token::Kind::GroupStart);
                return token::Token::build(token::Kind::Integer, self.expr());
            },
            Some(token::Token{ kind: token::Kind::Integer, .. }) => {
                return self.consume_next(token::Kind::Integer).unwrap();
            },
            _ => panic!("Error factor")
        }
    }

    fn term(&mut self) -> token::Token {
        let mut result = self.factor();

        if let Some(operator) = self.next() {
            result.value = match operator.value.as_ref() {
                "*" | "/" => {
                    self.consume_next(token::Kind::Operator);
                    let right = self.factor();
                    binary_operation(
                        &result,
                        &operator,
                        &right
                    ).to_string()
                },
                _ => result.clone().value
            };
        }
        return result;
    }

    pub fn expr(&mut self) -> String {
        let mut result = self.term();
        while let Some(operator) = self.next() {
            if operator.kind == token::Kind::GroupEnd {
                self.consume_next(token::Kind::GroupEnd);
                break;
            }
            self.consume_next(token::Kind::Operator);
            let right = self.term();

            let operation_result = match operator.value.as_ref() {
                "+" | "-" => binary_operation(&result, &operator, &right),
                _ => result.clone().as_integer()
            };

            result.value = operation_result.to_string();
        }

        format!("{}", result.value)
    }
}

fn binary_operation(first: &token::Token, operator: &token::Token, second: &token::Token) -> i32 {
    if first.kind == token::Kind::Integer {
        let operand = first.clone().as_integer();
        let operand2 = second.clone().as_integer();
        match &*operator.value {
            "+" => operand + operand2,
            "-" => operand - operand2,
            "*" => operand * operand2,
            "/" => operand / operand2,
            _ => panic!("Sintax error: invalid operator {}", operator.value)
        }
    } else {
        panic!("Sintax error: invalid binary operation using {} {} {}.",
               first.value,
               operator.value,
               second.value)
    }
}

#[test]
fn it_sums() {
    let text = "5+1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("6", interpreter.expr());
}

#[test]
fn it_substract() {
    let text = "5-1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("4", interpreter.expr());
}

#[test]
fn it_multiplies() {
    let text = "5*2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("10", interpreter.expr());
}

#[test]
fn it_divide() {
    let text = "4/2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("2", interpreter.expr());
}

#[test]
fn it_accepts_multiples_operation() {
    let text = "10+5-4-1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("10", interpreter.expr());
}

#[test]
fn it_respect_precedence() {
    let text = "1+1*2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("3", interpreter.expr());
}

#[test]
fn it_respects_grouped_expression() {
    let text = "(1+(1+1)*2)+1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("6", interpreter.expr());
}
<commit_msg>tests: adding more complex grouped test<commit_after>use token;

pub struct Interpreter {
    tokenizer: token::Tokenizer,
    current: Option<token::Token>
}

impl Interpreter {
    pub fn new(text: token::Tokenizer) -> Self {
        Interpreter {
            tokenizer: text,
            current: None
        }
    }

    pub fn next(&mut self) -> Option<token::Token> {
        if self.current.is_some() { return self.current.clone() }
        self.current = self.tokenizer.next();
        self.current.clone()
    }

    pub fn consume_next(&mut self, expected_kind: token::Kind) -> Option<token::Token> {
        let token = match self.current {
            Some(_) => {
                let curr = self.current.clone();
                self.current = None;
                curr
            },
            None => {
                let next = self.next();
                self.current = None;
                next.clone()
            }
        };

        if token.clone().unwrap().kind == expected_kind {
            return token;
        } else {
            panic!(
                "Sintax error: expected token kind {:?} found {:?} at position {}",
                expected_kind,
                token,
                self.tokenizer.position
                )
        }
    }

    fn factor(&mut self) -> token::Token {
        match self.next() {
            Some(token::Token{ kind: token::Kind::GroupStart , .. }) => {
                self.consume_next(token::Kind::GroupStart);
                return token::Token::build(token::Kind::Integer, self.expr());
            },
            Some(token::Token{ kind: token::Kind::Integer, .. }) => {
                return self.consume_next(token::Kind::Integer).unwrap();
            },
            _ => panic!("Error factor")
        }
    }

    fn term(&mut self) -> token::Token {
        let mut result = self.factor();

        if let Some(operator) = self.next() {
            result.value = match operator.value.as_ref() {
                "*" | "/" => {
                    self.consume_next(token::Kind::Operator);
                    let right = self.factor();
                    binary_operation(
                        &result,
                        &operator,
                        &right
                    ).to_string()
                },
                _ => result.clone().value
            };
        }
        return result;
    }

    pub fn expr(&mut self) -> String {
        let mut result = self.term();
        while let Some(operator) = self.next() {
            if operator.kind == token::Kind::GroupEnd {
                self.consume_next(token::Kind::GroupEnd);
                break;
            }
            self.consume_next(token::Kind::Operator);
            let right = self.term();

            let operation_result = match operator.value.as_ref() {
                "+" | "-" => binary_operation(&result, &operator, &right),
                _ => result.clone().as_integer()
            };

            result.value = operation_result.to_string();
        }

        format!("{}", result.value)
    }
}

fn binary_operation(first: &token::Token, operator: &token::Token, second: &token::Token) -> i32 {
    if first.kind == token::Kind::Integer {
        let operand = first.clone().as_integer();
        let operand2 = second.clone().as_integer();
        match &*operator.value {
            "+" => operand + operand2,
            "-" => operand - operand2,
            "*" => operand * operand2,
            "/" => operand / operand2,
            _ => panic!("Sintax error: invalid operator {}", operator.value)
        }
    } else {
        panic!("Sintax error: invalid binary operation using {} {} {}.",
               first.value,
               operator.value,
               second.value)
    }
}

#[test]
fn it_sums() {
    let text = "5+1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("6", interpreter.expr());
}

#[test]
fn it_substract() {
    let text = "5-1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("4", interpreter.expr());
}

#[test]
fn it_multiplies() {
    let text = "5*2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("10", interpreter.expr());
}

#[test]
fn it_divide() {
    let text = "4/2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("2", interpreter.expr());
}

#[test]
fn it_accepts_multiples_operation() {
    let text = "10+5-4-1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("10", interpreter.expr());
}

#[test]
fn it_respect_precedence() {
    let text = "1+1*2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("3", interpreter.expr());
}

#[test]
fn it_respects_grouped_expression() {
    let text = "4+(1+(1+1)*2)+1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("10", interpreter.expr());
}
<|endoftext|>


<commit_before>#![macro_escape]
macro_rules! auth_module (($auth_name:ident, $verify_name:ident, $verify_fn:ident, $keybytes:expr, $tagbytes:expr) => (

#[link(name = "sodium")]
extern {
    fn $auth_name(a: *mut u8,
                  m: *u8,
                  mlen: c_ulonglong,
                  k: *u8) -> c_int;
    fn $verify_name(a: *u8,
                    m: *u8,
                    mlen: c_ulonglong,
                    k: *u8) -> c_int;
}

pub static KEYBYTES: uint = $keybytes;
pub static TAGBYTES: uint = $tagbytes;

/**
 * Authentication `Key`
 *
 * When a `Key` goes out of scope its contents
 * will be zeroed out
 */
pub struct Key([u8, ..KEYBYTES]);

impl Drop for Key {
    fn drop(&mut self) {
        let &Key(ref mut k) = self;
        for e in k.mut_iter() { *e = 0 }
    }
}

/**
  * Authentication `Tag`
  *
  * The tag implements the traits `TotalEq` and `Eq` using constant-time
  * comparison functions. See `sodiumoxide::crypto::verify::verify_32`
  */
pub struct Tag([u8, ..TAGBYTES]);
impl TotalEq for Tag {
    fn equals(&self, &Tag(other): &Tag) -> bool {
        let &Tag(ref tag) = self;
        $verify_fn(tag, &other)
    }
}
impl Eq for Tag {
    fn eq(&self, &Tag(other): &Tag) -> bool {
        let &Tag(ref tag) = self;
        $verify_fn(tag, &other)
    }
}

/**
 * `gen_key()` randomly generates a key for authentication
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_key() -> Key {
    let mut k = [0, ..KEYBYTES];
    randombytes_into(k);
    Key(k)
}

/**
 * `authenticate()` authenticates a message `m` using a secret key `k`.
 * The function returns an authenticator tag.
 */
pub fn authenticate(m: &[u8],
                    &Key(k): &Key) -> Tag {
    unsafe {
        let mut tag = [0, ..TAGBYTES];
        $auth_name(tag.as_mut_ptr(),
                   m.as_ptr(),
                   m.len() as c_ulonglong,
                   k.as_ptr());
        Tag(tag)
    }
}

/**
 * `verify()` returns `true` if `tag` is a correct authenticator of message `m`
 * under a secret key `k`. Otherwise it returns false.
 */
pub fn verify(&Tag(tag): &Tag, m: &[u8],
              &Key(k): &Key) -> bool {
    unsafe {
        $verify_name(tag.as_ptr(),
                     m.as_ptr(),
                     m.len() as c_ulonglong,
                     k.as_ptr()) == 0
    }
}

#[test]
fn test_auth_verify() {
    use randombytes::randombytes;
    for i in range(0, 256) {
        let k = gen_key();
        let m = randombytes(i as uint);
        let tag = authenticate(m, &k);
        assert!(verify(&tag, m, &k));
    }
}

#[test]
fn test_auth_verify_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32) {
        let k = gen_key();
        let mut m = randombytes(i as uint);
        let Tag(mut tagbuf) = authenticate(m, &k);
        for j in range(0, m.len()) {
            m[j] ^= 0x20;
            assert!(!verify(&Tag(tagbuf), m, &k));
            m[j] ^= 0x20;
        }
        for j in range(0, tagbuf.len()) {
            tagbuf[j] ^= 0x20;
            assert!(!verify(&Tag(tagbuf), m, &k));
            tagbuf[j] ^= 0x20;
        }
    }
}

))
<commit_msg>TotalEq trait no longer defines an equal-function<commit_after>#![macro_escape]
macro_rules! auth_module (($auth_name:ident, $verify_name:ident, $verify_fn:ident, $keybytes:expr, $tagbytes:expr) => (

#[link(name = "sodium")]
extern {
    fn $auth_name(a: *mut u8,
                  m: *u8,
                  mlen: c_ulonglong,
                  k: *u8) -> c_int;
    fn $verify_name(a: *u8,
                    m: *u8,
                    mlen: c_ulonglong,
                    k: *u8) -> c_int;
}

pub static KEYBYTES: uint = $keybytes;
pub static TAGBYTES: uint = $tagbytes;

/**
 * Authentication `Key`
 *
 * When a `Key` goes out of scope its contents
 * will be zeroed out
 */
pub struct Key([u8, ..KEYBYTES]);

impl Drop for Key {
    fn drop(&mut self) {
        let &Key(ref mut k) = self;
        for e in k.mut_iter() { *e = 0 }
    }
}

/**
  * Authentication `Tag`
  *
  * The tag implements the traits `TotalEq` and `Eq` using constant-time
  * comparison functions. See `sodiumoxide::crypto::verify::verify_32`
  */
pub struct Tag([u8, ..TAGBYTES]);
impl TotalEq for Tag { }
impl Eq for Tag {
    fn eq(&self, &Tag(other): &Tag) -> bool {
        let &Tag(ref tag) = self;
        $verify_fn(tag, &other)
    }
}

/**
 * `gen_key()` randomly generates a key for authentication
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_key() -> Key {
    let mut k = [0, ..KEYBYTES];
    randombytes_into(k);
    Key(k)
}

/**
 * `authenticate()` authenticates a message `m` using a secret key `k`.
 * The function returns an authenticator tag.
 */
pub fn authenticate(m: &[u8],
                    &Key(k): &Key) -> Tag {
    unsafe {
        let mut tag = [0, ..TAGBYTES];
        $auth_name(tag.as_mut_ptr(),
                   m.as_ptr(),
                   m.len() as c_ulonglong,
                   k.as_ptr());
        Tag(tag)
    }
}

/**
 * `verify()` returns `true` if `tag` is a correct authenticator of message `m`
 * under a secret key `k`. Otherwise it returns false.
 */
pub fn verify(&Tag(tag): &Tag, m: &[u8],
              &Key(k): &Key) -> bool {
    unsafe {
        $verify_name(tag.as_ptr(),
                     m.as_ptr(),
                     m.len() as c_ulonglong,
                     k.as_ptr()) == 0
    }
}

#[test]
fn test_auth_verify() {
    use randombytes::randombytes;
    for i in range(0, 256) {
        let k = gen_key();
        let m = randombytes(i as uint);
        let tag = authenticate(m, &k);
        assert!(verify(&tag, m, &k));
    }
}

#[test]
fn test_auth_verify_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32) {
        let k = gen_key();
        let mut m = randombytes(i as uint);
        let Tag(mut tagbuf) = authenticate(m, &k);
        for j in range(0, m.len()) {
            m[j] ^= 0x20;
            assert!(!verify(&Tag(tagbuf), m, &k));
            m[j] ^= 0x20;
        }
        for j in range(0, tagbuf.len()) {
            tagbuf[j] ^= 0x20;
            assert!(!verify(&Tag(tagbuf), m, &k));
            tagbuf[j] ^= 0x20;
        }
    }
}

))
<|endoftext|>