<commit_before>// See LICENSE file for copyright and license details.

use std;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
  GLchar,
  GLenum,
  GLsizeiptr,
  GLsizei,
};
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use cgmath::angle;
use stb_image::image;
use misc::{
  c_str,
  deg_to_rad,
};
use color::Color3;

pub fn compile_shader(src: &str, shader_type: GLenum) -> GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &c_str(src), std::ptr::null());
    gl::CompileShader(shader);
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

pub fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

pub fn compile_program(
  vertex_shader_src: &str,
  frag_shader_src: &str,
) -> GLuint {
  let vertex_shader = compile_shader(
    vertex_shader_src, gl::VERTEX_SHADER);
  let fragment_shader = compile_shader(
    frag_shader_src, gl::FRAGMENT_SHADER);
  let program = link_program(vertex_shader, fragment_shader);
  // mark shaders for deletion after program deletion
  gl::DeleteShader(fragment_shader);
  gl::DeleteShader(vertex_shader);
  program
}

pub fn get_attr(program_id: GLuint, name: &str) -> GLuint {
  unsafe {
    gl::GetAttribLocation(program_id, c_str(name)) as GLuint
  }
}

pub fn get_uniform(program: GLuint, name: &str) -> GLint {
  unsafe {
    gl::GetUniformLocation(program, c_str(name))
  }
}

pub fn draw_mesh(faces_count: int) {
  let starting_index = 0;
  let vertices_count = faces_count as i32 * 3;
  gl::DrawArrays(gl::TRIANGLES, starting_index, vertices_count);
}

pub fn uniform_mat4f(mat_id: GLint, mat: &Mat4<GLfloat>) {
  unsafe {
    gl::UniformMatrix4fv(mat_id, 1, gl::FALSE, mat.cr(0, 0));
  }
}

pub fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

pub fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_x(rad).to_mat4();
  m.mul_m(&r)
}

pub fn rot_z(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_z(rad).to_mat4();
  m.mul_m(&r)
}

pub fn gen_buffer() -> GLuint {
  let mut n = 0 as GLuint;
  unsafe {
    gl::GenBuffers(1, &mut n);
  }
  n
}

pub fn delete_buffer(buffer: GLuint) {
  unsafe {
    gl::DeleteBuffers(1, &buffer);
  }
}

fn fill_buffer<T>(buffer_size: i64, data: &[T]) {
  unsafe {
    let data_ptr = std::cast::transmute(&data[0]);
    gl::BufferData(gl::ARRAY_BUFFER, buffer_size, data_ptr, gl::STATIC_DRAW);
  }
}

