<commit_before>//! Windows CRT definitions

pub type c_char = i8;
pub type c_long = i32;
pub type c_ulong = u32;
pub type wchar_t = u16;

pub type clock_t = i32;

cfg_if! {
    if #[cfg(all(target_arch = "x86", target_env = "gnu"))] {
        pub type time_t = i32;
    } else {
        pub type time_t = i64;
    }
}

pub type off_t = i32;
pub type dev_t = u32;
pub type ino_t = u16;
pub enum timezone {}
pub type time64_t = i64;

s! {
    // note this is the struct called stat64 in Windows. Not stat, nor stati64.
    pub struct stat {
        pub st_dev: dev_t,
        pub st_ino: ino_t,
        pub st_mode: u16,
        pub st_nlink: ::c_short,
        pub st_uid: ::c_short,
        pub st_gid: ::c_short,
        pub st_rdev: dev_t,
        pub st_size: i64,
        pub st_atime: time64_t,
        pub st_mtime: time64_t,
        pub st_ctime: time64_t,
    }

    // note that this is called utimbuf64 in Windows
    pub struct utimbuf {
        pub actime: time64_t,
        pub modtime: time64_t,
    }

    pub struct timeval {
        pub tv_sec: c_long,
        pub tv_usec: c_long,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;
pub const RAND_MAX: ::c_int = 32767;
pub const EOF: ::c_int = -1;
pub const SEEK_SET: ::c_int = 0;
pub const SEEK_CUR: ::c_int = 1;
pub const SEEK_END: ::c_int = 2;
pub const _IOFBF: ::c_int = 0;
pub const _IONBF: ::c_int = 4;
pub const _IOLBF: ::c_int = 64;
pub const BUFSIZ: ::c_uint = 512;
pub const FOPEN_MAX: ::c_uint = 20;
pub const FILENAME_MAX: ::c_uint = 260;

cfg_if! {
    if #[cfg(all(target_env = "gnu"))] {
        pub const L_tmpnam: ::c_uint = 14;
        pub const TMP_MAX: ::c_uint = 0x7fff;
    } else if #[cfg(all(target_env = "msvc"))] {
        pub const L_tmpnam: ::c_uint = 260;
        pub const TMP_MAX: ::c_uint = 0x7fff_ffff;
    } else {
        // Unknown target_env
    }
}

pub const O_RDONLY: ::c_int = 0;
pub const O_WRONLY: ::c_int = 1;
pub const O_RDWR: ::c_int = 2;
pub const O_APPEND: ::c_int = 8;
pub const O_CREAT: ::c_int = 256;
pub const O_EXCL: ::c_int = 1024;
pub const O_TEXT: ::c_int = 16384;
pub const O_BINARY: ::c_int = 32768;
pub const O_NOINHERIT: ::c_int = 128;
pub const O_TRUNC: ::c_int = 512;
pub const S_IFCHR: ::c_int = 8192;
pub const S_IFDIR: ::c_int = 16384;
pub const S_IFREG: ::c_int = 32768;
pub const S_IFMT: ::c_int = 61440;
pub const S_IEXEC: ::c_int = 64;
pub const S_IWRITE: ::c_int = 128;
pub const S_IREAD: ::c_int = 256;

pub const LC_ALL: ::c_int = 0;
pub const LC_COLLATE: ::c_int = 1;
pub const LC_CTYPE: ::c_int = 2;
pub const LC_MONETARY: ::c_int = 3;
pub const LC_NUMERIC: ::c_int = 4;
pub const LC_TIME: ::c_int = 5;

#[cfg(target_env = "msvc")] // " if " -- appease style checker
#[link(name = "msvcrt")]
extern {}

extern {
    #[link_name = "_chmod"]
    pub fn chmod(path: *const c_char, mode: ::c_int) -> ::c_int;
    #[link_name = "_wchmod"]
    pub fn wchmod(path: *const wchar_t, mode: ::c_int) -> ::c_int;
    #[link_name = "_mkdir"]
    pub fn mkdir(path: *const c_char) -> ::c_int;
    #[link_name = "_wrmdir"]
    pub fn wrmdir(path: *const wchar_t) -> ::c_int;
    #[link_name = "_fstat64"]
    pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int;
    #[link_name = "_stat64"]
    pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int;
    #[link_name = "_wstat64"]
    pub fn wstat(path: *const wchar_t, buf: *mut stat) -> ::c_int;
    #[link_name = "_wutime64"]
    pub fn wutime(file: *const wchar_t, buf: *mut utimbuf) -> ::c_int;
    #[link_name = "_popen"]
    pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE;
    #[link_name = "_pclose"]
    pub fn pclose(stream: *mut ::FILE) -> ::c_int;
    #[link_name = "_fdopen"]
    pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE;
    #[link_name = "_fileno"]
    pub fn fileno(stream: *mut ::FILE) -> ::c_int;
    #[link_name = "_open"]
    pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int;
    #[link_name = "_wopen"]
    pub fn wopen(path: *const wchar_t, oflag: ::c_int, ...) -> ::c_int;
    #[link_name = "_creat"]
    pub fn creat(path: *const c_char, mode: ::c_int) -> ::c_int;
    #[link_name = "_access"]
    pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int;
    #[link_name = "_chdir"]
    pub fn chdir(dir: *const c_char) -> ::c_int;
    #[link_name = "_close"]
    pub fn close(fd: ::c_int) -> ::c_int;
    #[link_name = "_dup"]
    pub fn dup(fd: ::c_int) -> ::c_int;
    #[link_name = "_dup2"]
    pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int;
    #[link_name = "_execv"]
    pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::intptr_t;
    #[link_name = "_execve"]
    pub fn execve(prog: *const c_char, argv: *const *const c_char,
                  envp: *const *const c_char) -> ::c_int;
    #[link_name = "_execvp"]
    pub fn execvp(c: *const c_char, argv: *const *const c_char) -> ::c_int;
    #[link_name = "_execvpe"]
    pub fn execvpe(c: *const c_char, argv: *const *const c_char,
                   envp: *const *const c_char) -> ::c_int;
    #[link_name = "_getcwd"]
    pub fn getcwd(buf: *mut c_char, size: ::c_int) -> *mut c_char;
    #[link_name = "_getpid"]
    pub fn getpid() -> ::c_int;
    #[link_name = "_isatty"]
    pub fn isatty(fd: ::c_int) -> ::c_int;
    #[link_name = "_lseek"]
    pub fn lseek(fd: ::c_int, offset: c_long, origin: ::c_int) -> c_long;
    #[link_name = "_pipe"]
    pub fn pipe(fds: *mut ::c_int,
                psize: ::c_uint,
                textmode: ::c_int) -> ::c_int;
    #[link_name = "_read"]
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::c_uint) -> ::c_int;
    #[link_name = "_rmdir"]
    pub fn rmdir(path: *const c_char) -> ::c_int;
    #[link_name = "_unlink"]
    pub fn unlink(c: *const c_char) -> ::c_int;
    #[link_name = "_write"]
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::c_uint) -> ::c_int;
    #[link_name = "_commit"]
    pub fn commit(fd: ::c_int) -> ::c_int;
    #[link_name = "_get_osfhandle"]
    pub fn get_osfhandle(fd: ::c_int) -> ::intptr_t;
    #[link_name = "_open_osfhandle"]
    pub fn open_osfhandle(osfhandle: ::intptr_t, flags: ::c_int) -> ::c_int;
    pub fn setlocale(category: ::c_int, locale: *const c_char) -> *mut c_char;
    #[link_name = "_wsetlocale"]
    pub fn wsetlocale(category: ::c_int,
                      locale: *const wchar_t) -> *mut wchar_t;
}
<commit_msg>Auto merge of #395 - lemonrock:windows_posix_errors, r=alexcrichton<commit_after>//! Windows CRT definitions

pub type c_char = i8;
pub type c_long = i32;
pub type c_ulong = u32;
pub type wchar_t = u16;

pub type clock_t = i32;

cfg_if! {
    if #[cfg(all(target_arch = "x86", target_env = "gnu"))] {
        pub type time_t = i32;
    } else {
        pub type time_t = i64;
    }
}

pub type off_t = i32;
pub type dev_t = u32;
pub type ino_t = u16;
pub enum timezone {}
pub type time64_t = i64;

s! {
    // note this is the struct called stat64 in Windows. Not stat, nor stati64.
    pub struct stat {
        pub st_dev: dev_t,
        pub st_ino: ino_t,
        pub st_mode: u16,
        pub st_nlink: ::c_short,
        pub st_uid: ::c_short,
        pub st_gid: ::c_short,
        pub st_rdev: dev_t,
        pub st_size: i64,
        pub st_atime: time64_t,
        pub st_mtime: time64_t,
        pub st_ctime: time64_t,
    }

    // note that this is called utimbuf64 in Windows
    pub struct utimbuf {
        pub actime: time64_t,
        pub modtime: time64_t,
    }

    pub struct timeval {
        pub tv_sec: c_long,
        pub tv_usec: c_long,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;
pub const RAND_MAX: ::c_int = 32767;
pub const EOF: ::c_int = -1;
pub const SEEK_SET: ::c_int = 0;
pub const SEEK_CUR: ::c_int = 1;
pub const SEEK_END: ::c_int = 2;
pub const _IOFBF: ::c_int = 0;
pub const _IONBF: ::c_int = 4;
pub const _IOLBF: ::c_int = 64;
pub const BUFSIZ: ::c_uint = 512;
pub const FOPEN_MAX: ::c_uint = 20;
pub const FILENAME_MAX: ::c_uint = 260;

cfg_if! {
    if #[cfg(all(target_env = "gnu"))] {
        pub const L_tmpnam: ::c_uint = 14;
        pub const TMP_MAX: ::c_uint = 0x7fff;
    } else if #[cfg(all(target_env = "msvc"))] {
        pub const L_tmpnam: ::c_uint = 260;
        pub const TMP_MAX: ::c_uint = 0x7fff_ffff;
    } else {
        // Unknown target_env
    }
}

pub const O_RDONLY: ::c_int = 0;
pub const O_WRONLY: ::c_int = 1;
pub const O_RDWR: ::c_int = 2;
pub const O_APPEND: ::c_int = 8;
pub const O_CREAT: ::c_int = 256;
pub const O_EXCL: ::c_int = 1024;
pub const O_TEXT: ::c_int = 16384;
pub const O_BINARY: ::c_int = 32768;
pub const O_NOINHERIT: ::c_int = 128;
pub const O_TRUNC: ::c_int = 512;
pub const S_IFCHR: ::c_int = 8192;
pub const S_IFDIR: ::c_int = 16384;
pub const S_IFREG: ::c_int = 32768;
pub const S_IFMT: ::c_int = 61440;
pub const S_IEXEC: ::c_int = 64;
pub const S_IWRITE: ::c_int = 128;
pub const S_IREAD: ::c_int = 256;

pub const LC_ALL: ::c_int = 0;
pub const LC_COLLATE: ::c_int = 1;
pub const LC_CTYPE: ::c_int = 2;
pub const LC_MONETARY: ::c_int = 3;
pub const LC_NUMERIC: ::c_int = 4;
pub const LC_TIME: ::c_int = 5;

