<commit_before>use cgmath::Point2;
use game::constants::{TERRAIN_OBJECTS, TILES_PCS_H, TILES_PCS_W};
use game::get_rand_from_range;
use graphics::coords_to_tile_offset;
use pathfinding::{directed::astar::astar, utils::absdiff};
use shaders::Position;

fn neighbours<'c>(curr_pos: &'c Point2<i32>, impassable_tiles: &[[usize; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> Vec<&'c Point2<i32>> {
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y - 1));

  neighbour_tiles.iter()
            .filter(|ref e| e.x >= 0 && e.x < TILES_PCS_W as i32 && e.y >= 0 && e.y < TILES_PCS_H as i32)
            .filter(|ref e| !impassable_tiles.contains(&[e.x as usize, e.y as usize]))
            .collect()
}

fn tiles<'c>(p: &'c Point2<i32>, impassable_tiles: &[[usize; 2]]) -> Vec<(Point2<i32>, i32)> {
  neighbours(&p, &impassable_tiles, &mut vec![]).iter()
                                                                                .map(|p| (**p, 1))
                                                                                .collect()
}

fn find_next_best_endpoint<'c>(end_point: &'c Point2<i32>, impassable_tiles: &[[usize; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> &'c Point2<i32> {
  if impassable_tiles.iter().any(|e| e[0] == end_point.x as usize && e[1] == end_point.y as usize) {
    neighbours(&end_point, &impassable_tiles, neighbour_tiles)[0]
  } else {
    &end_point
  }
}

pub fn calc_route(start_point: Position, end_point: Position, impassable_tiles: &[[usize; 2]]) -> Option<(Vec<Point2<i32>>, i32)> {
  let mut neighbour_tiles = vec![];
  let end_point_with_offset = coords_to_tile_offset(end_point);

  let start = coords_to_tile_offset(start_point);
  let end = find_next_best_endpoint(&end_point_with_offset, &impassable_tiles, &mut neighbour_tiles);

  astar(&start,
        |p: &Point2<i32>| tiles(p, &impassable_tiles),
        |p: &Point2<i32>| absdiff(p.x, end.x) + absdiff(p.y, end.y),
        |p: &Point2<i32>| p.x == end.x && p.y == end.y)
}

pub fn calc_next_movement(start_point: Position, end_point: Position) -> i32 {
  let next_step: Point2<i32> = calc_route(start_point, end_point, &TERRAIN_OBJECTS)
    .map_or_else(|| Point2::new(0, 0),
                 |(route, _)| {
                   if route.len() > 1 {
                     Point2::new(route[1].x, route[1].y)
                   } else {
                     Point2::new(route[0].x, route[0].y)
                   }
                 });

  let start = coords_to_tile_offset(start_point);
  let diff: (i32, i32) = (next_step.x - start.x, next_step.y - start.y);

  match diff {
    (1, 0) => 315,
    (1, 1) => 270,
    (0, 1) => 225,
    (-1, 1) => 180,
    (-1, 0) => 135,
    (-1, -1) => 90,
    (0, -1) => 45,
    (1, -1) => 0,
    _ => get_rand_from_range(0, 359),
  }
}
<commit_msg>Reindent path_finding.rs<commit_after>use cgmath::Point2;
use game::constants::{TERRAIN_OBJECTS, TILES_PCS_H, TILES_PCS_W};
use game::get_rand_from_range;
use graphics::coords_to_tile_offset;
use pathfinding::{directed::astar::astar, utils::absdiff};
use shaders::Position;

fn neighbours<'c>(curr_pos: &'c Point2<i32>, impassable_tiles: &[[usize; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> Vec<&'c Point2<i32>> {
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y - 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x - 1, curr_pos.y + 1));
  neighbour_tiles.push(Point2::new(curr_pos.x + 1, curr_pos.y - 1));

  neighbour_tiles
    .iter()
    .filter(|ref e| e.x >= 0 && e.x < TILES_PCS_W as i32 && e.y >= 0 && e.y < TILES_PCS_H as i32)
    .filter(|ref e| !impassable_tiles.contains(&[e.x as usize, e.y as usize]))
    .collect()
}

fn tiles<'c>(p: &'c Point2<i32>, impassable_tiles: &[[usize; 2]]) -> Vec<(Point2<i32>, i32)> {
  neighbours(&p, &impassable_tiles, &mut vec![]).iter()
    .map(|p| (**p, 1))
    .collect()
}

fn find_next_best_endpoint<'c>(end_point: &'c Point2<i32>, impassable_tiles: &[[usize; 2]], neighbour_tiles: &'c mut Vec<Point2<i32>>) -> &'c Point2<i32> {
  if impassable_tiles.iter().any(|e| e[0] == end_point.x as usize && e[1] == end_point.y as usize) {
    neighbours(&end_point, &impassable_tiles, neighbour_tiles)[0]
  } else {
    &end_point
  }
}

pub fn calc_route(start_point: Position, end_point: Position, impassable_tiles: &[[usize; 2]]) -> Option<(Vec<Point2<i32>>, i32)> {
  let mut neighbour_tiles = vec![];
  let end_point_with_offset = coords_to_tile_offset(end_point);

  let start = coords_to_tile_offset(start_point);
  let end = find_next_best_endpoint(&end_point_with_offset, &impassable_tiles, &mut neighbour_tiles);

  astar(&start,
        |p: &Point2<i32>| tiles(p, &impassable_tiles),
        |p: &Point2<i32>| absdiff(p.x, end.x) + absdiff(p.y, end.y),
        |p: &Point2<i32>| p.x == end.x && p.y == end.y)
}

pub fn calc_next_movement(start_point: Position, end_point: Position) -> i32 {
  let next_step: Point2<i32> = calc_route(start_point, end_point, &TERRAIN_OBJECTS)
    .map_or_else(|| Point2::new(0, 0),
                 |(route, _)| {
                   if route.len() > 1 {
                     Point2::new(route[1].x, route[1].y)
                   } else {
                     Point2::new(route[0].x, route[0].y)
                   }
                 });

  let start = coords_to_tile_offset(start_point);
  let diff: (i32, i32) = (next_step.x - start.x, next_step.y - start.y);

  match diff {
    (1, 0) => 315,
    (1, 1) => 270,
    (0, 1) => 225,
    (-1, 1) => 180,
    (-1, 0) => 135,
    (-1, -1) => 90,
    (0, -1) => 45,
    (1, -1) => 0,
    _ => get_rand_from_range(0, 359),
  }
}
<|endoftext|>


<commit_before>
#[macro_use]
extern crate nccl;
use nccl::*;

#[test]
fn pair_keys() {
    let mut p = ::Pair::new("top");
    p.add("numbers");
    p["numbers"].add("1");
    p["numbers"].add("2");
    p["numbers"].add("3");
    p["numbers"].add("4");
    p["numbers"].add("5");
    assert_eq!(p["numbers"].keys_as::<String>().unwrap(), vec!["1", "2", "3", "4", "5"]);
}

#[test]
fn pair_value_parse() {
    let mut p = ::Pair::new("top");
    p.add("bools");
    p["bools"].add(true);
    assert!(p["bools"].value_as::<bool>().unwrap());
}

#[test]
fn error_key_not_found() {
    let mut p = ::Pair::new("jjj");
    assert!(p.get("jwiofiojwaef jio").is_err());
}

#[test]
fn scan_file() {
    assert!(::parse_file("examples/config.nccl").is_ok());
}

#[test]
fn dos_unix_lines() {
    assert!(::parse_file("examples/config.nccl").is_ok());
    assert!(::parse_file("examples/config_dos.nccl").is_ok());
}

#[test]
fn add_pair() {
    // create a new pair
    let mut p1 = ::Pair::new("happy birthday");

    p1.add("Bobby");
    p1["Bobby"].add("Today!");

    // we think Ron's birthday is the 3rd...
    p1.add("Ron");
    p1["Ron"].add("March 3rd");

    // whoops, we were wrong
    let mut p2 = ::Pair::new("Ron");
    p2.add("March 2nd");

    // there you go Ron, happy belated birthday
    p1.add_pair(p2);
}

#[test]
fn traverse_path() {
    let mut p = ::Pair::new("top");
    p.add_slice(&["a".into(), "b".into(), "c".into()]);
    p.traverse_path(&["a".into(), "b".into()]).add("happy");
    assert_eq!(p.traverse_path(&["a".into(), "b".into(), "happy".into()]), &mut ::Pair::new("happy"));
}

#[test]
fn add_slice() {
    let mut config = ::Pair::new("top_level");
    config.add("server");
    config["server"].add("domain");
    config["server"].add("port");
    config["server"].add("root");
    config["server"]["domain"].add("example.com");
    config["server"]["domain"].add("www.example.com");
    config["server"]["port"].add("80");
    config["server"]["port"].add("443");
    config["server"]["root"].add("/var/www/html");

    config.add_slice(&["server".into(), "port".into(), "22".into()]);
    assert_eq!(config["server"]["port"].keys_as::<String>().unwrap(), vec!["80", "443", "22"]);
}

#[test]
fn add_vec() {
    let mut p = ::Pair::new("__top_level__");
    p.add("a");
    p.add_slice(&["a".into(), "hello".into(), "world".into()]);
    p.add_slice(&["a".into(), "hello".into(), "world".into()]);
    assert_eq!(p["a"]["hello"].keys_as::<String>().unwrap().len(), 1);
}

#[test]
fn long() {
    let oh_dear = ::parse_file("examples/long.nccl").unwrap();
    oh_dear.pretty_print();
}

#[test]
fn inherit2() {
    let schemas = ::parse_file("examples/inherit.nccl").unwrap();
    let user = ::parse_file_with("examples/inherit2.nccl", schemas).unwrap();
    assert_eq!(user["sandwich"]["meat"].keys_as::<String>().unwrap().len(), 3);
    assert_eq!(user["hello"]["world"].keys_as::<String>().unwrap().len(), 3);
}

#[test]
fn tabs() {
    assert!(::parse_file("examples/tabs.nccl").is_err());
}

