<commit_before>#[feature(globs)];
#[crate_type = "lib"];
#[link(name = "win32")];

#[link_args = "-lgdi32"];

use std::ptr;

use ll::*;

pub mod ll {
    pub use ll::platform::*;
    pub use ll::windef::*;
    pub use ll::all::*;
    pub use ll::font::*;

    pub mod platform;
    pub mod windef;
    pub mod all;
    pub mod font;
}

pub mod instance;
pub mod resource;
pub mod font;
pub mod wchar;
pub mod window;
pub mod gdi;
pub mod dialog;

/// Returns a vector of (variable, value) pairs for all the environment
/// variables of the current process.
/// This is unicode-version of `std::os::env()`.
pub fn env() -> ~[(~str,~str)] {
    unsafe {
        unsafe fn get_env_pairs() -> ~[~str] {
            extern "system" {
                fn GetEnvironmentStringsW() -> *u16;
                fn FreeEnvironmentStringsW(ch: *u16) -> std::libc::BOOL;
            }

            let ch = GetEnvironmentStringsW();
            if (ch as uint == 0) {
                fail!("os::env() failure getting env string from OS: {}",
                       std::os::last_os_error());
            }
            let mut result = ~[];
            do wchar::from_c_u16_multistring(ch as *u16, None) |cstr| {
                result.push(cstr.to_str());
            };
            FreeEnvironmentStringsW(ch);
            result
        }

        fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
            let mut pairs = ~[];
            for p in input.iter() {
                let vs: ~[&str] = p.splitn_iter('=', 1).collect();
                debug!("splitting: vs: {:?} len: {}", vs, vs.len());
                assert_eq!(vs.len(), 2);
                pairs.push((vs[0].to_owned(), vs[1].to_owned()));
            }
            pairs
        }
        let unparsed_environ = get_env_pairs();
        debug!("unp: {:?}", unparsed_environ);
        env_convert(unparsed_environ)
    }
}

pub fn get_last_error() -> DWORD {
    unsafe { GetLastError() }
}

pub fn def_window_proc(hwnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT {
    unsafe { DefWindowProcW(hwnd, msg, w, l) }
}

pub fn main_window_loop() -> u32 {
    let msg = MSG {
        hwnd: ptr::mut_null(),
        message: 0 as UINT,
        wParam: 0 as WPARAM,
        lParam: 0 as LPARAM,
        time: 0 as DWORD,
        pt: POINT { x: 0 as LONG, y: 0 as LONG },
    };
    loop {
        let ret = unsafe {
            GetMessageW(&msg as *MSG, ptr::mut_null(),
                    0 as UINT, 0 as UINT)
        };

        if ret == 0 {
            let exit_code = msg.wParam;
            return exit_code;
        }
        else {
            unsafe {
                TranslateMessage(&msg as *MSG);
                DispatchMessageW(&msg as *MSG);
            }
        }
    }
}
<commit_msg>Fix main_window_loop on win64<commit_after>#[feature(globs)];
#[crate_type = "lib"];
#[link(name = "win32")];

#[link_args = "-lgdi32"];

use std::ptr;

use ll::*;

pub mod ll {
    pub use ll::platform::*;
    pub use ll::windef::*;
    pub use ll::all::*;
    pub use ll::font::*;

    pub mod platform;
    pub mod windef;
    pub mod all;
    pub mod font;
}

pub mod instance;
pub mod resource;
pub mod font;
pub mod wchar;
pub mod window;
pub mod gdi;
pub mod dialog;

/// Returns a vector of (variable, value) pairs for all the environment
/// variables of the current process.
/// This is unicode-version of `std::os::env()`.
pub fn env() -> ~[(~str,~str)] {
    unsafe {
        unsafe fn get_env_pairs() -> ~[~str] {
            extern "system" {
                fn GetEnvironmentStringsW() -> *u16;
                fn FreeEnvironmentStringsW(ch: *u16) -> std::libc::BOOL;
            }

            let ch = GetEnvironmentStringsW();
            if (ch as uint == 0) {
                fail!("os::env() failure getting env string from OS: {}",
                       std::os::last_os_error());
            }
            let mut result = ~[];
            do wchar::from_c_u16_multistring(ch as *u16, None) |cstr| {
                result.push(cstr.to_str());
            };
            FreeEnvironmentStringsW(ch);
            result
        }

        fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
            let mut pairs = ~[];
            for p in input.iter() {
                let vs: ~[&str] = p.splitn_iter('=', 1).collect();
                debug!("splitting: vs: {:?} len: {}", vs, vs.len());
                assert_eq!(vs.len(), 2);
                pairs.push((vs[0].to_owned(), vs[1].to_owned()));
            }
            pairs
        }
        let unparsed_environ = get_env_pairs();
        debug!("unp: {:?}", unparsed_environ);
        env_convert(unparsed_environ)
    }
}

pub fn get_last_error() -> DWORD {
    unsafe { GetLastError() }
}

pub fn def_window_proc(hwnd: HWND, msg: UINT, w: WPARAM, l: LPARAM) -> LRESULT {
    unsafe { DefWindowProcW(hwnd, msg, w, l) }
}

