<commit_before>//! Public-key Authenticated encryption.

use std::io;
use std::convert::TryFrom;
use rand::{ Rand, Rng };
use seckey::Bytes;
use ::aead::{ AeadCipher, DecryptFail };
use ::kex::KeyExchange;

/// `SealedBox` trait.
///
/// ```
/// # extern crate rand;
/// # extern crate sarkara;
/// # fn main() {
/// # use rand::{ Rng, thread_rng, ChaChaRng };
/// # use sarkara::aead::{ Ascon, AeadCipher };
/// # use sarkara::kex::{ NewHope, KeyExchange };
/// # use sarkara::sealedbox::SealedBox;
/// #
/// // ...
/// # let mut rng = thread_rng();
/// # let mut data = vec![0; 1024];
/// # rng.fill_bytes(&mut data);
///
/// let (sk, pk) = NewHope::keygen::<ChaChaRng>();
///
/// let mut ciphertext = Ascon::seal::<NewHope, ChaChaRng>(&pk, &data);
/// # assert_eq!(
/// #     ciphertext.len(),
/// #     data.len() + Ascon::tag_length() + NewHope::rec_length()
/// # );
/// let plaintext = Ascon::open::<NewHope>(&sk, &ciphertext).unwrap();
/// assert_eq!(plaintext, data);
/// #
/// # ciphertext[0] ^= 1;
/// # assert!(Ascon::open::<NewHope>(&sk, &ciphertext).is_err());
/// # ciphertext[0] ^= 1;
/// # let pos = ciphertext.len();
/// # ciphertext[pos - 1] ^= 1;
/// # assert!(Ascon::open::<NewHope>(&sk, &ciphertext).is_err());
/// # }
/// ```
pub trait SealedBox {
    /// Seal SecretBox.
    fn seal<K, R>(pka: &K::PublicKey, data: &[u8])
        -> Vec<u8>
        where
            K: KeyExchange,
            K::Reconciliation: Into<Vec<u8>>,
            R: Rand + Rng;

    /// Open SecretBox.
    fn open<'a, K>(ska: &K::PrivateKey, data: &'a [u8])
        -> Result<Vec<u8>, DecryptFail>
        where
            K: KeyExchange,
            K::Reconciliation: TryFrom<&'a [u8], Err=io::Error>;
}

impl<T> SealedBox for T where T: AeadCipher {
    fn seal<K, R>(pka: &K::PublicKey, data: &[u8])
        -> Vec<u8>
        where
            K: KeyExchange,
            K::Reconciliation: Into<Vec<u8>>,
            R: Rand + Rng
    {
        let mut key = Bytes::from(vec![0; Self::key_length() + Self::nonce_length()]);
        let mut rec = K::exchange::<R>(&mut key, pka).into();
        let (key, nonce) = key.split_at(Self::key_length());

        let mut output = Self::new(key)
            .with_aad(&rec)
            .encrypt(nonce, data);
        output.append(&mut rec);
        output
    }

    fn open<'a, K>(ska: &K::PrivateKey, data: &'a [u8])
        -> Result<Vec<u8>, DecryptFail>
        where
            K: KeyExchange,
            K::Reconciliation: TryFrom<&'a [u8], Err=io::Error>
    {
        if data.len() < K::rec_length() { Err(DecryptFail::LengthError)? };

        let mut key = Bytes::from(vec![0; Self::key_length() + Self::nonce_length()]);
        let (data, rec) = data.split_at(data.len() - K::rec_length());
        K::exchange_from(&mut key, ska, &K::Reconciliation::try_from(rec)?);
        let (key, nonce) = key.split_at(Self::key_length());

        Self::new(key)
            .with_aad(rec)
            .decrypt(nonce, data)
    }
}
<commit_msg>refactor: sealedbox::open lifetime<commit_after>//! Public-key Authenticated encryption.

use std::io;
use std::convert::TryFrom;
use rand::{ Rand, Rng };
use seckey::Bytes;
use ::aead::{ AeadCipher, DecryptFail };
use ::kex::KeyExchange;

/// `SealedBox` trait.
///
/// ```
/// # extern crate rand;
/// # extern crate sarkara;
/// # fn main() {
/// # use rand::{ Rng, thread_rng, ChaChaRng };
/// # use sarkara::aead::{ Ascon, AeadCipher };
/// # use sarkara::kex::{ NewHope, KeyExchange };
/// # use sarkara::sealedbox::SealedBox;
/// #
/// // ...
/// # let mut rng = thread_rng();
/// # let mut data = vec![0; 1024];
/// # rng.fill_bytes(&mut data);
///
/// let (sk, pk) = NewHope::keygen::<ChaChaRng>();
///
/// let mut ciphertext = Ascon::seal::<NewHope, ChaChaRng>(&pk, &data);
/// # assert_eq!(
/// #     ciphertext.len(),
/// #     data.len() + Ascon::tag_length() + NewHope::rec_length()
/// # );
/// let plaintext = Ascon::open::<NewHope>(&sk, &ciphertext).unwrap();
/// assert_eq!(plaintext, data);
/// #
/// # ciphertext[0] ^= 1;
/// # assert!(Ascon::open::<NewHope>(&sk, &ciphertext).is_err());
/// # ciphertext[0] ^= 1;
/// # let pos = ciphertext.len();
/// # ciphertext[pos - 1] ^= 1;
/// # assert!(Ascon::open::<NewHope>(&sk, &ciphertext).is_err());
/// # }
/// ```
pub trait SealedBox {
    /// Seal SecretBox.
    fn seal<K, R>(pka: &K::PublicKey, data: &[u8])
        -> Vec<u8>
        where
            K: KeyExchange,
            K::Reconciliation: Into<Vec<u8>>,
            R: Rand + Rng;

    /// Open SecretBox.
    fn open<K>(ska: &K::PrivateKey, data: &[u8])
        -> Result<Vec<u8>, DecryptFail>
        where
            K: KeyExchange,
            for<'a> K::Reconciliation: TryFrom<&'a [u8], Err=io::Error>;
}

impl<T> SealedBox for T where T: AeadCipher {
    fn seal<K, R>(pka: &K::PublicKey, data: &[u8])
        -> Vec<u8>
        where
            K: KeyExchange,
            K::Reconciliation: Into<Vec<u8>>,
            R: Rand + Rng
    {
        let mut key = Bytes::from(vec![0; Self::key_length() + Self::nonce_length()]);
        let mut rec = K::exchange::<R>(&mut key, pka).into();
        let (key, nonce) = key.split_at(Self::key_length());

        let mut output = Self::new(key)
            .with_aad(&rec)
            .encrypt(nonce, data);
        output.append(&mut rec);
        output
    }

    fn open<K>(ska: &K::PrivateKey, data: &[u8])
        -> Result<Vec<u8>, DecryptFail>
        where
            K: KeyExchange,
            for<'a> K::Reconciliation: TryFrom<&'a [u8], Err=io::Error>
    {
        if data.len() < K::rec_length() { Err(DecryptFail::LengthError)? };

        let mut key = Bytes::from(vec![0; Self::key_length() + Self::nonce_length()]);
        let (data, rec) = data.split_at(data.len() - K::rec_length());
        K::exchange_from(&mut key, ska, &K::Reconciliation::try_from(rec)?);
        let (key, nonce) = key.split_at(Self::key_length());

        Self::new(key)
            .with_aad(rec)
            .decrypt(nonce, data)
    }
}
<|endoftext|>


<commit_before>// This version is based on the Go version on Rosettacode

#[derive(PartialEq, Debug, Copy, Clone)]
enum Month {
    May,
    June,
    July,
    August,
}

#[derive(PartialEq, Debug, Copy, Clone)]
struct Birthday {
    month: Month,
    day: u8,
}

impl Birthday {
    fn month_unique_in(&self, birthdays: &[Birthday]) -> bool {
        birthdays
            .iter()
            .filter(|birthday| birthday.month == self.month)
            .count()
            == 1
    }

    fn day_unique_in(&self, birthdays: &[Birthday]) -> bool {
        birthdays
            .iter()
            .filter(|birthday| birthday.day == self.day)
            .count()
            == 1
    }

    fn month_with_unique_day_in(&self, birthdays: &[Birthday]) -> bool {
        birthdays
            .iter()
            .any(|birthday| self.month == birthday.month && birthday.day_unique_in(birthdays))
    }
}

