<commit_before>extern crate clap;
extern crate image;

use clap::{Arg,App,SubCommand};
use std::fs::File;
use image::{FilterType, GenericImage, Pixel};
use image::DynamicImage;
use std::path::Path;

fn main() {
     let matches = App::new("IPCLI ")
                          .version("0.1")
                          .author("Mikolaj Wawrzyniak <mikolaj.wawrzyniak at fh-dortmund.de>")
                          .about("Basic CLI for image processing")
                          .arg(Arg::with_name("operation")
                               .short("o")
                               .long("operation")
                               .help("Specifies operation to be done on the image")
                               .takes_value(true)
                               .required(true))
                          .arg(Arg::with_name("value")
                               .short("v")
                               .long("value")
                               .help("Value for the transformation. To see what values are needed, check the documentation.")
                               .takes_value(true)
                               .required(false))
                          .arg(Arg::with_name("image")
                               .short("i")
                               .long("image")
                               .value_name("FILE")
                               .help("Opens specified image file and uses it for transformations.")
                               .takes_value(true)
                               .required(true))
                          .get_matches();

    let imagePath = matches.value_of("image").unwrap_or("empty");
    println!("Transforming the image: {}", imagePath);

    let operation = matches.value_of("operation").unwrap_or("empty");
    println!("Using operation: {}", operation);

    let value = matches.value_of("value").unwrap_or("empty");
    println!("Value: {}", value);

    match operation.as_ref(){
        "average" => {averageColor(imagePath)}
        "copy" => {copy(imagePath)}
        "thumbnail" => {
            let size: u32 = value.parse().unwrap();
            createThumnbail(imagePath, size)}
        "blur" => {
            let v : f32 = value.parse().unwrap();
            gaussianBlur(imagePath,v)}
        "brighten" => {
            let v: i32 = value.parse().unwrap();
            brighten(imagePath,v)}
        "huerotate" => {
            let v: i32 = value.parse().unwrap();
            huerotate(imagePath,v)}
        "contrast" => {
            let v: f32 = value.parse().unwrap();
            contrast(imagePath,v);}
        "grayscale" => {
            grayscale(imagePath);
        }
        "invert" => {
            invert(imagePath);
        }
        _ => {println!("Not implemented yet!")}
    }
}

fn averageColor(i: &str){
    let img = image::open(i).expect("Opening image failed");
    let mut r: u32 = 0;
    let mut g: u32 = 0;
    let mut b: u32 = 0;
    let (width,height) = img.dimensions();
    for x in 0..(width){
        for y in 0..(height){
            let px = img.get_pixel(x,y);
            let rgb = px.to_rgb();
            r = (r as u32 + rgb.data[0] as u32)/2;
            g = (g as u32 + rgb.data[1] as u32)/2;
            b = (b as u32 + rgb.data[2] as u32)/2;
        }
    }
    println!("Average color is: RGB {} {} {}",r,g,b);
}

fn createThumnbail(i: &str, size: u32){
    let operation = "Thumbnail";
    let img = image::open(i).expect("Opening image failed");
    let thumbnail = img.resize(size,size, FilterType::Lanczos3);
    saveFile(&thumbnail, &i, &operation);

}

fn copy(i: &str){
    let operation = "Copy";
    let img = image::open(i).expect("Opening image failed");
    saveFile(&img, &i, &operation);
}

fn gaussianBlur(i: &str, v: f32){
    let operation = "GuassianBlur";
    let img = image::open(i).expect("Opening image failed");
    let blurred = img.blur(v);
    saveFile(&blurred, &i, &operation);
}

fn brighten(i: &str,v: i32){
    let operation = "Brighten";
    let img = image::open(i).expect("Opening image failed");
    let brightened = img.brighten(v);
    saveFile(&brightened, &i, &operation);
}

fn huerotate(i: &str, v: i32){
    let operation = "Huerotate";
    let img = image::open(i).expect("Opening image failed");
    let huerotated = img.huerotate(v);
    saveFile(&huerotated, &i, &operation);
}

fn contrast(i: &str, v: f32){
    let operation = "AdjustContrast";
    let img = image::open(i).expect("Opening image failed");
    let contrast = img.adjust_contrast(v);
    saveFile(&contrast, &i, &operation);
}

fn grayscale(i: &str){
    let operation = "Grayscale";
    let img = image::open(i).expect("Opening image failed");
    let grayscale = img.grayscale();
    saveFile(&grayscale, &i, &operation);
}

fn invert(i: &str){
    let operation = "Invert";
    let mut img = image::open(i).expect("Opening image failed");
    img.invert();
    saveFile(&img, &i, &operation);
}

fn saveFile(img: &DynamicImage, i: &str, operation: &str){
    let mut outputPath: String = i.chars().take(i.len()-4).collect();
    let ext: String = i.chars().skip(i.len()-3).take(3).collect();
    outputPath.push_str(operation);
    outputPath.push_str(".");
    outputPath.push_str(&ext);
    println!("Output path: {}", outputPath);
    let mut out = File::create(outputPath).unwrap();
    match ext.as_ref() {
        "jpg" | "JPG" => {img.save(&mut out, image::JPEG).expect("Saving image failed");}
        "png" | "PNG" => {img.save(&mut out, image::PNG).expect("Saving image failed");}
        "gif" | "GIF" => {img.save(&mut out, image::GIF).expect("Saving image failed");}
        "bmp" | "BMP" => {img.save(&mut out, image::BMP).expect("Saving image failed");}
        "ico" | "ICO" => {img.save(&mut out, image::ICO).expect("Saving image failed");}
        _ => {println!("Unsupported file format")}
    }
}

<commit_msg>Update main.rs<commit_after>extern crate clap;
extern crate image;

use clap::{Arg,App,SubCommand};
use std::fs::File;
use image::{FilterType, GenericImage, Pixel};
use image::DynamicImage;
use std::path::Path;

fn main() {
     let matches = App::new("IPCLI ")
                          .version("0.1")
                          .author("Mikolaj Wawrzyniak <mikolaj.wawrzyniak at fh-dortmund.de>")
                          .about("Basic CLI for image processing")
                          .arg(Arg::with_name("operation")
                               .short("o")
                               .long("operation")
                               .help("Specifies operation to be done on the image")
                               .takes_value(true)
                               .required(true))
                          .arg(Arg::with_name("value")
                               .short("v")
                               .long("value")
                               .help("Value for the transformation. To see what values are needed, check the documentation.")
                               .takes_value(true)
                               .required(false))
                          .arg(Arg::with_name("image")
                               .short("i")
                               .long("image")
                               .value_name("FILE")
                               .help("Opens specified image file and uses it for transformations.")
                               .takes_value(true)
                               .required(true))
                          .get_matches();

    let imagePath = matches.value_of("image").unwrap_or("empty");
    println!("Transforming the image: {}", imagePath);

    let operation = matches.value_of("operation").unwrap_or("empty");
    println!("Using operation: {}", operation);

    let value = matches.value_of("value").unwrap_or("empty");
    println!("Value: {}", value);

    match operation.as_ref(){
        "average" => {averageColor(imagePath)}
        "copy" => {copy(imagePath)}
        "thumbnail" => {
            let size: u32 = value.parse().unwrap();
            createThumnbail(imagePath, size)}
        "blur" => {
            let v : f32 = value.parse().unwrap();
            gaussianBlur(imagePath,v)}
        "brighten" => {
            let v: i32 = value.parse().unwrap();
            brighten(imagePath,v)}
        "huerotate" => {
            let v: i32 = value.parse().unwrap();
            huerotate(imagePath,v)}
        "contrast" => {
            let v: f32 = value.parse().unwrap();
            contrast(imagePath,v);}
        "grayscale" => {
            grayscale(imagePath);
        }
        "invert" => {
            invert(imagePath);
        }
        _ => {println!("Not implemented yet!")}
    }
}

fn averageColor(i: &str){
    let img = image::open(i).expect("Opening image failed");
    let mut r: u32 = 0;
    let mut g: u32 = 0;
    let mut b: u32 = 0;
    let (width,height) = img.dimensions();
    for x in 0..(width){
        for y in 0..(height){
            let px = img.get_pixel(x,y);
            let rgb = px.to_rgb();
            r = (r as u32 + rgb.data[0] as u32)/2;
            g = (g as u32 + rgb.data[1] as u32)/2;
            b = (b as u32 + rgb.data[2] as u32)/2;
        }
    }
    println!("Average color is: RGB {} {} {}",r,g,b);
}

fn createThumnbail(i: &str, size: u32){
    let operation = "Thumbnail";
    let img = image::open(i).expect("Opening image failed");
    let thumbnail = img.resize(size,size, FilterType::Lanczos3);
    saveFile(&thumbnail, &i, &operation);

}

fn copy(i: &str){
    let operation = "Copy";
    let img = image::open(i).expect("Opening image failed");
    saveFile(&img, &i, &operation);
}

fn gaussianBlur(i: &str, v: f32){
    let operation = "GuassianBlur";
    let img = image::open(i).expect("Opening image failed");
    let blurred = img.blur(v);
    saveFile(&blurred, &i, &operation);
}

fn brighten(i: &str,v: i32){
    let operation = "Brighten";
    let img = image::open(i).expect("Opening image failed");
    let brightened = img.brighten(v);
    saveFile(&brightened, &i, &operation);
}

fn huerotate(i: &str, v: i32){
    let operation = "Huerotate";
    let img = image::open(i).expect("Opening image failed");
    let huerotated = img.huerotate(v);
    saveFile(&huerotated, &i, &operation);
}

fn contrast(i: &str, v: f32){
    let operation = "AdjustContrast";
    let img = image::open(i).expect("Opening image failed");
    let contrast = img.adjust_contrast(v);
    saveFile(&contrast, &i, &operation);
}

fn grayscale(i: &str){
    let operation = "Grayscale";
    let img = image::open(i).expect("Opening image failed");
    let grayscale = img.grayscale();
    saveFile(&grayscale, &i, &operation);
}