pub fn main_window_loop() -> uint {
    let msg = MSG {
        hwnd: ptr::mut_null(),
        message: 0 as UINT,
        wParam: 0 as WPARAM,
        lParam: 0 as LPARAM,
        time: 0 as DWORD,
        pt: POINT { x: 0 as LONG, y: 0 as LONG },
    };
    loop {
        let ret = unsafe {
            GetMessageW(&msg as *MSG, ptr::mut_null(),
                    0 as UINT, 0 as UINT)
        };

        if ret == 0 {
            let exit_code = msg.wParam;
            return exit_code as uint;
        }
        else {
            unsafe {
                TranslateMessage(&msg as *MSG);
                DispatchMessageW(&msg as *MSG);
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(libc, std_misc, path_ext)]
#[cfg(not(windows))]
extern crate "pkg-config" as pkg_config;
extern crate libc;
use std::ffi::{OsStr, AsOsStr};
use std::os::unix::ffi::OsStrExt;
use std::fs::{self, PathExt};
use std::env;
use std::path::Path;

#[cfg(windows)]
static FINAL_LIB:&'static str = "libjit.dll";

#[cfg(not(windows))]
static FINAL_LIB:&'static str = "libjit.a";

static MINGW:&'static str = "c:/mingw";

static INSTALL_AUTOTOOLS_MSG:&'static str = "Failed to generate configuration script. Did you forget to install autotools, bison, flex, and libtool?";
#[cfg(windows)]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install MinGW and MSYS?";
#[cfg(not(windows))]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install gcc?";

fn main() {
	if cfg!(windows) && !Path::new(MINGW).exists() {
		panic!("{}", INSTALL_COMPILER_MSG);
	} else if pkg_config::find_library("jit").is_ok() {
		return;
	}
	let out_dir = env::var("OUT_DIR").unwrap();
	let out_dir = Path::new(&*out_dir);
	let submod_path = Path::new("libjit");
	let final_lib_dir = submod_path.join("jit/.libs");
	if !final_lib_dir.join(FINAL_LIB).exists() {
		run_wocare("git submodule init");
		run("git submodule update");
		if !submod_path.exists() {
			let text = format!("git clone git://git.savannah.gnu.org/libjit.git {}", submod_path.display());
			run(&*text);
		}
		chdir(submod_path);
		run_nice("sh auto_gen.sh", INSTALL_AUTOTOOLS_MSG);
		run_nice("sh configure --enable-static --disable-shared CC=clang CFLAGS=-fPIC", INSTALL_COMPILER_MSG);
		run("make");
	}
	let from = final_lib_dir.join(FINAL_LIB);
	let to = out_dir.join(FINAL_LIB);
    println!("{:?} -> {:?}", from, to);
	fs::copy(&from, &to).unwrap();
    println!("cargo:rustc-flags=-l jit:static -L {}", out_dir.display());
}
fn chdir(path: &Path) {
	use libc::chdir;
	use std::str::from_utf8_unchecked;
	unsafe {
		let c_path = path.as_os_str().to_cstring().unwrap();
		if libc::chdir(c_path.as_ptr()) == -1 {
			panic!("Failed to change directory into {}", from_utf8_unchecked(c_path.as_bytes()))
		}
	}
}
fn run_nice(cmd: &str, text: &str) {
	unsafe {
		let c_cmd = OsStr::from_str(cmd).to_cstring().unwrap();
		if libc::system(c_cmd.as_ptr()) != 0 {
			panic!("{}", text);
		}
	}
}
fn run(cmd: &str) {
	unsafe {
		let c_cmd = OsStr::from_str(cmd).to_cstring().unwrap();
		if libc::system(c_cmd.as_ptr()) != 0 {
			panic!("{} failed", cmd);
		}
	}
}
fn run_wocare(cmd: &str) {
	unsafe {
		let c_cmd = OsStr::from_str(cmd).to_cstring().unwrap();
		if libc::system(c_cmd.as_ptr()) < 0 {
			panic!("{} failed", cmd);
		}
	}
}
<commit_msg>Verbose errors in build script<commit_after>#![feature(libc, std_misc, path_ext)]
#[cfg(not(windows))]
extern crate "pkg-config" as pkg_config;
extern crate libc;
use std::ffi::{OsStr, AsOsStr};
use std::os::unix::ffi::OsStrExt;
use std::fs::{self, PathExt};
use std::env;
use std::path::Path;

#[cfg(windows)]
static FINAL_LIB:&'static str = "libjit.dll";

#[cfg(not(windows))]
static FINAL_LIB:&'static str = "libjit.a";

static MINGW:&'static str = "c:/mingw";

static INSTALL_AUTOTOOLS_MSG:&'static str = "Failed to generate configuration script. Did you forget to install autotools, bison, flex, and libtool?";

static USE_CARGO_MSG:&'static str = "Build script should be ran with Cargo";

#[cfg(windows)]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install MinGW and MSYS?";
#[cfg(not(windows))]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install gcc?";

fn main() {
	if cfg!(windows) && !Path::new(MINGW).exists() {
		panic!("{}", INSTALL_COMPILER_MSG);
	} else if pkg_config::find_library("jit").is_ok() {
		return;
	}
	let out_dir = env::var("OUT_DIR").ok().expect(USE_CARGO_MSG);
	let out_dir = Path::new(&*out_dir);
	let submod_path = Path::new("libjit");
	let final_lib_dir = submod_path.join("jit/.libs");
	if !final_lib_dir.join(FINAL_LIB).exists() {
		run_wocare("git submodule init");
		run("git submodule update");
		if !submod_path.exists() {
			let text = format!("git clone git://git.savannah.gnu.org/libjit.git {}", submod_path.display());
			run(&*text);
		}
		chdir(submod_path);
		run_nice("sh auto_gen.sh", INSTALL_AUTOTOOLS_MSG);
		run_nice("sh configure --enable-static --disable-shared CC=clang CFLAGS=-fPIC", INSTALL_COMPILER_MSG);
		run("make");
	}
	let from = final_lib_dir.join(FINAL_LIB);
	let to = out_dir.join(FINAL_LIB);
    println!("{:?} -> {:?}", from, to);
	if let Err(error) = fs::copy(&from, &to) {
		panic!("Failed to copy library from {:?} to {:?} due to {}", from, to, error)
	}
    println!("cargo:rustc-flags=-l jit:static -L {}", out_dir.display());
}
fn chdir(path: &Path) {
	use libc::chdir;
	use std::str::from_utf8_unchecked;
	unsafe {
		let c_path = path.as_os_str().to_cstring().unwrap();
		if libc::chdir(c_path.as_ptr()) == -1 {
			panic!("Failed to change directory into {}", from_utf8_unchecked(c_path.as_bytes()))
		}
	}
}
fn run_nice(cmd: &str, text: &str) {
	unsafe {
		let c_cmd = OsStr::from_str(cmd).to_cstring().unwrap();
		if libc::system(c_cmd.as_ptr()) != 0 {
			panic!("{}", text);
		}
	}
}
fn run(cmd: &str) {
	unsafe {
		let c_cmd = OsStr::from_str(cmd).to_cstring().unwrap();
		if libc::system(c_cmd.as_ptr()) != 0 {
			panic!("{} failed", cmd);
		}
	}
}
fn run_wocare(cmd: &str) {
	unsafe {
		let c_cmd = OsStr::from_str(cmd).to_cstring().unwrap();
		if libc::system(c_cmd.as_ptr()) < 0 {
			panic!("{} failed", cmd);
		}
	}
}
<|endoftext|>


<commit_before>extern mod std;

use std::*;
use io::{ReaderUtil,WriterUtil};

enum Result {
  Nil,
  Int(int),
  Data(~str),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

priv fn parse_data(len: uint, sb: net::tcp::TcpSocketBuf) -> Result {
  let res =
    if (len > 0) {
      let bytes = sb.read_bytes(len as uint);
      assert bytes.len() == len;
      Data(str::from_bytes(bytes))
    } else {
      Data(~"")
    };
  assert sb.read_char() == '\r';
  assert sb.read_char() == '\n';
  return res;
}

fn parse_list(len: uint, sb: net::tcp::TcpSocketBuf) -> Result {
  let mut list: ~[Result] = ~[];
  for len.times {
    let v =
      match sb.read_char() {
        '$' => parse_bulk(sb),
        ':' => parse_int(sb),
         _  => fail
      };
    list.push(v);
  }
  return List(list);
}

priv fn chop(s: ~str) -> ~str {
  s.slice(0, s.len() - 1)
}

priv fn parse_bulk(sb: net::tcp::TcpSocketBuf) -> Result {
  match int::from_str(chop(sb.read_line())) {
    None => fail,
    Some(-1) => Nil,
    Some(len) if len >= 0 => parse_data(len as uint, sb),
    Some(_) => fail
  }
}

priv fn parse_multi(sb: net::tcp::TcpSocketBuf) -> Result {
  match int::from_str(chop(sb.read_line())) {
    None => fail,
    Some(-1) => Nil,
    Some(0) => List(~[]),
    Some(len) if len >= 0 => parse_list(len as uint, sb),
    Some(_) => fail
  }
}

priv fn parse_int(sb: net::tcp::TcpSocketBuf) -> Result {
  match int::from_str(chop(sb.read_line())) {
    None => fail,
    Some(i) => Int(i)
  }
}

fn parse_response(sb: net::tcp::TcpSocketBuf) -> Result {
  match sb.read_char() {
    '$' => parse_bulk(sb),
    '*' => parse_multi(sb),
    '+' => Status(chop(sb.read_line())),
    '-' => Error(chop(sb.read_line())),
    ':' => parse_int(sb),
    _   => fail
  }
}

fn cmd_to_str(cmd: ~[~str]) -> ~str {
  let mut res = ~"*";
  str::push_str(&mut res, cmd.len().to_str());
  str::push_str(&mut res, "\r\n");
  for cmd.each |s| {
    str::push_str(&mut res, str::concat(~[~"$", s.len().to_str(), ~"\r\n", *s, ~"\r\n"]));
  }
  res
}

fn query(cmd: ~[~str], sb: net::tcp::TcpSocketBuf) -> Result {
  let cmd = cmd_to_str(cmd);
  //io::println(cmd);
  sb.write_str(cmd);
  let res = parse_response(sb);
  io::println(fmt!("%?", res));
  res
}

fn main() {
  let server_ip_addr = net::ip::v4::parse_addr("127.0.0.1");
  let server_port = 6379;
  let iotask = uv::global_loop::get();
  let connect_result = net::tcp::connect(server_ip_addr, server_port, iotask);
  let sock = result::unwrap(connect_result);
  let sb = net::tcp::socket_buf(sock);

/*  for 10_000.times {
    query(~[~"GET", ~"abc"], sb);
  }
*/

  query(~[~"MULTI"], sb);
  query(~[~"GET", ~"def"], sb);
  query(~[~"INCR", ~"def"], sb);
  query(~[~"INCR", ~"def"], sb);
  query(~[~"GET", ~"def"], sb);
  query(~[~"EXEC"], sb);

  query(~[~"SET", ~"abc", ~"XXX"], sb);
  query(~[~"SET", ~"def", ~"123"], sb);
  query(~[~"GET", ~"abc"], sb);
  query(~[~"MGET", ~"abc", ~"def", ~"non"], sb);
}
<commit_msg>Return raw data as [u8] instead of str.<commit_after>extern mod std;

use std::*;
use io::{ReaderUtil,WriterUtil};

enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

priv fn parse_data(len: uint, sb: net::tcp::TcpSocketBuf) -> Result {
  let res =
    if (len > 0) {
      let bytes = sb.read_bytes(len as uint);
      assert bytes.len() == len;
      Data(bytes)
    } else {
      Data(~[])
    };
  assert sb.read_char() == '\r';
  assert sb.read_char() == '\n';
  return res;
}

fn parse_list(len: uint, sb: net::tcp::TcpSocketBuf) -> Result {
  let mut list: ~[Result] = ~[];
  for len.times {
    let v =
      match sb.read_char() {
        '$' => parse_bulk(sb),
        ':' => parse_int(sb),
         _  => fail
      };
    list.push(v);
  }
  return List(list);
}

priv fn chop(s: ~str) -> ~str {
  s.slice(0, s.len() - 1)
}

priv fn parse_bulk(sb: net::tcp::TcpSocketBuf) -> Result {
  match int::from_str(chop(sb.read_line())) {
    None => fail,
    Some(-1) => Nil,
    Some(len) if len >= 0 => parse_data(len as uint, sb),
    Some(_) => fail
  }
}

priv fn parse_multi(sb: net::tcp::TcpSocketBuf) -> Result {
  match int::from_str(chop(sb.read_line())) {
    None => fail,
    Some(-1) => Nil,
    Some(0) => List(~[]),
    Some(len) if len >= 0 => parse_list(len as uint, sb),
    Some(_) => fail
  }
}

priv fn parse_int(sb: net::tcp::TcpSocketBuf) -> Result {
  match int::from_str(chop(sb.read_line())) {
    None => fail,
    Some(i) => Int(i)
  }
}

fn parse_response(sb: net::tcp::TcpSocketBuf) -> Result {
  match sb.read_char() {
    '$' => parse_bulk(sb),
    '*' => parse_multi(sb),
    '+' => Status(chop(sb.read_line())),
    '-' => Error(chop(sb.read_line())),
    ':' => parse_int(sb),
    _   => fail
  }
}

fn cmd_to_str(cmd: ~[~str]) -> ~str {
  let mut res = ~"*";
  str::push_str(&mut res, cmd.len().to_str());
  str::push_str(&mut res, "\r\n");
  for cmd.each |s| {
    str::push_str(&mut res, str::concat(~[~"$", s.len().to_str(), ~"\r\n", *s, ~"\r\n"]));
  }
  res
}

fn query(cmd: ~[~str], sb: net::tcp::TcpSocketBuf) -> Result {
  let cmd = cmd_to_str(cmd);
  //io::println(cmd);
  sb.write_str(cmd);
  let res = parse_response(sb);
  io::println(fmt!("%?", res));
  res
}

fn main() {
  let server_ip_addr = net::ip::v4::parse_addr("127.0.0.1");
  let server_port = 6379;
  let iotask = uv::global_loop::get();
  let connect_result = net::tcp::connect(server_ip_addr, server_port, iotask);
  let sock = result::unwrap(connect_result);
  let sb = net::tcp::socket_buf(sock);

/*  for 10_000.times {
    query(~[~"GET", ~"abc"], sb);
  }
*/

  query(~[~"MULTI"], sb);
  query(~[~"GET", ~"def"], sb);
  query(~[~"INCR", ~"def"], sb);
  query(~[~"INCR", ~"def"], sb);
  query(~[~"GET", ~"def"], sb);
  query(~[~"EXEC"], sb);

  query(~[~"SET", ~"abc", ~"XXX"], sb);
  query(~[~"SET", ~"def", ~"123"], sb);
  query(~[~"GET", ~"abc"], sb);
  query(~[~"MGET", ~"abc", ~"def", ~"non"], sb);
}
<|endoftext|>


<commit_before>use std::fmt::Result as FmtResult;
use std::fmt::{Display, Formatter};
use std::fs::File;
use std::io::Error as IOError;
use std::io::{BufRead, BufReader, stdin};

#[derive(Debug)]
enum WCError {
    IO(IOError),
    // There's more in the real program.
}

impl Display for WCError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            WCError::IO(ref e) => write!(f, "{}", e),
            // There's more in the real program.
        }
    }
}

impl From<IOError> for WCError {
    fn from(e: IOError) -> WCError {
        WCError::IO(e)
    }
}

type WCResult<T> = Result<T, WCError>;

fn open_arg(filename: &str) -> WCResult<Box<BufRead>> {
    match filename {
        "-" => Ok(Box::new(BufReader::new(stdin()))),
        _ => Ok(Box::new(BufReader::new(try!(File::open(filename))))),
    }
}

fn main() {
    for arg in &["-", "Cargo.toml", "MISSING"] {
        let file = open_arg(arg);
        match file {
            Ok(mut reader) => {
                let mut lbuf = Vec::new();
                let _ = reader.read_until('\n' as u8, &mut lbuf);
                // I'll do the error checking in the real program
                println!("{}: {:?}", arg, lbuf);
            },
            Err(e) => {
                println!("{}: {:?}", arg, e);
            }
        }
    }
}
<commit_msg>Remove repro<commit_after><|endoftext|>


<commit_before>extern crate firebase;
extern crate url;

use firebase::*;
use url::Url;

use std::sync::{Arc, Mutex};

#[test]
fn builds_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    assert_eq!(f.get_url(), "http://db.rifebass.com/?auth=deadbeaf");
}

