<commit_before>extern crate toml;
extern crate reqwest;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate glob;
extern crate nix;

#[macro_use]
extern crate lazy_static;

use std::io::{Write, BufRead};
use std::ffi::CStr;
extern crate libc;

mod structs;
use structs::Config;
mod ghclient;
mod buffer;
use buffer::Buffer;
mod cstructs;
use cstructs::{Passwd, Spwd, Group};
mod runfiles;
mod statics;
use statics::{CLIENT, CONFIG};

#[allow(dead_code)]
enum NssStatus {
    TryAgain,
    Unavail,
    NotFound,
    Success,
}

impl From<NssStatus> for libc::c_int {
    fn from(status: NssStatus) -> libc::c_int {
        match status {
            NssStatus::TryAgain => -2,
            NssStatus::Unavail => -1,
            NssStatus::NotFound => 0,
            NssStatus::Success => 1,
        }
    }
}

fn string_from(cstrptr: *const libc::c_char) -> String {
    let cstr: &CStr = unsafe { CStr::from_ptr(cstrptr) };
    String::from(cstr.to_str().unwrap())
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwnam_r(cnameptr: *const libc::c_char,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (team, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, team.id, &CONFIG) } {
                Ok(_) => libc::c_int::from(NssStatus::Success),
                Err(_) => nix::Errno::ERANGE as libc::c_int,
            }
        }
        None => libc::c_int::from(NssStatus::NotFound),
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwuid_r(uid: libc::uid_t,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (team, members) = CLIENT.get_team_members().unwrap();
    for member in members.values() {
        if uid == member.id as libc::uid_t {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, team.id, &CONFIG) } {
                Ok(_) => return libc::c_int::from(NssStatus::Success),
                Err(_) => return nix::Errno::ERANGE as libc::c_int,
            }
        }
    }
    libc::c_int::from(NssStatus::NotFound)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setpwent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let (team, members) = match CLIENT.get_team_members() {
        Ok((team, members)) => (team, members),
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\t{}\n", member.login, member.id, team.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwent_r(pwbuf: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         pwbufp: *mut *mut Passwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let id = words[1].parse::<u64>().unwrap();
        let gid = words[2].parse::<u64>().unwrap();
        match unsafe { (*pwbuf).pack_args(&mut buffer, words[0], id, gid, &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *pwbufp = pwbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *pwbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endpwent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspnam_r(cnameptr: *const libc::c_char,
                                         spwd: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (_, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*spwd).pack_args(&mut buffer, &member.login, &CONFIG) } {
                Ok(_) => libc::c_int::from(NssStatus::Success),
                Err(_) => nix::Errno::ERANGE as libc::c_int,
            }
        }
        None => libc::c_int::from(NssStatus::NotFound),
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setspent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let members = match CLIENT.get_team_members() {
        Ok((_, members)) => members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\n", member.login, member.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspent_r(spbuf: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         spbufp: *mut *mut Spwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        match unsafe { (*spbuf).pack_args(&mut buffer, words[0], &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *spbufp = spbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *spbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endspent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrgid_r(gid: libc::gid_t,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if gid as u64 == team.id {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, gid as u64, &members) } {
            Ok(_) => libc::c_int::from(NssStatus::Success),
            Err(_) => nix::Errno::ERANGE as libc::c_int,
        }
    } else {
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrnam_r(cnameptr: *const libc::c_char,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if name == team.name {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, team.id, &members) } {
            Ok(_) => libc::c_int::from(NssStatus::Success),
            Err(_) => nix::Errno::ERANGE as libc::c_int,
        }
    } else {
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setgrent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let (team, members) = match CLIENT.get_team_members() {
        Ok(team_members) => team_members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let member_names = members.values().map(|x| x.login.as_str()).collect::<Vec<&str>>().join(" ");
    list_file.write(format!("{}\t{}\t{}\n", team.name, team.id, member_names).as_bytes())
             .unwrap();
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrent_r(grbuf: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         grbufp: *mut *mut Group)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let member_names: Vec<&str> = words[2].split(" ").collect();
        let gid = words[1].parse::<u64>().unwrap();
        match unsafe { (*grbuf).pack_args(&mut buffer, words[0], gid, &member_names) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *grbufp = grbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *grbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endgrent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}
<commit_msg>Improve pointer handling<commit_after>extern crate toml;
extern crate reqwest;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate glob;
extern crate nix;

#[macro_use]
extern crate lazy_static;

use std::io::{Write, BufRead};
use std::ffi::CStr;
extern crate libc;

mod structs;
use structs::Config;
mod ghclient;
mod buffer;
use buffer::Buffer;
mod cstructs;
use cstructs::{Passwd, Spwd, Group};
mod runfiles;
mod statics;
use statics::{CLIENT, CONFIG};

#[allow(dead_code)]
enum NssStatus {
    TryAgain,
    Unavail,
    NotFound,
    Success,
}

impl From<NssStatus> for libc::c_int {
    fn from(status: NssStatus) -> libc::c_int {
        match status {
            NssStatus::TryAgain => -2,
            NssStatus::Unavail => -1,
            NssStatus::NotFound => 0,
            NssStatus::Success => 1,
        }
    }
}

fn string_from(cstrptr: *const libc::c_char) -> String {
    let cstr: &CStr = unsafe { CStr::from_ptr(cstrptr) };
    String::from(cstr.to_str().unwrap())
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwnam_r(cnameptr: *const libc::c_char,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         pwbufp: *mut *mut Passwd)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (team, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, team.id, &CONFIG) } {
                Ok(_) => {
                    unsafe { *pwbufp = pw };
                    return libc::c_int::from(NssStatus::Success);
                }
                Err(_) => {
                    unsafe { *pwbufp = std::ptr::null_mut() };
                    return nix::Errno::ERANGE as libc::c_int;
                }

            }
        }
        None => {
            unsafe { *pwbufp = std::ptr::null_mut() };
            libc::c_int::from(NssStatus::NotFound)
        }
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwuid_r(uid: libc::uid_t,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         pwbufp: *mut *mut Passwd)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (team, members) = CLIENT.get_team_members().unwrap();
    for member in members.values() {
        if uid == member.id as libc::uid_t {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, team.id, &CONFIG) } {
                Ok(_) => {
                    unsafe { *pwbufp = pw };
                    return libc::c_int::from(NssStatus::Success);
                }
                Err(_) => {
                    unsafe { *pwbufp = std::ptr::null_mut() };
                    return nix::Errno::ERANGE as libc::c_int;
                }
            }
        }
    }
    unsafe { *pwbufp = std::ptr::null_mut() };
    libc::c_int::from(NssStatus::NotFound)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setpwent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let (team, members) = match CLIENT.get_team_members() {
        Ok((team, members)) => (team, members),
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\t{}\n", member.login, member.id, team.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwent_r(pwbuf: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         pwbufp: *mut *mut Passwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let id = words[1].parse::<u64>().unwrap();
        let gid = words[2].parse::<u64>().unwrap();
        match unsafe { (*pwbuf).pack_args(&mut buffer, words[0], id, gid, &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *pwbufp = pwbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *pwbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endpwent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspnam_r(cnameptr: *const libc::c_char,
                                         spwd: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         spbufp: *mut *mut Spwd)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (_, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*spwd).pack_args(&mut buffer, &member.login, &CONFIG) } {
                Ok(_) => {
                    unsafe { *spbufp = spwd };
                    libc::c_int::from(NssStatus::Success)
                }
                Err(_) => {
                    unsafe { *spbufp = std::ptr::null_mut() };
                    nix::Errno::ERANGE as libc::c_int
                }
            }
        }
        None => {
            unsafe { *spbufp = std::ptr::null_mut() };
            libc::c_int::from(NssStatus::NotFound)
        }
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setspent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let members = match CLIENT.get_team_members() {
        Ok((_, members)) => members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\n", member.login, member.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspent_r(spbuf: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         spbufp: *mut *mut Spwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        match unsafe { (*spbuf).pack_args(&mut buffer, words[0], &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *spbufp = spbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *spbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endspent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrgid_r(gid: libc::gid_t,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         grbufp: *mut *mut Group)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if gid as u64 == team.id {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, gid as u64, &members) } {
            Ok(_) => {
                unsafe { *grbufp = group };
                libc::c_int::from(NssStatus::Success)
            }
            Err(_) => {
                unsafe { *grbufp = std::ptr::null_mut() };
                nix::Errno::ERANGE as libc::c_int
            }
        }
    } else {
        unsafe { *grbufp = std::ptr::null_mut() };
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrnam_r(cnameptr: *const libc::c_char,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         grbufp: *mut *mut Group)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if name == team.name {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, team.id, &members) } {
            Ok(_) => {
                unsafe { *grbufp = group };
                libc::c_int::from(NssStatus::Success)
            }
            Err(_) => {
                unsafe { *grbufp = std::ptr::null_mut() };
                nix::Errno::ERANGE as libc::c_int
            }
        }
    } else {
        unsafe { *grbufp = std::ptr::null_mut() };
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setgrent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let (team, members) = match CLIENT.get_team_members() {
        Ok(team_members) => team_members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let member_names = members.values().map(|x| x.login.as_str()).collect::<Vec<&str>>().join(" ");
    list_file.write(format!("{}\t{}\t{}\n", team.name, team.id, member_names).as_bytes())
             .unwrap();
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrent_r(grbuf: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         grbufp: *mut *mut Group)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let member_names: Vec<&str> = words[2].split(" ").collect();
        let gid = words[1].parse::<u64>().unwrap();
        match unsafe { (*grbuf).pack_args(&mut buffer, words[0], gid, &member_names) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *grbufp = grbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *grbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endgrent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}
<|endoftext|>


<commit_before>//! ArrayFire is a high performance software library for parallel computing with
//! an easy-to-use API. ArrayFire abstracts away much of the details of
//! programming parallel architectures by providing a high-level container object,
//! the [Array](./struct.Array.html), that represents data stored on a CPU, GPU, FPGA,
//! or other type of accelerator. This abstraction permits developers to write
//! massively parallel applications in a high-level language where they need
//! not be concerned about low-level optimizations that are frequently required to
//! achieve high throughput on most parallel architectures.

//! This crate provides Rust bindings for the ArrayFire library. Given below table shows the rust bindings compatability with ArrayFire upstream.  If you find any bugs, please report them on [github](https://github.com/arrayfire/arrayfire-rust/issues).
//!
//!
//! | ArrayFire Upstream | Rust Crate |
//! |:------------------:|:---------------:|
//! | 3.3.x | 3.3.x |
//! | 3.4.x | 3.4.x |
//!
//! Only, Major & Minor version numbers need to match.
//!
//! ## Tutorials
//!
//! - [Getting Started with ArrayFire](./getting_started.html)
//! - [Introduction to Vectorization](./vectorization.html)
//! - [Array and Matrix Manipulation](./array_and_matrix_manipulation.html)
//! - [Indexing](./indexing.html)
//! - [Configure ArrayFire Environment](./configuring_arrayfire_environment.html)

#![doc(html_logo_url = "http://www.arrayfire.com/logos/arrayfire_logo_symbol.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://arrayfire.com/docs/rust")]
#![warn(missing_docs)]

#[macro_use]
extern crate lazy_static;

pub use array::Array;
pub use array::{print, print_gen, eval_multiple, is_eval_manual, set_manual_eval};
mod array;

//pub use algorithm::{sum_nan, product_nan, sum_nan_all, product_nan_all};
pub use algorithm::{sum, product, min, max, all_true, any_true, count, sum_nan, product_nan};
pub use algorithm::{sum_all, product_all, min_all, max_all, sum_nan_all, product_nan_all};
pub use algorithm::{all_true_all, any_true_all, count_all, imin, imax, imin_all, imax_all};
pub use algorithm::{accum, locate, diff1, diff2, sort, sort_index, sort_by_key};
pub use algorithm::{set_unique, set_union, set_intersect, scan, scan_by_key};
mod algorithm;

pub use arith::{add, sub, div, mul, lt, gt, le, ge, eq, neq, and, or, minof, maxof, rem};
pub use arith::{bitand, bitor, bitxor, shiftl, shiftr};
pub use arith::{abs, sign, round, trunc, floor, ceil, modulo, sigmoid, clamp};
pub use arith::{sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh};
pub use arith::{atan2, cplx2, arg, cplx, real, imag, conjg, hypot};
pub use arith::{sqrt, log, log1p, log10, log2, pow2, exp, expm1, erf, erfc, root, pow};
pub use arith::{cbrt, factorial, tgamma, lgamma, iszero, isinf, isnan};
mod arith;

pub use backend::{set_backend, get_backend_count, get_available_backends, get_active_backend};
mod backend;

pub use blas::{matmul, dot, transpose, transpose_inplace};
mod blas;

pub use data::{constant, range, iota, identity};
pub use data::{diag_create, diag_extract, lower, upper};
pub use data::{join, join_many, tile};
pub use data::{reorder, shift, moddims, flat, flip};
pub use data::{select, selectl, selectr, replace, replace_scalar};
pub use data::{range_t, iota_t, identity_t, constant_t};
mod data;

pub use device::{get_version, get_revision, info, info_string, device_info, init, device_count, is_double_available, set_device, get_device};
pub use device::{device_mem_info, print_mem_info, set_mem_step_size, get_mem_step_size, device_gc, sync};
mod device;

pub use defines::{DType, AfError, Backend, ColorMap, YCCStd, HomographyType};
pub use defines::{InterpType, BorderType, MatchType, NormType};
pub use defines::{Connectivity, ConvMode, ConvDomain, ColorSpace, MatProp};
pub use defines::{MarkerType, MomentType, SparseFormat, BinaryOp, RandomEngineType};
pub use defines::{PHILOX, THREEFRY, MERSENNE, DEFAULT_RANDOM_ENGINE, Scalar};
mod defines;

pub use dim4::Dim4;
mod dim4;

pub use error::{Callback, ErrorCallback, register_error_handler, handle_error_general};
mod error;

pub use index::{Indexer, index, row, rows, col, cols, slice, slices,
                set_row, set_rows, set_col, set_cols, set_slice, set_slices,
                lookup, assign_seq, index_gen, assign_gen};
mod index;

pub use seq::Seq;
mod seq;

pub use graphics::Window;
mod graphics;

pub use image::{gaussian_kernel, load_image, load_image_native, save_image, save_image_native};
pub use image::{resize, transform, rotate, translate, scale, skew};
pub use image::{dilate, dilate3, erode, erode3, minfilt, maxfilt};
pub use image::{gradient, histogram, hist_equal, regions};
pub use image::{gray2rgb, rgb2gray, hsv2rgb, rgb2hsv, color_space};
pub use image::{bilateral, mean_shift, medfilt, sobel, medfilt1};
pub use image::{unwrap, wrap, sat, rgb2ycbcr, ycbcr2rgb, is_imageio_available, transform_coords};
pub use image::{moments, moments_all};
mod image;

pub use lapack::{svd, lu, qr, cholesky, solve, solve_lu, inverse, det, rank, norm};
pub use lapack::{svd_inplace, lu_inplace, qr_inplace, cholesky_inplace, is_lapack_available};
mod lapack;
mod macros;
mod num;

pub use random::RandomEngine;
pub use random::{set_seed, get_seed, randu, randn, random_uniform, random_normal};
pub use random::{get_default_random_engine, set_default_random_engine_type};
mod random;

pub use signal::{approx1, approx2, set_fft_plan_cache_size};
pub use signal::{fft, fft2, fft3, ifft, ifft2, ifft3};
pub use signal::{fft_r2c, fft2_r2c, fft3_r2c, fft_c2r, fft2_c2r, fft3_c2r};
pub use signal::{fft_inplace, fft2_inplace, fft3_inplace};
pub use signal::{ifft_inplace, ifft2_inplace, ifft3_inplace};
pub use signal::{convolve1, convolve2, convolve3, convolve2_sep};
pub use signal::{fft_convolve1, fft_convolve2, fft_convolve3};
pub use signal::{fir, iir};
mod signal;

pub use sparse::{sparse, sparse_from_host, sparse_from_dense, sparse_convert_to};
pub use sparse::{sparse_to_dense, sparse_get_info, sparse_get_values, sparse_get_nnz};
pub use sparse::{sparse_get_row_indices, sparse_get_col_indices, sparse_get_format};
mod sparse;

pub use statistics::{mean, stdev, median, var, cov, corrcoef};
pub use statistics::{mean_weighted, var_weighted};
pub use statistics::{var_all, mean_all, stdev_all, median_all};
pub use statistics::{mean_all_weighted, var_all_weighted};
mod statistics;

pub use util::{HasAfEnum, get_size};
mod util;

pub use vision::Features;
pub use vision::{fast, harris, orb, hamming_matcher, nearest_neighbour, match_template, susan, dog};
pub use vision::{homography};
mod vision;

// headers that are not exposed through rust wrapper are as follows:
// compatible.h
// constants.h
// complex.h
// cuda.h
// opencl.h
<commit_msg>add lint to allow non camel case naming for enums<commit_after>//! ArrayFire is a high performance software library for parallel computing with
//! an easy-to-use API. ArrayFire abstracts away much of the details of
//! programming parallel architectures by providing a high-level container object,
//! the [Array](./struct.Array.html), that represents data stored on a CPU, GPU, FPGA,
//! or other type of accelerator. This abstraction permits developers to write
//! massively parallel applications in a high-level language where they need
//! not be concerned about low-level optimizations that are frequently required to
//! achieve high throughput on most parallel architectures.

//! This crate provides Rust bindings for the ArrayFire library. Given below table shows the rust bindings compatability with ArrayFire upstream.  If you find any bugs, please report them on [github](https://github.com/arrayfire/arrayfire-rust/issues).
//!
//!
//! | ArrayFire Upstream | Rust Crate |
//! |:------------------:|:---------------:|
//! | 3.3.x | 3.3.x |
//! | 3.4.x | 3.4.x |
//!
//! Only, Major & Minor version numbers need to match.
//!
//! ## Tutorials
//!
//! - [Getting Started with ArrayFire](./getting_started.html)
//! - [Introduction to Vectorization](./vectorization.html)
//! - [Array and Matrix Manipulation](./array_and_matrix_manipulation.html)
//! - [Indexing](./indexing.html)
//! - [Configure ArrayFire Environment](./configuring_arrayfire_environment.html)

#![doc(html_logo_url = "http://www.arrayfire.com/logos/arrayfire_logo_symbol.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://arrayfire.com/docs/rust")]
#![warn(missing_docs)]
#![allow(non_camel_case_types)]

#[macro_use]
extern crate lazy_static;

pub use array::Array;
pub use array::{print, print_gen, eval_multiple, is_eval_manual, set_manual_eval};
mod array;

//pub use algorithm::{sum_nan, product_nan, sum_nan_all, product_nan_all};
pub use algorithm::{sum, product, min, max, all_true, any_true, count, sum_nan, product_nan};
pub use algorithm::{sum_all, product_all, min_all, max_all, sum_nan_all, product_nan_all};
pub use algorithm::{all_true_all, any_true_all, count_all, imin, imax, imin_all, imax_all};
pub use algorithm::{accum, locate, diff1, diff2, sort, sort_index, sort_by_key};
pub use algorithm::{set_unique, set_union, set_intersect, scan, scan_by_key};
mod algorithm;

pub use arith::{add, sub, div, mul, lt, gt, le, ge, eq, neq, and, or, minof, maxof, rem};
pub use arith::{bitand, bitor, bitxor, shiftl, shiftr};
pub use arith::{abs, sign, round, trunc, floor, ceil, modulo, sigmoid, clamp};
pub use arith::{sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh};
pub use arith::{atan2, cplx2, arg, cplx, real, imag, conjg, hypot};
pub use arith::{sqrt, log, log1p, log10, log2, pow2, exp, expm1, erf, erfc, root, pow};
pub use arith::{cbrt, factorial, tgamma, lgamma, iszero, isinf, isnan};
mod arith;

pub use backend::{set_backend, get_backend_count, get_available_backends, get_active_backend};
mod backend;

pub use blas::{matmul, dot, transpose, transpose_inplace};
mod blas;

pub use data::{constant, range, iota, identity};
pub use data::{diag_create, diag_extract, lower, upper};
pub use data::{join, join_many, tile};
pub use data::{reorder, shift, moddims, flat, flip};
pub use data::{select, selectl, selectr, replace, replace_scalar};
pub use data::{range_t, iota_t, identity_t, constant_t};
mod data;

pub use device::{get_version, get_revision, info, info_string, device_info, init, device_count, is_double_available, set_device, get_device};
pub use device::{device_mem_info, print_mem_info, set_mem_step_size, get_mem_step_size, device_gc, sync};
mod device;

pub use defines::{DType, AfError, Backend, ColorMap, YCCStd, HomographyType};
pub use defines::{InterpType, BorderType, MatchType, NormType};
pub use defines::{Connectivity, ConvMode, ConvDomain, ColorSpace, MatProp};
pub use defines::{MarkerType, MomentType, SparseFormat, BinaryOp, RandomEngineType};
pub use defines::{PHILOX, THREEFRY, MERSENNE, DEFAULT_RANDOM_ENGINE, Scalar};
mod defines;

pub use dim4::Dim4;
mod dim4;

pub use error::{Callback, ErrorCallback, register_error_handler, handle_error_general};
mod error;

pub use index::{Indexer, index, row, rows, col, cols, slice, slices,
                set_row, set_rows, set_col, set_cols, set_slice, set_slices,
                lookup, assign_seq, index_gen, assign_gen};
mod index;

pub use seq::Seq;
mod seq;

pub use graphics::Window;
mod graphics;

pub use image::{gaussian_kernel, load_image, load_image_native, save_image, save_image_native};
pub use image::{resize, transform, rotate, translate, scale, skew};
pub use image::{dilate, dilate3, erode, erode3, minfilt, maxfilt};
pub use image::{gradient, histogram, hist_equal, regions};
pub use image::{gray2rgb, rgb2gray, hsv2rgb, rgb2hsv, color_space};
pub use image::{bilateral, mean_shift, medfilt, sobel, medfilt1};
pub use image::{unwrap, wrap, sat, rgb2ycbcr, ycbcr2rgb, is_imageio_available, transform_coords};
pub use image::{moments, moments_all};
mod image;

pub use lapack::{svd, lu, qr, cholesky, solve, solve_lu, inverse, det, rank, norm};
pub use lapack::{svd_inplace, lu_inplace, qr_inplace, cholesky_inplace, is_lapack_available};
mod lapack;
mod macros;
mod num;

pub use random::RandomEngine;
pub use random::{set_seed, get_seed, randu, randn, random_uniform, random_normal};
pub use random::{get_default_random_engine, set_default_random_engine_type};
mod random;

pub use signal::{approx1, approx2, set_fft_plan_cache_size};
pub use signal::{fft, fft2, fft3, ifft, ifft2, ifft3};
pub use signal::{fft_r2c, fft2_r2c, fft3_r2c, fft_c2r, fft2_c2r, fft3_c2r};
pub use signal::{fft_inplace, fft2_inplace, fft3_inplace};
pub use signal::{ifft_inplace, ifft2_inplace, ifft3_inplace};
pub use signal::{convolve1, convolve2, convolve3, convolve2_sep};
pub use signal::{fft_convolve1, fft_convolve2, fft_convolve3};
pub use signal::{fir, iir};
mod signal;

pub use sparse::{sparse, sparse_from_host, sparse_from_dense, sparse_convert_to};
pub use sparse::{sparse_to_dense, sparse_get_info, sparse_get_values, sparse_get_nnz};
pub use sparse::{sparse_get_row_indices, sparse_get_col_indices, sparse_get_format};
mod sparse;

pub use statistics::{mean, stdev, median, var, cov, corrcoef};
pub use statistics::{mean_weighted, var_weighted};
pub use statistics::{var_all, mean_all, stdev_all, median_all};
pub use statistics::{mean_all_weighted, var_all_weighted};
mod statistics;

pub use util::{HasAfEnum, get_size};
mod util;

pub use vision::Features;
pub use vision::{fast, harris, orb, hamming_matcher, nearest_neighbour, match_template, susan, dog};
pub use vision::{homography};
mod vision;

// headers that are not exposed through rust wrapper are as follows:
// compatible.h
// constants.h
// complex.h
// cuda.h
// opencl.h
<|endoftext|>


<commit_before>#![feature(core, io, hash)]
extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;

mod error;
mod errorcode;
mod response;

pub use error::RecaptchaError;
pub use errorcode::RecaptchaErrorCode;

use std::collections::HashSet;
use rustc_serialize::json;
use response::RecaptchaResponse;

/// Verify a recaptcha user response
fn verify(key: &str, response: &str, user_ip: Option<&str>) -> Result<(), RecaptchaError> {
    use hyper::{Client, Url};

    let mut query = vec![
        ("secret", key),
        ("response", response),
    ];

    if let Some(user_ip) = user_ip {
        query.push(("remoteip", user_ip));
    }

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.set_query_from_pairs(query.into_iter());

    let mut client = Client::new();

    let mut response = try!(client.get(url).send());
    let body = try!(response.read_to_string());
    let recaptcha_response = try!(json::decode::<RecaptchaResponse>(&body));

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(RecaptchaError::Codes(errors)),
        (false, _) => Err(RecaptchaError::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use RecaptchaError::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Wrapped(ref e)) => panic!("unexpected response: {}", e),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
    };

    println!("{:?}", resp);
}
<commit_msg>Make verify fn public<commit_after>#![feature(core, io, hash)]
extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;

mod error;
mod errorcode;
mod response;

pub use error::RecaptchaError;
pub use errorcode::RecaptchaErrorCode;

use std::collections::HashSet;
use rustc_serialize::json;
use response::RecaptchaResponse;

/// Verify a recaptcha user response
pub fn verify(key: &str, response: &str, user_ip: Option<&str>) -> Result<(), RecaptchaError> {
    use hyper::{Client, Url};

    let mut query = vec![
        ("secret", key),
        ("response", response),
    ];

    if let Some(user_ip) = user_ip {
        query.push(("remoteip", user_ip));
    }

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.set_query_from_pairs(query.into_iter());

    let mut client = Client::new();

    let mut response = try!(client.get(url).send());
    let body = try!(response.read_to_string());
    let recaptcha_response = try!(json::decode::<RecaptchaResponse>(&body));

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(RecaptchaError::Codes(errors)),
        (false, _) => Err(RecaptchaError::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use RecaptchaError::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Wrapped(ref e)) => panic!("unexpected response: {}", e),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
    };

    println!("{:?}", resp);
}
<|endoftext|>