fn solution() -> Option<Birthday> {
    let choices: Vec<Birthday> = vec![
        Birthday {
            month: Month::May,
            day: 15,
        },
        Birthday {
            month: Month::May,
            day: 16,
        },
        Birthday {
            month: Month::May,
            day: 19,
        },
        Birthday {
            month: Month::June,
            day: 17,
        },
        Birthday {
            month: Month::June,
            day: 18,
        },
        Birthday {
            month: Month::July,
            day: 14,
        },
        Birthday {
            month: Month::July,
            day: 16,
        },
        Birthday {
            month: Month::August,
            day: 14,
        },
        Birthday {
            month: Month::August,
            day: 15,
        },
        Birthday {
            month: Month::August,
            day: 17,
        },
    ];

    // Albert knows the month but doesn't know the day.
    // So the month can't be unique within the choices.
    let filtered = choices
        .clone()
        .into_iter()
        .filter(|birthday| !(&birthday.month_unique_in(&choices)))
        .collect::<Vec<Birthday>>();

    // Albert also knows that Bernard doesn't know the answer.
    // So the month can't have a unique day.
    let filtered2 = filtered
        .clone()
        .into_iter()
        .filter(|birthday| !(birthday.month_with_unique_day_in(&filtered)))
        .collect::<Vec<Birthday>>();

    // Bernard now knows the answer.
    // So the day must be unique within the remaining choices.
    let filtered3 = filtered2
        .clone()
        .into_iter()
        .filter(|birthday| birthday.day_unique_in(&filtered2))
        .collect::<Vec<Birthday>>();

    // Albert now knows the answer too.
    // So the month must be unique within the remaining choices.
    let filtered4 = filtered3
        .clone()
        .into_iter()
        .filter(|birthday| birthday.month_unique_in(&filtered3))
        .collect::<Vec<Birthday>>();

    if filtered4.len() == 1 {
        Some(filtered4[0])
    } else {
        None
    }
}

fn main() {
    match solution() {
        Some(solution) => println!("Cheryl's birthday is {:?}", solution),
        None => panic!("Didn't work!"),
    }
}

#[test]
fn test_solution_works() {
    let solution = solution().unwrap();

    let real_solution = Birthday {
        month: Month::July,
        day: 16,
    };

    assert_eq!(solution, real_solution);
}
<commit_msg>From iter/filter to retain<commit_after>// This version is based on the Go version on Rosettacode

#[derive(PartialEq, Debug, Copy, Clone)]
enum Month {
    May,
    June,
    July,
    August,
}

#[derive(PartialEq, Debug, Copy, Clone)]
struct Birthday {
    month: Month,
    day: u8,
}

impl Birthday {
    fn month_unique_in(&self, birthdays: &[Birthday]) -> bool {
        birthdays
            .iter()
            .filter(|birthday| birthday.month == self.month)
            .count()
            == 1
    }

    fn day_unique_in(&self, birthdays: &[Birthday]) -> bool {
        birthdays
            .iter()
            .filter(|birthday| birthday.day == self.day)
            .count()
            == 1
    }

    fn month_with_unique_day_in(&self, birthdays: &[Birthday]) -> bool {
        birthdays
            .iter()
            .any(|birthday| self.month == birthday.month && birthday.day_unique_in(birthdays))
    }
}

fn solution() -> Option<Birthday> {
    let mut choices: Vec<Birthday> = vec![
        Birthday {
            month: Month::May,
            day: 15,
        },
        Birthday {
            month: Month::May,
            day: 16,
        },
        Birthday {
            month: Month::May,
            day: 19,
        },
        Birthday {
            month: Month::June,
            day: 17,
        },
        Birthday {
            month: Month::June,
            day: 18,
        },
        Birthday {
            month: Month::July,
            day: 14,
        },
        Birthday {
            month: Month::July,
            day: 16,
        },
        Birthday {
            month: Month::August,
            day: 14,
        },
        Birthday {
            month: Month::August,
            day: 15,
        },
        Birthday {
            month: Month::August,
            day: 17,
        },
    ];

    // Albert knows the month but doesn't know the day.
    // So the month can't be unique within the choices.
    let choices_copy = choices.clone();
    choices.retain(|birthday| !(&birthday.month_unique_in(&choices_copy)));

    // Albert also knows that Bernard doesn't know the answer.
    // So the month can't have a unique day.
    let choices_copy = choices.clone();
    choices.retain(|birthday| !(birthday.month_with_unique_day_in(&choices_copy)));

    // Bernard now knows the answer.
    // So the day must be unique within the remaining choices.
    let choices_copy = choices.clone();
    choices.retain(|birthday| birthday.day_unique_in(&choices_copy));

    // Albert now knows the answer too.
    // So the month must be unique within the remaining choices.
    let choices_copy = choices.clone();
    choices.retain(|birthday| birthday.month_unique_in(&choices_copy));

    if choices.len() == 1 {
        Some(choices[0])
    } else {
        None
    }
}

fn main() {
    match solution() {
        Some(solution) => println!("Cheryl's birthday is {:?}", solution),
        None => panic!("Didn't work!"),
    }
}

#[test]
fn test_solution_works() {
    let solution = solution().unwrap();

    let real_solution = Birthday {
        month: Month::July,
        day: 16,
    };

    assert_eq!(solution, real_solution);
}
<|endoftext|>


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

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4
};
use cgmath::vector::{
  Vec3,
  Vec2
};
use cgmath::projection;
use cgmath::angle;

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

pub mod misc {
  use cgmath::matrix::Mat4;

  pub fn print_mat4(name: &str, mat: Mat4<f32>) {
    println!("{}:", name);
    for i in range(0u, 4) {
      for j in range(0u, 4) {
        print!("{} ", *mat.cr(i, j));
      }
      println("");
    }
    println("");
  }
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), 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(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

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: GLint = 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(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

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)
}

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

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

struct Win {
  vertex_shader: GLuint,
  fragment_shader: GLuint,
  program: GLuint,
  vertex_array_obj: GLuint,
  vertex_buffer_obj: GLuint,
  matrix_id: GLint,
  projection_matrix: Mat4<f32>,
  window: glfw::Window
}

fn get_projection_matrix() -> Mat4<f32> {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  projection::perspective(
    fov, ratio, display_range_min, display_range_max
  )
}

impl Win {
  fn new() -> Win {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    let mut win = Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      projection_matrix: get_projection_matrix(),
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };

    win.window.make_context_current();
    win.window.set_cursor_pos_callback(~CursorPosContext);
    win.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    win.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    win.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    win.program = link_program(win.vertex_shader, win.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut win.vertex_array_obj);
      gl::BindVertexArray(win.vertex_array_obj);

      // Create a Vertex Buffer Object and copy the vertex data to it
      gl::GenBuffers(1, &mut win.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, win.vertex_buffer_obj);
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(win.program);
      gl::BindFragDataLocation(
        win.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        win.program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);
      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      win.matrix_id = gl::GetUniformLocation(
        win.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }

    win
  }

  fn cleanup(&self) {
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let mut mvp_matrix = self.projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);

      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform for each model
      // you render, since the model_view_proj_matrix will be
      // different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);
    self.window.swap_buffers();
  }

  fn is_running(&self) -> bool {
    return !self.window.should_close()
  }

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    let distance = 1.0;
    if action != glfw::Press {
      return;
    }
    match key {
      glfw::KeyEscape | glfw::KeyQ
                     => window.set_should_close(true),
      glfw::KeySpace => println!("space"),
      glfw::KeyUp    => unsafe { CAMERA_POS.y -= distance },
      glfw::KeyDown  => unsafe { CAMERA_POS.y += distance },
      glfw::KeyRight => unsafe { CAMERA_POS.x -= distance },
      glfw::KeyLeft  => unsafe { CAMERA_POS.x += distance },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Win::init_open_gl(&mut self)<commit_after>// See LICENSE file for copyright and license details.

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4
};
use cgmath::vector::{
  Vec3,
  Vec2
};
use cgmath::projection;
use cgmath::angle;

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

pub mod misc {
  use cgmath::matrix::Mat4;

  pub fn print_mat4(name: &str, mat: Mat4<f32>) {
    println!("{}:", name);
    for i in range(0u, 4) {
      for j in range(0u, 4) {
        print!("{} ", *mat.cr(i, j));
      }
      println("");
    }
    println("");
  }
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), 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(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

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: GLint = 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(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

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)
}

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

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