#[test]
fn extends_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn double_extends_url() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_slashes() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());

    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/").ok().unwrap();
    let f = f.at("/SpacePilot3000/").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_json_suffix() {
    let f = Firebase::new("http://db.rifebass.com").ok().unwrap();
    let f = f.at("0.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("8.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("7.json").ok().unwrap().at("2.json").ok().unwrap()
             .at("5.json").ok().unwrap().at("3.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//0/1/1/8/9/9/9/8/8/1/9/9/9/1/1/9/7/2/5/3.json";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn test_ops() {
    let f = Firebase::new("http://db.fe/").ok().expect("url err");
    let f = f.at("lol").ok().expect("extend err");
    let req = f.end_at(13).limit_to_first(4).equal_to(8).shallow(false);
    let correct = Url::parse("http://db.fe//lol.json?limitToFirst=4&endAt=13&equalTo=8&shallow=false").ok().unwrap();
    let generated = Url::parse(&req.get_url()).ok().unwrap();

    assert_queries(&correct, &generated);
}

#[test]
fn test_auth_ops() {
    let f = Firebase::authed("db.fe/", "key").ok().expect("url err").at("lol").ok().unwrap();
    let req = f.order_by("pts").limit_to_last(5).start_at(8);

    let correct = Url::parse("https://db.fe/lol.json?auth=key&orderBy=pts&limitToLast=5&startAt=8").ok().unwrap();
    let generated = Url::parse(&req.get_url()).ok().unwrap();

    assert_queries(&correct, &generated);
}

#[test]
fn test_async_get() {
    let fb = Firebase::new("mybd.firebase.com").ok().unwrap();
    let db_ref = fb.at("Profiles/a9sdc8asd99acc/profile_img").ok().unwrap();

    let finished = Arc::new(Mutex::new(false));

    let marker = finished.clone();
    let thread = db_ref.get_async(move |_| {
        let mut finished = marker.lock().unwrap();
        *finished = true;
    });

    assert!(!*finished.lock().unwrap());
    thread.join().ok();
}

#[test]
fn test_ops_ctor() {
    let fb = Firebase::new("db.fb.com").ok().unwrap();
    let query = fb.ops(&FbOps {
        order_by:       Some("Hello World"),
        limit_to_first: Some(5),
        end_at:         Some(7),
        equal_to:       Some(3),
        shallow:        Some(true),
        format:         Some(true),
        .. FbOps::default()
    });

    let corr = Url::parse("https://db.fb.com/?limitToFirst=5&orderBy=Hello+World&equalTo=3&format=export&shallow=true&endAt=7").ok().unwrap();
    let this = Url::parse(&query.get_url()).ok().unwrap();
    assert_queries(&corr, &this);
}

#[test]
fn test_resp_json() {
    let response = Response {
        code: 200,
        body: "{
            \"id\":   \"mongo id\",
            \"data\": \"Hello World!\"
        }".to_string(),
    };

    let record = match response.json().ok().expect("Should've parsed json") {
        Json::Object(o) => o,
        _ => panic!("This shouldv'e been a object!"),
    };

    let data = record.get("data").expect("Should've had a data member");

    match data.clone() {
        Json::String(d) => assert_eq!("Hello World!", d),
        _ => panic!("This shouldv'e been a string!"),
    }
}

fn assert_queries(a: &Url, b: &Url) {
    let param_a = a.query_pairs().expect("Url should have query params.");
    let param_b = b.query_pairs().expect("Url should have query params.");

    assert_eq!(param_b.len(), param_a.len());

    for pair in param_a.iter() {
        assert!(param_b.contains(pair));
    }
}
<commit_msg>Added test to parse response into struct<commit_after>extern crate firebase;
extern crate url;
extern crate rustc_serialize;

use firebase::*;
use url::Url;

use std::sync::{Arc, Mutex};

#[test]
fn builds_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    assert_eq!(f.get_url(), "http://db.rifebass.com/?auth=deadbeaf");
}

#[test]
fn extends_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn double_extends_url() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_slashes() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());

    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/").ok().unwrap();
    let f = f.at("/SpacePilot3000/").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_json_suffix() {
    let f = Firebase::new("http://db.rifebass.com").ok().unwrap();
    let f = f.at("0.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("8.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("7.json").ok().unwrap().at("2.json").ok().unwrap()
             .at("5.json").ok().unwrap().at("3.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//0/1/1/8/9/9/9/8/8/1/9/9/9/1/1/9/7/2/5/3.json";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn test_ops() {
    let f = Firebase::new("http://db.fe/").ok().expect("url err");
    let f = f.at("lol").ok().expect("extend err");
    let req = f.end_at(13).limit_to_first(4).equal_to(8).shallow(false);
    let correct = Url::parse("http://db.fe//lol.json?limitToFirst=4&endAt=13&equalTo=8&shallow=false").ok().unwrap();
    let generated = Url::parse(&req.get_url()).ok().unwrap();

    assert_queries(&correct, &generated);
}

#[test]
fn test_auth_ops() {
    let f = Firebase::authed("db.fe/", "key").ok().expect("url err").at("lol").ok().unwrap();
    let req = f.order_by("pts").limit_to_last(5).start_at(8);

    let correct = Url::parse("https://db.fe/lol.json?auth=key&orderBy=pts&limitToLast=5&startAt=8").ok().unwrap();
    let generated = Url::parse(&req.get_url()).ok().unwrap();

    assert_queries(&correct, &generated);
}

#[test]
fn test_async_get() {
    let fb = Firebase::new("mybd.firebase.com").ok().unwrap();
    let db_ref = fb.at("Profiles/a9sdc8asd99acc/profile_img").ok().unwrap();

    let finished = Arc::new(Mutex::new(false));

    let marker = finished.clone();
    let thread = db_ref.get_async(move |_| {
        let mut finished = marker.lock().unwrap();
        *finished = true;
    });

    assert!(!*finished.lock().unwrap());
    thread.join().ok();
}

#[test]
fn test_ops_ctor() {
    let fb = Firebase::new("db.fb.com").ok().unwrap();
    let query = fb.ops(&FbOps {
        order_by:       Some("Hello World"),
        limit_to_first: Some(5),
        end_at:         Some(7),
        equal_to:       Some(3),
        shallow:        Some(true),
        format:         Some(true),
        .. FbOps::default()
    });

    let corr = Url::parse("https://db.fb.com/?limitToFirst=5&orderBy=Hello+World&equalTo=3&format=export&shallow=true&endAt=7").ok().unwrap();
    let this = Url::parse(&query.get_url()).ok().unwrap();
    assert_queries(&corr, &this);
}

#[test]
fn test_resp_json() {
    let response = Response {
        code: 200,
        body: "{
            \"id\":   \"mongo id\",
            \"data\": \"Hello World!\"
        }".to_string(),
    };

    let record = match response.json().ok().expect("Should've parsed json") {
        Json::Object(o) => o,
        _ => panic!("This shouldv'e been a object!"),
    };

    let data = record.get("data").expect("Should've had a data member");

    match data.clone() {
        Json::String(d) => assert_eq!("Hello World!", d),
        _ => panic!("This shouldv'e been a string!"),
    }
}

#[test]
fn test_resp_struct_easy() {
    let response = Response {
        code: 200,
        body: "{
            \"fizz\": 3,
            \"buzz\": 5
        }".to_string(),
    };

    let bee: FizzBuzz = response.parse().ok().expect("Should parse into FizzBuzz struct");

    assert_eq!(bee.fizz, 3);
    assert_eq!(bee.buzz, 5);
}

fn assert_queries(a: &Url, b: &Url) {
    let param_a = a.query_pairs().expect("Url should have query params.");
    let param_b = b.query_pairs().expect("Url should have query params.");

    assert_eq!(param_b.len(), param_a.len());

    for pair in param_a.iter() {
        assert!(param_b.contains(pair));
    }
}

#[derive(RustcDecodable)]
struct FizzBuzz {
    fizz: u32,
    buzz: u32,
}
<|endoftext|>


<commit_before>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    DataSource::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    dbc.connect("DoesntExist", "", "").unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = DataSource::with_parent(&env).unwrap();
    let dbc = dbc.connect("DoesntExist", "", "");
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            ReturnOption::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "");
    match dbc {
        Success(c) => assert_no_diagnostic(&c.disconnect()),
        Info(c) => assert_no_diagnostic(&c),
        Error(c) => assert_no_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "").unwrap();
    {
        let stmt = Statement::with_parent(&dbc).unwrap();
        let stmt = match stmt.exec_direct("SELECT title FROM Movies WHERE year=1968;") {
            ReturnOption::Success(s) | ReturnOption::Info(s) => {
                assert_no_diagnostic(&s);
                s
            }
            ReturnOption::NoData(_) => panic!("No Data"),
            ReturnOption::Error(s) => panic!("{}", get_last_error(&s)),
        };
        assert_eq!(1, stmt.num_result_cols().unwrap());
        let mut stmt = match stmt.fetch() {
            ReturnOption::Success(s) => s,
            ReturnOption::Info(s) => s,
            ReturnOption::Error(s) => panic!("Error during fetching row: {}", get_last_error(&s)),
            ReturnOption::NoData(_) => panic!("Empty result set returned from SELECT"),
        };
        let mut buffer = [0u8; 256];
        if let ReturnOption::Success(Indicator::Length(i)) =
            stmt.get_data(1, &mut buffer as &mut [u8])
        {
            assert_eq!("2001: A Space Odyssey".as_bytes(), &buffer[..(i as usize)]);
        } else {
            panic!("No field found!");
        }
    }
    dbc.disconnect().unwrap();
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn auto_disconnect() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    dbc.connect("PostgreSQL", "postgres", "").unwrap();
    // No panic on Drop, because of automatic disconnect
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn assert_no_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        ReturnOption::Success(dr) | ReturnOption::Info(dr) => panic!(
            "{}",
            str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
        ),
        ReturnOption::Error(()) => panic!("Error during fetching diagnostic record"),
        ReturnOption::NoData(()) => (),
    }
}

