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

const DATA: &'static str = include_str!("../data/input_18.txt");

pub fn main() -> Vec<String> {
    let mut life = Life::from_str(DATA).unwrap();
    let lcount = life.nth(100).unwrap().lcount();

    let mut life = Life::from_str(DATA).unwrap();
    life.stick(0, 0);
    life.stick(0, 99);
    life.stick(99, 0);
    life.stick(99, 99);
    let lcount2 = life.nth(100).unwrap().lcount();

    vec![lcount.to_string(), lcount2.to_string()]
}

struct Life {
    size: (usize, usize),
    arr: [bool; 100 * 100],
    stuck: Vec<(usize, usize)>,
}

impl Life {
    fn new() -> Life {
        Life {
            size: (100, 100),
            arr: [false; 100 * 100],
            stuck: Vec::new(),
        }
    }

    fn stick(&mut self, x: usize, y: usize) {
        self.stuck.push((x, y));
    }

    fn to_string(&self) -> String {
        self.arr
            .chunks(self.size.0)
            .map(|l| {
                l.iter()
                 .map(|v| {
                     if *v {
                         '#'
                     } else {
                         '.'
                     }
                 })
                 .collect::<String>()
            })
            .collect::<Vec<String>>()
            .join("\n")
    }

    fn neighbors(x: usize, y: usize) -> Vec<(usize, usize)> {
        let mut n = Vec::new();
        if x != 0 {
            if y != 0 {
                n.push((x - 1, y - 1));
            }
            n.push((x - 1, y));
            if y != 99 {
                n.push((x - 1, y + 1));
            }
        }
        if y != 0 {
            n.push((x, y - 1));
        }
        if y != 99 {
            n.push((x, y + 1));
        }
        if x != 99 {
            if y != 0 {
                n.push((x + 1, y - 1));
            }
            n.push((x + 1, y));
            if y != 99 {
                n.push((x + 1, y + 1));
            }
        }
        n
    }

    fn lcount(&self) -> usize {
        self.arr
            .iter()
            .filter(|&&b| b == true)
            .count()
    }
}

impl FromStr for Life {
    type Err = ();

    fn from_str(data: &str) -> Result<Life, ()> {
        let mut life = Life::new();
        {
            for (l, c) in data.lines()
                              .enumerate()
                              .flat_map(move |(l, s)| {
                                  s.chars()
                                   .enumerate()
                                   .filter(|&(_, z)| z == '#')
                                   .map(move |(c, _)| (l, c))
                              }) {
                life.arr[l * life.size.0 + c] = true;
            }
        }
        Ok(life)
    }
}

impl fmt::Display for Life {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(&self.to_string(), f)
    }
}

impl Iterator for Life {
    type Item = Life;

    fn next(&mut self) -> Option<Life> {
        let mut next = [false; 100 * 100];

        for x in 0..100 {
            for y in 0..100 {
                let count = Life::neighbors(x, y)
                                .into_iter()
                                .map(|(x, y)| {
                                    let b = self.arr.get(x * self.size.0 + y);
                                    b.unwrap_or(&false).to_owned()
                                })
                                .filter(|b| *b == true)
                                .count();
                match (self.arr[x * self.size.0 + y], count) {
                    (true, 2) | (true, 3) => next[x * 100 + y] = true,
                    (true, _) => next[x * 100 + y] = false,
                    (false, 3) => next[x * 100 + y] = true,
                    (false, _) => next[x * 100 + y] = false,
                }
            }
        }
        for &(x, y) in &self.stuck {
            next[x * 100 + y] = true;
        }

        mem::swap(&mut self.arr, &mut next);

        Some(Life {
            size: self.size,
            arr: next,
            stuck: self.stuck.clone(),
        })
    }
}
<commit_msg>day 18: don't fix game size, build examples as tests<commit_after>use std::fmt;
use std::mem;
use std::str::FromStr;

const DATA: &'static str = include_str!("../data/input_18.txt");

pub fn main() -> Vec<String> {
    let mut life = DATA.parse::<Life>().unwrap();
    let lcount = life.nth(100).unwrap().lcount();

    let mut life = DATA.parse::<Life>().unwrap();
    life.stick(0, 0);
    life.stick(0, 99);
    life.stick(99, 0);
    life.stick(99, 99);
    let lcount2 = life.nth(100).unwrap().lcount();

    vec![lcount.to_string(), lcount2.to_string()]
}

struct Life {
    size: (usize, usize),
    arr: Box<[bool]>,
    stuck: Vec<(usize, usize)>,
}

impl Life {
    fn new(x: usize, y: usize) -> Life {
        Life {
            size: (x, y),
            arr: vec![false; x * y].into_boxed_slice(),
            stuck: Vec::new(),
        }
    }

    fn get(&self, x: usize, y: usize) -> Option<bool> {
        if (x < self.size.0) && (y < self.size.1) {
            self.arr.get(x * self.size.0 + y).map(&bool::to_owned)
        } else {
            None
        }
    }

    fn stick(&mut self, x: usize, y: usize) {
        self.arr[x * self.size.0 + y] = true;
        self.stuck.push((x, y));
    }

    fn to_string(&self) -> String {
        self.arr
            .chunks(self.size.0)
            .map(|l| {
                l.iter()
                 .map(|v| {
                     if *v {
                         '#'
                     } else {
                         '.'
                     }
                 })
                 .collect::<String>()
            })
            .collect::<Vec<String>>()
            .join("\n")
    }

    fn neighbors(&self, x: usize, y: usize) -> Vec<(usize, usize)> {
        vec![(x - 1, y - 1),
             (x - 1, y),
             (x - 1, y + 1),
             (x, y - 1),
             (x, y + 1),
             (x + 1, y - 1),
             (x + 1, y),
             (x + 1, y + 1)]
    }

    fn lcount(&self) -> usize {
        self.arr
            .iter()
            .filter(|&&b| b == true)
            .count()
    }
}

impl FromStr for Life {
    type Err = ();

    fn from_str(data: &str) -> Result<Life, ()> {
        let mut buff = vec![false; data.len()];

        let mut lines = data.lines();
        let x = lines.next().map_or(0, str::len);
        if !lines.all(|s| s.len() == x) {
            return Err(());
        }
        let mut y = 0;

        for index in data.lines()
                         .inspect(|_| y = y + 1)
                         .enumerate()
                         .flat_map(|(l, s)| {
                             s.chars()
                              .enumerate()
                              .filter(|&(_, z)| z == '#')
                              .map(move |(c, _)| l * s.len() + c)
                         }) {
            buff[index] = true;
        }

        Ok(Life {
            arr: {
                buff.resize(x * y, false);
                buff.into_boxed_slice()
            },
            ..Life::new(x, y)
        })
    }
}

impl fmt::Display for Life {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(&self.to_string(), f)
    }
}

impl Iterator for Life {
    type Item = Life;

    fn next(&mut self) -> Option<Life> {
        let mut next = vec![false; self.size.0 * self.size.1].into_boxed_slice();

        for x in 0..self.size.0 {
            for y in 0..self.size.1 {
                let count = self.neighbors(x, y)
                                .into_iter()
                                .map(|(x, y)| self.get(x, y).unwrap_or(false))
                                .filter(|b| *b == true)
                                .count();
                match (self.arr[x * self.size.0 + y], count) {
                    (true, 2) | (true, 3) => next[x * self.size.0 + y] = true,
                    (true, _) => next[x * self.size.0 + y] = false,
                    (false, 3) => next[x * self.size.0 + y] = true,
                    (false, _) => next[x * self.size.0 + y] = false,
                }
            }
        }
        for &(x, y) in &self.stuck {
            next[x * self.size.0 + y] = true;
        }

        mem::swap(&mut self.arr, &mut next);

        Some(Life {
            size: self.size,
            arr: next,
            stuck: self.stuck.clone(),
        })
    }
}

#[cfg(test)]
mod test {
    use super::Life;
    const EXAMPLE_DATA: [&'static str; 6] = [".#.#.#", "...##.", "#....#",
                                             "..#...", "#.#..#", "####.."];

    #[test]
    fn examples_1() {
        let life = EXAMPLE_DATA.join("\n").parse::<Life>().unwrap();
        let lcount = life.inspect(|l| println!("\n{}", l))
                         .nth(4)
                         .unwrap()
                         .lcount();
        assert_eq!(lcount, 4);
    }