struct Win {
  vertex_shader: GLuint,
  fragment_shader: GLuint,
  program: GLuint,
  vertex_array_obj: GLuint,
  vertex_buffer_obj: GLuint,
  matrix_id: GLint,
  projection_matrix: Mat4<f32>,
  window: glfw::Window
}

fn get_projection_matrix() -> Mat4<f32> {
  let fov = angle::deg(45.0f32);
  let ratio = 4.0 / 3.0;
  let display_range_min = 0.1;
  let display_range_max = 100.0;
  projection::perspective(
    fov, ratio, display_range_min, display_range_max
  )
}

impl Win {
  fn new() -> Win {
    let mut win = Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      projection_matrix: get_projection_matrix(),
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };
    win.init_opengl();
    win
  }

  fn init_opengl(&mut self) {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    self.window.make_context_current();
    self.window.set_cursor_pos_callback(~CursorPosContext);
    self.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    self.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    self.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    self.program = link_program(self.vertex_shader, self.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut self.vertex_array_obj);
      gl::BindVertexArray(self.vertex_array_obj);

      // Create a Vertex Buffer Object
      gl::GenBuffers(1, &mut self.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);

      // Copy vertex data to VBO
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(self.program);
      gl::BindFragDataLocation(
        self.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        self.program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);

      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      self.matrix_id = gl::GetUniformLocation(
        self.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }
  }

  fn cleanup(&self) {
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let mut mvp_matrix = self.projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);

      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform for each model
      // you render, since the model_view_proj_matrix will be
      // different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);
    self.window.swap_buffers();
  }

  fn is_running(&self) -> bool {
    return !self.window.should_close()
  }

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    let distance = 1.0;
    if action != glfw::Press {
      return;
    }
    match key {
      glfw::KeyEscape | glfw::KeyQ
                     => window.set_should_close(true),
      glfw::KeySpace => println!("space"),
      glfw::KeyUp    => unsafe { CAMERA_POS.y -= distance },
      glfw::KeyDown  => unsafe { CAMERA_POS.y += distance },
      glfw::KeyRight => unsafe { CAMERA_POS.x -= distance },
      glfw::KeyLeft  => unsafe { CAMERA_POS.x += distance },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

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


<commit_before>//! lapin-futures
//!
//! This library offers a futures based API over the lapin-async library.
//! It leverages the tokio-io and futures library, so you can use it
//! with tokio-core, futures-cpupool or any other reactor.
//!
//! The library is designed so it does not own the socket, so you
//! can use any TCP, TLS or unix socket based stream.
//!
//! Calls to the underlying stream are guarded by a mutex, so you could
//! use one connection from multiple threads.
//!
//! There's an [example available](https://github.com/Geal/lapin/blob/master/futures/examples/client.rs)
//! using tokio-core.
//!
//! ## Publishing a message
//!
//! ```rust
//! #[macro_use] extern crate log;
//! extern crate lapin_futures as lapin;
//! extern crate amq_protocol;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use amq_protocol::types::FieldTable;
//! use futures::future::Future;
//! use futures::Stream;
//! use tokio_core::reactor::Core;
//! use tokio_core::net::TcpStream;
//! use lapin::client::ConnectionOptions;
//! use lapin::channel::{BasicPublishOptions,BasicProperties,QueueDeclareOptions};
//!
//! fn main() {
//!
//!   // create the reactor
//!   let mut core = Core::new().unwrap();
//!   let handle = core.handle();
//!   let addr = "127.0.0.1:5672".parse().unwrap();
//!
//!   core.run(
//!
//!     TcpStream::connect(&addr, &handle).and_then(|stream| {
//!
//!       // connect() returns a future of an AMQP Client
//!       // that resolves once the handshake is done
//!       lapin::client::Client::connect(stream, &ConnectionOptions::default())
//!     }).and_then(|client| {
//!
//!       // create_channel returns a future that is resolved
//!       // once the channel is successfully created
//!       client.create_channel()
//!     }).and_then(|channel| {
//!       let id = channel.id;
//!       info!("created channel with id: {}", id);
//!
//!       // we using a "move" closure to reuse the channel
//!       // once the queue is declared. We could also clone
//!       // the channel
//!       channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
//!         info!("channel {} declared queue {}", id, "hello");
//!
//!         channel.basic_publish("hello", b"hello from tokio", &BasicPublishOptions::default(), BasicProperties::default())
//!       })
//!     })
//!   ).unwrap();
//! }
//! ```
//!
//! ## Creating a consumer
//!
//! ```rust,ignore
//! #[macro_use] extern crate log;
//! extern crate lapin_futures as lapin;
//! extern crate amq_protocol;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use amq_protocol::types::FieldTable;
//! use futures::future::Future;
//! use futures::Stream;
//! use tokio_core::reactor::Core;
//! use tokio_core::net::TcpStream;
//! use lapin::client::ConnectionOptions;
//! use lapin::channel::{BasicConsumeOptions,BasicPublishOptions,QueueDeclareOptions};
//!
//! fn main() {
//!
//!   // create the reactor
//!   let mut core = Core::new().unwrap();
//!   let handle = core.handle();
//!   let addr = "127.0.0.1:5672".parse().unwrap();
//!
//!   core.run(
//!
//!     TcpStream::connect(&addr, &handle).and_then(|stream| {
//!
//!       // connect() returns a future of an AMQP Client
//!       // that resolves once the handshake is done
//!       lapin::client::Client::connect(stream, &ConnectionOptions::default())
//!     }).and_then(|client| {
//!
//!       // create_channel returns a future that is resolved
//!       // once the channel is successfully created
//!       client.create_channel()
//!     }).and_then(|channel| {
//!       let id = channel.id;
//!       info!("created channel with id: {}", id);
//!
//!       let ch = channel.clone();
//!       channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
//!         info!("channel {} declared queue {}", id, "hello");
//!
//!         // basic_consume returns a future of a message
//!         // stream. Any time a message arrives for this consumer,
//!         // the for_each method would be called
//!         channel.basic_consume("hello", "my_consumer", &BasicConsumeOptions::default())
//!       }).and_then(|stream| {
//!         info!("got consumer stream");
//!
//!         stream.for_each(move |message| {
//!           debug!("got message: {:?}", message);
//!           info!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
//!           ch.basic_ack(message.delivery_tag);
//!           Ok(())
//!         })
//!       })
//!     })
//!   ).unwrap();
//! }
//! ```
//!

#[macro_use] extern crate log;
#[macro_use] extern crate futures;
extern crate amq_protocol;
extern crate nom;
extern crate bytes;
extern crate tokio_io;
extern crate tokio_timer;
extern crate lapin_async;
extern crate cookie_factory;

pub mod client;
pub mod transport;
pub mod channel;
pub mod consumer;
<commit_msg>futures: we do not use macros from the futures crate<commit_after>//! lapin-futures
//!
//! This library offers a futures based API over the lapin-async library.
//! It leverages the tokio-io and futures library, so you can use it
//! with tokio-core, futures-cpupool or any other reactor.
//!
//! The library is designed so it does not own the socket, so you
//! can use any TCP, TLS or unix socket based stream.
//!
//! Calls to the underlying stream are guarded by a mutex, so you could
//! use one connection from multiple threads.
//!
//! There's an [example available](https://github.com/Geal/lapin/blob/master/futures/examples/client.rs)
//! using tokio-core.
//!
//! ## Publishing a message
//!
//! ```rust
//! #[macro_use] extern crate log;
//! extern crate lapin_futures as lapin;
//! extern crate amq_protocol;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use amq_protocol::types::FieldTable;
//! use futures::future::Future;
//! use futures::Stream;
//! use tokio_core::reactor::Core;
//! use tokio_core::net::TcpStream;
//! use lapin::client::ConnectionOptions;
//! use lapin::channel::{BasicPublishOptions,BasicProperties,QueueDeclareOptions};
//!
//! fn main() {
//!
//!   // create the reactor
//!   let mut core = Core::new().unwrap();
//!   let handle = core.handle();
//!   let addr = "127.0.0.1:5672".parse().unwrap();
//!
//!   core.run(
//!
//!     TcpStream::connect(&addr, &handle).and_then(|stream| {
//!
//!       // connect() returns a future of an AMQP Client
//!       // that resolves once the handshake is done
//!       lapin::client::Client::connect(stream, &ConnectionOptions::default())
//!     }).and_then(|client| {
//!
//!       // create_channel returns a future that is resolved
//!       // once the channel is successfully created
//!       client.create_channel()
//!     }).and_then(|channel| {
//!       let id = channel.id;
//!       info!("created channel with id: {}", id);
//!
//!       // we using a "move" closure to reuse the channel
//!       // once the queue is declared. We could also clone
//!       // the channel
//!       channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
//!         info!("channel {} declared queue {}", id, "hello");
//!
//!         channel.basic_publish("hello", b"hello from tokio", &BasicPublishOptions::default(), BasicProperties::default())
//!       })
//!     })
//!   ).unwrap();
//! }
//! ```
//!
//! ## Creating a consumer
//!
//! ```rust,ignore
//! #[macro_use] extern crate log;
//! extern crate lapin_futures as lapin;
//! extern crate amq_protocol;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use amq_protocol::types::FieldTable;
//! use futures::future::Future;
//! use futures::Stream;
//! use tokio_core::reactor::Core;
//! use tokio_core::net::TcpStream;
//! use lapin::client::ConnectionOptions;
//! use lapin::channel::{BasicConsumeOptions,BasicPublishOptions,QueueDeclareOptions};
//!
//! fn main() {
//!
//!   // create the reactor
//!   let mut core = Core::new().unwrap();
//!   let handle = core.handle();
//!   let addr = "127.0.0.1:5672".parse().unwrap();
//!
//!   core.run(
//!
//!     TcpStream::connect(&addr, &handle).and_then(|stream| {
//!
//!       // connect() returns a future of an AMQP Client
//!       // that resolves once the handshake is done
//!       lapin::client::Client::connect(stream, &ConnectionOptions::default())
//!     }).and_then(|client| {
//!
//!       // create_channel returns a future that is resolved
//!       // once the channel is successfully created
//!       client.create_channel()
//!     }).and_then(|channel| {
//!       let id = channel.id;
//!       info!("created channel with id: {}", id);
//!
//!       let ch = channel.clone();
//!       channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
//!         info!("channel {} declared queue {}", id, "hello");
//!
//!         // basic_consume returns a future of a message
//!         // stream. Any time a message arrives for this consumer,
//!         // the for_each method would be called
//!         channel.basic_consume("hello", "my_consumer", &BasicConsumeOptions::default())
//!       }).and_then(|stream| {
//!         info!("got consumer stream");
//!
//!         stream.for_each(move |message| {
//!           debug!("got message: {:?}", message);
//!           info!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
//!           ch.basic_ack(message.delivery_tag);
//!           Ok(())
//!         })
//!       })
//!     })
//!   ).unwrap();
//! }
//! ```
//!

extern crate amq_protocol;
extern crate cookie_factory;
extern crate bytes;
extern crate futures;
extern crate lapin_async;
#[macro_use] extern crate log;
extern crate nom;
extern crate tokio_io;
extern crate tokio_timer;

pub mod client;
pub mod transport;
pub mod channel;
pub mod consumer;
<|endoftext|>


<commit_before>//! Types for the [`m.ignored_user_list`] event.
//!
//! [`m.ignored_user_list`]: https://spec.matrix.org/v1.4/client-server-api/#mignored_user_list

use std::collections::BTreeMap;

use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};