fn get_last_error(diag: &Diagnostics) -> String {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        ReturnOption::Success(dr) | ReturnOption::Info(dr) => str::from_utf8(
            &buffer[0..(dr.text_length as usize)],
        ).unwrap()
            .to_owned(),
        ReturnOption::Error(()) => panic!("Error during fetching diagnostic record"),
        ReturnOption::NoData(()) => panic!("No diagnostic available"),
    }
}
<commit_msg>added test, for passing to empty buffers into drivers<commit_after>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    DataSource::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    dbc.connect("DoesntExist", "", "").unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = DataSource::with_parent(&env).unwrap();
    let dbc = dbc.connect("DoesntExist", "", "");
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            ReturnOption::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[test]
fn drivers_with_empty_buffer() {
    use odbc_sys::SQL_FETCH_NEXT;
    let env = Environment::new().unwrap();
    let mut env: Environment<Odbc3> = env.declare_version().unwrap();
    let mut description = [0; 0];
    let mut attributes = [0; 0];
    match env.drivers(SQL_FETCH_NEXT, &mut description, &mut attributes) {
        ReturnOption::Error(()) => panic!("SQLDrivers call returned error"),
        _ => (),
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "");
    match dbc {
        Success(c) => assert_no_diagnostic(&c.disconnect()),
        Info(c) => assert_no_diagnostic(&c),
        Error(c) => assert_no_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    let dbc = dbc.connect("PostgreSQL", "postgres", "").unwrap();
    {
        let stmt = Statement::with_parent(&dbc).unwrap();
        let stmt = match stmt.exec_direct("SELECT title FROM Movies WHERE year=1968;") {
            ReturnOption::Success(s) | ReturnOption::Info(s) => {
                assert_no_diagnostic(&s);
                s
            }
            ReturnOption::NoData(_) => panic!("No Data"),
            ReturnOption::Error(s) => panic!("{}", get_last_error(&s)),
        };
        assert_eq!(1, stmt.num_result_cols().unwrap());
        let mut stmt = match stmt.fetch() {
            ReturnOption::Success(s) => s,
            ReturnOption::Info(s) => s,
            ReturnOption::Error(s) => panic!("Error during fetching row: {}", get_last_error(&s)),
            ReturnOption::NoData(_) => panic!("Empty result set returned from SELECT"),
        };
        let mut buffer = [0u8; 256];
        if let ReturnOption::Success(Indicator::Length(i)) =
            stmt.get_data(1, &mut buffer as &mut [u8])
        {
            assert_eq!("2001: A Space Odyssey".as_bytes(), &buffer[..(i as usize)]);
        } else {
            panic!("No field found!");
        }
    }
    dbc.disconnect().unwrap();
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn auto_disconnect() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = DataSource::with_parent(&env).unwrap();
    dbc.connect("PostgreSQL", "postgres", "").unwrap();
    // No panic on Drop, because of automatic disconnect
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn assert_no_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        ReturnOption::Success(dr) | ReturnOption::Info(dr) => panic!(
            "{}",
            str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
        ),
        ReturnOption::Error(()) => panic!("Error during fetching diagnostic record"),
        ReturnOption::NoData(()) => (),
    }
}

fn get_last_error(diag: &Diagnostics) -> String {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        ReturnOption::Success(dr) | ReturnOption::Info(dr) => str::from_utf8(
            &buffer[0..(dr.text_length as usize)],
        ).unwrap()
            .to_owned(),
        ReturnOption::Error(()) => panic!("Error during fetching diagnostic record"),
        ReturnOption::NoData(()) => panic!("No diagnostic available"),
    }
}
<|endoftext|>


<commit_before>extern crate sorting;