pub const EPERM: ::c_int = 1;
pub const ENOENT: ::c_int = 2;
pub const ESRCH: ::c_int = 3;
pub const EINTR: ::c_int = 4;
pub const EIO: ::c_int = 5;
pub const ENXIO: ::c_int = 6;
pub const E2BIG: ::c_int = 7;
pub const ENOEXEC: ::c_int = 8;
pub const EBADF: ::c_int = 9;
pub const ECHILD: ::c_int = 10;
pub const EAGAIN: ::c_int = 11;
pub const ENOMEM: ::c_int = 12;
pub const EACCES: ::c_int = 13;
pub const EFAULT: ::c_int = 14;
pub const EBUSY: ::c_int = 16;
pub const EEXIST: ::c_int = 17;
pub const EXDEV: ::c_int = 18;
pub const ENODEV: ::c_int = 19;
pub const ENOTDIR: ::c_int = 20;
pub const EISDIR: ::c_int = 21;
pub const EINVAL: ::c_int = 22;
pub const ENFILE: ::c_int = 23;
pub const EMFILE: ::c_int = 24;
pub const ENOTTY: ::c_int = 25;
pub const EFBIG: ::c_int = 27;
pub const ENOSPC: ::c_int = 28;
pub const ESPIPE: ::c_int = 29;
pub const EROFS: ::c_int = 30;
pub const EMLINK: ::c_int = 31;
pub const EPIPE: ::c_int = 32;
pub const EDOM: ::c_int = 33;
pub const ERANGE: ::c_int = 34;
pub const EDEADLK: ::c_int = 36;
pub const EDEADLOCK: ::c_int = 36;
pub const ENAMETOOLONG: ::c_int = 38;
pub const ENOLCK: ::c_int = 39;
pub const ENOSYS: ::c_int = 40;
pub const ENOTEMPTY: ::c_int = 41;
pub const EILSEQ: ::c_int = 42;
pub const STRUNCATE: ::c_int = 80;

#[cfg(target_env = "msvc")] // " if " -- appease style checker
#[link(name = "msvcrt")]
extern {}

extern {
    #[link_name = "_chmod"]
    pub fn chmod(path: *const c_char, mode: ::c_int) -> ::c_int;
    #[link_name = "_wchmod"]
    pub fn wchmod(path: *const wchar_t, mode: ::c_int) -> ::c_int;
    #[link_name = "_mkdir"]
    pub fn mkdir(path: *const c_char) -> ::c_int;
    #[link_name = "_wrmdir"]
    pub fn wrmdir(path: *const wchar_t) -> ::c_int;
    #[link_name = "_fstat64"]
    pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int;
    #[link_name = "_stat64"]
    pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int;
    #[link_name = "_wstat64"]
    pub fn wstat(path: *const wchar_t, buf: *mut stat) -> ::c_int;
    #[link_name = "_wutime64"]
    pub fn wutime(file: *const wchar_t, buf: *mut utimbuf) -> ::c_int;
    #[link_name = "_popen"]
    pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE;
    #[link_name = "_pclose"]
    pub fn pclose(stream: *mut ::FILE) -> ::c_int;
    #[link_name = "_fdopen"]
    pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE;
    #[link_name = "_fileno"]
    pub fn fileno(stream: *mut ::FILE) -> ::c_int;
    #[link_name = "_open"]
    pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int;
    #[link_name = "_wopen"]
    pub fn wopen(path: *const wchar_t, oflag: ::c_int, ...) -> ::c_int;
    #[link_name = "_creat"]
    pub fn creat(path: *const c_char, mode: ::c_int) -> ::c_int;
    #[link_name = "_access"]
    pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int;
    #[link_name = "_chdir"]
    pub fn chdir(dir: *const c_char) -> ::c_int;
    #[link_name = "_close"]
    pub fn close(fd: ::c_int) -> ::c_int;
    #[link_name = "_dup"]
    pub fn dup(fd: ::c_int) -> ::c_int;
    #[link_name = "_dup2"]
    pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int;
    #[link_name = "_execv"]
    pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::intptr_t;
    #[link_name = "_execve"]
    pub fn execve(prog: *const c_char, argv: *const *const c_char,
                  envp: *const *const c_char) -> ::c_int;
    #[link_name = "_execvp"]
    pub fn execvp(c: *const c_char, argv: *const *const c_char) -> ::c_int;
    #[link_name = "_execvpe"]
    pub fn execvpe(c: *const c_char, argv: *const *const c_char,
                   envp: *const *const c_char) -> ::c_int;
    #[link_name = "_getcwd"]
    pub fn getcwd(buf: *mut c_char, size: ::c_int) -> *mut c_char;
    #[link_name = "_getpid"]
    pub fn getpid() -> ::c_int;
    #[link_name = "_isatty"]
    pub fn isatty(fd: ::c_int) -> ::c_int;
    #[link_name = "_lseek"]
    pub fn lseek(fd: ::c_int, offset: c_long, origin: ::c_int) -> c_long;
    #[link_name = "_pipe"]
    pub fn pipe(fds: *mut ::c_int,
                psize: ::c_uint,
                textmode: ::c_int) -> ::c_int;
    #[link_name = "_read"]
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::c_uint) -> ::c_int;
    #[link_name = "_rmdir"]
    pub fn rmdir(path: *const c_char) -> ::c_int;
    #[link_name = "_unlink"]
    pub fn unlink(c: *const c_char) -> ::c_int;
    #[link_name = "_write"]
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::c_uint) -> ::c_int;
    #[link_name = "_commit"]
    pub fn commit(fd: ::c_int) -> ::c_int;
    #[link_name = "_get_osfhandle"]
    pub fn get_osfhandle(fd: ::c_int) -> ::intptr_t;
    #[link_name = "_open_osfhandle"]
    pub fn open_osfhandle(osfhandle: ::intptr_t, flags: ::c_int) -> ::c_int;
    pub fn setlocale(category: ::c_int, locale: *const c_char) -> *mut c_char;
    #[link_name = "_wsetlocale"]
    pub fn wsetlocale(category: ::c_int,
                      locale: *const wchar_t) -> *mut wchar_t;
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate failure;
#[macro_use]
extern crate failure_derive;
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate assert_cmd;
extern crate serde_json;
extern crate varlink;
extern crate varlink_parser;

use clap::{App, Arg, SubCommand};
use error::{ErrorKind, Result};
use failure::ResultExt;
use org_varlink_resolver::{VarlinkClient, VarlinkClientInterface};
use proxy::{handle, handle_connect};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::path::Path;
use std::str;
use std::sync::{Arc, RwLock};
use varlink::{
    Connection, GetInterfaceDescriptionReply, MethodCall, OrgVarlinkServiceClient,
    OrgVarlinkServiceInterface,
};

use varlink_parser::Varlink;

#[cfg(test)]
mod test;

mod error;
mod org_varlink_resolver;
mod proxy;

fn varlink_format(filename: &str) -> Result<()> {
    let mut buffer = String::new();
    File::open(Path::new(filename))?.read_to_string(&mut buffer)?;

    let v = Varlink::from_string(&buffer)?;
    println!("{}", v.interface);
    Ok(())
}

fn varlink_info(connection: Arc<RwLock<varlink::Connection>>) -> Result<()> {
    let mut call = OrgVarlinkServiceClient::new(connection);
    let info = call.get_info()?;
    println!("Vendor: {}", info.vendor);
    println!("Product: {}", info.product);
    println!("Version: {}", info.version);
    println!("URL: {}", info.url);
    println!("Interfaces:");
    for i in info.interfaces {
        println!("  {}", i)
    }

    Ok(())
}

fn varlink_help(url: &str) -> Result<()> {
    let resolved_address: String;
    let address: &str;
    let interface: &str;

    if let Some(del) = url.rfind('/') {
        address = &url[0..del];
        interface = &url[(del + 1)..];
    } else {
        let conn = Connection::new("unix:/run/org.varlink.resolver")?;
        let mut resolver = VarlinkClient::new(conn);
        address = match resolver.resolve(url.into()).call() {
            Ok(r) => {
                resolved_address = r.address.clone();
                resolved_address.as_ref()
            }
            _ => Err(varlink::Error::from(varlink::ErrorKind::InterfaceNotFound(
                url.into(),
            )))?,
        };
        interface = url;
    }

    if interface.find('.') == None {
        Err(varlink::Error::from(varlink::ErrorKind::InvalidAddress))?
    }

    let conn = Connection::new(address).context(ErrorKind::Connection(address.into()))?;
    let mut call = OrgVarlinkServiceClient::new(conn);
    match call.get_interface_description(interface.to_string())? {
        GetInterfaceDescriptionReply {
            description: Some(desc),
        } => println!("{}", desc),
        _ => {
            return Err(ErrorKind::NoDescription(format!("No description for {}", url)).into());
        }
    };

    Ok(())
}

fn varlink_call(
    url: &str,
    args: Option<&str>,
    more: bool,
    resolver: &str,
    activate: Option<&str>,
    bridge: Option<&str>,
) -> Result<()> {
    let resolved_address: String;
    let address: &str;
    let interface: &str;
    let method: &str;

    let connection = match activate {
        Some(activate) => {
            method = url;
            Connection::with_activate(activate)?
        }
        None => match bridge {
            Some(bridge) => {
                method = url;
                Connection::with_bridge(bridge)?
            }
            None => {
                if let Some(del) = url.rfind('/') {
                    address = &url[0..del];
                    method = &url[(del + 1)..];
                    if method.find('.') == None {
                        return Err(varlink::Error::from(varlink::ErrorKind::InvalidAddress).into());
                    }
                } else {
                    if let Some(del) = url.rfind('.') {
                        interface = &url[0..del];
                        method = url;
                        if method.find('.') == None {
                            return Err(
                                varlink::Error::from(varlink::ErrorKind::InvalidAddress).into()
                            );
                        }
                    } else {
                        return Err(varlink::Error::from(varlink::ErrorKind::InvalidAddress).into());
                    }
                    let conn = Connection::new(resolver)?;
                    let mut resolver = VarlinkClient::new(conn);
                    address = match resolver.resolve(interface.into()).call() {
                        Ok(r) => {
                            resolved_address = r.address.clone();
                            resolved_address.as_ref()
                        }
                        _ => Err(varlink::Error::from(varlink::ErrorKind::InterfaceNotFound(
                            interface.into(),
                        )))?,
                    };
                }
                Connection::with_address(address).context(ErrorKind::Connection(address.into()))?
            }
        },
    };

    let args = match args {
        Some(args) => serde_json::from_str(args).context(ErrorKind::SerdeJsonDe(args.to_string()))?,
        None => serde_json::Value::Null,
    };

    let mut call = MethodCall::<serde_json::Value, serde_json::Value, varlink::Error>::new(
        connection.clone(),
        String::from(method),
        args,
    );

    if !more {
        let reply = call.call()?;
        println!("{}", serde_json::to_string_pretty(&reply)?);
    } else {
        for reply in call.more()? {
            println!("{}", serde_json::to_string_pretty(&reply?)?);
        }
    }

    Ok(())
}