    #[test]
    fn examples_2() {
        let mut life = EXAMPLE_DATA.join("\n").parse::<Life>().unwrap();
        life.stick(0, 0);
        life.stick(0, 5);
        life.stick(5, 0);
        life.stick(5, 5);
        let lcount = life.inspect(|l| println!("\n{}", l))
                         .nth(5)
                         .unwrap()
                         .lcount();
        assert_eq!(lcount, 17);
    }
}
<|endoftext|>


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

pub enum LazyFile {
    Absent(PathBuf),
    File(File)
}

fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).open(p)
}

fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).create(true).open(p)
}

impl LazyFile {
    pub fn new(p: PathBuf) -> LazyFile {
        LazyFile::Absent(p)
    }
    pub fn new_with_file(f: File) -> LazyFile {
        LazyFile::File(f)
    }

    pub fn get_file(&mut self) -> Result<&File, StoreError> {
        let file = match *self {
            LazyFile::File(ref f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))

            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    pub fn get_file_mut(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    pub fn create_file(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(create_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::LazyFile;
    use std::io::{Read, Write};
    use std::path::PathBuf;
    use std::fs::File;
    use tempdir::TempDir;

    fn get_dir() -> TempDir {
        TempDir::new("test-image").unwrap()
    }

    #[test]
    fn lazy_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test1");
        let mut lf = LazyFile::new(path);

        write!(lf.create_file().unwrap(), "Hello World").unwrap();
        dir.close().unwrap();
    }

    #[test]
    fn lazy_file_with_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test2");

        {
            let mut lf = LazyFile::new(path.clone());
            let mut file = lf.create_file().unwrap();

            file.write(b"Hello World").unwrap();
            file.sync_all().unwrap();
        }

        {
            let mut lf = LazyFile::new(path);
            let mut file = lf.create_file().unwrap();

            let mut s = Vec::new();
            file.read_to_end(&mut s).unwrap();
            assert_eq!(s, "Hello World".to_string().into_bytes());
        }

        dir.close().unwrap();
    }
}
<commit_msg>Seek to beginning of file before reading<commit_after>
use error::{StoreError, StoreErrorKind};
use std::io::{Seek, SeekFrom};
use std::path::{Path, PathBuf};
use std::fs::{File, OpenOptions};

pub enum LazyFile {
    Absent(PathBuf),
    File(File)
}

fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).open(p)
}

fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).create(true).open(p)
}

impl LazyFile {
    pub fn new(p: PathBuf) -> LazyFile {
        LazyFile::Absent(p)
    }
    pub fn new_with_file(f: File) -> LazyFile {
        LazyFile::File(f)
    }

    pub fn get_file(&mut self) -> Result<&File, StoreError> {
        match self.get_file_mut() {
            Ok(file) => Ok(&*file),
            Err(e) => Err(e)
        }
    }

    pub fn get_file_mut(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return {
                // We seek to the beginning of the file since we expect each
                // access to the file to be in a different context
                f.seek(SeekFrom::Start(0)).map_err(|e|
                    StoreError::new(
                        StoreErrorKind::FileNotCreated, Some(Box::new(e))));
                Ok(f)
            },
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    pub fn create_file(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(create_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::LazyFile;
    use std::io::{Read, Write, Seek, SeekFrom};
    use std::path::PathBuf;
    use std::fs::File;
    use tempdir::TempDir;

    fn get_dir() -> TempDir {
        TempDir::new("test-image").unwrap()
    }

    #[test]
    fn lazy_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test1");
        let mut lf = LazyFile::new(path);

        write!(lf.create_file().unwrap(), "Hello World").unwrap();
        dir.close().unwrap();
    }

    #[test]
    fn lazy_file_with_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test2");
        let mut lf = LazyFile::new(path.clone());

        {
            let mut file = lf.create_file().unwrap();

            file.write(b"Hello World").unwrap();
            file.sync_all().unwrap();
        }

        {
            let mut file = lf.get_file().unwrap();
            let mut s = Vec::new();
            file.read_to_end(&mut s).unwrap();
            assert_eq!(s, "Hello World".to_string().into_bytes());
        }

        dir.close().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::string::String;
use std::path::Path;
use std::vec::Vec;
use std::io::{BufReader};
use json;
use game::data::Rectangle;
use tiled::{Map};
use tiled;

pub fn load_map_file(filename: &str) -> Map {
  let file = match File::open(&Path::new(&filename)) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let reader = BufReader::new(file);
  match tiled::parse(reader) {
    Ok(m) => m,
    Err(e) => panic!("Map parse error {:?}", e)
  }
}

pub fn get_tile(map: &Map, layer_index: usize, x: usize, y: usize) -> u32 {
  let layer = match map.layers.get(layer_index) {
    None => panic!("layer_index value out of index {:?}", map.layers),
    Some(ref l) => *l
  };
  let y_index = match layer.tiles.iter().nth(y) {
    None => panic!("x value out of index {:?}", map.layers[0]),
    Some(ref x) => *x
  };
  let val = match y_index.get(x) {
    None => panic!("y value out of index {:?}", layer.tiles[y]),
    Some(ref val) => **val
  };
  val
}

fn read_sprite_file(filename: &str) -> String {
  let path = Path::new(&filename);
  let mut file = match File::open(&path) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let mut buf = String::new();
  match file.read_to_string(&mut buf) {
    Ok(_) => buf,
    Err(_) => panic!("Couldn't read file {}", filename),
  }
}

pub fn load_character() -> Vec<Rectangle> {
  let mut sprites = Vec::with_capacity(512);
  let mut move_sprite_names = Vec::with_capacity(256);
  let mut fire_sprite_names = Vec::with_capacity(256);
  let character_json = read_sprite_file("./assets/character.json");
  let character = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };
  for x in 0..15 {
    for y in 0..14 {
      move_sprite_names.push(format!("run_{}_{}", x, y));
    }
  }
  for x in 0..15 {
    for y in 0..3 {
      fire_sprite_names.push(format!("fire_{}_{}", x, y));
    }
  }

  for &ref move_sprite in &move_sprite_names {
    let x = character["frames"][move_sprite]["frame"]["x"].as_f64().unwrap();
    let y = character["frames"][move_sprite]["frame"]["y"].as_f64().unwrap();
    let w = character["frames"][move_sprite]["frame"]["w"].as_f64().unwrap();
    let h = character["frames"][move_sprite]["frame"]["h"].as_f64().unwrap();
    sprites.push(Rectangle {
      w: w,
      h: h,
      x: x,
      y: y,
    });
  }

  for &ref fire_sprite in &fire_sprite_names {
    let x = character["frames"][fire_sprite]["frame"]["x"].as_f64().unwrap();
    let y = character["frames"][fire_sprite]["frame"]["y"].as_f64().unwrap();
    let w = character["frames"][fire_sprite]["frame"]["w"].as_f64().unwrap();
    let h = character["frames"][fire_sprite]["frame"]["h"].as_f64().unwrap();
    sprites.push(Rectangle {
      w: w,
      h: h,
      x: x,
      y: y,
    });
  }
  sprites
}

pub fn load_zombie() -> Vec<Rectangle> {
  let mut sprites = Vec::with_capacity(512);
  let mut idle_sprite_names = Vec::with_capacity(256);
  let character_json = read_sprite_file("./assets/zombie.json");
  let zombie = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };

  for x in 0..7 {
    for y in 0..3 {
      idle_sprite_names.push(format!("idle_{}_{}", x, y));
    }
  }

  for &ref idle_sprite in &idle_sprite_names {
    let x = zombie["frames"][idle_sprite]["frame"]["x"].as_f64().unwrap();
    let y = zombie["frames"][idle_sprite]["frame"]["y"].as_f64().unwrap();
    let w = zombie["frames"][idle_sprite]["frame"]["w"].as_f64().unwrap();
    let h = zombie["frames"][idle_sprite]["frame"]["h"].as_f64().unwrap();
    sprites.push(Rectangle {
      w: w,
      h: h,
      x: x,
      y: y,
    });
  }
  sprites
}
<commit_msg>Load move sprites for zombie<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::string::String;
use std::path::Path;
use std::vec::Vec;
use std::io::{BufReader};
use json;
use game::data::Rectangle;
use tiled::{Map};
use tiled;

pub fn load_map_file(filename: &str) -> Map {
  let file = match File::open(&Path::new(&filename)) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let reader = BufReader::new(file);
  match tiled::parse(reader) {
    Ok(m) => m,
    Err(e) => panic!("Map parse error {:?}", e)
  }
}

pub fn get_tile(map: &Map, layer_index: usize, x: usize, y: usize) -> u32 {
  let layer = match map.layers.get(layer_index) {
    None => panic!("layer_index value out of index {:?}", map.layers),
    Some(ref l) => *l
  };
  let y_index = match layer.tiles.iter().nth(y) {
    None => panic!("x value out of index {:?}", map.layers[0]),
    Some(ref x) => *x
  };
  let val = match y_index.get(x) {
    None => panic!("y value out of index {:?}", layer.tiles[y]),
    Some(ref val) => **val
  };
  val
}

fn read_sprite_file(filename: &str) -> String {
  let path = Path::new(&filename);
  let mut file = match File::open(&path) {
    Ok(f) => f,
    Err(e) => panic!("File {} not found: {}", filename, e),
  };
  let mut buf = String::new();
  match file.read_to_string(&mut buf) {
    Ok(_) => buf,
    Err(_) => panic!("Couldn't read file {}", filename),
  }
}

pub fn load_character() -> Vec<Rectangle> {
  let mut sprites = Vec::with_capacity(512);
  let mut move_sprite_names = Vec::with_capacity(256);
  let mut fire_sprite_names = Vec::with_capacity(256);
  let character_json = read_sprite_file("./assets/character.json");
  let character = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };
  for x in 0..15 {
    for y in 0..14 {
      move_sprite_names.push(format!("run_{}_{}", x, y));
    }
  }
  for x in 0..15 {
    for y in 0..3 {
      fire_sprite_names.push(format!("fire_{}_{}", x, y));
    }
  }