fn invert(i: &str){
    let operation = "Invert";
    let mut img = image::open(i).expect("Opening image failed");
    img.invert();
    saveFile(&img, &i, &operation);
}

fn saveFile(img: &DynamicImage, i: &str, operation: &str){
    let mut outputPath: String = i.chars().take(i.len()-4).collect();
    let ext: String = i.chars().skip(i.len()-3).take(3).collect();
    outputPath.push_str(operation);
    outputPath.push_str(".");
    outputPath.push_str(&ext);
    println!("Output path: {}", outputPath);
    let mut out = File::create(outputPath).unwrap();
    match ext.as_ref() {
        "jpg" | "JPG" | "jpeg" | "JPEG" => {img.save(&mut out, image::JPEG).expect("Saving image failed");}
        "png" | "PNG" => {img.save(&mut out, image::PNG).expect("Saving image failed");}
        "gif" | "GIF" => {img.save(&mut out, image::GIF).expect("Saving image failed");}
        "bmp" | "BMP" => {img.save(&mut out, image::BMP).expect("Saving image failed");}
        "ico" | "ICO" => {img.save(&mut out, image::ICO).expect("Saving image failed");}
        _ => {println!("Unsupported file format")}
    }
}

<|endoftext|>


<commit_before>extern crate libc;

use std::ffi::CStr;
use std::os::raw::c_char;
use libc::size_t;
use libc::strncpy;

mod rnc {
    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    pub fn add(num_l: &str, num_r: &str) -> String {
        let sum = String::from(num_l);
        return sum + num_r;
    }
}

use rnc::add;

#[no_mangle]
pub extern fn rnc_add(dst: *mut c_char, dstlen: size_t, num_l: *const c_char, num_r: *const c_char) {
    unsafe {
        let sum = add(CStr::from_ptr(num_l).to_str().unwrap(), CStr::from_ptr(num_r).to_str().unwrap());
        strncpy(dst, sum.as_ptr() as *const i8, dstlen);
    }
}
<commit_msg>Red unit test for IIIII -> V in Rust<commit_after>extern crate libc;

use std::ffi::CStr;
use std::os::raw::c_char;
use libc::size_t;
use libc::strncpy;

mod rnc {
    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii() {
        assert_eq!("V", add("II", "III"));

    }

    pub fn add(num_l: &str, num_r: &str) -> String {
        let sum = String::from(num_l);
        return sum + num_r;
    }
}

use rnc::add;

#[no_mangle]
pub extern fn rnc_add(dst: *mut c_char, dstlen: size_t, num_l: *const c_char, num_r: *const c_char) {
    unsafe {
        let sum = add(CStr::from_ptr(num_l).to_str().unwrap(), CStr::from_ptr(num_r).to_str().unwrap());
        strncpy(dst, sum.as_ptr() as *const i8, dstlen);
    }
}
<|endoftext|>


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

use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use glfw_events::EventHandlers;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 mvp_mat;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = mvp_mat * 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);
  }
";

pub struct Visualizer {
  glfw_event_handlers: EventHandlers,
  program: GLuint,
  vertex_buffer_obj: GLuint,
  unit_buffer_obj: GLuint,
  unit_mesh: ~[Vec3<GLfloat>],
  mat_id: GLint,
  win: Option<glfw::Window>,
  vertex_data: ~[Vec3<GLfloat>],
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
  obj: obj::Model,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "OpenGL",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = Vec2::<int>{x: 640, y: 480};
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      glfw_event_handlers: EventHandlers::new(&win),
      program: 0,
      vertex_buffer_obj: 0,
      unit_buffer_obj: 0,
      unit_mesh: ~[],
      mat_id: 0,
      win: Some(win),
      vertex_data: ~[],
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
      obj: obj::Model::new("tank.obj"),
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_model();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn build_hex_mesh(&mut self) {
    for tile_pos in TileIterator::new() {
      let pos3d = self.geom.v2i_to_v2f(tile_pos).extend(0.0);
      for num in range(0, 6) {
        let vertex = self.geom.index_to_hex_vertex(num);
        let next_vertex = self.geom.index_to_hex_vertex(num + 1);
        let data = &mut self.vertex_data;
        data.push(pos3d + vertex.extend(0.0));
        data.push(pos3d + next_vertex.extend(0.0));
        data.push(pos3d + Vec3::zero());
      }
    }
  }

  fn init_model(&mut self) {
    self.build_hex_mesh();
    self.program = glh::compile_program(
      VERTEX_SHADER_SRC,
      FRAGMENT_SHADER_SRC,
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    {
      unsafe {
        gl::GenBuffers(1, &mut self.vertex_buffer_obj);
      }
      gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
      glh::fill_current_coord_vbo(self.vertex_data);
      let pos_attr = glh::get_attr(self.program, "position");
      glh::vertex_attrib_pointer(pos_attr);
    }

    // prepare model
    {
      self.unit_mesh = self.obj.build();
      unsafe {
        gl::GenBuffers(1, &mut self.unit_buffer_obj);
      }
      gl::BindBuffer(gl::ARRAY_BUFFER, self.unit_buffer_obj);
      glh::fill_current_coord_vbo(self.unit_mesh);
    }
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteBuffers(1, &self.unit_buffer_obj);
    }
  }

  fn draw_map(&self) {
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
    glh::vertex_attrib_pointer(glh::get_attr(self.program, "position"));
    glh::draw_mesh(self.vertex_data);
  }

  fn draw_model(&self) {
    gl::BindBuffer(gl::ARRAY_BUFFER, self.unit_buffer_obj);
    glh::vertex_attrib_pointer(glh::get_attr(self.program, "position"));
    glh::draw_mesh(self.unit_mesh);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.draw_map();
    self.draw_model();
    self.win().swap_buffers();
  }

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

  fn handle_key_events(&mut self) {
    self.glfw_event_handlers.key_handler.handle(|event| {
      if event.action != glfw::Press {
        return;
      }
      match event.key {
        glfw::KeyEscape | glfw::KeyQ
                       => self.win().set_should_close(true),
        glfw::KeySpace => println!("space"),
        glfw::KeyUp    => self.camera.move(270.0),
        glfw::KeyDown  => self.camera.move(90.0),
        glfw::KeyRight => self.camera.move(0.0),
        glfw::KeyLeft  => self.camera.move(180.0),
        _ => {},
      }
    });
  }

  fn handle_cursor_pos_events(&mut self) {
    self.glfw_event_handlers.cursor_pos_handler.handle(|event| {
      let button = self.win().get_mouse_button(glfw::MouseButtonRight);
      if button == glfw::Press {
        self.camera.z_angle += self.mouse_pos.x - event.x;
        self.camera.x_angle += self.mouse_pos.y - event.y;
      }
      self.mouse_pos = Vec2{x: event.x, y: event.y};
    });
  }

  fn handle_events(&mut self) {
    glfw::poll_events();
    self.handle_key_events();
    self.handle_cursor_pos_events();
  }

  fn close_window(&mut self) {
    // destroy glfw::Window before terminating glfw
    self.win = None;
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
    println!("selected: {:?}", self.selected_tile_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
    self.close_window();
    glfw::terminate();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Visualizer: init_{map,unit}_model(&mut self)<commit_after>// See LICENSE file for copyright and license details.

use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use glfw_events::EventHandlers;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 mvp_mat;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = mvp_mat * 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);
  }
";

pub struct Visualizer {
  glfw_event_handlers: EventHandlers,
  program: GLuint,
  vertex_buffer_obj: GLuint,
  unit_buffer_obj: GLuint,
  unit_mesh: ~[Vec3<GLfloat>],
  mat_id: GLint,
  win: Option<glfw::Window>,
  vertex_data: ~[Vec3<GLfloat>],
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
  obj: obj::Model,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "OpenGL",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = Vec2::<int>{x: 640, y: 480};
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      glfw_event_handlers: EventHandlers::new(&win),
      program: 0,
      vertex_buffer_obj: 0,
      unit_buffer_obj: 0,
      unit_mesh: ~[],
      mat_id: 0,
      win: Some(win),
      vertex_data: ~[],
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
      obj: obj::Model::new("tank.obj"),
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_model();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn build_hex_mesh(&mut self) {
    for tile_pos in TileIterator::new() {
      let pos3d = self.geom.v2i_to_v2f(tile_pos).extend(0.0);
      for num in range(0, 6) {
        let vertex = self.geom.index_to_hex_vertex(num);
        let next_vertex = self.geom.index_to_hex_vertex(num + 1);
        let data = &mut self.vertex_data;
        data.push(pos3d + vertex.extend(0.0));
        data.push(pos3d + next_vertex.extend(0.0));
        data.push(pos3d + Vec3::zero());
      }
    }
  }

  fn init_map_model(&mut self) {
    unsafe {
      gl::GenBuffers(1, &mut self.vertex_buffer_obj);
    }
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
    glh::fill_current_coord_vbo(self.vertex_data);
  }

  fn init_unit_model(&mut self) {
    self.unit_mesh = self.obj.build();
    unsafe {
      gl::GenBuffers(1, &mut self.unit_buffer_obj);
    }
    gl::BindBuffer(gl::ARRAY_BUFFER, self.unit_buffer_obj);
    glh::fill_current_coord_vbo(self.unit_mesh);
  }

  fn init_model(&mut self) {
    self.build_hex_mesh();
    self.program = glh::compile_program(
      VERTEX_SHADER_SRC,
      FRAGMENT_SHADER_SRC,
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let pos_attr = glh::get_attr(self.program, "position");
    glh::vertex_attrib_pointer(pos_attr);
    self.init_map_model();
    self.init_unit_model();
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteBuffers(1, &self.unit_buffer_obj);
    }
  }

  fn draw_map(&self) {
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer_obj);
    glh::vertex_attrib_pointer(glh::get_attr(self.program, "position"));
    glh::draw_mesh(self.vertex_data);
  }

  fn draw_model(&self) {
    gl::BindBuffer(gl::ARRAY_BUFFER, self.unit_buffer_obj);
    glh::vertex_attrib_pointer(glh::get_attr(self.program, "position"));
    glh::draw_mesh(self.unit_mesh);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.draw_map();
    self.draw_model();
    self.win().swap_buffers();
  }

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