pub fn fill_current_coord_vbo(data: &[Vec3<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 3 * glfloat_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn fill_current_color_vbo(data: &[Color3]) {
  let color3_size = std::mem::size_of::<Color3>();
  let buffer_size = (data.len() * color3_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn fill_current_texture_coords_vbo(data: &[Vec2<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 2 * glfloat_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn vertex_attrib_pointer(attr: GLuint, components_count: i32) {
  let normalized = gl::FALSE;
  let stride = 0;
  unsafe {
    gl::VertexAttribPointer(
      attr,
      components_count,
      gl::FLOAT,
      normalized,
      stride,
      std::ptr::null(),
    );
  }
}

fn load_image(path: ~str) -> image::Image<u8> {
  let load_result = image::load(path);
  match load_result {
    image::ImageU8(image) => {
      image
    },
    image::Error(message) => {
      fail!("{}", message);
    },
    _ => {
      fail!("unkn");
    }
  }
}

pub fn load_texture(path: ~str) -> GLuint {
  let image = load_image(path);
  let mut id = 0;
  unsafe {
    gl::GenTextures(1, &mut id)
  };
  gl::ActiveTexture(gl::TEXTURE0);
  gl::BindTexture(gl::TEXTURE_2D, id);
  let format = match image.depth {
    4 => gl::RGBA,
    3 => gl::RGB,
    _ => fail!("wrong depth"),
  };
  unsafe {
    let level = 0;
    let border = 0;
    gl::TexImage2D(
      gl::TEXTURE_2D,
      level,
      format as GLint,
      image.width as GLsizei,
      image.height as GLsizei,
      border,
      format,
      gl::UNSIGNED_BYTE,
      std::cast::transmute(&image.data[0]),
    );
  }
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
  id
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>gl_helpers.rs: Fixed fail! message<commit_after>// See LICENSE file for copyright and license details.

use std;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
  GLchar,
  GLenum,
  GLsizeiptr,
  GLsizei,
};
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use cgmath::angle;
use stb_image::image;
use misc::{
  c_str,
  deg_to_rad,
};
use color::Color3;

pub fn compile_shader(src: &str, shader_type: GLenum) -> GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &c_str(src), std::ptr::null());
    gl::CompileShader(shader);
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

pub fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

pub fn compile_program(
  vertex_shader_src: &str,
  frag_shader_src: &str,
) -> GLuint {
  let vertex_shader = compile_shader(
    vertex_shader_src, gl::VERTEX_SHADER);
  let fragment_shader = compile_shader(
    frag_shader_src, gl::FRAGMENT_SHADER);
  let program = link_program(vertex_shader, fragment_shader);
  // mark shaders for deletion after program deletion
  gl::DeleteShader(fragment_shader);
  gl::DeleteShader(vertex_shader);
  program
}

pub fn get_attr(program_id: GLuint, name: &str) -> GLuint {
  unsafe {
    gl::GetAttribLocation(program_id, c_str(name)) as GLuint
  }
}

pub fn get_uniform(program: GLuint, name: &str) -> GLint {
  unsafe {
    gl::GetUniformLocation(program, c_str(name))
  }
}

pub fn draw_mesh(faces_count: int) {
  let starting_index = 0;
  let vertices_count = faces_count as i32 * 3;
  gl::DrawArrays(gl::TRIANGLES, starting_index, vertices_count);
}

pub fn uniform_mat4f(mat_id: GLint, mat: &Mat4<GLfloat>) {
  unsafe {
    gl::UniformMatrix4fv(mat_id, 1, gl::FALSE, mat.cr(0, 0));
  }
}

pub fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

pub fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_x(rad).to_mat4();
  m.mul_m(&r)
}

pub fn rot_z(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_z(rad).to_mat4();
  m.mul_m(&r)
}

pub fn gen_buffer() -> GLuint {
  let mut n = 0 as GLuint;
  unsafe {
    gl::GenBuffers(1, &mut n);
  }
  n
}

pub fn delete_buffer(buffer: GLuint) {
  unsafe {
    gl::DeleteBuffers(1, &buffer);
  }
}

fn fill_buffer<T>(buffer_size: i64, data: &[T]) {
  unsafe {
    let data_ptr = std::cast::transmute(&data[0]);
    gl::BufferData(gl::ARRAY_BUFFER, buffer_size, data_ptr, gl::STATIC_DRAW);
  }
}

pub fn fill_current_coord_vbo(data: &[Vec3<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 3 * glfloat_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn fill_current_color_vbo(data: &[Color3]) {
  let color3_size = std::mem::size_of::<Color3>();
  let buffer_size = (data.len() * color3_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn fill_current_texture_coords_vbo(data: &[Vec2<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 2 * glfloat_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn vertex_attrib_pointer(attr: GLuint, components_count: i32) {
  let normalized = gl::FALSE;
  let stride = 0;
  unsafe {
    gl::VertexAttribPointer(
      attr,
      components_count,
      gl::FLOAT,
      normalized,
      stride,
      std::ptr::null(),
    );
  }
}

fn load_image(path: ~str) -> image::Image<u8> {
  let load_result = image::load(path);
  match load_result {
    image::ImageU8(image) => {
      image
    },
    image::Error(message) => {
      fail!("{}", message);
    },
    _ => {
      fail!("Unknown image format");
    }
  }
}

pub fn load_texture(path: ~str) -> GLuint {
  let image = load_image(path);
  let mut id = 0;
  unsafe {
    gl::GenTextures(1, &mut id)
  };
  gl::ActiveTexture(gl::TEXTURE0);
  gl::BindTexture(gl::TEXTURE_2D, id);
  let format = match image.depth {
    4 => gl::RGBA,
    3 => gl::RGB,
    _ => fail!("wrong depth"),
  };
  unsafe {
    let level = 0;
    let border = 0;
    gl::TexImage2D(
      gl::TEXTURE_2D,
      level,
      format as GLint,
      image.width as GLsizei,
      image.height as GLsizei,
      border,
      format,
      gl::UNSIGNED_BYTE,
      std::cast::transmute(&image.data[0]),
    );
  }
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
  id
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>use std::env;
use std::time::Duration;

use futures::StreamExt;
use tokio::time::delay_for;

use telegram_bot::prelude::*;
use telegram_bot::{
    Api, Error, Message, MessageKind, Poll, PollAnswer, SendPoll, UpdateKind, User,
};

fn make_test_poll<'p>(message: Message) -> SendPoll<'p, 'p, 'p> {
    let question = "Simple poll";
    let options = vec!["Option 1", "Option 2"];

    message.poll_reply(question, options)
}

async fn send_and_stop_poll<'p>(api: Api, poll: SendPoll<'p, 'p, 'p>) -> Result<(), Error> {
    let poll_message = api.send(poll).await?;

    delay_for(Duration::from_secs(10)).await;

    api.send(poll_message.stop_poll()).await?;
    Ok(())
}

async fn test_anonymous_poll(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message);
    send_and_stop_poll(api, poll).await
}

async fn test_public_poll(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message.clone()).not_anonymous().to_owned();

    send_and_stop_poll(api, poll).await
}

async fn test_quiz_poll(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message.clone())
        .quiz()
        .correct_option_id(0)
        .to_owned();

    send_and_stop_poll(api, poll).await
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let token = env::var("TELEGRAM_BOT_TOKEN").expect("TELEGRAM_BOT_TOKEN not set");

    let api = Api::new(token);
    let mut stream = api.stream();

    while let Some(update) = stream.next().await {
        let update = update?;

        match update.kind {
            UpdateKind::Message(message) => match message.kind {
                MessageKind::Text { ref data, .. } => match data.as_str() {
                    "/poll" => test_anonymous_poll(api.clone(), message).await?,
                    "/quiz" => test_quiz_poll(api.clone(), message).await?,
                    "/public" => test_public_poll(api.clone(), message).await?,
                    _ => (),
                },
                _ => (),
            },
            UpdateKind::Poll(Poll {
                total_voter_count,
                id,
                ..
            }) => println!(
                "Poll update - {} with total voters {}",
                id, total_voter_count
            ),
            UpdateKind::PollAnswer(PollAnswer {
                poll_id,
                user: User { first_name, .. },
                option_ids,
            }) => println!(
                "In poll {} {} voted for {:?}",
                poll_id, first_name, option_ids
            ),
            _ => (),
        }
    }

    Ok(())
}
<commit_msg>add more poll examples<commit_after>use std::env;
use std::time::Duration;

use futures::StreamExt;
use tokio::time::delay_for;

use telegram_bot::prelude::*;
use telegram_bot::{
    Api, Error, Message, MessageKind, Poll, PollAnswer, SendPoll, UpdateKind, User,
};

fn make_test_poll<'p>(message: Message) -> SendPoll<'p, 'p, 'p> {
    let question = "Simple poll";
    let options = vec!["Option 1", "Option 2"];

    message.poll_reply(question, options)
}

async fn send_and_stop_poll<'p>(api: Api, poll: SendPoll<'p, 'p, 'p>) -> Result<(), Error> {
    let poll_message = api.send(poll).await?;

    delay_for(Duration::from_secs(10)).await;

    api.send(poll_message.stop_poll()).await?;
    Ok(())
}

async fn test_anonymous_poll(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message);
    send_and_stop_poll(api, poll).await
}

async fn test_public_poll(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message.clone()).not_anonymous().to_owned();

    send_and_stop_poll(api, poll).await
}

async fn test_quiz_poll(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message.clone())
        .quiz()
        .correct_option_id(0)
        .explanation("Some explanation")
        .to_owned();

    send_and_stop_poll(api, poll).await
}

async fn test_multiple_answers(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message.clone())
        .allows_multiple_answers()
        .to_owned();

    send_and_stop_poll(api, poll).await
}

async fn test_closed_poll(api: Api, message: Message) -> Result<(), Error> {
    let poll = make_test_poll(message.clone()).closed().to_owned();

    api.send(poll).await?;
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let token = env::var("TELEGRAM_BOT_TOKEN").expect("TELEGRAM_BOT_TOKEN not set");

    let api = Api::new(token);
    let mut stream = api.stream();

    while let Some(update) = stream.next().await {
        let update = update?;

        match update.kind {
            UpdateKind::Message(message) => match message.kind {
                MessageKind::Text { ref data, .. } => match data.as_str() {
                    "/poll" => test_anonymous_poll(api.clone(), message).await?,
                    "/quiz" => test_quiz_poll(api.clone(), message).await?,
                    "/public" => test_public_poll(api.clone(), message).await?,
                    "/multiple" => test_multiple_answers(api.clone(), message).await?,
                    "/closed" => test_closed_poll(api.clone(), message).await?,
                    _ => (),
                },
                _ => (),
            },
            UpdateKind::Poll(Poll {
                total_voter_count,
                id,
                ..
            }) => println!(
                "Poll update - {} with total voters {}",
                id, total_voter_count
            ),
            UpdateKind::PollAnswer(PollAnswer {
                poll_id,
                user: User { first_name, .. },
                option_ids,
            }) => println!(
                "In poll {} {} voted for {:?}",
                poll_id, first_name, option_ids
            ),
            _ => (),
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::string::ToString;

#[derive(Debug, Clone, PartialEq, Serialize)]
pub enum FrameRate {
  _24_00,
  _25_00,
  _30_00,
  _50_00,
  _60_00,
}

impl From<FrameRate> for f32 {
  fn from(fr: FrameRate) -> Self {
    match fr {
      FrameRate::_24_00 => 24.0,
      FrameRate::_25_00 => 25.0,
      FrameRate::_30_00 => 30.0,
      FrameRate::_50_00 => 50.0,
      FrameRate::_60_00 => 60.0,
    }
  }
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Timecode {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: FrameRate,
}

impl ToString for Timecode {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl From<(u32, FrameRate)> for Timecode {
  fn from((frames, frame_rate): (u32, FrameRate)) -> Self {
    let fps: f32 = frame_rate.clone().into();

    let hours = frames / (60 * 60 * fps as u32);
    let minutes = frames / (60 * fps as u32) - hours * 60;
    let seconds = (frames / fps as u32) - minutes * 60 - hours * 60 * 60;
    let frame = frames
      - seconds * (fps as u32)
      - minutes * 60 * (fps as u32)
      - hours * 60 * 60 * (fps as u32);
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate,
    }
  }
}

impl Timecode {
  pub fn frame_rate(&self) -> &FrameRate {
    &self.frame_rate
  }

  pub fn parse_smpte_331m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::parse_smpte_12m(&data[1..], frame_rate),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::get_number(data[0], mask_tens_2);
    let seconds = Timecode::get_number(data[1], mask_tens_3);
    let minutes = Timecode::get_number(data[2], mask_tens_3);
    let hours = Timecode::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate,
    })
  }

  // used in STL format (EBU Tech 3264)
  pub fn from_ebu_smpte_time_and_control(data: &[u8; 4], frame_rate: FrameRate) -> Timecode {
    Timecode {
      hours: data[0],
      minutes: data[1],
      seconds: data[2],
      frame: data[3],
      drop_frame: false,
      color_frame: false,
      frame_rate,
    }
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let timecode = Timecode::from((24 * 60 * 60 * 10, FrameRate::_24_00));
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 1);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 59);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 1);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((23, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((25, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 24);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[10, 0, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 10, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 10);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 10, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 10);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 0, 10], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 10);
}
<commit_msg>convert timecode to f64<commit_after>use std::string::ToString;

#[derive(Debug, Clone, PartialEq, Serialize)]
pub enum FrameRate {
  _24_00,
  _25_00,
  _30_00,
  _50_00,
  _60_00,
}

impl From<FrameRate> for f32 {
  fn from(fr: FrameRate) -> Self {
    match fr {
      FrameRate::_24_00 => 24.0,
      FrameRate::_25_00 => 25.0,
      FrameRate::_30_00 => 30.0,
      FrameRate::_50_00 => 50.0,
      FrameRate::_60_00 => 60.0,
    }
  }
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Timecode {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: FrameRate,
}

impl ToString for Timecode {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl From<(u32, FrameRate)> for Timecode {
  fn from((frames, frame_rate): (u32, FrameRate)) -> Self {
    let fps: f32 = frame_rate.clone().into();

    let hours = frames / (60 * 60 * fps as u32);
    let minutes = frames / (60 * fps as u32) - hours * 60;
    let seconds = (frames / fps as u32) - minutes * 60 - hours * 60 * 60;
    let frame = frames
      - seconds * (fps as u32)
      - minutes * 60 * (fps as u32)
      - hours * 60 * 60 * (fps as u32);
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate,
    }
  }
}

impl From<&Timecode> for f64 {
  fn from(timecode: &Timecode) -> Self {
    (timecode.hours as f64) * 3600.0 + (timecode.minutes as f64) * 60.0 + (timecode.seconds as f64)
  }
}

impl Timecode {
  pub fn frame_rate(&self) -> &FrameRate {
    &self.frame_rate
  }

  pub fn parse_smpte_331m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::parse_smpte_12m(&data[1..], frame_rate),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::get_number(data[0], mask_tens_2);
    let seconds = Timecode::get_number(data[1], mask_tens_3);
    let minutes = Timecode::get_number(data[2], mask_tens_3);
    let hours = Timecode::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate,
    })
  }

  // used in STL format (EBU Tech 3264)
  pub fn from_ebu_smpte_time_and_control(data: &[u8; 4], frame_rate: FrameRate) -> Timecode {
    Timecode {
      hours: data[0],
      minutes: data[1],
      seconds: data[2],
      frame: data[3],
      drop_frame: false,
      color_frame: false,
      frame_rate,
    }
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let timecode = Timecode::from((24 * 60 * 60 * 10, FrameRate::_24_00));
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 1);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 59);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 1);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((23, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((25, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 24);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[10, 0, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 10, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 10);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 10, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 10);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 0, 10], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 10);
}
<|endoftext|>