  for &ref move_sprite in &move_sprite_names {
    let x = character["frames"][move_sprite]["frame"]["x"].as_f64().unwrap();
    let y = character["frames"][move_sprite]["frame"]["y"].as_f64().unwrap();
    let w = character["frames"][move_sprite]["frame"]["w"].as_f64().unwrap();
    let h = character["frames"][move_sprite]["frame"]["h"].as_f64().unwrap();
    sprites.push(Rectangle {
      w: w,
      h: h,
      x: x,
      y: y,
    });
  }

  for &ref fire_sprite in &fire_sprite_names {
    let x = character["frames"][fire_sprite]["frame"]["x"].as_f64().unwrap();
    let y = character["frames"][fire_sprite]["frame"]["y"].as_f64().unwrap();
    let w = character["frames"][fire_sprite]["frame"]["w"].as_f64().unwrap();
    let h = character["frames"][fire_sprite]["frame"]["h"].as_f64().unwrap();
    sprites.push(Rectangle {
      w: w,
      h: h,
      x: x,
      y: y,
    });
  }
  sprites
}

pub fn load_zombie() -> Vec<Rectangle> {
  let mut sprites = Vec::with_capacity(256);
  let mut idle_sprite_names = Vec::with_capacity(64);
  let mut walk_sprite_names = Vec::with_capacity(64);
  let character_json = read_sprite_file("./assets/zombie.json");
  let zombie = match json::parse(&character_json) {
    Ok(res) => res,
    Err(e) => panic!("Character JSON parse error {:?}", e),
  };

  for x in 0..7 {
    for y in 0..3 {
      idle_sprite_names.push(format!("idle_{}_{}", x, y));
    }
  }

  for x in 0..7 {
    for y in 0..3 {
      walk_sprite_names.push(format!("walk_{}_{}", x, y));
    }
  }

  for &ref idle_sprite in &idle_sprite_names {
    let x = zombie["frames"][idle_sprite]["frame"]["x"].as_f64().unwrap();
    let y = zombie["frames"][idle_sprite]["frame"]["y"].as_f64().unwrap();
    let w = zombie["frames"][idle_sprite]["frame"]["w"].as_f64().unwrap();
    let h = zombie["frames"][idle_sprite]["frame"]["h"].as_f64().unwrap();
    sprites.push(Rectangle {
      w: w,
      h: h,
      x: x,
      y: y,
    });
  }

  for &ref walk_sprite in &walk_sprite_names {
    let x = zombie["frames"][walk_sprite]["frame"]["x"].as_f64().unwrap();
    let y = zombie["frames"][walk_sprite]["frame"]["y"].as_f64().unwrap();
    let w = zombie["frames"][walk_sprite]["frame"]["w"].as_f64().unwrap();
    let h = zombie["frames"][walk_sprite]["frame"]["h"].as_f64().unwrap();
    sprites.push(Rectangle {
      w: w,
      h: h,
      x: x,
      y: y,
    });
  }
  sprites
}
<|endoftext|>


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

#[phase(plugin)]
extern crate gl_generator;

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use self::glutin::{Event, VirtualKeyCode}; // TODO: why 'self'?
use core_types::{Size2, MInt};
use visualizer_types::{Color3, Color4, ColorId};
use mgl::Mgl;
use mgl;
use std::mem;

// TODO: remove 'gl'
use gl;
use gl::types::{GLfloat, GLuint};

static VS_SRC: &'static str = "\
    #version 100\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

pub struct Visualizer {
    mgl: Mgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    program: GLuint,
    color_unifrom_location: ColorId,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window = glutin::Window::new().unwrap(); // TODO: unwrap -> expect
        unsafe {
            window.make_current();
        };
        let mgl = Mgl::new(|s| window.get_proc_address(s));
        // TODO: extract to separate func 'print_gl_info'
        println!("GL_VERSION: {}", mgl.get_info(gl::VERSION));
        println!("GL_SHADING_LANGUAGE_VERSION: {}", mgl.get_info(gl::SHADING_LANGUAGE_VERSION));
        println!("GL_VENDOR: {}", mgl.get_info(gl::VENDOR));
        println!("GL_RENDERER: {}", mgl.get_info(gl::RENDERER));
        // println!("GL_EXTENSIONS: {}", mgl.get_info(gl::EXTENSIONS));
        // TODO: extract to separate func 'compile_shaders'
        let vs = mgl::compile_shader(&mgl.gl, VS_SRC, gl::VERTEX_SHADER);
        let fs = mgl::compile_shader(&mgl.gl, FS_SRC, gl::FRAGMENT_SHADER);
        let program = mgl::link_program(&mgl.gl, vs, fs);
        let color_unifrom_location = ColorId {
            id: mgl.get_uniform(program, "col") as GLuint
        };
        Visualizer {
            mgl: mgl,
            window: window,
            should_close: false,
            color_counter: 0,
            program: program,
            color_unifrom_location: color_unifrom_location,
        }
    }

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

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if !events.is_empty() {
            println!("{}", events);
        }
        for event in events.iter() {
            match *event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape))
                    | Event::Closed =>
                {
                    self.should_close = true;
                },
                _ => {},
            }
        }
    }

    fn draw(&mut self) {
        match self.color_counter {
            0 => self.mgl.set_clear_color(Color3{r: 0.5, g: 0.0, b: 0.0}),
            30 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.5, b: 0.0}),
            60 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.5}),
            _ => if self.color_counter > 90 {
                self.color_counter = -1;
            },
        }
        self.color_counter += 1;
        self.mgl.clear_screen();
        unsafe {
            let vertices: [GLfloat, ..3 * 3] = [
                0.0,  0.5, 0.0,
                0.5, -0.5, 0.0,
                -0.5, -0.5, 0.0,
            ];
            let (w, h) = self.window.get_inner_size().unwrap(); // TODO: unwrap -> expect
            self.mgl.set_viewport(Size2{w: w as MInt, h: h as MInt});
            self.mgl.gl.UseProgram(self.program);
            self.mgl.set_uniform_color(
                self.color_unifrom_location, Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0});
            self.mgl.gl.VertexAttribPointer(
                0, 3, gl::FLOAT, gl::FALSE, 0, mem::transmute(&vertices));
            self.mgl.gl.EnableVertexAttribArray(0);
            self.mgl.gl.DrawArrays(gl::TRIANGLES, 0, 3);
        }
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>src/visualizer.rs: 'fn print_gl_info'<commit_after>// See LICENSE file for copyright and license details.

#[phase(plugin)]
extern crate gl_generator;

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use self::glutin::{Event, VirtualKeyCode}; // TODO: why 'self'?
use core_types::{Size2, MInt};
use visualizer_types::{Color3, Color4, ColorId};
use mgl::Mgl;
use mgl;
use std::mem;

// TODO: remove 'gl'
use gl;
use gl::types::{GLfloat, GLuint};