fn varlink_bridge(address: Option<&str>) -> Result<()> {
    let stdin = ::std::io::stdin();
    let stdout = ::std::io::stdout();

    let inbuf =
        unsafe { ::std::io::BufReader::new(::std::fs::File::from_raw_fd(stdin.as_raw_fd())) };
    let outw = unsafe { ::std::fs::File::from_raw_fd(stdout.as_raw_fd()) };

    if let Some(address) = address {
        handle_connect(address, inbuf, outw)?;
    } else {
        handle(inbuf, outw)?;
    }
    Ok(())
}

const VERSION: &str = env!("CARGO_PKG_VERSION");

fn main() -> Result<()> {
    let mut app = App::new("varlink")
        .version(VERSION)
        /*
                .arg(
                    Arg::with_name("timeout")
                        .short("t")
                        .long("timeout")
                        .value_name("SECONDS")
                        .help("time in seconds to wait for a reply")
                        .takes_value(true),
                )
        */
        .arg(
            Arg::with_name("resolver")
                .short("R")
                .long("resolver")
                .value_name("ADDRESS")
                .help("address of the resolver")
                .takes_value(true)
                .required(false)
                .default_value("unix:/run/org.varlink.resolver"),
        )
        .arg(
            Arg::with_name("bridge")
                .short("b")
                .long("bridge")
                .value_name("COMMAND")
                .help("Command to execute and connect to")
                .takes_value(true)
                .required(false)
        )
        .arg(
            Arg::with_name("activate")
                .short("A")
                .long("activate")
                .value_name("COMMAND")
                .help("Service to socket-activate and connect to")
                .long_help("Service to socket-activate and connect to. The temporary UNIX socket \
                address is exported as $VARLINK_ADDRESS.")
                .takes_value(true)
                .required(false)
        )
        .subcommand(
            SubCommand::with_name("bridge")
                .version(VERSION)
                .about("Bridge varlink messages from stdio to services on this machine")
                .long_about(
                    "Bridge varlink messages on stdin and stdout to varlink services on this \
                     machine.",
                )
                .arg(
                    Arg::with_name("connect")
                        .short("C")
                        .long("connect")
                        .value_name("ADDRESS")
                        .help("connect directly to ADDRESS")
                        .required(false)
                        .takes_value(true),
                ),
        )
        .subcommand(
            SubCommand::with_name("call")
                .version(VERSION)
                .about("Call a method")
                .long_about("Call METHOD on INTERFACE at ADDRESS. ARGUMENTS must be valid JSON.")
                .arg(
                    Arg::with_name("more")
                        .short("m")
                        .long("more")
                        .help("wait for multiple method returns if supported"),
                )
                .arg(
                    Arg::with_name("METHOD")
                        .value_name("[ADDRESS/]INTERFACE.METHOD")
                        .required(true),
                )
                .arg(Arg::with_name("ARGUMENTS").required(false)),
        )
        .subcommand(
            SubCommand::with_name("format")
                .version(VERSION)
                .about("Format a varlink service file")
                .arg(
                    Arg::with_name("FILE")
                        .required(true)
                        .help("The varlink interface definition file to format"),
                ),
        )
        .subcommand(
            SubCommand::with_name("info")
                .version(VERSION)
                .about("Print information about a service")
                .long_about("Prints information about the service running at ADDRESS.")
                .arg(Arg::with_name("ADDRESS").required(false)),
        )
        .subcommand(
            SubCommand::with_name("help")
                .version(VERSION)
                .about("Print interface description or service information")
                .long_about("Prints information about INTERFACE.")
                .arg(
                    Arg::with_name("INTERFACE")
                        .value_name("[ADDRESS/]INTERFACE")
                        .required(true),
                ),
        )
        .subcommand(
            SubCommand::with_name("resolve")
                .version(VERSION)
                .about("Resolve an interface name to a varlink address")
                .long_about("Resolve INTERFACE to the varlink address that implements it.")
                .arg(Arg::with_name("INTERFACE").required(true)),
        )
        .subcommand(
            SubCommand::with_name("completions")
                .version(VERSION)
                .about("Generates completion scripts for your shell")
                .arg(
                    Arg::with_name("SHELL")
                        .required(true)
                        .possible_values(&["bash", "fish", "zsh"])
                        .help("The shell to generate the script for"),
                ),
        );
    let matches = app.clone().get_matches();
    let resolver = matches.value_of("resolver").unwrap();
    let bridge = matches.value_of("bridge");
    let activate = matches.value_of("activate");

    match matches.subcommand() {
        ("completions", Some(sub_matches)) => {
            let shell = sub_matches.value_of("SHELL").unwrap();
            app.gen_completions_to("varlink", shell.parse().unwrap(), &mut io::stdout());
        }
        ("format", Some(sub_matches)) => {
            let filename = sub_matches.value_of("FILE").unwrap();
            varlink_format(filename)?
        }
        ("info", Some(sub_matches)) => {
            let connection = match activate {
                Some(activate) => Connection::with_activate(activate)?,
                None => match bridge {
                    Some(bridge) => Connection::with_bridge(bridge)?,
                    None => match sub_matches.value_of("ADDRESS") {
                        Some(address) => Connection::with_address(address)?,
                        None => {
                            app.print_help().context(ErrorKind::Argument)?;
                            println!();
                            return Err(
                                ErrorKind::Connection("No ADDRESS or activation".into()).into()
                            );
                        }
                    },
                },
            };
            varlink_info(connection)?
        }
        ("bridge", Some(sub_matches)) => {
            let address = sub_matches.value_of("connect");
            varlink_bridge(address)?
        }
        ("help", Some(sub_matches)) => {
            let interface = sub_matches.value_of("INTERFACE").unwrap();
            varlink_help(interface)?
        }
        ("call", Some(sub_matches)) => {
            let method = sub_matches.value_of("METHOD").unwrap();
            let args = sub_matches.value_of("ARGUMENTS");
            let more = sub_matches.is_present("more");
            varlink_call(method, args, more, resolver, activate, bridge)?
        }
        (_, _) => {
            app.print_help().context(ErrorKind::Argument)?;
            println!();
        }
    }
    Ok(())
}
<commit_msg>varlink-cli: handle "help" and "info" with --activate and --bridge<commit_after>extern crate clap;
extern crate failure;
#[macro_use]
extern crate failure_derive;
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate assert_cmd;
extern crate serde_json;
extern crate varlink;
extern crate varlink_parser;

use clap::{App, Arg, SubCommand};
use error::{ErrorKind, Result};
use failure::ResultExt;
use org_varlink_resolver::{VarlinkClient, VarlinkClientInterface};
use proxy::{handle, handle_connect};
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::path::Path;
use std::str;
use varlink::{
    Connection, GetInterfaceDescriptionReply, MethodCall, OrgVarlinkServiceClient,
    OrgVarlinkServiceInterface,
};

use varlink_parser::Varlink;

#[cfg(test)]
mod test;

mod error;
mod org_varlink_resolver;
mod proxy;

fn varlink_format(filename: &str) -> Result<()> {
    let mut buffer = String::new();
    File::open(Path::new(filename))?.read_to_string(&mut buffer)?;

    let v = Varlink::from_string(&buffer)?;
    println!("{}", v.interface);
    Ok(())
}

fn varlink_info(
    address: Option<&str>,
    resolver: &str,
    activate: Option<&str>,
    bridge: Option<&str>,
) -> Result<()> {
    let connection = match activate {
        Some(activate) => Connection::with_activate(activate)?,
        None => match bridge {
            Some(bridge) => Connection::with_bridge(bridge)?,
            None => {
                let address = address.unwrap();
                if address.rfind(':').is_none() {
                    let conn = Connection::new(resolver)?;
                    let mut resolver = VarlinkClient::new(conn);
                    let address = match resolver.resolve(address.into()).call() {
                        Ok(r) => r.address.clone(),
                        _ => Err(varlink::Error::from(varlink::ErrorKind::InterfaceNotFound(
                            address.into(),
                        )))?,
                    };
                    Connection::with_address(&address)?
                } else {
                    Connection::with_address(&address)?
                }
            }
        },
    };
    let mut call = OrgVarlinkServiceClient::new(connection);
    let info = call.get_info()?;
    println!("Vendor: {}", info.vendor);
    println!("Product: {}", info.product);
    println!("Version: {}", info.version);
    println!("URL: {}", info.url);
    println!("Interfaces:");
    for i in info.interfaces {
        println!("  {}", i)
    }

    Ok(())
}

fn varlink_help(
    url: &str,
    resolver: &str,
    activate: Option<&str>,
    bridge: Option<&str>,
) -> Result<()> {
    let address: &str;
    let interface: &str;

    let connection = if let Some(del) = url.rfind('/') {
        address = &url[0..del];
        interface = &url[(del + 1)..];
        Connection::with_address(&address)?
    } else {
        interface = url;
        match activate {
            Some(activate) => Connection::with_activate(activate)?,
            None => match bridge {
                Some(bridge) => Connection::with_bridge(bridge)?,
                None => {
                    let conn = Connection::new(resolver)?;
                    let mut resolver = VarlinkClient::new(conn);
                    let address = match resolver.resolve(interface.into()).call() {
                        Ok(r) => r.address.clone(),
                        _ => Err(varlink::Error::from(varlink::ErrorKind::InterfaceNotFound(
                            interface.into(),
                        )))?,
                    };
                    Connection::with_address(&address)?
                }
            },
        }
    };

    if interface.find('.') == None {
        Err(varlink::Error::from(varlink::ErrorKind::InvalidAddress))?
    }

    let mut call = OrgVarlinkServiceClient::new(connection);
    match call.get_interface_description(interface.to_string())? {
        GetInterfaceDescriptionReply {
            description: Some(desc),
        } => println!("{}", desc),
        _ => {
            return Err(ErrorKind::NoDescription(format!("No description for {}", url)).into());
        }
    };

    Ok(())
}

fn varlink_call(
    url: &str,
    args: Option<&str>,
    more: bool,
    resolver: &str,
    activate: Option<&str>,
    bridge: Option<&str>,
) -> Result<()> {
    let resolved_address: String;
    let address: &str;
    let interface: &str;
    let method: &str;

    let connection = match activate {
        Some(activate) => {
            method = url;
            Connection::with_activate(activate)?
        }
        None => match bridge {
            Some(bridge) => {
                method = url;
                Connection::with_bridge(bridge)?
            }
            None => {
                if let Some(del) = url.rfind('/') {
                    address = &url[0..del];
                    method = &url[(del + 1)..];
                    if method.find('.') == None {
                        return Err(varlink::Error::from(varlink::ErrorKind::InvalidAddress).into());
                    }
                } else {
                    if let Some(del) = url.rfind('.') {
                        interface = &url[0..del];
                        method = url;
                        if method.find('.') == None {
                            return Err(
                                varlink::Error::from(varlink::ErrorKind::InvalidAddress).into()
                            );
                        }
                    } else {
                        return Err(varlink::Error::from(varlink::ErrorKind::InvalidAddress).into());
                    }
                    let conn = Connection::new(resolver)?;
                    let mut resolver = VarlinkClient::new(conn);
                    address = match resolver.resolve(interface.into()).call() {
                        Ok(r) => {
                            resolved_address = r.address.clone();
                            resolved_address.as_ref()
                        }
                        _ => Err(varlink::Error::from(varlink::ErrorKind::InterfaceNotFound(
                            interface.into(),
                        )))?,
                    };
                }
                Connection::with_address(address).context(ErrorKind::Connection(address.into()))?
            }
        },
    };

    let args = match args {
        Some(args) => serde_json::from_str(args).context(ErrorKind::SerdeJsonDe(args.to_string()))?,
        None => serde_json::Value::Null,
    };

    let mut call = MethodCall::<serde_json::Value, serde_json::Value, varlink::Error>::new(
        connection.clone(),
        String::from(method),
        args,
    );

    if !more {
        let reply = call.call()?;
        println!("{}", serde_json::to_string_pretty(&reply)?);
    } else {
        for reply in call.more()? {
            println!("{}", serde_json::to_string_pretty(&reply?)?);
        }
    }

    Ok(())
}