  fn handle_key_events(&mut self) {
    self.glfw_event_handlers.key_handler.handle(|event| {
      if event.action != glfw::Press {
        return;
      }
      match event.key {
        glfw::KeyEscape | glfw::KeyQ
                       => self.win().set_should_close(true),
        glfw::KeySpace => println!("space"),
        glfw::KeyUp    => self.camera.move(270.0),
        glfw::KeyDown  => self.camera.move(90.0),
        glfw::KeyRight => self.camera.move(0.0),
        glfw::KeyLeft  => self.camera.move(180.0),
        _ => {},
      }
    });
  }

  fn handle_cursor_pos_events(&mut self) {
    self.glfw_event_handlers.cursor_pos_handler.handle(|event| {
      let button = self.win().get_mouse_button(glfw::MouseButtonRight);
      if button == glfw::Press {
        self.camera.z_angle += self.mouse_pos.x - event.x;
        self.camera.x_angle += self.mouse_pos.y - event.y;
      }
      self.mouse_pos = Vec2{x: event.x, y: event.y};
    });
  }

  fn handle_events(&mut self) {
    glfw::poll_events();
    self.handle_key_events();
    self.handle_cursor_pos_events();
  }

  fn close_window(&mut self) {
    // destroy glfw::Window before terminating glfw
    self.win = None;
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
    println!("selected: {:?}", self.selected_tile_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
    self.close_window();
    glfw::terminate();
  }
}

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


<commit_before>extern crate rs6502;
extern crate sdl2;

mod console;
mod position;
mod text;

use std::io::{self, BufRead, Write};

use rs6502::{CodeSegment, Cpu, Disassembler};
use sdl2::render::Renderer;

pub use self::console::Console;
pub use self::position::Position;
pub use self::text::Text;

const HELPTEXT: &'static str = "

HAKKA
-----

Commands:

break | b: addr
       - Toggles a breakpoint at a specific address. If the
         program counter hits this address, execution
         stops.

step | s
       - Executes the current instruction before breaking
         execution again.

continue | c
       - Resumes execution of code within the virtual machine.

list
       - Lists the code surrounding the current program
         counter.

memset | set: addr args [args, ...]
       - memset sets the value of memory directly.

memdmp | dmp: page || start end
       - memdmp dumps a single memory page, or a specified
         memory range from <start> to <end> (inclusive).

monitor | mon: start end
       - monitor dumps the memory between start and end (inclusive)
         every second. Press ENTER to stop the monitor.

source
       - Lists the code currently running in the virtual
         machine. A '>' symbol indicates the current
         program counter.

registers | reg
       - Lists the CPU registers and their current values.

help
       - Lists this help text.
";

#[derive(Debug)]
pub struct MemoryMonitor {
    pub enabled: bool,
    start_addr: usize,
    end_addr: usize,
}

pub struct VirtualMachine<'a> {
    pub cpu: Cpu,
    pub monitor: MemoryMonitor,
    pub console: Console<'a>,
    segments: Vec<CodeSegment>,
    clock_rate: Option<u32>,
    last_command: String,
    breakpoints: [u8; 64 * 1024],
    broken: bool,
    step: bool,
}

impl<'a> VirtualMachine<'a> {
    pub fn new<CR>(cpu: Cpu, clock_rate: CR, mut console: Console<'a>) -> VirtualMachine<'a>
        where CR: Into<Option<u32>>
    {
        console.println("Welcome to hakka. Type 'help' for instructions.");
        console.println("");

        VirtualMachine {
            cpu: cpu,
            console: console,
            segments: Vec::new(),
            clock_rate: clock_rate.into(),
            monitor: MemoryMonitor {
                enabled: false,
                start_addr: 0,
                end_addr: 0,
            },
            last_command: "".into(),
            breakpoints: [0; 64 * 1024],
            broken: false,
            step: false,
        }
    }

    pub fn render(&mut self, mut renderer: &mut Renderer) {
        self.console.render(renderer);
    }

    pub fn load_code_segments(&mut self, segments: Vec<CodeSegment>) {
        if segments.len() == 0 {
            return;
        }
        self.segments = segments;
        for segment in &self.segments {
            self.cpu.load(&segment.code, segment.address);
        }

        self.cpu.registers.PC = self.segments[0].address;
    }

    /// Cycles the Virtual Machine CPU according to the clock rate
    pub fn cycle(&mut self) {
        if let Some(clock_rate) = self.clock_rate {
            let mut n = 0;
            while (n < clock_rate && !self.broken) || self.step {
                n += self.cpu.step().expect("SEGFAULT") as u32;
                if self.breakpoints[self.cpu.registers.PC as usize] > 0 {
                    self.broken = true;
                    self.console.println("");
                    self.console
                        .println(format!("BREAKPOINT hit at {:04X}", self.cpu.registers.PC));
                }
                // If we stepped, dump the local disassembly
                if self.step {
                    self.dump_local_disassembly();
                }
                self.step = false;
            }
        } else {
            self.cpu.step().expect("SEGFAULT");
            if self.step {
                self.dump_local_disassembly();
            }
            self.step = false;
            if self.breakpoints[self.cpu.registers.PC as usize] > 0 {
                self.broken = true;
                self.console.println("");
                self.console.println(format!("BREAKPOINT hit at {:04X}", self.cpu.registers.PC));
            }
        }
    }

    pub fn execute_command<S>(&mut self, cmd: S)
        where S: Into<String>
    {
        let mut input: String = cmd.into().trim().into();

        if input == "r" || input == "repeat" {
            input = self.last_command.clone();
        }

        let parts = input.split(" ").collect::<Vec<_>>();

        if input.len() == 0 {
            if self.monitor.enabled {
                self.monitor.enabled = false;
            }
        } else if parts[0] == "clear" || parts[0] == "cls" {
            self.console.clear();
        } else if parts[0] == "help" {
            self.console.print(format!("{}", HELPTEXT));
        } else if parts[0] == "source" {
            self.dump_disassembly();
        } else if parts[0] == "list" {
            self.dump_local_disassembly();
        } else if parts[0] == "monitor" || parts[0] == "mon" {
            if self.monitor.enabled {
                self.monitor.enabled = false;
            } else {
                self.enable_memory_monitor(&input);
            }
        } else if parts[0] == "memset" || parts[0] == "set" {
            if parts.len() < 3 {
                self.console
                    .println("ERR: Requires 2 arguments. Example: memset 0x00 0x01 to store 0x01 \
                              in 0x00.");
            } else if parts.len() == 3 {
                if let Ok(dst) = u16::from_str_radix(&parts[1].replace("0x", "")[..], 16) {
                    if let Ok(src) = u8::from_str_radix(&parts[2].replace("0x", "")[..], 16) {
                        self.cpu.memory[dst as usize] = src;
                    } else {
                        self.console.println("ERR: Unable to parse source byte value");
                    }
                } else {
                    self.console.println("ERR: Unable to parse destination byte value");
                }
            } else {
                if let Ok(mut dst) = usize::from_str_radix(&parts[1].replace("0x", "")[..], 16) {
                    for p in &parts[2..] {
                        if let Ok(byte) = u8::from_str_radix(&p.replace("0x", "")[..], 16) {
                            self.cpu.memory[dst] = byte;
                            dst += 0x01;
                        } else {
                            self.console.println("ERR: Unable to parse source byte value");
                        }
                    }
                } else {
                    self.console.println("ERR: Unable to parse destination byte value");
                }
            }
        } else if parts[0] == "memdmp" || parts[0] == "dmp" {
            // 1 argument assumes 1 memory "page"
            if parts.len() == 2 {
                if let Ok(page_number) = parts[1].parse() {

                    self.dump_memory_page(page_number);
                } else {
                    self.console.println("ERR: Unable to parse memory page");
                }
            } else if parts.len() == 3 {
                // A memory range instead
                if let Ok(start) = u16::from_str_radix(&parts[1].replace("0x", "")[..], 16) {
                    if let Ok(end) = u16::from_str_radix(&parts[2].replace("0x", "")[..], 16) {
                        self.dump_memory_range(start, end);
                    } else {
                        self.console.println("ERR: Unable to parse end address value");
                    }
                } else {
                    self.console.println("ERR: Unable to parse start address value");
                }
            }
        } else if parts[0] == "registers" || parts[0] == "reg" {
            self.dump_registers();
        } else if parts[0] == "break" || parts[0] == "b" {
            // 1 argument assumes 1 memory "page"
            if parts.len() == 2 {
                if let Ok(addr) = usize::from_str_radix(&parts[1][..], 16) {
                    if addr <= u16::max_value() as usize {
                        if self.breakpoints[addr] > 0 {
                            self.console.println(format!("Removed breakpoint at {:04X}", addr));
                            self.breakpoints[addr] = 0;
                        } else {
                            self.console.println(format!("Added breakpoint at {:04X}", addr));
                            self.breakpoints[addr] = 1;
                        }
                    } else {
                        self.console.println("ERR: Value outside addressable range.");
                    }
                } else {
                    self.broken = true;
                    println!("Execution stopped");
                }
            } else {
                self.console.println("ERR: Requires 1 argument");
            }
        } else if parts[0] == "continue" || parts[0] == "c" {
            self.broken = false;
            self.console.println("Execution resumed");
        } else if parts[0] == "step" || parts[0] == "s" {
            self.broken = true;
            self.step = true;
        } else {
            self.console.println("Unknown command");
        }

        // Don't assign a blank command as a last command
        if input.len() > 0 {
            self.last_command = input.clone();
        }
    }

    fn enable_memory_monitor(&mut self, input: &str) {
        let parts: Vec<&str> = input.split(" ").collect();
        if parts.len() < 3 {
            self.console.println("ERR: Requires 2 arguments. Example: monitor 0x00 0xFF");
        } else {
            let start = usize::from_str_radix(&parts[1].replace("0x", "")[..], 16).unwrap();
            let end = usize::from_str_radix(&parts[2].replace("0x", "")[..], 16).unwrap();

            self.monitor.start_addr = start;
            self.monitor.end_addr = end;
            self.monitor.enabled = true;
        }
    }

    fn dump_disassembly(&mut self) {
        self.console.println("");

        for segment in &self.segments {
            self.console.println(format!(".ORG ${:04X}", segment.address));
            let disassembler = Disassembler::with_offset(segment.address);
            let pairs = disassembler.disassemble_with_addresses(&segment.code);
            for line in self.highlight_lines(self.cpu.registers.PC as usize,
                                             pairs,
                                             segment.address,
                                             false) {
                self.console.println(format!("{}", line));
            }
            self.console.println("");
        }
    }

    fn dump_local_disassembly(&mut self) {
        self.console.println("");

        let result = {
            let pc = self.cpu.registers.PC as usize;
            let local_segment = self.get_local_segment(pc);
            let disassembler = Disassembler::with_offset(local_segment.address);
            let pairs = disassembler.disassemble_with_addresses(&local_segment.code);
            self.highlight_lines(pc, pairs, local_segment.address, true)
        };
        for line in result {
            self.console.println(format!("{}", line));
        }
        self.console.println("");
    }

    pub fn dump_memory_page(&mut self, page: usize) {
        let mut addr = page * 0x100;
        for chunk in self.cpu.memory[page * 0x100..(page * 0x100) + 0x100].chunks(8) {
            self.console.print(format!("{:04X}: ", addr));
            for b in chunk {
                self.console.print(format!("{:02X} ", *b));
            }
            self.console.wrap_line();
            addr += 0x08;
        }
    }

    pub fn dump_memory(&mut self) {
        self.console.println("");
        for chunk in self.cpu.memory[self.monitor.start_addr..self.monitor.end_addr + 0x01]
            .chunks(8) {
            for b in chunk {
                self.console.print(format!("{:02X} ", *b));
            }
            self.console.println("");
        }
    }

    fn dump_memory_range(&mut self, start: u16, end: u16) {
        self.console.println("");
        let start = start as usize;
        let end = end as usize;
        for chunk in self.cpu.memory[start..end + 0x01].chunks(8) {
            for b in chunk {
                self.console.print(format!("{:02X} ", *b));
            }
            self.console.println("");
        }
    }

    fn dump_registers(&mut self) {
        self.console.println("");
        self.console.println(format!("A: {} ({:04X})", self.cpu.registers.A, self.cpu.registers.A));
        self.console.println(format!("X: {} ({:04X})", self.cpu.registers.X, self.cpu.registers.X));
        self.console.println(format!("Y: {} ({:04X})", self.cpu.registers.Y, self.cpu.registers.Y));
        self.console.println(format!("PC: {} ({:04X})",
                                     self.cpu.registers.PC,
                                     self.cpu.registers.PC));
        self.console.println(format!("S: {} ({:04X})",
                                     self.cpu.stack.pointer,
                                     self.cpu.stack.pointer));
    }

    fn get_local_segment(&self, pc: usize) -> &CodeSegment {
        for segment in &self.segments {
            let addr = segment.address as usize;
            if pc >= addr && pc <= addr + segment.code.len() {
                return segment;
            }
        }

        &self.segments[0]
    }

    fn highlight_lines(&self,
                       pc: usize,
                       pairs: Vec<(String, u16)>,
                       segment_start: u16,
                       limit_results: bool)
                       -> Vec<String> {
        let mut result = Vec::new();

        let base = pc as isize - segment_start as isize;

        for pair in pairs {
            if limit_results {
                let start = if base > 0x0A { base - 0x0A } else { 0 };
                if (pair.1 as isize) < start || (pair.1 as isize) > base + 0x0A {
                    continue;
                }
            }
            let current_line = pc as u16 == segment_start + pair.1;
            let breakpoint = self.breakpoints[segment_start as usize + pair.1 as usize] > 0x00;

            if breakpoint && current_line {
                result.push(format!("> * {}", pair.0));
            } else if breakpoint && !current_line {
                result.push(format!("  * {}", pair.0));
            } else if !breakpoint && current_line {
                result.push(format!(">   {}", pair.0));
            } else {
                result.push(format!("    {}", pair.0));
            }
        }

        result
    }
}
<commit_msg>Automatically toggle Console when breakpoint is hit<commit_after>extern crate rs6502;
extern crate sdl2;

mod console;
mod position;
mod text;

use std::io::{self, BufRead, Write};

use rs6502::{CodeSegment, Cpu, Disassembler};
use sdl2::render::Renderer;

pub use self::console::Console;
pub use self::position::Position;
pub use self::text::Text;

const HELPTEXT: &'static str = "

HAKKA
-----

Commands:

break | b: addr
       - Toggles a breakpoint at a specific address. If the
         program counter hits this address, execution
         stops.

step | s
       - Executes the current instruction before breaking
         execution again.

continue | c
       - Resumes execution of code within the virtual machine.

list
       - Lists the code surrounding the current program
         counter.

memset | set: addr args [args, ...]
       - memset sets the value of memory directly.

memdmp | dmp: page || start end
       - memdmp dumps a single memory page, or a specified
         memory range from <start> to <end> (inclusive).

monitor | mon: start end
       - monitor dumps the memory between start and end (inclusive)
         every second. Press ENTER to stop the monitor.

source
       - Lists the code currently running in the virtual
         machine. A '>' symbol indicates the current
         program counter.

registers | reg
       - Lists the CPU registers and their current values.

help
       - Lists this help text.
";

#[derive(Debug)]
pub struct MemoryMonitor {
    pub enabled: bool,
    start_addr: usize,
    end_addr: usize,
}

pub struct VirtualMachine<'a> {
    pub cpu: Cpu,
    pub monitor: MemoryMonitor,
    pub console: Console<'a>,
    segments: Vec<CodeSegment>,
    clock_rate: Option<u32>,
    last_command: String,
    breakpoints: [u8; 64 * 1024],
    broken: bool,
    step: bool,
}