static VS_SRC: &'static str = "\
    #version 100\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn print_gl_info(mgl: &Mgl) {
    println!("GL_VERSION: {}", mgl.get_info(gl::VERSION));
    println!("GL_SHADING_LANGUAGE_VERSION: {}", mgl.get_info(gl::SHADING_LANGUAGE_VERSION));
    println!("GL_VENDOR: {}", mgl.get_info(gl::VENDOR));
    println!("GL_RENDERER: {}", mgl.get_info(gl::RENDERER));
    // println!("GL_EXTENSIONS: {}", mgl.get_info(gl::EXTENSIONS));
}

pub struct Visualizer {
    mgl: Mgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    program: GLuint,
    color_unifrom_location: ColorId,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window = glutin::Window::new().unwrap(); // TODO: unwrap -> expect
        unsafe {
            window.make_current();
        };
        let mgl = Mgl::new(|s| window.get_proc_address(s));
        print_gl_info(&mgl);
        // TODO: extract to separate func 'compile_shaders'
        let vs = mgl::compile_shader(&mgl.gl, VS_SRC, gl::VERTEX_SHADER);
        let fs = mgl::compile_shader(&mgl.gl, FS_SRC, gl::FRAGMENT_SHADER);
        let program = mgl::link_program(&mgl.gl, vs, fs);
        let color_unifrom_location = ColorId {
            id: mgl.get_uniform(program, "col") as GLuint
        };
        Visualizer {
            mgl: mgl,
            window: window,
            should_close: false,
            color_counter: 0,
            program: program,
            color_unifrom_location: color_unifrom_location,
        }
    }

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

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if !events.is_empty() {
            println!("{}", events);
        }
        for event in events.iter() {
            match *event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape))
                    | Event::Closed =>
                {
                    self.should_close = true;
                },
                _ => {},
            }
        }
    }

    fn draw(&mut self) {
        match self.color_counter {
            0 => self.mgl.set_clear_color(Color3{r: 0.5, g: 0.0, b: 0.0}),
            30 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.5, b: 0.0}),
            60 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.5}),
            _ => if self.color_counter > 90 {
                self.color_counter = -1;
            },
        }
        self.color_counter += 1;
        self.mgl.clear_screen();
        unsafe {
            let vertices: [GLfloat, ..3 * 3] = [
                0.0,  0.5, 0.0,
                0.5, -0.5, 0.0,
                -0.5, -0.5, 0.0,
            ];
            let (w, h) = self.window.get_inner_size().unwrap(); // TODO: unwrap -> expect
            self.mgl.set_viewport(Size2{w: w as MInt, h: h as MInt});
            self.mgl.gl.UseProgram(self.program);
            self.mgl.set_uniform_color(
                self.color_unifrom_location, Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0});
            self.mgl.gl.VertexAttribPointer(
                0, 3, gl::FLOAT, gl::FALSE, 0, mem::transmute(&vertices));
            self.mgl.gl.EnableVertexAttribArray(0);
            self.mgl.gl.DrawArrays(gl::TRIANGLES, 0, 3);
        }
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.draw();
        // self.update_time();
    }
}

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


<commit_before>extern crate rand;

use self::rand::{thread_rng, Rng};
use card;

mod tests;

pub struct Deck {
    pub cards: Vec<card::Card>
}

impl Deck {
    pub fn new() -> Deck {
        let mut cards: Vec<card::Card> = vec![];

        for value in 0..13 {
            for suit in 0..4 {
                let value = match value {
                    0   =>  card::Value::Two,
                    1   =>  card::Value::Three,
                    2   =>  card::Value::Four,
                    3   =>  card::Value::Five,
                    4   =>  card::Value::Six,
                    5   =>  card::Value::Seven,
                    6   =>  card::Value::Eight,
                    7   =>  card::Value::Nine,
                    8   =>  card::Value::Ten,
                    9   =>  card::Value::Jack,
                    10  =>  card::Value::Queen,
                    11  =>  card::Value::King,
                    12  =>  card::Value::Ace,
                    _   =>  card::Value::None
                };
                let suit = match suit {
                    0   =>  card::Suit::Diamonds,
                    1   =>  card::Suit::Clubs,
                    2   =>  card::Suit::Hearts,
                    3   =>  card::Suit::Spades,
                    _   =>  card::Suit::None
                };
                cards.push(card::Card {
                    value: value,
                    suit: suit
                });
            }
        }

        thread_rng().shuffle(&mut cards);

        Deck {
            cards: cards
        }
    }
}
<commit_msg>Added draw() method to deck<commit_after>extern crate rand;

use self::rand::{thread_rng, Rng};
use card;

mod tests;

pub struct Deck {
    pub cards: Vec<card::Card>
}

impl Deck {
    pub fn new() -> Deck {
        let mut cards: Vec<card::Card> = vec![];

        for value in 0..13 {
            for suit in 0..4 {
                let value = match value {
                    0   =>  card::Value::Two,
                    1   =>  card::Value::Three,
                    2   =>  card::Value::Four,
                    3   =>  card::Value::Five,
                    4   =>  card::Value::Six,
                    5   =>  card::Value::Seven,
                    6   =>  card::Value::Eight,
                    7   =>  card::Value::Nine,
                    8   =>  card::Value::Ten,
                    9   =>  card::Value::Jack,
                    10  =>  card::Value::Queen,
                    11  =>  card::Value::King,
                    12  =>  card::Value::Ace,
                    _   =>  card::Value::None
                };
                let suit = match suit {
                    0   =>  card::Suit::Diamonds,
                    1   =>  card::Suit::Clubs,
                    2   =>  card::Suit::Hearts,
                    3   =>  card::Suit::Spades,
                    _   =>  card::Suit::None
                };
                cards.push(card::Card {
                    value: value,
                    suit: suit
                });
            }
        }

        thread_rng().shuffle(&mut cards);

        Deck {
            cards: cards
        }
    }

    pub fn draw(&mut self) -> card::Card {
        let idx = self.cards.len() - 1;
        self.cards.remove(idx)
    }
}
<|endoftext|>


<commit_before>extern crate rocksdb;

use std::{error, fmt};
use std::num::ParseIntError;
use std::num::ParseFloatError;
use std::io;

#[derive(Debug)]
pub enum Error {
    Parse(String),
    Shred(String),
    Rocks(rocksdb::Error),
    Write(String),
    Io(io::Error),
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        self == other
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Parse(ref description) => description,
            Error::Shred(ref description) => description,
            // XXX vmx 2016-11-07: It should be fixed on the RocksDB wrapper
            // that it has the std::error:Error implemented and hence
            // and err.description()
            Error::Rocks(_) => "This is an rocksdb error",
            Error::Write(ref description) => description,
            Error::Io(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            Error::Parse(_) => None,
            Error::Shred(_) => None,
            // NOTE vmx 2016-11-07: Looks like the RocksDB Wrapper needs to be
            // patched to be based on the std::error::Error trait
            Error::Rocks(_) => None,
            Error::Write(_) => None,
            Error::Io(ref err) => Some(err as &dyn error::Error),
        }
    }
}

impl From<rocksdb::Error> for Error {
    fn from(err: rocksdb::Error) -> Error {
        Error::Rocks(err)
    }
}

impl From<ParseIntError> for Error {
    fn from(err: ParseIntError) -> Error {
        Error::Parse(err.to_string())
    }
}

impl From<ParseFloatError> for Error {
    fn from(err: ParseFloatError) -> Error {
        Error::Parse(err.to_string())
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Parse(ref err) => write!(f, "Parse error: {}", err),
            Error::Shred(ref err) => write!(f, "Shred error: {}", err),
            Error::Rocks(ref err) => write!(f, "RocksDB error: {}", err),
            Error::Write(ref err) => write!(f, "Write error: {}", err),
            Error::Io(ref err) => write!(f, "Io error: {}", err),
        }
    }
}
<commit_msg>errors: Fix a warning with description() being deprecated.<commit_after>extern crate rocksdb;

use std::{error, fmt};
use std::num::ParseIntError;
use std::num::ParseFloatError;
use std::io;

#[derive(Debug)]
pub enum Error {
    Parse(String),
    Shred(String),
    Rocks(rocksdb::Error),
    Write(String),
    Io(io::Error),
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        self == other
    }
}

impl error::Error for Error {
    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            Error::Parse(_) => None,
            Error::Shred(_) => None,
            // NOTE vmx 2016-11-07: Looks like the RocksDB Wrapper needs to be
            // patched to be based on the std::error::Error trait
            Error::Rocks(_) => None,
            Error::Write(_) => None,
            Error::Io(ref err) => Some(err as &dyn error::Error),
        }
    }
}