use crate::OwnedUserId;

/// The content of an `m.ignored_user_list` event.
///
/// A list of users to ignore.
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.ignored_user_list", kind = GlobalAccountData)]
pub struct IgnoredUserListEventContent {
    /// A map of users to ignore.
    ///
    /// As [`IgnoredUser`] is currently empty, only the user IDs are useful and
    /// can be accessed with the `.keys()` and `into_keys()` iterators.
    pub ignored_users: BTreeMap<OwnedUserId, IgnoredUser>,
}

impl IgnoredUserListEventContent {
    /// Creates a new `IgnoredUserListEventContent` from the given map of ignored user.
    pub fn new(ignored_users: BTreeMap<OwnedUserId, IgnoredUser>) -> Self {
        Self { ignored_users }
    }

    /// Creates a new `IgnoredUserListEventContent` from the given list of users.
    pub fn users(ignored_users: impl IntoIterator<Item = OwnedUserId>) -> Self {
        Self::new(ignored_users.into_iter().map(|id| (id, IgnoredUser {})).collect())
    }
}

/// Details about an ignored user.
///
/// This is currently empty.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct IgnoredUser {}

#[cfg(test)]
mod tests {
    use assert_matches::assert_matches;
    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::IgnoredUserListEventContent;
    use crate::{
        events::{AnyGlobalAccountDataEvent, GlobalAccountDataEvent},
        user_id,
    };

    #[test]
    fn serialization() {
        let ignored_user_list_event = GlobalAccountDataEvent {
            content: IgnoredUserListEventContent::users(vec![
                user_id!("@carl:example.com").to_owned()
            ]),
        };

        let json = json!({
            "content": {
                "ignored_users": {
                    "@carl:example.com": {}
                }
            },
            "type": "m.ignored_user_list"
        });

        assert_eq!(to_json_value(ignored_user_list_event).unwrap(), json);
    }

    #[test]
    fn deserialization() {
        let json = json!({
            "content": {
                "ignored_users": {
                    "@carl:example.com": {}
                }
            },
            "type": "m.ignored_user_list"
        });

        let ev = assert_matches!(
            from_json_value::<AnyGlobalAccountDataEvent>(json),
            Ok(AnyGlobalAccountDataEvent::IgnoredUserList(ev)) => ev
        );
        assert_eq!(
            ev.content.ignored_users.keys().collect::<Vec<_>>(),
            vec![user_id!("@carl:example.com")]
        );
    }
}
<commit_msg>events: Add IgnoredUser::new<commit_after>//! Types for the [`m.ignored_user_list`] event.
//!
//! [`m.ignored_user_list`]: https://spec.matrix.org/v1.4/client-server-api/#mignored_user_list

use std::collections::BTreeMap;

use ruma_macros::EventContent;
use serde::{Deserialize, Serialize};

use crate::OwnedUserId;

/// The content of an `m.ignored_user_list` event.
///
/// A list of users to ignore.
#[derive(Clone, Debug, Default, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.ignored_user_list", kind = GlobalAccountData)]
pub struct IgnoredUserListEventContent {
    /// A map of users to ignore.
    ///
    /// As [`IgnoredUser`] is currently empty, only the user IDs are useful and
    /// can be accessed with the `.keys()` and `into_keys()` iterators.
    pub ignored_users: BTreeMap<OwnedUserId, IgnoredUser>,
}

impl IgnoredUserListEventContent {
    /// Creates a new `IgnoredUserListEventContent` from the given map of ignored user.
    pub fn new(ignored_users: BTreeMap<OwnedUserId, IgnoredUser>) -> Self {
        Self { ignored_users }
    }

    /// Creates a new `IgnoredUserListEventContent` from the given list of users.
    pub fn users(ignored_users: impl IntoIterator<Item = OwnedUserId>) -> Self {
        Self::new(ignored_users.into_iter().map(|id| (id, IgnoredUser {})).collect())
    }
}

/// Details about an ignored user.
///
/// This is currently empty.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct IgnoredUser {}

impl IgnoredUser {
    /// Creates an empty `IgnoredUser`.
    pub fn new() -> Self {
        Self::default()
    }
}

#[cfg(test)]
mod tests {
    use assert_matches::assert_matches;
    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::IgnoredUserListEventContent;
    use crate::{
        events::{AnyGlobalAccountDataEvent, GlobalAccountDataEvent},
        user_id,
    };

    #[test]
    fn serialization() {
        let ignored_user_list_event = GlobalAccountDataEvent {
            content: IgnoredUserListEventContent::users(vec![
                user_id!("@carl:example.com").to_owned()
            ]),
        };

        let json = json!({
            "content": {
                "ignored_users": {
                    "@carl:example.com": {}
                }
            },
            "type": "m.ignored_user_list"
        });

        assert_eq!(to_json_value(ignored_user_list_event).unwrap(), json);
    }

    #[test]
    fn deserialization() {
        let json = json!({
            "content": {
                "ignored_users": {
                    "@carl:example.com": {}
                }
            },
            "type": "m.ignored_user_list"
        });

        let ev = assert_matches!(
            from_json_value::<AnyGlobalAccountDataEvent>(json),
            Ok(AnyGlobalAccountDataEvent::IgnoredUserList(ev)) => ev
        );
        assert_eq!(
            ev.content.ignored_users.keys().collect::<Vec<_>>(),
            vec![user_id!("@carl:example.com")]
        );
    }
}
<|endoftext|>