<commit_before>#![cfg_attr(not(stage0), deny(warnings))]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "compiler-builtins", compiler_builtins)]
#![crate_name = "compiler_builtins"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       test(attr(deny(warnings))))]
#![feature(asm)]
#![feature(compiler_builtins)]
#![feature(core_intrinsics)]
#![feature(naked_functions)]
#![feature(i128_type)]
#![feature(repr_simd)]
#![feature(abi_unadjusted)]
#![feature(linkage)]
#![feature(lang_items)]
#![allow(unused_features)]
#![no_builtins]
#![cfg_attr(feature = "compiler-builtins", feature(staged_api))]
#![cfg_attr(feature = "compiler-builtins",
            unstable(feature = "compiler_builtins_lib",
                     reason = "Compiler builtins. Will never become stable.",
                     issue = "0"))]

// We disable #[no_mangle] for tests so that we can verify the test results
// against the native compiler-rt implementations of the builtins.

// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized
// implementation of that intrinsic and we'll prefer to use that

// NOTE(aapcs, aeabi, arm) ARM targets use intrinsics named __aeabi_* instead of the intrinsics
// that follow "x86 naming convention" (e.g. addsf3). Those aeabi intrinsics must adhere to the
// AAPCS calling convention (`extern "aapcs"`) because that's how LLVM will call them.