impl<'a> VirtualMachine<'a> {
    pub fn new<CR>(cpu: Cpu, clock_rate: CR, mut console: Console<'a>) -> VirtualMachine<'a>
        where CR: Into<Option<u32>>
    {
        console.println("Welcome to hakka. Type 'help' for instructions.");
        console.println("");

        VirtualMachine {
            cpu: cpu,
            console: console,
            segments: Vec::new(),
            clock_rate: clock_rate.into(),
            monitor: MemoryMonitor {
                enabled: false,
                start_addr: 0,
                end_addr: 0,
            },
            last_command: "".into(),
            breakpoints: [0; 64 * 1024],
            broken: false,
            step: false,
        }
    }

    pub fn render(&mut self, mut renderer: &mut Renderer) {
        self.console.render(renderer);
    }

    pub fn load_code_segments(&mut self, segments: Vec<CodeSegment>) {
        if segments.len() == 0 {
            return;
        }
        self.segments = segments;
        for segment in &self.segments {
            self.cpu.load(&segment.code, segment.address);
        }

        self.cpu.registers.PC = self.segments[0].address;
    }

    /// Cycles the Virtual Machine CPU according to the clock rate
    pub fn cycle(&mut self) {
        if let Some(clock_rate) = self.clock_rate {
            let mut n = 0;
            while (n < clock_rate && !self.broken) || self.step {
                n += self.cpu.step().expect("SEGFAULT") as u32;
                if self.breakpoints[self.cpu.registers.PC as usize] > 0 {
                    self.broken = true;
                    self.console.println("");
                    self.console
                        .println(format!("BREAKPOINT hit at {:04X}", self.cpu.registers.PC));
                    self.console.toggle();
                }
                // If we stepped, dump the local disassembly
                if self.step {
                    self.dump_local_disassembly();
                }
                self.step = false;
            }
        } else {
            self.cpu.step().expect("SEGFAULT");
            if self.step {
                self.dump_local_disassembly();
            }
            self.step = false;
            if self.breakpoints[self.cpu.registers.PC as usize] > 0 {
                self.broken = true;
                self.console.println("");
                self.console.println(format!("BREAKPOINT hit at {:04X}", self.cpu.registers.PC));
                self.console.toggle();
            }
        }
    }

    pub fn execute_command<S>(&mut self, cmd: S)
        where S: Into<String>
    {
        let mut input: String = cmd.into().trim().into();

        if input == "r" || input == "repeat" {
            input = self.last_command.clone();
        }

        let parts = input.split(" ").collect::<Vec<_>>();

        if input.len() == 0 {
            if self.monitor.enabled {
                self.monitor.enabled = false;
            }
        } else if parts[0] == "clear" || parts[0] == "cls" {
            self.console.clear();
        } else if parts[0] == "help" {
            self.console.print(format!("{}", HELPTEXT));
        } else if parts[0] == "source" {
            self.dump_disassembly();
        } else if parts[0] == "list" {
            self.dump_local_disassembly();
        } else if parts[0] == "monitor" || parts[0] == "mon" {
            if self.monitor.enabled {
                self.monitor.enabled = false;
            } else {
                self.enable_memory_monitor(&input);
            }
        } else if parts[0] == "memset" || parts[0] == "set" {
            if parts.len() < 3 {
                self.console
                    .println("ERR: Requires 2 arguments. Example: memset 0x00 0x01 to store 0x01 \
                              in 0x00.");
            } else if parts.len() == 3 {
                if let Ok(dst) = u16::from_str_radix(&parts[1].replace("0x", "")[..], 16) {
                    if let Ok(src) = u8::from_str_radix(&parts[2].replace("0x", "")[..], 16) {
                        self.cpu.memory[dst as usize] = src;
                    } else {
                        self.console.println("ERR: Unable to parse source byte value");
                    }
                } else {
                    self.console.println("ERR: Unable to parse destination byte value");
                }
            } else {
                if let Ok(mut dst) = usize::from_str_radix(&parts[1].replace("0x", "")[..], 16) {
                    for p in &parts[2..] {
                        if let Ok(byte) = u8::from_str_radix(&p.replace("0x", "")[..], 16) {
                            self.cpu.memory[dst] = byte;
                            dst += 0x01;
                        } else {
                            self.console.println("ERR: Unable to parse source byte value");
                        }
                    }
                } else {
                    self.console.println("ERR: Unable to parse destination byte value");
                }
            }
        } else if parts[0] == "memdmp" || parts[0] == "dmp" {
            // 1 argument assumes 1 memory "page"
            if parts.len() == 2 {
                if let Ok(page_number) = parts[1].parse() {

                    self.dump_memory_page(page_number);
                } else {
                    self.console.println("ERR: Unable to parse memory page");
                }
            } else if parts.len() == 3 {
                // A memory range instead
                if let Ok(start) = u16::from_str_radix(&parts[1].replace("0x", "")[..], 16) {
                    if let Ok(end) = u16::from_str_radix(&parts[2].replace("0x", "")[..], 16) {
                        self.dump_memory_range(start, end);
                    } else {
                        self.console.println("ERR: Unable to parse end address value");
                    }
                } else {
                    self.console.println("ERR: Unable to parse start address value");
                }
            }
        } else if parts[0] == "registers" || parts[0] == "reg" {
            self.dump_registers();
        } else if parts[0] == "break" || parts[0] == "b" {
            // 1 argument assumes 1 memory "page"
            if parts.len() == 2 {
                if let Ok(addr) = usize::from_str_radix(&parts[1][..], 16) {
                    if addr <= u16::max_value() as usize {
                        if self.breakpoints[addr] > 0 {
                            self.console.println(format!("Removed breakpoint at {:04X}", addr));
                            self.breakpoints[addr] = 0;
                        } else {
                            self.console.println(format!("Added breakpoint at {:04X}", addr));
                            self.breakpoints[addr] = 1;
                        }
                    } else {
                        self.console.println("ERR: Value outside addressable range.");
                    }
                } else {
                    self.broken = true;
                    println!("Execution stopped");
                }
            } else {
                self.console.println("ERR: Requires 1 argument");
            }
        } else if parts[0] == "continue" || parts[0] == "c" {
            self.broken = false;
            self.console.println("Execution resumed");
        } else if parts[0] == "step" || parts[0] == "s" {
            self.broken = true;
            self.step = true;
        } else {
            self.console.println("Unknown command");
        }

        // Don't assign a blank command as a last command
        if input.len() > 0 {
            self.last_command = input.clone();
        }
    }

    fn enable_memory_monitor(&mut self, input: &str) {
        let parts: Vec<&str> = input.split(" ").collect();
        if parts.len() < 3 {
            self.console.println("ERR: Requires 2 arguments. Example: monitor 0x00 0xFF");
        } else {
            let start = usize::from_str_radix(&parts[1].replace("0x", "")[..], 16).unwrap();
            let end = usize::from_str_radix(&parts[2].replace("0x", "")[..], 16).unwrap();

            self.monitor.start_addr = start;
            self.monitor.end_addr = end;
            self.monitor.enabled = true;
        }
    }

    fn dump_disassembly(&mut self) {
        self.console.println("");

        for segment in &self.segments {
            self.console.println(format!(".ORG ${:04X}", segment.address));
            let disassembler = Disassembler::with_offset(segment.address);
            let pairs = disassembler.disassemble_with_addresses(&segment.code);
            for line in self.highlight_lines(self.cpu.registers.PC as usize,
                                             pairs,
                                             segment.address,
                                             false) {
                self.console.println(format!("{}", line));
            }
            self.console.println("");
        }
    }

    fn dump_local_disassembly(&mut self) {
        self.console.println("");

        let result = {
            let pc = self.cpu.registers.PC as usize;
            let local_segment = self.get_local_segment(pc);
            let disassembler = Disassembler::with_offset(local_segment.address);
            let pairs = disassembler.disassemble_with_addresses(&local_segment.code);
            self.highlight_lines(pc, pairs, local_segment.address, true)
        };
        for line in result {
            self.console.println(format!("{}", line));
        }
        self.console.println("");
    }

    pub fn dump_memory_page(&mut self, page: usize) {
        let mut addr = page * 0x100;
        for chunk in self.cpu.memory[page * 0x100..(page * 0x100) + 0x100].chunks(8) {
            self.console.print(format!("{:04X}: ", addr));
            for b in chunk {
                self.console.print(format!("{:02X} ", *b));
            }
            self.console.wrap_line();
            addr += 0x08;
        }
    }

    pub fn dump_memory(&mut self) {
        self.console.println("");
        for chunk in self.cpu.memory[self.monitor.start_addr..self.monitor.end_addr + 0x01]
            .chunks(8) {
            for b in chunk {
                self.console.print(format!("{:02X} ", *b));
            }
            self.console.println("");
        }
    }

    fn dump_memory_range(&mut self, start: u16, end: u16) {
        self.console.println("");
        let start = start as usize;
        let end = end as usize;
        for chunk in self.cpu.memory[start..end + 0x01].chunks(8) {
            for b in chunk {
                self.console.print(format!("{:02X} ", *b));
            }
            self.console.println("");
        }
    }

    fn dump_registers(&mut self) {
        self.console.println("");
        self.console.println(format!("A: {} ({:04X})", self.cpu.registers.A, self.cpu.registers.A));
        self.console.println(format!("X: {} ({:04X})", self.cpu.registers.X, self.cpu.registers.X));
        self.console.println(format!("Y: {} ({:04X})", self.cpu.registers.Y, self.cpu.registers.Y));
        self.console.println(format!("PC: {} ({:04X})",
                                     self.cpu.registers.PC,
                                     self.cpu.registers.PC));
        self.console.println(format!("S: {} ({:04X})",
                                     self.cpu.stack.pointer,
                                     self.cpu.stack.pointer));
    }

    fn get_local_segment(&self, pc: usize) -> &CodeSegment {
        for segment in &self.segments {
            let addr = segment.address as usize;
            if pc >= addr && pc <= addr + segment.code.len() {
                return segment;
            }
        }

        &self.segments[0]
    }

    fn highlight_lines(&self,
                       pc: usize,
                       pairs: Vec<(String, u16)>,
                       segment_start: u16,
                       limit_results: bool)
                       -> Vec<String> {
        let mut result = Vec::new();

        let base = pc as isize - segment_start as isize;

        for pair in pairs {
            if limit_results {
                let start = if base > 0x0A { base - 0x0A } else { 0 };
                if (pair.1 as isize) < start || (pair.1 as isize) > base + 0x0A {
                    continue;
                }
            }
            let current_line = pc as u16 == segment_start + pair.1;
            let breakpoint = self.breakpoints[segment_start as usize + pair.1 as usize] > 0x00;

            if breakpoint && current_line {
                result.push(format!("> * {}", pair.0));
            } else if breakpoint && !current_line {
                result.push(format!("  * {}", pair.0));
            } else if !breakpoint && current_line {
                result.push(format!(">   {}", pair.0));
            } else {
                result.push(format!("    {}", pair.0));
            }
        }

        result
    }
}
<|endoftext|>


<commit_before><commit_msg>Added first method to insert in db<commit_after>use diesel;
use diesel::prelude::*;
use schema::tasks;
use diesel::pg::PgConnection;
use models::task::{Task};

#[derive(Insertable)]
#[table("tasks")]
struct NewTask<'a> {
     title: &'a str,
     body: &'a str,
     done: &'a bool,
}

