<commit_before>use programs::common::*;

pub struct Application {
    output: String,
    scroll: Point,
    wrap: bool
}

impl SessionItem for Application {
    fn main(&mut self, url: URL){
        let mut window = Window::new(Point::new((rand() % 400 + 50) as isize, (rand() % 300 + 50) as isize), Size::new(576, 400), "HTTP Server".to_string());

        macro_rules! println {
            ($text:expr) => ({
                self.output.vec.push_all(&$text.vec);
                self.output.vec.push('\n');
                self.draw_content(&mut window);
            });
        }

        println!("Starting HTTP Server".to_string());

        loop {
            let mut resource = URL::from_string(&"tcp:///80".to_string()).open();
            match resource.stat(){
                ResourceType::File => {
                    println!("Incoming stream from ".to_string() + resource.url().to_string());

                    let mut data: Vec<u8> = Vec::new();
                    resource.read_to_end(&mut data);
                    println!(String::from_utf8(&data));
                    resource.write("Test".to_string().to_utf8().as_slice());
                },
                _ => ()
            }

            match window.poll() {
                EventOption::Key(key_event) => {
                    if key_event.pressed{
                        if key_event.scancode == 1 {
                            break;
                        }
                    }
                },
                EventOption::None => sys_yield(),
                _ => ()
            }
        }

        println!("Closed HTTP Server".to_string());

        loop {
            match window.poll() {
                EventOption::Key(key_event) => {
                    if key_event.pressed{
                        if key_event.scancode == 1 {
                            break;
                        }
                    }
                },
                EventOption::None => sys_yield(),
                _ => ()
            }
        }
    }
}

impl Application {
    pub fn new() -> Application {
        return Application {
            output: String::new(),
            scroll: Point::new(0, 0),
            wrap: true
        };
    }

    fn draw_content(&mut self, window: &mut Window){
        let scroll = self.scroll;

        let mut col = -scroll.x;
        let cols = window.content.width as isize / 8;
        let mut row = -scroll.y;
        let rows = window.content.height as isize / 16;

        {
            let content = &window.content;
            content.set(Color::new(0, 0, 0));

            for c in self.output.chars(){
                if self.wrap && col >= cols {
                    col = -scroll.x;
                    row += 1;
                }

                if c == '\n' {
                    col = -scroll.x;
                    row += 1;
                }else if c == '\t' {
                    col += 8 - col % 8;
                }else{
                    if col >= 0 && col < cols && row >= 0 && row < rows{
                        content.char(Point::new(8 * col, 16 * row), c, Color::new(224, 224, 224));
                    }
                    col += 1;
                }
            }

            if col > -scroll.x {
                col = -scroll.x;
                row += 1;
            }

            if self.wrap && col >= cols {
                col = -scroll.x;
                row += 1;
            }

            content.flip();

            RedrawEvent {
                redraw: REDRAW_ALL
            }.to_event().trigger();
        }

        if row >= rows {
            self.scroll.y += row - rows + 1;

            self.draw_content(window);
        }
    }
}
<commit_msg>Add http response headers<commit_after>use programs::common::*;

pub struct Application {
    output: String,
    scroll: Point,
    wrap: bool
}

impl SessionItem for Application {
    fn main(&mut self, url: URL){
        let mut window = Window::new(Point::new((rand() % 400 + 50) as isize, (rand() % 300 + 50) as isize), Size::new(576, 400), "HTTP Server".to_string());

        macro_rules! println {
            ($text:expr) => ({
                self.output.vec.push_all(&$text.vec);
                self.output.vec.push('\n');
                self.draw_content(&mut window);
            });
        }

        println!("Starting HTTP Server".to_string());

        let html = "Test".to_string().to_utf8();

        let mut response = ("HTTP/1.1 200 OK\r\n".to_string()
                + "Content-Type: text/html; charset=UTF-8\r\n"
                + "Content-Length: " + html.len() + "\r\n"
                + "Connection: Close\r\n"
                + "\r\n").to_utf8();
        response.push_all(&html);

        loop {
            {
                let mut resource = URL::from_string(&"tcp:///80".to_string()).open();
                match resource.stat(){
                    ResourceType::File => {
                        println!("Incoming stream from ".to_string() + resource.url().to_string());

                        let mut data: Vec<u8> = Vec::new();
                        resource.read_to_end(&mut data);
                        println!(String::from_utf8(&data));
                        resource.write(response.as_slice());
                    },
                    _ => ()
                }
            }

            match window.poll() {
                EventOption::Key(key_event) => {
                    if key_event.pressed{
                        if key_event.scancode == 1 {
                            break;
                        }
                    }
                },
                EventOption::None => sys_yield(),
                _ => ()
            }
        }

        println!("Closed HTTP Server".to_string());

        loop {
            match window.poll() {
                EventOption::Key(key_event) => {
                    if key_event.pressed{
                        if key_event.scancode == 1 {
                            break;
                        }
                    }
                },
                EventOption::None => sys_yield(),
                _ => ()
            }
        }
    }
}

impl Application {
    pub fn new() -> Application {
        return Application {
            output: String::new(),
            scroll: Point::new(0, 0),
            wrap: true
        };
    }

    fn draw_content(&mut self, window: &mut Window){
        let scroll = self.scroll;

        let mut col = -scroll.x;
        let cols = window.content.width as isize / 8;
        let mut row = -scroll.y;
        let rows = window.content.height as isize / 16;

        {
            let content = &window.content;
            content.set(Color::new(0, 0, 0));

            for c in self.output.chars(){
                if self.wrap && col >= cols {
                    col = -scroll.x;
                    row += 1;
                }

                if c == '\n' {
                    col = -scroll.x;
                    row += 1;
                }else if c == '\t' {
                    col += 8 - col % 8;
                }else{
                    if col >= 0 && col < cols && row >= 0 && row < rows{
                        content.char(Point::new(8 * col, 16 * row), c, Color::new(224, 224, 224));
                    }
                    col += 1;
                }
            }

            if col > -scroll.x {
                col = -scroll.x;
                row += 1;
            }

            if self.wrap && col >= cols {
                col = -scroll.x;
                row += 1;
            }

            content.flip();

            RedrawEvent {
                redraw: REDRAW_ALL
            }.to_event().trigger();
        }

        if row >= rows {
            self.scroll.y += row - rows + 1;

            self.draw_content(window);
        }
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::iter::Peekable;
use std::fmt::{Show,Formatter};
use std::fmt;

pub struct TokenValue<'a> {
  token: Token,
  value: &'a str
}

/// Lexer
pub struct Lexer<'a> {
  line: int,
  column: int,
  pos: int,
  iter: Peekable<char, Chars<'a>>,
  curr_ch: Option<char>,
  done: bool
}

/// Lexer tokens.
pub enum Token {
  PLUS,
  MINUS,
  INTEGER, // Any type of integer
  IDEN, // Identifier
  LPAREN,
  RPAREN,
  COLON
}

impl<'a> TokenValue<'a> {
  pub fn new(tok: Token, val: &'a str) -> TokenValue<'a> {
    TokenValue {
      token: tok,
      value: val
    }
  }
}

impl Eq for Token {
  fn eq(&self, other: &Token) -> bool {
    match *self {
      PLUS => match *other { PLUS => true, _ => false },
      MINUS => match *other { MINUS => true, _ => false },
      INTEGER => match *other { INTEGER => true, _ => false },
      IDEN => match *other { IDEN => true, _ => false },
      LPAREN => match *other { LPAREN => true, _ => false },
      RPAREN => match *other { RPAREN => true, _ => false },
      COLON => match *other { COLON => true, _ => false }
    }
  }
}

impl Show for Token {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    let c = match *self {
      PLUS => &"+",
      MINUS => &"-",
      INTEGER => &"integer",
      IDEN => &"iden",
      LPAREN => &"(",
      RPAREN => &")",
      COLON => ":"
    };

    write!(f.buf, "({})", c)
  }
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Lexer<'a> {
    let it = input.chars().peekable();
    Lexer {
      line: 0,
      column: 0,
      pos: 0,
      iter: it,
      curr_ch: None,
      done: false
    }
  }

  pub fn bump(&mut self) {
    self.curr_ch = self.iter.next();
  }

  pub fn nextch_is(&mut self, ch: char) -> bool {
    self.bump();
    self.curr_ch.unwrap() == ch
  }

  pub fn peekch_is(&mut self, ch: char) -> bool {
    *self.iter.peek().unwrap() == ch
  }

  pub fn next_token(&mut self) -> Option<TokenValue<'a>> {

    for c in self.iter {
      match c {
        '(' => return Some(TokenValue::new(LPAREN, &"(")),
        ')' => return Some(TokenValue::new(RPAREN, &")")),
        '+' => return Some(TokenValue::new(PLUS, &"+")),
        '-' => return Some(TokenValue::new(MINUS, &"-")),
        ':' => return Some(TokenValue::new(COLON, &":")),
        '9' => return Some(TokenValue::new(INTEGER, &"9")),
        '8' => return Some(TokenValue::new(INTEGER, &"8")),
        '7' => return Some(TokenValue::new(INTEGER, &"7")),
        '6' => return Some(TokenValue::new(INTEGER, &"6")),
        '5' => return Some(TokenValue::new(INTEGER, &"5")),
        '4' => return Some(TokenValue::new(INTEGER, &"4")),
        '3' => return Some(TokenValue::new(INTEGER, &"3")),
        '2' => return Some(TokenValue::new(INTEGER, &"2")),
        '1' => return Some(TokenValue::new(INTEGER, &"1")),
        '0' => return Some(TokenValue::new(INTEGER, &"0")),
        _ => return None
      }
    }

    None
  }

}

#[cfg(test)]
mod test {
  use super::Lexer;
  use super::LPAREN;
  use super::TokenValue;

  #[test]
  fn bump() {
    let mut lex = Lexer::new(&"Hello World");
    lex.bump();
    assert_eq!(lex.curr_ch.unwrap(), 'H');
  }

  #[test]
  fn nextch() {
    let mut lex = Lexer::new(&"Woot");
    assert!(lex.nextch_is('W'));
  }

  #[test]
  fn peekable() {
    let mut lex = Lexer::new(&"Haha");
    lex.bump();
    assert!(lex.peekch_is('a'));
  }

  #[test]
  fn next_token() {
    // Should spit out two tokens (LPAREN,RPAREN)
    let mut lex = Lexer::new(&"()");
    assert!(lex.next_token().unwrap().value == &"("); //TokenValue::new(LPAREN, "("));
    assert!(lex.next_token().unwrap().value == &")");
  }

}<commit_msg>tests pass<commit_after>use std::str::Chars;
use std::iter::Peekable;
use std::fmt::{Show,Formatter};
use std::fmt;

pub struct TokenValue<'a> {
  token: Token,
  value: &'a str
}

/// Lexer
pub struct Lexer<'a> {
  line: int,
  column: int,
  pos: int,
  iter: Peekable<char, Chars<'a>>,
  curr_ch: Option<char>,
  done: bool
}

/// Lexer tokens.
pub enum Token {
  PLUS,
  MINUS,
  INTEGER, // Any type of integer
  IDEN, // Identifier
  LPAREN,
  RPAREN,
  COLON
}