fn varlink_bridge(address: Option<&str>) -> Result<()> {
    let stdin = ::std::io::stdin();
    let stdout = ::std::io::stdout();

    let inbuf =
        unsafe { ::std::io::BufReader::new(::std::fs::File::from_raw_fd(stdin.as_raw_fd())) };
    let outw = unsafe { ::std::fs::File::from_raw_fd(stdout.as_raw_fd()) };

    if let Some(address) = address {
        handle_connect(address, inbuf, outw)?;
    } else {
        handle(inbuf, outw)?;
    }
    Ok(())
}

const VERSION: &str = env!("CARGO_PKG_VERSION");

fn main() -> Result<()> {
    let mut app = App::new("varlink")
        .version(VERSION)
        /*
                .arg(
                    Arg::with_name("timeout")
                        .short("t")
                        .long("timeout")
                        .value_name("SECONDS")
                        .help("time in seconds to wait for a reply")
                        .takes_value(true),
                )
        */
        .arg(
            Arg::with_name("resolver")
                .short("R")
                .long("resolver")
                .value_name("ADDRESS")
                .help("address of the resolver")
                .takes_value(true)
                .required(false)
                .default_value("unix:/run/org.varlink.resolver"),
        )
        .arg(
            Arg::with_name("bridge")
                .short("b")
                .long("bridge")
                .value_name("COMMAND")
                .help("Command to execute and connect to")
                .takes_value(true)
                .required(false)
        )
        .arg(
            Arg::with_name("activate")
                .short("A")
                .long("activate")
                .value_name("COMMAND")
                .help("Service to socket-activate and connect to")
                .long_help("Service to socket-activate and connect to. The temporary UNIX socket \
                address is exported as $VARLINK_ADDRESS.")
                .takes_value(true)
                .required(false)
        )
        .subcommand(
            SubCommand::with_name("bridge")
                .version(VERSION)
                .about("Bridge varlink messages from stdio to services on this machine")
                .long_about(
                    "Bridge varlink messages on stdin and stdout to varlink services on this \
                     machine.",
                )
                .arg(
                    Arg::with_name("connect")
                        .short("C")
                        .long("connect")
                        .value_name("ADDRESS")
                        .help("connect directly to ADDRESS")
                        .required(false)
                        .takes_value(true),
                ),
        )
        .subcommand(
            SubCommand::with_name("call")
                .version(VERSION)
                .about("Call a method")
                .long_about("Call METHOD on INTERFACE at ADDRESS. ARGUMENTS must be valid JSON.")
                .arg(
                    Arg::with_name("more")
                        .short("m")
                        .long("more")
                        .help("wait for multiple method returns if supported"),
                )
                .arg(
                    Arg::with_name("METHOD")
                        .value_name("[ADDRESS/]INTERFACE.METHOD")
                        .required(true),
                )
                .arg(Arg::with_name("ARGUMENTS").required(false)),
        )
        .subcommand(
            SubCommand::with_name("format")
                .version(VERSION)
                .about("Format a varlink service file")
                .arg(
                    Arg::with_name("FILE")
                        .required(true)
                        .help("The varlink interface definition file to format"),
                ),
        )
        .subcommand(
            SubCommand::with_name("info")
                .version(VERSION)
                .about("Print information about a service")
                .long_about("Prints information about the service running at ADDRESS.")
                .arg(Arg::with_name("ADDRESS").required(false)),
        )
        .subcommand(
            SubCommand::with_name("help")
                .version(VERSION)
                .about("Print interface description or service information")
                .long_about("Prints information about INTERFACE.")
                .arg(
                    Arg::with_name("INTERFACE")
                        .value_name("[ADDRESS/]INTERFACE")
                        .required(true),
                ),
        )
        .subcommand(
            SubCommand::with_name("resolve")
                .version(VERSION)
                .about("Resolve an interface name to a varlink address")
                .long_about("Resolve INTERFACE to the varlink address that implements it.")
                .arg(Arg::with_name("INTERFACE").required(true)),
        )
        .subcommand(
            SubCommand::with_name("completions")
                .version(VERSION)
                .about("Generates completion scripts for your shell")
                .arg(
                    Arg::with_name("SHELL")
                        .required(true)
                        .possible_values(&["bash", "fish", "zsh"])
                        .help("The shell to generate the script for"),
                ),
        );
    let matches = app.clone().get_matches();
    let resolver = matches.value_of("resolver").unwrap();
    let bridge = matches.value_of("bridge");
    let activate = matches.value_of("activate");

    match matches.subcommand() {
        ("completions", Some(sub_matches)) => {
            let shell = sub_matches.value_of("SHELL").unwrap();
            app.gen_completions_to("varlink", shell.parse().unwrap(), &mut io::stdout());
        }
        ("format", Some(sub_matches)) => {
            let filename = sub_matches.value_of("FILE").unwrap();
            varlink_format(filename)?
        }
        ("info", Some(sub_matches)) => {
            let address = sub_matches.value_of("ADDRESS");
            if address.is_none() && activate.is_none() && bridge.is_none() {
                app.print_help().context(ErrorKind::Argument)?;
                println!();
                return Err(
                    ErrorKind::Connection("No ADDRESS or activation or bridge".into()).into(),
                );
            }

            varlink_info(address, resolver, activate, bridge)?
        }
        ("bridge", Some(sub_matches)) => {
            let address = sub_matches.value_of("connect");
            varlink_bridge(address)?
        }
        ("help", Some(sub_matches)) => {
            let interface = sub_matches.value_of("INTERFACE").unwrap();
            varlink_help(interface, resolver, activate, bridge)?
        }
        ("call", Some(sub_matches)) => {
            let method = sub_matches.value_of("METHOD").unwrap();
            let args = sub_matches.value_of("ARGUMENTS");
            let more = sub_matches.is_present("more");
            varlink_call(method, args, more, resolver, activate, bridge)?
        }
        (_, _) => {
            app.print_help().context(ErrorKind::Argument)?;
            println!();
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use v256::*;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Add packed double-precision (64-bit) floating-point elements
/// in `a` and `b`.
#[inline(always)]
#[target_feature = "+avx"]
pub fn _mm256_add_pd(a: f64x4, b: f64x4) -> f64x4 {
    a + b
}

/// Add packed single-precision (32-bit) floating-point elements in `a` and `b`.
#[inline(always)]
#[target_feature = "+avx"]
pub fn _mm256_add_ps(a: f32x8, b: f32x8) -> f32x8 {
    a + b
}

/// Alternatively add and subtract packed double-precision (64-bit)
/// floating-point elements in `a` to/from packed elements in `b`.
#[inline(always)]
#[target_feature = "+avx"]
pub fn _mm256_addsub_pd(a: f64x4, b: f64x4) -> f64x4 {
    unsafe { addsubpd256(a, b) }
}

/// Subtract packed double-precision (64-bit) floating-point elements in `b`
/// from packed elements in `a`.
#[inline(always)]
#[target_feature = "+avx"]
#[cfg_attr(test, assert_instr(vsubpd))]
pub fn _mm256_sub_pd(a: f64x4, b: f64x4) -> f64x4 {
    a - b
}

/// Subtract packed single-precision (32-bit) floating-point elements in `b`
/// from packed elements in `a`.
#[inline(always)]
#[target_feature = "+avx"]
#[cfg_attr(test, assert_instr(vsubps))]
pub fn _mm256_sub_ps(a: f32x8, b: f32x8) -> f32x8 {
    a - b
}

/// Round packed double-precision (64-bit) floating point elements in `a`
/// according to the flag `b`. The value of `b` may be as follows:
/// 0x00: Round to the nearest whole number.
/// 0x01: Round down, toward negative infinity.
/// 0x02: Round up, toward positive infinity.
/// 0x03: Truncate the values.
/// For a few additional values options, check the LLVM docs:
/// https://github.com/llvm-mirror/clang/blob/dcd8d797b20291f1a6b3e0ddda085aa2bbb382a8/lib/Headers/avxintrin.h#L382
#[inline(always)]
#[target_feature = "+avx"]
// #[cfg_attr(test, assert_instr(vroundpd))]
// TODO: Replace with assert_expanded_instr https://github.com/rust-lang-nursery/stdsimd/issues/49
pub fn _mm256_round_pd(a: f64x4, b: i32) -> f64x4 {
    macro_rules! call {
        ($imm8:expr) => {
            unsafe { roundpd256(a, $imm8) }
        }
    }
    constify_imm8!(b, call)
}

/// Round packed double-precision (64-bit) floating point elements in `a` toward
/// positive infinity.
#[inline(always)]
#[target_feature = "+avx"]
// #[cfg_attr(test, assert_instr(vroundpd))]
// TODO: Replace with assert_expanded_instr https://github.com/rust-lang-nursery/stdsimd/issues/49
pub fn _mm256_ceil_pd(a: f64x4) -> f64x4 {
    unsafe { roundpd256(a, 0x02) }
}

/// Round packed double-precision (64-bit) floating point elements in `a` toward
/// negative infinity.
#[inline(always)]
#[target_feature = "+avx"]
// #[cfg_attr(test, assert_instr(vroundpd))]
// TODO: Replace with assert_expanded_instr https://github.com/rust-lang-nursery/stdsimd/issues/49
pub fn _mm256_floor_pd(a: f64x4) -> f64x4 {
    unsafe { roundpd256(a, 0x01) }
}

/// LLVM intrinsics used in the above functions
#[allow(improper_ctypes)]
extern "C" {
    #[link_name = "llvm.x86.avx.addsub.pd.256"]
    fn addsubpd256(a: f64x4, b: f64x4) -> f64x4;
    #[link_name = "llvm.x86.avx.round.pd.256"]
    fn roundpd256(a: f64x4, b: i32) -> f64x4;
}

#[cfg(all(test, target_feature = "avx", any(target_arch = "x86", target_arch = "x86_64")))]
mod tests {
    use stdsimd_test::simd_test;

    use v256::*;
    use x86::avx;

    #[simd_test = "avx"]
    fn _mm256_add_pd() {
        let a = f64x4::new(1.0, 2.0, 3.0, 4.0);
        let b = f64x4::new(5.0, 6.0, 7.0, 8.0);
        let r = avx::_mm256_add_pd(a, b);
        let e = f64x4::new(6.0, 8.0, 10.0, 12.0);
        assert_eq!(r, e);
    }

    #[simd_test = "avx"]
    fn _mm256_add_ps() {
        let a = f32x8::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
        let b = f32x8::new(9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
        let r = avx::_mm256_add_ps(a, b);
        let e = f32x8::new(10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0);
        assert_eq!(r, e);
    }

    #[simd_test = "avx"]
    fn _mm256_addsub_pd() {
        let a = f64x4::new(1.0, 2.0, 3.0, 4.0);
        let b = f64x4::new(5.0, 6.0, 7.0, 8.0);
        let r = avx::_mm256_addsub_pd(a, b);
        let e = f64x4::new(-4.0,8.0,-4.0,12.0);
        assert_eq!(r, e);
    }

    #[test]
    #[target_feature = "+avx"]
    fn _mm256_sub_pd() {
        let a = f64x4::new(1.0, 2.0, 3.0, 4.0);
        let b = f64x4::new(5.0, 6.0, 7.0, 8.0);
        let r = avx::_mm256_sub_pd(a, b);
        let e = f64x4::new(-4.0,-4.0,-4.0,-4.0);
        assert_eq!(r, e);
    }

    #[test]
    #[target_feature = "+avx"]
    fn _mm256_sub_ps() {
        let a = f32x8::new(1.0, 2.0, 3.0, 4.0, -1.0, -2.0, -3.0, -4.0);
        let b = f32x8::new(5.0, 6.0, 7.0, 8.0, 3.0, 2.0, 1.0, 0.0);
        let r = avx::_mm256_sub_ps(a, b);
        let e = f32x8::new(-4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0);
        assert_eq!(r, e);
    }

    #[test]
    #[target_feature = "+avx"]
    pub fn _mm256_round_pd() {
        let a = f64x4::new(1.55, 2.2, 3.99, -1.2);
        let result_closest = avx::_mm256_round_pd(a, 0b00000000);
        let result_down = avx::_mm256_round_pd(a, 0b00000001);
        let result_up = avx::_mm256_round_pd(a, 0b00000010);
        let expected_closest = f64x4::new(2.0, 2.0, 4.0, -1.0);
        let expected_down = f64x4::new(1.0, 2.0, 3.0, -2.0);
        let expected_up = f64x4::new(2.0, 3.0, 4.0, -1.0);
        assert_eq!(result_closest, expected_closest);
        assert_eq!(result_down, expected_down);
        assert_eq!(result_up, expected_up);
    }

    #[test]
    #[target_feature = "+avx"]
    pub fn _mm256_floor_pd() {
        let a = f64x4::new(1.55, 2.2, 3.99, -1.2);
        let result_down = avx::_mm256_floor_pd(a);
        let expected_down = f64x4::new(1.0, 2.0, 3.0, -2.0);
        assert_eq!(result_down, expected_down);
    }

    #[test]
    #[target_feature = "+avx"]
    pub fn _mm256_ceil_pd() {
        let a = f64x4::new(1.55, 2.2, 3.99, -1.2);
        let result_up = avx::_mm256_ceil_pd(a, );
        let expected_up = f64x4::new(2.0, 3.0, 4.0, -1.0);
        assert_eq!(result_up, expected_up);
    }
}
<commit_msg>Add assert_instr to the rest of avx.rs<commit_after>use v256::*;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Add packed double-precision (64-bit) floating-point elements
/// in `a` and `b`.
#[inline(always)]
#[target_feature = "+avx"]
#[cfg_attr(test, assert_instr(vaddpd))]
pub fn _mm256_add_pd(a: f64x4, b: f64x4) -> f64x4 {
    a + b
}

/// Add packed single-precision (32-bit) floating-point elements in `a` and `b`.
#[inline(always)]
#[target_feature = "+avx"]
#[cfg_attr(test, assert_instr(vaddps))]
pub fn _mm256_add_ps(a: f32x8, b: f32x8) -> f32x8 {
    a + b
}

/// Alternatively add and subtract packed double-precision (64-bit)
/// floating-point elements in `a` to/from packed elements in `b`.
#[inline(always)]
#[target_feature = "+avx"]
#[cfg_attr(test, assert_instr(vaddsubpd))]
pub fn _mm256_addsub_pd(a: f64x4, b: f64x4) -> f64x4 {
    unsafe { addsubpd256(a, b) }
}

/// Subtract packed double-precision (64-bit) floating-point elements in `b`
/// from packed elements in `a`.
#[inline(always)]
#[target_feature = "+avx"]
#[cfg_attr(test, assert_instr(vsubpd))]
pub fn _mm256_sub_pd(a: f64x4, b: f64x4) -> f64x4 {
    a - b
}

/// Subtract packed single-precision (32-bit) floating-point elements in `b`
/// from packed elements in `a`.
#[inline(always)]
#[target_feature = "+avx"]
#[cfg_attr(test, assert_instr(vsubps))]
pub fn _mm256_sub_ps(a: f32x8, b: f32x8) -> f32x8 {
    a - b
}

/// Round packed double-precision (64-bit) floating point elements in `a`
/// according to the flag `b`. The value of `b` may be as follows:
/// 0x00: Round to the nearest whole number.
/// 0x01: Round down, toward negative infinity.
/// 0x02: Round up, toward positive infinity.
/// 0x03: Truncate the values.
/// For a few additional values options, check the LLVM docs:
/// https://github.com/llvm-mirror/clang/blob/dcd8d797b20291f1a6b3e0ddda085aa2bbb382a8/lib/Headers/avxintrin.h#L382
#[inline(always)]
#[target_feature = "+avx"]
// #[cfg_attr(test, assert_instr(vroundpd))]
// TODO: Replace with assert_expanded_instr https://github.com/rust-lang-nursery/stdsimd/issues/49
pub fn _mm256_round_pd(a: f64x4, b: i32) -> f64x4 {
    macro_rules! call {
        ($imm8:expr) => {
            unsafe { roundpd256(a, $imm8) }
        }
    }
    constify_imm8!(b, call)
}

/// Round packed double-precision (64-bit) floating point elements in `a` toward
/// positive infinity.
#[inline(always)]
#[target_feature = "+avx"]
// #[cfg_attr(test, assert_instr(vroundpd))]
// TODO: Replace with assert_expanded_instr https://github.com/rust-lang-nursery/stdsimd/issues/49
pub fn _mm256_ceil_pd(a: f64x4) -> f64x4 {
    unsafe { roundpd256(a, 0x02) }
}

/// Round packed double-precision (64-bit) floating point elements in `a` toward
/// negative infinity.
#[inline(always)]
#[target_feature = "+avx"]
// #[cfg_attr(test, assert_instr(vroundpd))]
// TODO: Replace with assert_expanded_instr https://github.com/rust-lang-nursery/stdsimd/issues/49
pub fn _mm256_floor_pd(a: f64x4) -> f64x4 {
    unsafe { roundpd256(a, 0x01) }
}

/// LLVM intrinsics used in the above functions
#[allow(improper_ctypes)]
extern "C" {
    #[link_name = "llvm.x86.avx.addsub.pd.256"]
    fn addsubpd256(a: f64x4, b: f64x4) -> f64x4;
    #[link_name = "llvm.x86.avx.round.pd.256"]
    fn roundpd256(a: f64x4, b: i32) -> f64x4;
}

#[cfg(all(test, target_feature = "avx", any(target_arch = "x86", target_arch = "x86_64")))]
mod tests {
    use stdsimd_test::simd_test;

    use v256::*;
    use x86::avx;

    #[simd_test = "avx"]
    fn _mm256_add_pd() {
        let a = f64x4::new(1.0, 2.0, 3.0, 4.0);
        let b = f64x4::new(5.0, 6.0, 7.0, 8.0);
        let r = avx::_mm256_add_pd(a, b);
        let e = f64x4::new(6.0, 8.0, 10.0, 12.0);
        assert_eq!(r, e);
    }

    #[simd_test = "avx"]
    fn _mm256_add_ps() {
        let a = f32x8::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
        let b = f32x8::new(9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
        let r = avx::_mm256_add_ps(a, b);
        let e = f32x8::new(10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0);
        assert_eq!(r, e);
    }

    #[simd_test = "avx"]
    fn _mm256_addsub_pd() {
        let a = f64x4::new(1.0, 2.0, 3.0, 4.0);
        let b = f64x4::new(5.0, 6.0, 7.0, 8.0);
        let r = avx::_mm256_addsub_pd(a, b);
        let e = f64x4::new(-4.0,8.0,-4.0,12.0);
        assert_eq!(r, e);
    }

    #[test]
    #[target_feature = "+avx"]
    fn _mm256_sub_pd() {
        let a = f64x4::new(1.0, 2.0, 3.0, 4.0);
        let b = f64x4::new(5.0, 6.0, 7.0, 8.0);
        let r = avx::_mm256_sub_pd(a, b);
        let e = f64x4::new(-4.0,-4.0,-4.0,-4.0);
        assert_eq!(r, e);
    }

    #[test]
    #[target_feature = "+avx"]
    fn _mm256_sub_ps() {
        let a = f32x8::new(1.0, 2.0, 3.0, 4.0, -1.0, -2.0, -3.0, -4.0);
        let b = f32x8::new(5.0, 6.0, 7.0, 8.0, 3.0, 2.0, 1.0, 0.0);
        let r = avx::_mm256_sub_ps(a, b);
        let e = f32x8::new(-4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0);
        assert_eq!(r, e);
    }

    #[test]
    #[target_feature = "+avx"]
    pub fn _mm256_round_pd() {
        let a = f64x4::new(1.55, 2.2, 3.99, -1.2);
        let result_closest = avx::_mm256_round_pd(a, 0b00000000);
        let result_down = avx::_mm256_round_pd(a, 0b00000001);
        let result_up = avx::_mm256_round_pd(a, 0b00000010);
        let expected_closest = f64x4::new(2.0, 2.0, 4.0, -1.0);
        let expected_down = f64x4::new(1.0, 2.0, 3.0, -2.0);
        let expected_up = f64x4::new(2.0, 3.0, 4.0, -1.0);
        assert_eq!(result_closest, expected_closest);
        assert_eq!(result_down, expected_down);
        assert_eq!(result_up, expected_up);
    }

    #[test]
    #[target_feature = "+avx"]
    pub fn _mm256_floor_pd() {
        let a = f64x4::new(1.55, 2.2, 3.99, -1.2);
        let result_down = avx::_mm256_floor_pd(a);
        let expected_down = f64x4::new(1.0, 2.0, 3.0, -2.0);
        assert_eq!(result_down, expected_down);
    }

    #[test]
    #[target_feature = "+avx"]
    pub fn _mm256_ceil_pd() {
        let a = f64x4::new(1.55, 2.2, 3.99, -1.2);
        let result_up = avx::_mm256_ceil_pd(a, );
        let expected_up = f64x4::new(2.0, 3.0, 4.0, -1.0);
        assert_eq!(result_up, expected_up);
    }
}
<|endoftext|>


<commit_before>extern crate ascii;

use ascii::{Ascii, AsciiStr, AsciiString, AsciiCast, OwnedAsciiCast};

#[test]
fn ascii_vec() {
    let test = &[40_u8, 32, 59];
    let b = AsciiStr::from_bytes(test).unwrap();
    assert_eq!(test.to_ascii().unwrap(), b);
    assert_eq!("( ;".to_ascii().unwrap(), b);
    let v = vec![40_u8, 32, 59];
    assert_eq!(v.to_ascii().unwrap(), b);
    assert_eq!("( ;".to_string().to_ascii().unwrap(), b);
}

#[test]
fn opt() {
    assert_eq!("zoä华".to_ascii(), Err(()));

    let test1 = &[127_u8, 128, 255];
    assert_eq!(test1.to_ascii(), Err(()));

    let v = [40_u8, 32, 59];
    let v1 = AsciiStr::from_bytes(&v).unwrap();
    assert_eq!(v.to_ascii(), Ok(v1));
    let v = [127_u8, 128, 255];
    assert_eq!(v.to_ascii(), Err(()));

    let v = "( ;";
    assert_eq!(v.to_ascii(), Ok(v1));
    assert_eq!("zoä华".to_ascii(), Err(()));

    let v1 = AsciiString::from_bytes(&[40_u8, 32, 59][..]).unwrap();
    assert_eq!(vec![40_u8, 32, 59].into_ascii(), Ok(v1));
    assert_eq!(vec![127_u8, 128, 255].into_ascii(), Err(vec![127_u8, 128, 255]));

    let v1 = AsciiString::from_bytes(&[40_u8, 32, 59][..]).unwrap();
    assert_eq!("( ;".to_string().into_ascii(), Ok(v1));
    assert_eq!("zoä华".to_string().into_ascii(), Err("zoä华".to_string()));
}

#[test]
fn compare_ascii_string_ascii_str() {
    let v = b"abc";
    let ascii_string = AsciiString::from_bytes(&v[..]).unwrap();
    let ascii_str = AsciiStr::from_bytes(v).unwrap();
    assert!(ascii_string == ascii_str);
    assert!(ascii_str == ascii_string);
}

#[test]
fn compare_ascii_string_string() {
    let v = b"abc";
    let string = String::from_utf8(v.to_vec()).unwrap();
    let ascii_string = AsciiString::from_bytes(&v[..]).unwrap();
    assert!(string == ascii_string);
    assert!(ascii_string == string);
}

#[test]
fn compare_ascii_str_string() {
    let v = b"abc";
    let string = String::from_utf8(v.to_vec()).unwrap();
    let ascii_str = AsciiStr::from_bytes(&v[..]).unwrap();
    assert!(string == ascii_str);
    assert!(ascii_str == string);
}

#[test]
fn compare_ascii_string_str() {
    let v = b"abc";
    let sstr = ::std::str::from_utf8(v).unwrap();
    let ascii_string = AsciiString::from_bytes(&v[..]).unwrap();
    assert!(sstr == ascii_string);
    assert!(ascii_string == sstr);
}

#[test]
fn compare_ascii_str_str() {
    let v = b"abc";
    let sstr = ::std::str::from_utf8(v).unwrap();
    let ascii_str = AsciiStr::from_bytes(v).unwrap();
    assert!(sstr == ascii_str);
    assert!(ascii_str == sstr);
}

#[test]
fn compare_ascii_str_slice() {
    let b = b"abc".to_ascii().unwrap();
    let c = b"ab".to_ascii().unwrap();
    assert_eq!(&b[..2], &c[..]);
    assert_eq!(c[1].as_char(), 'b');
}

#[test]
fn compare_ascii_string_slice() {
    let b = AsciiString::from_bytes("abc").unwrap();
    let c = AsciiString::from_bytes("ab").unwrap();
    assert_eq!(&b[..2], &c[..]);
    assert_eq!(c[1].as_char(), 'b');
}
<commit_msg>Remove an unused import<commit_after>extern crate ascii;

use ascii::{AsciiStr, AsciiString, AsciiCast, OwnedAsciiCast};

#[test]
fn ascii_vec() {
    let test = &[40_u8, 32, 59];
    let b = AsciiStr::from_bytes(test).unwrap();
    assert_eq!(test.to_ascii().unwrap(), b);
    assert_eq!("( ;".to_ascii().unwrap(), b);
    let v = vec![40_u8, 32, 59];
    assert_eq!(v.to_ascii().unwrap(), b);
    assert_eq!("( ;".to_string().to_ascii().unwrap(), b);
}

#[test]
fn opt() {
    assert_eq!("zoä华".to_ascii(), Err(()));

    let test1 = &[127_u8, 128, 255];
    assert_eq!(test1.to_ascii(), Err(()));

    let v = [40_u8, 32, 59];
    let v1 = AsciiStr::from_bytes(&v).unwrap();
    assert_eq!(v.to_ascii(), Ok(v1));
    let v = [127_u8, 128, 255];
    assert_eq!(v.to_ascii(), Err(()));

    let v = "( ;";
    assert_eq!(v.to_ascii(), Ok(v1));
    assert_eq!("zoä华".to_ascii(), Err(()));

    let v1 = AsciiString::from_bytes(&[40_u8, 32, 59][..]).unwrap();
    assert_eq!(vec![40_u8, 32, 59].into_ascii(), Ok(v1));
    assert_eq!(vec![127_u8, 128, 255].into_ascii(), Err(vec![127_u8, 128, 255]));

    let v1 = AsciiString::from_bytes(&[40_u8, 32, 59][..]).unwrap();
    assert_eq!("( ;".to_string().into_ascii(), Ok(v1));
    assert_eq!("zoä华".to_string().into_ascii(), Err("zoä华".to_string()));
}

#[test]
fn compare_ascii_string_ascii_str() {
    let v = b"abc";
    let ascii_string = AsciiString::from_bytes(&v[..]).unwrap();
    let ascii_str = AsciiStr::from_bytes(v).unwrap();
    assert!(ascii_string == ascii_str);
    assert!(ascii_str == ascii_string);
}

#[test]
fn compare_ascii_string_string() {
    let v = b"abc";
    let string = String::from_utf8(v.to_vec()).unwrap();
    let ascii_string = AsciiString::from_bytes(&v[..]).unwrap();
    assert!(string == ascii_string);
    assert!(ascii_string == string);
}

#[test]
fn compare_ascii_str_string() {
    let v = b"abc";
    let string = String::from_utf8(v.to_vec()).unwrap();
    let ascii_str = AsciiStr::from_bytes(&v[..]).unwrap();
    assert!(string == ascii_str);
    assert!(ascii_str == string);
}

#[test]
fn compare_ascii_string_str() {
    let v = b"abc";
    let sstr = ::std::str::from_utf8(v).unwrap();
    let ascii_string = AsciiString::from_bytes(&v[..]).unwrap();
    assert!(sstr == ascii_string);
    assert!(ascii_string == sstr);
}

#[test]
fn compare_ascii_str_str() {
    let v = b"abc";
    let sstr = ::std::str::from_utf8(v).unwrap();
    let ascii_str = AsciiStr::from_bytes(v).unwrap();
    assert!(sstr == ascii_str);
    assert!(ascii_str == sstr);
}

#[test]
fn compare_ascii_str_slice() {
    let b = b"abc".to_ascii().unwrap();
    let c = b"ab".to_ascii().unwrap();
    assert_eq!(&b[..2], &c[..]);
    assert_eq!(c[1].as_char(), 'b');
}

#[test]
fn compare_ascii_string_slice() {
    let b = AsciiString::from_bytes("abc").unwrap();
    let c = AsciiString::from_bytes("ab").unwrap();
    assert_eq!(&b[..2], &c[..]);
    assert_eq!(c[1].as_char(), 'b');
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate typedopts;

extern crate "rustc-serialize" as rustc_serialize;
use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use rustc_serialize::Decodable;
use typedopts::{Error,ErrorType,DecodeResult};
use std::vec::Vec;

#[derive(RustcDecodable,PartialEq,Eq,Show)]
struct ParseInt {
  number: uint
}

#[test]
fn parse_int() {
  let opts = vec!(reqopt("n", "number", "integer", ""));
  let matches = getopts(vec!("-n".to_string(), "10".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseInt = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.number, 10);
}

#[test]
fn parse_not_int() {
  let opts = vec!(reqopt("n", "number", "integer", ""));
  let matches = getopts(vec!("-n".to_string(), "10.0".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let result:DecodeResult<ParseInt> = Decodable::decode(&mut decoder);
  assert_eq!(result, Err(ErrorType::ExpectedType("number".to_string(), "u64".to_string(), "10.0".to_string())));
}

#[derive(RustcDecodable)]
struct ParseFloat {
  number: f32
}

#[test]
fn parse_float() {
  let opts = vec!(reqopt("n", "number", "integer", ""));
  let matches = getopts(vec!("-n".to_string(), "10".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseFloat = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.number, 10.0);
}
#[derive(RustcDecodable)]
struct ParseBoolean {
  boolean: bool
}

#[test]
fn parse_bool() {
  let opts = vec!(reqopt("b", "boolean", "bool", ""));
  let matches = getopts(vec!("--boolean=true".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseBoolean = Decodable::decode(&mut decoder).unwrap();
  assert!(decoded.boolean);
}

#[derive(RustcDecodable)]
struct ParseChar {
  character: char
}

#[test]
fn parse_char() {
  let opts = vec!(reqopt("c", "character", "char", ""));
  let matches = getopts(vec!("-c".to_string(), "a".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseChar = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.character, 'a');
}

#[derive(RustcDecodable)]
struct ParseString {
  string: String
}

#[test]
fn parse_string() {
  let opts = vec!(reqopt("s", "string", "string", ""));
  let matches = getopts(vec!("-s".to_string(), "abcd".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseString = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.string, "abcd".to_string());
}

#[derive(RustcDecodable, PartialEq, Eq, Show)]
enum Color {
  Red,
  Blue,
  Green
}

#[derive(RustcDecodable)]
struct ParseEnum {
  color: Color
}

#[test]
fn parse_enum() {
  let opts = vec!(reqopt("c", "color", "enum", ""));
  let matches = getopts(vec!("--color".to_string(), "Blue".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseEnum = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.color, Color::Blue);
}

#[derive(RustcDecodable)]
struct ParseOption {
  option: Option<uint>
}

#[test]
fn parse_option() {
  let opts = vec!(optopt("o", "option", "option", ""));
  let matches = getopts(vec!("-o".to_string(), "1".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseOption = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.option, Some(1));
}

#[test]
fn parse_none_option() {
  let opts = vec!(optopt("o", "option", "option", ""), reqopt("a", "a", "number", ""));
  let matches = getopts(vec!("-a".to_string(), "1".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseOption = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.option, None);
}

#[derive(RustcDecodable, Show)]
struct ParseStruct {
  string: String,
  optuint: Option<uint>,
  optenum: Option<Color>
}

#[test]
fn parse_struct_noopt() {
  let opts = vec!(reqopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let matches = getopts(vec!("-s".to_string(), "abcd".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseStruct = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.string, "abcd".to_string());
  assert_eq!(decoded.optuint, None);
  assert_eq!(decoded.optenum, None);
}

#[test]
fn parse_struct_optenum() {
  let opts = vec!(reqopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let d = vec!("-s".to_string(), "abcd".to_string(),
     "-c".to_string(), "Green".to_string());
  let matches = getopts(d.as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseStruct = Decodable::decode(&mut decoder).unwrap();
  assert_eq!(decoded.string, "abcd".to_string());
  assert_eq!(decoded.optuint, None);
  assert_eq!(decoded.optenum, Some(Color::Green));
}

#[test]
fn decode_task_ok() {
  let opts = vec!(reqopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let matches = getopts(vec!("-s".to_string(), "abcd".to_string()).as_slice(), opts.as_slice()).unwrap();
  let result = typedopts::decode(matches);
  assert!(result.is_ok());
  let decoded: ParseStruct = result.unwrap();
  assert_eq!(decoded.string, "abcd".to_string());
  assert_eq!(decoded.optuint, None);
  assert_eq!(decoded.optenum, None);
}

#[test]
fn decode_task_err() {
  let opts = vec!(optopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let matches = getopts(&vec!("-u".to_string(), "1".to_string())[], &opts[]).unwrap();
  let result: typedopts::DecodeResult<ParseStruct> = typedopts::decode(matches);
  assert!(result.is_err());
  let err = result.unwrap_err();
  assert_eq!(err, ErrorType::MissingField("string".to_string()));
}
<commit_msg>stop using unwrap in Result<commit_after>extern crate getopts;
extern crate typedopts;

extern crate "rustc-serialize" as rustc_serialize;
use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use rustc_serialize::Decodable;
use typedopts::{Error,ErrorType,DecodeResult};
use std::vec::Vec;

#[derive(RustcDecodable,PartialEq,Eq,Show)]
struct ParseInt {
  number: uint
}

#[test]
fn parse_int() {
  let opts = vec!(reqopt("n", "number", "integer", ""));
  let matches = getopts(vec!("-n".to_string(), "10".to_string()).as_slice(), opts.as_slice()).ok().expect("getopts match");
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseInt = Decodable::decode(&mut decoder).ok().expect("ParseInt");
  assert_eq!(decoded.number, 10);
}

#[test]
fn parse_not_int() {
  let opts = vec!(reqopt("n", "number", "integer", ""));
  let matches = getopts(vec!("-n".to_string(), "10.0".to_string()).as_slice(), opts.as_slice()).ok().expect("getopts match");
  let mut decoder = typedopts::Decoder::new(matches);
  let result:DecodeResult<ParseInt> = Decodable::decode(&mut decoder);
  assert_eq!(result, Err(ErrorType::ExpectedType("number".to_string(), "u64".to_string(), "10.0".to_string())));
}

#[derive(RustcDecodable)]
struct ParseFloat {
  number: f32
}

#[test]
fn parse_float() {
  let opts = vec!(reqopt("n", "number", "integer", ""));
  let matches = getopts(vec!("-n".to_string(), "10".to_string()).as_slice(), opts.as_slice()).ok().expect("getopts match");
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseFloat = Decodable::decode(&mut decoder).ok().expect("ParseFloat");
  assert_eq!(decoded.number, 10.0);
}
#[derive(RustcDecodable)]
struct ParseBoolean {
  boolean: bool
}

#[test]
fn parse_bool() {
  let opts = vec!(reqopt("b", "boolean", "bool", ""));
  let matches = getopts(vec!("--boolean=true".to_string()).as_slice(), opts.as_slice()).ok().expect("getopts match");
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseBoolean = Decodable::decode(&mut decoder).ok().expect("ParseBoolean");
  assert!(decoded.boolean);
}

#[derive(RustcDecodable)]
struct ParseChar {
  character: char
}

#[test]
fn parse_char() {
  let opts = vec!(reqopt("c", "character", "char", ""));
  let matches = getopts(vec!("-c".to_string(), "a".to_string()).as_slice(), opts.as_slice()).ok().expect("getopts match");
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseChar = Decodable::decode(&mut decoder).ok().expect("ParseChar");
  assert_eq!(decoded.character, 'a');
}

#[derive(RustcDecodable)]
struct ParseString {
  string: String
}

#[test]
fn parse_string() {
  let opts = vec!(reqopt("s", "string", "string", ""));
  let matches = getopts(vec!("-s".to_string(), "abcd".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseString = Decodable::decode(&mut decoder).ok().expect("ParseString");
  assert_eq!(decoded.string, "abcd".to_string());
}

#[derive(RustcDecodable, PartialEq, Eq, Show)]
enum Color {
  Red,
  Blue,
  Green
}

#[derive(RustcDecodable)]
struct ParseEnum {
  color: Color
}

#[test]
fn parse_enum() {
  let opts = vec!(reqopt("c", "color", "enum", ""));
  let matches = getopts(vec!("--color".to_string(), "Blue".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseEnum = Decodable::decode(&mut decoder).ok().expect("ParseEnum");
  assert_eq!(decoded.color, Color::Blue);
}

#[derive(RustcDecodable)]
struct ParseOption {
  option: Option<uint>
}

#[test]
fn parse_option() {
  let opts = vec!(optopt("o", "option", "option", ""));
  let matches = getopts(vec!("-o".to_string(), "1".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseOption = Decodable::decode(&mut decoder).ok().expect("ParseOption");
  assert_eq!(decoded.option, Some(1));
}

#[test]
fn parse_none_option() {
  let opts = vec!(optopt("o", "option", "option", ""), reqopt("a", "a", "number", ""));
  let matches = getopts(vec!("-a".to_string(), "1".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseOption = Decodable::decode(&mut decoder).ok().expect("ParseOption");
  assert_eq!(decoded.option, None);
}

#[derive(RustcDecodable, Show)]
struct ParseStruct {
  string: String,
  optuint: Option<uint>,
  optenum: Option<Color>
}

#[test]
fn parse_struct_noopt() {
  let opts = vec!(reqopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let matches = getopts(vec!("-s".to_string(), "abcd".to_string()).as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseStruct = Decodable::decode(&mut decoder).ok().expect("ParseStruct");
  assert_eq!(decoded.string, "abcd".to_string());
  assert_eq!(decoded.optuint, None);
  assert_eq!(decoded.optenum, None);
}

#[test]
fn parse_struct_optenum() {
  let opts = vec!(reqopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let d = vec!("-s".to_string(), "abcd".to_string(),
     "-c".to_string(), "Green".to_string());
  let matches = getopts(d.as_slice(), opts.as_slice()).unwrap();
  let mut decoder = typedopts::Decoder::new(matches);
  let decoded: ParseStruct = Decodable::decode(&mut decoder).ok().expect("ParseStruct");
  assert_eq!(decoded.string, "abcd".to_string());
  assert_eq!(decoded.optuint, None);
  assert_eq!(decoded.optenum, Some(Color::Green));
}

#[test]
fn decode_task_ok() {
  let opts = vec!(reqopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let matches = getopts(vec!("-s".to_string(), "abcd".to_string()).as_slice(), opts.as_slice()).unwrap();
  let result = typedopts::decode(matches);
  assert!(result.is_ok());
  let decoded: ParseStruct = result.ok().expect("ParseStruct");
  assert_eq!(decoded.string, "abcd".to_string());
  assert_eq!(decoded.optuint, None);
  assert_eq!(decoded.optenum, None);
}

#[test]
fn decode_task_err() {
  let opts = vec!(optopt("s", "string", "string", ""),
               optopt("u", "optuint", "Option<uint>", ""),
               optopt("c", "optenum", "Option<Color>", ""));
  let matches = getopts(&vec!("-u".to_string(), "1".to_string())[], &opts[]).unwrap();
  let result: typedopts::DecodeResult<ParseStruct> = typedopts::decode(matches);
  assert!(result.is_err());
  let err = result.err().expect("ErrorType");
  assert_eq!(err, ErrorType::MissingField("string".to_string()));
}
<|endoftext|>


<commit_before>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cell::Ref;
use std::cell::RefCell;
use std::cell::RefMut;
use std::marker::PhantomData;
use std::rc::Rc;

use anyhow::{anyhow, Result};

use crate::bindings;
use crate::buffer::Buffer;
use crate::context::Context;
use crate::status::Status;
use crate::surface::Surface;

// Use the sealed trait pattern to make sure that new states are not created in
// caller code. More information about the sealed trait pattern can be found at
// <https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed>
mod private {
    pub trait Sealed {}
}

/// A `Picture` will only have valid YUV data after a sequence of operations are
/// performed in a particular order. This order correspond to the following
/// VA-API calls: vaBeginPicture, vaRenderPicture, vaEndPicture and
/// vaSyncSurface. This trait enforces this ordering by implementing the
/// Typestate pattern to constrain what operations are available in what
/// particular states.
///
/// The states for the state machine are:
/// PictureNew -> PictureBegin
/// PictureBegin -> PictureRender
/// PictureRender ->PictureEnd
/// PictureEnd -> PictureSync
///
/// Where the surface can be reclaimed in both PictureNew and PictureSync, as
/// either no operation took place (as in PictureNew), or it is guaranteed that
/// the operation has already completed (as in PictureSync)
///
/// More information about the Typestate pattern can be found
/// at <http://cliffle.com/blog/rust-typestate/>
pub trait PictureState: private::Sealed {}

/// Represents a `Picture` that has just been created.
pub enum PictureNew {}
impl PictureState for PictureNew {}
impl private::Sealed for PictureNew {}

/// Represents a `Picture` after `vaBeginPicture` has been called.
pub enum PictureBegin {}
impl PictureState for PictureBegin {}
impl private::Sealed for PictureBegin {}

/// Represents a `Picture` after `vaRenderPicture` has been called.
pub enum PictureRender {}
impl PictureState for PictureRender {}
impl private::Sealed for PictureRender {}

/// Represents a `Picture` after `vaEndPicture` has been called.
pub enum PictureEnd {}
impl PictureState for PictureEnd {}
impl private::Sealed for PictureEnd {}

/// Represents a `Picture` after `vaSyncSurface` has been called on the
/// underlying surface.
pub enum PictureSync {}
impl PictureState for PictureSync {}
impl private::Sealed for PictureSync {}

/// Represents a state where one can reclaim the underlying `Surface` for this
/// `Picture`. This is true when either no decoding has been initiated or,
/// alternatively, when the decoding operation has completed for the underlying
/// `vaSurface`
pub trait PictureReclaimableSurface: PictureState + private::Sealed {}
impl PictureReclaimableSurface for PictureNew {}
impl PictureReclaimableSurface for PictureSync {}

pub(crate) struct PictureInner {
    /// Timestamp of the picture
    timestamp: u64,
    /// A context associated with this picture
    context: Rc<Context>,
    /// Contains the buffers used to decode the data
    buffers: Vec<Buffer>,
    /// Contains the actual decoded data. Note that the surface may be shared in
    /// interlaced decoding.
    surface: Rc<RefCell<Surface>>,
}

impl PictureInner {
    /// Returns a reference to the Context used by the Picture
    pub(crate) fn context(&self) -> Rc<Context> {
        Rc::clone(&self.context)
    }
}

/// An abstraction over VABuffers and a VASurface suitable for decoding with
/// vaBeginPicture, vaRenderPicture, vaEndPicture "surface" will have valid raw
/// picture data after "begin", "render", "end" and "sync" are called, in this
/// order.
pub struct Picture<S: PictureState> {
    inner: Box<PictureInner>,
    phantom: std::marker::PhantomData<S>,
}

impl Picture<PictureNew> {
    /// Creates a new Picture with a given `frame_number` to identify it.
    /// `surface` is the underlying surface that libva will render to.
    pub fn new(timestamp: u64, context: Rc<Context>, surface: Surface) -> Self {
        Self {
            inner: Box::new(PictureInner {
                timestamp,
                context,
                buffers: Default::default(),
                surface: Rc::new(RefCell::new(surface)),
            }),

            phantom: PhantomData,
        }
    }

    /// Add buffers to a picture
    pub fn add_buffer(&mut self, buffer: Buffer) {
        self.inner.buffers.push(buffer);
    }

    /// A wrapper around vaBeginPicture
    pub fn begin(self) -> Result<Picture<PictureBegin>> {
        // Safe because `self.inner.context` represents a valid VAContext and
        // `self.inner.surface` represents a valid VASurface.
        Status(unsafe {
            bindings::vaBeginPicture(
                self.inner.context.display().handle(),
                self.inner.context.id(),
                self.inner.surface.borrow().id(),
            )
        })
        .check()?;

        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureBegin> {
    /// A wrapper around vaRenderPicture
    pub fn render(self) -> Result<Picture<PictureRender>> {
        // Safe because `self.inner.context` represents a valid VAContext and
        // `self.inner.surface` represents a valid VASurface. `buffers` point to
        // a Rust struct and the vector length is passed to the C function, so
        // it is impossible to write past the end of the vector's storage by
        // mistake.
        Status(unsafe {
            bindings::vaRenderPicture(
                self.inner.context.display().handle(),
                self.inner.context.id(),
                Buffer::as_id_vec(&self.inner.buffers).as_mut_ptr(),
                self.inner.buffers.len() as i32,
            )
        })
        .check()?;

        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureRender> {
    /// A wrapper around vaEndPicture
    pub fn end(self) -> Result<Picture<PictureEnd>> {
        // Safe because `self.inner.context` represents a valid VAContext.
        Status(unsafe {
            bindings::vaEndPicture(
                self.inner.context.display().handle(),
                self.inner.context.id(),
            )
        })
        .check()?;
        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureEnd> {
    /// Syncs the picture, ensuring that any pending decode operations are
    /// complete when this call returns
    pub fn sync(self) -> Result<Picture<PictureSync>> {
        self.inner.surface.borrow().sync()?;

        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureSync> {
    /// Returns a reference to the underlying `Surface` for this
    /// `Picture`
    pub fn surface(&self) -> Ref<Surface> {
        self.inner.surface.borrow()
    }

    /// Returns a mutable reference to the underlying `Surface` for this
    /// `Picture`
    pub fn surface_mut(&mut self) -> RefMut<Surface> {
        self.inner.surface.borrow_mut()
    }
}

impl<S: PictureState> Picture<S> {
    /// Get the timestamp for this picture.
    pub fn timestamp(&self) -> u64 {
        self.inner.timestamp
    }

    /// Returns a reference to the `inner` struct
    pub(crate) fn inner(&self) -> &PictureInner {
        self.inner.as_ref()
    }
}

impl<S: PictureReclaimableSurface> Picture<S> {
    /// Reclaim ownership of the Surface, consuming the picture in the process.
    /// Useful if the Surface is part of a pool.
    pub fn take_surface(self) -> Result<Surface> {
        match Rc::try_unwrap(self.inner.surface) {
            Ok(surface) => Ok(surface.into_inner()),
            Err(_) => Err(anyhow!("Surface still in use")),
        }
    }
}
<commit_msg>media: libva: picture: add new_from_same_surface<commit_after>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cell::Ref;
use std::cell::RefCell;
use std::cell::RefMut;
use std::marker::PhantomData;
use std::rc::Rc;

use anyhow::{anyhow, Result};

use crate::bindings;
use crate::buffer::Buffer;
use crate::context::Context;
use crate::status::Status;
use crate::surface::Surface;

// Use the sealed trait pattern to make sure that new states are not created in
// caller code. More information about the sealed trait pattern can be found at
// <https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed>
mod private {
    pub trait Sealed {}
}

/// A `Picture` will only have valid YUV data after a sequence of operations are
/// performed in a particular order. This order correspond to the following
/// VA-API calls: vaBeginPicture, vaRenderPicture, vaEndPicture and
/// vaSyncSurface. This trait enforces this ordering by implementing the
/// Typestate pattern to constrain what operations are available in what
/// particular states.
///
/// The states for the state machine are:
/// PictureNew -> PictureBegin
/// PictureBegin -> PictureRender
/// PictureRender ->PictureEnd
/// PictureEnd -> PictureSync
///
/// Where the surface can be reclaimed in both PictureNew and PictureSync, as
/// either no operation took place (as in PictureNew), or it is guaranteed that
/// the operation has already completed (as in PictureSync)
///
/// More information about the Typestate pattern can be found
/// at <http://cliffle.com/blog/rust-typestate/>
pub trait PictureState: private::Sealed {}

/// Represents a `Picture` that has just been created.
pub enum PictureNew {}
impl PictureState for PictureNew {}
impl private::Sealed for PictureNew {}

/// Represents a `Picture` after `vaBeginPicture` has been called.
pub enum PictureBegin {}
impl PictureState for PictureBegin {}
impl private::Sealed for PictureBegin {}

/// Represents a `Picture` after `vaRenderPicture` has been called.
pub enum PictureRender {}
impl PictureState for PictureRender {}
impl private::Sealed for PictureRender {}

/// Represents a `Picture` after `vaEndPicture` has been called.
pub enum PictureEnd {}
impl PictureState for PictureEnd {}
impl private::Sealed for PictureEnd {}

/// Represents a `Picture` after `vaSyncSurface` has been called on the
/// underlying surface.
pub enum PictureSync {}
impl PictureState for PictureSync {}
impl private::Sealed for PictureSync {}

/// Represents a state where one can reclaim the underlying `Surface` for this
/// `Picture`. This is true when either no decoding has been initiated or,
/// alternatively, when the decoding operation has completed for the underlying
/// `vaSurface`
pub trait PictureReclaimableSurface: PictureState + private::Sealed {}
impl PictureReclaimableSurface for PictureNew {}
impl PictureReclaimableSurface for PictureSync {}

pub(crate) struct PictureInner {
    /// Timestamp of the picture
    timestamp: u64,
    /// A context associated with this picture
    context: Rc<Context>,
    /// Contains the buffers used to decode the data
    buffers: Vec<Buffer>,
    /// Contains the actual decoded data. Note that the surface may be shared in
    /// interlaced decoding.
    surface: Rc<RefCell<Surface>>,
}

impl PictureInner {
    /// Returns a reference to the Context used by the Picture
    pub(crate) fn context(&self) -> Rc<Context> {
        Rc::clone(&self.context)
    }
}

/// An abstraction over VABuffers and a VASurface suitable for decoding with
/// vaBeginPicture, vaRenderPicture, vaEndPicture "surface" will have valid raw
/// picture data after "begin", "render", "end" and "sync" are called, in this
/// order.
pub struct Picture<S: PictureState> {
    inner: Box<PictureInner>,
    phantom: std::marker::PhantomData<S>,
}

impl Picture<PictureNew> {
    /// Creates a new Picture with a given `frame_number` to identify it.
    /// `surface` is the underlying surface that libva will render to.
    pub fn new(timestamp: u64, context: Rc<Context>, surface: Surface) -> Self {
        Self {
            inner: Box::new(PictureInner {
                timestamp,
                context,
                buffers: Default::default(),
                surface: Rc::new(RefCell::new(surface)),
            }),

            phantom: PhantomData,
        }
    }

    /// Creates a new Picture with a given `frame_number` to identify it,
    /// reusing the Surface from `picture`. This is useful for interlaced
    /// decoding as one can render both fields to the same underlying surface.
    pub fn new_from_same_surface<T: PictureReclaimableSurface, S: PictureReclaimableSurface>(
        timestamp: u64,
        picture: &Picture<S>,
    ) -> Picture<T> {
        let context = Rc::clone(&picture.inner.context);
        Picture {
            inner: Box::new(PictureInner {
                timestamp,
                context,
                buffers: Default::default(),
                surface: Rc::clone(&picture.inner.surface),
            }),

            phantom: PhantomData,
        }
    }

    /// Add buffers to a picture
    pub fn add_buffer(&mut self, buffer: Buffer) {
        self.inner.buffers.push(buffer);
    }

    /// A wrapper around vaBeginPicture
    pub fn begin(self) -> Result<Picture<PictureBegin>> {
        // Safe because `self.inner.context` represents a valid VAContext and
        // `self.inner.surface` represents a valid VASurface.
        Status(unsafe {
            bindings::vaBeginPicture(
                self.inner.context.display().handle(),
                self.inner.context.id(),
                self.inner.surface.borrow().id(),
            )
        })
        .check()?;

        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureBegin> {
    /// A wrapper around vaRenderPicture
    pub fn render(self) -> Result<Picture<PictureRender>> {
        // Safe because `self.inner.context` represents a valid VAContext and
        // `self.inner.surface` represents a valid VASurface. `buffers` point to
        // a Rust struct and the vector length is passed to the C function, so
        // it is impossible to write past the end of the vector's storage by
        // mistake.
        Status(unsafe {
            bindings::vaRenderPicture(
                self.inner.context.display().handle(),
                self.inner.context.id(),
                Buffer::as_id_vec(&self.inner.buffers).as_mut_ptr(),
                self.inner.buffers.len() as i32,
            )
        })
        .check()?;

        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureRender> {
    /// A wrapper around vaEndPicture
    pub fn end(self) -> Result<Picture<PictureEnd>> {
        // Safe because `self.inner.context` represents a valid VAContext.
        Status(unsafe {
            bindings::vaEndPicture(
                self.inner.context.display().handle(),
                self.inner.context.id(),
            )
        })
        .check()?;
        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureEnd> {
    /// Syncs the picture, ensuring that any pending decode operations are
    /// complete when this call returns
    pub fn sync(self) -> Result<Picture<PictureSync>> {
        self.inner.surface.borrow().sync()?;

        Ok(Picture {
            inner: self.inner,
            phantom: PhantomData,
        })
    }
}

impl Picture<PictureSync> {
    /// Returns a reference to the underlying `Surface` for this
    /// `Picture`
    pub fn surface(&self) -> Ref<Surface> {
        self.inner.surface.borrow()
    }

    /// Returns a mutable reference to the underlying `Surface` for this
    /// `Picture`
    pub fn surface_mut(&mut self) -> RefMut<Surface> {
        self.inner.surface.borrow_mut()
    }
}

impl<S: PictureState> Picture<S> {
    /// Get the timestamp for this picture.
    pub fn timestamp(&self) -> u64 {
        self.inner.timestamp
    }

    /// Returns a reference to the `inner` struct
    pub(crate) fn inner(&self) -> &PictureInner {
        self.inner.as_ref()
    }
}

impl<S: PictureReclaimableSurface> Picture<S> {
    /// Reclaim ownership of the Surface, consuming the picture in the process.
    /// Useful if the Surface is part of a pool.
    pub fn take_surface(self) -> Result<Surface> {
        match Rc::try_unwrap(self.inner.surface) {
            Ok(surface) => Ok(surface.into_inner()),
            Err(_) => Err(anyhow!("Surface still in use")),
        }
    }
}
<|endoftext|>