<commit_before>/// Saturating math operations
pub trait Saturating {
    /// Saturating addition operator.
    /// Returns a+b, saturating at the numeric bounds instead of overflowing.
    fn saturating_add(self, v: Self) -> Self;

    /// Saturating subtraction operator.
    /// Returns a-b, saturating at the numeric bounds instead of overflowing.
    fn saturating_sub(self, v: Self) -> Self;
}

macro_rules! saturating_impl {
    ($trait_name:ident for $($t:ty)*) => {$(
        impl $trait_name for $t {
            fn saturating_add(self, v: Self) -> Self {
                Self::saturating_add(self, v)
            }

            fn saturating_sub(self, v: Self) -> Self {
                Self::saturating_sub(self, v)
            }
        }
    )*}
}

saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
<commit_msg>traits: inline Saturating methods<commit_after>/// Saturating math operations
pub trait Saturating {
    /// Saturating addition operator.
    /// Returns a+b, saturating at the numeric bounds instead of overflowing.
    fn saturating_add(self, v: Self) -> Self;

    /// Saturating subtraction operator.
    /// Returns a-b, saturating at the numeric bounds instead of overflowing.
    fn saturating_sub(self, v: Self) -> Self;
}

macro_rules! saturating_impl {
    ($trait_name:ident for $($t:ty)*) => {$(
        impl $trait_name for $t {
            #[inline]
            fn saturating_add(self, v: Self) -> Self {
                Self::saturating_add(self, v)
            }

            #[inline]
            fn saturating_sub(self, v: Self) -> Self {
                Self::saturating_sub(self, v)
            }
        }
    )*}
}

saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
<|endoftext|>


<commit_before>//! Checks for continue statements in loops that are redundant.
//!
//! For example, the lint would catch
//!
//! ```
//! while condition() {
//!     update_condition();
//!     if x {
//!         // ...
//!     } else {
//!         continue;
//!     }
//!     println!("Hello, world");
//! }
//! ```
//!
//! And suggest something like this:
//!
//! ```
//! while condition() {
//!     update_condition();
//!     if x {
//!         // ...
//!         println!("Hello, world");
//!     }
//! }
//! ```
//!
//! This lint is **warn** by default.
use rustc::lint::*;
use syntax::ast;
use syntax::codemap::{original_sp,DUMMY_SP};
use std::borrow::Cow;

use utils::{in_macro, span_help_and_lint, snippet_block, snippet, trim_multiline};

/// **What it does:** The lint checks for `if`-statements appearing in loops
/// that contain a `continue` statement in either their main blocks or their
/// `else`-blocks, when omitting the `else`-block possibly with some
/// rearrangement of code can make the code easier to understand.
///
/// **Why is this bad?** Having explicit `else` blocks for `if` statements
/// containing `continue` in their THEN branch adds unnecessary branching and
/// nesting to the code. Having an else block containing just `continue` can
/// also be better written by grouping the statements following the whole `if`
/// statement within the THEN block and omitting the else block completely.
///
/// **Known problems:** None
///
/// **Example:**
/// ```rust
/// while condition() {
///     update_condition();
///     if x {
///         // ...
///     } else {
///         continue;
///     }
///     println!("Hello, world");
/// }
/// ```
///
/// Could be rewritten as
///
/// ```rust
/// while condition() {
///     update_condition();
///     if x {
///         // ...
///         println!("Hello, world");
///     }
/// }
/// ```
///
/// As another example, the following code
///
/// ```rust
/// loop {
///     if waiting() {
///         continue;
///     } else {
///         // Do something useful
///     }
/// }
/// ```
/// Could be rewritten as
///
/// ```rust
/// loop {
///     if waiting() {
///         continue;
///     }
///     // Do something useful
/// }
/// ```
declare_lint! {
    pub NEEDLESS_CONTINUE,
    Warn,
    "`continue` statements that can be replaced by a rearrangement of code"
}

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

impl LintPass for NeedlessContinue {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEEDLESS_CONTINUE)
    }
}

impl EarlyLintPass for NeedlessContinue {
    fn check_expr(&mut self, ctx: &EarlyContext, expr: &ast::Expr) {
        if !in_macro(expr.span) {
            check_and_warn(ctx, expr);
        }
    }
}

/* This lint has to mainly deal with two cases of needless continue statements.
 *
 * Case 1 [Continue inside else block]:
 *
 *     loop {
 *         // region A
 *         if cond {
 *             // region B
 *         } else {
 *             continue;
 *         }
 *         // region C
 *     }
 *
 * This code can better be written as follows:
 *
 *     loop {
 *         // region A
 *         if cond {
 *             // region B
 *             // region C
 *         }
 *     }
 *
 * Case 2 [Continue inside then block]:
 *
 *     loop {
 *       // region A
 *       if cond {
 *           continue;
 *           // potentially more code here.
 *       } else {
 *           // region B
 *       }
 *       // region C
 *     }
 *
 *
 * This snippet can be refactored to:
 *
 *     loop {
 *       // region A
 *       if !cond {
 *           // region B
 *           // region C
 *       }
 *     }
 */

/// Given an expression, returns true if either of the following is true
///
/// - The expression is a `continue` node.
/// - The expression node is a block with the first statement being a `continue`.
///
fn needless_continue_in_else(else_expr: &ast::Expr) -> bool {
    match else_expr.node {
        ast::ExprKind::Block(ref else_block) => is_first_block_stmt_continue(else_block),
        ast::ExprKind::Continue(_) => true,
        _ => false,
    }
}

fn is_first_block_stmt_continue(block: &ast::Block) -> bool {
    block.stmts.get(0).map_or(false, |stmt| match stmt.node {
        ast::StmtKind::Semi(ref e) |
        ast::StmtKind::Expr(ref e) => if let ast::ExprKind::Continue(_) = e.node {
            true
        } else {
            false
        },
        _ => false,
    })
}

/// If `expr` is a loop expression (while/while let/for/loop), calls `func` with
/// the AST object representing the loop block of `expr`.
fn with_loop_block<F>(expr: &ast::Expr, mut func: F) where F: FnMut(&ast::Block) {
    match expr.node {
        ast::ExprKind::While(_, ref loop_block, _)       |
        ast::ExprKind::WhileLet(_, _, ref loop_block, _) |
        ast::ExprKind::ForLoop( _, _, ref loop_block, _) |
        ast::ExprKind::Loop(ref loop_block, _)           => func(loop_block),
        _ => {},
    }
}

/// If `stmt` is an if expression node with an `else` branch, calls func with the
/// following:
///
/// - The `if` expression itself,
/// - The `if` condition expression,
/// - The `then` block, and
/// - The `else` expression.
///
fn with_if_expr<F>(stmt: &ast::Stmt, mut func: F)
        where F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr) {
    match stmt.node {
        ast::StmtKind::Semi(ref e) |
        ast::StmtKind::Expr(ref e) => {
            if let ast::ExprKind::If(ref cond, ref if_block, Some(ref else_expr)) = e.node {
                func(e, cond, if_block, else_expr);
            }
        },
        _ => { },
    }
}

/// A type to distinguish between the two distinct cases this lint handles.
#[derive(Copy, Clone, Debug)]
enum LintType {
    ContinueInsideElseBlock,
    ContinueInsideThenBlock,
}

/// Data we pass around for construction of help messages.
struct LintData<'a> {
    /// The `if` expression encountered in the above loop.
    if_expr: &'a ast::Expr,
    /// The condition expression for the above `if`.
    if_cond: &'a ast::Expr,
    /// The `then` block of the `if` statement.
    if_block: &'a ast::Block,
    /// The `else` block of the `if` statement.
    /// Note that we only work with `if` exprs that have an `else` branch.
    else_expr: &'a ast::Expr,
    /// The 0-based index of the `if` statement in the containing loop block.
    stmt_idx: usize,
    /// The statements of the loop block.
    block_stmts: &'a [ast::Stmt],
}

const MSG_REDUNDANT_ELSE_BLOCK: &'static str = "This else block is redundant.\n";

const MSG_ELSE_BLOCK_NOT_NEEDED: &'static str = "There is no need for an explicit `else` block for this `if` expression\n";

const DROP_ELSE_BLOCK_AND_MERGE_MSG: &'static str =
    "Consider dropping the else clause and merging the code that follows (in the loop) with the if block, like so:\n";