#[test]
fn spaces() {
    assert!(::parse_file("examples/spaces").is_err());
}

#[test]
fn comments() {
    assert!(::parse_file("examples/comments.nccl").is_ok());
}

#[test]
fn indent() {
    assert!(::parse_file("examples/indent.nccl").is_ok());
}

#[test]
fn escapes() {
    let p = ::parse_file("examples/escapes.nccl").unwrap();
    assert_eq!(p["hello"].value_as::<String>().unwrap(), "people of the earth\nhow's it doing?\"");
}

#[test]
fn has_path() {
    let p = ::parse_file("examples/inherit2.nccl").unwrap();
    assert!(p.has_path(vec_into!["hello", "world", "alaska"]));
}

#[test]
fn readme() {
    let config = ::parse_file("examples/config.nccl").unwrap();
    let ports = config["server"]["port"].keys_as::<i64>().unwrap();
    assert_eq!(ports, vec![80, 443]);
}
<commit_msg>add newline<commit_after>
#[macro_use]
extern crate nccl;
use nccl::*;

#[test]
fn pair_keys() {
    let mut p = ::Pair::new("top");
    p.add("numbers");
    p["numbers"].add("1");
    p["numbers"].add("2");
    p["numbers"].add("3");
    p["numbers"].add("4");
    p["numbers"].add("5");
    assert_eq!(p["numbers"].keys_as::<String>().unwrap(), vec!["1", "2", "3", "4", "5"]);
}

#[test]
fn pair_value_parse() {
    let mut p = ::Pair::new("top");
    p.add("bools");
    p["bools"].add(true);
    assert!(p["bools"].value_as::<bool>().unwrap());
}

#[test]
fn error_key_not_found() {
    let mut p = ::Pair::new("jjj");
    assert!(p.get("jwiofiojwaef jio").is_err());
}

#[test]
fn scan_file() {
    assert!(::parse_file("examples/config.nccl").is_ok());
}

#[test]
fn dos_unix_lines() {
    assert!(::parse_file("examples/config.nccl").is_ok());
    assert!(::parse_file("examples/config_dos.nccl").is_ok());
}

#[test]
fn add_pair() {
    // create a new pair
    let mut p1 = ::Pair::new("happy birthday");

    p1.add("Bobby");
    p1["Bobby"].add("Today!");

    // we think Ron's birthday is the 3rd...
    p1.add("Ron");
    p1["Ron"].add("March 3rd");

    // whoops, we were wrong
    let mut p2 = ::Pair::new("Ron");
    p2.add("March 2nd");

    // there you go Ron, happy belated birthday
    p1.add_pair(p2);
}

#[test]
fn traverse_path() {
    let mut p = ::Pair::new("top");
    p.add_slice(&["a".into(), "b".into(), "c".into()]);
    p.traverse_path(&["a".into(), "b".into()]).add("happy");
    assert_eq!(p.traverse_path(&["a".into(), "b".into(), "happy".into()]), &mut ::Pair::new("happy"));
}

#[test]
fn add_slice() {
    let mut config = ::Pair::new("top_level");
    config.add("server");
    config["server"].add("domain");
    config["server"].add("port");
    config["server"].add("root");
    config["server"]["domain"].add("example.com");
    config["server"]["domain"].add("www.example.com");
    config["server"]["port"].add("80");
    config["server"]["port"].add("443");
    config["server"]["root"].add("/var/www/html");

    config.add_slice(&["server".into(), "port".into(), "22".into()]);
    assert_eq!(config["server"]["port"].keys_as::<String>().unwrap(), vec!["80", "443", "22"]);
}

#[test]
fn add_vec() {
    let mut p = ::Pair::new("__top_level__");
    p.add("a");
    p.add_slice(&["a".into(), "hello".into(), "world".into()]);
    p.add_slice(&["a".into(), "hello".into(), "world".into()]);
    assert_eq!(p["a"]["hello"].keys_as::<String>().unwrap().len(), 1);
}

#[test]
fn long() {
    let oh_dear = ::parse_file("examples/long.nccl").unwrap();
    oh_dear.pretty_print();
}

#[test]
fn inherit2() {
    let schemas = ::parse_file("examples/inherit.nccl").unwrap();
    let user = ::parse_file_with("examples/inherit2.nccl", schemas).unwrap();
    assert_eq!(user["sandwich"]["meat"].keys_as::<String>().unwrap().len(), 3);
    assert_eq!(user["hello"]["world"].keys_as::<String>().unwrap().len(), 3);
}

#[test]
fn tabs() {
    assert!(::parse_file("examples/tabs.nccl").is_err());
}

#[test]
fn spaces() {
    assert!(::parse_file("examples/spaces").is_err());
}

#[test]
fn comments() {
    assert!(::parse_file("examples/comments.nccl").is_ok());
}

#[test]
fn indent() {
    assert!(::parse_file("examples/indent.nccl").is_ok());
}

#[test]
fn escapes() {
    let p = ::parse_file("examples/escapes.nccl").unwrap();
    assert_eq!(p["hello"].value_as::<String>().unwrap(), "people of the earth\nhow's it doing?\"");
}

#[test]
fn has_path() {
    let p = ::parse_file("examples/inherit2.nccl").unwrap();
    assert!(p.has_path(vec_into!["hello", "world", "alaska"]));
}

#[test]
fn readme() {
    let config = ::parse_file("examples/config.nccl").unwrap();
    let ports = config["server"]["port"].keys_as::<i64>().unwrap();
    assert_eq!(ports, vec![80, 443]);
}

<|endoftext|>


<commit_before>pub type greg_t = ::c_long;

pub type Elf64_Addr = ::c_ulong;
pub type Elf64_Half = ::c_ushort;
pub type Elf64_Off = ::c_ulong;
pub type Elf64_Sword = ::c_int;
pub type Elf64_Sxword = ::c_long;
pub type Elf64_Word = ::c_uint;
pub type Elf64_Xword = ::c_ulong;
pub type Elf64_Lword = ::c_ulong;
pub type Elf64_Phdr = __c_anonymous_Elf64_Phdr;

s! {
    pub struct __c_anonymous_fpchip_state {
        pub cw: u16,
        pub sw: u16,
        pub fctw: u8,
        pub __fx_rsvd: u8,
        pub fop: u16,
        pub rip: u64,
        pub rdp: u64,
        pub mxcsr: u32,
        pub mxcsr_mask: u32,
        pub st: [::upad128_t; 8],
        pub xmm: [::upad128_t; 16],
        pub __fx_ign: [::upad128_t; 6],
        pub status: u32,
        pub xstatus: u32,
    }

    pub struct __c_anonymous_Elf64_Phdr {
        pub p_type: ::Elf64_Word,
        pub p_flags: ::Elf64_Word,
        pub p_offset: ::Elf64_Off,
        pub p_vaddr: ::Elf64_Addr,
        pub p_paddr: ::Elf64_Addr,
        pub p_filesz: ::Elf64_Xword,
        pub p_memsz: ::Elf64_Xword,
        pub p_align: ::Elf64_Xword,
    }

    pub struct dl_phdr_info {
        pub dlpi_addr: ::Elf64_Addr,
        pub dlpi_name: *const ::c_char,
        pub dlpi_phdr: *const ::Elf64_Phdr,
        pub dlpi_phnum: ::Elf64_Half,
        pub dlpi_adds: ::c_ulonglong,
        pub dlpi_subs: ::c_ulonglong,
    }
}

s_no_extra_traits! {
    #[cfg(libc_union)]
    pub union __c_anonymous_fp_reg_set {
        pub fpchip_state: __c_anonymous_fpchip_state,
        pub f_fpregs: [[u32; 13]; 10],
    }

    pub struct fpregset_t {
        pub fp_reg_set: __c_anonymous_fp_reg_set,
    }

    pub struct mcontext_t {
        pub gregs: [::greg_t; 28],
        pub fpregs: fpregset_t,
    }

    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_stack: ::stack_t,
        pub uc_mcontext: mcontext_t,
        pub uc_filler: [::c_long; 5],
    }
}

cfg_if! {
    if #[cfg(feature = "extra_traits")] {
        #[cfg(libc_union)]
        impl PartialEq for __c_anonymous_fp_reg_set {
            fn eq(&self, other: &__c_anonymous_fp_reg_set) -> bool {
                unsafe {
                self.fpchip_state == other.fpchip_state ||
                    self.
                    f_fpregs.
                    iter().
                    zip(other.f_fpregs.iter()).
                    all(|(a, b)| a == b)
                }
            }
        }
        #[cfg(libc_union)]
        impl Eq for __c_anonymous_fp_reg_set {}
        #[cfg(libc_union)]
        impl ::fmt::Debug for __c_anonymous_fp_reg_set {
            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
                unsafe {
                f.debug_struct("__c_anonymous_fp_reg_set")
                    .field("fpchip_state", &{self.fpchip_state})
                    .field("f_fpregs", &{self.f_fpregs})
                    .finish()
                }
            }
        }
        impl PartialEq for fpregset_t {
            fn eq(&self, other: &fpregset_t) -> bool {
                self.fp_reg_set == other.fp_reg_set
            }
        }
        impl Eq for fpregset_t {}
        impl ::fmt::Debug for fpregset_t {
            fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("fpregset_t")
                    .field("fp_reg_set", &self.fp_reg_set)
                    .finish()
            }
        }
        impl PartialEq for mcontext_t {
            fn eq(&self, other: &mcontext_t) -> bool {
                self.gregs == other.gregs &&
                    self.fpregs == other.fpregs
            }
        }
        impl Eq for mcontext_t {}
        impl ::fmt::Debug for mcontext_t {
            fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("mcontext_t")
                    .field("gregs", &self.gregs)
                    .field("fpregs", &self.fpregs)
                    .finish()
            }
        }
        impl PartialEq for ucontext_t {
            fn eq(&self, other: &ucontext_t) -> bool {
                self.uc_flags == other.uc_flags
                    && self.uc_link == other.uc_link
                    && self.uc_sigmask == other.uc_sigmask
                    && self.uc_stack == other.uc_stack
                    && self.uc_mcontext == other.uc_mcontext
                    && self.uc_filler == other.uc_filler
            }
        }
        impl Eq for ucontext_t {}
        impl ::fmt::Debug for ucontext_t {
            fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("ucontext_t")
                    .field("uc_flags", &self.uc_flags)
                    .field("uc_link", &self.uc_link)
                    .field("uc_sigmask", &self.uc_sigmask)
                    .field("uc_stack", &self.uc_stack)
                    .field("uc_mcontext", &self.uc_mcontext)
                    .field("uc_filler", &self.uc_filler)
                    .finish()
            }
        }

    }
}
<commit_msg>solarish amd64 regset constants<commit_after>pub type greg_t = ::c_long;