#[cfg(test)]
extern crate core;

fn abort() -> ! {
    unsafe { core::intrinsics::abort() }
}

#[macro_use]
mod macros;

pub mod int;
pub mod float;

pub mod mem;

#[cfg(target_arch = "arm")]
pub mod arm;

#[cfg(all(kernel_user_helpers, target_os = "linux", target_arch = "arm"))]
pub mod arm_linux;

#[cfg(target_arch = "x86")]
pub mod x86;

#[cfg(target_arch = "x86_64")]
pub mod x86_64;

pub mod probestack;
<commit_msg>i128 is being stabilized<commit_after>#![cfg_attr(not(stage0), deny(warnings))]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "compiler-builtins", compiler_builtins)]
#![crate_name = "compiler_builtins"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       test(attr(deny(warnings))))]
#![feature(asm)]
#![feature(compiler_builtins)]
#![feature(core_intrinsics)]
#![feature(naked_functions)]
#![feature(repr_simd)]
#![feature(abi_unadjusted)]
#![feature(linkage)]
#![feature(lang_items)]
#![allow(unused_features)]
#![no_builtins]
#![cfg_attr(feature = "compiler-builtins", feature(staged_api))]
#![cfg_attr(feature = "compiler-builtins",
            unstable(feature = "compiler_builtins_lib",
                     reason = "Compiler builtins. Will never become stable.",
                     issue = "0"))]