impl From<rocksdb::Error> for Error {
    fn from(err: rocksdb::Error) -> Error {
        Error::Rocks(err)
    }
}

impl From<ParseIntError> for Error {
    fn from(err: ParseIntError) -> Error {
        Error::Parse(err.to_string())
    }
}

impl From<ParseFloatError> for Error {
    fn from(err: ParseFloatError) -> Error {
        Error::Parse(err.to_string())
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Parse(ref err) => write!(f, "Parse error: {}", err),
            Error::Shred(ref err) => write!(f, "Shred error: {}", err),
            Error::Rocks(ref err) => write!(f, "RocksDB error: {}", err),
            Error::Write(ref err) => write!(f, "Write error: {}", err),
            Error::Io(ref err) => write!(f, "Io error: {}", err),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// 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.

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

use buffer::Cursor;
use thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug)]
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test where Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate syn;
    ///
    /// use syn::{Ident, LitStr};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error which spans the items provided with the specified
    /// message.
    ///
    /// Unlike the `new` constructor this constructors takes a spanned item (the
    /// first argument here). This allows the `Error` returned to attempt to
    /// ensure it spans all the tokens inside of `tokens`. While you typically
    /// can use the `Spanned` trait with the above `new` constructor
    /// implementation limitations today mean that this constructor may provide
    /// a higher-quality error message on stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map(|t| t.span()).unwrap_or_else(Span::call_site);
        let end = iter.last().map(|t| t.span()).unwrap_or(start);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };

        #[cfg(procmacro2_semver_exempt)]
        {
            let end = match self.end_span.get() {
                Some(span) => *span,
                None => return Span::call_site(),
            };
            start.join(end).unwrap_or(start)
        }
        #[cfg(not(procmacro2_semver_exempt))]
        {
            start
        }
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<commit_msg>Address option_map_unwrap_or lint<commit_after>// Copyright 2018 Syn Developers
//
// 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.

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

use buffer::Cursor;
use thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug)]
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test where Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate syn;
    ///
    /// use syn::{Ident, LitStr};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error which spans the items provided with the specified
    /// message.
    ///
    /// Unlike the `new` constructor this constructors takes a spanned item (the
    /// first argument here). This allows the `Error` returned to attempt to
    /// ensure it spans all the tokens inside of `tokens`. While you typically
    /// can use the `Spanned` trait with the above `new` constructor
    /// implementation limitations today mean that this constructor may provide
    /// a higher-quality error message on stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };

        #[cfg(procmacro2_semver_exempt)]
        {
            let end = match self.end_span.get() {
                Some(span) => *span,
                None => return Span::call_site(),
            };
            start.join(end).unwrap_or(start)
        }
        #[cfg(not(procmacro2_semver_exempt))]
        {
            start
        }
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub struct CTError {
    pub kind: CTErrorKind,
    pub desc: String,
    pub pos: Option<(usize, usize)>,
}

#[derive(Debug, PartialEq)]
pub enum CTErrorKind {
    InputError,
    DatabaseError,
}

pub type CTResult<T> = Result<T, CTError>;

impl CTError {
    /// Pretty-prints the CTError struct to stdout
    pub fn print(&self, extra_desc: Option<&String>) {
        match self.kind {
            CTErrorKind::InputError => {
                println!("{}", self.desc);
                if let (Some((pos, len)), Some(input)) = (self.pos, extra_desc) {
                    println!("    {}", input);
                    print!("    ");
                    for _ in 0..pos {
                        print!(" ");
                    }
                    print!("^");
                    for _ in 1..len {
                        print!("~");
                    }
                    println!("");
                }
            },
            CTErrorKind::DatabaseError => {
                println!("{}", self.desc);
            }
        }
    }
}<commit_msg>Make CTError.print always print the desc<commit_after>#[derive(Debug, PartialEq)]
pub struct CTError {
    pub kind: CTErrorKind,
    pub desc: String,
    pub pos: Option<(usize, usize)>,
}

#[derive(Debug, PartialEq)]
pub enum CTErrorKind {
    InputError,
    DatabaseError,
    UsageError,
}

pub type CTResult<T> = Result<T, CTError>;

impl CTError {
    /// Pretty-prints the CTError struct to stdout
    pub fn print(&self, extra_desc: Option<&String>) {
        println!("{}", self.desc);
        // some errors will have extra stuff to report to make the message clearer for the user
        match self.kind {
            CTErrorKind::InputError => {
                if let (Some((pos, len)), Some(input)) = (self.pos, extra_desc) {
                    println!("    {}", input);
                    print!("    ");
                    for _ in 0..pos {
                        print!(" ");
                    }
                    print!("^");
                    for _ in 1..len {
                        print!("~");
                    }
                    println!("");
                }
            },
            _ => (),
        }
    }
}<|endoftext|>


<commit_before>use libc::{c_uint, c_void};

use std::ops::Index;
use num::{Integer, Zero, Bounded};
use std::error::{self, Error};
use std::ptr;
use std::fmt;

pub struct ErrorFrame {
    pub desc: String,
    pub func: String,
    pub major: String,
    pub minor: String
}

impl ErrorFrame {
    pub fn description(&self) -> &str {
        &self.desc
    }

    pub fn detail(&self) -> Option<String> {
        Some(format!("Error in {}(): {} [{}: {}]",
             self.func, self.desc, self.major, self.minor).clone())
    }
}

pub fn silence_errors() {
    use ffi::h5e::{H5Eset_auto2, H5E_DEFAULT};

    h5lock!(H5Eset_auto2(H5E_DEFAULT, None, ptr::null_mut::<c_void>()));
}

pub struct ErrorStack {
    frames: Vec<ErrorFrame>
}

impl Index<usize> for ErrorStack {
    type Output = ErrorFrame;

    fn index<'a>(&'a self, index: usize) -> &'a ErrorFrame {
        &self.frames[index]
    }
}

impl ErrorStack {
    // This low-level function is not thread-safe and has to be synchronized by the user
    pub fn query() -> Result<Option<ErrorStack>> {
        use ffi::types::herr_t;
        use ffi::util::{get_h5_str, string_from_cstr};
        use ffi::h5e::{H5Ewalk2, H5Eget_msg, H5E_error2_t, H5E_type_t, H5E_WALK_DOWNWARD,
                       H5Eget_current_stack, H5Eclose_stack};

        struct CallbackData {
            stack: ErrorStack,
            err: Option<H5Error>,
        }

        extern fn callback(_: c_uint, err_desc: *const H5E_error2_t, data: *mut c_void) -> herr_t {
            unsafe {
                let data = &mut *(data as *mut CallbackData);
                if data.err.is_some() {
                    return 0;
                }
                let closure = |e: H5E_error2_t| -> Result<ErrorFrame> {
                    let (desc, func) = (string_from_cstr(e.desc), string_from_cstr(e.func_name));
                    let major = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.maj_num, ptr::null_mut::<H5E_type_t>(), m, s)
                    }));
                    let minor = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.min_num, ptr::null_mut::<H5E_type_t>(), m, s)
                    }));
                    Ok(ErrorFrame { desc: desc, func: func, major: major, minor: minor })
                };
                match closure(*err_desc) {
                    Ok(frame) => { data.stack.push(frame); 0 },
                    Err(err)  => { data.err = Some(From::from(err)); 0 }
                }
            }
        }

        let mut data = CallbackData { stack: ErrorStack::new(), err: None };
        let data_ptr: *mut c_void = &mut data as *mut _ as *mut c_void;

        // known HDF5 bug: H5Eget_msg() may corrupt the current stack, so we copy it first
        unsafe {
            let stack_id = H5Eget_current_stack();
            ensure!(stack_id >= 0, "failed to copy the current error stack");
            H5Ewalk2(stack_id, H5E_WALK_DOWNWARD, Some(callback), data_ptr);
            H5Eclose_stack(stack_id)
        };

        match (data.err, data.stack.is_empty()) {
            (Some(err), _) => Err(err),
            (None, false)  => Ok(Some(data.stack)),
            (None, true)   => Ok(None),
        }
    }

    pub fn new() -> ErrorStack {
        ErrorStack { frames: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.frames.len()
    }

    pub fn push(&mut self, frame: ErrorFrame) {
        self.frames.push(frame)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn top(&self) -> Option<&ErrorFrame> {
        match !self.is_empty() {
            false => None,
            true  => Some(&self.frames[0]),
        }
    }

    pub fn description(&self) -> &str {
        match self.top() {
            None        => "unknown library error",
            Some(frame) => frame.description(),
        }
    }

    pub fn detail(&self) -> Option<String> {
        match self.top() {
            None        => None,
            Some(frame) => frame.detail(),
        }
    }
}

pub enum H5Error {
    LibraryError(ErrorStack),
    InternalError(&'static str),
}

pub type Result<T> = ::std::result::Result<T, H5Error>;

impl H5Error {
    pub fn query() -> Option<H5Error> {
        match ErrorStack::query() {
            Err(err)        => Some(From::from(err)),
            Ok(Some(stack)) => Some(H5Error::LibraryError(stack)),
            Ok(None)        => None,
        }
    }
}

impl From<&'static str> for H5Error {
    fn from(desc: &'static str) -> H5Error {
        H5Error::InternalError(desc)
    }
}

impl fmt::Debug for H5Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            H5Error::InternalError(desc)     => desc.fmt(formatter),
            H5Error::LibraryError(ref stack) => stack.detail().fmt(formatter),
        }
    }
}