impl<'a> TokenValue<'a> {
  pub fn new(tok: Token, val: &'a str) -> TokenValue<'a> {
    TokenValue {
      token: tok,
      value: val
    }
  }
}

impl Eq for Token {
  fn eq(&self, other: &Token) -> bool {
    match *self {
      PLUS => match *other { PLUS => true, _ => false },
      MINUS => match *other { MINUS => true, _ => false },
      INTEGER => match *other { INTEGER => true, _ => false },
      IDEN => match *other { IDEN => true, _ => false },
      LPAREN => match *other { LPAREN => true, _ => false },
      RPAREN => match *other { RPAREN => true, _ => false },
      COLON => match *other { COLON => true, _ => false }
    }
  }
}

impl Show for Token {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    let c = match *self {
      PLUS => &"+",
      MINUS => &"-",
      INTEGER => &"integer",
      IDEN => &"iden",
      LPAREN => &"(",
      RPAREN => &")",
      COLON => ":"
    };

    write!(f.buf, "({})", c)
  }
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Lexer<'a> {
    let it = input.chars().peekable();
    Lexer {
      line: 0,
      column: 0,
      pos: 0,
      iter: it,
      curr_ch: None,
      done: false
    }
  }

  pub fn bump(&mut self) {
    self.curr_ch = self.iter.next();
  }

  pub fn nextch_is(&mut self, ch: char) -> bool {
    self.bump();
    self.curr_ch.unwrap() == ch
  }

  pub fn peekch_is(&mut self, ch: char) -> bool {
    *self.iter.peek().unwrap() == ch
  }

  pub fn next_token(&mut self) -> Option<TokenValue<'a>> {

    for c in self.iter {
      match c {
        '(' => return Some(TokenValue::new(LPAREN, &"(")),
        ')' => return Some(TokenValue::new(RPAREN, &")")),
        '+' => return Some(TokenValue::new(PLUS, &"+")),
        '-' => return Some(TokenValue::new(MINUS, &"-")),
        ':' => return Some(TokenValue::new(COLON, &":")),
        '9' => return Some(TokenValue::new(INTEGER, &"9")),
        '8' => return Some(TokenValue::new(INTEGER, &"8")),
        '7' => return Some(TokenValue::new(INTEGER, &"7")),
        '6' => return Some(TokenValue::new(INTEGER, &"6")),
        '5' => return Some(TokenValue::new(INTEGER, &"5")),
        '4' => return Some(TokenValue::new(INTEGER, &"4")),
        '3' => return Some(TokenValue::new(INTEGER, &"3")),
        '2' => return Some(TokenValue::new(INTEGER, &"2")),
        '1' => return Some(TokenValue::new(INTEGER, &"1")),
        '0' => return Some(TokenValue::new(INTEGER, &"0")),
        _ => return None
      }
    }

    None
  }

}

#[cfg(test)]
mod test {
  use super::Lexer;
  use super::LPAREN;
  use super::TokenValue;

  #[test]
  fn bump() {
    let mut lex = Lexer::new(&"Hello World");
    lex.bump();
    assert_eq!(lex.curr_ch.unwrap(), 'H');
  }

  #[test]
  fn nextch() {
    let mut lex = Lexer::new(&"Woot");
    assert!(lex.nextch_is('W'));
  }

  #[test]
  fn peekable() {
    let mut lex = Lexer::new(&"Haha");
    lex.bump();
    assert!(lex.peekch_is('a'));
  }

  #[test]
  fn next_token() {
    // Should spit out two tokens (LPAREN,RPAREN)
    let mut lex = Lexer::new(&"()");
    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &")");
  }

  #[test]
  fn return_complex_tokens() {
    let mut lex = Lexer::new(&"(+(():830");

    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &"+");
    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &")");
    assert!(lex.next_token().unwrap().value == &":");
    assert!(lex.next_token().unwrap().value == &"8");
    assert!(lex.next_token().unwrap().value == &"3");
    assert!(lex.next_token().unwrap().value == &"0");
  }

}<|endoftext|>


<commit_before>#[cfg(not(feature = "fitsio-src"))]
fn bind_cfitsio() {
    use pkg_config::Error;
    use std::io::Write;

    let package_name = "cfitsio";
    match pkg_config::probe_library(package_name) {
        Ok(_) => {}
        Err(Error::Failure { output, .. }) => {
            // Handle the case where the user has not installed cfitsio, and thusly it is not on
            // the PKG_CONFIG_PATH
            let stderr = String::from_utf8(output.stderr).unwrap();
            if stderr.contains::<&str>(
                format!(
                    "{} was not found in the pkg-config search path",
                    package_name
                )
                .as_ref(),
            ) {
                let err_msg = format!(
                    "
Cannot find {} on the pkg-config search path.  Consider installing the library for your
system (e.g. through homebrew, apt-get etc.).  Alternatively if it is installed, then add
the directory that contains `cfitsio.pc` on your PKG_CONFIG_PATH, e.g.:

PKG_CONFIG_PATH=<blah> cargo build
",
                    package_name
                );
                std::io::stderr().write_all(err_msg.as_bytes()).unwrap();
                std::process::exit(output.status.code().unwrap());
            }
        }
        Err(e) => panic!("Unhandled error: {:?}", e),
    };
}

#[cfg(feature = "fitsio-src")]
fn bind_cfitsio() {
    use std::env::var;
    use std::path::PathBuf;

    let cfitsio_project_dir = PathBuf::from("ext/cfitsio");
    if !cfitsio_project_dir.exists() {
        panic!(
            "Expected to find cfitsio source directory {}",
            cfitsio_project_dir.display()
        );
    }
    // Make sure the source directory isn't empty.
    match std::fs::read_dir(&cfitsio_project_dir) {
        Ok(mut d) => {
            if let None = d.next() {
                panic!("cfitsio source directory ext/cfitsio is empty!");
            }
        }
        _ => panic!("Could not read from cfitsio source directory ext/cfitsio !"),
    }

    // Translate rustc optimisation levels to things a C compiler can
    // understand. I don't know if all C compilers agree here, but it should
    // at least work for gcc.
    let opt_level: String = match var("OPT_LEVEL").as_ref().map(|o| o.as_str()) {
        Err(_) => panic!("Something wrong with OPT_LEVEL"),
        // gcc doesn't handle 'z'. Just set it to 's', which also optimises
        // for size.
        Ok("z") => "s",
        Ok(o) => o,
    }
    .to_string();

    // Run the contigure script. I'd use the autotools crate here, but it
    // always outputs two of --{enable,disable}-{shared,static}, none of
    // which is supported by the cfitsio configure script! So, just run the
    // script manually.
    let dst = PathBuf::from(var("OUT_DIR").unwrap());

    std::process::Command::new("make")
        .arg("clean")
        .current_dir(&cfitsio_project_dir)
        .spawn()
        .expect("Couldn't run cfitsio make clean")
        .wait()
        .expect("Failed to wait on child");

    std::process::Command::new("sh")
        .args(&[
            "./configure",
            &format!("--prefix={}", dst.display()),
            // cfitsio should always be built with reentrant support.
            "--enable-reentrant",
        ])
        .env(
            "CFLAGS",
            &format!("-Wall -O{} -march=native -fPIE", opt_level),
        )
        .current_dir(&cfitsio_project_dir)
        .spawn()
        .expect("Couldn't run cfitsio configure script")
        .wait()
        .expect("Failed to wait on child");

    std::process::Command::new("make")
        .arg("-j")
        .arg("install")
        .current_dir(&cfitsio_project_dir)
        .spawn()
        .expect("Couldn't run cfitsio makefile")
        .wait()
        .expect("Failed to wait on child");

    println!("cargo:rustc-link-search=native={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=cfitsio");
}

fn main() {
    bind_cfitsio();
}
<commit_msg>Don't use curl when building from source.<commit_after>#[cfg(not(feature = "fitsio-src"))]
fn bind_cfitsio() {
    use pkg_config::Error;
    use std::io::Write;

    let package_name = "cfitsio";
    match pkg_config::probe_library(package_name) {
        Ok(_) => {}
        Err(Error::Failure { output, .. }) => {
            // Handle the case where the user has not installed cfitsio, and thusly it is not on
            // the PKG_CONFIG_PATH
            let stderr = String::from_utf8(output.stderr).unwrap();
            if stderr.contains::<&str>(
                format!(
                    "{} was not found in the pkg-config search path",
                    package_name
                )
                .as_ref(),
            ) {
                let err_msg = format!(
                    "
Cannot find {} on the pkg-config search path.  Consider installing the library for your
system (e.g. through homebrew, apt-get etc.).  Alternatively if it is installed, then add
the directory that contains `cfitsio.pc` on your PKG_CONFIG_PATH, e.g.:

PKG_CONFIG_PATH=<blah> cargo build
",
                    package_name
                );
                std::io::stderr().write_all(err_msg.as_bytes()).unwrap();
                std::process::exit(output.status.code().unwrap());
            }
        }
        Err(e) => panic!("Unhandled error: {:?}", e),
    };
}

#[cfg(feature = "fitsio-src")]
fn bind_cfitsio() {
    use std::env::var;
    use std::path::PathBuf;

    let cfitsio_project_dir = PathBuf::from("ext/cfitsio");
    if !cfitsio_project_dir.exists() {
        panic!(
            "Expected to find cfitsio source directory {}",
            cfitsio_project_dir.display()
        );
    }
    // Make sure the source directory isn't empty.
    match std::fs::read_dir(&cfitsio_project_dir) {
        Ok(mut d) => {
            if let None = d.next() {
                panic!("cfitsio source directory ext/cfitsio is empty!");
            }
        }
        _ => panic!("Could not read from cfitsio source directory ext/cfitsio !"),
    }

    // Translate rustc optimisation levels to things a C compiler can
    // understand. I don't know if all C compilers agree here, but it should
    // at least work for gcc.
    let opt_level: String = match var("OPT_LEVEL").as_ref().map(|o| o.as_str()) {
        Err(_) => panic!("Something wrong with OPT_LEVEL"),
        // gcc doesn't handle 'z'. Just set it to 's', which also optimises
        // for size.
        Ok("z") => "s",
        Ok(o) => o,
    }
    .to_string();

    // Run the contigure script. I'd use the autotools crate here, but it
    // always outputs two of --{enable,disable}-{shared,static}, none of
    // which is supported by the cfitsio configure script! So, just run the
    // script manually.
    let dst = PathBuf::from(var("OUT_DIR").unwrap());

    std::process::Command::new("make")
        .arg("clean")
        .current_dir(&cfitsio_project_dir)
        .spawn()
        .expect("Couldn't run cfitsio make clean")
        .wait()
        .expect("Failed to wait on child");

    std::process::Command::new("sh")
        .args(&[
            "./configure",
            &format!("--prefix={}", dst.display()),
            // cfitsio should always be built with reentrant support.
            "--enable-reentrant",
            // curl functionality is not used through rust-fitsio.
            "--disable-curl",
        ])
        .env(
            "CFLAGS",
            &format!("-Wall -O{} -march=native -fPIE", opt_level),
        )
        .current_dir(&cfitsio_project_dir)
        .spawn()
        .expect("Couldn't run cfitsio configure script")
        .wait()
        .expect("Failed to wait on child");

    std::process::Command::new("make")
        .arg("-j")
        .arg("install")
        .current_dir(&cfitsio_project_dir)
        .spawn()
        .expect("Couldn't run cfitsio makefile")
        .wait()
        .expect("Failed to wait on child");

    println!("cargo:rustc-link-search=native={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=cfitsio");
}

fn main() {
    bind_cfitsio();
}
<|endoftext|>


<commit_before>use std::io::fs;
use std::io::File;
use std::collections::HashMap;
use std::os;