<commit_before>extern crate bincode;
extern crate rustc_serialize;

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use rustc_serialize::{Encodable, Decodable};

use ::{KeyType, ValueType};

use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Iter as MIter;
use std::collections::btree_set::Iter as SIter;
use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write, ErrorKind};
use std::io::Error as IOError;
use std::iter::Peekable;
use std::marker::PhantomData;

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
pub struct KeyValuePair<K: KeyType, V: ValueType> {
    pub key: K,
    pub value: V,
}

pub struct WALFile<K: KeyType, V: ValueType> {
    fd: File,  // the WAL file
    key_size: usize,
    value_size: usize,
    _k_marker: PhantomData<K>,
    _v_marker: PhantomData<V>
}

pub struct WALIterator<'a, K: KeyType + 'a, V: ValueType + 'a> {
    wal_file: &'a mut WALFile<K,V>,  // the WAL file
    _k_marker: PhantomData<K>,
    _v_marker: PhantomData<V>
}

impl <K: KeyType, V: ValueType> WALFile<K,V> {
    pub fn new(wal_file_path: String, key_size: usize, value_size: usize) -> Result<WALFile<K,V>, Box<Error>> {
        let mut wal_file = try!(OpenOptions::new().read(true).create(false).open(wal_file_path));

        return Ok(WALFile{fd: wal_file,
                          key_size: key_size,
                          value_size: value_size,
                          _k_marker: PhantomData,
                          _v_marker: PhantomData});
    }

    pub fn is_new(&self) -> Result<bool, Box<Error>> {
        return Ok(try!(self.fd.metadata()).len() == 0);
    }

    pub fn write_record(&mut self, kv: &KeyValuePair<K,V>) -> Result<(), Box<Error>> {
        // encode the record
        let record_size = self.key_size + self.value_size;
        let mut buff = try!(encode(&kv, SizeLimit::Bounded(record_size as u64)));

        // padd it out to the max size
        if buff.len() > self.key_size + self.value_size {
            return Err(From::from(IOError::new(ErrorKind::InvalidData, "Key and value size are too large")));
        } else {
            let diff = (self.key_size + self.value_size) - buff.len();
            buff.extend(vec![0; diff]);
        }

        match self.fd.write_all(&buff) {
            Ok(_) => Ok( () ),
            Err(e) => Err(From::from(e))
        }
    }
}

impl <'a, K: KeyType, V: ValueType> IntoIterator for &'a mut WALFile<K,V> {
    type Item = KeyValuePair<K,V>;
    type IntoIter = WALIterator<'a, K,V>;

    fn into_iter(self) -> Self::IntoIter {
        let k_marker = self._k_marker;
        let v_marker = self._v_marker;

        WALIterator{wal_file: self, _k_marker: k_marker, _v_marker: v_marker}
    }
}