pub fn create (
    conn: &PgConnection,
    title: &str,
    body: &str,
    done: &bool,
    ) -> ArticleJson  {
    let new_task = &NewTask {
        title,
        body,
        done,
    };

    diesel::insert_into(tasks::table).values(new_task).get_result::<Task>(conn).expect("Error creating task");
    // TODO return json
}

<|endoftext|>


<commit_before>use std::str::FromStr;

extern crate adventutils;

struct Present {
    length: u64,
    width: u64,
    height: u64
}

fn main() {
    // Load the input file
    let content = adventutils::read_input_file();

    // Load the input data
    let presents = eval(&content);

    // Fold to create result
    let result = presents.iter().fold(0, process_present);
    println!("The elves need {} sqft of wrapping paper!", result);
}

fn process_present(acc: u64, pres: &Present) -> u64 {
    let sides = [
        (pres.length * pres.width),
        (pres.width * pres.height),
        (pres.height * pres.length)];
    let extra = sides.iter().min().unwrap();

    acc + sides.iter().fold(0, |acc, side| acc + (2 * side)) + extra
}

fn eval(input: &str) -> Vec<Present> {
    input.lines().map(|line| {
        let mut splat = line.split('x');
        Present {
            length: FromStr::from_str(splat.next().unwrap()).unwrap(),
            width: FromStr::from_str(splat.next().unwrap()).unwrap(),
            height: FromStr::from_str(splat.next().unwrap()).unwrap()
        }
    }).collect()
}
<commit_msg>add day2 part2<commit_after>use std::str::FromStr;

extern crate adventutils;

struct Present {
    length: u64,
    width: u64,
    height: u64
}

fn main() {
    // Load the input file
    let content = adventutils::read_input_file();

    // Load the input data
    let presents = eval(&content);

    // Fold to create result
    let (paper, ribbon) = presents.iter().fold((0, 0), process_present);
    println!("The elves need {} sqft of wrapping paper and {} feet of ribbon!", paper, ribbon);
}

fn process_present((paper, ribbon): (u64, u64), pres: &Present) -> (u64, u64) {
    let sides = [
        (pres.length * pres.width),
        (pres.width * pres.height),
        (pres.height * pres.length)];
    let extra = sides.iter().min().unwrap();

    let paper = paper +
        sides.iter().fold(0, |acc, side| acc + (2 * side)) +
        extra;

    // Find the smallest two sides
    let mut dims = [pres.length, pres.width, pres.height];
    dims.sort();

    let bow = pres.length * pres.width * pres.height;

    let ribbon = ribbon + bow +
        dims[0] + dims[0] +
        dims[1] + dims[1];

    (paper, ribbon)
}