pub type Elf64_Addr = ::c_ulong;
pub type Elf64_Half = ::c_ushort;
pub type Elf64_Off = ::c_ulong;
pub type Elf64_Sword = ::c_int;
pub type Elf64_Sxword = ::c_long;
pub type Elf64_Word = ::c_uint;
pub type Elf64_Xword = ::c_ulong;
pub type Elf64_Lword = ::c_ulong;
pub type Elf64_Phdr = __c_anonymous_Elf64_Phdr;

s! {
    pub struct __c_anonymous_fpchip_state {
        pub cw: u16,
        pub sw: u16,
        pub fctw: u8,
        pub __fx_rsvd: u8,
        pub fop: u16,
        pub rip: u64,
        pub rdp: u64,
        pub mxcsr: u32,
        pub mxcsr_mask: u32,
        pub st: [::upad128_t; 8],
        pub xmm: [::upad128_t; 16],
        pub __fx_ign: [::upad128_t; 6],
        pub status: u32,
        pub xstatus: u32,
    }

    pub struct __c_anonymous_Elf64_Phdr {
        pub p_type: ::Elf64_Word,
        pub p_flags: ::Elf64_Word,
        pub p_offset: ::Elf64_Off,
        pub p_vaddr: ::Elf64_Addr,
        pub p_paddr: ::Elf64_Addr,
        pub p_filesz: ::Elf64_Xword,
        pub p_memsz: ::Elf64_Xword,
        pub p_align: ::Elf64_Xword,
    }

    pub struct dl_phdr_info {
        pub dlpi_addr: ::Elf64_Addr,
        pub dlpi_name: *const ::c_char,
        pub dlpi_phdr: *const ::Elf64_Phdr,
        pub dlpi_phnum: ::Elf64_Half,
        pub dlpi_adds: ::c_ulonglong,
        pub dlpi_subs: ::c_ulonglong,
    }
}

s_no_extra_traits! {
    #[cfg(libc_union)]
    pub union __c_anonymous_fp_reg_set {
        pub fpchip_state: __c_anonymous_fpchip_state,
        pub f_fpregs: [[u32; 13]; 10],
    }

    pub struct fpregset_t {
        pub fp_reg_set: __c_anonymous_fp_reg_set,
    }

    pub struct mcontext_t {
        pub gregs: [::greg_t; 28],
        pub fpregs: fpregset_t,
    }

    pub struct ucontext_t {
        pub uc_flags: ::c_ulong,
        pub uc_link: *mut ucontext_t,
        pub uc_sigmask: ::sigset_t,
        pub uc_stack: ::stack_t,
        pub uc_mcontext: mcontext_t,
        pub uc_filler: [::c_long; 5],
    }
}

cfg_if! {
    if #[cfg(feature = "extra_traits")] {
        #[cfg(libc_union)]
        impl PartialEq for __c_anonymous_fp_reg_set {
            fn eq(&self, other: &__c_anonymous_fp_reg_set) -> bool {
                unsafe {
                self.fpchip_state == other.fpchip_state ||
                    self.
                    f_fpregs.
                    iter().
                    zip(other.f_fpregs.iter()).
                    all(|(a, b)| a == b)
                }
            }
        }
        #[cfg(libc_union)]
        impl Eq for __c_anonymous_fp_reg_set {}
        #[cfg(libc_union)]
        impl ::fmt::Debug for __c_anonymous_fp_reg_set {
            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
                unsafe {
                f.debug_struct("__c_anonymous_fp_reg_set")
                    .field("fpchip_state", &{self.fpchip_state})
                    .field("f_fpregs", &{self.f_fpregs})
                    .finish()
                }
            }
        }
        impl PartialEq for fpregset_t {
            fn eq(&self, other: &fpregset_t) -> bool {
                self.fp_reg_set == other.fp_reg_set
            }
        }
        impl Eq for fpregset_t {}
        impl ::fmt::Debug for fpregset_t {
            fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("fpregset_t")
                    .field("fp_reg_set", &self.fp_reg_set)
                    .finish()
            }
        }
        impl PartialEq for mcontext_t {
            fn eq(&self, other: &mcontext_t) -> bool {
                self.gregs == other.gregs &&
                    self.fpregs == other.fpregs
            }
        }
        impl Eq for mcontext_t {}
        impl ::fmt::Debug for mcontext_t {
            fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("mcontext_t")
                    .field("gregs", &self.gregs)
                    .field("fpregs", &self.fpregs)
                    .finish()
            }
        }
        impl PartialEq for ucontext_t {
            fn eq(&self, other: &ucontext_t) -> bool {
                self.uc_flags == other.uc_flags
                    && self.uc_link == other.uc_link
                    && self.uc_sigmask == other.uc_sigmask
                    && self.uc_stack == other.uc_stack
                    && self.uc_mcontext == other.uc_mcontext
                    && self.uc_filler == other.uc_filler
            }
        }
        impl Eq for ucontext_t {}
        impl ::fmt::Debug for ucontext_t {
            fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result {
                f.debug_struct("ucontext_t")
                    .field("uc_flags", &self.uc_flags)
                    .field("uc_link", &self.uc_link)
                    .field("uc_sigmask", &self.uc_sigmask)
                    .field("uc_stack", &self.uc_stack)
                    .field("uc_mcontext", &self.uc_mcontext)
                    .field("uc_filler", &self.uc_filler)
                    .finish()
            }
        }

    }
}

// sys/regset.h

pub const REG_GSBASE: ::c_int = 27;
pub const REG_FSBASE: ::c_int = 26;
pub const REG_DS: ::c_int = 25;
pub const REG_ES: ::c_int = 24;
pub const REG_GS: ::c_int = 23;
pub const REG_FS: ::c_int = 22;
pub const REG_SS: ::c_int = 21;
pub const REG_RSP: ::c_int = 20;
pub const REG_RFL: ::c_int = 19;
pub const REG_CS: ::c_int = 18;
pub const REG_RIP: ::c_int = 17;
pub const REG_ERR: ::c_int = 16;
pub const REG_TRAPNO: ::c_int = 15;
pub const REG_RAX: ::c_int = 14;
pub const REG_RCX: ::c_int = 13;
pub const REG_RDX: ::c_int = 12;
pub const REG_RBX: ::c_int = 11;
pub const REG_RBP: ::c_int = 10;
pub const REG_RSI: ::c_int = 9;
pub const REG_RDI: ::c_int = 8;
pub const REG_R8: ::c_int = 7;
pub const REG_R9: ::c_int = 6;
pub const REG_R10: ::c_int = 5;
pub const REG_R11: ::c_int = 4;
pub const REG_R12: ::c_int = 3;
pub const REG_R13: ::c_int = 2;
pub const REG_R14: ::c_int = 1;
pub const REG_R15: ::c_int = 0;
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Yury Krivopalov <ykrivopalov@yandex.ru>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore N'th M'th

use crate::errors::*;
use crate::format::format_and_print;
use crate::options::*;
use crate::units::{Result, Unit};
use clap::{crate_version, App, AppSettings, Arg, ArgMatches};
use std::io::{BufRead, Write};
use uucore::display::Quotable;
use uucore::error::UResult;
use uucore::ranges::Range;

pub mod errors;
pub mod format;
pub mod options;
mod units;

static ABOUT: &str = "Convert numbers from/to human-readable strings";
static LONG_HELP: &str = "UNIT options:
   none   no auto-scaling is done; suffixes will trigger an error

   auto   accept optional single/two letter suffix:

          1K = 1000, 1Ki = 1024, 1M = 1000000, 1Mi = 1048576,

   si     accept optional single letter suffix:

          1K = 1000, 1M = 1000000, ...

   iec    accept optional single letter suffix:

          1K = 1024, 1M = 1048576, ...

   iec-i  accept optional two-letter suffix:

          1Ki = 1024, 1Mi = 1048576, ...

FIELDS supports cut(1) style field ranges:
  N    N'th field, counted from 1
  N-   from N'th field, to end of line
  N-M  from N'th to M'th field (inclusive)
  -M   from first to M'th field (inclusive)
  -    all fields
Multiple fields/ranges can be separated with commas
";

fn usage() -> String {
    format!("{0} [OPTION]... [NUMBER]...", uucore::execution_phrase())
}

fn handle_args<'a>(args: impl Iterator<Item = &'a str>, options: NumfmtOptions) -> UResult<()> {
    for l in args {
        match format_and_print(l, &options) {
            Ok(_) => Ok(()),
            Err(e) => Err(NumfmtError::FormattingError(e.to_string())),
        }?;
    }

    Ok(())
}

fn handle_buffer<R>(input: R, options: NumfmtOptions) -> UResult<()>
where
    R: BufRead,
{
    let mut lines = input.lines();
    for (idx, line) in lines.by_ref().enumerate() {
        match line {
            Ok(l) if idx < options.header => {
                println!("{}", l);
                Ok(())
            }
            Ok(l) => match format_and_print(&l, &options) {
                Ok(_) => Ok(()),
                Err(e) => Err(NumfmtError::FormattingError(e.to_string())),
            },
            Err(e) => Err(NumfmtError::IoError(e.to_string())),
        }?;
    }
    Ok(())
}