impl <'a, K: KeyType, V: ValueType> Iterator for WALIterator<'a,K,V> {
    type Item = KeyValuePair<K,V>;

    fn next(&mut self) -> Option<Self::Item> {
        let total_size = self.wal_file.key_size + self.wal_file.value_size;
        let mut buff = vec![0; total_size];

        // attempt to read a buffer's worth and decode
        match self.wal_file.fd.read_exact(&mut buff) {
            Ok(_) => {
                match decode(&buff) {
                    Ok(record) => Some(record),
                    Err(_) => None
                }
            },
            Err(_) => None
        }
    }
}

/*

struct MemoryRecordIterator<'a, 'b, K: KeyType, V: ValueType> {
    key_size: usize,
    value_size: usize,
    key_iter: Peekable<MIter<'a, K, BTreeSet<V>>>,
    value_iter: Option<Peekable<SIter<'b, V>>>
}

impl <'a, 'b, K: KeyType, V: ValueType> MemoryRecordIterator<'a, 'b, K, V> {
    fn new(key_size: usize, value_size: usize, mem_tree: BTreeMap<K, BTreeSet<V>>) -> MemoryRecordIterator<'a, 'b, K,V> {
        let key_it = mem_tree.iter().peekable();

        MemoryRecordIterator {key_size: key_size,
                              value_size: value_size,
                              key_iter: key_it,
                              value_iter: key_it.peek().iter().peekable()}
    }
}

impl <'a, 'b, K: KeyType, V: ValueType> Iterator for MemoryRecordIterator<'a, 'b, K,V> {
    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Self::Item> {

    }
}

*/

#[cfg(test)]
mod tests {
    use tests::gen_temp_name;
    use std::fs;
    use std::fs::OpenOptions;
    use wal_file::{WALFile, KeyValuePair};

    #[test]
    fn test_iterator() {
        let file_path = gen_temp_name();
        let wal_file = WALFile::new(file_path.to_owned() + ".wal", 20, 20).unwrap();

        let kv1 = KeyValuePair{key: "hello".to_owned(), value: "world".to_owned()};
        let kv2 = KeyValuePair{key: "foo".to_owned(), value: "bar".to_owned()};

        wal_file.write_record(kv1);
        wal_file.write_record(kv2);

        let wal_it = wal_file.iter();

        let it_kv1 = wal_it.next().unwrap();

        assert!(kv1.key == it_kv1.key);
        assert!(kv1.value == it_kv1.value);

        let it_kv2 = wal_it.next().unwrap();

        assert!(kv2.key == it_kv2.key);
        assert!(kv2.value == it_kv2.value);
    }
}
<commit_msg>Fixed test case for WALIterator<commit_after>extern crate bincode;
extern crate rustc_serialize;

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use rustc_serialize::{Encodable, Decodable};

use ::{KeyType, ValueType};

use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Iter as MIter;
use std::collections::btree_set::Iter as SIter;
use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write, ErrorKind, Seek, SeekFrom};
use std::io::Error as IOError;
use std::iter::Peekable;
use std::marker::PhantomData;

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
pub struct KeyValuePair<K: KeyType, V: ValueType> {
    pub key: K,
    pub value: V,
}

pub struct WALFile<K: KeyType, V: ValueType> {
    fd: File,  // the WAL file
    key_size: usize,
    value_size: usize,
    _k_marker: PhantomData<K>,
    _v_marker: PhantomData<V>
}

pub struct WALIterator<'a, K: KeyType + 'a, V: ValueType + 'a> {
    wal_file: &'a mut WALFile<K,V>,  // the WAL file
    _k_marker: PhantomData<K>,
    _v_marker: PhantomData<V>
}

impl <K: KeyType, V: ValueType> WALFile<K,V> {
    pub fn new(wal_file_path: String, key_size: usize, value_size: usize) -> Result<WALFile<K,V>, Box<Error>> {
        let mut wal_file = try!(OpenOptions::new().read(true).write(true).create(false).open(wal_file_path));

        return Ok(WALFile{fd: wal_file,
                          key_size: key_size,
                          value_size: value_size,
                          _k_marker: PhantomData,
                          _v_marker: PhantomData});
    }

    pub fn is_new(&self) -> Result<bool, Box<Error>> {
        return Ok(try!(self.fd.metadata()).len() == 0);
    }

    pub fn write_record(&mut self, kv: &KeyValuePair<K,V>) -> Result<(), Box<Error>> {
        // encode the record
        let record_size = self.key_size + self.value_size;
        let mut buff = try!(encode(&kv, SizeLimit::Bounded(record_size as u64)));

        // padd it out to the max size
        if buff.len() > self.key_size + self.value_size {
            return Err(From::from(IOError::new(ErrorKind::InvalidData, "Key and value size are too large")));
        } else {
            let diff = (self.key_size + self.value_size) - buff.len();
            buff.extend(vec![0; diff]);
        }

        match self.fd.write_all(&buff) {
            Ok(_) => Ok( () ),
            Err(e) => Err(From::from(e))
        }
    }
}

impl <'a, K: KeyType, V: ValueType> IntoIterator for &'a mut WALFile<K,V> {
    type Item = KeyValuePair<K,V>;
    type IntoIter = WALIterator<'a, K,V>;

    fn into_iter(self) -> Self::IntoIter {
        let k_marker = self._k_marker;
        let v_marker = self._v_marker;

        // seek back to the start
        self.fd.seek(SeekFrom::Start(0));

        // create our iterator
        WALIterator{wal_file: self, _k_marker: k_marker, _v_marker: v_marker}
    }
}

impl <'a, K: KeyType, V: ValueType> Iterator for WALIterator<'a,K,V> {
    type Item = KeyValuePair<K,V>;