// We disable #[no_mangle] for tests so that we can verify the test results
// against the native compiler-rt implementations of the builtins.

// NOTE cfg(all(feature = "c", ..)) indicate that compiler-rt provides an arch optimized
// implementation of that intrinsic and we'll prefer to use that

// NOTE(aapcs, aeabi, arm) ARM targets use intrinsics named __aeabi_* instead of the intrinsics
// that follow "x86 naming convention" (e.g. addsf3). Those aeabi intrinsics must adhere to the
// AAPCS calling convention (`extern "aapcs"`) because that's how LLVM will call them.

#[cfg(test)]
extern crate core;

fn abort() -> ! {
    unsafe { core::intrinsics::abort() }
}

#[macro_use]
mod macros;

pub mod int;
pub mod float;

pub mod mem;

#[cfg(target_arch = "arm")]
pub mod arm;

#[cfg(all(kernel_user_helpers, target_os = "linux", target_arch = "arm"))]
pub mod arm_linux;

#[cfg(target_arch = "x86")]
pub mod x86;

#[cfg(target_arch = "x86_64")]
pub mod x86_64;

pub mod probestack;
<|endoftext|>


<commit_before>#![feature(asm)]
#![feature(core)]
#![cfg_attr(test, feature(test))]

use std::str::pattern::{Pattern,Searcher,SearchStep};

#[derive(Debug,Copy,Clone)]
pub struct ByteSearch {
    pub needle: u64,
    pub count: u8,
}

impl ByteSearch {
    pub fn new() -> ByteSearch {
        ByteSearch { needle: 0, count: 0 }
    }

    pub fn push(&mut self, byte: u8) {
        assert!(self.count < 8);
        self.needle <<= 8;
        self.needle |= byte as u64;
        self.count += 1;
    }

    #[inline]
    pub fn find(self, haystack: &str) -> Option<usize> {
        let haystack = haystack.as_bytes();

        let ptr = haystack.as_ptr();
        let mut offset = 0;
        let mut len = haystack.len();

        let mut res: usize;

        // Zero-length strings have a pointer set to 0x1. Even though the
        // length is zero, we still trigger a bad access exception. I
        // think this indicates that the instruction reads in 16 bytes
        // worth of memory at a time, regardless of the length instruction.
        //
        // This could also be an indication of a subtle bug, where we
        // might trigger access violations if we are near the end of a
        // page. See the comment by Renat Saifutdinov on
        // http://www.strchr.com/strcmp_and_strlen_using_sse_4.2
        // It is suggested to use an "aligned read with mask false bits"
        // to avoid the problem.
        //
        // We don't do this yet.
        if len == 0 { return None }

        loop {
            unsafe {
                asm!("pcmpestri $$0, ($1, $5), $2"
                     : // output operands
                     "={ecx}"(res)
                     : // input operands
                     "r"(ptr),
                     "x"(self.needle),
                     "{rdx}"(len),
                     "{rax}"(self.count),
                     "r"(offset)
                     : // clobbers
                     : // options
                     );
            }

            // We know if it matched if the zero flag is set (or
            // unset?), we shouldn't need to test res...
            if res == 16 {
                if len <= 16 {
                    return None;
                }

                offset += 16;
                len -= 16;
            } else {
                return Some(res + offset);
            }
        }
    }
}

impl<'a> Pattern<'a> for ByteSearch {
    type Searcher = ByteSearcher<'a>;

    fn into_searcher(self, haystack: &'a str) -> ByteSearcher<'a> {
        ByteSearcher { haystack: haystack, offset: 0, needle: self }
    }
}

#[derive(Debug,Copy,Clone)]
pub struct ByteSearcher<'a> {
    haystack: &'a str,
    offset: usize,
    needle: ByteSearch,
}

unsafe impl<'a> Searcher<'a> for ByteSearcher<'a> {
    fn haystack(&self) -> &'a str { self.haystack }

    #[inline]
    fn next(&mut self) -> SearchStep {
        if self.offset >= self.haystack.len() { return SearchStep::Done }

        let left_to_search = &self.haystack[self.offset..]; // TODO: unchecked_slice?
        let idx = self.needle.find(left_to_search);

        // If there's no match, then the rest of the string should be
        // returned.
        let idx = idx.unwrap_or(self.haystack.len());

        let (res, next_offset) = if idx == 0 {
            // A match occurs at the beginning of the string
            let next = self.offset + 1;
            (SearchStep::Match(self.offset, next), next)
        } else {
            // A match occurs somewhere further in the string
            let next = self.offset + idx;
            (SearchStep::Reject(self.offset, next), next)
        };

        self.offset = next_offset;
        res
    }
}

#[cfg(test)]
mod test {
    extern crate quickcheck;

    use super::ByteSearch;
    use self::quickcheck::quickcheck;
    use std::str::pattern::{Pattern,Searcher,SearchStep};

    pub const SPACE: ByteSearch       = ByteSearch { needle: 0x0000000000000020, count: 1 };
    // a
    pub const VOWEL: ByteSearch       = ByteSearch { needle: 0x0000000000000061, count: 1 };
    // a e i o u
    pub const VOWELS: ByteSearch      = ByteSearch { needle: 0x0000006165696f75, count: 5 };
    // < > &
    pub const XML_DELIM_3: ByteSearch = ByteSearch { needle: 0x00000000003c3e26, count: 3 };
    // < > & ' "
    pub const XML_DELIM_5: ByteSearch = ByteSearch { needle: 0x0000003c3e262722, count: 5 };

    #[test]
    fn works_as_find_does_for_single_characters() {
        // Quickcheck currently only generates Strings with A-Z, a-z, 0-9
        fn prop(s: String) -> bool {
            s.find(VOWEL) == s.find('a')
        }
        quickcheck(prop as fn(String) -> bool);
    }

    #[test]
    fn works_as_find_does_for_multiple_characters() {
        // Quickcheck currently only generates Strings with A-Z, a-z, 0-9
        fn prop(s: String) -> bool {
            s.find(VOWELS) == s.find(&['a', 'e', 'i', 'o', 'u'][..])
        }
        quickcheck(prop as fn(String) -> bool);
    }

    #[test]
    fn pattern_does_not_backtrack_after_first() {
        let mut searcher = SPACE.into_searcher("hello w ");
        assert_eq!(SearchStep::Reject(0,5), searcher.next());
        assert_eq!(SearchStep::Match(5,6), searcher.next());
        assert_eq!(SearchStep::Reject(6,7), searcher.next());
        assert_eq!(SearchStep::Match(7,8), searcher.next());
        assert_eq!(SearchStep::Done, searcher.next());
    }

    #[test]
    fn space_is_found() {
        // Since the algorithm operates on 16-byte chunks, it's
        // important to cover tests around that boundary. Since 16
        // isn't that big of a number, we might as well do all of
        // them.

        assert_eq!(Some(0),  SPACE.find(" "));
        assert_eq!(Some(1),  SPACE.find("0 "));
        assert_eq!(Some(2),  SPACE.find("01 "));
        assert_eq!(Some(3),  SPACE.find("012 "));
        assert_eq!(Some(4),  SPACE.find("0123 "));
        assert_eq!(Some(5),  SPACE.find("01234 "));
        assert_eq!(Some(6),  SPACE.find("012345 "));
        assert_eq!(Some(7),  SPACE.find("0123456 "));
        assert_eq!(Some(8),  SPACE.find("01234567 "));
        assert_eq!(Some(9),  SPACE.find("012345678 "));
        assert_eq!(Some(10), SPACE.find("0123456789 "));
        assert_eq!(Some(11), SPACE.find("0123456789A "));
        assert_eq!(Some(12), SPACE.find("0123456789AB "));
        assert_eq!(Some(13), SPACE.find("0123456789ABC "));
        assert_eq!(Some(14), SPACE.find("0123456789ABCD "));
        assert_eq!(Some(15), SPACE.find("0123456789ABCDE "));
        assert_eq!(Some(16), SPACE.find("0123456789ABCDEF "));
        assert_eq!(Some(17), SPACE.find("0123456789ABCDEFG "));
    }

    #[test]
    fn space_not_found() {
        // Since the algorithm operates on 16-byte chunks, it's
        // important to cover tests around that boundary. Since 16
        // isn't that big of a number, we might as well do all of
        // them.

        assert_eq!(None, SPACE.find(""));
        assert_eq!(None, SPACE.find("0"));
        assert_eq!(None, SPACE.find("01"));
        assert_eq!(None, SPACE.find("012"));
        assert_eq!(None, SPACE.find("0123"));
        assert_eq!(None, SPACE.find("01234"));
        assert_eq!(None, SPACE.find("012345"));
        assert_eq!(None, SPACE.find("0123456"));
        assert_eq!(None, SPACE.find("01234567"));
        assert_eq!(None, SPACE.find("012345678"));
        assert_eq!(None, SPACE.find("0123456789"));
        assert_eq!(None, SPACE.find("0123456789A"));
        assert_eq!(None, SPACE.find("0123456789AB"));
        assert_eq!(None, SPACE.find("0123456789ABC"));
        assert_eq!(None, SPACE.find("0123456789ABCD"));
        assert_eq!(None, SPACE.find("0123456789ABCDE"));
        assert_eq!(None, SPACE.find("0123456789ABCDEF"));
        assert_eq!(None, SPACE.find("0123456789ABCDEFG"));
    }