fn examine_files(directory_path: &Path, map: &mut HashMap<(u64,u64), Box<String>>) {

    let entries = fs::readdir(directory_path);

    if !entries.is_ok() {
        return;
    }

    for entry in entries.unwrap().iter() {
        if entry.is_dir() {
            examine_files(entry, map);
        } else {
            let path = entry.as_str().unwrap();
            let stat = entry.stat();
            if stat.is_ok() {
                let unwrapped_stat = stat.unwrap();
                map.insert((unwrapped_stat.size, unwrapped_stat.modified), box path.to_string());
            }
        }
    }
}

fn compare_files(src_path: &Path, new_path: &Path) -> bool {
    let mut src_file = File::open(src_path);
    let mut new_file = File::open(new_path);
    let src_data = src_file.read_to_end();
    let new_data = new_file.read_to_end();

    src_data == new_data
}

fn main() {

    let args = os::args();

    if args.len() != 3 {
        println!("Usage: {} <original-directory> <new-directory>", args[0]);
        return;
    }

    let src_directory = Path::new(args[1].clone());
    let dst_directory = Path::new(args[2].clone());

    let mut src_map = HashMap::<(u64, u64), Box<String>>::new();
    examine_files(&src_directory, &mut src_map);
    let mut new_map = HashMap::<(u64, u64), Box<String>>::new();
    examine_files(&dst_directory, &mut new_map);
    for (key, value) in new_map.iter() {
        if src_map.contains_key(key) {
            let src_path = Path::new(*src_map.get(key).clone());
            let new_path = Path::new(*value.clone());
            if compare_files(&src_path, &new_path) {
                println!("{} was renamed to {}",
                         src_path.path_relative_from(&src_directory).unwrap().as_str().unwrap(),
                         new_path.path_relative_from(&dst_directory).unwrap().as_str().unwrap());
            }
        }
    }
}
<commit_msg>Remove unneeded boxing<commit_after>use std::io::fs;
use std::io::File;
use std::collections::HashMap;
use std::os;

fn examine_files(directory_path: &Path, map: &mut HashMap<(u64,u64), String>) {

    let entries = fs::readdir(directory_path);

    if !entries.is_ok() {
        return;
    }

    for entry in entries.unwrap().iter() {
        if entry.is_dir() {
            examine_files(entry, map);
        } else {
            let path = entry.as_str().unwrap();
            let stat = entry.stat();
            if stat.is_ok() {
                let unwrapped_stat = stat.unwrap();
                map.insert((unwrapped_stat.size, unwrapped_stat.modified), path.to_string());
            }
        }
    }
}

fn compare_files(src_path: &Path, new_path: &Path) -> bool {
    let mut src_file = File::open(src_path);
    let mut new_file = File::open(new_path);
    let src_data = src_file.read_to_end();
    let new_data = new_file.read_to_end();

    src_data == new_data
}

fn main() {

    let args = os::args();

    if args.len() != 3 {
        println!("Usage: {} <original-directory> <new-directory>", args[0]);
        return;
    }

    let src_directory = Path::new(args[1].clone());
    let dst_directory = Path::new(args[2].clone());

    let mut src_map = HashMap::<(u64, u64), String>::new();
    examine_files(&src_directory, &mut src_map);
    let mut new_map = HashMap::<(u64, u64), String>::new();
    examine_files(&dst_directory, &mut new_map);
    for (key, value) in new_map.iter() {
        if src_map.contains_key(key) {
            let src_path = Path::new(src_map.get(key).clone());
            let new_path = Path::new(value.clone());
            if compare_files(&src_path, &new_path) {
                println!("{} was renamed to {}",
                         src_path.path_relative_from(&src_directory).unwrap().as_str().unwrap(),
                         new_path.path_relative_from(&dst_directory).unwrap().as_str().unwrap());
            }
        }
    }
}
<|endoftext|>


<commit_before>use handle::Owned;
use raw;
use raw::{ SSize_t };
use SV;

pub struct AV(Owned<raw::AV>);

impl AV {
    pub unsafe fn from_raw_owned(pthx: raw::Interpreter, raw: *mut raw::AV) -> AV {
        AV(Owned::from_raw_owned(pthx, raw))
    }

    pub unsafe fn from_raw_borrowed(pthx: raw::Interpreter, raw: *mut raw::AV) -> AV {
        AV(Owned::from_raw_borrowed(pthx, raw))
    }

    fn pthx(&self) -> raw::Interpreter { self.0.pthx() }

    fn as_ptr(&self) -> *mut raw::AV { self.0.as_ptr() }

    method! { simple fn clear() = av_clear() }
    method! { getter fn delete(key: SSize_t) = av_delete(key, 0) }
    method! { simple fn discard(key: SSize_t) = av_delete(key, raw::G_DISCARD as raw::I32) }
    method! { simple fn exists(key: SSize_t) -> bool = av_exists(key) != 0 }
    method! { simple fn extend(key: SSize_t) = av_extend(key) }
    method! { getptr fn fetch(key: SSize_t) = av_fetch(key, 0) }
    method! { getptr fn fetch_lvalue(key: SSize_t) = av_fetch(key, 1) }
    method! { simple fn fill(fill: SSize_t) = av_fill(fill) }
    method! { simple fn top_index() -> SSize_t = av_len() }
    method! { getter fn pop() = av_pop() }
    method! { simple fn push(val: SV) = av_push(val.into_raw()) }
    method! { getter fn shift() = av_shift() }
    method! { simple fn undef() = av_undef() }
    method! { simple fn unshift(num: SSize_t) = av_unshift(num) }

    pub fn store(&self, key: SSize_t, val: SV) {
        unsafe {
            let svpp = self.pthx().av_store(self.as_ptr(), key, val.into_raw());
            if !svpp.is_null() { self.pthx().sv_refcnt_dec(*svpp) }
        }
    }
}
<commit_msg>Document AV methods.<commit_after>use handle::Owned;
use raw;
use raw::{ SSize_t };
use SV;

pub struct AV(Owned<raw::AV>);

impl AV {
    /// Construct new `AV` from a raw pointer without incrementing reference counter (raw pointer
    /// already "owns" one incref).
    pub unsafe fn from_raw_owned(pthx: raw::Interpreter, raw: *mut raw::AV) -> AV {
        AV(Owned::from_raw_owned(pthx, raw))
    }

    /// Construct new `AV` from a raw pointer and increment its reference counter (raw pointer is
    /// "borrowed" from another structure that owns one incref).
    pub unsafe fn from_raw_borrowed(pthx: raw::Interpreter, raw: *mut raw::AV) -> AV {
        AV(Owned::from_raw_borrowed(pthx, raw))
    }

    fn pthx(&self) -> raw::Interpreter { self.0.pthx() }

    fn as_ptr(&self) -> *mut raw::AV { self.0.as_ptr() }

    method! {
        /// Empty the array, preserving underlying allocation.
        ///
        /// See ['av_clear'](http://perldoc.perl.org/perlapi.html#av_clear).
        simple fn clear() = av_clear()
    }
    method! {
        /// Delete element of array and return it.
        ///
        /// See ['av_delete'](http://perldoc.perl.org/perlapi.html#av_delete).
        getter fn delete(key: SSize_t) = av_delete(key, 0)
    }
    method! {
        /// Delete element of array without returning it.
        ///
        /// See ['av_delete'](http://perldoc.perl.org/perlapi.html#av_delete).
        simple fn discard(key: SSize_t) = av_delete(key, raw::G_DISCARD as raw::I32)
    }
    method! {
        /// Return true when element exists in the array.
        ///
        /// See ['av_exists'](http://perldoc.perl.org/perlapi.html#av_exists).
        simple fn exists(key: SSize_t) -> bool = av_exists(key) != 0
    }
    method! {
        /// Grow array to contain at least `key` elements.
        ///
        /// See ['av_extend'](http://perldoc.perl.org/perlapi.html#av_extend).
        simple fn extend(key: SSize_t) = av_extend(key)
    }
    method! {
        /// Fetch element from array.
        ///
        /// See ['av_fetch'](http://perldoc.perl.org/perlapi.html#av_fetch).
        getptr fn fetch(key: SSize_t) = av_fetch(key, 0)
    }
    method! {
        /// Fetch element from array ready for assignment.
        ///
        /// See ['av_fetch'](http://perldoc.perl.org/perlapi.html#av_fetch).
        getptr fn fetch_lvalue(key: SSize_t) = av_fetch(key, 1)
    }
    method! {
        /// Set array length to `fill + 1`.
        ///
        /// See ['av_fill'](http://perldoc.perl.org/perlapi.html#av_fill).
        simple fn fill(fill: SSize_t) = av_fill(fill)
    }
    method! {
        /// Return the highest index in the array.
        ///
        /// See ['av_top_index'](http://perldoc.perl.org/perlapi.html#av_top_index).
        simple fn top_index() -> SSize_t = av_len()
    }
    method! {
        /// Remove and return one element at the end of the array.
        ///
        /// See ['av_pop'](http://perldoc.perl.org/perlapi.html#av_pop).
        getter fn pop() = av_pop()
    }
    method! {
        /// Append new element to the array.
        ///
        /// See ['av_push'](http://perldoc.perl.org/perlapi.html#av_push).
        simple fn push(val: SV) = av_push(val.into_raw())
    }
    method! {
        /// Remove and return one element at the beginning of the array.
        ///
        /// See ['av_shift'](http://perldoc.perl.org/perlapi.html#av_shift).
        getter fn shift() = av_shift()
    }
    method! {
        ///  Clear the array and release array memory.
        ///
        /// See ['av_undef'](http://perldoc.perl.org/perlapi.html#av_undef).
        simple fn undef() = av_undef()
    }
    method! {
        /// Insert one or more `undef` elements at the beginning of the array.
        ///
        /// See ['av_unshift'](http://perldoc.perl.org/perlapi.html#av_unshift).
        simple fn unshift(num: SSize_t) = av_unshift(num)
    }

    /// Set array element at index `key` to `val`.
    ///
    /// See ['av_store'](http://perldoc.perl.org/perlapi.html#av_store).
    pub fn store(&self, key: SSize_t, val: SV) {
        unsafe {
            let svpp = self.pthx().av_store(self.as_ptr(), key, val.into_raw());
            if !svpp.is_null() { self.pthx().sv_refcnt_dec(*svpp) }
        }
    }
}
<|endoftext|>


<commit_before>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

fn create_task(todo: ~str, id: int) -> Todo {
        let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"", priority: '^',
                                contexts: &[], projects: &[]};

        task.todo = todo.clone();

        return task;
}

fn main () {

        let t = create_task(~"some important task", 1);
}
<commit_msg>x chceck<commit_after>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

fn create_task(todo: ~str, id: int) -> Todo {
        let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"", priority: '^',
                                contexts: &[], projects: &[]};

        if (todo[0] == "x".as_bytes()[0]) {
                println("finished");
        }
        task.todo = todo.clone();

        return task;
}

fn main () {

        let t = create_task(~"some important task", 1);
        let x = create_task(~"x some important task", 1);
}
<|endoftext|>


<commit_before>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        raw_todo: ~str
}

fn create_task(todo: ~str, id: int) -> Todo {
        let task = Todo{id: id, raw_todo: todo, todo: ~"", priority: '^'};

        task.todo = todo;

        return task;
}

fn main () {

        let t = create_task(~"some important task", 1);
}
<commit_msg>mutable Todo<commit_after>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        raw_todo: ~str
}

fn create_task(todo: ~str, id: int) -> Todo {
        let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"", priority: '^'};

        task.todo = todo.clone();

        return task;
}