fn eval(input: &str) -> Vec<Present> {
    input.lines().map(|line| {
        let mut splat = line.split('x');
        Present {
            length: FromStr::from_str(splat.next().unwrap()).unwrap(),
            width: FromStr::from_str(splat.next().unwrap()).unwrap(),
            height: FromStr::from_str(splat.next().unwrap()).unwrap()
        }
    }).collect()
}
<|endoftext|>


<commit_before>use uci::SetOption;
use board::*;
use search_executor::*;
use pv::*;

pub trait TimeManager: SetOption {
    /// Creates a new instance.
    ///
    /// `position` gives the current position. `wtime_millis`,
    /// `btime_millis`, `winc_millis`, and `binc_millis` specify the
    /// remaining time in milliseconds, and the number of milliseconds
    /// with which the remaining time will be incremented on each move
    /// (for black and white). `movestogo` specifies the number of
    /// moves to the next time control.
    fn new(board: &Board,
           wtime_millis: Option<u64>,
           btime_millis: Option<u64>,
           winc_millis: Option<u64>,
           binc_millis: Option<u64>,
           movestogo: Option<u64>)
           -> Self;

    /// Registers a new search report with the time manager.
    fn update(&mut self, report: &SearchReport<Vec<Variation>>);

    /// Decides if the search must be terminated.
    fn must_play(&self) -> bool;
}
<commit_msg>add docs<commit_after>//! Defines the `TimeManager` trait.

use uci::SetOption;
use board::*;
use search_executor::*;
use pv::*;

/// A trait for deciding when the search must be terminated and the
/// best move played.
pub trait TimeManager: SetOption {
    /// Creates a new instance.
    ///
    /// * `board` gives the current position.
    ///
    /// * `wtime_millis` and `btime_millis` specify the remaining time
    ///   in milliseconds for white and black.
    ///
    /// * `winc_millis` and `binc_millis` specify the number of
    ///   milliseconds with which the remaining time will be
    ///   incremented on each move for white and black.
    ///
    /// * `movestogo` specifies the number of moves to the next time
    ///   control.
    fn new(board: &Board,
           wtime_millis: Option<u64>,
           btime_millis: Option<u64>,
           winc_millis: Option<u64>,
           binc_millis: Option<u64>,
           movestogo: Option<u64>)
           -> Self;

    /// Registers a new search report with the time manager.
    fn update(&mut self, report: &SearchReport<Vec<Variation>>);

    /// Decides whether the search must be terminated and the best
    /// move played.
    fn must_play(&self) -> bool;
}
<|endoftext|>


<commit_before>use super::{Null, Value, ValueRef};
use Result;

/// `ToSqlOutput` represents the possible output types for implementors of the `ToSql` trait.
#[derive(Clone,Debug,PartialEq)]
pub enum ToSqlOutput<'a> {
    /// A borrowed SQLite-representable value.
    Borrowed(ValueRef<'a>),

    /// An owned SQLite-representable value.
    Owned(Value),

    /// A BLOB of the given length that is filled with zeroes.
    #[cfg(feature = "blob")]
    ZeroBlob(i32),
}

impl<'a, T: ?Sized> From<&'a T> for ToSqlOutput<'a>
    where &'a T: Into<ValueRef<'a>>
{
    fn from(t: &'a T) -> Self {
        ToSqlOutput::Borrowed(t.into())
    }
}

impl<'a, T: Into<Value>> From<T> for ToSqlOutput<'a> {
    fn from(t: T) -> Self {
        ToSqlOutput::Owned(t.into())
    }
}

impl<'a> ToSql for ToSqlOutput<'a> {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(match *self {
               ToSqlOutput::Borrowed(v) => ToSqlOutput::Borrowed(v),
               ToSqlOutput::Owned(ref v) => ToSqlOutput::Borrowed(ValueRef::from(v)),

               #[cfg(feature = "blob")]
            ToSqlOutput::ZeroBlob(i) => ToSqlOutput::ZeroBlob(i),
           })
    }
}

/// A trait for types that can be converted into SQLite values.
pub trait ToSql {
    fn to_sql(&self) -> Result<ToSqlOutput>;
}

// We should be able to use a generic impl like this:
//
// impl<T: Copy> ToSql for T where T: Into<Value> {
//     fn to_sql(&self) -> Result<ToSqlOutput> {
//         Ok(ToSqlOutput::from((*self).into()))
//     }
// }
//
// instead of the following macro, but this runs afoul of
// https://github.com/rust-lang/rust/issues/30191 and reports conflicting
// implementations even when there aren't any.

macro_rules! to_sql_self(
    ($t:ty) => (
        impl ToSql for $t {
            fn to_sql(&self) -> Result<ToSqlOutput> {
                Ok(ToSqlOutput::from(*self))
            }
        }
    )
);

to_sql_self!(Null);
to_sql_self!(bool);
to_sql_self!(i8);
to_sql_self!(i16);
to_sql_self!(i32);
to_sql_self!(i64);
to_sql_self!(isize);
to_sql_self!(u8);
to_sql_self!(u16);
to_sql_self!(u32);
to_sql_self!(f64);

impl<'a, T: ?Sized> ToSql for &'a T
    where &'a T: Into<ToSqlOutput<'a>>
{
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from((*self).into()))
    }
}

impl ToSql for String {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self.as_str()))
    }
}

impl ToSql for Vec<u8> {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self.as_slice()))
    }
}

impl ToSql for Value {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self))
    }
}

impl<T: ToSql> ToSql for Option<T> {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        match *self {
            None => Ok(ToSqlOutput::from(Null)),
            Some(ref t) => t.to_sql(),
        }
    }
}

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

    fn is_to_sql<T: ToSql>() {}

    #[test]
    fn test_integral_types() {
        is_to_sql::<i8>();
        is_to_sql::<i16>();
        is_to_sql::<i32>();
        is_to_sql::<i64>();
        is_to_sql::<u8>();
        is_to_sql::<u16>();
        is_to_sql::<u32>();
    }
}
<commit_msg>Add ToSql impls for str and [u8].<commit_after>use super::{Null, Value, ValueRef};
use Result;

/// `ToSqlOutput` represents the possible output types for implementors of the `ToSql` trait.
#[derive(Clone,Debug,PartialEq)]
pub enum ToSqlOutput<'a> {
    /// A borrowed SQLite-representable value.
    Borrowed(ValueRef<'a>),

    /// An owned SQLite-representable value.
    Owned(Value),

    /// A BLOB of the given length that is filled with zeroes.
    #[cfg(feature = "blob")]
    ZeroBlob(i32),
}

impl<'a, T: ?Sized> From<&'a T> for ToSqlOutput<'a>
    where &'a T: Into<ValueRef<'a>>
{
    fn from(t: &'a T) -> Self {
        ToSqlOutput::Borrowed(t.into())
    }
}

impl<'a, T: Into<Value>> From<T> for ToSqlOutput<'a> {
    fn from(t: T) -> Self {
        ToSqlOutput::Owned(t.into())
    }
}

impl<'a> ToSql for ToSqlOutput<'a> {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(match *self {
               ToSqlOutput::Borrowed(v) => ToSqlOutput::Borrowed(v),
               ToSqlOutput::Owned(ref v) => ToSqlOutput::Borrowed(ValueRef::from(v)),

               #[cfg(feature = "blob")]
            ToSqlOutput::ZeroBlob(i) => ToSqlOutput::ZeroBlob(i),
           })
    }
}

/// A trait for types that can be converted into SQLite values.
pub trait ToSql {
    fn to_sql(&self) -> Result<ToSqlOutput>;
}

// We should be able to use a generic impl like this:
//
// impl<T: Copy> ToSql for T where T: Into<Value> {
//     fn to_sql(&self) -> Result<ToSqlOutput> {
//         Ok(ToSqlOutput::from((*self).into()))
//     }
// }
//
// instead of the following macro, but this runs afoul of
// https://github.com/rust-lang/rust/issues/30191 and reports conflicting
// implementations even when there aren't any.

macro_rules! to_sql_self(
    ($t:ty) => (
        impl ToSql for $t {
            fn to_sql(&self) -> Result<ToSqlOutput> {
                Ok(ToSqlOutput::from(*self))
            }
        }
    )
);

to_sql_self!(Null);
to_sql_self!(bool);
to_sql_self!(i8);
to_sql_self!(i16);
to_sql_self!(i32);
to_sql_self!(i64);
to_sql_self!(isize);
to_sql_self!(u8);
to_sql_self!(u16);
to_sql_self!(u32);
to_sql_self!(f64);

impl<'a, T: ?Sized> ToSql for &'a T
    where &'a T: Into<ToSqlOutput<'a>>
{
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from((*self).into()))
    }
}

impl ToSql for String {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self.as_str()))
    }
}

impl ToSql for str {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self))
    }
}

impl ToSql for Vec<u8> {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self.as_slice()))
    }
}

impl ToSql for [u8] {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self))
    }
}

impl ToSql for Value {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        Ok(ToSqlOutput::from(self))
    }
}

impl<T: ToSql> ToSql for Option<T> {
    fn to_sql(&self) -> Result<ToSqlOutput> {
        match *self {
            None => Ok(ToSqlOutput::from(Null)),
            Some(ref t) => t.to_sql(),
        }
    }
}

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

    fn is_to_sql<T: ToSql>() {}

    #[test]
    fn test_integral_types() {
        is_to_sql::<i8>();
        is_to_sql::<i16>();
        is_to_sql::<i32>();
        is_to_sql::<i64>();
        is_to_sql::<u8>();
        is_to_sql::<u16>();
        is_to_sql::<u32>();
    }
}
<|endoftext|>


<commit_before>use std::{
    collections::HashMap,
    sync::{atomic::Ordering, Arc},
    time::Duration,
};

use smithay::{
    desktop::WindowSurfaceType,
    reexports::{
        calloop::{
            channel::{Channel, Event as ChannelEvent},
            EventLoop,
        },
        wayland_server::{
            protocol::{wl_output, wl_pointer, wl_surface},
            Client, Display, Resource,
        },
    },
    utils::IsAlive,
    wayland::{
        input_method::InputMethodSeat,
        output::{Mode, Output, PhysicalProperties},
        seat::{ButtonEvent, CursorImageStatus, MotionEvent},
        SERIAL_COUNTER as SCOUNTER,
    },
};