    #[test]
    fn xml_delim_3_is_found() {
        assert_eq!(Some(0), XML_DELIM_3.find("<"));
        assert_eq!(Some(0), XML_DELIM_3.find(">"));
        assert_eq!(Some(0), XML_DELIM_3.find("&"));
        assert_eq!(None,    XML_DELIM_3.find(""));
    }

    #[test]
    fn xml_delim_5_is_found() {
        assert_eq!(Some(0), XML_DELIM_5.find("<"));
        assert_eq!(Some(0), XML_DELIM_5.find(">"));
        assert_eq!(Some(0), XML_DELIM_5.find("&"));
        assert_eq!(Some(0), XML_DELIM_5.find("'"));
        assert_eq!(Some(0), XML_DELIM_5.find("\""));
        assert_eq!(None,    XML_DELIM_5.find(""));
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use super::test::{SPACE,XML_DELIM_3,XML_DELIM_5};
    use std::iter;

    fn prefix_string() -> String {
        iter::repeat("a").take(5 * 1024 * 1024).collect()
    }

    fn bench_space<F>(b: &mut test::Bencher, f: F)
        where F: Fn(&str) -> Option<usize>
    {
        let mut haystack = prefix_string();
        haystack.push(' ');

        b.iter(|| test::black_box(f(&haystack)));
        b.bytes = haystack.len() as u64;
    }

    #[bench]
    fn space_assembly(b: &mut test::Bencher) {
        bench_space(b, |hs| SPACE.find(hs))
    }

    #[bench]
    fn space_assembly_as_pattern(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(SPACE))
    }

    #[bench]
    fn space_find_string(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(" "))
    }

    #[bench]
    fn space_find_char(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(' '))
    }

    #[bench]
    fn space_find_char_set(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(&[' '][..]))
    }

    #[bench]
    fn space_find_byte(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.as_bytes().iter().position(|&v| v == b' '))
    }

    fn bench_xml_delim_3<F>(b: &mut test::Bencher, f: F)
        where F: Fn(&str) -> Option<usize>
    {
        let mut haystack = prefix_string();
        haystack.push('&');

        b.iter(|| test::black_box(f(&haystack)));
        b.bytes = haystack.len() as u64;
    }

    #[bench]
    fn xml_delim_3_assembly(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| XML_DELIM_3.find(hs))
    }

    #[bench]
    fn xml_delim_3_assembly_as_pattern(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| hs.find(XML_DELIM_3))
    }

    #[bench]
    fn xml_delim_3_find_char_set(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| hs.find(&['<', '>', '&'][..]))
    }

    fn bench_xml_delim_5<F>(b: &mut test::Bencher, f: F)
        where F: Fn(&str) -> Option<usize>
    {
        let mut haystack = prefix_string();
        haystack.push('"');

        b.iter(|| test::black_box(f(&haystack)));
        b.bytes = haystack.len() as u64;
    }

    #[bench]
    fn xml_delim_5_assembly(b: &mut test::Bencher) {
        bench_xml_delim_5(b, |hs| XML_DELIM_5.find(hs))
    }

    #[bench]
    fn xml_delim_5_assembly_as_pattern(b: &mut test::Bencher) {
        bench_xml_delim_5(b, |hs| hs.find(XML_DELIM_5))
    }

    #[bench]
    fn xml_delim_5_find_char_set(b: &mut test::Bencher) {
        bench_xml_delim_5(b, |hs| hs.find(&['<', '>', '&', '\'', '"'][..]))
    }
}
<commit_msg>Add more benchmarks using closures<commit_after>#![feature(asm)]
#![feature(core)]
#![cfg_attr(test, feature(test))]

use std::str::pattern::{Pattern,Searcher,SearchStep};

#[derive(Debug,Copy,Clone)]
pub struct ByteSearch {
    pub needle: u64,
    pub count: u8,
}

impl ByteSearch {
    pub fn new() -> ByteSearch {
        ByteSearch { needle: 0, count: 0 }
    }

    pub fn push(&mut self, byte: u8) {
        assert!(self.count < 8);
        self.needle <<= 8;
        self.needle |= byte as u64;
        self.count += 1;
    }

    #[inline]
    pub fn find(self, haystack: &str) -> Option<usize> {
        let haystack = haystack.as_bytes();

        let ptr = haystack.as_ptr();
        let mut offset = 0;
        let mut len = haystack.len();

        let mut res: usize;

        // Zero-length strings have a pointer set to 0x1. Even though the
        // length is zero, we still trigger a bad access exception. I
        // think this indicates that the instruction reads in 16 bytes
        // worth of memory at a time, regardless of the length instruction.
        //
        // This could also be an indication of a subtle bug, where we
        // might trigger access violations if we are near the end of a
        // page. See the comment by Renat Saifutdinov on
        // http://www.strchr.com/strcmp_and_strlen_using_sse_4.2
        // It is suggested to use an "aligned read with mask false bits"
        // to avoid the problem.
        //
        // We don't do this yet.
        if len == 0 { return None }

        loop {
            unsafe {
                asm!("pcmpestri $$0, ($1, $5), $2"
                     : // output operands
                     "={ecx}"(res)
                     : // input operands
                     "r"(ptr),
                     "x"(self.needle),
                     "{rdx}"(len),
                     "{rax}"(self.count),
                     "r"(offset)
                     : // clobbers
                     : // options
                     );
            }

            // We know if it matched if the zero flag is set (or
            // unset?), we shouldn't need to test res...
            if res == 16 {
                if len <= 16 {
                    return None;
                }

                offset += 16;
                len -= 16;
            } else {
                return Some(res + offset);
            }
        }
    }
}

impl<'a> Pattern<'a> for ByteSearch {
    type Searcher = ByteSearcher<'a>;

    fn into_searcher(self, haystack: &'a str) -> ByteSearcher<'a> {
        ByteSearcher { haystack: haystack, offset: 0, needle: self }
    }
}

#[derive(Debug,Copy,Clone)]
pub struct ByteSearcher<'a> {
    haystack: &'a str,
    offset: usize,
    needle: ByteSearch,
}

unsafe impl<'a> Searcher<'a> for ByteSearcher<'a> {
    fn haystack(&self) -> &'a str { self.haystack }

    #[inline]
    fn next(&mut self) -> SearchStep {
        if self.offset >= self.haystack.len() { return SearchStep::Done }

        let left_to_search = &self.haystack[self.offset..]; // TODO: unchecked_slice?
        let idx = self.needle.find(left_to_search);

        // If there's no match, then the rest of the string should be
        // returned.
        let idx = idx.unwrap_or(self.haystack.len());

        let (res, next_offset) = if idx == 0 {
            // A match occurs at the beginning of the string
            let next = self.offset + 1;
            (SearchStep::Match(self.offset, next), next)
        } else {
            // A match occurs somewhere further in the string
            let next = self.offset + idx;
            (SearchStep::Reject(self.offset, next), next)
        };

        self.offset = next_offset;
        res
    }
}

#[cfg(test)]
mod test {
    extern crate quickcheck;

    use super::ByteSearch;
    use self::quickcheck::quickcheck;
    use std::str::pattern::{Pattern,Searcher,SearchStep};

    pub const SPACE: ByteSearch       = ByteSearch { needle: 0x0000000000000020, count: 1 };
    // a
    pub const VOWEL: ByteSearch       = ByteSearch { needle: 0x0000000000000061, count: 1 };
    // a e i o u
    pub const VOWELS: ByteSearch      = ByteSearch { needle: 0x0000006165696f75, count: 5 };
    // < > &
    pub const XML_DELIM_3: ByteSearch = ByteSearch { needle: 0x00000000003c3e26, count: 3 };
    // < > & ' "
    pub const XML_DELIM_5: ByteSearch = ByteSearch { needle: 0x0000003c3e262722, count: 5 };

    #[test]
    fn works_as_find_does_for_single_characters() {
        // Quickcheck currently only generates Strings with A-Z, a-z, 0-9
        fn prop(s: String) -> bool {
            s.find(VOWEL) == s.find('a')
        }
        quickcheck(prop as fn(String) -> bool);
    }

    #[test]
    fn works_as_find_does_for_multiple_characters() {
        // Quickcheck currently only generates Strings with A-Z, a-z, 0-9
        fn prop(s: String) -> bool {
            s.find(VOWELS) == s.find(&['a', 'e', 'i', 'o', 'u'][..])
        }
        quickcheck(prop as fn(String) -> bool);
    }

    #[test]
    fn pattern_does_not_backtrack_after_first() {
        let mut searcher = SPACE.into_searcher("hello w ");
        assert_eq!(SearchStep::Reject(0,5), searcher.next());
        assert_eq!(SearchStep::Match(5,6), searcher.next());
        assert_eq!(SearchStep::Reject(6,7), searcher.next());
        assert_eq!(SearchStep::Match(7,8), searcher.next());
        assert_eq!(SearchStep::Done, searcher.next());
    }

    #[test]
    fn space_is_found() {
        // Since the algorithm operates on 16-byte chunks, it's
        // important to cover tests around that boundary. Since 16
        // isn't that big of a number, we might as well do all of
        // them.

        assert_eq!(Some(0),  SPACE.find(" "));
        assert_eq!(Some(1),  SPACE.find("0 "));
        assert_eq!(Some(2),  SPACE.find("01 "));
        assert_eq!(Some(3),  SPACE.find("012 "));
        assert_eq!(Some(4),  SPACE.find("0123 "));
        assert_eq!(Some(5),  SPACE.find("01234 "));
        assert_eq!(Some(6),  SPACE.find("012345 "));
        assert_eq!(Some(7),  SPACE.find("0123456 "));
        assert_eq!(Some(8),  SPACE.find("01234567 "));
        assert_eq!(Some(9),  SPACE.find("012345678 "));
        assert_eq!(Some(10), SPACE.find("0123456789 "));
        assert_eq!(Some(11), SPACE.find("0123456789A "));
        assert_eq!(Some(12), SPACE.find("0123456789AB "));
        assert_eq!(Some(13), SPACE.find("0123456789ABC "));
        assert_eq!(Some(14), SPACE.find("0123456789ABCD "));
        assert_eq!(Some(15), SPACE.find("0123456789ABCDE "));
        assert_eq!(Some(16), SPACE.find("0123456789ABCDEF "));
        assert_eq!(Some(17), SPACE.find("0123456789ABCDEFG "));
    }