impl fmt::Display for H5Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        self.description().fmt(formatter)
    }
}

impl error::Error for H5Error {
    fn description(&self) -> &str {
        match *self {
            H5Error::InternalError(desc)     => desc,
            H5Error::LibraryError(ref stack) => stack.description(),
        }
    }
}

pub fn h5check<T>(value: T) -> Result<T> where T: Integer + Zero + Bounded,
{
    let min_value: T = Bounded::min_value();
    let zero:      T = Zero::zero();

    let maybe_error = if min_value < zero {
        value < zero
    } else {
        value == zero
    };

    match maybe_error {
        false => Ok(value),
        true  => match H5Error::query() {
            None       => Ok(value),
            Some(err)  => Err(From::from(err)),
        },
    }
}

#[test]
pub fn test_error_stack() {
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};

    silence_errors();

    let result_no_error = h5lock!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id);
        ErrorStack::query()
    });
    assert!(result_no_error.ok().unwrap().is_none());

    let result_error = h5lock!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id);
        H5Pclose(plist_id);
        ErrorStack::query()
    });
    let stack = result_error.ok().unwrap().unwrap();
    assert_eq!(stack.description(), "can't close");
    assert_eq!(&stack.detail().unwrap(),
               "Error in H5Pclose(): can't close [Property lists: Unable to free object]");

    assert_eq!(stack.len(), 3);
    assert!(!stack.is_empty());

    assert_eq!(stack[0].description(), "can't close");
    assert_eq!(&stack[0].detail().unwrap(),
               "Error in H5Pclose(): can't close \
                [Property lists: Unable to free object]");

    assert_eq!(stack[1].description(), "can't decrement ID ref count");
    assert_eq!(&stack[1].detail().unwrap(),
               "Error in H5I_dec_app_ref(): can't decrement ID ref count \
                [Object atom: Unable to decrement reference count]");

    assert_eq!(stack[2].description(), "can't locate ID");
    assert_eq!(&stack[2].detail().unwrap(),
               "Error in H5I_dec_ref(): can't locate ID \
                [Object atom: Unable to find atom information (already closed?)]");

    let empty_stack = ErrorStack::new();
    assert!(empty_stack.is_empty());
    assert_eq!(empty_stack.len(), 0);
}

#[test]
pub fn test_h5call() {
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};

    silence_errors();

    let result_no_error = h5call!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id)
    });
    assert!(result_no_error.is_ok());

    let result_error = h5call!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id);
        H5Pclose(plist_id)
    });
    assert!(result_error.is_err());
}

#[test]
pub fn test_h5try() {
    use ffi::types::herr_t;
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};

    silence_errors();

    fn f1() -> Result<herr_t> {
        let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
        h5try!(H5Pclose(plist_id));
        Ok(100)
    }

    let result1 = f1();
    assert!(result1.is_ok());
    assert_eq!(result1.ok().unwrap(), 100);

    fn f2() -> Result<herr_t> {
        let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
        h5try!(H5Pclose(plist_id));
        h5try!(H5Pclose(plist_id));
        Ok(100)
    }

    let result2 = f2();
    assert!(result2.is_err());
}
<commit_msg>Use String instead of &'static str for H5Error::InternalError<commit_after>use libc::{c_uint, c_void};

use std::ops::Index;
use num::{Integer, Zero, Bounded};
use std::error::{self, Error};
use std::ptr;
use std::fmt;

pub struct ErrorFrame {
    pub desc: String,
    pub func: String,
    pub major: String,
    pub minor: String
}

impl ErrorFrame {
    pub fn description(&self) -> &str {
        &self.desc
    }

    pub fn detail(&self) -> Option<String> {
        Some(format!("Error in {}(): {} [{}: {}]",
             self.func, self.desc, self.major, self.minor).clone())
    }
}

pub fn silence_errors() {
    use ffi::h5e::{H5Eset_auto2, H5E_DEFAULT};

    h5lock!(H5Eset_auto2(H5E_DEFAULT, None, ptr::null_mut::<c_void>()));
}

pub struct ErrorStack {
    frames: Vec<ErrorFrame>
}

impl Index<usize> for ErrorStack {
    type Output = ErrorFrame;

    fn index<'a>(&'a self, index: usize) -> &'a ErrorFrame {
        &self.frames[index]
    }
}

impl ErrorStack {
    // This low-level function is not thread-safe and has to be synchronized by the user
    pub fn query() -> Result<Option<ErrorStack>> {
        use ffi::types::herr_t;
        use ffi::util::{get_h5_str, string_from_cstr};
        use ffi::h5e::{H5Ewalk2, H5Eget_msg, H5E_error2_t, H5E_type_t, H5E_WALK_DOWNWARD,
                       H5Eget_current_stack, H5Eclose_stack};

        struct CallbackData {
            stack: ErrorStack,
            err: Option<H5Error>,
        }

        extern fn callback(_: c_uint, err_desc: *const H5E_error2_t, data: *mut c_void) -> herr_t {
            unsafe {
                let data = &mut *(data as *mut CallbackData);
                if data.err.is_some() {
                    return 0;
                }
                let closure = |e: H5E_error2_t| -> Result<ErrorFrame> {
                    let (desc, func) = (string_from_cstr(e.desc), string_from_cstr(e.func_name));
                    let major = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.maj_num, ptr::null_mut::<H5E_type_t>(), m, s)
                    }));
                    let minor = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.min_num, ptr::null_mut::<H5E_type_t>(), m, s)
                    }));
                    Ok(ErrorFrame { desc: desc, func: func, major: major, minor: minor })
                };
                match closure(*err_desc) {
                    Ok(frame) => { data.stack.push(frame); 0 },
                    Err(err)  => { data.err = Some(From::from(err)); 0 }
                }
            }
        }

        let mut data = CallbackData { stack: ErrorStack::new(), err: None };
        let data_ptr: *mut c_void = &mut data as *mut _ as *mut c_void;

        // known HDF5 bug: H5Eget_msg() may corrupt the current stack, so we copy it first
        unsafe {
            let stack_id = H5Eget_current_stack();
            ensure!(stack_id >= 0, "failed to copy the current error stack");
            H5Ewalk2(stack_id, H5E_WALK_DOWNWARD, Some(callback), data_ptr);
            H5Eclose_stack(stack_id)
        };

        match (data.err, data.stack.is_empty()) {
            (Some(err), _) => Err(err),
            (None, false)  => Ok(Some(data.stack)),
            (None, true)   => Ok(None),
        }
    }

    pub fn new() -> ErrorStack {
        ErrorStack { frames: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.frames.len()
    }

    pub fn push(&mut self, frame: ErrorFrame) {
        self.frames.push(frame)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn top(&self) -> Option<&ErrorFrame> {
        match !self.is_empty() {
            false => None,
            true  => Some(&self.frames[0]),
        }
    }

    pub fn description(&self) -> &str {
        match self.top() {
            None        => "unknown library error",
            Some(frame) => frame.description(),
        }
    }

    pub fn detail(&self) -> Option<String> {
        match self.top() {
            None        => None,
            Some(frame) => frame.detail(),
        }
    }
}

pub enum H5Error {
    LibraryError(ErrorStack),
    InternalError(String),
}

pub type Result<T> = ::std::result::Result<T, H5Error>;

impl H5Error {
    pub fn query() -> Option<H5Error> {
        match ErrorStack::query() {
            Err(err)        => Some(From::from(err)),
            Ok(Some(stack)) => Some(H5Error::LibraryError(stack)),
            Ok(None)        => None,
        }
    }
}

impl<S> From<S> for H5Error where S: Into<String> {
    fn from(desc: S) -> H5Error {
        H5Error::InternalError(desc.into())
    }
}

impl fmt::Debug for H5Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            H5Error::InternalError(ref desc) => desc.fmt(formatter),
            H5Error::LibraryError(ref stack) => stack.detail().fmt(formatter),
        }
    }
}