const TO_SORT_I8:  [i8;  16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_I16: [i16; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_I32: [i32; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_I64: [i64; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U8:  [u8;  16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U16: [u16; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U32: [u32; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U64: [u64; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const SORTED_IND_INT:  [usize; 16] = [3, 4, 15, 2, 8, 13, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];

const TO_SORT_F32: [f32; 16] = [6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                                3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];
const TO_SORT_F64: [f64; 16] = [6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                                3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];
const SORTED_IND_FLOAT: [usize; 16] = [3, 15, 4, 2, 13, 8, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];

/// Verify order of input vector as sorted by indices.
///
/// # Details
///
/// This function takes as arguments a vector of data and a vector representing the indices of the
/// first vector making it sorted.
///
/// The elements of the sorted vector are compared to the next ones to make sure they are less
/// or equal.
///
/// # Panics
///
/// The sorting of the data vector is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// let sorted_indices: Vec<usize> = vec![3, 1, 2, 0];
/// verify_sorting(&data, &sorted_indices);
/// ```
///
fn verify_sorting<T: PartialOrd>(array: &Vec<T>, sorted_indices: &Vec<usize>) {
    let n = array.len();
    assert_eq!(n , sorted_indices.len());

    if !array.is_empty() {
        for i in 0..n-1 {
            assert!(array[sorted_indices[i]] <= array[sorted_indices[i+1]]);
        }
    }
}

/// Call the specified sorting function on an empty vector of specific type.
///
/// # Details
///
/// This function takes as arguments a pointer to a sorting function acting and call
/// it on an empty vector of type T. The call should succeed and the index vector should
/// be empty as well.
///
/// # Panics
///
/// The emptiness of the sorted list is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
/// ```
///
fn test_empty_vec<T: PartialOrd>(sorting_fct: fn(&Vec<T>) -> Vec<usize>) {
    let to_sort: Vec<T> = vec![];
    let sorted_indices = sorting_fct(&to_sort);
    assert_eq!(sorted_indices, vec![]);
    assert!(sorted_indices.is_empty());
}

/// Call the specified sorting function on an specific vector of floats and validate the output.
///
/// # Details
///
/// This function takes as arguments:
///    1. An immutable vector of floats, to be sorted;
///    2. An immutable vector of indices as the reference to compare with;
///    3. A function pointer to be called on the first vector.
///
/// # Panics
///
/// This calls the function `verify_sorting()` which will assert if the result is not in order.
/// It also compares the resulting indices with expected values using asserts.
///
/// # Examples
///
/// ```
/// let to_sort: Vec<f32> = vec![6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
///                              3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];
///
/// let known_sorted_indices = vec![3, 15, 4, 2, 13, 8, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];
///
/// test_sort_vec_float::<f32>(&to_sort, &known_sorted_indices,
///                            sorting::simplesorts::insertion::sort);
/// ```
///
fn test_sort_vec_float<T: PartialOrd>(to_sort: &Vec<T>, expected_indices: &Vec<usize>,
                                      sorting_fct: fn(&Vec<T>) -> Vec<usize>) {
    let sorted_indices = sorting_fct(&to_sort);

    verify_sorting(&to_sort, &sorted_indices);

    assert_eq!(sorted_indices.len(), expected_indices.len());

    for i in 0..to_sort.len() {
        assert_eq!(sorted_indices[i], expected_indices[i]);
    }
}

/// Validate against empty vector (i8).
#[test]
fn simple_insertion_empty_vec_i8() {
    test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i16() {
    test_empty_vec::<i16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i32() {
    test_empty_vec::<i32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i64).
#[test]
fn simple_insertion_empty_vec_i64() {
    test_empty_vec::<i64>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (u8).
#[test]
fn simple_insertion_empty_vec_u8() {
    test_empty_vec::<u8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u16() {
    test_empty_vec::<u16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u32() {
    test_empty_vec::<u32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u64).
#[test]
fn simple_insertion_empty_vec_u64() {
    test_empty_vec::<u64>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (isize).
#[test]
fn simple_insertion_empty_vec_isize() {
    test_empty_vec::<isize>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (usize).
#[test]
fn simple_insertion_empty_vec_usize() {
    test_empty_vec::<usize>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (f32).
#[test]
fn simple_insertion_empty_vec_f32() {
    test_empty_vec::<f32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (f64).
#[test]
fn simple_insertion_empty_vec_f64() {
    test_empty_vec::<f64>(sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of single precision values (i8).
#[test]
fn simple_insertion_vec_i8() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I8[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i8>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (i16).
#[test]
fn simple_insertion_vec_i16() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I16[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i16>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (i32).
#[test]
fn simple_insertion_vec_i32() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I32[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i32>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (i64).
#[test]
fn simple_insertion_vec_i64() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I64[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i64>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of single precision values (u8).
#[test]
fn simple_insertion_vec_u8() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U8[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u8>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (u16).
#[test]
fn simple_insertion_vec_u16() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U16[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u16>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (u32).
#[test]
fn simple_insertion_vec_u32() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U32[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u32>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (u64).
#[test]
fn simple_insertion_vec_u64() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U64[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u64>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of single precision values (f32).
#[test]
fn simple_insertion_vec_f32() {
    let to_sort: Vec<_> = From::from(&TO_SORT_F32[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_FLOAT[..]);

    test_sort_vec_float::<f32>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of double precision values (f64).
#[test]
fn simple_insertion_vec_f64() {
    let to_sort: Vec<_> = From::from(&TO_SORT_F64[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_FLOAT[..]);

    test_sort_vec_float::<f64>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
<commit_msg>Comment<commit_after>extern crate sorting;

const TO_SORT_I8:  [i8;  16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_I16: [i16; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_I32: [i32; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_I64: [i64; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U8:  [u8;  16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U16: [u16; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U32: [u32; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const TO_SORT_U64: [u64; 16] = [6,  5,  3,  1,  2, 4, 10, 7, 3, 32, 44, 56, 67, 3, 44, 2];
const SORTED_IND_INT:  [usize; 16] = [3, 4, 15, 2, 8, 13, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];

const TO_SORT_F32: [f32; 16] = [6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                                3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];
const TO_SORT_F64: [f64; 16] = [6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                                3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];
// NOTE: The order is different for the floats because of the fractional parts. For example,
//       "2.0" comes before "2.4", while in the integer arrays it was "2" vs "2". Since the
//       algorithms are stable, the floating points vector will get a different sorting sequence.
const SORTED_IND_FLOAT: [usize; 16] = [3, 15, 4, 2, 13, 8, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];

/// Verify order of input vector as sorted by indices.
///
/// # Details
///
/// This function takes as arguments a vector of data and a vector representing the indices of the
/// first vector making it sorted.
///
/// The elements of the sorted vector are compared to the next ones to make sure they are less
/// or equal.
///
/// # Panics
///
/// The sorting of the data vector is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// let sorted_indices: Vec<usize> = vec![3, 1, 2, 0];
/// verify_sorting(&data, &sorted_indices);
/// ```
///
fn verify_sorting<T: PartialOrd>(array: &Vec<T>, sorted_indices: &Vec<usize>) {
    let n = array.len();
    assert_eq!(n , sorted_indices.len());

    if !array.is_empty() {
        for i in 0..n-1 {
            assert!(array[sorted_indices[i]] <= array[sorted_indices[i+1]]);
        }
    }
}

/// Call the specified sorting function on an empty vector of specific type.
///
/// # Details
///
/// This function takes as arguments a pointer to a sorting function acting and call
/// it on an empty vector of type T. The call should succeed and the index vector should
/// be empty as well.
///
/// # Panics
///
/// The emptiness of the sorted list is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
/// ```
///
fn test_empty_vec<T: PartialOrd>(sorting_fct: fn(&Vec<T>) -> Vec<usize>) {
    let to_sort: Vec<T> = vec![];
    let sorted_indices = sorting_fct(&to_sort);
    assert_eq!(sorted_indices, vec![]);
    assert!(sorted_indices.is_empty());
}

/// Call the specified sorting function on an specific vector of floats and validate the output.
///
/// # Details
///
/// This function takes as arguments:
///    1. An immutable vector of floats, to be sorted;
///    2. An immutable vector of indices as the reference to compare with;
///    3. A function pointer to be called on the first vector.
///
/// # Panics
///
/// This calls the function `verify_sorting()` which will assert if the result is not in order.
/// It also compares the resulting indices with expected values using asserts.
///
/// # Examples
///
/// ```
/// let to_sort: Vec<f32> = vec![6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
///                              3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];
///
/// let known_sorted_indices = vec![3, 15, 4, 2, 13, 8, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];
///
/// test_sort_vec_float::<f32>(&to_sort, &known_sorted_indices,
///                            sorting::simplesorts::insertion::sort);
/// ```
///
fn test_sort_vec_float<T: PartialOrd>(to_sort: &Vec<T>, expected_indices: &Vec<usize>,
                                      sorting_fct: fn(&Vec<T>) -> Vec<usize>) {
    let sorted_indices = sorting_fct(&to_sort);

    verify_sorting(&to_sort, &sorted_indices);

    assert_eq!(sorted_indices.len(), expected_indices.len());

    for i in 0..to_sort.len() {
        assert_eq!(sorted_indices[i], expected_indices[i]);
    }
}

/// Validate against empty vector (i8).
#[test]
fn simple_insertion_empty_vec_i8() {
    test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i16() {
    test_empty_vec::<i16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i32() {
    test_empty_vec::<i32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i64).
#[test]
fn simple_insertion_empty_vec_i64() {
    test_empty_vec::<i64>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (u8).
#[test]
fn simple_insertion_empty_vec_u8() {
    test_empty_vec::<u8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u16() {
    test_empty_vec::<u16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u32() {
    test_empty_vec::<u32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u64).
#[test]
fn simple_insertion_empty_vec_u64() {
    test_empty_vec::<u64>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (isize).
#[test]
fn simple_insertion_empty_vec_isize() {
    test_empty_vec::<isize>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (usize).
#[test]
fn simple_insertion_empty_vec_usize() {
    test_empty_vec::<usize>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (f32).
#[test]
fn simple_insertion_empty_vec_f32() {
    test_empty_vec::<f32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (f64).
#[test]
fn simple_insertion_empty_vec_f64() {
    test_empty_vec::<f64>(sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of single precision values (i8).
#[test]
fn simple_insertion_vec_i8() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I8[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i8>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (i16).
#[test]
fn simple_insertion_vec_i16() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I16[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i16>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (i32).
#[test]
fn simple_insertion_vec_i32() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I32[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i32>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (i64).
#[test]
fn simple_insertion_vec_i64() {
    let to_sort: Vec<_> = From::from(&TO_SORT_I64[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<i64>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of single precision values (u8).
#[test]
fn simple_insertion_vec_u8() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U8[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u8>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (u16).
#[test]
fn simple_insertion_vec_u16() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U16[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u16>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (u32).
#[test]
fn simple_insertion_vec_u32() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U32[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u32>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
/// Validate sorting a vector of single precision values (u64).
#[test]
fn simple_insertion_vec_u64() {
    let to_sort: Vec<_> = From::from(&TO_SORT_U64[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_INT[..]);

    test_sort_vec_float::<u64>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of single precision values (f32).
#[test]
fn simple_insertion_vec_f32() {
    let to_sort: Vec<_> = From::from(&TO_SORT_F32[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_FLOAT[..]);

    test_sort_vec_float::<f32>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of double precision values (f64).
#[test]
fn simple_insertion_vec_f64() {
    let to_sort: Vec<_> = From::from(&TO_SORT_F64[..]);
    let known_sorted_indices: Vec<usize> = From::from(&SORTED_IND_FLOAT[..]);

    test_sort_vec_float::<f64>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
<|endoftext|>


<commit_before>use std::collections::hashmap::HashMap;
use std::char::is_digit;

#[deriving(PartialEq,Show,Clone)]
pub enum XPathToken {
    And,
    AtSign,
    CurrentNode,
    Divide,
    DollarSign,
    DoubleColon,
    DoubleSlash,
    Equal,
    GreaterThan,
    GreaterThanOrEqual,
    LeftBracket,
    LeftParen,
    LessThan,
    LessThanOrEqual,
    Literal(String),
    MinusSign,
    Multiply,
    NotEqual,
    Number(f64),
    Or,
    ParentNode,
    Pipe,
    PlusSign,
    PrefixedName(String, String),
    Remainder,
    RightBracket,
    RightParen,
    Slash,
    String(String),
}

impl XPathToken {
    fn precedes_node_test(& self) -> bool {
        match *self {
            AtSign |
            DoubleColon => true,
            _ => false,
        }
    }

    fn precedes_expression(& self) -> bool {
        match *self {
            LeftParen |
            LeftBracket => true,
            _ => false,
        }
    }

    fn is_operator(& self) -> bool {
        match *self {
            Slash |
            DoubleSlash |
            PlusSign |
            MinusSign |
            Pipe |
            Equal |
            NotEqual |
            LessThan |
            LessThanOrEqual |
            GreaterThan |
            GreaterThanOrEqual |
            And |
            Or |
            Remainder |
            Divide |
            Multiply => true,
            _ => false,
        }
    }
}

pub struct XPathTokenizer {
    xpath: Vec<char>,
    start: uint,
    prefer_recognition_of_operator_names: bool,
}

pub type TokenResult = Result<XPathToken, & 'static str>;

impl XPathTokenizer {
    pub fn new(xpath: & str) -> XPathTokenizer {
        XPathTokenizer {
            xpath: xpath.chars().collect(),
            start: 0,
            prefer_recognition_of_operator_names: false,
        }
    }

    pub fn has_more_tokens(& self) -> bool {
        self.xpath.len() > self.start
    }

    fn valid_ncname_start_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if c >= 'A' && c <= 'Z' { return true }
        if c == '_' { return true }
        if c >= 'a' && c <= 'z' { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn valid_ncname_follow_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if self.valid_ncname_start_char(offset) { return true }
        if c == '-' { return true }
        if c == '.' { return true }
        if c >= '0' && c <= '9' { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn while_valid_string(& self, offset: uint) -> uint {
        let mut offset = offset;

        if offset < self.xpath.len() && self.valid_ncname_start_char(offset) {
            offset += 1;

            while offset < self.xpath.len() && self.valid_ncname_follow_char(offset) {
                offset += 1;
            }
        }

        return offset;
    }

    fn while_valid_number(& self, offset: uint) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && is_number_char(self.xpath[offset]) {
            offset += 1;
        }

        return offset;
    }

    fn while_not_character(& self, offset: uint, end_char: char) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && self.xpath[offset] != end_char {
            offset += 1;
        }

        return offset;
    }

    fn two_char_tokens(& self) -> HashMap<String, XPathToken> {
        let mut m = HashMap::new();
        m.insert("<=".to_string(), LessThanOrEqual);
        m.insert(">=".to_string(), GreaterThanOrEqual);
        m.insert("!=".to_string(), NotEqual);
        m.insert("::".to_string(), DoubleColon);
        m.insert("//".to_string(), DoubleSlash);
        m.insert("..".to_string(), ParentNode);
        m
    }

    fn single_char_tokens(&self) -> HashMap<char, XPathToken> {
        let mut m = HashMap::new();
        m.insert('/', Slash);
        m.insert('(', LeftParen);
        m.insert(')', RightParen);
        m.insert('[', LeftBracket);
        m.insert(']', RightBracket);
        m.insert('@', AtSign);
        m.insert('$', DollarSign);
        m.insert('+', PlusSign);
        m.insert('-', MinusSign);
        m.insert('|', Pipe);
        m.insert('=', Equal);
        m.insert('<', LessThan);
        m.insert('>', GreaterThan);
        m
    }

    fn named_operators(& self) -> Vec<(& 'static str, XPathToken)> {
        vec!(("and", And),
             ("or",  Or),
             ("mod", Remainder),
             ("div", Divide),
             ("*",   Multiply))
    }

    fn tokenize_literal(& mut self, quote_char: char) -> Result<XPathToken, & 'static str> {
        let mut offset = self.start;

        offset += 1; // Skip over the starting quote
        let start_of_string = offset;

        offset = self.while_not_character(offset, quote_char);
        let end_of_string = offset;

        if offset >= self.xpath.len() || self.xpath[offset] != quote_char {
            return Err("found mismatched quote characters");
        }
        offset += 1; // Skip over ending quote

        self.start = offset;
        let value = self.xpath.slice(start_of_string, end_of_string);
        return Ok(Literal(String::from_chars(value)));
    }

    fn substr(& self, start: uint, end: uint) -> String {
        String::from_chars(self.xpath.slice(start, end))
    }

    fn raw_next_token(& mut self) -> Result<XPathToken, & 'static str> {
        if self.xpath.len() >= self.start + 2 {
            let first_two = self.substr(self.start, self.start + 2);
            match self.two_char_tokens().find(&first_two) {
                Some(token) => {
                    self.start += 2;
                    return Ok(token.clone());
                }
                _ => {}
            }
        }

        let c = self.xpath[self.start];
        match self.single_char_tokens().find(&c) {
            Some(token) => {
                self.start += 1;
                return Ok(token.clone());
            }
            _ => {}
        }

        for quote_char in QUOTE_CHARS.iter() {
            if *quote_char == c {
                return self.tokenize_literal(*quote_char);
            }
        }

        if '.' == c {
            let has_more_chars = self.xpath.len() > self.start + 1;

            if ! has_more_chars ||
                has_more_chars && ! is_digit(self.xpath[self.start + 1]) {
                    // Ugly. Should we use START / FOLLOW constructs?
                    self.start += 1;
                    return Ok(CurrentNode);
                }
        }

        if is_number_char(c) {
            let mut offset = self.start;
            let current_start = self.start;

            offset = self.while_valid_number(offset);

            self.start = offset;
            let substr = self.substr(current_start, offset);
            match from_str(substr.as_slice()) {
                Some(value) => Ok(Number(value)),
                None => fail!("Not really a number!")
            }
        } else {
            let mut offset = self.start;
            let current_start = self.start;

            if self.prefer_recognition_of_operator_names {
                for &(ref name, ref token) in self.named_operators().iter() {
                    let name_chars: Vec<char> = name.chars().collect();
                    let name_chars_slice = name_chars.as_slice();

                    if self.xpath.len() >= offset + name_chars.len() {
                        let xpath_chars = self.xpath.slice(offset, offset + name_chars.len());

                        if name_chars_slice == xpath_chars {
                            self.start += name_chars.len();
                            return Ok(token.clone());
                        }
                    }
                }
            }

            if self.xpath[offset] == '*' {
                self.start = offset + 1;
                return Ok(String("*".to_string()));
            }

            offset = self.while_valid_string(offset);

            println!("{}, {}", self.xpath.len(), offset);

            let has_one_more = self.xpath.len() >= offset + 1;
            let has_two_more = self.xpath.len() >= offset + 2;

            println!("{}, {}", has_one_more, has_two_more);

            if (has_one_more && self.xpath[offset] == ':') &&
                (! has_two_more ||
                 (has_two_more && {println!("inner"); true} && self.xpath[offset + 1] != ':')) {
                    let prefix = self.substr(current_start, offset);

                    offset += 1;

                    let current_start = offset;
                    offset = self.while_valid_string(offset);

                    if current_start == offset {
                        return Err("The XPath is missing a local name");
                    }

                    let name = self.substr(current_start, offset);

                    self.start = offset;
                    return Ok(PrefixedName(prefix, name));

            } else {
                self.start = offset;
                return Ok(String(String::from_chars(self.xpath.slice(current_start, offset))));
            }
        }
    }

    fn consume_whitespace(& mut self) {
        while self.start < self.xpath.len() {
            let c = self.xpath[self.start];

            if ! is_xml_space(c) {
                break;
            }

            self.start += 1;
        }
    }

    fn next_token(& mut self) -> TokenResult {
        self.consume_whitespace();

        let old_start = self.start;
        let token = self.raw_next_token();
        if token.is_err() { return token; }

        let token = token.unwrap();

        if old_start == self.start {
            return Err("Unable to create a token");
        }

        self.consume_whitespace();

        if ! (token.precedes_node_test() ||
              token.precedes_expression() ||
              token.is_operator()) {
            // See http://www.w3.org/TR/xpath/#exprlex
            self.prefer_recognition_of_operator_names = true;
        } else {
            self.prefer_recognition_of_operator_names = false;
        }

        return Ok(token);
    }
}

impl Iterator<TokenResult> for XPathTokenizer {
    fn next(&mut self) -> Option<TokenResult> {
        if self.has_more_tokens() {
            let x = Some(self.next_token());
            println!("return {}", x);
            x

        } else {
            None
        }
    }
}

fn is_xml_space(c: char) -> bool {
    return
        c == ' '  ||
        c == '\t' ||
        c == '\n' ||
        c == '\r';
}

fn is_number_char(c: char) -> bool {
    return is_digit(c) || '.' == c;
}

// broken nesting double in single
// open paren / suqre brace causes indent
static QUOTE_CHARS: [char, .. 2] =  ['\'', '"'];
<commit_msg>methods for xpath fns<commit_after>use std::collections::hashmap::HashMap;
use std::char::is_digit;

#[deriving(PartialEq,Show,Clone)]
pub enum XPathToken {
    And,
    AtSign,
    CurrentNode,
    Divide,
    DollarSign,
    DoubleColon,
    DoubleSlash,
    Equal,
    GreaterThan,
    GreaterThanOrEqual,
    LeftBracket,
    LeftParen,
    LessThan,
    LessThanOrEqual,
    Literal(String),
    MinusSign,
    Multiply,
    NotEqual,
    Number(f64),
    Or,
    ParentNode,
    Pipe,
    PlusSign,
    PrefixedName(String, String),
    Remainder,
    RightBracket,
    RightParen,
    Slash,
    String(String),
}

impl XPathToken {
    fn precedes_node_test(& self) -> bool {
        match *self {
            AtSign |
            DoubleColon => true,
            _ => false,
        }
    }

    fn precedes_expression(& self) -> bool {
        match *self {
            LeftParen |
            LeftBracket => true,
            _ => false,
        }
    }

    fn is_operator(& self) -> bool {
        match *self {
            Slash |
            DoubleSlash |
            PlusSign |
            MinusSign |
            Pipe |
            Equal |
            NotEqual |
            LessThan |
            LessThanOrEqual |
            GreaterThan |
            GreaterThanOrEqual |
            And |
            Or |
            Remainder |
            Divide |
            Multiply => true,
            _ => false,
        }
    }
}

pub struct XPathTokenizer {
    xpath: Vec<char>,
    start: uint,
    prefer_recognition_of_operator_names: bool,
}

pub type TokenResult = Result<XPathToken, & 'static str>;

impl XPathTokenizer {
    pub fn new(xpath: & str) -> XPathTokenizer {
        XPathTokenizer {
            xpath: xpath.chars().collect(),
            start: 0,
            prefer_recognition_of_operator_names: false,
        }
    }

    pub fn has_more_tokens(& self) -> bool {
        self.xpath.len() > self.start
    }

    fn valid_ncname_start_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if c >= 'A' && c <= 'Z' { return true }
        if c == '_' { return true }
        if c >= 'a' && c <= 'z' { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn valid_ncname_follow_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if self.valid_ncname_start_char(offset) { return true }
        if c == '-' { return true }
        if c == '.' { return true }
        if c >= '0' && c <= '9' { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn while_valid_string(& self, offset: uint) -> uint {
        let mut offset = offset;

        if offset < self.xpath.len() && self.valid_ncname_start_char(offset) {
            offset += 1;

            while offset < self.xpath.len() && self.valid_ncname_follow_char(offset) {
                offset += 1;
            }
        }

        return offset;
    }

    fn while_valid_number(& self, offset: uint) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && is_number_char(self.xpath[offset]) {
            offset += 1;
        }

        return offset;
    }

    fn while_not_character(& self, offset: uint, end_char: char) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && self.xpath[offset] != end_char {
            offset += 1;
        }

        return offset;
    }

    fn two_char_tokens(& self) -> HashMap<String, XPathToken> {
        let mut m = HashMap::new();
        m.insert("<=".to_string(), LessThanOrEqual);
        m.insert(">=".to_string(), GreaterThanOrEqual);
        m.insert("!=".to_string(), NotEqual);
        m.insert("::".to_string(), DoubleColon);
        m.insert("//".to_string(), DoubleSlash);
        m.insert("..".to_string(), ParentNode);
        m
    }

    fn single_char_tokens(&self) -> HashMap<char, XPathToken> {
        let mut m = HashMap::new();
        m.insert('/', Slash);
        m.insert('(', LeftParen);
        m.insert(')', RightParen);
        m.insert('[', LeftBracket);
        m.insert(']', RightBracket);
        m.insert('@', AtSign);
        m.insert('$', DollarSign);
        m.insert('+', PlusSign);
        m.insert('-', MinusSign);
        m.insert('|', Pipe);
        m.insert('=', Equal);
        m.insert('<', LessThan);
        m.insert('>', GreaterThan);
        m
    }

    fn named_operators(& self) -> Vec<(& 'static str, XPathToken)> {
        vec!(("and", And),
             ("or",  Or),
             ("mod", Remainder),
             ("div", Divide),
             ("*",   Multiply))
    }

    fn tokenize_literal(& mut self, quote_char: char) -> Result<XPathToken, & 'static str> {
        let mut offset = self.start;

        offset += 1; // Skip over the starting quote
        let start_of_string = offset;

        offset = self.while_not_character(offset, quote_char);
        let end_of_string = offset;

        if self.char_at_is_not(offset, quote_char) {
            return Err("found mismatched quote characters");
        }
        offset += 1; // Skip over ending quote

        self.start = offset;
        return Ok(Literal(self.substr(start_of_string, end_of_string)));
    }

    fn substr(& self, start: uint, end: uint) -> String {
        String::from_chars(self.xpath.slice(start, end))
    }

    fn first_two(& self) -> Option<String> {
        if self.xpath.len() >= self.start + 2 {
            Some(self.substr(self.start, self.start + 2))
        } else {
            None
        }
    }

    fn first(& self) -> char {
        self.xpath[self.start]
    }

    fn next_char_is_digit(& self) -> bool {
        let has_more_chars = self.xpath.len() > self.start + 1;

        ! has_more_chars ||
            has_more_chars && ! is_digit(self.xpath[self.start + 1])
    }

    fn str_at_is(& self, offset: uint, needle: &[char]) -> bool {
        let s_len = needle.len();

        if self.xpath.len() < offset + s_len { return false; }

        let xpath_chars = self.xpath.slice(offset, offset + s_len);

        needle == xpath_chars
    }

    fn char_at_is(&self, offset: uint, c: char) -> bool {
        let has_one_more = self.xpath.len() >= offset + 1;

        has_one_more && self.xpath[offset] == c
    }

    fn char_at_is_not(&self, offset: uint, c: char) -> bool {
        let has_one_more = self.xpath.len() >= offset + 1;

        ! has_one_more || self.xpath[offset] != c
    }

    fn raw_next_token(& mut self) -> Result<XPathToken, & 'static str> {
        match self.first_two() {
            Some(first_two) => {
                match self.two_char_tokens().find(&first_two) {
                    Some(token) => {
                        self.start += 2;
                        return Ok(token.clone());
                    }
                    _ => {}
                }
            },
            _ => {}
        }

        let c = self.first();
        match self.single_char_tokens().find(&c) {
            Some(token) => {
                self.start += 1;
                return Ok(token.clone());
            }
            _ => {}
        }

        for quote_char in QUOTE_CHARS.iter() {
            if *quote_char == c {
                return self.tokenize_literal(*quote_char);
            }
        }

        if '.' == c {
            if self.next_char_is_digit() {
                // Ugly. Should we use START / FOLLOW constructs?
                self.start += 1;
                return Ok(CurrentNode);
            }
        }

        if is_number_char(c) {
            let mut offset = self.start;
            let current_start = self.start;

            offset = self.while_valid_number(offset);

            self.start = offset;
            let substr = self.substr(current_start, offset);
            match from_str(substr.as_slice()) {
                Some(value) => Ok(Number(value)),
                None => fail!("Not really a number!")
            }
        } else {
            let mut offset = self.start;
            let current_start = self.start;

            if self.prefer_recognition_of_operator_names {
                for &(ref name, ref token) in self.named_operators().iter() {
                    let name_chars: Vec<char> = name.chars().collect();
                    let name_chars_slice = name_chars.as_slice();

                    if self.str_at_is(offset, name_chars_slice) {
                        self.start += name_chars.len();
                        return Ok(token.clone());
                    }
                }
            }

            if self.char_at_is(offset, '*') {
                self.start = offset + 1;
                return Ok(String("*".to_string()));
            }

            offset = self.while_valid_string(offset);

            if self.char_at_is(offset, ':') && self.char_at_is_not(offset + 1, ':') {
                let prefix = self.substr(current_start, offset);

                offset += 1;

                let current_start = offset;
                offset = self.while_valid_string(offset);

                if current_start == offset {
                    return Err("The XPath is missing a local name");
                }

                let name = self.substr(current_start, offset);

                self.start = offset;
                return Ok(PrefixedName(prefix, name));

            } else {
                self.start = offset;
                return Ok(String(self.substr(current_start, offset)));
            }
        }
    }

    fn consume_whitespace(& mut self) {
        while self.start < self.xpath.len() {
            let c = self.xpath[self.start];

            if ! is_xml_space(c) {
                break;
            }

            self.start += 1;
        }
    }

    fn next_token(& mut self) -> TokenResult {
        self.consume_whitespace();

        let old_start = self.start;
        let token = self.raw_next_token();
        if token.is_err() { return token; }

        let token = token.unwrap();

        if old_start == self.start {
            return Err("Unable to create a token");
        }

        self.consume_whitespace();

        if ! (token.precedes_node_test() ||
              token.precedes_expression() ||
              token.is_operator()) {
            // See http://www.w3.org/TR/xpath/#exprlex
            self.prefer_recognition_of_operator_names = true;
        } else {
            self.prefer_recognition_of_operator_names = false;
        }

        return Ok(token);
    }
}

impl Iterator<TokenResult> for XPathTokenizer {
    fn next(&mut self) -> Option<TokenResult> {
        if self.has_more_tokens() {
            let x = Some(self.next_token());
            println!("return {}", x);
            x

        } else {
            None
        }
    }
}

fn is_xml_space(c: char) -> bool {
    return
        c == ' '  ||
        c == '\t' ||
        c == '\n' ||
        c == '\r';
}

fn is_number_char(c: char) -> bool {
    return is_digit(c) || '.' == c;
}

// broken nesting double in single
// open paren / suqre brace causes indent
static QUOTE_CHARS: [char, .. 2] =  ['\'', '"'];
<|endoftext|>


<commit_before>#[doc(hidden)]
macro_rules! link {
    (
        $(
            extern "C" {
                pub fn $name:ident($($pname:ident: $pty:ty),* $(,)?) $(-> $ret:ty)*;
            }
        )+
    ) => (
        use lazy_static::lazy_static;
        use libloading;
        use std::path::PathBuf;
        use std::sync::Arc;
        use std::sync::RwLock;

        // Wrap the loaded functions.
        pub(crate) struct SharedLibrary {
            library: libloading::Library,
            path: PathBuf,
            pub functions: Functions,
        }
        impl SharedLibrary {
            fn new(library: libloading::Library, path: PathBuf) -> Self {
                Self {
                    library,
                    path,
                    functions: Functions::default(),
                }
            }
        }

        // `LIBRARY` holds the shared library reference.
        lazy_static!{
            static ref LIBRARY: RwLock<Option<Arc<SharedLibrary>>> = RwLock::new(None);
        }

        // Helper function for accessing the thread-local version of the library.
        fn with_library<T, F>(f: F) -> Option<T>
        where
            F: FnOnce(&SharedLibrary) -> T,
        {
            match LIBRARY.read().unwrap().as_ref() {
                Some(library) => Some(f(&library)),
                _ => None,
            }
        }

        // The set of functions loaded dynamically.
        #[derive(Default)]
        pub(crate) struct Functions {
            $(
                pub $name: Option<unsafe extern fn($($pname: $pty), *) $(-> $ret)*>,
            )+
        }

        // Provide functions to load each name from the shared library into the `SharedLibrary`
        // struct.
        mod load {
            $(
                pub(crate) fn $name(library: &mut super::SharedLibrary) {
                    let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
                    library.functions.$name = match symbol {
                        Some(s) => *s,
                        None => None,
                    };
                }
            )+
        }

        /// Load all of the function definitions from a shared library.
        pub fn load() -> Result<(), String> {
            match crate::library::find() {
                None => Err("Unable to find the `libtensorflow` library to load".into()),
                Some(path) => load_from(path),
            }
        }
        fn load_from(path: PathBuf) -> Result<(), String> {
            let library = Arc::new(SharedLibrary::load(path)?);

            let mut static_lib = LIBRARY.write().map_err(|e| {
                format!( "Failed to acquire global lock for TensorFlow library {}",e)
            }).unwrap();

            *static_lib = Some(library);
            Ok(())
        }
        impl SharedLibrary {
            fn load(path: PathBuf) -> Result<SharedLibrary, String> {
                unsafe {
                    let library = libloading::Library::new(&path).map_err(|e| {
                        format!(
                            "the shared library at {} could not be opened: {}",
                            path.display(),
                            e,
                        )
                    });

                    let mut library = SharedLibrary::new(library?, path);
                    $(load::$name(&mut library);)+
                    Ok(library)
                }
            }
        }
        // For each loaded function, we redefine them to proxy their call through the SharedLibrary
        // on the local thread and into the loaded shared library implementation.
        $(
            pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = with_library(|l| {
                    l.functions.$name.expect(concat!(
                        "`libtensorflow` function not loaded: `",
                        stringify!($name)
                    ))
                }).expect("an `libtensorflow` shared library is not loaded on this thread");
                f($($pname), *)
            }
        )+
    )
}
<commit_msg>Swapping unwrap with ? to catch possible error.<commit_after>#[doc(hidden)]
macro_rules! link {
    (
        $(
            extern "C" {
                pub fn $name:ident($($pname:ident: $pty:ty),* $(,)?) $(-> $ret:ty)*;
            }
        )+
    ) => (
        use lazy_static::lazy_static;
        use libloading;
        use std::path::PathBuf;
        use std::sync::Arc;
        use std::sync::RwLock;

        // Wrap the loaded functions.
        pub(crate) struct SharedLibrary {
            library: libloading::Library,
            path: PathBuf,
            pub functions: Functions,
        }
        impl SharedLibrary {
            fn new(library: libloading::Library, path: PathBuf) -> Self {
                Self {
                    library,
                    path,
                    functions: Functions::default(),
                }
            }
        }

        // `LIBRARY` holds the shared library reference.
        lazy_static!{
            static ref LIBRARY: RwLock<Option<Arc<SharedLibrary>>> = RwLock::new(None);
        }

        // Helper function for accessing the thread-local version of the library.
        fn with_library<T, F>(f: F) -> Option<T>
        where
            F: FnOnce(&SharedLibrary) -> T,
        {
            match LIBRARY.read().unwrap().as_ref() {
                Some(library) => Some(f(&library)),
                _ => None,
            }
        }

        // The set of functions loaded dynamically.
        #[derive(Default)]
        pub(crate) struct Functions {
            $(
                pub $name: Option<unsafe extern fn($($pname: $pty), *) $(-> $ret)*>,
            )+
        }

        // Provide functions to load each name from the shared library into the `SharedLibrary`
        // struct.
        mod load {
            $(
                pub(crate) fn $name(library: &mut super::SharedLibrary) {
                    let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
                    library.functions.$name = match symbol {
                        Some(s) => *s,
                        None => None,
                    };
                }
            )+
        }

        /// Load all of the function definitions from a shared library.
        pub fn load() -> Result<(), String> {
            match crate::library::find() {
                None => Err("Unable to find the `libtensorflow` library to load".into()),
                Some(path) => load_from(path),
            }
        }
        fn load_from(path: PathBuf) -> Result<(), String> {
            let library = Arc::new(SharedLibrary::load(path)?);

            let mut static_lib = LIBRARY.write().map_err(|e| {
                format!( "Failed to acquire global lock for TensorFlow library {}",e)
            })?;

            *static_lib = Some(library);
            Ok(())
        }
        impl SharedLibrary {
            fn load(path: PathBuf) -> Result<SharedLibrary, String> {
                unsafe {
                    let library = libloading::Library::new(&path).map_err(|e| {
                        format!(
                            "the shared library at {} could not be opened: {}",
                            path.display(),
                            e,
                        )
                    });

                    let mut library = SharedLibrary::new(library?, path);
                    $(load::$name(&mut library);)+
                    Ok(library)
                }
            }
        }
        // For each loaded function, we redefine them to proxy their call through the SharedLibrary
        // on the local thread and into the loaded shared library implementation.
        $(
            pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = with_library(|l| {
                    l.functions.$name.expect(concat!(
                        "`libtensorflow` function not loaded: `",
                        stringify!($name)
                    ))
                }).expect("an `libtensorflow` shared library is not loaded on this thread");
                f($($pname), *)
            }
        )+
    )
}
<|endoftext|>


<commit_before>//! Tests for internal code checks.
use std::fs;

#[test]
fn check_forbidden_code() {
    // Do not use certain macros, functions, etc.
    if !cargo::util::is_ci() {
        // Only check these on CI, otherwise it could be annoying.
        return;
    }
    let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
    for entry in walkdir::WalkDir::new(path)
        .into_iter()
        .filter_map(|e| e.ok())
    {
        let path = entry.path();
        if !entry
            .file_name()
            .to_str()
            .map(|s| s.ends_with(".rs"))
            .unwrap_or(false)
        {
            continue;
        }
        let c = fs::read_to_string(path).unwrap();
        for (line_index, line) in c.lines().enumerate() {
            if line.trim().starts_with("//") {
                continue;
            }
            if line_has_print(line) {
                if entry.file_name().to_str().unwrap() == "cargo_new.rs" && line.contains("Hello") {
                    // An exception.
                    continue;
                }
                panic!(
                    "found print macro in {}:{}\n\n{}\n\n\
                    print! macros should not be used in Cargo because they can panic.\n\
                    Use one of the drop_print macros instead.\n\
                    ",
                    path.display(),
                    line_index,
                    line
                );
            }
            if line_has_macro(line, "dbg") {
                panic!(
                    "found dbg! macro in {}:{}\n\n{}\n\n\
                    dbg! should not be used outside of debugging.",
                    path.display(),
                    line_index,
                    line
                );
            }
        }
    }
}

fn line_has_print(line: &str) -> bool {
    line_has_macro(line, "print")
        || line_has_macro(line, "eprint")
        || line_has_macro(line, "println")
        || line_has_macro(line, "eprintln")
}

#[test]
fn line_has_print_works() {
    assert!(line_has_print("print!"));
    assert!(line_has_print("println!"));
    assert!(line_has_print("eprint!"));
    assert!(line_has_print("eprintln!"));
    assert!(line_has_print("(print!(\"hi!\"))"));
    assert!(!line_has_print("print"));
    assert!(!line_has_print("i like to print things"));
    assert!(!line_has_print("drop_print!"));
    assert!(!line_has_print("drop_println!"));
    assert!(!line_has_print("drop_eprint!"));
    assert!(!line_has_print("drop_eprintln!"));
}

fn line_has_macro(line: &str, mac: &str) -> bool {
    for (i, _) in line.match_indices(mac) {
        if line.get(i + mac.len()..i + mac.len() + 1) != Some("!") {
            continue;
        }
        if i == 0 {
            return true;
        }
        // Check for identifier boundary start.
        let prev1 = line.get(i - 1..i).unwrap().chars().next().unwrap();
        if prev1.is_alphanumeric() || prev1 == '_' {
            continue;
        }
        return true;
    }
    false
}
<commit_msg>Don't check src/doc directory.<commit_after>//! Tests for internal code checks.
use std::fs;

#[test]
fn check_forbidden_code() {
    // Do not use certain macros, functions, etc.
    if !cargo::util::is_ci() {
        // Only check these on CI, otherwise it could be annoying.
        use std::io::Write;
        writeln!(
            std::io::stderr(),
            "\nSkipping check_forbidden_code test, set CI=1 to enable"
        )
        .unwrap();
        return;
    }
    let root_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
    for entry in walkdir::WalkDir::new(&root_path)
        .into_iter()
        .filter_entry(|e| e.path() != root_path.join("doc"))
        .filter_map(|e| e.ok())
    {
        let path = entry.path();
        if !entry
            .file_name()
            .to_str()
            .map(|s| s.ends_with(".rs"))
            .unwrap_or(false)
        {
            continue;
        }
        eprintln!("checking {}", path.display());
        let c = fs::read_to_string(path).unwrap();
        for (line_index, line) in c.lines().enumerate() {
            if line.trim().starts_with("//") {
                continue;
            }
            if line_has_print(line) {
                if entry.file_name().to_str().unwrap() == "cargo_new.rs" && line.contains("Hello") {
                    // An exception.
                    continue;
                }
                panic!(
                    "found print macro in {}:{}\n\n{}\n\n\
                    print! macros should not be used in Cargo because they can panic.\n\
                    Use one of the drop_print macros instead.\n\
                    ",
                    path.display(),
                    line_index,
                    line
                );
            }
            if line_has_macro(line, "dbg") {
                panic!(
                    "found dbg! macro in {}:{}\n\n{}\n\n\
                    dbg! should not be used outside of debugging.",
                    path.display(),
                    line_index,
                    line
                );
            }
        }
    }
}

fn line_has_print(line: &str) -> bool {
    line_has_macro(line, "print")
        || line_has_macro(line, "eprint")
        || line_has_macro(line, "println")
        || line_has_macro(line, "eprintln")
}

#[test]
fn line_has_print_works() {
    assert!(line_has_print("print!"));
    assert!(line_has_print("println!"));
    assert!(line_has_print("eprint!"));
    assert!(line_has_print("eprintln!"));
    assert!(line_has_print("(print!(\"hi!\"))"));
    assert!(!line_has_print("print"));
    assert!(!line_has_print("i like to print things"));
    assert!(!line_has_print("drop_print!"));
    assert!(!line_has_print("drop_println!"));
    assert!(!line_has_print("drop_eprint!"));
    assert!(!line_has_print("drop_eprintln!"));
}

fn line_has_macro(line: &str, mac: &str) -> bool {
    for (i, _) in line.match_indices(mac) {
        if line.get(i + mac.len()..i + mac.len() + 1) != Some("!") {
            continue;
        }
        if i == 0 {
            return true;
        }
        // Check for identifier boundary start.
        let prev1 = line.get(i - 1..i).unwrap().chars().next().unwrap();
        if prev1.is_alphanumeric() || prev1 == '_' {
            continue;
        }
        return true;
    }
    false
}
<|endoftext|>