    #[test]
    fn space_not_found() {
        // Since the algorithm operates on 16-byte chunks, it's
        // important to cover tests around that boundary. Since 16
        // isn't that big of a number, we might as well do all of
        // them.

        assert_eq!(None, SPACE.find(""));
        assert_eq!(None, SPACE.find("0"));
        assert_eq!(None, SPACE.find("01"));
        assert_eq!(None, SPACE.find("012"));
        assert_eq!(None, SPACE.find("0123"));
        assert_eq!(None, SPACE.find("01234"));
        assert_eq!(None, SPACE.find("012345"));
        assert_eq!(None, SPACE.find("0123456"));
        assert_eq!(None, SPACE.find("01234567"));
        assert_eq!(None, SPACE.find("012345678"));
        assert_eq!(None, SPACE.find("0123456789"));
        assert_eq!(None, SPACE.find("0123456789A"));
        assert_eq!(None, SPACE.find("0123456789AB"));
        assert_eq!(None, SPACE.find("0123456789ABC"));
        assert_eq!(None, SPACE.find("0123456789ABCD"));
        assert_eq!(None, SPACE.find("0123456789ABCDE"));
        assert_eq!(None, SPACE.find("0123456789ABCDEF"));
        assert_eq!(None, SPACE.find("0123456789ABCDEFG"));
    }

    #[test]
    fn xml_delim_3_is_found() {
        assert_eq!(Some(0), XML_DELIM_3.find("<"));
        assert_eq!(Some(0), XML_DELIM_3.find(">"));
        assert_eq!(Some(0), XML_DELIM_3.find("&"));
        assert_eq!(None,    XML_DELIM_3.find(""));
    }

    #[test]
    fn xml_delim_5_is_found() {
        assert_eq!(Some(0), XML_DELIM_5.find("<"));
        assert_eq!(Some(0), XML_DELIM_5.find(">"));
        assert_eq!(Some(0), XML_DELIM_5.find("&"));
        assert_eq!(Some(0), XML_DELIM_5.find("'"));
        assert_eq!(Some(0), XML_DELIM_5.find("\""));
        assert_eq!(None,    XML_DELIM_5.find(""));
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use super::test::{SPACE,XML_DELIM_3,XML_DELIM_5};
    use std::iter;

    fn prefix_string() -> String {
        iter::repeat("a").take(5 * 1024 * 1024).collect()
    }

    fn bench_space<F>(b: &mut test::Bencher, f: F)
        where F: Fn(&str) -> Option<usize>
    {
        let mut haystack = prefix_string();
        haystack.push(' ');

        b.iter(|| test::black_box(f(&haystack)));
        b.bytes = haystack.len() as u64;
    }

    #[bench]
    fn space_assembly(b: &mut test::Bencher) {
        bench_space(b, |hs| SPACE.find(hs))
    }

    #[bench]
    fn space_assembly_as_pattern(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(SPACE))
    }

    #[bench]
    fn space_find_string(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(" "))
    }

    #[bench]
    fn space_find_char(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(' '))
    }

    #[bench]
    fn space_find_char_set(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(&[' '][..]))
    }

    #[bench]
    fn space_find_byte(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.as_bytes().iter().position(|&v| v == b' '))
    }

    #[bench]
    fn space_find_closure(b: &mut test::Bencher) {
        bench_space(b, |hs| hs.find(|c| c == ' '))
    }

    fn bench_xml_delim_3<F>(b: &mut test::Bencher, f: F)
        where F: Fn(&str) -> Option<usize>
    {
        let mut haystack = prefix_string();
        haystack.push('&');

        b.iter(|| test::black_box(f(&haystack)));
        b.bytes = haystack.len() as u64;
    }

    #[bench]
    fn xml_delim_3_assembly(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| XML_DELIM_3.find(hs))
    }

    #[bench]
    fn xml_delim_3_assembly_as_pattern(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| hs.find(XML_DELIM_3))
    }

    #[bench]
    fn xml_delim_3_find_byte_closure(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| hs.as_bytes().iter().position(|&c| {
            c == b'<' || c == b'>' || c == b'&'
        }))
    }

    #[bench]
    fn xml_delim_3_find_char_set(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| hs.find(&['<', '>', '&'][..]))
    }

    #[bench]
    fn xml_delim_3_find_char_closure(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| hs.find(|c| {
            c == '<' || c == '>' || c == '&'
        }))
    }

    fn bench_xml_delim_5<F>(b: &mut test::Bencher, f: F)
        where F: Fn(&str) -> Option<usize>
    {
        let mut haystack = prefix_string();
        haystack.push('"');

        b.iter(|| test::black_box(f(&haystack)));
        b.bytes = haystack.len() as u64;
    }

    #[bench]
    fn xml_delim_5_assembly(b: &mut test::Bencher) {
        bench_xml_delim_5(b, |hs| XML_DELIM_5.find(hs))
    }

    #[bench]
    fn xml_delim_5_assembly_as_pattern(b: &mut test::Bencher) {
        bench_xml_delim_5(b, |hs| hs.find(XML_DELIM_5))
    }

    #[bench]
    fn xml_delim_5_find_byte_closure(b: &mut test::Bencher) {
        bench_xml_delim_3(b, |hs| hs.as_bytes().iter().position(|&c| {
            c == b'<' || c == b'>' || c == b'&' || c == b'\'' || c == b'"'
        }))
    }

    #[bench]
    fn xml_delim_5_find_char_set(b: &mut test::Bencher) {
        bench_xml_delim_5(b, |hs| hs.find(&['<', '>', '&', '\'', '"'][..]))
    }

    #[bench]
    fn xml_delim_5_find_char_closure(b: &mut test::Bencher) {
        bench_xml_delim_5(b, |hs| hs.find(|c| {
            c == '<' || c == '>' || c == '&' || c == '\'' || c == '"'
        }))
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate quick_error;
extern crate num;
extern crate nalgebra;
extern crate rand;
extern crate image;
extern crate ndarray;

pub mod testimage_generator;

pub mod helpers;

mod online_nmf;
pub use online_nmf::OnlineNMF;

mod orthogonal_nmf;
pub use orthogonal_nmf::OrthogonalNMF;

mod orthogonal_nmf_blas;
pub use orthogonal_nmf_blas::OrthogonalNMFBlas;
<commit_msg>extern crate rblas<commit_after>#[macro_use]
extern crate quick_error;
extern crate num;
extern crate nalgebra;
extern crate rand;
extern crate image;
extern crate ndarray;
extern crate rblas;

pub mod testimage_generator;

pub mod helpers;

mod online_nmf;
pub use online_nmf::OnlineNMF;

mod orthogonal_nmf;
pub use orthogonal_nmf::OrthogonalNMF;

mod orthogonal_nmf_blas;
pub use orthogonal_nmf_blas::OrthogonalNMFBlas;
<|endoftext|>


<commit_before>#![feature(collections)]

extern crate num;
#[cfg(test)] extern crate rand;

pub mod base58;
<commit_msg>The library now has traits ToBase58, FromBase58 in root<commit_after>#![feature(collections)]

extern crate num;
#[cfg(test)] extern crate rand;

pub use base58::{ToBase58, FromBase58};
pub mod base58;
<|endoftext|>


<commit_before>//! Additional methods for Read and Write
//!
//! The additional methods implemented allow reading and writing integers and floats
//! in the specified endianness.
//!
//! # Usage
//!
//! Basically, you need to `use` the trait WritePodExt or ReadPodExt.
//!
//! # Examples
//!
//! ## Reading
//!
//! To read some value from a reader, import ReadPodExt and the needed endianness.
//!
//! ```
//! use podio::{ReadPodExt, BigEndian};
//!
//! let slice: &[u8] = &[0x10, 0x20, 0x30, 0x40];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! let value = reader.read_u32::<BigEndian>().unwrap();
//!
//! assert_eq!(value, 0x10203040);
//! ```
//!
//! ## Writing
//!
//! For writing, you need to import the trait WritePodExt.
//!
//! ```
//! use podio::{WritePodExt, LittleEndian};
//!
//! let slice: &mut [u8] = &mut [0; 2];
//! let mut writer = std::io::Cursor::new(slice);
//!
//! writer.write_u16::<LittleEndian>(0x8802).unwrap();
//!
//! assert_eq!(writer.into_inner(), &[0x02, 0x88]);
//! ```
//!
//! ## Read exact
//!
//! One additional method, not really dealing with POD, is `read_exact`.
//!
//! ```
//! use podio::ReadPodExt;
//!
//! let slice: &[u8] = &[0, 1, 2, 3];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! assert_eq!(reader.read_exact(1).unwrap(), [0]);
//! assert_eq!(reader.read_exact(2).unwrap(), [1,2]);
//! assert_eq!(reader.read_exact(0).unwrap(), []);
//! assert_eq!(reader.read_exact(1).unwrap(), [3]);
//! assert!(reader.read_exact(1).is_err());

#![warn(missing_docs)]

use std::io;
use std::io::prelude::*;

/// Little endian. The number `0xABCD` is stored `[0xCD, 0xAB]`
pub enum LittleEndian {}
/// Big endian. The number `0xABCD` is stored `[0xAB, 0xCD]`
pub enum BigEndian {}

/// Trait implementing conversion methods for a specific endianness
pub trait Endianness {
    /// Converts a value from the platform type to the specified endianness
    fn int_to_target<T: EndianConvert>(val: T) -> T;
    /// Converts a value from the sepcified endianness to the platform type
    fn int_from_target<T: EndianConvert>(val: T) -> T;
}

/// Generic trait for endian conversions on integers
pub trait EndianConvert {
    /// Convert self to a big-endian value
    fn to_be(self) -> Self;
    /// Convert self to a little-endian value
    fn to_le(self) -> Self;
    /// Convert a big-endian value to the target endianness
    fn from_be(x: Self) -> Self;
    /// Convert a little-endian value to the target endiannes
    fn from_le(x: Self) -> Self;
}

/// Additional write methods for a io::Write
pub trait WritePodExt {
    /// Write a u64
    fn write_u64<T: Endianness>(&mut self, u64) -> io::Result<()>;
    /// Write a u32
    fn write_u32<T: Endianness>(&mut self, u32) -> io::Result<()>;
    /// Write a u16
    fn write_u16<T: Endianness>(&mut self, u16) -> io::Result<()>;
    /// Write a u8
    fn write_u8(&mut self, u8) -> io::Result<()>;
    /// Write a i64
    fn write_i64<T: Endianness>(&mut self, i64) -> io::Result<()>;
    /// Write a i32
    fn write_i32<T: Endianness>(&mut self, i32) -> io::Result<()>;
    /// Write a i16
    fn write_i16<T: Endianness>(&mut self, i16) -> io::Result<()>;
    /// Write a i8
    fn write_i8(&mut self, i8) -> io::Result<()>;
    /// Write a f32
    fn write_f32<T: Endianness>(&mut self, f32) -> io::Result<()>;
    /// Write a f64
    fn write_f64<T: Endianness>(&mut self, f64) -> io::Result<()>;
}

/// Additional read methods for a io::Read
pub trait ReadPodExt {
    /// Read a u64
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64>;
    /// Read a u32
    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32>;
    /// Read a u16
    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16>;
    /// Read a u8
    fn read_u8(&mut self) -> io::Result<u8>;
    /// Read a i64
    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64>;
    /// Read a i32
    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32>;
    /// Read a i16
    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16>;
    /// Read a i8
    fn read_i8(&mut self) -> io::Result<i8>;
    /// Read a f32
    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32>;
    /// Read a f64
    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64>;
    /// Read a specific number of bytes
    fn read_exact(&mut self, usize) -> io::Result<Vec<u8>>;
}

impl Endianness for LittleEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_le()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_le(val)
    }
}