const DROP_ELSE_BLOCK_MSG: &'static str =
    "Consider dropping the else clause, and moving out the code in the else block, like so:\n";

fn emit_warning<'a>(ctx: &EarlyContext,
                    data: &'a LintData,
                    header: &str,
                    typ: LintType) {

    // snip    is the whole *help* message that appears after the warning.
    // message is the warning message.
    // expr    is the expression which the lint warning message refers to.
    let (snip, message, expr) = match typ {
        LintType::ContinueInsideElseBlock => {
            (suggestion_snippet_for_continue_inside_else(ctx, data, header),
             MSG_REDUNDANT_ELSE_BLOCK,
             data.else_expr)
        },
        LintType::ContinueInsideThenBlock => {
            (suggestion_snippet_for_continue_inside_if(ctx, data, header),
             MSG_ELSE_BLOCK_NOT_NEEDED,
             data.if_expr)
        }
    };
    span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip);
}

fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext,
                                                data: &'a LintData,
                                                header: &str) -> String {
    let cond_code = snippet(ctx, data.if_cond.span, "..");

    let if_code   = format!("if {} {{\n    continue;\n}}\n", cond_code);
                                   /*  ^^^^--- Four spaces of indentation. */
    // region B
    let else_code = snippet(ctx, data.else_expr.span, "..").into_owned();
    let else_code = erode_block(&else_code);
    let else_code = trim_multiline(Cow::from(else_code), false);

    let mut ret = String::from(header);
    ret.push_str(&if_code);
    ret.push_str(&else_code);
    ret.push_str("\n...");
    ret
}

fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext,
                                                   data: &'a LintData,
                                                   header: &str) -> String
{
    let cond_code = snippet(ctx, data.if_cond.span, "..");
    let mut if_code   = format!("if {} {{\n", cond_code);

    // Region B
    let block_code = &snippet(ctx, data.if_block.span, "..").into_owned();
    let block_code = erode_block(block_code);
    let block_code = trim_multiline(Cow::from(block_code), false);

    if_code.push_str(&block_code);

    // Region C
    // These is the code in the loop block that follows the if/else construction
    // we are complaining about. We want to pull all of this code into the
    // `then` block of the `if` statement.
    let to_annex = data.block_stmts[data.stmt_idx+1..]
                   .iter()
                   .map(|stmt| {
                        original_sp(stmt.span, DUMMY_SP)
                    })
                   .map(|span| snippet_block(ctx, span, "..").into_owned())
                   .collect::<Vec<_>>().join("\n");

    let mut ret = String::from(header);

    ret.push_str(&if_code);
    ret.push_str("\n// Merged code follows...");
    ret.push_str(&to_annex);
    ret.push_str("\n}\n");
    ret
}

fn check_and_warn<'a>(ctx: &EarlyContext, expr: &'a ast::Expr) {
    with_loop_block(expr, |loop_block| {
        for (i, stmt) in loop_block.stmts.iter().enumerate() {
            with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {
                let data = &LintData {
                    stmt_idx:    i,
                    if_expr:     if_expr,
                    if_cond:     cond,
                    if_block:    then_block,
                    else_expr:   else_expr,
                    block_stmts: &loop_block.stmts,
                };
                if needless_continue_in_else(else_expr) {
                    emit_warning(ctx, data, DROP_ELSE_BLOCK_AND_MERGE_MSG, LintType::ContinueInsideElseBlock);
                } else if is_first_block_stmt_continue(then_block) {
                    emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock);
                }
            });
        }
    });
}

/// Eats at `s` from the end till a closing brace `}` is encountered, and then
/// continues eating till a non-whitespace character is found.
/// e.g., the string
///
/// ```
///     {
///         let x = 5;
///     }
/// ```
///
/// is transformed to
///
/// ```
///     {
///         let x = 5;"
/// ```
///
/// NOTE: when there is no closing brace in `s`, `s` is _not_ preserved, i.e.,
/// an empty string will be returned in that case.
pub fn erode_from_back(s: &str) -> String {
    let mut ret = String::from(s);
    while ret.pop().map_or(false, |c| c != '}') { }
    while let Some(c) = ret.pop() {
        if !c.is_whitespace() {
            ret.push(c);
            break;
        }
    }
    ret
}

/// Eats at `s` from the front by first skipping all leading whitespace. Then,
/// any number of opening braces are eaten, followed by any number of newlines.
/// e.g.,  the string
///
/// ```
///         {
///             something();
///             inside_a_block();
///         }
/// ```
///
/// is transformed to
///
/// ```
///             something();
///             inside_a_block();
///         }
///
/// ```
///
pub fn erode_from_front(s: &str) -> String {
    s.chars()
     .skip_while(|c| c.is_whitespace())
     .skip_while(|c| *c == '{')
     .skip_while(|c| *c == '\n')
     .collect::<String>()
}

/// If `s` contains the code for a block, delimited by braces, this function
/// tries to get the contents of the block. If there is no closing brace present,
/// an empty string is returned.
pub fn erode_block(s: &str) -> String {
    erode_from_back(&erode_from_front(s))
}
<commit_msg>Fix two doc comments<commit_after>//! Checks for continue statements in loops that are redundant.
//!
//! For example, the lint would catch
//!
//! ```
//! while condition() {
//!     update_condition();
//!     if x {
//!         // ...
//!     } else {
//!         continue;
//!     }
//!     println!("Hello, world");
//! }
//! ```
//!
//! And suggest something like this:
//!
//! ```
//! while condition() {
//!     update_condition();
//!     if x {
//!         // ...
//!         println!("Hello, world");
//!     }
//! }
//! ```
//!
//! This lint is **warn** by default.
use rustc::lint::*;
use syntax::ast;
use syntax::codemap::{original_sp,DUMMY_SP};
use std::borrow::Cow;

use utils::{in_macro, span_help_and_lint, snippet_block, snippet, trim_multiline};

/// **What it does:** The lint checks for `if`-statements appearing in loops
/// that contain a `continue` statement in either their main blocks or their
/// `else`-blocks, when omitting the `else`-block possibly with some
/// rearrangement of code can make the code easier to understand.
///
/// **Why is this bad?** Having explicit `else` blocks for `if` statements
/// containing `continue` in their THEN branch adds unnecessary branching and
/// nesting to the code. Having an else block containing just `continue` can
/// also be better written by grouping the statements following the whole `if`
/// statement within the THEN block and omitting the else block completely.
///
/// **Known problems:** None
///
/// **Example:**
/// ```rust
/// while condition() {
///     update_condition();
///     if x {
///         // ...
///     } else {
///         continue;
///     }
///     println!("Hello, world");
/// }
/// ```
///
/// Could be rewritten as
///
/// ```rust
/// while condition() {
///     update_condition();
///     if x {
///         // ...
///         println!("Hello, world");
///     }
/// }
/// ```
///
/// As another example, the following code
///
/// ```rust
/// loop {
///     if waiting() {
///         continue;
///     } else {
///         // Do something useful
///     }
/// }
/// ```
/// Could be rewritten as
///
/// ```rust
/// loop {
///     if waiting() {
///         continue;
///     }
///     // Do something useful
/// }
/// ```
declare_lint! {
    pub NEEDLESS_CONTINUE,
    Warn,
    "`continue` statements that can be replaced by a rearrangement of code"
}

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

impl LintPass for NeedlessContinue {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEEDLESS_CONTINUE)
    }
}

impl EarlyLintPass for NeedlessContinue {
    fn check_expr(&mut self, ctx: &EarlyContext, expr: &ast::Expr) {
        if !in_macro(expr.span) {
            check_and_warn(ctx, expr);
        }
    }
}

/* This lint has to mainly deal with two cases of needless continue statements.
 *
 * Case 1 [Continue inside else block]:
 *
 *     loop {
 *         // region A
 *         if cond {
 *             // region B
 *         } else {
 *             continue;
 *         }
 *         // region C
 *     }
 *
 * This code can better be written as follows:
 *
 *     loop {
 *         // region A
 *         if cond {
 *             // region B
 *             // region C
 *         }
 *     }
 *
 * Case 2 [Continue inside then block]:
 *
 *     loop {
 *       // region A
 *       if cond {
 *           continue;
 *           // potentially more code here.
 *       } else {
 *           // region B
 *       }
 *       // region C
 *     }
 *
 *
 * This snippet can be refactored to:
 *
 *     loop {
 *       // region A
 *       if !cond {
 *           // region B
 *           // region C
 *       }
 *     }
 */