use anvil::{
    drawing::{draw_cursor, draw_dnd_icon, draw_input_popup_surface},
    render::render_output,
    state::Backend,
    AnvilState, CalloopData, ClientState,
};

use crate::WlcsEvent;

pub const OUTPUT_NAME: &str = "anvil";

struct TestState {
    clients: HashMap<i32, Client>,
}

impl Backend for TestState {
    fn seat_name(&self) -> String {
        "anvil_wlcs".into()
    }

    fn reset_buffers(&mut self, _output: &Output) {}
    fn early_import(&mut self, _surface: &wl_surface::WlSurface) {}
}

pub fn run(channel: Channel<WlcsEvent>) {
    let mut event_loop =
        EventLoop::<CalloopData<TestState>>::try_new().expect("Failed to init the event loop.");

    let mut display = Display::new().expect("Failed to init display");
    let dh = display.handle();

    let logger = slog::Logger::root(slog::Discard, slog::o!());

    let test_state = TestState {
        clients: HashMap::new(),
    };

    let mut state = AnvilState::init(
        &mut display,
        event_loop.handle(),
        test_state,
        logger.clone(),
        false,
    );

    event_loop
        .handle()
        .insert_source(channel, move |event, &mut (), data| match event {
            ChannelEvent::Msg(evt) => handle_event(evt, &mut data.state, &mut data.display),
            ChannelEvent::Closed => handle_event(WlcsEvent::Exit, &mut data.state, &mut data.display),
        })
        .unwrap();

    let mut renderer = crate::renderer::DummyRenderer::new();

    let mode = Mode {
        size: (800, 600).into(),
        refresh: 60_000,
    };

    let output = Output::new(
        OUTPUT_NAME.to_string(),
        PhysicalProperties {
            size: (0, 0).into(),
            subpixel: wl_output::Subpixel::Unknown,
            make: "Smithay".into(),
            model: "WLCS".into(),
        },
        logger.clone(),
    );
    let _global = output.create_global::<AnvilState<TestState>>(&dh);
    output.change_current_state(Some(mode), None, None, Some((0, 0).into()));
    output.set_preferred(mode);
    state.space.map_output(&output, (0, 0));

    while state.running.load(Ordering::SeqCst) {
        // pretend to draw something
        {
            let mut elements = Vec::new();
            let mut cursor_guard = state.cursor_status.lock().unwrap();

            // draw the dnd icon if any
            if let Some(surface) = state.dnd_icon.as_ref() {
                if surface.alive() {
                    elements.push(draw_dnd_icon(
                        surface.clone(),
                        state.pointer_location.to_i32_round(),
                        &logger,
                    ));
                }
            }

            // draw input method square if any
            let input_method = state.seat.input_method().unwrap();
            let rectangle = input_method.coordinates();
            input_method.with_surface(|surface| {
                elements.push(
                    draw_input_popup_surface(
                        surface.clone(),
                        (
                            rectangle.loc.x + rectangle.size.w,
                            (rectangle.loc.y + rectangle.size.h),
                        ),
                    )
                    .into(),
                );
            });

            // draw the cursor as relevant
            // reset the cursor if the surface is no longer alive
            let mut reset = false;
            if let CursorImageStatus::Image(ref surface) = *cursor_guard {
                reset = !surface.alive();
            }
            if reset {
                *cursor_guard = CursorImageStatus::Default;
            }
            if let CursorImageStatus::Image(ref surface) = *cursor_guard {
                elements.push(draw_cursor(
                    surface.clone(),
                    state.pointer_location.to_i32_round(),
                    &logger,
                ));
            }

            let _ = render_output(&output, &mut state.space, &mut renderer, 0, &*elements, &logger);
        }

        // Send frame events so that client start drawing their next frame
        state
            .space
            .send_frames(state.start_time.elapsed().as_millis() as u32);

        let mut calloop_data = CalloopData { state, display };
        let result = event_loop.dispatch(Some(Duration::from_millis(16)), &mut calloop_data);
        CalloopData { state, display } = calloop_data;

        if result.is_err() {
            state.running.store(false, Ordering::SeqCst);
        } else {
            state.space.refresh(&display.handle());
            state.popups.cleanup();
            display.flush_clients().unwrap();
        }
    }
}