impl Endianness for BigEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_be()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_be(val)
    }
}

macro_rules! impl_platform_convert {
    ($T:ty) => {
        impl EndianConvert for $T {
            #[inline]
            fn to_be(self) -> $T {
                self.to_be()
            }

            #[inline]
            fn to_le(self) -> $T {
                self.to_le()
            }

            #[inline]
            fn from_be(x: $T) -> $T {
                if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
            }

            #[inline]
            fn from_le(x: $T) -> $T {
                if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
            }
        }
    };
}

impl_platform_convert!(u8);
impl_platform_convert!(u16);
impl_platform_convert!(u32);
impl_platform_convert!(u64);

macro_rules! val_to_buf {
    ($val:ident, $buf:ident) => {
        {
            for i in 0..$buf.len() {
                $buf[i] = ($val >> (i * 8)) as u8;
            }
        }
    };
}

impl<W: Write> WritePodExt for W {
    fn write_u64<T: Endianness>(&mut self, val: u64) -> io::Result<()> {
        let mut buf = [0u8; 8];
        let tval = <T as Endianness>::int_to_target(val);
        val_to_buf!(tval, buf);
        self.write_all(&buf)
    }

    fn write_u32<T: Endianness>(&mut self, val: u32) -> io::Result<()> {
        let mut buf = [0u8; 4];
        let tval = <T as Endianness>::int_to_target(val);
        val_to_buf!(tval, buf);
        self.write_all(&buf)
    }

    fn write_u16<T: Endianness>(&mut self, val: u16) -> io::Result<()> {
        let mut buf = [0u8; 2];
        let tval = <T as Endianness>::int_to_target(val);
        val_to_buf!(tval, buf);
        self.write_all(&buf)
    }

    fn write_u8(&mut self, val: u8) -> io::Result<()> {
        self.write_all(&[val])
    }

    fn write_i64<T: Endianness>(&mut self, val: i64) -> io::Result<()> {
        self.write_u64::<T>(val as u64)
    }

    fn write_i32<T: Endianness>(&mut self, val: i32) -> io::Result<()> {
        self.write_u32::<T>(val as u32)
    }

    fn write_i16<T: Endianness>(&mut self, val: i16) -> io::Result<()> {
        self.write_u16::<T>(val as u16)
    }

    fn write_i8(&mut self, val: i8) -> io::Result<()> {
        self.write_u8(val as u8)
    }

    fn write_f32<T: Endianness>(&mut self, val: f32) -> io::Result<()> {
        let tval: u32 = unsafe { std::mem::transmute::<f32, u32>(val) };
        self.write_u32::<T>(tval)
    }

    fn write_f64<T: Endianness>(&mut self, val: f64) -> io::Result<()> {
        let tval: u64 = unsafe { std::mem::transmute::<f64, u64>(val) };
        self.write_u64::<T>(tval)
    }
}

#[inline]
fn fill_buf<R: Read>(reader: &mut R, buf: &mut [u8]) -> io::Result<()> {
    let mut idx = 0;
    while idx != buf.len() {
        match reader.read(&mut buf[idx..]) {
            Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "Could not read enough bytes")),
            Ok(v) => { idx += v; }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}

macro_rules! buf_to_val {
    ($buf:ident, $typ:ty) => {
        {
            let mut val: $typ = 0;
            for i in 0..$buf.len() {
                val |= ($buf[i] as $typ) << (i * 8);
            }
            val
        }
    };
}

impl<R: Read> ReadPodExt for R {
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64> {
        let buf = &mut [0u8; 8];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u64);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32> {
        let buf = &mut [0u8; 4];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u32);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16> {
        let buf = &mut [0u8; 2];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u16);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u8(&mut self) -> io::Result<u8> {
        let buf = &mut [0u8; 1];
        try!(fill_buf(self, buf));
        Ok(buf[0])
    }
    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64> {
        self.read_u64::<T>().map(|v| v as i64)
    }
    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32> {
        self.read_u32::<T>().map(|v| v as i32)
    }
    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16> {
        self.read_u16::<T>().map(|v| v as i16)
    }
    fn read_i8(&mut self) -> io::Result<i8> {
        self.read_u8().map(|v| v as i8)
    }
    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64> {
        self.read_u64::<T>().map(|v| unsafe { std::mem::transmute::<u64, f64>(v) })
    }
    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32> {
        self.read_u32::<T>().map(|v| unsafe { std::mem::transmute::<u32, f32>(v) })
    }
    fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>> {
        let mut res = vec![0; len];
        try!(fill_buf(self, &mut res));
        Ok(res)
    }
}
<commit_msg>Rewrite the macros a little bit<commit_after>//! Additional methods for Read and Write
//!
//! The additional methods implemented allow reading and writing integers and floats
//! in the specified endianness.
//!
//! # Usage
//!
//! Basically, you need to `use` the trait WritePodExt or ReadPodExt.
//!
//! # Examples
//!
//! ## Reading
//!
//! To read some value from a reader, import ReadPodExt and the needed endianness.
//!
//! ```
//! use podio::{ReadPodExt, BigEndian};
//!
//! let slice: &[u8] = &[0x10, 0x20, 0x30, 0x40];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! let value = reader.read_u32::<BigEndian>().unwrap();
//!
//! assert_eq!(value, 0x10203040);
//! ```
//!
//! ## Writing
//!
//! For writing, you need to import the trait WritePodExt.
//!
//! ```
//! use podio::{WritePodExt, LittleEndian};
//!
//! let slice: &mut [u8] = &mut [0; 2];
//! let mut writer = std::io::Cursor::new(slice);
//!
//! writer.write_u16::<LittleEndian>(0x8802).unwrap();
//!
//! assert_eq!(writer.into_inner(), &[0x02, 0x88]);
//! ```
//!
//! ## Read exact
//!
//! One additional method, not really dealing with POD, is `read_exact`.
//!
//! ```
//! use podio::ReadPodExt;
//!
//! let slice: &[u8] = &[0, 1, 2, 3];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! assert_eq!(reader.read_exact(1).unwrap(), [0]);
//! assert_eq!(reader.read_exact(2).unwrap(), [1,2]);
//! assert_eq!(reader.read_exact(0).unwrap(), []);
//! assert_eq!(reader.read_exact(1).unwrap(), [3]);
//! assert!(reader.read_exact(1).is_err());

#![warn(missing_docs)]

use std::io;
use std::io::prelude::*;

/// Little endian. The number `0xABCD` is stored `[0xCD, 0xAB]`
pub enum LittleEndian {}
/// Big endian. The number `0xABCD` is stored `[0xAB, 0xCD]`
pub enum BigEndian {}

/// Trait implementing conversion methods for a specific endianness
pub trait Endianness {
    /// Converts a value from the platform type to the specified endianness
    fn int_to_target<T: EndianConvert>(val: T) -> T;
    /// Converts a value from the sepcified endianness to the platform type
    fn int_from_target<T: EndianConvert>(val: T) -> T;
}

/// Generic trait for endian conversions on integers
pub trait EndianConvert {
    /// Convert self to a big-endian value
    fn to_be(self) -> Self;
    /// Convert self to a little-endian value
    fn to_le(self) -> Self;
    /// Convert a big-endian value to the target endianness
    fn from_be(x: Self) -> Self;
    /// Convert a little-endian value to the target endiannes
    fn from_le(x: Self) -> Self;
}