impl fmt::Display for H5Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        self.description().fmt(formatter)
    }
}

impl error::Error for H5Error {
    fn description(&self) -> &str {
        match *self {
            H5Error::InternalError(ref desc) => desc.as_ref(),
            H5Error::LibraryError(ref stack) => stack.description(),
        }
    }
}

pub fn h5check<T>(value: T) -> Result<T> where T: Integer + Zero + Bounded,
{
    let min_value: T = Bounded::min_value();
    let zero:      T = Zero::zero();

    let maybe_error = if min_value < zero {
        value < zero
    } else {
        value == zero
    };

    match maybe_error {
        false => Ok(value),
        true  => match H5Error::query() {
            None       => Ok(value),
            Some(err)  => Err(From::from(err)),
        },
    }
}

#[test]
pub fn test_error_stack() {
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};

    silence_errors();

    let result_no_error = h5lock!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id);
        ErrorStack::query()
    });
    assert!(result_no_error.ok().unwrap().is_none());

    let result_error = h5lock!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id);
        H5Pclose(plist_id);
        ErrorStack::query()
    });
    let stack = result_error.ok().unwrap().unwrap();
    assert_eq!(stack.description(), "can't close");
    assert_eq!(&stack.detail().unwrap(),
               "Error in H5Pclose(): can't close [Property lists: Unable to free object]");

    assert_eq!(stack.len(), 3);
    assert!(!stack.is_empty());

    assert_eq!(stack[0].description(), "can't close");
    assert_eq!(&stack[0].detail().unwrap(),
               "Error in H5Pclose(): can't close \
                [Property lists: Unable to free object]");

    assert_eq!(stack[1].description(), "can't decrement ID ref count");
    assert_eq!(&stack[1].detail().unwrap(),
               "Error in H5I_dec_app_ref(): can't decrement ID ref count \
                [Object atom: Unable to decrement reference count]");

    assert_eq!(stack[2].description(), "can't locate ID");
    assert_eq!(&stack[2].detail().unwrap(),
               "Error in H5I_dec_ref(): can't locate ID \
                [Object atom: Unable to find atom information (already closed?)]");

    let empty_stack = ErrorStack::new();
    assert!(empty_stack.is_empty());
    assert_eq!(empty_stack.len(), 0);
}

#[test]
pub fn test_h5call() {
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};

    silence_errors();

    let result_no_error = h5call!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id)
    });
    assert!(result_no_error.is_ok());

    let result_error = h5call!({
        let plist_id = H5Pcreate(*H5P_ROOT);
        H5Pclose(plist_id);
        H5Pclose(plist_id)
    });
    assert!(result_error.is_err());
}

#[test]
pub fn test_h5try() {
    use ffi::types::herr_t;
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};

    silence_errors();

    fn f1() -> Result<herr_t> {
        let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
        h5try!(H5Pclose(plist_id));
        Ok(100)
    }

    let result1 = f1();
    assert!(result1.is_ok());
    assert_eq!(result1.ok().unwrap(), 100);

    fn f2() -> Result<herr_t> {
        let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
        h5try!(H5Pclose(plist_id));
        h5try!(H5Pclose(plist_id));
        Ok(100)
    }

    let result2 = f2();
    assert!(result2.is_err());
}
<|endoftext|>


<commit_before>use std::collections::{
    HashMap,
    BinaryHeap,
};
use std::collections::hash_map::Hasher;
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};

use std::default::Default;
use std::hash::Hash;
use std::ops::{
    Add,
};

use super::MinScored;
use super::visit::{
    Visitable,
    VisitMap,
};

/// Dijkstra's shortest path algorithm.
pub fn dijkstra<'a, G, N, K, F, Edges>(graph: &'a G,
                                       start: N,
                                       goal: Option<N>,
                                       mut edges: F) -> HashMap<N, K> where
    G: Visitable<NodeId=N>,
    N: Clone + Eq + Hash<Hasher>,
    K: Default + Add<Output=K> + Copy + PartialOrd,
    F: FnMut(&'a G, N) -> Edges,
    Edges: Iterator<Item=(N, K)>,
    <G as Visitable>::Map: VisitMap<N>,
{
    let mut visited = graph.visit_map();
    let mut scores = HashMap::new();
    let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score: K = Default::default();
    scores.insert(start.clone(), zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.is_visited(&node) {
            continue
        }
        for (next, edge) in edges(graph, node.clone()) {
            if visited.is_visited(&next) {
                continue
            }
            let mut next_score = node_score + edge;
            match scores.entry(next.clone()) {
                Occupied(ent) => if next_score < *ent.get() {
                    *ent.into_mut() = next_score;
                    predecessor.insert(next.clone(), node.clone());
                } else {
                    next_score = *ent.get();
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    predecessor.insert(next.clone(), node.clone());
                }
            }
            visit_next.push(MinScored(next_score, next));
        }
        if goal.as_ref() == Some(&node) {
            break
        }
        visited.visit(node);
    }
    scores
}
<commit_msg>Remove redundant type parameter in dijkstra<commit_after>use std::collections::{
    HashMap,
    BinaryHeap,
};
use std::collections::hash_map::Hasher;
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};

use std::default::Default;
use std::hash::Hash;
use std::ops::{
    Add,
};

use super::MinScored;
use super::visit::{
    Visitable,
    VisitMap,
};