fn handle_event(
    event: WlcsEvent,
    state: &mut AnvilState<TestState>,
    display: &mut Display<AnvilState<TestState>>,
) {
    match event {
        WlcsEvent::Exit => state.running.store(false, Ordering::SeqCst),
        WlcsEvent::NewClient { stream, client_id } => {
            let client = display
                .handle()
                .insert_client(stream, Arc::new(ClientState::default()))
                .expect("Failed to insert client");
            state.backend_data.clients.insert(client_id, client);
        }
        WlcsEvent::PositionWindow {
            client_id,
            surface_id,
            location,
        } => {
            // find the surface
            let client = state.backend_data.clients.get(&client_id);
            let toplevel = state.space.windows().find(|w| {
                let surface = w.toplevel().wl_surface();
                display.handle().get_client(surface.id()).ok().as_ref() == client
                    && surface.id().protocol_id() == surface_id
            });
            if let Some(toplevel) = toplevel.cloned() {
                // set its location
                state.space.map_window(&toplevel, location, None, false);
            }
        }
        // pointer inputs
        WlcsEvent::NewPointer { .. } => {}
        WlcsEvent::PointerMoveAbsolute { location, .. } => {
            state.pointer_location = location;
            let serial = SCOUNTER.next_serial();
            let under = state.surface_under();
            let time = state.start_time.elapsed().as_millis() as u32;
            state.seat.get_pointer().unwrap().motion(
                state,
                &display.handle(),
                &MotionEvent {
                    location,
                    focus: under,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerMoveRelative { delta, .. } => {
            state.pointer_location += delta;
            let serial = SCOUNTER.next_serial();
            let under = state.surface_under();
            let time = state.start_time.elapsed().as_millis() as u32;
            state.seat.get_pointer().unwrap().motion(
                state,
                &display.handle(),
                &MotionEvent {
                    location: state.pointer_location,
                    focus: under,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerButtonDown { button_id, .. } => {
            let serial = SCOUNTER.next_serial();
            let pointer = state.seat.get_pointer().unwrap();
            if !pointer.is_grabbed() {
                let under = state
                    .space
                    .surface_under(pointer.current_location(), WindowSurfaceType::ALL)
                    .map(|(window, surface, _)| (window, surface));
                if let Some((window, _)) = under.as_ref() {
                    state.space.raise_window(window, true);
                }
                state.seat.get_keyboard().unwrap().set_focus(
                    &display.handle(),
                    under.as_ref().map(|&(ref w, _)| w.toplevel().wl_surface()),
                    serial,
                );
            }
            let time = state.start_time.elapsed().as_millis() as u32;
            pointer.button(
                state,
                &display.handle(),
                &ButtonEvent {
                    button: button_id as u32,
                    state: wl_pointer::ButtonState::Pressed,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerButtonUp { button_id, .. } => {
            let serial = SCOUNTER.next_serial();
            let time = state.start_time.elapsed().as_millis() as u32;
            state.seat.get_pointer().unwrap().button(
                state,
                &display.handle(),
                &ButtonEvent {
                    button: button_id as u32,
                    state: wl_pointer::ButtonState::Released,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerRemoved { .. } => {}
        // touch inputs
        WlcsEvent::NewTouch { .. } => {}
        WlcsEvent::TouchDown { .. } => {}
        WlcsEvent::TouchMove { .. } => {}
        WlcsEvent::TouchUp { .. } => {}
        WlcsEvent::TouchRemoved { .. } => {}
    }
}
<commit_msg>wlcs_anvil: Update for input-split<commit_after>use std::{
    collections::HashMap,
    sync::{atomic::Ordering, Arc},
    time::Duration,
};

use smithay::{
    backend::input::ButtonState,
    desktop::WindowSurfaceType,
    input::pointer::{ButtonEvent, CursorImageStatus, MotionEvent},
    reexports::{
        calloop::{
            channel::{Channel, Event as ChannelEvent},
            EventLoop,
        },
        wayland_server::{
            protocol::{wl_output, wl_surface},
            Client, Display, Resource,
        },
    },
    utils::{IsAlive, SERIAL_COUNTER as SCOUNTER},
    wayland::{
        input_method::InputMethodSeat,
        output::{Mode, Output, PhysicalProperties},
        seat::{ButtonEvent, CursorImageStatus, MotionEvent},
    },
};

use anvil::{
    drawing::{draw_cursor, draw_dnd_icon, draw_input_popup_surface},
    render::render_output,
    state::Backend,
    AnvilState, CalloopData, ClientState,
};

use crate::WlcsEvent;

pub const OUTPUT_NAME: &str = "anvil";

struct TestState {
    clients: HashMap<i32, Client>,
}

impl Backend for TestState {
    fn seat_name(&self) -> String {
        "anvil_wlcs".into()
    }

    fn reset_buffers(&mut self, _output: &Output) {}
    fn early_import(&mut self, _surface: &wl_surface::WlSurface) {}
}

pub fn run(channel: Channel<WlcsEvent>) {
    let mut event_loop =
        EventLoop::<CalloopData<TestState>>::try_new().expect("Failed to init the event loop.");

    let mut display = Display::new().expect("Failed to init display");
    let dh = display.handle();

    let logger = slog::Logger::root(slog::Discard, slog::o!());

    let test_state = TestState {
        clients: HashMap::new(),
    };

    let mut state = AnvilState::init(
        &mut display,
        event_loop.handle(),
        test_state,
        logger.clone(),
        false,
    );

    event_loop
        .handle()
        .insert_source(channel, move |event, &mut (), data| match event {
            ChannelEvent::Msg(evt) => handle_event(evt, &mut data.state, &mut data.display),
            ChannelEvent::Closed => handle_event(WlcsEvent::Exit, &mut data.state, &mut data.display),
        })
        .unwrap();

    let mut renderer = crate::renderer::DummyRenderer::new();

    let mode = Mode {
        size: (800, 600).into(),
        refresh: 60_000,
    };

    let output = Output::new(
        OUTPUT_NAME.to_string(),
        PhysicalProperties {
            size: (0, 0).into(),
            subpixel: wl_output::Subpixel::Unknown,
            make: "Smithay".into(),
            model: "WLCS".into(),
        },
        logger.clone(),
    );
    let _global = output.create_global::<AnvilState<TestState>>(&dh);
    output.change_current_state(Some(mode), None, None, Some((0, 0).into()));
    output.set_preferred(mode);
    state.space.map_output(&output, (0, 0));

    while state.running.load(Ordering::SeqCst) {
        // pretend to draw something
        {
            let mut elements = Vec::new();
            let mut cursor_guard = state.cursor_status.lock().unwrap();

            // draw the dnd icon if any
            if let Some(surface) = state.dnd_icon.as_ref() {
                if surface.alive() {
                    elements.push(draw_dnd_icon(
                        surface.clone(),
                        state.pointer_location.to_i32_round(),
                        &logger,
                    ));
                }
            }

            // draw input method square if any
            let input_method = state.seat.input_method().unwrap();
            let rectangle = input_method.coordinates();
            input_method.with_surface(|surface| {
                elements.push(
                    draw_input_popup_surface(
                        surface.clone(),
                        (
                            rectangle.loc.x + rectangle.size.w,
                            (rectangle.loc.y + rectangle.size.h),
                        ),
                    )
                    .into(),
                );
            });

            // draw the cursor as relevant
            // reset the cursor if the surface is no longer alive
            let mut reset = false;
            if let CursorImageStatus::Surface(ref surface) = *cursor_guard {
                reset = !surface.alive();
            }
            if reset {
                *cursor_guard = CursorImageStatus::Default;
            }
            if let CursorImageStatus::Surface(ref surface) = *cursor_guard {
                elements.push(draw_cursor(
                    surface.clone(),
                    state.pointer_location.to_i32_round(),
                    &logger,
                ));
            }

            let _ = render_output(&output, &mut state.space, &mut renderer, 0, &*elements, &logger);
        }

        // Send frame events so that client start drawing their next frame
        state
            .space
            .send_frames(state.start_time.elapsed().as_millis() as u32);

        let mut calloop_data = CalloopData { state, display };
        let result = event_loop.dispatch(Some(Duration::from_millis(16)), &mut calloop_data);
        CalloopData { state, display } = calloop_data;

        if result.is_err() {
            state.running.store(false, Ordering::SeqCst);
        } else {
            state.space.refresh(&display.handle());
            state.popups.cleanup();
            display.flush_clients().unwrap();
        }
    }
}

fn handle_event(
    event: WlcsEvent,
    state: &mut AnvilState<TestState>,
    display: &mut Display<AnvilState<TestState>>,
) {
    match event {
        WlcsEvent::Exit => state.running.store(false, Ordering::SeqCst),
        WlcsEvent::NewClient { stream, client_id } => {
            let client = display
                .handle()
                .insert_client(stream, Arc::new(ClientState::default()))
                .expect("Failed to insert client");
            state.backend_data.clients.insert(client_id, client);
        }
        WlcsEvent::PositionWindow {
            client_id,
            surface_id,
            location,
        } => {
            // find the surface
            let client = state.backend_data.clients.get(&client_id);
            let toplevel = state.space.windows().find(|w| {
                let surface = w.toplevel().wl_surface();
                display.handle().get_client(surface.id()).ok().as_ref() == client
                    && surface.id().protocol_id() == surface_id
            });
            if let Some(toplevel) = toplevel.cloned() {
                // set its location
                state.space.map_window(&toplevel, location, None, false);
            }
        }
        // pointer inputs
        WlcsEvent::NewPointer { .. } => {}
        WlcsEvent::PointerMoveAbsolute { location, .. } => {
            state.pointer_location = location;
            let serial = SCOUNTER.next_serial();
            let under = state.surface_under();
            let time = state.start_time.elapsed().as_millis() as u32;
            state.seat.get_pointer().unwrap().motion(
                state,
                under,
                &MotionEvent {
                    location,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerMoveRelative { delta, .. } => {
            state.pointer_location += delta;
            let serial = SCOUNTER.next_serial();
            let under = state.surface_under();
            let time = state.start_time.elapsed().as_millis() as u32;
            state.seat.get_pointer().unwrap().motion(
                state,
                under,
                &MotionEvent {
                    location: state.pointer_location,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerButtonDown { button_id, .. } => {
            let serial = SCOUNTER.next_serial();
            let pointer = state.seat.get_pointer().unwrap();
            if !pointer.is_grabbed() {
                let under = state
                    .space
                    .surface_under(pointer.current_location(), WindowSurfaceType::ALL)
                    .map(|(window, surface, _)| (window, surface));
                if let Some((window, _)) = under.as_ref() {
                    state.space.raise_window(window, true);
                }
                state.seat.get_keyboard().unwrap().set_focus(
                    state,
                    under
                        .as_ref()
                        .map(|&(ref w, _)| w.toplevel().wl_surface().clone()),
                    serial,
                );
            }
            let time = state.start_time.elapsed().as_millis() as u32;
            pointer.button(
                state,
                &ButtonEvent {
                    button: button_id as u32,
                    state: ButtonState::Pressed,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerButtonUp { button_id, .. } => {
            let serial = SCOUNTER.next_serial();
            let time = state.start_time.elapsed().as_millis() as u32;
            state.seat.get_pointer().unwrap().button(
                state,
                &ButtonEvent {
                    button: button_id as u32,
                    state: ButtonState::Released,
                    serial,
                    time,
                },
            );
        }
        WlcsEvent::PointerRemoved { .. } => {}
        // touch inputs
        WlcsEvent::NewTouch { .. } => {}
        WlcsEvent::TouchDown { .. } => {}
        WlcsEvent::TouchMove { .. } => {}
        WlcsEvent::TouchUp { .. } => {}
        WlcsEvent::TouchRemoved { .. } => {}
    }
}
<|endoftext|>


<commit_before>use std::hash::{Hash, Hasher};
use std::string::String;

use uuid::Uuid;

use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;

#[derive(Clone)]
pub struct JsVar {
    pub binding: Option<String>,
    pub uuid: Uuid,
    pub t: JsType,
}

impl JsVar {
    pub fn new(t: JsType) -> JsVar {
        JsVar {
            binding: None,
            uuid: Uuid::new_v4(),
            t: t,
        }
    }

    pub fn bind(binding: &str, t: JsType) -> JsVar {
        JsVar {
            binding: Some(String::from(binding)),
            uuid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsVar {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsVar {}

#[derive(Clone)]
pub enum JsPtrEnum {
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
}

#[derive(Clone)]
pub enum JsType {
    JsUndef,
    JsNum(f64),
    JsBool(bool),
    JsPtr,
    JsNull,
}

impl PartialEq for JsType {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&JsType::JsUndef, &JsType::JsUndef) => true,
            (&JsType::JsNum(x), &JsType::JsNum(y)) => x == y,
            (&JsType::JsBool(b1), &JsType::JsBool(b2)) => b1 == b2,
            (&JsType::JsNull, &JsType::JsNull) => true,
            (_, _) => false,
        }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsType {}

#[derive(Clone)]
pub enum JsKeyEnum {
    JsNum(f64),
    JsBool(bool),
    JsStr(JsStrStruct),
    JsSym(String),
}

#[derive(Clone)]
pub struct JsKey {
    pub uuid: Uuid,
    pub k: JsKeyEnum,
}

impl JsKey {
    pub fn new(k: JsKeyEnum) -> JsKey {
        JsKey {
            uuid: Uuid::new_v4(),
            k: k,
        }
    }
}

impl PartialEq for JsKey {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsKey {}

impl Hash for JsKey {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uuid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uuid.hash(state);
        }
    }
}

// `array`
pub type JsArr = Vec<JsType>;
<commit_msg>Document why JsNull isn't a reference type<commit_after>use std::hash::{Hash, Hasher};
use std::string::String;

use uuid::Uuid;

use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;

#[derive(Clone)]
pub struct JsVar {
    pub binding: Option<String>,
    pub uuid: Uuid,
    pub t: JsType,
}

impl JsVar {
    pub fn new(t: JsType) -> JsVar {
        JsVar {
            binding: None,
            uuid: Uuid::new_v4(),
            t: t,
        }
    }

    pub fn bind(binding: &str, t: JsType) -> JsVar {
        JsVar {
            binding: Some(String::from(binding)),
            uuid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsVar {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsVar {}

#[derive(Clone)]
pub enum JsPtrEnum {
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
}

#[derive(Clone)]
pub enum JsType {
    JsUndef,
    JsNum(f64),
    JsBool(bool),
    JsPtr,
    JsNull, // null is not a ptr since it doesn't actually require allocation
}

impl PartialEq for JsType {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&JsType::JsUndef, &JsType::JsUndef) => true,
            (&JsType::JsNum(x), &JsType::JsNum(y)) => x == y,
            (&JsType::JsBool(b1), &JsType::JsBool(b2)) => b1 == b2,
            (&JsType::JsNull, &JsType::JsNull) => true,
            (_, _) => false,
        }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsType {}

#[derive(Clone)]
pub enum JsKeyEnum {
    JsNum(f64),
    JsBool(bool),
    JsStr(JsStrStruct),
    JsSym(String),
}

#[derive(Clone)]
pub struct JsKey {
    pub uuid: Uuid,
    pub k: JsKeyEnum,
}

impl JsKey {
    pub fn new(k: JsKeyEnum) -> JsKey {
        JsKey {
            uuid: Uuid::new_v4(),
            k: k,
        }
    }
}

impl PartialEq for JsKey {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsKey {}

impl Hash for JsKey {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uuid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uuid.hash(state);
        }
    }
}

// `array`
pub type JsArr = Vec<JsType>;
<|endoftext|>