/// Additional write methods for a io::Write
pub trait WritePodExt {
    /// Write a u64
    fn write_u64<T: Endianness>(&mut self, u64) -> io::Result<()>;
    /// Write a u32
    fn write_u32<T: Endianness>(&mut self, u32) -> io::Result<()>;
    /// Write a u16
    fn write_u16<T: Endianness>(&mut self, u16) -> io::Result<()>;
    /// Write a u8
    fn write_u8(&mut self, u8) -> io::Result<()>;
    /// Write a i64
    fn write_i64<T: Endianness>(&mut self, i64) -> io::Result<()>;
    /// Write a i32
    fn write_i32<T: Endianness>(&mut self, i32) -> io::Result<()>;
    /// Write a i16
    fn write_i16<T: Endianness>(&mut self, i16) -> io::Result<()>;
    /// Write a i8
    fn write_i8(&mut self, i8) -> io::Result<()>;
    /// Write a f32
    fn write_f32<T: Endianness>(&mut self, f32) -> io::Result<()>;
    /// Write a f64
    fn write_f64<T: Endianness>(&mut self, f64) -> io::Result<()>;
}

/// Additional read methods for a io::Read
pub trait ReadPodExt {
    /// Read a u64
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64>;
    /// Read a u32
    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32>;
    /// Read a u16
    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16>;
    /// Read a u8
    fn read_u8(&mut self) -> io::Result<u8>;
    /// Read a i64
    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64>;
    /// Read a i32
    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32>;
    /// Read a i16
    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16>;
    /// Read a i8
    fn read_i8(&mut self) -> io::Result<i8>;
    /// Read a f32
    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32>;
    /// Read a f64
    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64>;
    /// Read a specific number of bytes
    fn read_exact(&mut self, usize) -> io::Result<Vec<u8>>;
}

impl Endianness for LittleEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_le()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_le(val)
    }
}

impl Endianness for BigEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_be()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_be(val)
    }
}

macro_rules! impl_platform_convert {
    ($T:ty) => {
        impl EndianConvert for $T {
            #[inline]
            fn to_be(self) -> $T {
                self.to_be()
            }

            #[inline]
            fn to_le(self) -> $T {
                self.to_le()
            }

            #[inline]
            fn from_be(x: $T) -> $T {
                if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
            }

            #[inline]
            fn from_le(x: $T) -> $T {
                if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
            }
        }
    };
}

impl_platform_convert!(u8);
impl_platform_convert!(u16);
impl_platform_convert!(u32);
impl_platform_convert!(u64);

macro_rules! val_to_buf {
    ($val:ident, $T:expr) => {
        {
            let mut buf = [0; $T];
            for i in 0..buf.len() {
                buf[i] = ($val >> (i * 8)) as u8;
            }
            buf
        }
    };
}

impl<W: Write> WritePodExt for W {
    fn write_u64<T: Endianness>(&mut self, val: u64) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 8);
        self.write_all(&buf)
    }

    fn write_u32<T: Endianness>(&mut self, val: u32) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 4);
        self.write_all(&buf)
    }

    fn write_u16<T: Endianness>(&mut self, val: u16) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 2);
        self.write_all(&buf)
    }

    fn write_u8(&mut self, val: u8) -> io::Result<()> {
        self.write_all(&[val])
    }

    fn write_i64<T: Endianness>(&mut self, val: i64) -> io::Result<()> {
        self.write_u64::<T>(val as u64)
    }

    fn write_i32<T: Endianness>(&mut self, val: i32) -> io::Result<()> {
        self.write_u32::<T>(val as u32)
    }

    fn write_i16<T: Endianness>(&mut self, val: i16) -> io::Result<()> {
        self.write_u16::<T>(val as u16)
    }

    fn write_i8(&mut self, val: i8) -> io::Result<()> {
        self.write_u8(val as u8)
    }

    fn write_f32<T: Endianness>(&mut self, val: f32) -> io::Result<()> {
        let tval: u32 = unsafe { std::mem::transmute::<f32, u32>(val) };
        self.write_u32::<T>(tval)
    }

    fn write_f64<T: Endianness>(&mut self, val: f64) -> io::Result<()> {
        let tval: u64 = unsafe { std::mem::transmute::<f64, u64>(val) };
        self.write_u64::<T>(tval)
    }
}

#[inline]
fn fill_buf<R: Read>(reader: &mut R, buf: &mut [u8]) -> io::Result<()> {
    let mut idx = 0;
    while idx != buf.len() {
        match reader.read(&mut buf[idx..]) {
            Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "Could not read enough bytes")),
            Ok(v) => { idx += v; }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}

macro_rules! buf_to_val {
    ($buf:ident, $T:ty) => {
        {
            let mut val: $T = 0;
            for i in 0..$buf.len() {
                val |= ($buf[i] as $T) << (i * 8);
            }
            val
        }
    };
}

impl<R: Read> ReadPodExt for R {
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64> {
        let buf = &mut [0u8; 8];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u64);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32> {
        let buf = &mut [0u8; 4];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u32);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16> {
        let buf = &mut [0u8; 2];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u16);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u8(&mut self) -> io::Result<u8> {
        let buf = &mut [0u8; 1];
        try!(fill_buf(self, buf));
        Ok(buf[0])
    }
    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64> {
        self.read_u64::<T>().map(|v| v as i64)
    }
    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32> {
        self.read_u32::<T>().map(|v| v as i32)
    }
    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16> {
        self.read_u16::<T>().map(|v| v as i16)
    }
    fn read_i8(&mut self) -> io::Result<i8> {
        self.read_u8().map(|v| v as i8)
    }
    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64> {
        self.read_u64::<T>().map(|v| unsafe { std::mem::transmute::<u64, f64>(v) })
    }
    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32> {
        self.read_u32::<T>().map(|v| unsafe { std::mem::transmute::<u32, f32>(v) })
    }
    fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>> {
        let mut res = vec![0; len];
        try!(fill_buf(self, &mut res));
        Ok(res)
    }
}
<|endoftext|>


<commit_before>//! Whatlang is a Rust library to detect(regonize) natural languages.
//! Apart from it, the library also recognizes scripts (writing system).
//! Every language and script are represented by determined list of enums.
//!
//! # Examples
//!
//! Using `detect` function:
//!
//! ```
//! use whatlang::{detect, Lang, Script};
//!
//! let text = "Ĉu vi ne volas eklerni Esperanton? Bonvolu! Estas unu de la plej bonaj aferoj!";
//! let info = detect(text).unwrap();
//! assert_eq!(info.lang(), Lang::Epo);
//! assert_eq!(info.script(), Script::Latin);
//!
//! // Confidence is in the range from 0 to 1.
//! assert_eq!(info.confidence(), 1.0);
//! assert!(info.is_reliable());
//! ```
//!
//! Using `Detector` with specified blacklist or whitelist:
//!
//! ```
//! use whatlang::{Detector, Lang};
//!
//! let whitelist = vec![Lang::Eng, Lang::Rus];
//!
//! // You can also create detector using with_blacklist function
//! let detector = Detector::with_whitelist(whitelist);
//! let lang = detector.detect_lang("There is no reason not to learn Esperanto.");
//! assert_eq!(lang, Some(Lang::Eng));
//! ```
//!
//!
//! Breaking test (check CI):
//! ```
//! let lang = whatlang::detect_lang("Man soll weiterhin Deutsch lernen").unwrap();
//! assert_eq!(lang, whatlang::Lang::Rus);
//! ```
//!
mod constants;
mod detect;
mod detector;
mod error;
mod info;
mod lang;
mod options;
mod scripts;
mod trigrams;
mod utils;

pub use crate::detector::Detector;
pub use crate::info::Info;
pub use crate::lang::Lang;
pub use crate::options::Options;
pub use crate::scripts::Script;

pub use crate::detect::detect;
pub use crate::detect::detect_lang;
pub use crate::detect::detect_with_options;
pub use crate::scripts::detect_script;
<commit_msg>Revert "Add breaking test"<commit_after>//! Whatlang is a Rust library to detect(regonize) natural languages.
//! Apart from it, the library also recognizes scripts (writing system).
//! Every language and script are represented by determined list of enums.
//!
//! # Examples
//!
//! Using `detect` function:
//!
//! ```
//! use whatlang::{detect, Lang, Script};
//!
//! let text = "Ĉu vi ne volas eklerni Esperanton? Bonvolu! Estas unu de la plej bonaj aferoj!";
//! let info = detect(text).unwrap();
//! assert_eq!(info.lang(), Lang::Epo);
//! assert_eq!(info.script(), Script::Latin);
//!
//! // Confidence is in the range from 0 to 1.
//! assert_eq!(info.confidence(), 1.0);
//! assert!(info.is_reliable());
//! ```
//!
//! Using `Detector` with specified blacklist or whitelist:
//!
//! ```
//! use whatlang::{Detector, Lang};
//!
//! let whitelist = vec![Lang::Eng, Lang::Rus];
//!
//! // You can also create detector using with_blacklist function
//! let detector = Detector::with_whitelist(whitelist);
//! let lang = detector.detect_lang("There is no reason not to learn Esperanto.");
//! assert_eq!(lang, Some(Lang::Eng));
//!
mod constants;
mod detect;
mod detector;
mod error;
mod info;
mod lang;
mod options;
mod scripts;
mod trigrams;
mod utils;

pub use crate::detector::Detector;
pub use crate::info::Info;
pub use crate::lang::Lang;
pub use crate::options::Options;
pub use crate::scripts::Script;

pub use crate::detect::detect;
pub use crate::detect::detect_lang;
pub use crate::detect::detect_with_options;
pub use crate::scripts::detect_script;
<|endoftext|>