/// Given an expression, returns true if either of the following is true
///
/// - The expression is a `continue` node.
/// - The expression node is a block with the first statement being a `continue`.
///
fn needless_continue_in_else(else_expr: &ast::Expr) -> bool {
    match else_expr.node {
        ast::ExprKind::Block(ref else_block) => is_first_block_stmt_continue(else_block),
        ast::ExprKind::Continue(_) => true,
        _ => false,
    }
}

fn is_first_block_stmt_continue(block: &ast::Block) -> bool {
    block.stmts.get(0).map_or(false, |stmt| match stmt.node {
        ast::StmtKind::Semi(ref e) |
        ast::StmtKind::Expr(ref e) => if let ast::ExprKind::Continue(_) = e.node {
            true
        } else {
            false
        },
        _ => false,
    })
}

/// If `expr` is a loop expression (while/while let/for/loop), calls `func` with
/// the AST object representing the loop block of `expr`.
fn with_loop_block<F>(expr: &ast::Expr, mut func: F) where F: FnMut(&ast::Block) {
    match expr.node {
        ast::ExprKind::While(_, ref loop_block, _)       |
        ast::ExprKind::WhileLet(_, _, ref loop_block, _) |
        ast::ExprKind::ForLoop( _, _, ref loop_block, _) |
        ast::ExprKind::Loop(ref loop_block, _)           => func(loop_block),
        _ => {},
    }
}

/// If `stmt` is an if expression node with an `else` branch, calls func with the
/// following:
///
/// - The `if` expression itself,
/// - The `if` condition expression,
/// - The `then` block, and
/// - The `else` expression.
///
fn with_if_expr<F>(stmt: &ast::Stmt, mut func: F)
        where F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr) {
    match stmt.node {
        ast::StmtKind::Semi(ref e) |
        ast::StmtKind::Expr(ref e) => {
            if let ast::ExprKind::If(ref cond, ref if_block, Some(ref else_expr)) = e.node {
                func(e, cond, if_block, else_expr);
            }
        },
        _ => { },
    }
}

/// A type to distinguish between the two distinct cases this lint handles.
#[derive(Copy, Clone, Debug)]
enum LintType {
    ContinueInsideElseBlock,
    ContinueInsideThenBlock,
}

/// Data we pass around for construction of help messages.
struct LintData<'a> {
    /// The `if` expression encountered in the above loop.
    if_expr: &'a ast::Expr,
    /// The condition expression for the above `if`.
    if_cond: &'a ast::Expr,
    /// The `then` block of the `if` statement.
    if_block: &'a ast::Block,
    /// The `else` block of the `if` statement.
    /// Note that we only work with `if` exprs that have an `else` branch.
    else_expr: &'a ast::Expr,
    /// The 0-based index of the `if` statement in the containing loop block.
    stmt_idx: usize,
    /// The statements of the loop block.
    block_stmts: &'a [ast::Stmt],
}

const MSG_REDUNDANT_ELSE_BLOCK: &'static str = "This else block is redundant.\n";

const MSG_ELSE_BLOCK_NOT_NEEDED: &'static str = "There is no need for an explicit `else` block for this `if` expression\n";

const DROP_ELSE_BLOCK_AND_MERGE_MSG: &'static str =
    "Consider dropping the else clause and merging the code that follows (in the loop) with the if block, like so:\n";

const DROP_ELSE_BLOCK_MSG: &'static str =
    "Consider dropping the else clause, and moving out the code in the else block, like so:\n";

fn emit_warning<'a>(ctx: &EarlyContext,
                    data: &'a LintData,
                    header: &str,
                    typ: LintType) {

    // snip    is the whole *help* message that appears after the warning.
    // message is the warning message.
    // expr    is the expression which the lint warning message refers to.
    let (snip, message, expr) = match typ {
        LintType::ContinueInsideElseBlock => {
            (suggestion_snippet_for_continue_inside_else(ctx, data, header),
             MSG_REDUNDANT_ELSE_BLOCK,
             data.else_expr)
        },
        LintType::ContinueInsideThenBlock => {
            (suggestion_snippet_for_continue_inside_if(ctx, data, header),
             MSG_ELSE_BLOCK_NOT_NEEDED,
             data.if_expr)
        }
    };
    span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip);
}

fn suggestion_snippet_for_continue_inside_if<'a>(ctx: &EarlyContext,
                                                data: &'a LintData,
                                                header: &str) -> String {
    let cond_code = snippet(ctx, data.if_cond.span, "..");

    let if_code   = format!("if {} {{\n    continue;\n}}\n", cond_code);
                                   /*  ^^^^--- Four spaces of indentation. */
    // region B
    let else_code = snippet(ctx, data.else_expr.span, "..").into_owned();
    let else_code = erode_block(&else_code);
    let else_code = trim_multiline(Cow::from(else_code), false);

    let mut ret = String::from(header);
    ret.push_str(&if_code);
    ret.push_str(&else_code);
    ret.push_str("\n...");
    ret
}

fn suggestion_snippet_for_continue_inside_else<'a>(ctx: &EarlyContext,
                                                   data: &'a LintData,
                                                   header: &str) -> String
{
    let cond_code = snippet(ctx, data.if_cond.span, "..");
    let mut if_code   = format!("if {} {{\n", cond_code);

    // Region B
    let block_code = &snippet(ctx, data.if_block.span, "..").into_owned();
    let block_code = erode_block(block_code);
    let block_code = trim_multiline(Cow::from(block_code), false);

    if_code.push_str(&block_code);

    // Region C
    // These is the code in the loop block that follows the if/else construction
    // we are complaining about. We want to pull all of this code into the
    // `then` block of the `if` statement.
    let to_annex = data.block_stmts[data.stmt_idx+1..]
                   .iter()
                   .map(|stmt| {
                        original_sp(stmt.span, DUMMY_SP)
                    })
                   .map(|span| snippet_block(ctx, span, "..").into_owned())
                   .collect::<Vec<_>>().join("\n");

    let mut ret = String::from(header);

    ret.push_str(&if_code);
    ret.push_str("\n// Merged code follows...");
    ret.push_str(&to_annex);
    ret.push_str("\n}\n");
    ret
}

fn check_and_warn<'a>(ctx: &EarlyContext, expr: &'a ast::Expr) {
    with_loop_block(expr, |loop_block| {
        for (i, stmt) in loop_block.stmts.iter().enumerate() {
            with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {
                let data = &LintData {
                    stmt_idx:    i,
                    if_expr:     if_expr,
                    if_cond:     cond,
                    if_block:    then_block,
                    else_expr:   else_expr,
                    block_stmts: &loop_block.stmts,
                };
                if needless_continue_in_else(else_expr) {
                    emit_warning(ctx, data, DROP_ELSE_BLOCK_AND_MERGE_MSG, LintType::ContinueInsideElseBlock);
                } else if is_first_block_stmt_continue(then_block) {
                    emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock);
                }
            });
        }
    });
}

/// Eats at `s` from the end till a closing brace `}` is encountered, and then
/// continues eating till a non-whitespace character is found.
/// e.g., the string
///
/// ```
///     {
///         let x = 5;
///     }
/// ```
///
/// is transformed to
///
/// ```
///     {
///         let x = 5;
/// ```
///
/// NOTE: when there is no closing brace in `s`, `s` is _not_ preserved, i.e.,
/// an empty string will be returned in that case.
pub fn erode_from_back(s: &str) -> String {
    let mut ret = String::from(s);
    while ret.pop().map_or(false, |c| c != '}') { }
    while let Some(c) = ret.pop() {
        if !c.is_whitespace() {
            ret.push(c);
            break;
        }
    }
    ret
}

/// Eats at `s` from the front by first skipping all leading whitespace. Then,
/// any number of opening braces are eaten, followed by any number of newlines.
/// e.g.,  the string
///
/// ```
///         {
///             something();
///             inside_a_block();
///         }
/// ```
///
/// is transformed to
///
/// ```
///             something();
///             inside_a_block();
///         }
/// ```
///
pub fn erode_from_front(s: &str) -> String {
    s.chars()
     .skip_while(|c| c.is_whitespace())
     .skip_while(|c| *c == '{')
     .skip_while(|c| *c == '\n')
     .collect::<String>()
}