fn main () {

        let t = create_task(~"some important task", 1);
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use super::Normalizable;

use Colors;

/// Casting iterator for `Colors`.
#[derive(Debug, Clone)]
pub struct CastingIter<'a, T>(Colors<'a>, PhantomData<T>);

/// Type which describes how to cast any color into RGB u8.
#[derive(Debug, Clone)]
pub struct RgbU8;

/// Type which describes how to cast any color into RGB u16.
#[derive(Debug, Clone)]
pub struct RgbU16;

/// Type which describes how to cast any color into RGB f32.
#[derive(Debug, Clone)]
pub struct RgbF32;

/// Type which describes how to cast any color into RGBA u8.
#[derive(Debug, Clone)]
pub struct RgbaU8;

/// Type which describes how to cast any color into RGBA u16.
#[derive(Debug, Clone)]
pub struct RgbaU16;

/// Type which describes how to cast any color into RGBA f32.
#[derive(Debug, Clone)]
pub struct RgbaF32;

/// Trait for types which describe casting behaviour.
pub trait Cast {
    /// Output type.
    type Into;

    /// Cast from RGB u8.
    fn from_rgb_u8(x: [u8; 3]) -> Self::Into;

    /// Cast from RGB u16.
    fn from_rgb_u16(x: [u16; 3]) -> Self::Into;

    /// Cast from RGB f32.
    fn from_rgb_f32(x: [f32; 3]) -> Self::Into;

    /// Cast from RGBA u8.
    fn from_rgba_u8(x: [u8; 4]) -> Self::Into;

    /// Cast from RGBA u16.
    fn from_rgba_u16(x: [u16; 4]) -> Self::Into;

    /// Cast from RGBA f32.
    fn from_rgba_f32(x: [f32; 4]) -> Self::Into;
}

impl<'a, A> CastingIter<'a, A> {
    pub(crate) fn new(iter: Colors<'a>) -> Self {
        CastingIter(iter, PhantomData)
    }

    /// Unwrap underlying `Colors` object.
    pub fn unwrap(self) -> Colors<'a> {
        self.0
    }
}

impl<'a, A: Cast> Iterator for CastingIter<'a, A> {
    type Item = A::Into;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        match self.0 {
            Colors::RgbU8(ref mut i)   => i.next().map(A::from_rgb_u8),
            Colors::RgbU16(ref mut i)  => i.next().map(A::from_rgb_u16),
            Colors::RgbF32(ref mut i)  => i.next().map(A::from_rgb_f32),
            Colors::RgbaU8(ref mut i)  => i.next().map(A::from_rgba_u8),
            Colors::RgbaU16(ref mut i) => i.next().map(A::from_rgba_u16),
            Colors::RgbaF32(ref mut i) => i.next().map(A::from_rgba_f32),
        }
    }

    #[inline]
    fn nth(&mut self, x: usize) -> Option<Self::Item> {
        match self.0 {
            Colors::RgbU8(ref mut i)   => i.nth(x).map(A::from_rgb_u8),
            Colors::RgbU16(ref mut i)  => i.nth(x).map(A::from_rgb_u16),
            Colors::RgbF32(ref mut i)  => i.nth(x).map(A::from_rgb_f32),
            Colors::RgbaU8(ref mut i)  => i.nth(x).map(A::from_rgba_u8),
            Colors::RgbaU16(ref mut i) => i.nth(x).map(A::from_rgba_u16),
            Colors::RgbaF32(ref mut i) => i.nth(x).map(A::from_rgba_f32),
        }
    }

    fn last(self) -> Option<Self::Item> {
        match self.0 {
            Colors::RgbU8(i)   => i.last().map(A::from_rgb_u8),
            Colors::RgbU16(i)  => i.last().map(A::from_rgb_u16),
            Colors::RgbF32(i)  => i.last().map(A::from_rgb_f32),
            Colors::RgbaU8(i)  => i.last().map(A::from_rgba_u8),
            Colors::RgbaU16(i) => i.last().map(A::from_rgba_u16),
            Colors::RgbaF32(i) => i.last().map(A::from_rgba_f32),
        }
    }

    fn count(self) -> usize {
        self.size_hint().0
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.0 {
            Colors::RgbU8(ref i)   => i.size_hint(),
            Colors::RgbU16(ref i)  => i.size_hint(),
            Colors::RgbF32(ref i)  => i.size_hint(),
            Colors::RgbaU8(ref i)  => i.size_hint(),
            Colors::RgbaU16(ref i) => i.size_hint(),
            Colors::RgbaF32(ref i) => i.size_hint(),
        }
    }
}

impl Cast for RgbU8 {
    type Into = [u8; 3];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        Self::from_rgb_u8([x[0], x[1], x[2]])
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        Self::from_rgb_u16([x[0], x[1], x[2]])
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        Self::from_rgb_f32([x[0], x[1], x[2]])
    }
}

impl Cast for RgbU16 {
    type Into = [u16; 3];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        Self::from_rgb_u8([x[0], x[1], x[2]])
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        Self::from_rgb_u16([x[0], x[1], x[2]])
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        Self::from_rgb_f32([x[0], x[1], x[2]])
    }
}

impl Cast for RgbF32 {
    type Into = [f32; 3];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        Self::from_rgb_u8([x[0], x[1], x[2]])
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        Self::from_rgb_u16([x[0], x[1], x[2]])
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        Self::from_rgb_f32([x[0], x[1], x[2]])
    }
}

impl Cast for RgbaU8 {
    type Into = [u8; 4];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        Self::from_rgba_u8([x[0], x[1], x[2], u8::max_value()])
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        Self::from_rgba_u16([x[0], x[1], x[2], u16::max_value()])
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        Self::from_rgba_f32([x[0], x[1], x[2], 1.0])
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }
}

impl Cast for RgbaU16 {
    type Into = [u16; 4];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        Self::from_rgba_u8([x[0], x[1], x[2], u8::max_value()])
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        Self::from_rgba_u16([x[0], x[1], x[2], u16::max_value()])
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        Self::from_rgba_f32([x[0], x[1], x[2], 1.0])
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }
}

impl Cast for RgbaF32 {
    type Into = [f32; 4];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        Self::from_rgba_u8([x[0], x[1], x[2], u8::max_value()])
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        Self::from_rgba_u16([x[0], x[1], x[2], u16::max_value()])
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        Self::from_rgba_f32([x[0], x[1], x[2], 1.0])
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        Normalizable::normalize(x)
    }
}
<commit_msg>Generalize<commit_after>use std::marker::PhantomData;

use super::Normalizable;

use Colors;

/// Casting iterator for `Colors`.
#[derive(Debug, Clone)]
pub struct CastingIter<'a, T>(Colors<'a>, PhantomData<T>);

/// Type which describes how to cast any color into RGB u8.
#[derive(Debug, Clone)]
pub struct RgbU8;

/// Type which describes how to cast any color into RGB u16.
#[derive(Debug, Clone)]
pub struct RgbU16;

/// Type which describes how to cast any color into RGB f32.
#[derive(Debug, Clone)]
pub struct RgbF32;

/// Type which describes how to cast any color into RGBA u8.
#[derive(Debug, Clone)]
pub struct RgbaU8;

/// Type which describes how to cast any color into RGBA u16.
#[derive(Debug, Clone)]
pub struct RgbaU16;

/// Type which describes how to cast any color into RGBA f32.
#[derive(Debug, Clone)]
pub struct RgbaF32;

pub trait ArrayRelation<T> {
    fn into_rgb(self)  -> [T; 3];
    fn into_rgba(self) -> [T; 4];
}

impl<T: Copy + Default> ArrayRelation<T> for [T; 3] {
    fn into_rgb(self)  -> [T; 3] { self }
    fn into_rgba(self) -> [T; 4] { [self[0], self[1], self[2], T::default()] }
}

impl<T: Copy + Default> ArrayRelation<T> for [T; 4] {
    fn into_rgb(self)  -> [T; 3] { [self[0], self[1], self[2]] }
    fn into_rgba(self) -> [T; 4] { self }
}

/// Trait for types which describe casting behaviour.
pub trait Cast {
    /// Output type.
    type Into;

    /// Cast from RGB u8.
    fn from_rgb_u8(x: [u8; 3]) -> Self::Into;

    /// Cast from RGB u16.
    fn from_rgb_u16(x: [u16; 3]) -> Self::Into;

    /// Cast from RGB f32.
    fn from_rgb_f32(x: [f32; 3]) -> Self::Into;

    /// Cast from RGBA u8.
    fn from_rgba_u8(x: [u8; 4]) -> Self::Into;

    /// Cast from RGBA u16.
    fn from_rgba_u16(x: [u16; 4]) -> Self::Into;

    /// Cast from RGBA f32.
    fn from_rgba_f32(x: [f32; 4]) -> Self::Into;
}

impl<'a, A> CastingIter<'a, A> {
    pub(crate) fn new(iter: Colors<'a>) -> Self {
        CastingIter(iter, PhantomData)
    }

    /// Unwrap underlying `Colors` object.
    pub fn unwrap(self) -> Colors<'a> {
        self.0
    }
}

impl<'a, A: Cast> Iterator for CastingIter<'a, A> {
    type Item = A::Into;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        match self.0 {
            Colors::RgbU8(ref mut i)   => i.next().map(A::from_rgb_u8),
            Colors::RgbU16(ref mut i)  => i.next().map(A::from_rgb_u16),
            Colors::RgbF32(ref mut i)  => i.next().map(A::from_rgb_f32),
            Colors::RgbaU8(ref mut i)  => i.next().map(A::from_rgba_u8),
            Colors::RgbaU16(ref mut i) => i.next().map(A::from_rgba_u16),
            Colors::RgbaF32(ref mut i) => i.next().map(A::from_rgba_f32),
        }
    }

    #[inline]
    fn nth(&mut self, x: usize) -> Option<Self::Item> {
        match self.0 {
            Colors::RgbU8(ref mut i)   => i.nth(x).map(A::from_rgb_u8),
            Colors::RgbU16(ref mut i)  => i.nth(x).map(A::from_rgb_u16),
            Colors::RgbF32(ref mut i)  => i.nth(x).map(A::from_rgb_f32),
            Colors::RgbaU8(ref mut i)  => i.nth(x).map(A::from_rgba_u8),
            Colors::RgbaU16(ref mut i) => i.nth(x).map(A::from_rgba_u16),
            Colors::RgbaF32(ref mut i) => i.nth(x).map(A::from_rgba_f32),
        }
    }

    fn last(self) -> Option<Self::Item> {
        match self.0 {
            Colors::RgbU8(i)   => i.last().map(A::from_rgb_u8),
            Colors::RgbU16(i)  => i.last().map(A::from_rgb_u16),
            Colors::RgbF32(i)  => i.last().map(A::from_rgb_f32),
            Colors::RgbaU8(i)  => i.last().map(A::from_rgba_u8),
            Colors::RgbaU16(i) => i.last().map(A::from_rgba_u16),
            Colors::RgbaF32(i) => i.last().map(A::from_rgba_f32),
        }
    }

    fn count(self) -> usize {
        self.size_hint().0
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.0 {
            Colors::RgbU8(ref i)   => i.size_hint(),
            Colors::RgbU16(ref i)  => i.size_hint(),
            Colors::RgbF32(ref i)  => i.size_hint(),
            Colors::RgbaU8(ref i)  => i.size_hint(),
            Colors::RgbaU16(ref i) => i.size_hint(),
            Colors::RgbaF32(ref i) => i.size_hint(),
        }
    }
}