    fn next(&mut self) -> Option<Self::Item> {
        let total_size = self.wal_file.key_size + self.wal_file.value_size;
        let mut buff = vec![0; total_size];

        println!("Creating buffer: {}", total_size);

        // attempt to read a buffer's worth and decode
        match self.wal_file.fd.read_exact(&mut buff) {
            Ok(_) => {
                match decode(&buff) {
                    Ok(record) => Some(record),
                    Err(_) => None
                }
            },
            Err(e) => {
                println!("ERROR: {}", e);
                None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use tests::gen_temp_name;
    use std::fs;
    use std::fs::OpenOptions;
    use wal_file::{WALFile, KeyValuePair};

    #[test]
    fn test_iterator() {
        let temp_path = gen_temp_name();
        let file_path = temp_path.to_owned() + ".wal";

        // create a new blank file
        OpenOptions::new().read(true).write(true).truncate(true).create(true).open(&file_path);

        let mut wal_file = WALFile::new(file_path, 20, 20).unwrap();

        let kv1 = KeyValuePair{key: "hello".to_owned(), value: "world".to_owned()};
        let kv2 = KeyValuePair{key: "foo".to_owned(), value: "bar".to_owned()};

        wal_file.write_record(&kv1).unwrap();
        wal_file.write_record(&kv2).unwrap();

        let mut wal_it = wal_file.into_iter();

        let it_kv1 = wal_it.next().unwrap();

        assert!(kv1.key == it_kv1.key);
        assert!(kv1.value == it_kv1.value);

        let it_kv2 = wal_it.next().unwrap();

        assert!(kv2.key == it_kv2.key);
        assert!(kv2.value == it_kv2.value);
    }
}
<|endoftext|>


<commit_before>use std::slice;
use std::vec;
use std::cmp;

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// The iterator **Zip\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::Zip;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
///
/// for (i, a, b) in Zip::new((0i32..100, xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct Zip<T> {
    t: T
}

impl<T> Zip<T> where Zip<T>: Iterator
{
    /// Create a new **Zip** from a tuple of iterators.
    pub fn new(t: T) -> Zip<T>
    {
        Zip{t: t}
    }
}

macro_rules! impl_zip_iter {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for Zip<($($B,)*)>
            where
            $(
                $B: Iterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<
                    ($(<$B as Iterator>::Item,)*)
                >
            {
                let &mut Zip { t : ($(ref mut $B,)*)} = self;
                // WARNING: partial consume possible
                // Zip worked the same.
                $(
                    let $B = match $B.next() {
                        None => return None,
                        Some(elt) => elt
                    };
                )*
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                let low = ::std::usize::MAX;
                let high = None;
                let &Zip { t : ($(ref $B,)*) } = self;
                $(
                    // update estimate
                    let (l, h) = $B.size_hint();
                    let low = cmp::min(low, l);
                    let high = match (high, h) {
                        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
                        _ => high.or(h)
                    };
                )*
                (low, high)
            }
        }
    );
}

impl_zip_iter!(A);
impl_zip_iter!(A, B);
impl_zip_iter!(A, B, C);
impl_zip_iter!(A, B, C, D);
impl_zip_iter!(A, B, C, D, E);
impl_zip_iter!(A, B, C, D, E, F);
impl_zip_iter!(A, B, C, D, E, F, G);
impl_zip_iter!(A, B, C, D, E, F, G, H);
impl_zip_iter!(A, B, C, D, E, F, G, H, I);

/// A **TrustedIterator** has exact size, always.
///
/// **Note:** TrustedIterator is *Experimental.*
pub unsafe trait TrustedIterator : ExactSizeIterator
{
    /* no methods */
}

unsafe impl TrustedIterator for ::std::ops::Range<usize> { }
unsafe impl TrustedIterator for ::std::ops::Range<u32> { }
unsafe impl TrustedIterator for ::std::ops::Range<i32> { }
unsafe impl TrustedIterator for ::std::ops::Range<u16> { }
unsafe impl TrustedIterator for ::std::ops::Range<i16> { }
unsafe impl TrustedIterator for ::std::ops::Range<u8> { }
unsafe impl TrustedIterator for ::std::ops::Range<i8> { }
unsafe impl<'a, T> TrustedIterator for slice::Iter<'a, T> { }
unsafe impl<'a, T> TrustedIterator for slice::IterMut<'a, T> { }
unsafe impl<T> TrustedIterator for vec::IntoIter<T> { }

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// **ZipTrusted** is an experimental version of **Zip**, and it can only use iterators that are
/// known to provide their exact size up front. The lockstep iteration can then compile to faster
/// code, ideally not checking more than once per lap for the end of iteration.
///
/// The iterator **ZipTrusted\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::ZipTrusted;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
///
/// for (i, a, b) in ZipTrusted::new((0..100, xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct ZipTrusted<T> {
    length: usize,
    t: T
}

trait SetLength {
    fn set_length(&mut self);
}

impl<T> ZipTrusted<T> where ZipTrusted<T>: SetLength
{
    /// Create a new **ZipTrusted** from a tuple of iterators.
    #[inline]
    pub fn new(t: T) -> ZipTrusted<T>
    {
        let mut iter = ZipTrusted {
            length: 0,
            t: t,
        };
        iter.set_length();
        iter
    }
}

macro_rules! impl_zip_trusted {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> SetLength for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            #[inline]
            fn set_length(&mut self)
            {
                let len = ::std::usize::MAX;
                let ($(ref $B,)*) = self.t;
                $(
                    let (l, h) = $B.size_hint();
                    let len = cmp::min(len, l);
                    debug_assert!(Some(l) == h);
                )*
                self.length = len;
            }
        }

        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<<Self as Iterator>::Item>
            {
                let ($(ref mut $B,)*) = self.t;

                if self.length == 0 {
                    return None
                }
                $(
                    let next_opt = $B.next();
                    let $B;
                    unsafe {
                        ::std::intrinsics::assume(match next_opt {
                            None => false,
                            Some(_) => true,
                        });
                        $B = match next_opt {
                            None => return None,
                            Some(elt) => elt
                        };
                    }
                )*
                self.length -= 1;
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                (self.length, Some(self.length))
            }
        }
    );
}

impl_zip_trusted!(A);
impl_zip_trusted!(A, B);
impl_zip_trusted!(A, B, C);
impl_zip_trusted!(A, B, C, D);
impl_zip_trusted!(A, B, C, D, E);
impl_zip_trusted!(A, B, C, D, E, F);
impl_zip_trusted!(A, B, C, D, E, F, G);
impl_zip_trusted!(A, B, C, D, E, F, G, H);
impl_zip_trusted!(A, B, C, D, E, F, G, H, I);

<commit_msg>Mark iter::{Rev, Take} as a trusted iterators<commit_after>use std::slice;
use std::vec;
use std::iter;
use std::cmp;

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// The iterator **Zip\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::Zip;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
///
/// for (i, a, b) in Zip::new((0i32..100, xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct Zip<T> {
    t: T
}

impl<T> Zip<T> where Zip<T>: Iterator
{
    /// Create a new **Zip** from a tuple of iterators.
    pub fn new(t: T) -> Zip<T>
    {
        Zip{t: t}
    }
}

macro_rules! impl_zip_iter {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for Zip<($($B,)*)>
            where
            $(
                $B: Iterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<
                    ($(<$B as Iterator>::Item,)*)
                >
            {
                let &mut Zip { t : ($(ref mut $B,)*)} = self;
                // WARNING: partial consume possible
                // Zip worked the same.
                $(
                    let $B = match $B.next() {
                        None => return None,
                        Some(elt) => elt
                    };
                )*
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                let low = ::std::usize::MAX;
                let high = None;
                let &Zip { t : ($(ref $B,)*) } = self;
                $(
                    // update estimate
                    let (l, h) = $B.size_hint();
                    let low = cmp::min(low, l);
                    let high = match (high, h) {
                        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
                        _ => high.or(h)
                    };
                )*
                (low, high)
            }
        }
    );
}

impl_zip_iter!(A);
impl_zip_iter!(A, B);
impl_zip_iter!(A, B, C);
impl_zip_iter!(A, B, C, D);
impl_zip_iter!(A, B, C, D, E);
impl_zip_iter!(A, B, C, D, E, F);
impl_zip_iter!(A, B, C, D, E, F, G);
impl_zip_iter!(A, B, C, D, E, F, G, H);
impl_zip_iter!(A, B, C, D, E, F, G, H, I);

/// A **TrustedIterator** has exact size, always.
///
/// **Note:** TrustedIterator is *Experimental.*
pub unsafe trait TrustedIterator : ExactSizeIterator
{
    /* no methods */
}