/// If `s` contains the code for a block, delimited by braces, this function
/// tries to get the contents of the block. If there is no closing brace present,
/// an empty string is returned.
pub fn erode_block(s: &str) -> String {
    erode_from_back(&erode_from_front(s))
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! x86_64 architecture-specific implementation.
pub mod cpu;
pub mod drivers;
pub mod memory;
<commit_msg>[x86_64] Begin on arch-specific kernel entries<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! x86_64 architecture-specific implementation.
pub mod cpu;
pub mod drivers;
pub mod memory;

use memory::PAddr;
use multiboot2;

/// Entry point for architecture-specific kernel init
#[no_mangle]
pub extern "C" fn arch_init(multiboot_addr: PAddr) {
    // -- Unpack multiboot tag ------------------------------------------------
    let boot_info = unsafe {
        multiboot2::Info::from(multiboot_addr)
            .expect("Could not unpack multiboot2 information!")
    };
}
<|endoftext|>


<commit_before>use std::fs::{File, OpenOptions, metadata};
use std::path::{Path, PathBuf};

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, encode_into, decode_from};

use super::Error;
use super::database::Database;
use super::column::Column;
use super::rows::Rows;

use super::super::identifier::Identifier;

pub struct Table<'a> {
    database: &'a Database,
    name: Identifier,
    meta_data: TableMetadata
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct TableMetadata {
    engine_id: u8,
    columns: Vec<Column>
}

/// Table representation
impl<'a> Table<'a> {
    /// Create table in database
    pub fn create<'b>(name: &str, engine_id: u8, columns: Vec<Column>, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("creating table: {}", name);

        // TODO: verify if name is a valid identifier

        let metadata = TableMetadata {
            engine_id: engine_id,
            columns: columns
        };

        let mut buf = try!(File::create(db.get_path().clone().join(&name).with_extension("tbl")));

        encode_into(&metadata, &mut buf, SizeLimit::Infinite).unwrap();

        Ok(Table {
            database: &db,
            name: try!(Identifier::new(name)),
            meta_data: metadata.clone()
        })
    }

    /// Load table from database
    pub fn load<'b>(name: &str, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("loading table: {}", &name);
        let path = db.get_path().clone().join(&name).with_extension("tbl");
        if !try!(metadata(&path)).is_dir()
        {
            let mut file = try!(OpenOptions::new()
                        .read(true)
                        .open(&path));

            let metadata: TableMetadata = try!(decode_from(&mut file, SizeLimit::Infinite));
            info!("loaded table: {}", &name);

            Ok(Table {
                database: db,
                name: try!(Identifier::new(name)),
                meta_data: metadata
            })
        }else {
            error!("could not load table: {} at {}", &name, &path.to_str().unwrap());
            Err(Error::LoadTable)
        }
    }

    // TODO: write table delete static function

    /// Returns a vector of the sizes of the columns
    pub fn get_cols_sizes(&self) -> Vec<u32> {
        let mut column_sizes = Vec::<u32>::new();

        for v in &self.meta_data.columns {
            column_sizes.push(v.size());
        }

        column_sizes
    }

    pub fn get_table_header_offset(&self) -> u32 {
        let bytes: Vec<u8> = encode(&self.meta_data, SizeLimit::Infinite).unwrap();
        bytes.len() as u32
    }

    pub fn get_cols_offset(&self) -> u32 {
        let mut size = 0;

        for v in &self.meta_data.columns {
            size += v.size();
        }

        size
    }

    /// Get full file path including filename and ext
    pub fn get_path(&self) -> PathBuf {
        self.database.get_path().clone().join(&self.name.get_name()).with_extension("tbl")
    }

    pub fn get_engine_id(&self) -> u8 {
        self.meta_data.engine_id
    }

}

#[cfg(test)]
mod test {
    use super::Table;
    use super::super::database::*;
    use std::fs::metadata;
    use super::super::column::Column;
    use super::super::types::Types;

    #[test]
    fn create_table() {
        let path = "/tmp/test1/";
        let name = "test_db3";
        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 0, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());
    }

    #[test]
    fn load_table() {
        let path = "/tmp/test1/";
        let name = "test_db4";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());

        let table2 = Table::load("test_table1", &db).unwrap();

        assert_eq!(table.get_engine_id(), table2.get_engine_id());
        assert_eq!(&table.meta_data.columns, &table2.meta_data.columns);
    }

    #[test]
    fn table_offset() {
        let path = "/tmp/test1/";
        let name = "test_db5";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert_eq!(table.get_table_header_offset(), 42u32);

    }

}
<commit_msg>fix test for table load problem<commit_after>use std::fs::{File, OpenOptions, metadata};
use std::path::{Path, PathBuf};

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, encode_into, decode_from};

use super::Error;
use super::database::Database;
use super::column::Column;
use super::rows::Rows;

use super::super::identifier::Identifier;

pub struct Table<'a> {
    database: &'a Database,
    name: Identifier,
    meta_data: TableMetadata
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct TableMetadata {
    engine_id: u8,
    columns: Vec<Column>
}

/// Table representation
impl<'a> Table<'a> {
    /// Create table in database
    pub fn create<'b>(name: &str, engine_id: u8, columns: Vec<Column>, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("creating table: {}", name);

        // TODO: verify if name is a valid identifier

        let metadata = TableMetadata {
            engine_id: engine_id,
            columns: columns
        };

        let mut buf = try!(File::create(db.get_path().clone().join(&name).with_extension("tbl")));

        encode_into(&metadata, &mut buf, SizeLimit::Infinite).unwrap();

        Ok(Table {
            database: &db,
            name: try!(Identifier::new(name)),
            meta_data: metadata.clone()
        })
    }

    /// Load table from database
    pub fn load<'b>(name: &str, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("loading table: {}", &name);
        let path = db.get_path().clone().join(&name).with_extension("tbl");
        if !try!(metadata(&path)).is_dir()
        {
            let mut file = try!(OpenOptions::new()
                        .read(true)
                        .open(&path));

            let metadata: TableMetadata = try!(decode_from(&mut file, SizeLimit::Infinite));
            info!("loaded table: {}", &name);

            Ok(Table {
                database: db,
                name: try!(Identifier::new(name)),
                meta_data: metadata
            })
        }else {
            error!("could not load table: {} at {}", &name, &path.to_str().unwrap());
            Err(Error::LoadTable)
        }
    }

    // TODO: write table delete static function

    /// Returns a vector of the sizes of the columns
    pub fn get_cols_sizes(&self) -> Vec<u32> {
        let mut column_sizes = Vec::<u32>::new();

        for v in &self.meta_data.columns {
            column_sizes.push(v.size());
        }

        column_sizes
    }

    pub fn get_table_header_offset(&self) -> u32 {
        let bytes: Vec<u8> = encode(&self.meta_data, SizeLimit::Infinite).unwrap();
        bytes.len() as u32
    }

    pub fn get_cols_offset(&self) -> u32 {
        let mut size = 0;

        for v in &self.meta_data.columns {
            size += v.size();
        }

        size
    }

    /// Get full file path including filename and ext
    pub fn get_path(&self) -> PathBuf {
        self.database.get_path().clone().join(&self.name.get_name()).with_extension("tbl")
    }

    pub fn get_engine_id(&self) -> u8 {
        self.meta_data.engine_id
    }

}

#[cfg(test)]
mod test {
    use super::Table;
    use super::super::database::*;
    use std::fs::metadata;
    use super::super::column::Column;
    use super::super::types::Types;

    #[test]
    fn create_table() {
        let path = "/tmp/test1/";
        let name = "test_db3";
        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 0, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());
    }

    #[test]
    fn load_table() {
        let path = "/tmp/test1/";
        let name = "test_db4";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db2 = Database::create(&name, DatabaseConfig::new(&path));
        assert!(db2.is_ok());
        let db = db2.unwrap();
        let table2 = Table::create("test_table2", 34, columns, &db);
        assert!(table2.is_ok());
        let table = table2.unwrap();

       // assert!(!metadata("/tmp/test1/test_db3/test_table2.tbl").unwrap().is_dir());

        let table2 = Table::load("test_table1", &db).unwrap();

        assert_eq!(table.get_engine_id(), table2.get_engine_id());
        assert_eq!(&table.meta_data.columns, &table2.meta_data.columns);
    }

    #[test]
    fn table_offset() {
        let path = "/tmp/test1/";
        let name = "test_db5";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert_eq!(table.get_table_header_offset(), 42u32);

    }

}
<|endoftext|>