/// Dijkstra's shortest path algorithm.
pub fn dijkstra<'a, G: Visitable, K, F, Edges>(graph: &'a G,
                                               start: G::NodeId,
                                               goal: Option<G::NodeId>,
                                               mut edges: F) -> HashMap<G::NodeId, K> where
    G::NodeId: Clone + Eq + Hash<Hasher>,
    K: Default + Add<Output=K> + Copy + PartialOrd,
    F: FnMut(&'a G, G::NodeId) -> Edges,
    Edges: Iterator<Item=(G::NodeId, K)>,
    <G as Visitable>::Map: VisitMap<G::NodeId>,
{
    let mut visited = graph.visit_map();
    let mut scores = HashMap::new();
    let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score: K = Default::default();
    scores.insert(start.clone(), zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.is_visited(&node) {
            continue
        }
        for (next, edge) in edges(graph, node.clone()) {
            if visited.is_visited(&next) {
                continue
            }
            let mut next_score = node_score + edge;
            match scores.entry(next.clone()) {
                Occupied(ent) => if next_score < *ent.get() {
                    *ent.into_mut() = next_score;
                    predecessor.insert(next.clone(), node.clone());
                } else {
                    next_score = *ent.get();
                },
                Vacant(ent) => {
                    ent.insert(next_score);
                    predecessor.insert(next.clone(), node.clone());
                }
            }
            visit_next.push(MinScored(next_score, next));
        }
        if goal.as_ref() == Some(&node) {
            break
        }
        visited.visit(node);
    }
    scores
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

/// Wrapper types for the values returned from `File` objects.
///
/// The methods of `File` don't return formatted strings; neither do they
/// return raw numbers representing timestamps or user IDs. Instead, they will
/// return an object in this `fields` module. These objects are later rendered
/// into formatted strings in the `output/details` module.
pub type blkcnt_t = u64;
pub type gid_t = u32;
pub type ino_t = u64;
pub type nlink_t = u64;
pub type time_t = i64;
pub type uid_t = u32;

pub enum Type {
    File, Directory, Pipe, Link, Special,
}

pub struct Permissions {
    pub file_type:      Type,
    pub user_read:      bool,
    pub user_write:     bool,
    pub user_execute:   bool,
    pub group_read:     bool,
    pub group_write:    bool,
    pub group_execute:  bool,
    pub other_read:     bool,
    pub other_write:    bool,
    pub other_execute:  bool,
}

pub struct Links {
    pub count: nlink_t,
    pub multiple: bool,
}

pub struct Inode(pub ino_t);

pub enum Blocks {
    Some(blkcnt_t),
    None,
}

pub struct User(pub uid_t);

pub struct Group(pub gid_t);

pub enum Size {
    Some(u64),
    None,
}

pub struct Time(pub time_t);

pub enum GitStatus {
    NotModified,
    New,
    Modified,
    Deleted,
    Renamed,
    TypeChange,
}

pub struct Git {
    pub staged:   GitStatus,
    pub unstaged: GitStatus,
}

impl Git {
    pub fn empty() -> Git {
        Git { staged: GitStatus::NotModified, unstaged: GitStatus::NotModified }
    }
}
<commit_msg>Add comments to the new fields module<commit_after>//! Wrapper types for the values returned from `File`s.
//!
//! The methods of `File` that return information about the entry on the
//! filesystem -- size, modification date, block count, or Git status -- used
//! to just return these as formatted strings, but this became inflexible once
//! customisable output styles landed.
//!
//! Instead, they will return a wrapper type from this module, which tags the
//! type with what field it is while containing the actual raw value.
//!
//! The `output::details` module, among others, uses these types to render and
//! display the information as formatted strings.

// C-style `blkcnt_t` types don’t follow Rust’s rules!
#![allow(non_camel_case_types)]

/// The type of a file’s block count.
pub type blkcnt_t = u64;

/// The type of a file’s group ID.
pub type gid_t = u32;

/// The type of a file’s inode.
pub type ino_t = u64;

/// The type of a file’s number of links.
pub type nlink_t = u64;

/// The type of a file’s timestamp (creation, modification, access, etc).
pub type time_t = i64;

/// The type of a file’s user ID.
pub type uid_t = u32;

/// The file’s base type, which gets displayed in the very first column of the
/// details output.
///
/// This type is set entirely by the filesystem, rather than relying on a
/// file’s contents. So “link” is a type, but “image” is just a type of
/// regular file. (See the `filetype` module for those checks.)
pub enum Type {
    File, Directory, Pipe, Link, Special,
}

/// The file’s Unix permission bitfield, with one entry per bit.
pub struct Permissions {
    pub file_type:      Type,

    pub user_read:      bool,
    pub user_write:     bool,
    pub user_execute:   bool,

    pub group_read:     bool,
    pub group_write:    bool,
    pub group_execute:  bool,

    pub other_read:     bool,
    pub other_write:    bool,
    pub other_execute:  bool,
}

/// A file’s number of hard links on the filesystem.
///
/// Under Unix, a file can exist on the filesystem only once but appear in
/// multiple directories. However, it’s rare (but occasionally useful!) for a
/// regular file to have a link count greater than 1, so we highlight the
/// block count specifically for this case.
pub struct Links {

    /// The actual link count.
    pub count: nlink_t,

    /// Whether this file is a regular file with more than one hard link.
    pub multiple: bool,
}

/// A file’s inode. Every directory entry on a Unix filesystem has an inode,
/// including directories and links, so this is applicable to everything exa
/// can deal with.
pub struct Inode(pub ino_t);

/// The number of blocks that a file takes up on the filesystem, if any.
pub enum Blocks {

    /// This file has the given number of blocks.
    Some(blkcnt_t),

    /// This file isn’t of a type that can take up blocks.
    None,
}

/// The ID of the user that owns a file. This will only ever be a number;
/// looking up the username is done in the `display` module.
pub struct User(pub uid_t);

/// The ID of the group that a file belongs to.
pub struct Group(pub gid_t);

/// A file’s size, in bytes. This is usually formatted by the `number_prefix`
/// crate into something human-readable.
pub enum Size {

    /// This file has a defined size.
    Some(u64),

    /// This file has no size, or has a size but we aren’t interested in it.
    ///
    /// Under Unix, directory entries that aren’t regular files will still
    /// have a file size. For example, a directory will just contain a list of
    /// its files as its “contents” and will be specially flagged as being a
    /// directory, rather than a file. However, seeing the “file size” of this
    /// data is rarely useful -- I can’t think of a time when I’ve seen it and
    /// learnt something. So we discard it and just output “-” instead.
    ///
    /// See this answer for more: http://unix.stackexchange.com/a/68266
    None,
}

/// One of a file’s timestamps (created, accessed, or modified).
pub struct Time(pub time_t);

/// A file’s status in a Git repository. Whether a file is in a repository or
/// not is handled by the Git module, rather than having a “null” variant in
/// this enum.
pub enum GitStatus {

    /// This file hasn’t changed since the last commit.
    NotModified,

    /// This file didn’t exist for the last commit, and is not specified in
    /// the ignored files list.
    New,

    /// A file that’s been modified since the last commit.
    Modified,

    /// A deleted file. This can’t ever be shown, but it’s here anyway!
    Deleted,

    /// A file that Git has tracked a rename for.
    Renamed,

    /// A file that’s had its type (such as the file permissions) changed.
    TypeChange,
}

/// A file’s complete Git status. It’s possible to make changes to a file, add
/// it to the staging area, then make *more* changes, so we need to list each
/// file’s status for both of these.
pub struct Git {
    pub staged:   GitStatus,
    pub unstaged: GitStatus,
}

impl Git {

    /// Create a Git status for a file with nothing done to it.
    pub fn empty() -> Git {
        Git { staged: GitStatus::NotModified, unstaged: GitStatus::NotModified }
    }
}
<|endoftext|>


<commit_before>use std::thread;
use ws::WebSocket;
use redis::Client;

/// Runs a WebSocket server that subscribes to a Redis pubsub channel.
/// Workers can send publish messages to the channel and this server will forward them to
/// connected WebSocket clients.
pub fn ws_server(addr: &'static str, redis_addr: &'static str) -> thread::JoinHandle<()> {
    thread::spawn(move || {
        // websocket to broadcast to all clients
        let ws = WebSocket::new(|_| {
                move |msg| {
                    println!("got: {}", msg);
                    Ok(())
                }
            })
            .unwrap();
        let broadcaster = ws.broadcaster();

        // redis pubsub that workers can throw messages to
        let ps = thread::spawn(move || {
            let client = Client::open(redis_addr).unwrap();
            let mut pubsub = client.get_pubsub().unwrap();
            pubsub.subscribe("ws").unwrap();
            loop {
                let msg = pubsub.get_message().unwrap();
                let payload: String = msg.get_payload().unwrap();
                broadcaster.send(payload).unwrap();
            }
        });

        ws.listen(addr).unwrap();
        ps.join().unwrap();
    })
}
<commit_msg>improvement to websocket server. can now shutdown<commit_after>use std::thread;
use ws::WebSocket;
use redis::{Client, Commands};

pub struct WebSocketServer {
    addr: String,
    redis_addr: String,
    t: Option<thread::JoinHandle<()>>,
}

impl WebSocketServer {
    pub fn new(addr: &str, redis_addr: &str) -> WebSocketServer {
        WebSocketServer {
            t: None,
            addr: addr.to_owned(),
            redis_addr: redis_addr.to_owned(),
        }
    }

    /// Runs a WebSocket server that subscribes to a Redis pubsub channel.
    /// Workers can send publish messages to the channel and this server will forward them to
    /// connected WebSocket clients.
    pub fn start(&mut self) {
        let addr = self.addr.clone();
        let redis_addr = self.redis_addr.clone();
        self.t = Some(thread::spawn(move || {
            // websocket to broadcast to all clients
            let ws = WebSocket::new(|_| {
                    move |msg| {
                        println!("got: {}", msg);
                        Ok(())
                    }
                })
                .unwrap();
            let broadcaster = ws.broadcaster();

            // redis pubsub that workers can throw messages to
            let ps = thread::spawn(move || {
                let client = Client::open(&redis_addr[..]).unwrap();
                let mut pubsub = client.get_pubsub().unwrap();
                pubsub.subscribe("ws").unwrap();
                loop {
                    let msg = pubsub.get_message().unwrap();
                    let payload: String = msg.get_payload().unwrap();
                    if payload == "TERMINATE" {
                        broadcaster.shutdown().unwrap();
                        break;
                    } else {
                        broadcaster.send(payload).unwrap();
                    }
                }
            });

            ws.listen(&addr[..]).unwrap();
            ps.join().unwrap();
        }));
    }

    /// Shutdown the websocket server.
    pub fn shutdown(self) {
        match self.t {
            Some(t) => {
                let client = Client::open(self.redis_addr.as_ref()).unwrap();
                let conn = client.get_connection().unwrap();
                let _: () = conn.publish("ws", "TERMINATE").unwrap();
                t.join().unwrap();
            }
            None => (),
        }
    }
}
<|endoftext|>