unsafe impl TrustedIterator for ::std::ops::Range<usize> { }
unsafe impl TrustedIterator for ::std::ops::Range<u32> { }
unsafe impl TrustedIterator for ::std::ops::Range<i32> { }
unsafe impl TrustedIterator for ::std::ops::Range<u16> { }
unsafe impl TrustedIterator for ::std::ops::Range<i16> { }
unsafe impl TrustedIterator for ::std::ops::Range<u8> { }
unsafe impl TrustedIterator for ::std::ops::Range<i8> { }
unsafe impl<'a, T> TrustedIterator for slice::Iter<'a, T> { }
unsafe impl<'a, T> TrustedIterator for slice::IterMut<'a, T> { }
unsafe impl<T> TrustedIterator for vec::IntoIter<T> { }

unsafe impl<I> TrustedIterator for iter::Rev<I> where
    I: DoubleEndedIterator + TrustedIterator,
{ }
unsafe impl<I> TrustedIterator for iter::Take<I> where
    I: TrustedIterator,
{ }

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// **ZipTrusted** is an experimental version of **Zip**, and it can only use iterators that are
/// known to provide their exact size up front. The lockstep iteration can then compile to faster
/// code, ideally not checking more than once per lap for the end of iteration.
///
/// The iterator **ZipTrusted\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::ZipTrusted;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
///
/// for (i, a, b) in ZipTrusted::new((0..100, xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct ZipTrusted<T> {
    length: usize,
    t: T
}

trait SetLength {
    fn set_length(&mut self);
}

impl<T> ZipTrusted<T> where ZipTrusted<T>: SetLength
{
    /// Create a new **ZipTrusted** from a tuple of iterators.
    #[inline]
    pub fn new(t: T) -> ZipTrusted<T>
    {
        let mut iter = ZipTrusted {
            length: 0,
            t: t,
        };
        iter.set_length();
        iter
    }
}

macro_rules! impl_zip_trusted {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> SetLength for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            #[inline]
            fn set_length(&mut self)
            {
                let len = ::std::usize::MAX;
                let ($(ref $B,)*) = self.t;
                $(
                    let (l, h) = $B.size_hint();
                    let len = cmp::min(len, l);
                    debug_assert!(Some(l) == h);
                )*
                self.length = len;
            }
        }

        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<<Self as Iterator>::Item>
            {
                let ($(ref mut $B,)*) = self.t;

                if self.length == 0 {
                    return None
                }
                $(
                    let next_opt = $B.next();
                    let $B;
                    unsafe {
                        ::std::intrinsics::assume(match next_opt {
                            None => false,
                            Some(_) => true,
                        });
                        $B = match next_opt {
                            None => return None,
                            Some(elt) => elt
                        };
                    }
                )*
                self.length -= 1;
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                (self.length, Some(self.length))
            }
        }
    );
}

impl_zip_trusted!(A);
impl_zip_trusted!(A, B);
impl_zip_trusted!(A, B, C);
impl_zip_trusted!(A, B, C, D);
impl_zip_trusted!(A, B, C, D, E);
impl_zip_trusted!(A, B, C, D, E, F);
impl_zip_trusted!(A, B, C, D, E, F, G);
impl_zip_trusted!(A, B, C, D, E, F, G, H);
impl_zip_trusted!(A, B, C, D, E, F, G, H, I);

<|endoftext|>


<commit_before>use correlation::Correlator;
use correlation::message::MessageBuilder;
use correlation::test_utils::correlator::MessageEventHandler;

use env_logger;

use std::cell::RefCell;
use std::rc::Rc;

#[test]
fn test_given_correlator_when_messages_are_received_then_they_are_grouped_into_a_context_by_a_context_id() {
    let _ = env_logger::init();
    let contexts_file = "tests/correlator/contexts.json";
    let mut correlator = Correlator::from_path(contexts_file).ok().expect("Failed to load contexts from a valid contexts_file");
    let login_message = MessageBuilder::new("6d2cba0c-e241-464a-89c3-8035cac8f73e")
                                        .name(Some("LOGIN"))
                                        .pair("user_name", "linus")
                                        .build();
    let read_message = MessageBuilder::new("60dd1233-5fa6-4e3b-993f-e04ef9b4c164")
                                        .name(Some("MAIL_READ"))
                                        .pair("user_name", "linus")
                                        .build();
    let logout_message = MessageBuilder::new("91ea534a-4880-4853-aec2-7b2a2df9a8c9")
                                        .name(Some("LOGOUT"))
                                        .pair("user_name", "linus")
                                        .build();
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_event_handler = Box::new(MessageEventHandler{responses: responses.clone()});
    correlator.register_handler(message_event_handler);
    let _ = correlator.push_message(login_message);
    let _ = correlator.push_message(read_message);
    let _ = correlator.push_message(logout_message);
    correlator.handle_events();
    assert_eq!(1, responses.borrow().len());
}
<commit_msg>tests: fix a testcase by stopping the Correlator<commit_after>use correlation::Correlator;
use correlation::message::MessageBuilder;
use correlation::test_utils::correlator::MessageEventHandler;

use env_logger;

use std::cell::RefCell;
use std::rc::Rc;

#[test]
fn test_given_correlator_when_messages_are_received_then_they_are_grouped_into_a_context_by_a_context_id() {
    let _ = env_logger::init();
    let contexts_file = "tests/correlator/contexts.json";
    let mut correlator = Correlator::from_path(contexts_file).ok().expect("Failed to load contexts from a valid contexts_file");
    let login_message = MessageBuilder::new("6d2cba0c-e241-464a-89c3-8035cac8f73e")
                                        .name(Some("LOGIN"))
                                        .pair("user_name", "linus")
                                        .build();
    let read_message = MessageBuilder::new("60dd1233-5fa6-4e3b-993f-e04ef9b4c164")
                                        .name(Some("MAIL_READ"))
                                        .pair("user_name", "linus")
                                        .build();
    let logout_message = MessageBuilder::new("91ea534a-4880-4853-aec2-7b2a2df9a8c9")
                                        .name(Some("LOGOUT"))
                                        .pair("user_name", "linus")
                                        .build();
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_event_handler = Box::new(MessageEventHandler{responses: responses.clone()});
    correlator.register_handler(message_event_handler);
    let _ = correlator.push_message(login_message);
    let _ = correlator.push_message(read_message);
    let _ = correlator.push_message(logout_message);
    correlator.handle_events();
    correlator.stop();
    assert_eq!(1, responses.borrow().len());
}
<|endoftext|>


<commit_before>use std::fs::{self, File};
use std::io::prelude::*;
use std::env;
use tempdir::TempDir;

use support::{execs, paths};
use support::paths::CargoPathExt;
use hamcrest::{assert_that, existing_file, existing_dir, is_not};

use cargo::util::ProcessBuilder;

fn setup() {
}

fn cargo_process(s: &str) -> ProcessBuilder {
    let mut p = ::cargo_process();
    p.arg(s);
    return p;
}