impl Cast for RgbU8 {
    type Into = [u8; 3];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }
}

impl Cast for RgbU16 {
    type Into = [u16; 3];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }
}

impl Cast for RgbF32 {
    type Into = [f32; 3];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        x.into_rgb().normalize()
    }
}

impl Cast for RgbaU8 {
    type Into = [u8; 4];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }
}

impl Cast for RgbaU16 {
    type Into = [u16; 4];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }
}

impl Cast for RgbaF32 {
    type Into = [f32; 4];

    fn from_rgb_u8(x: [u8; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgb_u16(x: [u16; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgb_f32(x: [f32; 3]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_u8(x: [u8; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_u16(x: [u16; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }

    fn from_rgba_f32(x: [f32; 4]) -> Self::Into {
        x.normalize().into_rgba()
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use {VirtualKeyCode, ElementState, Event};

use super::wayland_kbd;
use wayland_client::EventQueueHandle;
use wayland_client::protocol::wl_keyboard;

pub struct KbdHandler {
    pub target: Option<Arc<Mutex<VecDeque<Event>>>>
}

impl KbdHandler {
    pub fn new() -> KbdHandler {
        KbdHandler { target: None }
    }
}

impl wayland_kbd::Handler for KbdHandler {
    fn key(&mut self,
           _evqh: &mut EventQueueHandle,
           _proxy: &wl_keyboard::WlKeyboard,
           _serial: u32,
           _time: u32,
           rawkey: u32,
           keysym: u32,
           state: wl_keyboard::KeyState,
           utf8: Option<String>)
    {
        if let Some(ref eviter) = self.target {
            let state = match state {
                wl_keyboard::KeyState::Pressed => ElementState::Pressed,
                wl_keyboard::KeyState::Released => ElementState::Released,
            };
            let vkcode = key_to_vkey(rawkey, keysym);
            let mut guard = eviter.lock().unwrap();
            guard.push_back(Event::KeyboardInput(state, rawkey as u8, vkcode));
            // send char event only on key press, not release
            if let ElementState::Released = state { return }
            if let Some(txt) = utf8 {
                for chr in txt.chars() {
                    guard.push_back(Event::ReceivedCharacter(chr));
                }
            }
        }
    }
}

fn key_to_vkey(rawkey: u32, keysym: u32) -> Option<VirtualKeyCode> {
    match rawkey {
         1 => Some(VirtualKeyCode::Escape),
         2 => Some(VirtualKeyCode::Key1),
         3 => Some(VirtualKeyCode::Key2),
         4 => Some(VirtualKeyCode::Key3),
         5 => Some(VirtualKeyCode::Key4),
         6 => Some(VirtualKeyCode::Key5),
         7 => Some(VirtualKeyCode::Key6),
         8 => Some(VirtualKeyCode::Key7),
         9 => Some(VirtualKeyCode::Key8),
        10 => Some(VirtualKeyCode::Key9),
        11 => Some(VirtualKeyCode::Key0),
        _  => keysym_to_vkey(keysym)
    }
}

fn keysym_to_vkey(keysym: u32) -> Option<VirtualKeyCode> {
    use super::wayland_kbd::keysyms;
    match keysym {
        // letters
        keysyms::XKB_KEY_A | keysyms::XKB_KEY_a => Some(VirtualKeyCode::A),
        keysyms::XKB_KEY_B | keysyms::XKB_KEY_b => Some(VirtualKeyCode::B),
        keysyms::XKB_KEY_C | keysyms::XKB_KEY_c => Some(VirtualKeyCode::C),
        keysyms::XKB_KEY_D | keysyms::XKB_KEY_d => Some(VirtualKeyCode::D),
        keysyms::XKB_KEY_E | keysyms::XKB_KEY_e => Some(VirtualKeyCode::E),
        keysyms::XKB_KEY_F | keysyms::XKB_KEY_f => Some(VirtualKeyCode::F),
        keysyms::XKB_KEY_G | keysyms::XKB_KEY_g => Some(VirtualKeyCode::G),
        keysyms::XKB_KEY_H | keysyms::XKB_KEY_h => Some(VirtualKeyCode::H),
        keysyms::XKB_KEY_I | keysyms::XKB_KEY_i => Some(VirtualKeyCode::I),
        keysyms::XKB_KEY_J | keysyms::XKB_KEY_j => Some(VirtualKeyCode::J),
        keysyms::XKB_KEY_K | keysyms::XKB_KEY_k => Some(VirtualKeyCode::K),
        keysyms::XKB_KEY_L | keysyms::XKB_KEY_l => Some(VirtualKeyCode::L),
        keysyms::XKB_KEY_M | keysyms::XKB_KEY_m => Some(VirtualKeyCode::M),
        keysyms::XKB_KEY_N | keysyms::XKB_KEY_n => Some(VirtualKeyCode::N),
        keysyms::XKB_KEY_O | keysyms::XKB_KEY_o => Some(VirtualKeyCode::O),
        keysyms::XKB_KEY_P | keysyms::XKB_KEY_p => Some(VirtualKeyCode::P),
        keysyms::XKB_KEY_Q | keysyms::XKB_KEY_q => Some(VirtualKeyCode::Q),
        keysyms::XKB_KEY_R | keysyms::XKB_KEY_r => Some(VirtualKeyCode::R),
        keysyms::XKB_KEY_S | keysyms::XKB_KEY_s => Some(VirtualKeyCode::S),
        keysyms::XKB_KEY_T | keysyms::XKB_KEY_t => Some(VirtualKeyCode::T),
        keysyms::XKB_KEY_U | keysyms::XKB_KEY_u => Some(VirtualKeyCode::U),
        keysyms::XKB_KEY_V | keysyms::XKB_KEY_v => Some(VirtualKeyCode::V),
        keysyms::XKB_KEY_W | keysyms::XKB_KEY_w => Some(VirtualKeyCode::W),
        keysyms::XKB_KEY_X | keysyms::XKB_KEY_x => Some(VirtualKeyCode::X),
        keysyms::XKB_KEY_Y | keysyms::XKB_KEY_y => Some(VirtualKeyCode::Y),
        keysyms::XKB_KEY_Z | keysyms::XKB_KEY_z => Some(VirtualKeyCode::Z),
        // F--
        keysyms::XKB_KEY_F1  => Some(VirtualKeyCode::F1),
        keysyms::XKB_KEY_F2  => Some(VirtualKeyCode::F2),
        keysyms::XKB_KEY_F3  => Some(VirtualKeyCode::F3),
        keysyms::XKB_KEY_F4  => Some(VirtualKeyCode::F4),
        keysyms::XKB_KEY_F5  => Some(VirtualKeyCode::F5),
        keysyms::XKB_KEY_F6  => Some(VirtualKeyCode::F6),
        keysyms::XKB_KEY_F7  => Some(VirtualKeyCode::F7),
        keysyms::XKB_KEY_F8  => Some(VirtualKeyCode::F8),
        keysyms::XKB_KEY_F9  => Some(VirtualKeyCode::F9),
        keysyms::XKB_KEY_F10 => Some(VirtualKeyCode::F10),
        keysyms::XKB_KEY_F11 => Some(VirtualKeyCode::F11),
        keysyms::XKB_KEY_F12 => Some(VirtualKeyCode::F12),
        keysyms::XKB_KEY_F13 => Some(VirtualKeyCode::F13),
        keysyms::XKB_KEY_F14 => Some(VirtualKeyCode::F14),
        keysyms::XKB_KEY_F15 => Some(VirtualKeyCode::F15),
        // flow control
        keysyms::XKB_KEY_Print => Some(VirtualKeyCode::Snapshot),
        keysyms::XKB_KEY_Scroll_Lock => Some(VirtualKeyCode::Scroll),
        keysyms::XKB_KEY_Pause => Some(VirtualKeyCode::Pause),
        keysyms::XKB_KEY_Insert => Some(VirtualKeyCode::Insert),
        keysyms::XKB_KEY_Home => Some(VirtualKeyCode::Home),
        keysyms::XKB_KEY_Delete => Some(VirtualKeyCode::Delete),
        keysyms::XKB_KEY_End => Some(VirtualKeyCode::End),
        keysyms::XKB_KEY_Page_Down => Some(VirtualKeyCode::PageDown),
        keysyms::XKB_KEY_Page_Up => Some(VirtualKeyCode::PageUp),
        // arrows
        keysyms::XKB_KEY_Left => Some(VirtualKeyCode::Left),
        keysyms::XKB_KEY_Up => Some(VirtualKeyCode::Up),
        keysyms::XKB_KEY_Right => Some(VirtualKeyCode::Right),
        keysyms::XKB_KEY_Down => Some(VirtualKeyCode::Down),
        //
        keysyms::XKB_KEY_BackSpace => Some(VirtualKeyCode::Back),
        keysyms::XKB_KEY_Return => Some(VirtualKeyCode::Return),
        keysyms::XKB_KEY_space => Some(VirtualKeyCode::Space),
        // keypad
        keysyms::XKB_KEY_Num_Lock => Some(VirtualKeyCode::Numlock),
        keysyms::XKB_KEY_KP_0 => Some(VirtualKeyCode::Numpad0),
        keysyms::XKB_KEY_KP_1 => Some(VirtualKeyCode::Numpad1),
        keysyms::XKB_KEY_KP_2 => Some(VirtualKeyCode::Numpad2),
        keysyms::XKB_KEY_KP_3 => Some(VirtualKeyCode::Numpad3),
        keysyms::XKB_KEY_KP_4 => Some(VirtualKeyCode::Numpad4),
        keysyms::XKB_KEY_KP_5 => Some(VirtualKeyCode::Numpad5),
        keysyms::XKB_KEY_KP_6 => Some(VirtualKeyCode::Numpad6),
        keysyms::XKB_KEY_KP_7 => Some(VirtualKeyCode::Numpad7),
        keysyms::XKB_KEY_KP_8 => Some(VirtualKeyCode::Numpad8),
        keysyms::XKB_KEY_KP_9 => Some(VirtualKeyCode::Numpad9),
        // misc
        // => Some(VirtualKeyCode::AbntC1),
        // => Some(VirtualKeyCode::AbntC2),
        keysyms::XKB_KEY_plus => Some(VirtualKeyCode::Add),
        keysyms::XKB_KEY_apostrophe => Some(VirtualKeyCode::Apostrophe),
        // => Some(VirtualKeyCode::Apps),
        // => Some(VirtualKeyCode::At),
        // => Some(VirtualKeyCode::Ax),
        keysyms::XKB_KEY_backslash => Some(VirtualKeyCode::Backslash),
        // => Some(VirtualKeyCode::Calculator),
        // => Some(VirtualKeyCode::Capital),
        keysyms::XKB_KEY_colon => Some(VirtualKeyCode::Colon),
        keysyms::XKB_KEY_comma => Some(VirtualKeyCode::Comma),
        // => Some(VirtualKeyCode::Convert),
        // => Some(VirtualKeyCode::Decimal),
        // => Some(VirtualKeyCode::Divide),
        keysyms::XKB_KEY_equal => Some(VirtualKeyCode::Equals),
        // => Some(VirtualKeyCode::Grave),
        // => Some(VirtualKeyCode::Kana),
        // => Some(VirtualKeyCode::Kanji),
        keysyms::XKB_KEY_Alt_L => Some(VirtualKeyCode::LAlt),
        // => Some(VirtualKeyCode::LBracket),
        keysyms::XKB_KEY_Control_L => Some(VirtualKeyCode::LControl),
        // => Some(VirtualKeyCode::LMenu),
        keysyms::XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift),
        // => Some(VirtualKeyCode::LWin),
        // => Some(VirtualKeyCode::Mail),
        // => Some(VirtualKeyCode::MediaSelect),
        // => Some(VirtualKeyCode::MediaStop),
        keysyms::XKB_KEY_minus => Some(VirtualKeyCode::Minus),
        keysyms::XKB_KEY_asterisk => Some(VirtualKeyCode::Multiply),
        // => Some(VirtualKeyCode::Mute),
        // => Some(VirtualKeyCode::MyComputer),
        // => Some(VirtualKeyCode::NextTrack),
        // => Some(VirtualKeyCode::NoConvert),
        keysyms::XKB_KEY_KP_Separator => Some(VirtualKeyCode::NumpadComma),
        keysyms::XKB_KEY_KP_Enter => Some(VirtualKeyCode::NumpadEnter),
        keysyms::XKB_KEY_KP_Equal => Some(VirtualKeyCode::NumpadEquals),
        // => Some(VirtualKeyCode::OEM102),
        // => Some(VirtualKeyCode::Period),
        // => Some(VirtualKeyCode::Playpause),
        // => Some(VirtualKeyCode::Power),
        // => Some(VirtualKeyCode::Prevtrack),
        keysyms::XKB_KEY_Alt_R => Some(VirtualKeyCode::RAlt),
        // => Some(VirtualKeyCode::RBracket),
        keysyms::XKB_KEY_Control_R => Some(VirtualKeyCode::RControl),
        // => Some(VirtualKeyCode::RMenu),
        keysyms::XKB_KEY_Shift_R => Some(VirtualKeyCode::RShift),
        // => Some(VirtualKeyCode::RWin),
        keysyms::XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon),
        keysyms::XKB_KEY_slash => Some(VirtualKeyCode::Slash),
        // => Some(VirtualKeyCode::Sleep),
        // => Some(VirtualKeyCode::Stop),
        // => Some(VirtualKeyCode::Subtract),
        // => Some(VirtualKeyCode::Sysrq),
        keysyms::XKB_KEY_Tab => Some(VirtualKeyCode::Tab),
        // => Some(VirtualKeyCode::Underline),
        // => Some(VirtualKeyCode::Unlabeled),
        keysyms::XKB_KEY_XF86AudioLowerVolume => Some(VirtualKeyCode::VolumeDown),
        keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(VirtualKeyCode::VolumeUp),
        // => Some(VirtualKeyCode::Wake),
        // => Some(VirtualKeyCode::Webback),
        // => Some(VirtualKeyCode::WebFavorites),
        // => Some(VirtualKeyCode::WebForward),
        // => Some(VirtualKeyCode::WebHome),
        // => Some(VirtualKeyCode::WebRefresh),
        // => Some(VirtualKeyCode::WebSearch),
        // => Some(VirtualKeyCode::WebStop),
        // => Some(VirtualKeyCode::Yen),
        // fallback
        _ => None
    }
}
<commit_msg>Wayland fix attempt<commit_after>use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use {VirtualKeyCode, ElementState, WindowEvent as Event};

use super::wayland_kbd;
use wayland_client::EventQueueHandle;
use wayland_client::protocol::wl_keyboard;

pub struct KbdHandler {
    pub target: Option<Arc<Mutex<VecDeque<Event>>>>
}

impl KbdHandler {
    pub fn new() -> KbdHandler {
        KbdHandler { target: None }
    }
}

impl wayland_kbd::Handler for KbdHandler {
    fn key(&mut self,
           _evqh: &mut EventQueueHandle,
           _proxy: &wl_keyboard::WlKeyboard,
           _serial: u32,
           _time: u32,
           rawkey: u32,
           keysym: u32,
           state: wl_keyboard::KeyState,
           utf8: Option<String>)
    {
        if let Some(ref eviter) = self.target {
            let state = match state {
                wl_keyboard::KeyState::Pressed => ElementState::Pressed,
                wl_keyboard::KeyState::Released => ElementState::Released,
            };
            let vkcode = key_to_vkey(rawkey, keysym);
            let mut guard = eviter.lock().unwrap();
            guard.push_back(Event::KeyboardInput(state, rawkey as u8, vkcode));
            // send char event only on key press, not release
            if let ElementState::Released = state { return }
            if let Some(txt) = utf8 {
                for chr in txt.chars() {
                    guard.push_back(Event::ReceivedCharacter(chr));
                }
            }
        }
    }
}

fn key_to_vkey(rawkey: u32, keysym: u32) -> Option<VirtualKeyCode> {
    match rawkey {
         1 => Some(VirtualKeyCode::Escape),
         2 => Some(VirtualKeyCode::Key1),
         3 => Some(VirtualKeyCode::Key2),
         4 => Some(VirtualKeyCode::Key3),
         5 => Some(VirtualKeyCode::Key4),
         6 => Some(VirtualKeyCode::Key5),
         7 => Some(VirtualKeyCode::Key6),
         8 => Some(VirtualKeyCode::Key7),
         9 => Some(VirtualKeyCode::Key8),
        10 => Some(VirtualKeyCode::Key9),
        11 => Some(VirtualKeyCode::Key0),
        _  => keysym_to_vkey(keysym)
    }
}

fn keysym_to_vkey(keysym: u32) -> Option<VirtualKeyCode> {
    use super::wayland_kbd::keysyms;
    match keysym {
        // letters
        keysyms::XKB_KEY_A | keysyms::XKB_KEY_a => Some(VirtualKeyCode::A),
        keysyms::XKB_KEY_B | keysyms::XKB_KEY_b => Some(VirtualKeyCode::B),
        keysyms::XKB_KEY_C | keysyms::XKB_KEY_c => Some(VirtualKeyCode::C),
        keysyms::XKB_KEY_D | keysyms::XKB_KEY_d => Some(VirtualKeyCode::D),
        keysyms::XKB_KEY_E | keysyms::XKB_KEY_e => Some(VirtualKeyCode::E),
        keysyms::XKB_KEY_F | keysyms::XKB_KEY_f => Some(VirtualKeyCode::F),
        keysyms::XKB_KEY_G | keysyms::XKB_KEY_g => Some(VirtualKeyCode::G),
        keysyms::XKB_KEY_H | keysyms::XKB_KEY_h => Some(VirtualKeyCode::H),
        keysyms::XKB_KEY_I | keysyms::XKB_KEY_i => Some(VirtualKeyCode::I),
        keysyms::XKB_KEY_J | keysyms::XKB_KEY_j => Some(VirtualKeyCode::J),
        keysyms::XKB_KEY_K | keysyms::XKB_KEY_k => Some(VirtualKeyCode::K),
        keysyms::XKB_KEY_L | keysyms::XKB_KEY_l => Some(VirtualKeyCode::L),
        keysyms::XKB_KEY_M | keysyms::XKB_KEY_m => Some(VirtualKeyCode::M),
        keysyms::XKB_KEY_N | keysyms::XKB_KEY_n => Some(VirtualKeyCode::N),
        keysyms::XKB_KEY_O | keysyms::XKB_KEY_o => Some(VirtualKeyCode::O),
        keysyms::XKB_KEY_P | keysyms::XKB_KEY_p => Some(VirtualKeyCode::P),
        keysyms::XKB_KEY_Q | keysyms::XKB_KEY_q => Some(VirtualKeyCode::Q),
        keysyms::XKB_KEY_R | keysyms::XKB_KEY_r => Some(VirtualKeyCode::R),
        keysyms::XKB_KEY_S | keysyms::XKB_KEY_s => Some(VirtualKeyCode::S),
        keysyms::XKB_KEY_T | keysyms::XKB_KEY_t => Some(VirtualKeyCode::T),
        keysyms::XKB_KEY_U | keysyms::XKB_KEY_u => Some(VirtualKeyCode::U),
        keysyms::XKB_KEY_V | keysyms::XKB_KEY_v => Some(VirtualKeyCode::V),
        keysyms::XKB_KEY_W | keysyms::XKB_KEY_w => Some(VirtualKeyCode::W),
        keysyms::XKB_KEY_X | keysyms::XKB_KEY_x => Some(VirtualKeyCode::X),
        keysyms::XKB_KEY_Y | keysyms::XKB_KEY_y => Some(VirtualKeyCode::Y),
        keysyms::XKB_KEY_Z | keysyms::XKB_KEY_z => Some(VirtualKeyCode::Z),
        // F--
        keysyms::XKB_KEY_F1  => Some(VirtualKeyCode::F1),
        keysyms::XKB_KEY_F2  => Some(VirtualKeyCode::F2),
        keysyms::XKB_KEY_F3  => Some(VirtualKeyCode::F3),
        keysyms::XKB_KEY_F4  => Some(VirtualKeyCode::F4),
        keysyms::XKB_KEY_F5  => Some(VirtualKeyCode::F5),
        keysyms::XKB_KEY_F6  => Some(VirtualKeyCode::F6),
        keysyms::XKB_KEY_F7  => Some(VirtualKeyCode::F7),
        keysyms::XKB_KEY_F8  => Some(VirtualKeyCode::F8),
        keysyms::XKB_KEY_F9  => Some(VirtualKeyCode::F9),
        keysyms::XKB_KEY_F10 => Some(VirtualKeyCode::F10),
        keysyms::XKB_KEY_F11 => Some(VirtualKeyCode::F11),
        keysyms::XKB_KEY_F12 => Some(VirtualKeyCode::F12),
        keysyms::XKB_KEY_F13 => Some(VirtualKeyCode::F13),
        keysyms::XKB_KEY_F14 => Some(VirtualKeyCode::F14),
        keysyms::XKB_KEY_F15 => Some(VirtualKeyCode::F15),
        // flow control
        keysyms::XKB_KEY_Print => Some(VirtualKeyCode::Snapshot),
        keysyms::XKB_KEY_Scroll_Lock => Some(VirtualKeyCode::Scroll),
        keysyms::XKB_KEY_Pause => Some(VirtualKeyCode::Pause),
        keysyms::XKB_KEY_Insert => Some(VirtualKeyCode::Insert),
        keysyms::XKB_KEY_Home => Some(VirtualKeyCode::Home),
        keysyms::XKB_KEY_Delete => Some(VirtualKeyCode::Delete),
        keysyms::XKB_KEY_End => Some(VirtualKeyCode::End),
        keysyms::XKB_KEY_Page_Down => Some(VirtualKeyCode::PageDown),
        keysyms::XKB_KEY_Page_Up => Some(VirtualKeyCode::PageUp),
        // arrows
        keysyms::XKB_KEY_Left => Some(VirtualKeyCode::Left),
        keysyms::XKB_KEY_Up => Some(VirtualKeyCode::Up),
        keysyms::XKB_KEY_Right => Some(VirtualKeyCode::Right),
        keysyms::XKB_KEY_Down => Some(VirtualKeyCode::Down),
        //
        keysyms::XKB_KEY_BackSpace => Some(VirtualKeyCode::Back),
        keysyms::XKB_KEY_Return => Some(VirtualKeyCode::Return),
        keysyms::XKB_KEY_space => Some(VirtualKeyCode::Space),
        // keypad
        keysyms::XKB_KEY_Num_Lock => Some(VirtualKeyCode::Numlock),
        keysyms::XKB_KEY_KP_0 => Some(VirtualKeyCode::Numpad0),
        keysyms::XKB_KEY_KP_1 => Some(VirtualKeyCode::Numpad1),
        keysyms::XKB_KEY_KP_2 => Some(VirtualKeyCode::Numpad2),
        keysyms::XKB_KEY_KP_3 => Some(VirtualKeyCode::Numpad3),
        keysyms::XKB_KEY_KP_4 => Some(VirtualKeyCode::Numpad4),
        keysyms::XKB_KEY_KP_5 => Some(VirtualKeyCode::Numpad5),
        keysyms::XKB_KEY_KP_6 => Some(VirtualKeyCode::Numpad6),
        keysyms::XKB_KEY_KP_7 => Some(VirtualKeyCode::Numpad7),
        keysyms::XKB_KEY_KP_8 => Some(VirtualKeyCode::Numpad8),
        keysyms::XKB_KEY_KP_9 => Some(VirtualKeyCode::Numpad9),
        // misc
        // => Some(VirtualKeyCode::AbntC1),
        // => Some(VirtualKeyCode::AbntC2),
        keysyms::XKB_KEY_plus => Some(VirtualKeyCode::Add),
        keysyms::XKB_KEY_apostrophe => Some(VirtualKeyCode::Apostrophe),
        // => Some(VirtualKeyCode::Apps),
        // => Some(VirtualKeyCode::At),
        // => Some(VirtualKeyCode::Ax),
        keysyms::XKB_KEY_backslash => Some(VirtualKeyCode::Backslash),
        // => Some(VirtualKeyCode::Calculator),
        // => Some(VirtualKeyCode::Capital),
        keysyms::XKB_KEY_colon => Some(VirtualKeyCode::Colon),
        keysyms::XKB_KEY_comma => Some(VirtualKeyCode::Comma),
        // => Some(VirtualKeyCode::Convert),
        // => Some(VirtualKeyCode::Decimal),
        // => Some(VirtualKeyCode::Divide),
        keysyms::XKB_KEY_equal => Some(VirtualKeyCode::Equals),
        // => Some(VirtualKeyCode::Grave),
        // => Some(VirtualKeyCode::Kana),
        // => Some(VirtualKeyCode::Kanji),
        keysyms::XKB_KEY_Alt_L => Some(VirtualKeyCode::LAlt),
        // => Some(VirtualKeyCode::LBracket),
        keysyms::XKB_KEY_Control_L => Some(VirtualKeyCode::LControl),
        // => Some(VirtualKeyCode::LMenu),
        keysyms::XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift),
        // => Some(VirtualKeyCode::LWin),
        // => Some(VirtualKeyCode::Mail),
        // => Some(VirtualKeyCode::MediaSelect),
        // => Some(VirtualKeyCode::MediaStop),
        keysyms::XKB_KEY_minus => Some(VirtualKeyCode::Minus),
        keysyms::XKB_KEY_asterisk => Some(VirtualKeyCode::Multiply),
        // => Some(VirtualKeyCode::Mute),
        // => Some(VirtualKeyCode::MyComputer),
        // => Some(VirtualKeyCode::NextTrack),
        // => Some(VirtualKeyCode::NoConvert),
        keysyms::XKB_KEY_KP_Separator => Some(VirtualKeyCode::NumpadComma),
        keysyms::XKB_KEY_KP_Enter => Some(VirtualKeyCode::NumpadEnter),
        keysyms::XKB_KEY_KP_Equal => Some(VirtualKeyCode::NumpadEquals),
        // => Some(VirtualKeyCode::OEM102),
        // => Some(VirtualKeyCode::Period),
        // => Some(VirtualKeyCode::Playpause),
        // => Some(VirtualKeyCode::Power),
        // => Some(VirtualKeyCode::Prevtrack),
        keysyms::XKB_KEY_Alt_R => Some(VirtualKeyCode::RAlt),
        // => Some(VirtualKeyCode::RBracket),
        keysyms::XKB_KEY_Control_R => Some(VirtualKeyCode::RControl),
        // => Some(VirtualKeyCode::RMenu),
        keysyms::XKB_KEY_Shift_R => Some(VirtualKeyCode::RShift),
        // => Some(VirtualKeyCode::RWin),
        keysyms::XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon),
        keysyms::XKB_KEY_slash => Some(VirtualKeyCode::Slash),
        // => Some(VirtualKeyCode::Sleep),
        // => Some(VirtualKeyCode::Stop),
        // => Some(VirtualKeyCode::Subtract),
        // => Some(VirtualKeyCode::Sysrq),
        keysyms::XKB_KEY_Tab => Some(VirtualKeyCode::Tab),
        // => Some(VirtualKeyCode::Underline),
        // => Some(VirtualKeyCode::Unlabeled),
        keysyms::XKB_KEY_XF86AudioLowerVolume => Some(VirtualKeyCode::VolumeDown),
        keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(VirtualKeyCode::VolumeUp),
        // => Some(VirtualKeyCode::Wake),
        // => Some(VirtualKeyCode::Webback),
        // => Some(VirtualKeyCode::WebFavorites),
        // => Some(VirtualKeyCode::WebForward),
        // => Some(VirtualKeyCode::WebHome),
        // => Some(VirtualKeyCode::WebRefresh),
        // => Some(VirtualKeyCode::WebSearch),
        // => Some(VirtualKeyCode::WebStop),
        // => Some(VirtualKeyCode::Yen),
        // fallback
        _ => None
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers.
// Copyright 2015 Guillaume Gomez
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Library to interface with chunks of memory allocated in C.
//!
//! It is often desirable to safely interface with memory allocated from C,
//! encapsulating the unsafety into allocation and destruction time.  Indeed,
//! allocating memory externally is currently the only way to give Rust shared
//! mut state with C programs that keep their own references; vectors are
//! unsuitable because they could be reallocated or moved at any time, and
//! importing C memory into a vector takes a one-time snapshot of the memory.
//!
//! This module simplifies the usage of such external blocks of memory.  Memory
//! is encapsulated into an opaque object after creation; the lifecycle of the
//! memory can be optionally managed by Rust, if an appropriate destructor
//! closure is provided.  Safety is ensured by bounds-checking accesses, which
//! are marshalled through get and set functions.
//!
//! There are three unsafe functions: the two constructors, and the
//! unwrapping method. The constructors are unsafe for the
//! obvious reason (they act on a pointer that cannot be checked inside the
//! method), but `into_inner()` is somewhat more subtle in its unsafety.
//! It returns the contained pointer, but at the same time destroys the CVec
//! without running its destructor. This can be used to pass memory back to
//! C, but care must be taken that the ownership of underlying resources are
//! handled correctly, i.e. that allocated memory is eventually freed
//! if necessary.

#![feature(unsafe_destructor, core, std_misc, unique)]

use std::mem;
use std::ptr;
use std::raw;
use std::ptr::Unique;
use std::thunk::Invoke;

/// The type representing a foreign chunk of memory
pub struct CVec<T> {
    base: Unique<T>,
    len: usize,
    dtor: Option<Box<Invoke<*mut T> + 'static>>
}

#[unsafe_destructor]
impl<T> Drop for CVec<T> {
    fn drop(&mut self) {
        match self.dtor.take() {
            None => (),
            Some(f) => f.invoke(*self.base),
        }
    }
}

impl<T> CVec<T> {
    /// Create a `CVec` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: Unique<T>, len: usize) -> CVec<T> {
        assert!(*base != ptr::null_mut());
        CVec {
            base: base,
            len: len,
            dtor: None,
        }
    }

    /// Create a `CVec` from a foreign buffer, with a given length,
    /// and a function to run upon destruction.
    ///
    /// Panics if the given pointer is null.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    /// * dtor - A fn to run when the value is destructed, useful
    ///          for freeing the buffer, etc. `base` will be passed
    ///          to it as an argument.
    pub unsafe fn new_with_dtor<F>(base: Unique<T>,
                                   len: usize,
                                   dtor: F)
                                   -> CVec<T>
        where F : FnOnce(*mut T) + 'static
    {
        assert!(*base != ptr::null_mut());
        let dtor = Box::new(dtor);
        CVec {
            base: base,
            len: len,
            dtor: Some(dtor)
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Unwrap the pointer without running the destructor
    ///
    /// This method retrieves the underlying pointer, and in the process
    /// destroys the CVec but without running the destructor. A use case
    /// would be transferring ownership of the buffer to a C function, as
    /// in this case you would not want to run the destructor.
    ///
    /// Note that if you want to access the underlying pointer without
    /// cancelling the destructor, you can simply call `transmute` on the return
    /// value of `get(0)`.
    pub unsafe fn into_inner(mut self) -> *mut T {
        self.dtor = None;
        *self.base
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T> AsSlice<T> for CVec<T> {
    /// View the stored data as a slice.
    fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }
}

/// The type representing an 'unsafe' foreign chunk of memory
pub struct CSlice<T> {
    base: *mut T,
    len: usize,
    dtor: Option<Box<Invoke<*mut T> + 'static>>
}

#[unsafe_destructor]
impl<T> Drop for CSlice<T> {
    fn drop(&mut self) {
        match self.dtor.take() {
            None => (),
            Some(f) => f.invoke(self.base),
        }
    }
}

impl<T> CSlice<T> {
    /// Create a `CSlice` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A raw pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: *mut T, len: usize) -> CSlice<T> {
        assert!(base != ptr::null_mut());
        CSlice {
            base: base,
            len: len,
            dtor: None,
        }
    }

    /// Create a `CSlice` from a foreign buffer, with a given length,
    /// and a function to run upon destruction.
    ///
    /// Panics if the given pointer is null.
    ///
    /// # Arguments
    ///
    /// * base - A raw pointer to a buffer
    /// * len - The number of elements in the buffer
    /// * dtor - A fn to run when the value is destructed, useful
    ///          for freeing the buffer, etc. `base` will be passed
    ///          to it as an argument.
    pub unsafe fn new_with_dtor<F>(base: *mut T,
                                   len: usize,
                                   dtor: F)
                                   -> CSlice<T>
        where F : FnOnce(*mut T) + 'static
    {
        assert!(base != ptr::null_mut());
        let dtor = Box::new(dtor);
        CSlice {
            base: base,
            len: len,
            dtor: Some(dtor)
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Unwrap the pointer without running the destructor
    ///
    /// This method retrieves the underlying pointer, and in the process
    /// destroys the CSlice but without running the destructor. A use case
    /// would be transferring ownership of the buffer to a C function, as
    /// in this case you would not want to run the destructor.
    ///
    /// Note that if you want to access the underlying pointer without
    /// cancelling the destructor, you can simply call `transmute` on the return
    /// value of `get(0)`.
    pub unsafe fn into_inner(mut self) -> *mut T {
        self.dtor = None;
        self.base
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T> AsSlice<T> for CSlice<T> {
    /// View the stored data as a slice.
    fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate alloc;
    extern crate libc;

    use super::{CVec, CSlice};
    use std::ptr::{self, Unique};

    // allocation of CVec
    fn v_malloc(n: usize) -> CVec<u8> {
        unsafe {
            let mem: Unique<u8> = Unique::new(
                libc::malloc(n as libc::size_t) as *mut _);
            if (*mem).is_null() { alloc::oom() }

            CVec::new_with_dtor(mem, n,
                                |mem| { libc::free((mem) as *mut _); })
        }
    }

    // allocation of CSlice
    fn s_malloc(n: usize) -> CSlice<u8> {
        unsafe {
            let mem: *mut u8 = libc::malloc(n as libc::size_t) as *mut _;
            if mem.is_null() { alloc::oom() }

            CSlice::new_with_dtor(mem, n,
                                |mem| { libc::free((mem) as *mut _); })
        }
    }

    #[test]
    fn vec_test_basic() {
        let mut cv = v_malloc(16);

        *cv.get_mut(3).unwrap() = 8;
        *cv.get_mut(4).unwrap() = 9;
        assert_eq!(*cv.get(3).unwrap(), 8);
        assert_eq!(*cv.get(4).unwrap(), 9);
        assert_eq!(cv.len(), 16);
    }

    #[test]
    fn slice_test_basic() {
        let mut cs = s_malloc(16);

        *cs.get_mut(3).unwrap() = 8;
        *cs.get_mut(4).unwrap() = 9;
        assert_eq!(*cs.get(3).unwrap(), 8);
        assert_eq!(*cs.get(4).unwrap(), 9);
        assert_eq!(cs.len(), 16);
    }

    #[test]
    #[should_fail]
    fn vec_test_panic_at_null() {
        unsafe {
            CVec::new(Unique::new(ptr::null_mut::<u8>()), 9);
        }
    }

    #[test]
    #[should_fail]
    fn slice_test_panic_at_null() {
        unsafe {
            CSlice::new(ptr::null_mut::<u8>(), 9);
        }
    }

    #[test]
    fn vec_test_overrun_get() {
        let cv = v_malloc(16);

        assert!(cv.get(17).is_none());
    }

    #[test]
    fn slice_test_overrun_get() {
        let cs = s_malloc(16);

        assert!(cs.get(17).is_none());
    }

    #[test]
    fn vec_test_overrun_set() {
        let mut cv = v_malloc(16);

        assert!(cv.get_mut(17).is_none());
    }

    #[test]
    fn slice_test_overrun_set() {
        let mut cs = s_malloc(16);

        assert!(cs.get_mut(17).is_none());
    }

    #[test]
    fn vec_test_unwrap() {
        unsafe {
            let cv = CVec::new_with_dtor(Unique::new(1 as *mut isize),
                                         0,
                                         |_| panic!("Don't run this destructor!"));
            let p = cv.into_inner();
            assert_eq!(p, 1 as *mut isize);
        }
    }

    #[test]
    fn slice_test_unwrap() {
        unsafe {
            let cs = CSlice::new_with_dtor(1 as *mut isize,
                                         0,
                                         |_| panic!("Don't run this destructor!"));
            let ps = cs.into_inner();
            assert_eq!(ps, 1 as *mut isize);
        }
    }
}
<commit_msg>Changes in CSlice struct<commit_after>// Copyright 2012 The Rust Project Developers.
// Copyright 2015 Guillaume Gomez
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Library to interface with chunks of memory allocated in C.
//!
//! It is often desirable to safely interface with memory allocated from C,
//! encapsulating the unsafety into allocation and destruction time.  Indeed,
//! allocating memory externally is currently the only way to give Rust shared
//! mut state with C programs that keep their own references; vectors are
//! unsuitable because they could be reallocated or moved at any time, and
//! importing C memory into a vector takes a one-time snapshot of the memory.
//!
//! This module simplifies the usage of such external blocks of memory.  Memory
//! is encapsulated into an opaque object after creation; the lifecycle of the
//! memory can be optionally managed by Rust, if an appropriate destructor
//! closure is provided.  Safety is ensured by bounds-checking accesses, which
//! are marshalled through get and set functions.
//!
//! There are three unsafe functions: the two constructors, and the
//! unwrapping method. The constructors are unsafe for the
//! obvious reason (they act on a pointer that cannot be checked inside the
//! method), but `into_inner()` is somewhat more subtle in its unsafety.
//! It returns the contained pointer, but at the same time destroys the CVec
//! without running its destructor. This can be used to pass memory back to
//! C, but care must be taken that the ownership of underlying resources are
//! handled correctly, i.e. that allocated memory is eventually freed
//! if necessary.

#![feature(unsafe_destructor, core, std_misc, unique)]

use std::mem;
use std::ptr;
use std::raw;
use std::ptr::Unique;
use std::thunk::Invoke;
use std::ops::{Index, IndexMut};

/// The type representing a foreign chunk of memory
pub struct CVec<T> {
    base: Unique<T>,
    len: usize,
    dtor: Option<Box<Invoke<*mut T> + 'static>>
}

#[unsafe_destructor]
impl<T> Drop for CVec<T> {
    fn drop(&mut self) {
        match self.dtor.take() {
            None => (),
            Some(f) => f.invoke(*self.base),
        }
    }
}

impl<T> CVec<T> {
    /// Create a `CVec` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: Unique<T>, len: usize) -> CVec<T> {
        assert!(*base != ptr::null_mut());
        CVec {
            base: base,
            len: len,
            dtor: None,
        }
    }

    /// Create a `CVec` from a foreign buffer, with a given length,
    /// and a function to run upon destruction.
    ///
    /// Panics if the given pointer is null.
    ///
    /// # Arguments
    ///
    /// * base - A unique pointer to a buffer
    /// * len - The number of elements in the buffer
    /// * dtor - A fn to run when the value is destructed, useful
    ///          for freeing the buffer, etc. `base` will be passed
    ///          to it as an argument.
    pub unsafe fn new_with_dtor<F>(base: Unique<T>,
                                   len: usize,
                                   dtor: F)
                                   -> CVec<T>
        where F : FnOnce(*mut T) + 'static
    {
        assert!(*base != ptr::null_mut());
        let dtor = Box::new(dtor);
        CVec {
            base: base,
            len: len,
            dtor: Some(dtor)
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Unwrap the pointer without running the destructor
    ///
    /// This method retrieves the underlying pointer, and in the process
    /// destroys the CVec but without running the destructor. A use case
    /// would be transferring ownership of the buffer to a C function, as
    /// in this case you would not want to run the destructor.
    ///
    /// Note that if you want to access the underlying pointer without
    /// cancelling the destructor, you can simply call `transmute` on the return
    /// value of `get(0)`.
    pub unsafe fn into_inner(mut self) -> *mut T {
        self.dtor = None;
        *self.base
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }

    /// Convert to CSlice
    pub fn as_cslice(&self) -> CSlice<T> {
        CSlice {
            base: *self.base,
            len: self.len
        }
    }
}

impl<T> AsSlice<T> for CVec<T> {
    /// View the stored data as a slice.
    fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            mem::transmute(raw::Slice { data: *self.base as *const T, len: self.len })
        }
    }
}

/// The type representing an 'unsafe' foreign chunk of memory
pub struct CSlice<T> {
    base: *mut T,
    len: usize
}

impl<T> CSlice<T> {
    /// Create a `CSlice` from a raw pointer to a buffer with a given length.
    ///
    /// Panics if the given pointer is null. The returned vector will not attempt
    /// to deallocate the vector when dropped.
    ///
    /// # Arguments
    ///
    /// * base - A raw pointer to a buffer
    /// * len - The number of elements in the buffer
    pub unsafe fn new(base: *mut T, len: usize) -> CSlice<T> {
        assert!(base != ptr::null_mut());
        CSlice {
            base: base,
            len: len
        }
    }

    /// View the stored data as a mutable slice.
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
        }
    }

    /// Retrieves an element at a given index, returning `None` if the requested
    /// index is greater than the length of the vector.
    pub fn get<'a>(&'a self, ofs: usize) -> Option<&'a T> {
        if ofs < self.len {
            Some(unsafe { &*self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Retrieves a mutable element at a given index, returning `None` if the
    /// requested index is greater than the length of the vector.
    pub fn get_mut<'a>(&'a mut self, ofs: usize) -> Option<&'a mut T> {
        if ofs < self.len {
            Some(unsafe { &mut *self.base.offset(ofs as isize) })
        } else {
            None
        }
    }

    /// Returns the number of items in this vector.
    pub fn len(&self) -> usize { self.len }

    /// Returns whether this vector is empty.
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<T> Index<usize> for CSlice<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: &usize) -> &'a T {
        assert!(*_index < self.len);
        unsafe { &*self.base.offset(*_index as isize) }
    }
}

impl<T> IndexMut<usize> for CSlice<T> {
    fn index_mut<'a>(&'a mut self, _index: &usize) -> &'a mut T {
        assert!(*_index < self.len);
        unsafe { &mut *self.base.offset(*_index as isize) }
    }
}

#[cfg(test)]
mod tests {
    extern crate alloc;
    extern crate libc;

    use super::{CVec, CSlice};
    use std::ptr::{self, Unique};

    // allocation of CVec
    fn v_malloc(n: usize) -> CVec<u8> {
        unsafe {
            let mem: Unique<u8> = Unique::new(
                libc::malloc(n as libc::size_t) as *mut _);
            if (*mem).is_null() { alloc::oom() }

            CVec::new_with_dtor(mem, n,
                                |mem| { libc::free((mem) as *mut _); })
        }
    }

    // allocation of CSlice
    fn s_malloc(n: usize) -> CSlice<u8> {
        unsafe {
            let mem: *mut u8 = libc::malloc(n as libc::size_t) as *mut _;
            if mem.is_null() { alloc::oom() }

            CSlice::new(mem, n)
        }
    }

    #[test]
    fn vec_test_basic() {
        let mut cv = v_malloc(16);

        *cv.get_mut(3).unwrap() = 8;
        *cv.get_mut(4).unwrap() = 9;
        assert_eq!(*cv.get(3).unwrap(), 8);
        assert_eq!(*cv.get(4).unwrap(), 9);
        assert_eq!(cv.len(), 16);
    }

    #[test]
    fn slice_test_basic() {
        let mut cs = s_malloc(16);

        cs[3] = 8;
        cs[4] = 9;
        assert_eq!(cs[3], 8);
        assert_eq!(cs[4], 9);
        assert_eq!(cs.len(), 16);
    }

    #[test]
    #[should_fail]
    fn vec_test_panic_at_null() {
        unsafe {
            CVec::new(Unique::new(ptr::null_mut::<u8>()), 9);
        }
    }

    #[test]
    #[should_fail]
    fn slice_test_panic_at_null() {
        unsafe {
            CSlice::new(ptr::null_mut::<u8>(), 9);
        }
    }

    #[test]
    fn vec_test_overrun_get() {
        let cv = v_malloc(16);

        assert!(cv.get(17).is_none());
    }

    #[test]
    #[should_fail]
    fn slice_test_overrun_get() {
        let cs = s_malloc(16);

        assert!(cs[17] == 18);
    }

    #[test]
    fn vec_test_overrun_set() {
        let mut cv = v_malloc(16);

        assert!(cv.get_mut(17).is_none());
    }

    #[test]
    fn vec_test_unwrap() {
        unsafe {
            let cv = CVec::new_with_dtor(Unique::new(1 as *mut isize),
                                         0,
                                         |_| panic!("Don't run this destructor!"));
            let p = cv.into_inner();
            assert_eq!(p, 1 as *mut isize);
        }
    }

    #[test]
    fn vec_to_slice_test() {
        unsafe {
            let mut cv = v_malloc(2);

            *cv.get_mut(0).unwrap() = 10;
            *cv.get_mut(1).unwrap() = 12;
            let cs = cv.as_cslice();

            assert_eq!(cs[0], 10);
            assert_eq!(cs[1], 12);
        }
    }

    #[test]
    fn slice_to_vec_test() {
        let cv = v_malloc(2);
        let mut cs = cv.as_cslice();

        cs[0] = 13;
        cs[1] = 26;
        assert_eq!(*cv.get(0).unwrap(), 13);
        assert_eq!(*cv.get(1).unwrap(), 26);
    }
}
<|endoftext|>