fn parse_unit(s: &str) -> Result<Unit> {
    match s {
        "auto" => Ok(Unit::Auto),
        "si" => Ok(Unit::Si),
        "iec" => Ok(Unit::Iec(false)),
        "iec-i" => Ok(Unit::Iec(true)),
        "none" => Ok(Unit::None),
        _ => Err("Unsupported unit is specified".to_owned()),
    }
}

fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
    let from = parse_unit(args.value_of(options::FROM).unwrap())?;
    let to = parse_unit(args.value_of(options::TO).unwrap())?;

    let transform = TransformOptions { from, to };

    let padding = match args.value_of(options::PADDING) {
        Some(s) => s.parse::<isize>().map_err(|err| err.to_string()),
        None => Ok(0),
    }?;

    let header = match args.occurrences_of(options::HEADER) {
        0 => Ok(0),
        _ => {
            let value = args.value_of(options::HEADER).unwrap();

            value
                .parse::<usize>()
                .map_err(|_| value)
                .and_then(|n| match n {
                    0 => Err(value),
                    _ => Ok(n),
                })
                .map_err(|value| format!("invalid header value {}", value.quote()))
        }
    }?;

    let fields = match args.value_of(options::FIELD).unwrap() {
        "-" => vec![Range {
            low: 1,
            high: std::usize::MAX,
        }],
        v => Range::from_list(v)?,
    };

    let delimiter = args.value_of(options::DELIMITER).map_or(Ok(None), |arg| {
        if arg.len() == 1 {
            Ok(Some(arg.to_string()))
        } else {
            Err("the delimiter must be a single character".to_string())
        }
    })?;

    // unwrap is fine because the argument has a default value
    let round = match args.value_of(options::ROUND).unwrap() {
        "up" => RoundMethod::Up,
        "down" => RoundMethod::Down,
        "from-zero" => RoundMethod::FromZero,
        "towards-zero" => RoundMethod::TowardsZero,
        "nearest" => RoundMethod::Nearest,
        _ => unreachable!("Should be restricted by clap"),
    };

    let suffix = args.value_of(options::SUFFIX).map(|s| s.to_owned());

    Ok(NumfmtOptions {
        transform,
        padding,
        header,
        fields,
        delimiter,
        round,
        suffix,
    })
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let usage = usage();

    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let options = parse_options(&matches).map_err(NumfmtError::IllegalArgument)?;

    let result = match matches.values_of(options::NUMBER) {
        Some(values) => handle_args(values, options),
        None => {
            let stdin = std::io::stdin();
            let mut locked_stdin = stdin.lock();
            handle_buffer(&mut locked_stdin, options)
        }
    };

    match result {
        Err(e) => {
            std::io::stdout().flush().expect("error flushing stdout");
            Err(e)
        }
        _ => Ok(()),
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .after_help(LONG_HELP)
        .setting(AppSettings::AllowNegativeNumbers)
        .arg(
            Arg::with_name(options::DELIMITER)
                .short("d")
                .long(options::DELIMITER)
                .value_name("X")
                .help("use X instead of whitespace for field delimiter"),
        )
        .arg(
            Arg::with_name(options::FIELD)
                .long(options::FIELD)
                .help("replace the numbers in these input fields (default=1) see FIELDS below")
                .value_name("FIELDS")
                .default_value(options::FIELD_DEFAULT),
        )
        .arg(
            Arg::with_name(options::FROM)
                .long(options::FROM)
                .help("auto-scale input numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::FROM_DEFAULT),
        )
        .arg(
            Arg::with_name(options::TO)
                .long(options::TO)
                .help("auto-scale output numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::TO_DEFAULT),
        )
        .arg(
            Arg::with_name(options::PADDING)
                .long(options::PADDING)
                .help(
                    "pad the output to N characters; positive N will \
                     right-align; negative N will left-align; padding is \
                     ignored if the output is wider than N; the default is \
                     to automatically pad if a whitespace is found",
                )
                .value_name("N"),
        )
        .arg(
            Arg::with_name(options::HEADER)
                .long(options::HEADER)
                .help(
                    "print (without converting) the first N header lines; \
                     N defaults to 1 if not specified",
                )
                .value_name("N")
                .default_value(options::HEADER_DEFAULT)
                .hide_default_value(true),
        )
        .arg(
            Arg::with_name(options::ROUND)
                .long(options::ROUND)
                .help(
                    "use METHOD for rounding when scaling; METHOD can be: up,\
                    down, from-zero (default), towards-zero, nearest",
                )
                .value_name("METHOD")
                .default_value("from-zero")
                .possible_values(&["up", "down", "from-zero", "towards-zero", "nearest"]),
        )
        .arg(
            Arg::with_name(options::SUFFIX)
                .long(options::SUFFIX)
                .help(
                    "print SUFFIX after each formatted number, and accept \
                    inputs optionally ending with SUFFIX",
                )
                .value_name("SUFFIX"),
        )
        .arg(Arg::with_name(options::NUMBER).hidden(true).multiple(true))
}

#[cfg(test)]
mod tests {
    use super::{handle_buffer, NumfmtOptions, Range, RoundMethod, TransformOptions, Unit};
    use std::io::{BufReader, Error, ErrorKind, Read};
    struct MockBuffer {}

    impl Read for MockBuffer {
        fn read(&mut self, _: &mut [u8]) -> Result<usize, Error> {
            Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
        }
    }

    fn get_valid_options() -> NumfmtOptions {
        NumfmtOptions {
            transform: TransformOptions {
                from: Unit::None,
                to: Unit::None,
            },
            padding: 10,
            header: 0,
            fields: vec![Range { low: 0, high: 1 }],
            delimiter: None,
            round: RoundMethod::Nearest,
            suffix: None,
        }
    }

    #[test]
    fn broken_buffer_returns_io_error() {
        let mock_buffer = MockBuffer {};
        let result = handle_buffer(BufReader::new(mock_buffer), get_valid_options())
            .expect_err("returned Ok after receiving IO error");
        let result_debug = format!("{:?}", result);
        let result_display = format!("{}", result);
        assert_eq!(result_debug, "IoError(\"broken pipe\")");
        assert_eq!(result_display, "broken pipe");
        assert_eq!(result.code(), 1);
    }

    #[test]
    fn non_numeric_returns_formatting_error() {
        let input_value = b"hello";
        let result = handle_buffer(BufReader::new(&input_value[..]), get_valid_options())
            .expect_err("returned Ok after receiving improperly formatted input");
        let result_debug = format!("{:?}", result);
        let result_display = format!("{}", result);
        assert_eq!(
            result_debug,
            "FormattingError(\"invalid suffix in input: 'hello'\")"
        );
        assert_eq!(result_display, "invalid suffix in input: 'hello'");
        assert_eq!(result.code(), 2);
    }

    #[test]
    fn valid_input_returns_ok() {
        let input_value = b"165";
        let result = handle_buffer(BufReader::new(&input_value[..]), get_valid_options());
        println!("{:?}", result);
        assert!(result.is_ok(), "did not return Ok for valid input");
    }
}
<commit_msg>numfmt: minor adjustments to test cases<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Yury Krivopalov <ykrivopalov@yandex.ru>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore N'th M'th

use crate::errors::*;
use crate::format::format_and_print;
use crate::options::*;
use crate::units::{Result, Unit};
use clap::{crate_version, App, AppSettings, Arg, ArgMatches};
use std::io::{BufRead, Write};
use uucore::display::Quotable;
use uucore::error::UResult;
use uucore::ranges::Range;

pub mod errors;
pub mod format;
pub mod options;
mod units;

static ABOUT: &str = "Convert numbers from/to human-readable strings";
static LONG_HELP: &str = "UNIT options:
   none   no auto-scaling is done; suffixes will trigger an error

   auto   accept optional single/two letter suffix:

          1K = 1000, 1Ki = 1024, 1M = 1000000, 1Mi = 1048576,

   si     accept optional single letter suffix:

          1K = 1000, 1M = 1000000, ...

   iec    accept optional single letter suffix:

          1K = 1024, 1M = 1048576, ...

   iec-i  accept optional two-letter suffix:

          1Ki = 1024, 1Mi = 1048576, ...

FIELDS supports cut(1) style field ranges:
  N    N'th field, counted from 1
  N-   from N'th field, to end of line
  N-M  from N'th to M'th field (inclusive)
  -M   from first to M'th field (inclusive)
  -    all fields
Multiple fields/ranges can be separated with commas
";

fn usage() -> String {
    format!("{0} [OPTION]... [NUMBER]...", uucore::execution_phrase())
}

fn handle_args<'a>(args: impl Iterator<Item = &'a str>, options: NumfmtOptions) -> UResult<()> {
    for l in args {
        match format_and_print(l, &options) {
            Ok(_) => Ok(()),
            Err(e) => Err(NumfmtError::FormattingError(e.to_string())),
        }?;
    }

    Ok(())
}

fn handle_buffer<R>(input: R, options: NumfmtOptions) -> UResult<()>
where
    R: BufRead,
{
    let mut lines = input.lines();
    for (idx, line) in lines.by_ref().enumerate() {
        match line {
            Ok(l) if idx < options.header => {
                println!("{}", l);
                Ok(())
            }
            Ok(l) => match format_and_print(&l, &options) {
                Ok(_) => Ok(()),
                Err(e) => Err(NumfmtError::FormattingError(e.to_string())),
            },
            Err(e) => Err(NumfmtError::IoError(e.to_string())),
        }?;
    }
    Ok(())
}

fn parse_unit(s: &str) -> Result<Unit> {
    match s {
        "auto" => Ok(Unit::Auto),
        "si" => Ok(Unit::Si),
        "iec" => Ok(Unit::Iec(false)),
        "iec-i" => Ok(Unit::Iec(true)),
        "none" => Ok(Unit::None),
        _ => Err("Unsupported unit is specified".to_owned()),
    }
}

fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
    let from = parse_unit(args.value_of(options::FROM).unwrap())?;
    let to = parse_unit(args.value_of(options::TO).unwrap())?;

    let transform = TransformOptions { from, to };

    let padding = match args.value_of(options::PADDING) {
        Some(s) => s.parse::<isize>().map_err(|err| err.to_string()),
        None => Ok(0),
    }?;

    let header = match args.occurrences_of(options::HEADER) {
        0 => Ok(0),
        _ => {
            let value = args.value_of(options::HEADER).unwrap();

            value
                .parse::<usize>()
                .map_err(|_| value)
                .and_then(|n| match n {
                    0 => Err(value),
                    _ => Ok(n),
                })
                .map_err(|value| format!("invalid header value {}", value.quote()))
        }
    }?;

    let fields = match args.value_of(options::FIELD).unwrap() {
        "-" => vec![Range {
            low: 1,
            high: std::usize::MAX,
        }],
        v => Range::from_list(v)?,
    };

    let delimiter = args.value_of(options::DELIMITER).map_or(Ok(None), |arg| {
        if arg.len() == 1 {
            Ok(Some(arg.to_string()))
        } else {
            Err("the delimiter must be a single character".to_string())
        }
    })?;

    // unwrap is fine because the argument has a default value
    let round = match args.value_of(options::ROUND).unwrap() {
        "up" => RoundMethod::Up,
        "down" => RoundMethod::Down,
        "from-zero" => RoundMethod::FromZero,
        "towards-zero" => RoundMethod::TowardsZero,
        "nearest" => RoundMethod::Nearest,
        _ => unreachable!("Should be restricted by clap"),
    };

    let suffix = args.value_of(options::SUFFIX).map(|s| s.to_owned());

    Ok(NumfmtOptions {
        transform,
        padding,
        header,
        fields,
        delimiter,
        round,
        suffix,
    })
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let usage = usage();

    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let options = parse_options(&matches).map_err(NumfmtError::IllegalArgument)?;

    let result = match matches.values_of(options::NUMBER) {
        Some(values) => handle_args(values, options),
        None => {
            let stdin = std::io::stdin();
            let mut locked_stdin = stdin.lock();
            handle_buffer(&mut locked_stdin, options)
        }
    };

    match result {
        Err(e) => {
            std::io::stdout().flush().expect("error flushing stdout");
            Err(e)
        }
        _ => Ok(()),
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .after_help(LONG_HELP)
        .setting(AppSettings::AllowNegativeNumbers)
        .arg(
            Arg::with_name(options::DELIMITER)
                .short("d")
                .long(options::DELIMITER)
                .value_name("X")
                .help("use X instead of whitespace for field delimiter"),
        )
        .arg(
            Arg::with_name(options::FIELD)
                .long(options::FIELD)
                .help("replace the numbers in these input fields (default=1) see FIELDS below")
                .value_name("FIELDS")
                .default_value(options::FIELD_DEFAULT),
        )
        .arg(
            Arg::with_name(options::FROM)
                .long(options::FROM)
                .help("auto-scale input numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::FROM_DEFAULT),
        )
        .arg(
            Arg::with_name(options::TO)
                .long(options::TO)
                .help("auto-scale output numbers to UNITs; see UNIT below")
                .value_name("UNIT")
                .default_value(options::TO_DEFAULT),
        )
        .arg(
            Arg::with_name(options::PADDING)
                .long(options::PADDING)
                .help(
                    "pad the output to N characters; positive N will \
                     right-align; negative N will left-align; padding is \
                     ignored if the output is wider than N; the default is \
                     to automatically pad if a whitespace is found",
                )
                .value_name("N"),
        )
        .arg(
            Arg::with_name(options::HEADER)
                .long(options::HEADER)
                .help(
                    "print (without converting) the first N header lines; \
                     N defaults to 1 if not specified",
                )
                .value_name("N")
                .default_value(options::HEADER_DEFAULT)
                .hide_default_value(true),
        )
        .arg(
            Arg::with_name(options::ROUND)
                .long(options::ROUND)
                .help(
                    "use METHOD for rounding when scaling; METHOD can be: up,\
                    down, from-zero (default), towards-zero, nearest",
                )
                .value_name("METHOD")
                .default_value("from-zero")
                .possible_values(&["up", "down", "from-zero", "towards-zero", "nearest"]),
        )
        .arg(
            Arg::with_name(options::SUFFIX)
                .long(options::SUFFIX)
                .help(
                    "print SUFFIX after each formatted number, and accept \
                    inputs optionally ending with SUFFIX",
                )
                .value_name("SUFFIX"),
        )
        .arg(Arg::with_name(options::NUMBER).hidden(true).multiple(true))
}

#[cfg(test)]
mod tests {
    use super::{handle_buffer, NumfmtOptions, Range, RoundMethod, TransformOptions, Unit};
    use std::io::{BufReader, Error, ErrorKind, Read};
    struct MockBuffer {}

    impl Read for MockBuffer {
        fn read(&mut self, _: &mut [u8]) -> Result<usize, Error> {
            Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
        }
    }

    fn get_valid_options() -> NumfmtOptions {
        NumfmtOptions {
            transform: TransformOptions {
                from: Unit::None,
                to: Unit::None,
            },
            padding: 10,
            header: 1,
            fields: vec![Range { low: 0, high: 1 }],
            delimiter: None,
            round: RoundMethod::Nearest,
            suffix: None,
        }
    }

    #[test]
    fn broken_buffer_returns_io_error() {
        let mock_buffer = MockBuffer {};
        let result = handle_buffer(BufReader::new(mock_buffer), get_valid_options())
            .expect_err("returned Ok after receiving IO error");
        let result_debug = format!("{:?}", result);
        let result_display = format!("{}", result);
        assert_eq!(result_debug, "IoError(\"broken pipe\")");
        assert_eq!(result_display, "broken pipe");
        assert_eq!(result.code(), 1);
    }

    #[test]
    fn non_numeric_returns_formatting_error() {
        let input_value = b"135\nhello";
        let result = handle_buffer(BufReader::new(&input_value[..]), get_valid_options())
            .expect_err("returned Ok after receiving improperly formatted input");
        let result_debug = format!("{:?}", result);
        let result_display = format!("{}", result);
        assert_eq!(
            result_debug,
            "FormattingError(\"invalid suffix in input: 'hello'\")"
        );
        assert_eq!(result_display, "invalid suffix in input: 'hello'");
        assert_eq!(result.code(), 2);
    }

    #[test]
    fn valid_input_returns_ok() {
        let input_value = b"165\n100\n300\n500";
        let result = handle_buffer(BufReader::new(&input_value[..]), get_valid_options());
        assert!(result.is_ok(), "did not return Ok for valid input");
    }
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use] extern crate serde_derive;

use std::collections::HashMap;
use std::fmt;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    TimeStamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> Option<AMQPType> {
        match id {
            't' => Some(AMQPType::Boolean),
            'b' => Some(AMQPType::ShortShortInt),
            'B' => Some(AMQPType::ShortShortUInt),
            'U' => Some(AMQPType::ShortInt),
            'u' => Some(AMQPType::ShortUInt),
            'I' => Some(AMQPType::LongInt),
            'i' => Some(AMQPType::LongUInt),
            'L' => Some(AMQPType::LongLongInt),
            'l' => Some(AMQPType::LongLongUInt),
            'f' => Some(AMQPType::Float),
            'd' => Some(AMQPType::Double),
            'D' => Some(AMQPType::DecimalValue),
            's' => Some(AMQPType::ShortString),
            'S' => Some(AMQPType::LongString),
            'A' => Some(AMQPType::FieldArray),
            'T' => Some(AMQPType::TimeStamp),
            'F' => Some(AMQPType::FieldTable),
            'V' => Some(AMQPType::Void),
            _   => None,
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::TimeStamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{}", self)
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type TimeStamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct DecimalValue {
    pub scale: u8,
    pub value: LongUInt,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    TimeStamp(TimeStamp),
    FieldTable(FieldTable),
    Void(Void),
}
<commit_msg>types: rename Timestamp<commit_after>extern crate serde;
#[macro_use] extern crate serde_derive;

use std::collections::HashMap;
use std::fmt;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    Timestamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> Option<AMQPType> {
        match id {
            't' => Some(AMQPType::Boolean),
            'b' => Some(AMQPType::ShortShortInt),
            'B' => Some(AMQPType::ShortShortUInt),
            'U' => Some(AMQPType::ShortInt),
            'u' => Some(AMQPType::ShortUInt),
            'I' => Some(AMQPType::LongInt),
            'i' => Some(AMQPType::LongUInt),
            'L' => Some(AMQPType::LongLongInt),
            'l' => Some(AMQPType::LongLongUInt),
            'f' => Some(AMQPType::Float),
            'd' => Some(AMQPType::Double),
            'D' => Some(AMQPType::DecimalValue),
            's' => Some(AMQPType::ShortString),
            'S' => Some(AMQPType::LongString),
            'A' => Some(AMQPType::FieldArray),
            'T' => Some(AMQPType::Timestamp),
            'F' => Some(AMQPType::FieldTable),
            'V' => Some(AMQPType::Void),
            _   => None,
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::Timestamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{}", self)
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type Timestamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct DecimalValue {
    pub scale: u8,
    pub value: LongUInt,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    Timestamp(Timestamp),
    FieldTable(FieldTable),
    Void(Void),
}
<|endoftext|>


<commit_before>use kekbit_core::api::{Reader, Writer};
use kekbit_core::header::Header;
use kekbit_core::shm::{shm_reader, shm_writer};
use kekbit_core::tick::TickUnit;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;

const FOREVER: u64 = 999_999_999_999;

fn run_writer(your_id: u64, channel_id: u64, run: Arc<AtomicBool>) {
    let tmp_dir = std::env::temp_dir().join("kekchat");
    let msg_size = 1000;
    let header = Header::new(
        your_id,
        channel_id,
        msg_size * 1000,
        msg_size,
        FOREVER,
        TickUnit::Nanos.nix_time(),
        TickUnit::Nanos,
    );
    let mut writer = shm_writer(&tmp_dir, &header).unwrap();
    std::thread::sleep(Duration::from_millis(100));
    while run.load(Ordering::Relaxed) == true {
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).expect("Failed read");
        let data = input.trim().as_bytes();
        writer.write(&data, data.len() as u32).unwrap();
        if input.trim() == "Bye".to_string() {
            println!("Sent Bye. Exiting.....");
            run.store(false, Ordering::Relaxed);
            break;
        }
    }
}

fn run_reader(other_id: u64, channel_id: u64, run: Arc<AtomicBool>) {
    let tmp_dir = std::env::temp_dir().join("kekchat");
    let mut tries = 5;
    let mut reader_res = shm_reader(&tmp_dir, other_id, channel_id);
    std::thread::sleep(Duration::from_millis(1000));
    while tries > 0 && reader_res.is_err() {
        reader_res = shm_reader(&tmp_dir, other_id, channel_id);
        if reader_res.is_ok() {
            break;
        }
        std::thread::sleep(Duration::from_millis(300));
        tries -= 1;
    }
    if reader_res.is_err() {
        println!("Could not connect to chat partner");
        std::process::exit(-1);
    }
    let mut reader = reader_res.unwrap();
    while run.load(Ordering::Relaxed) == true {
        let mut stop = false;
        let read_res = reader.read(
            &mut |msg: &[u8]| {
                let msg_str = std::str::from_utf8(&msg).unwrap();
                println!("{} >{}", other_id, msg_str);
                if msg_str == "Bye".to_string() {
                    println!("Received Bye. Exiting.....");
                    stop = true;
                }
            },
            10,
        );
        if stop {
            run.store(false, Ordering::Relaxed);
            std::process::exit(0);
        } else {
            match read_res {
                Ok(bytes_count) => {
                    if bytes_count == 0 {
                        std::thread::sleep(Duration::from_millis(1000));
                    }
                }
                Err(err) => {
                    println!("Error occured {:?} ", err);
                    run.store(false, Ordering::Relaxed);
                    std::io::stdin()::close();
                }
            }
        }
    }
}

pub fn main() {
    let args: Vec<u64> = std::env::args().skip(1).map(|id| id.parse().unwrap()).collect();
    assert!(args.len() == 3);
    let your_id = args[0];
    let other_id = args[1];
    let channel_id = args[2];
    println!("{} will talk with {} on channel {}", your_id, other_id, channel_id);
    let run = Arc::new(AtomicBool::new(true));
    let run_w = run.clone();
    let run_r = run.clone();
    let handle_w = std::thread::spawn(move || run_writer(your_id, channel_id, run_w));
    let handle_r = std::thread::spawn(move || run_reader(other_id, channel_id, run_r));
    handle_r.join().unwrap();
    handle_w.join().unwrap();
}
<commit_msg>Compilation error in chat sample fixed.<commit_after>use kekbit_core::api::{Reader, Writer};
use kekbit_core::header::Header;
use kekbit_core::shm::{shm_reader, shm_writer};
use kekbit_core::tick::TickUnit;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;

const FOREVER: u64 = 999_999_999_999;

fn run_writer(your_id: u64, channel_id: u64, run: Arc<AtomicBool>) {
    let tmp_dir = std::env::temp_dir().join("kekchat");
    let msg_size = 1000;
    let header = Header::new(
        your_id,
        channel_id,
        msg_size * 1000,
        msg_size,
        FOREVER,
        TickUnit::Nanos.nix_time(),
        TickUnit::Nanos,
    );
    let mut writer = shm_writer(&tmp_dir, &header).unwrap();
    std::thread::sleep(Duration::from_millis(100));
    while run.load(Ordering::Relaxed) == true {
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).expect("Failed read");
        let data = input.trim().as_bytes();
        writer.write(&data, data.len() as u32).unwrap();
        if input.trim() == "Bye".to_string() {
            println!("Sent Bye. Exiting.....");
            run.store(false, Ordering::Relaxed);
            break;
        }
    }
}

fn run_reader(other_id: u64, channel_id: u64, run: Arc<AtomicBool>) {
    let tmp_dir = std::env::temp_dir().join("kekchat");
    let mut tries = 5;
    let mut reader_res = shm_reader(&tmp_dir, other_id, channel_id);
    std::thread::sleep(Duration::from_millis(1000));
    while tries > 0 && reader_res.is_err() {
        reader_res = shm_reader(&tmp_dir, other_id, channel_id);
        if reader_res.is_ok() {
            break;
        }
        std::thread::sleep(Duration::from_millis(300));
        tries -= 1;
    }
    if reader_res.is_err() {
        println!("Could not connect to chat partner");
        std::process::exit(-1);
    }
    let mut reader = reader_res.unwrap();
    while run.load(Ordering::Relaxed) == true {
        let mut stop = false;
        let read_res = reader.read(
            &mut |msg: &[u8]| {
                let msg_str = std::str::from_utf8(&msg).unwrap();
                println!("{} >{}", other_id, msg_str);
                if msg_str == "Bye".to_string() {
                    println!("Received Bye. Exiting.....");
                    stop = true;
                }
            },
            10,
        );
        if stop {
            run.store(false, Ordering::Relaxed);
            std::process::exit(0);
        } else {
            match read_res {
                Ok(bytes_count) => {
                    if bytes_count == 0 {
                        std::thread::sleep(Duration::from_millis(1000));
                    }
                }
                Err(err) => {
                    println!("Error occured {:?} ", err);
                    run.store(false, Ordering::Relaxed);
                    std::process::exit(0);
                }
            }
        }
    }
}

pub fn main() {
    let args: Vec<u64> = std::env::args().skip(1).map(|id| id.parse().unwrap()).collect();
    assert!(args.len() == 3);
    let your_id = args[0];
    let other_id = args[1];
    let channel_id = args[2];
    println!("{} will talk with {} on channel {}", your_id, other_id, channel_id);
    let run = Arc::new(AtomicBool::new(true));
    let run_w = run.clone();
    let run_r = run.clone();
    let handle_w = std::thread::spawn(move || run_writer(your_id, channel_id, run_w));
    let handle_r = std::thread::spawn(move || run_reader(other_id, channel_id, run_r));
    handle_r.join().unwrap();
    handle_w.join().unwrap();
}
<|endoftext|>


<commit_before>//! Common types for the Cretonne code generator.

use std::default::Default;
use std::fmt::{self, Display, Formatter};

// ====--------------------------------------------------------------------------------------====//
//
// Value types
//
// ====--------------------------------------------------------------------------------------====//

/// The type of an SSA value.
///
/// The `VOID` type is only used for instructions that produce no value. It can't be part of a SIMD
/// vector.
///
/// Basic integer types: `I8`, `I16`, `I32`, and `I64`. These types are sign-agnostic.
///
/// Basic floating point types: `F32` and `F64`. IEEE single and double precision.
///
/// Boolean types: `B1`, `B8`, `B16`, `B32`, and `B64`. These all encode 'true' or 'false'. The
/// larger types use redundant bits.
///
/// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type.
///
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Type(u8);

/// No type. Used for functions without a return value. Can't be loaded or stored. Can't be part of
/// a SIMD vector.
pub const VOID: Type = Type(0);

// Include code generated by `meta/gen_types.py`. This file contains constant definitions for all
// the scalar types as well as common vector types for 64, 128, 256, and 512-bit SID vectors.
include!(concat!(env!("OUT_DIR"), "/types.rs"));

impl Type {
    /// Get the lane type of this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns itself.
    pub fn lane_type(self) -> Type {
        Type(self.0 & 0x0f)
    }

    /// Get log2 of the number of bits in a lane.
    pub fn log2_lane_bits(self) -> u8 {
        match self.lane_type() {
            B1 => 0,
            B8 | I8 => 3,
            B16 | I16 => 4,
            B32 | I32 | F32 => 5,
            B64 | I64 | F64 => 6,
            _ => 0,
        }
    }

    /// Get the number of bits in a lane.
    pub fn lane_bits(self) -> u8 {
        match self.lane_type() {
            B1 => 1,
            B8 | I8 => 8,
            B16 | I16 => 16,
            B32 | I32 | F32 => 32,
            B64 | I64 | F64 => 64,
            _ => 0,
        }
    }

    /// Get a type with the same number of lanes as this type, but with the lanes replaced by
    /// booleans of the same size.
    pub fn as_bool(self) -> Type {
        // Replace the low 4 bits with the boolean version, preserve the high 4 bits.
        let lane = match self.lane_type() {
            B8 | I8 => B8,
            B16 | I16 => B16,
            B32 | I32 | F32 => B32,
            B64 | I64 | F64 => B64,
            _ => B1,
        };
        Type(lane.0 | (self.0 & 0xf0))
    }

    /// Get a type with the same number of lanes as this type, but with lanes that are half the
    /// number of bits.
    pub fn half_width(self) -> Option<Type> {
        let lane = match self.lane_type() {
            I16 => I8,
            I32 => I16,
            I64 => I32,
            F64 => F32,
            B16 => B8,
            B32 => B16,
            B64 => B32,
            _ => return None,
        };
        Some(Type(lane.0 | (self.0 & 0xf0)))
    }

    /// Get a type with the same number of lanes as this type, but with lanes that are twice the
    /// number of bits.
    pub fn double_width(self) -> Option<Type> {
        let lane = match self.lane_type() {
            I8 => I16,
            I16 => I32,
            I32 => I64,
            F32 => F64,
            B8 => B16,
            B16 => B32,
            B32 => B64,
            _ => return None,
        };
        Some(Type(lane.0 | (self.0 & 0xf0)))
    }

    /// Is this the VOID type?
    pub fn is_void(self) -> bool {
        self == VOID
    }

    /// Is this a scalar boolean type?
    pub fn is_bool(self) -> bool {
        match self {
            B1 | B8 | B16 | B32 | B64 => true,
            _ => false,
        }
    }

    /// Is this a scalar integer type?
    pub fn is_int(self) -> bool {
        match self {
            I8 | I16 | I32 | I64 => true,
            _ => false,
        }
    }

    /// Is this a scalar floating point type?
    pub fn is_float(self) -> bool {
        match self {
            F32 | F64 => true,
            _ => false,
        }
    }

    /// Get log2 of the number of lanes in this SIMD vector type.
    ///
    /// All SIMD types have a lane count that is a power of two and no larger than 256, so this
    /// will be a number in the range 0-8.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it return 0.
    pub fn log2_lane_count(self) -> u8 {
        self.0 >> 4
    }

    /// Is this a scalar type? (That is, not a SIMD vector type).
    ///
    /// A scalar type is the same as a SIMD vector type with one lane.
    pub fn is_scalar(self) -> bool {
        self.log2_lane_count() == 0
    }

    /// Get the number of lanes in this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
    pub fn lane_count(self) -> u16 {
        1 << self.log2_lane_count()
    }

    /// Get the total number of bits used to represent this type.
    pub fn bits(self) -> u16 {
        self.lane_bits() as u16 * self.lane_count()
    }

    /// Get a SIMD vector type with `n` times more lanes than this one.
    ///
    /// If this is a scalar type, this produces a SIMD type with this as a lane type and `n` lanes.
    ///
    /// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
    /// self.lane_count()` lanes.
    pub fn by(self, n: u16) -> Option<Type> {
        if self.lane_bits() == 0 || !n.is_power_of_two() {
            return None;
        }
        let log2_lanes: u32 = n.trailing_zeros();
        let new_type = self.0 as u32 + (log2_lanes << 4);
        if new_type < 0x90 {
            Some(Type(new_type as u8))
        } else {
            None
        }
    }

    /// Get a SIMD vector with half the number of lanes.
    pub fn half_vector(self) -> Option<Type> {
        if self.is_scalar() {
            None
        } else {
            Some(Type(self.0 - 0x10))
        }
    }

    /// Index of this type, for use with hash tables etc.
    pub fn index(self) -> usize {
        self.0 as usize
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_void() {
            write!(f, "void")
        } else if self.is_bool() {
            write!(f, "b{}", self.lane_bits())
        } else if self.is_int() {
            write!(f, "i{}", self.lane_bits())
        } else if self.is_float() {
            write!(f, "f{}", self.lane_bits())
        } else if !self.is_scalar() {
            write!(f, "{}x{}", self.lane_type(), self.lane_count())
        } else {
            panic!("Invalid Type(0x{:x})", self.0)
        }
    }
}

impl Default for Type {
    fn default() -> Type {
        VOID
    }
}

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

    #[test]
    fn basic_scalars() {
        assert_eq!(VOID, VOID.lane_type());
        assert_eq!(0, VOID.bits());
        assert_eq!(B1, B1.lane_type());
        assert_eq!(B8, B8.lane_type());
        assert_eq!(B16, B16.lane_type());
        assert_eq!(B32, B32.lane_type());
        assert_eq!(B64, B64.lane_type());
        assert_eq!(I8, I8.lane_type());
        assert_eq!(I16, I16.lane_type());
        assert_eq!(I32, I32.lane_type());
        assert_eq!(I64, I64.lane_type());
        assert_eq!(F32, F32.lane_type());
        assert_eq!(F64, F64.lane_type());

        assert_eq!(VOID.lane_bits(), 0);
        assert_eq!(B1.lane_bits(), 1);
        assert_eq!(B8.lane_bits(), 8);
        assert_eq!(B16.lane_bits(), 16);
        assert_eq!(B32.lane_bits(), 32);
        assert_eq!(B64.lane_bits(), 64);
        assert_eq!(I8.lane_bits(), 8);
        assert_eq!(I16.lane_bits(), 16);
        assert_eq!(I32.lane_bits(), 32);
        assert_eq!(I64.lane_bits(), 64);
        assert_eq!(F32.lane_bits(), 32);
        assert_eq!(F64.lane_bits(), 64);
    }

    #[test]
    fn typevar_functions() {
        assert_eq!(VOID.half_width(), None);
        assert_eq!(B1.half_width(), None);
        assert_eq!(B8.half_width(), None);
        assert_eq!(B16.half_width(), Some(B8));
        assert_eq!(B32.half_width(), Some(B16));
        assert_eq!(B64.half_width(), Some(B32));
        assert_eq!(I8.half_width(), None);
        assert_eq!(I16.half_width(), Some(I8));
        assert_eq!(I32.half_width(), Some(I16));
        assert_eq!(I32X4.half_width(), Some(I16X4));
        assert_eq!(I64.half_width(), Some(I32));
        assert_eq!(F32.half_width(), None);
        assert_eq!(F64.half_width(), Some(F32));

        assert_eq!(VOID.double_width(), None);
        assert_eq!(B1.double_width(), None);
        assert_eq!(B8.double_width(), Some(B16));
        assert_eq!(B16.double_width(), Some(B32));
        assert_eq!(B32.double_width(), Some(B64));
        assert_eq!(B64.double_width(), None);
        assert_eq!(I8.double_width(), Some(I16));
        assert_eq!(I16.double_width(), Some(I32));
        assert_eq!(I32.double_width(), Some(I64));
        assert_eq!(I32X4.double_width(), Some(I64X4));
        assert_eq!(I64.double_width(), None);
        assert_eq!(F32.double_width(), Some(F64));
        assert_eq!(F64.double_width(), None);
    }

    #[test]
    fn vectors() {
        let big = F64.by(256).unwrap();
        assert_eq!(big.lane_bits(), 64);
        assert_eq!(big.lane_count(), 256);
        assert_eq!(big.bits(), 64 * 256);

        assert_eq!(big.half_vector().unwrap().to_string(), "f64x128");
        assert_eq!(B1.by(2).unwrap().half_vector().unwrap().to_string(), "b1");
        assert_eq!(I32.half_vector(), None);
        assert_eq!(VOID.half_vector(), None);

        // Check that the generated constants match the computed vector types.
        assert_eq!(I32.by(4), Some(I32X4));
        assert_eq!(F64.by(8), Some(F64X8));
    }

    #[test]
    fn format_scalars() {
        assert_eq!(VOID.to_string(), "void");
        assert_eq!(B1.to_string(), "b1");
        assert_eq!(B8.to_string(), "b8");
        assert_eq!(B16.to_string(), "b16");
        assert_eq!(B32.to_string(), "b32");
        assert_eq!(B64.to_string(), "b64");
        assert_eq!(I8.to_string(), "i8");
        assert_eq!(I16.to_string(), "i16");
        assert_eq!(I32.to_string(), "i32");
        assert_eq!(I64.to_string(), "i64");
        assert_eq!(F32.to_string(), "f32");
        assert_eq!(F64.to_string(), "f64");
    }

    #[test]
    fn format_vectors() {
        assert_eq!(B1.by(8).unwrap().to_string(), "b1x8");
        assert_eq!(B8.by(1).unwrap().to_string(), "b8");
        assert_eq!(B16.by(256).unwrap().to_string(), "b16x256");
        assert_eq!(B32.by(4).unwrap().by(2).unwrap().to_string(), "b32x8");
        assert_eq!(B64.by(8).unwrap().to_string(), "b64x8");
        assert_eq!(I8.by(64).unwrap().to_string(), "i8x64");
        assert_eq!(F64.by(2).unwrap().to_string(), "f64x2");
        assert_eq!(I8.by(3), None);
        assert_eq!(I8.by(512), None);
        assert_eq!(VOID.by(4), None);
    }
}
<commit_msg>Make Type::as_bool() less pedantic for scalars.<commit_after>//! Common types for the Cretonne code generator.

use std::default::Default;
use std::fmt::{self, Display, Debug, Formatter};

// ====--------------------------------------------------------------------------------------====//
//
// Value types
//
// ====--------------------------------------------------------------------------------------====//

/// The type of an SSA value.
///
/// The `VOID` type is only used for instructions that produce no value. It can't be part of a SIMD
/// vector.
///
/// Basic integer types: `I8`, `I16`, `I32`, and `I64`. These types are sign-agnostic.
///
/// Basic floating point types: `F32` and `F64`. IEEE single and double precision.
///
/// Boolean types: `B1`, `B8`, `B16`, `B32`, and `B64`. These all encode 'true' or 'false'. The
/// larger types use redundant bits.
///
/// SIMD vector types have power-of-two lanes, up to 256. Lanes can be any int/float/bool type.
///
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Type(u8);

/// No type. Used for functions without a return value. Can't be loaded or stored. Can't be part of
/// a SIMD vector.
pub const VOID: Type = Type(0);

// Include code generated by `meta/gen_types.py`. This file contains constant definitions for all
// the scalar types as well as common vector types for 64, 128, 256, and 512-bit SIMD vectors.
include!(concat!(env!("OUT_DIR"), "/types.rs"));

impl Type {
    /// Get the lane type of this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns itself.
    pub fn lane_type(self) -> Type {
        Type(self.0 & 0x0f)
    }

    /// Get log2 of the number of bits in a lane.
    pub fn log2_lane_bits(self) -> u8 {
        match self.lane_type() {
            B1 => 0,
            B8 | I8 => 3,
            B16 | I16 => 4,
            B32 | I32 | F32 => 5,
            B64 | I64 | F64 => 6,
            _ => 0,
        }
    }

    /// Get the number of bits in a lane.
    pub fn lane_bits(self) -> u8 {
        match self.lane_type() {
            B1 => 1,
            B8 | I8 => 8,
            B16 | I16 => 16,
            B32 | I32 | F32 => 32,
            B64 | I64 | F64 => 64,
            _ => 0,
        }
    }

    /// Get a type with the same number of lanes as this type, but with the lanes replaced by
    /// booleans of the same size.
    ///
    /// Scalar types are treated as vectors with one lane, so they are converted to the multi-bit
    /// boolean types.
    pub fn as_bool_pedantic(self) -> Type {
        // Replace the low 4 bits with the boolean version, preserve the high 4 bits.
        let lane = match self.lane_type() {
            B8 | I8 => B8,
            B16 | I16 => B16,
            B32 | I32 | F32 => B32,
            B64 | I64 | F64 => B64,
            _ => B1,
        };
        Type(lane.0 | (self.0 & 0xf0))
    }

    /// Get a type with the same number of lanes as this type, but with the lanes replaced by
    /// booleans of the same size.
    ///
    /// Scalar types are all converted to `b1` which is usually what you want.
    pub fn as_bool(self) -> Type {
        if self.is_scalar() {
            B1
        } else {
            self.as_bool_pedantic()
        }
    }

    /// Get a type with the same number of lanes as this type, but with lanes that are half the
    /// number of bits.
    pub fn half_width(self) -> Option<Type> {
        let lane = match self.lane_type() {
            I16 => I8,
            I32 => I16,
            I64 => I32,
            F64 => F32,
            B16 => B8,
            B32 => B16,
            B64 => B32,
            _ => return None,
        };
        Some(Type(lane.0 | (self.0 & 0xf0)))
    }

    /// Get a type with the same number of lanes as this type, but with lanes that are twice the
    /// number of bits.
    pub fn double_width(self) -> Option<Type> {
        let lane = match self.lane_type() {
            I8 => I16,
            I16 => I32,
            I32 => I64,
            F32 => F64,
            B8 => B16,
            B16 => B32,
            B32 => B64,
            _ => return None,
        };
        Some(Type(lane.0 | (self.0 & 0xf0)))
    }

    /// Is this the VOID type?
    pub fn is_void(self) -> bool {
        self == VOID
    }

    /// Is this a scalar boolean type?
    pub fn is_bool(self) -> bool {
        match self {
            B1 | B8 | B16 | B32 | B64 => true,
            _ => false,
        }
    }

    /// Is this a scalar integer type?
    pub fn is_int(self) -> bool {
        match self {
            I8 | I16 | I32 | I64 => true,
            _ => false,
        }
    }

    /// Is this a scalar floating point type?
    pub fn is_float(self) -> bool {
        match self {
            F32 | F64 => true,
            _ => false,
        }
    }

    /// Get log2 of the number of lanes in this SIMD vector type.
    ///
    /// All SIMD types have a lane count that is a power of two and no larger than 256, so this
    /// will be a number in the range 0-8.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it return 0.
    pub fn log2_lane_count(self) -> u8 {
        self.0 >> 4
    }

    /// Is this a scalar type? (That is, not a SIMD vector type).
    ///
    /// A scalar type is the same as a SIMD vector type with one lane.
    pub fn is_scalar(self) -> bool {
        self.log2_lane_count() == 0
    }

    /// Get the number of lanes in this SIMD vector type.
    ///
    /// A scalar type is the same as a SIMD vector type with one lane, so it returns 1.
    pub fn lane_count(self) -> u16 {
        1 << self.log2_lane_count()
    }

    /// Get the total number of bits used to represent this type.
    pub fn bits(self) -> u16 {
        self.lane_bits() as u16 * self.lane_count()
    }

    /// Get a SIMD vector type with `n` times more lanes than this one.
    ///
    /// If this is a scalar type, this produces a SIMD type with this as a lane type and `n` lanes.
    ///
    /// If this is already a SIMD vector type, this produces a SIMD vector type with `n *
    /// self.lane_count()` lanes.
    pub fn by(self, n: u16) -> Option<Type> {
        if self.lane_bits() == 0 || !n.is_power_of_two() {
            return None;
        }
        let log2_lanes: u32 = n.trailing_zeros();
        let new_type = self.0 as u32 + (log2_lanes << 4);
        if new_type < 0x90 {
            Some(Type(new_type as u8))
        } else {
            None
        }
    }

    /// Get a SIMD vector with half the number of lanes.
    pub fn half_vector(self) -> Option<Type> {
        if self.is_scalar() {
            None
        } else {
            Some(Type(self.0 - 0x10))
        }
    }

    /// Index of this type, for use with hash tables etc.
    pub fn index(self) -> usize {
        self.0 as usize
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_void() {
            write!(f, "void")
        } else if self.is_bool() {
            write!(f, "b{}", self.lane_bits())
        } else if self.is_int() {
            write!(f, "i{}", self.lane_bits())
        } else if self.is_float() {
            write!(f, "f{}", self.lane_bits())
        } else if !self.is_scalar() {
            write!(f, "{}x{}", self.lane_type(), self.lane_count())
        } else {
            panic!("Invalid Type(0x{:x})", self.0)
        }
    }
}

impl Debug for Type {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_void() {
            write!(f, "types::VOID")
        } else if self.is_bool() {
            write!(f, "types::B{}", self.lane_bits())
        } else if self.is_int() {
            write!(f, "types::I{}", self.lane_bits())
        } else if self.is_float() {
            write!(f, "types::F{}", self.lane_bits())
        } else if !self.is_scalar() {
            write!(f, "{:?}X{}", self.lane_type(), self.lane_count())
        } else {
            write!(f, "Type(0x{:x})", self.0)
        }
    }
}

impl Default for Type {
    fn default() -> Type {
        VOID
    }
}

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

    #[test]
    fn basic_scalars() {
        assert_eq!(VOID, VOID.lane_type());
        assert_eq!(0, VOID.bits());
        assert_eq!(B1, B1.lane_type());
        assert_eq!(B8, B8.lane_type());
        assert_eq!(B16, B16.lane_type());
        assert_eq!(B32, B32.lane_type());
        assert_eq!(B64, B64.lane_type());
        assert_eq!(I8, I8.lane_type());
        assert_eq!(I16, I16.lane_type());
        assert_eq!(I32, I32.lane_type());
        assert_eq!(I64, I64.lane_type());
        assert_eq!(F32, F32.lane_type());
        assert_eq!(F64, F64.lane_type());

        assert_eq!(VOID.lane_bits(), 0);
        assert_eq!(B1.lane_bits(), 1);
        assert_eq!(B8.lane_bits(), 8);
        assert_eq!(B16.lane_bits(), 16);
        assert_eq!(B32.lane_bits(), 32);
        assert_eq!(B64.lane_bits(), 64);
        assert_eq!(I8.lane_bits(), 8);
        assert_eq!(I16.lane_bits(), 16);
        assert_eq!(I32.lane_bits(), 32);
        assert_eq!(I64.lane_bits(), 64);
        assert_eq!(F32.lane_bits(), 32);
        assert_eq!(F64.lane_bits(), 64);
    }

    #[test]
    fn typevar_functions() {
        assert_eq!(VOID.half_width(), None);
        assert_eq!(B1.half_width(), None);
        assert_eq!(B8.half_width(), None);
        assert_eq!(B16.half_width(), Some(B8));
        assert_eq!(B32.half_width(), Some(B16));
        assert_eq!(B64.half_width(), Some(B32));
        assert_eq!(I8.half_width(), None);
        assert_eq!(I16.half_width(), Some(I8));
        assert_eq!(I32.half_width(), Some(I16));
        assert_eq!(I32X4.half_width(), Some(I16X4));
        assert_eq!(I64.half_width(), Some(I32));
        assert_eq!(F32.half_width(), None);
        assert_eq!(F64.half_width(), Some(F32));

        assert_eq!(VOID.double_width(), None);
        assert_eq!(B1.double_width(), None);
        assert_eq!(B8.double_width(), Some(B16));
        assert_eq!(B16.double_width(), Some(B32));
        assert_eq!(B32.double_width(), Some(B64));
        assert_eq!(B64.double_width(), None);
        assert_eq!(I8.double_width(), Some(I16));
        assert_eq!(I16.double_width(), Some(I32));
        assert_eq!(I32.double_width(), Some(I64));
        assert_eq!(I32X4.double_width(), Some(I64X4));
        assert_eq!(I64.double_width(), None);
        assert_eq!(F32.double_width(), Some(F64));
        assert_eq!(F64.double_width(), None);
    }

    #[test]
    fn vectors() {
        let big = F64.by(256).unwrap();
        assert_eq!(big.lane_bits(), 64);
        assert_eq!(big.lane_count(), 256);
        assert_eq!(big.bits(), 64 * 256);

        assert_eq!(big.half_vector().unwrap().to_string(), "f64x128");
        assert_eq!(B1.by(2).unwrap().half_vector().unwrap().to_string(), "b1");
        assert_eq!(I32.half_vector(), None);
        assert_eq!(VOID.half_vector(), None);

        // Check that the generated constants match the computed vector types.
        assert_eq!(I32.by(4), Some(I32X4));
        assert_eq!(F64.by(8), Some(F64X8));
    }

    #[test]
    fn format_scalars() {
        assert_eq!(VOID.to_string(), "void");
        assert_eq!(B1.to_string(), "b1");
        assert_eq!(B8.to_string(), "b8");
        assert_eq!(B16.to_string(), "b16");
        assert_eq!(B32.to_string(), "b32");
        assert_eq!(B64.to_string(), "b64");
        assert_eq!(I8.to_string(), "i8");
        assert_eq!(I16.to_string(), "i16");
        assert_eq!(I32.to_string(), "i32");
        assert_eq!(I64.to_string(), "i64");
        assert_eq!(F32.to_string(), "f32");
        assert_eq!(F64.to_string(), "f64");
    }

    #[test]
    fn format_vectors() {
        assert_eq!(B1.by(8).unwrap().to_string(), "b1x8");
        assert_eq!(B8.by(1).unwrap().to_string(), "b8");
        assert_eq!(B16.by(256).unwrap().to_string(), "b16x256");
        assert_eq!(B32.by(4).unwrap().by(2).unwrap().to_string(), "b32x8");
        assert_eq!(B64.by(8).unwrap().to_string(), "b64x8");
        assert_eq!(I8.by(64).unwrap().to_string(), "i8x64");
        assert_eq!(F64.by(2).unwrap().to_string(), "f64x2");
        assert_eq!(I8.by(3), None);
        assert_eq!(I8.by(512), None);
        assert_eq!(VOID.by(4), None);
    }

    #[test]
    fn as_bool() {
        assert_eq!(I32X4.as_bool(), B32X4);
        assert_eq!(I32.as_bool(), B1);
        assert_eq!(I32X4.as_bool_pedantic(), B32X4);
        assert_eq!(I32.as_bool_pedantic(), B32);
    }
}
<|endoftext|>