test!(simple_lib {
    assert_that(cargo_process("new").arg("foo").arg("--vcs").arg("none")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo"), existing_dir());
    assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
    assert_that(&paths::root().join("foo/src/lib.rs"), existing_file());
    assert_that(&paths::root().join("foo/.gitignore"), is_not(existing_file()));

    assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
                execs().with_status(0));
});

test!(simple_bin {
    assert_that(cargo_process("new").arg("foo").arg("--bin")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo"), existing_dir());
    assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
    assert_that(&paths::root().join("foo/src/main.rs"), existing_file());

    assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
                execs().with_status(0));
    assert_that(&paths::root().join(&format!("foo/target/debug/foo{}",
                                             env::consts::EXE_SUFFIX)),
                existing_file());
});

test!(simple_git {
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo").cwd(td.path().clone())
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(td.path(), existing_dir());
    assert_that(&td.path().join("foo/Cargo.toml"), existing_file());
    assert_that(&td.path().join("foo/src/lib.rs"), existing_file());
    assert_that(&td.path().join("foo/.git"), existing_dir());
    assert_that(&td.path().join("foo/.gitignore"), existing_file());

    assert_that(cargo_process("build").cwd(&td.path().clone().join("foo")),
                execs().with_status(0));
});

test!(no_argument {
    assert_that(cargo_process("new"),
                execs().with_status(1)
                       .with_stderr("\
[ERROR] Invalid arguments.

Usage:
    cargo new [options] <path>
    cargo new -h | --help
"));
});

test!(existing {
    let dst = paths::root().join("foo");
    fs::create_dir(&dst).unwrap();
    assert_that(cargo_process("new").arg("foo"),
                execs().with_status(101)
                       .with_stderr(format!("[ERROR] destination `{}` already exists\n",
                                            dst.display())));
});

test!(invalid_characters {
    assert_that(cargo_process("new").arg("foo.rs"),
                execs().with_status(101)
                       .with_stderr("\
[ERROR] Invalid character `.` in crate name: `foo.rs`
use --name to override crate name"));
});

test!(reserved_name {
    assert_that(cargo_process("new").arg("test"),
                execs().with_status(101)
                       .with_stderr("\
[ERROR] The name `test` cannot be used as a crate name\n\
use --name to override crate name"));
});

test!(keyword_name {
    assert_that(cargo_process("new").arg("pub"),
                execs().with_status(101)
                       .with_stderr("\
[ERROR] The name `pub` cannot be used as a crate name\n\
use --name to override crate name"));
});

test!(rust_prefix_stripped {
    assert_that(cargo_process("new").arg("rust-foo").env("USER", "foo"),
                execs().with_status(0)
                       .with_stdout("note: package will be named `foo`; use --name to override"));
    let toml = paths::root().join("rust-foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"name = "foo""#));
});

test!(bin_disables_stripping {
    assert_that(cargo_process("new").arg("rust-foo").arg("--bin").env("USER", "foo"),
                execs().with_status(0));
    let toml = paths::root().join("rust-foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"name = "rust-foo""#));
});

test!(explicit_name_not_stripped {
    assert_that(cargo_process("new").arg("foo").arg("--name").arg("rust-bar").env("USER", "foo"),
                execs().with_status(0));
    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"name = "rust-bar""#));
});

test!(finds_author_user {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo").env("USER", "foo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo"]"#));
});

test!(finds_author_user_escaped {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo").env("USER", "foo \"bar\"")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo \"bar\""]"#));
});

test!(finds_author_username {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env_remove("USER")
                                    .env("USERNAME", "foo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo"]"#));
});

test!(finds_author_priority {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env("USER", "bar2")
                                    .env("EMAIL", "baz2")
                                    .env("CARGO_NAME", "bar")
                                    .env("CARGO_EMAIL", "baz")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
});

test!(finds_author_email {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env("USER", "bar")
                                    .env("EMAIL", "baz")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
});

test!(finds_author_git {
    ::process("git").args(&["config", "--global", "user.name", "bar"])
                    .exec().unwrap();
    ::process("git").args(&["config", "--global", "user.email", "baz"])
                    .exec().unwrap();
    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
});

test!(finds_git_email{
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env("GIT_AUTHOR_NAME", "foo")
                                    .env("GIT_AUTHOR_EMAIL", "gitfoo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo <gitfoo>"]"#), contents);
});

test!(finds_git_author{
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env_remove("USER")
                                    .env("GIT_COMMITTER_NAME", "gitfoo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["gitfoo"]"#));
});

test!(author_prefers_cargo {
    ::process("git").args(&["config", "--global", "user.name", "foo"])
                    .exec().unwrap();
    ::process("git").args(&["config", "--global", "user.email", "bar"])
                    .exec().unwrap();
    let root = paths::root();
    fs::create_dir(&root.join(".cargo")).unwrap();
    File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
        [cargo-new]
        name = "new-foo"
        email = "new-bar"
        git = false
    "#).unwrap();

    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["new-foo <new-bar>"]"#));
    assert!(!root.join("foo/.gitignore").c_exists());
});

test!(git_prefers_command_line {
    let root = paths::root();
    let td = TempDir::new("cargo").unwrap();
    fs::create_dir(&root.join(".cargo")).unwrap();
    File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
        [cargo-new]
        vcs = "none"
        name = "foo"
        email = "bar"
    "#).unwrap();

    assert_that(cargo_process("new").arg("foo").arg("--vcs").arg("git")
                                    .cwd(td.path())
                                    .env("USER", "foo"),
                execs().with_status(0));
    assert!(td.path().join("foo/.gitignore").c_exists());
});

test!(subpackage_no_git {
    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let subpackage = paths::root().join("foo").join("components");
    fs::create_dir(&subpackage).unwrap();
    assert_that(cargo_process("new").arg("foo/components/subcomponent")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo/components/subcomponent/.git"),
                 is_not(existing_file()));
    assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
                 is_not(existing_file()));
});

test!(subpackage_git_with_vcs_arg {
    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let subpackage = paths::root().join("foo").join("components");
    fs::create_dir(&subpackage).unwrap();
    assert_that(cargo_process("new").arg("foo/components/subcomponent")
                                    .arg("--vcs").arg("git")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo/components/subcomponent/.git"),
                 existing_dir());
    assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
                 existing_file());
});

test!(unknown_flags {
    assert_that(cargo_process("new").arg("foo").arg("--flag"),
                execs().with_status(1)
                       .with_stderr("\
[ERROR] Unknown flag: '--flag'

Usage:
    cargo new [..]
    cargo new [..]
"));
});
<commit_msg>Auto merge of #2719 - semarie:test-git-vcs, r=alexcrichton<commit_after>use std::fs::{self, File};
use std::io::prelude::*;
use std::env;
use tempdir::TempDir;

use support::{execs, paths};
use support::paths::CargoPathExt;
use hamcrest::{assert_that, existing_file, existing_dir, is_not};

use cargo::util::ProcessBuilder;

fn setup() {
}

fn cargo_process(s: &str) -> ProcessBuilder {
    let mut p = ::cargo_process();
    p.arg(s);
    return p;
}

test!(simple_lib {
    assert_that(cargo_process("new").arg("foo").arg("--vcs").arg("none")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo"), existing_dir());
    assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
    assert_that(&paths::root().join("foo/src/lib.rs"), existing_file());
    assert_that(&paths::root().join("foo/.gitignore"), is_not(existing_file()));

    assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
                execs().with_status(0));
});

test!(simple_bin {
    assert_that(cargo_process("new").arg("foo").arg("--bin")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo"), existing_dir());
    assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
    assert_that(&paths::root().join("foo/src/main.rs"), existing_file());

    assert_that(cargo_process("build").cwd(&paths::root().join("foo")),
                execs().with_status(0));
    assert_that(&paths::root().join(&format!("foo/target/debug/foo{}",
                                             env::consts::EXE_SUFFIX)),
                existing_file());
});

test!(simple_git {
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo").cwd(td.path().clone())
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(td.path(), existing_dir());
    assert_that(&td.path().join("foo/Cargo.toml"), existing_file());
    assert_that(&td.path().join("foo/src/lib.rs"), existing_file());
    assert_that(&td.path().join("foo/.git"), existing_dir());
    assert_that(&td.path().join("foo/.gitignore"), existing_file());

    assert_that(cargo_process("build").cwd(&td.path().clone().join("foo")),
                execs().with_status(0));
});

test!(no_argument {
    assert_that(cargo_process("new"),
                execs().with_status(1)
                       .with_stderr("\
[ERROR] Invalid arguments.

Usage:
    cargo new [options] <path>
    cargo new -h | --help
"));
});

test!(existing {
    let dst = paths::root().join("foo");
    fs::create_dir(&dst).unwrap();
    assert_that(cargo_process("new").arg("foo"),
                execs().with_status(101)
                       .with_stderr(format!("[ERROR] destination `{}` already exists\n",
                                            dst.display())));
});

test!(invalid_characters {
    assert_that(cargo_process("new").arg("foo.rs"),
                execs().with_status(101)
                       .with_stderr("\
[ERROR] Invalid character `.` in crate name: `foo.rs`
use --name to override crate name"));
});

test!(reserved_name {
    assert_that(cargo_process("new").arg("test"),
                execs().with_status(101)
                       .with_stderr("\
[ERROR] The name `test` cannot be used as a crate name\n\
use --name to override crate name"));
});

test!(keyword_name {
    assert_that(cargo_process("new").arg("pub"),
                execs().with_status(101)
                       .with_stderr("\
[ERROR] The name `pub` cannot be used as a crate name\n\
use --name to override crate name"));
});

test!(rust_prefix_stripped {
    assert_that(cargo_process("new").arg("rust-foo").env("USER", "foo"),
                execs().with_status(0)
                       .with_stdout("note: package will be named `foo`; use --name to override"));
    let toml = paths::root().join("rust-foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"name = "foo""#));
});

test!(bin_disables_stripping {
    assert_that(cargo_process("new").arg("rust-foo").arg("--bin").env("USER", "foo"),
                execs().with_status(0));
    let toml = paths::root().join("rust-foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"name = "rust-foo""#));
});

test!(explicit_name_not_stripped {
    assert_that(cargo_process("new").arg("foo").arg("--name").arg("rust-bar").env("USER", "foo"),
                execs().with_status(0));
    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"name = "rust-bar""#));
});

test!(finds_author_user {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo").env("USER", "foo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo"]"#));
});

test!(finds_author_user_escaped {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo").env("USER", "foo \"bar\"")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo \"bar\""]"#));
});

test!(finds_author_username {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env_remove("USER")
                                    .env("USERNAME", "foo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo"]"#));
});

test!(finds_author_priority {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env("USER", "bar2")
                                    .env("EMAIL", "baz2")
                                    .env("CARGO_NAME", "bar")
                                    .env("CARGO_EMAIL", "baz")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
});

test!(finds_author_email {
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env("USER", "bar")
                                    .env("EMAIL", "baz")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
});

test!(finds_author_git {
    ::process("git").args(&["config", "--global", "user.name", "bar"])
                    .exec().unwrap();
    ::process("git").args(&["config", "--global", "user.email", "baz"])
                    .exec().unwrap();
    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["bar <baz>"]"#));
});

test!(finds_git_email{
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env("GIT_AUTHOR_NAME", "foo")
                                    .env("GIT_AUTHOR_EMAIL", "gitfoo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo <gitfoo>"]"#), contents);
});

test!(finds_git_author{
    // Use a temp dir to make sure we don't pick up .cargo/config somewhere in
    // the hierarchy
    let td = TempDir::new("cargo").unwrap();
    assert_that(cargo_process("new").arg("foo")
                                    .env_remove("USER")
                                    .env("GIT_COMMITTER_NAME", "gitfoo")
                                    .cwd(td.path().clone()),
                execs().with_status(0));

    let toml = td.path().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["gitfoo"]"#));
});

test!(author_prefers_cargo {
    ::process("git").args(&["config", "--global", "user.name", "foo"])
                    .exec().unwrap();
    ::process("git").args(&["config", "--global", "user.email", "bar"])
                    .exec().unwrap();
    let root = paths::root();
    fs::create_dir(&root.join(".cargo")).unwrap();
    File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
        [cargo-new]
        name = "new-foo"
        email = "new-bar"
        vcs = "none"
    "#).unwrap();

    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["new-foo <new-bar>"]"#));
    assert!(!root.join("foo/.gitignore").c_exists());
});

test!(git_prefers_command_line {
    let root = paths::root();
    let td = TempDir::new("cargo").unwrap();
    fs::create_dir(&root.join(".cargo")).unwrap();
    File::create(&root.join(".cargo/config")).unwrap().write_all(br#"
        [cargo-new]
        vcs = "none"
        name = "foo"
        email = "bar"
    "#).unwrap();

    assert_that(cargo_process("new").arg("foo").arg("--vcs").arg("git")
                                    .cwd(td.path())
                                    .env("USER", "foo"),
                execs().with_status(0));
    assert!(td.path().join("foo/.gitignore").c_exists());
});

test!(subpackage_no_git {
    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let subpackage = paths::root().join("foo").join("components");
    fs::create_dir(&subpackage).unwrap();
    assert_that(cargo_process("new").arg("foo/components/subcomponent")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo/components/subcomponent/.git"),
                 is_not(existing_file()));
    assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
                 is_not(existing_file()));
});

test!(subpackage_git_with_vcs_arg {
    assert_that(cargo_process("new").arg("foo").env("USER", "foo"),
                execs().with_status(0));

    let subpackage = paths::root().join("foo").join("components");
    fs::create_dir(&subpackage).unwrap();
    assert_that(cargo_process("new").arg("foo/components/subcomponent")
                                    .arg("--vcs").arg("git")
                                    .env("USER", "foo"),
                execs().with_status(0));

    assert_that(&paths::root().join("foo/components/subcomponent/.git"),
                 existing_dir());
    assert_that(&paths::root().join("foo/components/subcomponent/.gitignore"),
                 existing_file());
});

test!(unknown_flags {
    assert_that(cargo_process("new").arg("foo").arg("--flag"),
                execs().with_status(1)
                       .with_stderr("\
[ERROR] Unknown flag: '--flag'

Usage:
    cargo new [..]
    cargo new [..]
"));
});
<|endoftext|>