<commit_before>//! Runtime support needed for the `#![assert_instr]` macro
//!
//! This basically just disassembles the current executable and then parses the
//! output once globally and then provides the `assert` function which makes
//! assertions about the disassembly of a function.

#![feature(proc_macro)]

extern crate assert_instr_macro;
extern crate backtrace;
extern crate cc;
extern crate rustc_demangle;
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;
use std::env;
use std::process::Command;
use std::str;

pub use assert_instr_macro::*;

lazy_static! {
    static ref DISASSEMBLY: HashMap<String, Vec<Function>> = disassemble_myself();
}

struct Function {
    instrs: Vec<Instruction>,
}

struct Instruction {
    parts: Vec<String>,
}

fn disassemble_myself() -> HashMap<String, Vec<Function>> {
    let me = env::current_exe().expect("failed to get current exe");

    if cfg!(target_arch = "x86_64") &&
        cfg!(target_os = "windows") &&
        cfg!(target_env = "msvc") {
        let mut cmd = cc::windows_registry::find("x86_64-pc-windows-msvc", "dumpbin.exe")
            .expect("failed to find `dumpbin` tool");
        let output = cmd.arg("/DISASM").arg(&me).output()
            .expect("failed to execute dumpbin");
        println!("{}\n{}", output.status, String::from_utf8_lossy(&output.stderr));
        assert!(output.status.success());
        parse_dumpbin(&String::from_utf8_lossy(&output.stdout))
    } else if cfg!(target_os = "windows") {
        panic!("disassembly unimplemented")
    } else if cfg!(target_os = "macos") {
        let output = Command::new("otool")
            .arg("-vt")
            .arg(&me)
            .output()
            .expect("failed to execute otool");
        println!("{}\n{}", output.status, String::from_utf8_lossy(&output.stderr));
        assert!(output.status.success());

        parse_otool(&str::from_utf8(&output.stdout).expect("stdout not utf8"))
    } else {
        let objdump = env::var("OBJDUMP").unwrap_or("objdump".to_string());
        let output = Command::new(objdump)
            .arg("--disassemble")
            .arg(&me)
            .output()
            .expect("failed to execute objdump");
        println!("{}\n{}", output.status, String::from_utf8_lossy(&output.stderr));
        assert!(output.status.success());

        parse_objdump(&str::from_utf8(&output.stdout).expect("stdout not utf8"))
    }
}

fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();
    let expected_len = if cfg!(target_arch = "arm") {
        8
    } else if cfg!(target_arch = "aarch64") {
        8
    } else {
        2
    };

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    while let Some(header) = lines.next() {
        // symbols should start with `$hex_addr <$name>:`
        if !header.ends_with(">:") {
            continue
        }
        let start = header.find("<").unwrap();
        let symbol = &header[start + 1..header.len() - 2];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.is_empty() {
                break
            }
            // Each line of instructions should look like:
            //
            //      $rel_offset: ab cd ef 00    $instruction...
            let parts = instruction.split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == expected_len && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert(Vec::new())
            .push(Function { instrs: instructions });
    }

    return ret
}

fn parse_otool(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    loop {
        let header = match cached_header.take().or_else(|| lines.next()) {
            Some(header) => header,
            None => break,
        };
        // symbols should start with `$symbol:`
        if !header.ends_with(":") {
            continue
        }
        // strip the leading underscore and the trailing colon
        let symbol = &header[1..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.ends_with(":") {
                cached_header = Some(instruction);
                break
            }
            // Each line of instructions should look like:
            //
            //      $addr    $instruction...
            let parts = instruction.split_whitespace()
                .skip(1)
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert(Vec::new())
            .push(Function { instrs: instructions });
    }

    return ret
}

fn parse_dumpbin(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    loop {
        let header = match cached_header.take().or_else(|| lines.next()) {
            Some(header) => header,
            None => break,
        };
        // symbols should start with `$symbol:`
        if !header.ends_with(":") {
            continue
        }
        // strip the trailing colon
        let symbol = &header[..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if !instruction.starts_with("  ") {
                cached_header = Some(instruction);
                break
            }
            // Each line looks like:
            //
            // >  $addr: ab cd ef     $instr..
            // >         00 12          # this line os optional
            if instruction.starts_with("       ") {
                continue
            }
            let parts = instruction.split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == 2 && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert(Vec::new())
            .push(Function { instrs: instructions });
    }

    return ret
}

fn normalize(symbol: &str) -> String {
    let symbol = rustc_demangle::demangle(symbol).to_string();
    match symbol.rfind("::h") {
        Some(i) => symbol[..i].to_string(),
        None => symbol.to_string(),
    }
}

/// Main entry point for this crate, called by the `#[assert_instr]` macro.
///
/// This asserts that the function at `fnptr` contains the instruction
/// `expected` provided.
pub fn assert(fnptr: usize, fnname: &str, expected: &str) {
    // Translate this function pointer to a symbolic name that we'd have found
    // in the disassembly.
    let mut sym = None;
    backtrace::resolve(fnptr as *mut _, |name| {
        sym = name.name().and_then(|s| s.as_str()).map(normalize);
    });

    let functions = match sym.as_ref().and_then(|s| DISASSEMBLY.get(s)) {
        Some(s) => s,
        None => {
            if let Some(sym) = sym {
                println!("assumed symbol name: `{}`", sym);
            }
            println!("maybe related functions");
            for f in DISASSEMBLY.keys().filter(|k| k.contains(fnname)) {
                println!("\t- {}", f);
            }
            panic!("failed to find disassembly of {:#x} ({})", fnptr, fnname);
        }
    };

    assert_eq!(functions.len(), 1);
    let function = &functions[0];

    // Look for `expected` as the first part of any instruction in this
    // function, returning if we do indeed find it.
    for instr in function.instrs.iter() {
        // Gets the first instruction, e.g. tzcntl in tzcntl %rax,%rax
        if let Some(part) = instr.parts.get(0) {
            // Truncates the instruction with the length of the expected
            // instruction: tzcntl => tzcnt and compares that.
            if part.starts_with(expected) {
                return
            }
        }
    }

    // Help debug by printing out the found disassembly, and then panic as we
    // didn't find the instruction.
    println!("disassembly for {}: ", sym.as_ref().unwrap());
    for (i, instr) in function.instrs.iter().enumerate() {
        print!("\t{:2}: ", i);
        for part in instr.parts.iter() {
            print!("{} ", part);
        }
        println!("");
    }
    panic!("failed to find instruction `{}` in the disassembly", expected);
}
<commit_msg>Assert that diassembly is "small"<commit_after>//! Runtime support needed for the `#![assert_instr]` macro
//!
//! This basically just disassembles the current executable and then parses the
//! output once globally and then provides the `assert` function which makes
//! assertions about the disassembly of a function.

#![feature(proc_macro)]

extern crate assert_instr_macro;
extern crate backtrace;
extern crate cc;
extern crate rustc_demangle;
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;
use std::env;
use std::process::Command;
use std::str;

pub use assert_instr_macro::*;

lazy_static! {
    static ref DISASSEMBLY: HashMap<String, Vec<Function>> = disassemble_myself();
}

struct Function {
    instrs: Vec<Instruction>,
}

struct Instruction {
    parts: Vec<String>,
}

fn disassemble_myself() -> HashMap<String, Vec<Function>> {
    let me = env::current_exe().expect("failed to get current exe");

    if cfg!(target_arch = "x86_64") &&
        cfg!(target_os = "windows") &&
        cfg!(target_env = "msvc") {
        let mut cmd = cc::windows_registry::find("x86_64-pc-windows-msvc", "dumpbin.exe")
            .expect("failed to find `dumpbin` tool");
        let output = cmd.arg("/DISASM").arg(&me).output()
            .expect("failed to execute dumpbin");
        println!("{}\n{}", output.status, String::from_utf8_lossy(&output.stderr));
        assert!(output.status.success());
        parse_dumpbin(&String::from_utf8_lossy(&output.stdout))
    } else if cfg!(target_os = "windows") {
        panic!("disassembly unimplemented")
    } else if cfg!(target_os = "macos") {
        let output = Command::new("otool")
            .arg("-vt")
            .arg(&me)
            .output()
            .expect("failed to execute otool");
        println!("{}\n{}", output.status, String::from_utf8_lossy(&output.stderr));
        assert!(output.status.success());

        parse_otool(&str::from_utf8(&output.stdout).expect("stdout not utf8"))
    } else {
        let objdump = env::var("OBJDUMP").unwrap_or("objdump".to_string());
        let output = Command::new(objdump)
            .arg("--disassemble")
            .arg(&me)
            .output()
            .expect("failed to execute objdump");
        println!("{}\n{}", output.status, String::from_utf8_lossy(&output.stderr));
        assert!(output.status.success());

        parse_objdump(&str::from_utf8(&output.stdout).expect("stdout not utf8"))
    }
}

fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();
    let expected_len = if cfg!(target_arch = "arm") {
        8
    } else if cfg!(target_arch = "aarch64") {
        8
    } else {
        2
    };

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    while let Some(header) = lines.next() {
        // symbols should start with `$hex_addr <$name>:`
        if !header.ends_with(">:") {
            continue
        }
        let start = header.find("<").unwrap();
        let symbol = &header[start + 1..header.len() - 2];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.is_empty() {
                break
            }
            // Each line of instructions should look like:
            //
            //      $rel_offset: ab cd ef 00    $instruction...
            let parts = instruction.split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == expected_len && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert(Vec::new())
            .push(Function { instrs: instructions });
    }

    return ret
}

fn parse_otool(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    loop {
        let header = match cached_header.take().or_else(|| lines.next()) {
            Some(header) => header,
            None => break,
        };
        // symbols should start with `$symbol:`
        if !header.ends_with(":") {
            continue
        }
        // strip the leading underscore and the trailing colon
        let symbol = &header[1..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.ends_with(":") {
                cached_header = Some(instruction);
                break
            }
            // Each line of instructions should look like:
            //
            //      $addr    $instruction...
            let parts = instruction.split_whitespace()
                .skip(1)
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert(Vec::new())
            .push(Function { instrs: instructions });
    }

    return ret
}

fn parse_dumpbin(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    loop {
        let header = match cached_header.take().or_else(|| lines.next()) {
            Some(header) => header,
            None => break,
        };
        // symbols should start with `$symbol:`
        if !header.ends_with(":") {
            continue
        }
        // strip the trailing colon
        let symbol = &header[..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if !instruction.starts_with("  ") {
                cached_header = Some(instruction);
                break
            }
            // Each line looks like:
            //
            // >  $addr: ab cd ef     $instr..
            // >         00 12          # this line os optional
            if instruction.starts_with("       ") {
                continue
            }
            let parts = instruction.split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == 2 && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert(Vec::new())
            .push(Function { instrs: instructions });
    }

    return ret
}

fn normalize(symbol: &str) -> String {
    let symbol = rustc_demangle::demangle(symbol).to_string();
    match symbol.rfind("::h") {
        Some(i) => symbol[..i].to_string(),
        None => symbol.to_string(),
    }
}

/// Main entry point for this crate, called by the `#[assert_instr]` macro.
///
/// This asserts that the function at `fnptr` contains the instruction
/// `expected` provided.
pub fn assert(fnptr: usize, fnname: &str, expected: &str) {
    // Translate this function pointer to a symbolic name that we'd have found
    // in the disassembly.
    let mut sym = None;
    backtrace::resolve(fnptr as *mut _, |name| {
        sym = name.name().and_then(|s| s.as_str()).map(normalize);
    });

    let functions = match sym.as_ref().and_then(|s| DISASSEMBLY.get(s)) {
        Some(s) => s,
        None => {
            if let Some(sym) = sym {
                println!("assumed symbol name: `{}`", sym);
            }
            println!("maybe related functions");
            for f in DISASSEMBLY.keys().filter(|k| k.contains(fnname)) {
                println!("\t- {}", f);
            }
            panic!("failed to find disassembly of {:#x} ({})", fnptr, fnname);
        }
    };

    assert_eq!(functions.len(), 1);
    let function = &functions[0];

    // Look for `expected` as the first part of any instruction in this
    // function, returning if we do indeed find it.
    let mut found = false;
    for instr in function.instrs.iter() {
        // Gets the first instruction, e.g. tzcntl in tzcntl %rax,%rax
        if let Some(part) = instr.parts.get(0) {
            // Truncates the instruction with the length of the expected
            // instruction: tzcntl => tzcnt and compares that.
            if part.starts_with(expected) {
                found = true;
                break
            }
        }
    }

    let probably_only_one_instruction = function.instrs.len() < 20;

    if found && probably_only_one_instruction {
        return
    }

    // Help debug by printing out the found disassembly, and then panic as we
    // didn't find the instruction.
    println!("disassembly for {}: ", sym.as_ref().unwrap());
    for (i, instr) in function.instrs.iter().enumerate() {
        print!("\t{:2}: ", i);
        for part in instr.parts.iter() {
            print!("{} ", part);
        }
        println!("");
    }

    if !found {
        panic!("failed to find instruction `{}` in the disassembly", expected);
    } else if !probably_only_one_instruction {
        panic!("too many instructions in the disassembly");
    }
}
<|endoftext|>


<commit_before>extern crate failure;
#[macro_use]
extern crate failure_derive;
extern crate getopts;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate varlink;

use org_example_more::*;
use std::env;
use std::process::exit;
use std::sync::{Arc, RwLock};
use std::{thread, time};
use varlink::{Connection, VarlinkService};

// Dynamically build the varlink rust code.
mod org_example_more;

#[cfg(test)]
mod test;

// Main

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [--varlink=<address>] [--client]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = getopts::Options::new();
    opts.optopt("", "varlink", "varlink address URL", "<address>");
    opts.optflag("", "client", "run in client mode");
    opts.optflag("h", "help", "print this help menu");
    opts.optopt("", "timeout", "server timeout", "<seconds>");
    opts.optopt("", "sleep", "sleep duration", "<milliseconds>");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            print_usage(&program, &opts);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        return;
    }

    let client_mode = matches.opt_present("client");

    let timeout = matches
        .opt_str("timeout")
        .unwrap_or_default()
        .parse::<u64>()
        .unwrap_or(0);

    let sleep = matches
        .opt_str("sleep")
        .unwrap_or_default()
        .parse::<u64>()
        .unwrap_or(1000);

    let ret = if client_mode {
        let connection = match matches.opt_str("varlink") {
            None => Connection::with_activate(&format!("{} --varlink=$VARLINK_ADDRESS", program))
                .unwrap(),
            Some(address) => Connection::with_address(&address).unwrap(),
        };
        run_client(connection)
    } else {
        if let Some(address) = matches.opt_str("varlink") {
            run_server(&address, timeout, sleep).map_err(|e| e.into())
        } else {
            print_usage(&program, &opts);
            eprintln!("Need varlink address in server mode.");
            exit(1);
        }
    };
    exit(match ret {
        Ok(_) => 0,
        Err(err) => {
            eprintln!("error: {:?}", err);
            1
        }
    });
}

// Client

fn run_client(connection: Arc<RwLock<varlink::Connection>>) -> Result<()> {
    let new_addr = {
        let conn = connection.read().unwrap();
        conn.address()
    };
    let mut iface = org_example_more::VarlinkClient::new(connection);

    let con2 = varlink::Connection::with_address(&new_addr)?;
    let mut pingiface = org_example_more::VarlinkClient::new(con2);

    for reply in iface.test_more(10).more()? {
        let reply = reply?;
        //assert!(reply.state.is_some());
        let state = reply.state;
        match state {
            State {
                start: Some(true),
                end: None,
                progress: None,
                ..
            } => {
                eprintln!("--- Start ---");
            }
            State {
                start: None,
                end: Some(true),
                progress: None,
                ..
            } => {
                eprintln!("--- End ---");
            }
            State {
                start: None,
                end: None,
                progress: Some(progress),
                ..
            } => {
                eprintln!("Progress: {}", progress);
                if progress > 50 {
                    let reply = pingiface.ping("Test".into()).call()?;
                    println!("Pong: '{}'", reply.pong);
                }
            }
            _ => eprintln!("Got unknown state: {:?}", state),
        }
    }

    Ok(())
}

// Server

struct MyOrgExampleMore {
    sleep_duration: u64,
}

impl VarlinkInterface for MyOrgExampleMore {
    fn ping(&self, call: &mut Call_Ping, ping: String) -> varlink::Result<()> {
        call.reply(ping)
    }

    fn stop_serving(&self, call: &mut Call_StopServing) -> varlink::Result<()> {
        call.reply()?;
        Err(varlink::ErrorKind::ConnectionClosed.into())
    }
    fn test_more(&self, call: &mut Call_TestMore, n: i64) -> varlink::Result<()> {
        if !call.wants_more() {
            return call.reply_test_more_error("called without more".into());
        }

        if n == 0 {
            return call.reply_test_more_error("n == 0".into());
        }

        call.set_continues(true);

        call.reply(State {
            start: Some(true),
            end: None,
            progress: None,
        })?;

        for i in 0..n {
            thread::sleep(time::Duration::from_millis(self.sleep_duration));
            call.reply(State {
                progress: Some(i * 100 / n),
                start: None,
                end: None,
            })?;
        }

        call.reply(State {
            progress: Some(100),
            start: None,
            end: None,
        })?;

        call.set_continues(false);

        call.reply(State {
            end: Some(true),
            progress: None,
            start: None,
        })
    }
}

fn run_server(address: &str, timeout: u64, sleep_duration: u64) -> varlink::Result<()> {
    let myexamplemore = MyOrgExampleMore { sleep_duration };
    let myinterface = org_example_more::new(Box::new(myexamplemore));
    let service = VarlinkService::new(
        "org.varlink",
        "test service",
        "0.1",
        "http://varlink.org",
        vec![Box::new(myinterface)],
    );
    varlink::listen(service, &address, 10, timeout)?;
    Ok(())
}
<commit_msg>examples/more/src/main.rs: eprintln instead of println<commit_after>extern crate failure;
#[macro_use]
extern crate failure_derive;
extern crate getopts;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate varlink;

use org_example_more::*;
use std::env;
use std::process::exit;
use std::sync::{Arc, RwLock};
use std::{thread, time};
use varlink::{Connection, VarlinkService};

// Dynamically build the varlink rust code.
mod org_example_more;

#[cfg(test)]
mod test;

// Main

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [--varlink=<address>] [--client]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = getopts::Options::new();
    opts.optopt("", "varlink", "varlink address URL", "<address>");
    opts.optflag("", "client", "run in client mode");
    opts.optflag("h", "help", "print this help menu");
    opts.optopt("", "timeout", "server timeout", "<seconds>");
    opts.optopt("", "sleep", "sleep duration", "<milliseconds>");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            print_usage(&program, &opts);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        return;
    }

    let client_mode = matches.opt_present("client");

    let timeout = matches
        .opt_str("timeout")
        .unwrap_or_default()
        .parse::<u64>()
        .unwrap_or(0);

    let sleep = matches
        .opt_str("sleep")
        .unwrap_or_default()
        .parse::<u64>()
        .unwrap_or(1000);

    let ret = if client_mode {
        let connection = match matches.opt_str("varlink") {
            None => Connection::with_activate(&format!("{} --varlink=$VARLINK_ADDRESS", program))
                .unwrap(),
            Some(address) => Connection::with_address(&address).unwrap(),
        };
        run_client(connection)
    } else {
        if let Some(address) = matches.opt_str("varlink") {
            run_server(&address, timeout, sleep).map_err(|e| e.into())
        } else {
            print_usage(&program, &opts);
            eprintln!("Need varlink address in server mode.");
            exit(1);
        }
    };
    exit(match ret {
        Ok(_) => 0,
        Err(err) => {
            eprintln!("error: {:?}", err);
            1
        }
    });
}

// Client

fn run_client(connection: Arc<RwLock<varlink::Connection>>) -> Result<()> {
    let new_addr = {
        let conn = connection.read().unwrap();
        conn.address()
    };
    let mut iface = org_example_more::VarlinkClient::new(connection);

    let con2 = varlink::Connection::with_address(&new_addr)?;
    let mut pingiface = org_example_more::VarlinkClient::new(con2);

    for reply in iface.test_more(10).more()? {
        let reply = reply?;
        //assert!(reply.state.is_some());
        let state = reply.state;
        match state {
            State {
                start: Some(true),
                end: None,
                progress: None,
                ..
            } => {
                eprintln!("--- Start ---");
            }
            State {
                start: None,
                end: Some(true),
                progress: None,
                ..
            } => {
                eprintln!("--- End ---");
            }
            State {
                start: None,
                end: None,
                progress: Some(progress),
                ..
            } => {
                eprintln!("Progress: {}", progress);
                if progress > 50 {
                    let reply = pingiface.ping("Test".into()).call()?;
                    eprintln!("Pong: '{}'", reply.pong);
                }
            }
            _ => eprintln!("Got unknown state: {:?}", state),
        }
    }

    Ok(())
}

// Server

struct MyOrgExampleMore {
    sleep_duration: u64,
}

impl VarlinkInterface for MyOrgExampleMore {
    fn ping(&self, call: &mut Call_Ping, ping: String) -> varlink::Result<()> {
        call.reply(ping)
    }

    fn stop_serving(&self, call: &mut Call_StopServing) -> varlink::Result<()> {
        call.reply()?;
        Err(varlink::ErrorKind::ConnectionClosed.into())
    }
    fn test_more(&self, call: &mut Call_TestMore, n: i64) -> varlink::Result<()> {
        if !call.wants_more() {
            return call.reply_test_more_error("called without more".into());
        }

        if n == 0 {
            return call.reply_test_more_error("n == 0".into());
        }

        call.set_continues(true);

        call.reply(State {
            start: Some(true),
            end: None,
            progress: None,
        })?;

        for i in 0..n {
            thread::sleep(time::Duration::from_millis(self.sleep_duration));
            call.reply(State {
                progress: Some(i * 100 / n),
                start: None,
                end: None,
            })?;
        }

        call.reply(State {
            progress: Some(100),
            start: None,
            end: None,
        })?;

        call.set_continues(false);

        call.reply(State {
            end: Some(true),
            progress: None,
            start: None,
        })
    }
}

fn run_server(address: &str, timeout: u64, sleep_duration: u64) -> varlink::Result<()> {
    let myexamplemore = MyOrgExampleMore { sleep_duration };
    let myinterface = org_example_more::new(Box::new(myexamplemore));
    let service = VarlinkService::new(
        "org.varlink",
        "test service",
        "0.1",
        "http://varlink.org",
        vec![Box::new(myinterface)],
    );
    varlink::listen(service, &address, 10, timeout)?;
    Ok(())
}
<|endoftext|>


<commit_before>extern crate glium;
extern crate image;
extern crate zip;
extern crate cgmath;
extern crate notify;
extern crate lightfield_loader;

use std::io::Read;
use std::fs::File;
use std::io::Cursor;
use std::mem;

use lightfield_loader::{Lightfield, LightfieldView};

use glium::backend::Facade;
use glium::texture::{MipmapsOption, UncompressedFloatFormat};
use glium::texture::pixel_buffer::PixelBuffer;
use glium::texture::texture2d_array::Texture2dArray;
use std::iter::FromIterator;

use image::{DynamicImage, GenericImage, ImageFormat, Pixel, Rgb};

pub struct LightfieldTexture {
    pub tex: Texture2dArray,
}

impl LightfieldTexture {
    #![allow(dead_code)]
    pub fn new<F: Facade>(facade: &F, zip_filename: &str) -> LightfieldTexture {
        let lf = Lightfield::from_zip(zip_filename).unwrap();

        // FIXME n's and sizes
        let nlayers = lf.views.len() as u32;
        let img0 = &lf.views[0].image;
        let width = img0.width();
        let height = img0.height();
        let num_pixels = (width * height) as usize;

        let tex = Texture2dArray::empty_with_format(facade,
                                                    UncompressedFloatFormat::U8U8U8,
                                                    MipmapsOption::NoMipmap,
                                                    width,
                                                    height,
                                                    nlayers)
                      .unwrap();

        for (_layeridx, view) in lf.views.iter().enumerate() {
            let layeridx = _layeridx as u32;
            let image = &view.image;
            assert!(image.width() == width);
            assert!(image.height() == height);
            match image {
                &DynamicImage::ImageRgb8(_) => {}
                _ => {
                    panic!("Cannot handle this image type");
                }
            }
            println!("loading layer {}", layeridx);
            // TODO: due to wrong pixelbuffer format, texture upload uses format = GL_RED_INTEGER
            // how can i write() to a pixelbuffer with T=(u8,u8,u8,u8) from a [u8] src?
            let buffer = PixelBuffer::<(u8, u8, u8)>::new_empty(facade, num_pixels);
            let pixels: &Vec<u8> = &image.raw_pixels();

            /* //disabled code: format-changing copy for now to make sure no bugs are here
            // better make sure the rust tuple representation is packed,
            // so we can kind of safely transmute
            assert!(mem::size_of::<[(u8,u8,u8); 2]>() == 6);
            let pixel_tuples = unsafe {mem::transmute::<&[u8], &[(u8, u8, u8)]>(pixels)};
            buffer.write(pixel_tuples);
            */
            let rgb_iter = pixels.chunks(3).map(|v| (v[0], v[1], v[2]));
            let tuples: Vec<(u8,u8,u8)> = Vec::from_iter(rgb_iter);
            buffer.write(tuples.as_slice());
            tex.main_level().raw_upload_from_pixel_buffer(buffer.as_slice(),
                                                          0..width,
                                                          0..height,
                                                          layeridx..layeridx + 1);
        }
        unsafe { tex.generate_mipmaps() };
        LightfieldTexture { tex: tex }
    }
}
<commit_msg>Cleanup<commit_after>extern crate glium;
extern crate image;
extern crate zip;
extern crate cgmath;
extern crate notify;
extern crate lightfield_loader;

use lightfield_loader::{Lightfield, LightfieldView};

use glium::backend::Facade;
use glium::texture::{MipmapsOption, UncompressedFloatFormat};
use glium::texture::pixel_buffer::PixelBuffer;
use glium::texture::texture2d_array::Texture2dArray;
use std::iter::FromIterator;

use image::{DynamicImage, GenericImage};

pub struct LightfieldTexture {
    pub tex: Texture2dArray,
}

impl LightfieldTexture {
    #![allow(dead_code)]
    pub fn new<F: Facade>(facade: &F, zip_filename: &str) -> LightfieldTexture {
        let lf = Lightfield::from_zip(zip_filename).unwrap();
        let nlayers = lf.views.len() as u32;
        let img0 = &lf.views[0].image;
        let width = img0.width();
        let height = img0.height();
        let num_pixels = (width * height) as usize;

        let tex = Texture2dArray::empty_with_format(facade,
                                                    UncompressedFloatFormat::U8U8U8,
                                                    MipmapsOption::NoMipmap,
                                                    width,
                                                    height,
                                                    nlayers).unwrap();

        for (_layeridx, view) in lf.views.iter().enumerate() {
            let layeridx = _layeridx as u32;
            let image = &view.image;
            assert!(image.width() == width);
            assert!(image.height() == height);
            match image {
                &DynamicImage::ImageRgb8(_) => {}
                _ => {
                    panic!("Cannot handle this image type");
                }
            }
            debug!("loading layer {}", layeridx);
            let buffer = PixelBuffer::<(u8, u8, u8)>::new_empty(facade, num_pixels);
            let pixels: &Vec<u8> = &image.raw_pixels();
            let rgb_iter = pixels.chunks(3).map(|v| (v[0], v[1], v[2]));
            let tuples: Vec<(u8, u8, u8)> = Vec::from_iter(rgb_iter);
            buffer.write(tuples.as_slice());
            tex.main_level().raw_upload_from_pixel_buffer(buffer.as_slice(),
                                                          0..width,
                                                          0..height,
                                                          layeridx..layeridx + 1);
        }
        unsafe { tex.generate_mipmaps() };
        LightfieldTexture { tex: tex }
    }
}
<|endoftext|>


<commit_before>//! Compile time optimized maps and sets.
//!
//! PHF data structures can be generated via the syntax extensions in the
//! `phf_macros` crate or via code generation in the `phf_codegen` crate. See
//! the documentation of those crates for more details.
#![doc(html_root_url="https://sfackler.github.io/rust-phf/doc/v0.7.5")]
#![warn(missing_docs)]
#![cfg_attr(feature = "core", feature(no_std))]
#![cfg_attr(feature = "core", no_std)]

#[cfg(not(feature = "core"))]
extern crate std as core;

extern crate phf_shared;

pub use phf_shared::PhfHash;
#[doc(inline)]
pub use map::Map;
#[doc(inline)]
pub use set::Set;
#[doc(inline)]
pub use ordered_map::OrderedMap;
#[doc(inline)]
pub use ordered_set::OrderedSet;

pub mod map;
pub mod set;
pub mod ordered_map;
pub mod ordered_set;
<commit_msg>Fix core feature build<commit_after>//! Compile time optimized maps and sets.
//!
//! PHF data structures can be generated via the syntax extensions in the
//! `phf_macros` crate or via code generation in the `phf_codegen` crate. See
//! the documentation of those crates for more details.
#![doc(html_root_url="https://sfackler.github.io/rust-phf/doc/v0.7.5")]
#![warn(missing_docs)]
#![cfg_attr(feature = "core", feature(no_std, core_slice_ext))]
#![cfg_attr(feature = "core", no_std)]

#[cfg(not(feature = "core"))]
extern crate std as core;

extern crate phf_shared;

pub use phf_shared::PhfHash;
#[doc(inline)]
pub use map::Map;
#[doc(inline)]
pub use set::Set;
#[doc(inline)]
pub use ordered_map::OrderedMap;
#[doc(inline)]
pub use ordered_set::OrderedSet;

pub mod map;
pub mod set;
pub mod ordered_map;
pub mod ordered_set;
<|endoftext|>


<commit_before>use ast::FieldList;
use syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner, RefType, Type};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: add_lifetime_to_type
//
// Adds a new lifetime to a struct, enum or union.
//
// ```
// struct Point$0 {
//     x: &u32,
//     y: u32,
// }
// ```
// ->
// ```
// struct Point<'a> {
//     x: &'a u32,
//     y: u32,
// }
// ```
pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let node = ctx.find_node_at_offset::<ast::AdtDef>()?;
    let has_lifetime = node
        .generic_param_list()
        .map(|gen_list| gen_list.lifetime_params().count() > 0)
        .unwrap_or_default();

    if has_lifetime {
        return None;
    }

    let ref_types = fetch_borrowed_types(&node)?;
    let target = node.syntax().text_range();

    acc.add(
        AssistId("add_lifetime_to_type", AssistKind::Generate),
        "Add lifetime`",
        target,
        |builder| {
            match node.generic_param_list() {
                Some(gen_param) => {
                    if let Some(left_angle) = gen_param.l_angle_token() {
                        builder.insert(left_angle.text_range().end(), "'a, ");
                    }
                }
                None => {
                    if let Some(name) = node.name() {
                        builder.insert(name.syntax().text_range().end(), "<'a>");
                    }
                }
            }

            for ref_type in ref_types {
                if let Some(amp_token) = ref_type.amp_token() {
                    builder.insert(amp_token.text_range().end(), "'a ");
                }
            }
        },
    )
}

fn fetch_borrowed_types(node: &ast::AdtDef) -> Option<Vec<RefType>> {
    let ref_types: Vec<RefType> = match node {
        ast::AdtDef::Enum(enum_) => {
            let variant_list = enum_.variant_list()?;
            variant_list
                .variants()
                .filter_map(|variant| {
                    let field_list = variant.field_list()?;

                    find_ref_types_from_field_list(&field_list)
                })
                .flatten()
                .collect()
        }
        ast::AdtDef::Struct(strukt) => {
            let field_list = strukt.field_list()?;
            find_ref_types_from_field_list(&field_list)?
        }
        ast::AdtDef::Union(un) => {
            let record_field_list = un.record_field_list()?;
            record_field_list
                .fields()
                .filter_map(|r_field| {
                    if let Type::RefType(ref_type) = r_field.ty()? {
                        if ref_type.lifetime().is_none() {
                            return Some(ref_type);
                        }
                    }

                    None
                })
                .collect()
        }
    };

    if ref_types.is_empty() {
        None
    } else {
        Some(ref_types)
    }
}

fn find_ref_types_from_field_list(field_list: &FieldList) -> Option<Vec<RefType>> {
    let ref_types: Vec<RefType> = match field_list {
        ast::FieldList::RecordFieldList(record_list) => record_list
            .fields()
            .filter_map(|f| {
                if let Type::RefType(ref_type) = f.ty()? {
                    if ref_type.lifetime().is_none() {
                        return Some(ref_type);
                    }
                }

                None
            })
            .collect(),
        ast::FieldList::TupleFieldList(tuple_field_list) => tuple_field_list
            .fields()
            .filter_map(|f| {
                if let Type::RefType(ref_type) = f.ty()? {
                    if ref_type.lifetime().is_none() {
                        return Some(ref_type);
                    }
                }

                None
            })
            .collect(),
    };

    if ref_types.is_empty() {
        None
    } else {
        Some(ref_types)
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn add_lifetime_to_struct() {
        check_assist(
            add_lifetime_to_type,
            "struct Foo$0 { a: &i32 }",
            "struct Foo<'a> { a: &'a i32 }",
        );

        check_assist(
            add_lifetime_to_type,
            "struct Foo$0 { a: &i32, b: &usize }",
            "struct Foo<'a> { a: &'a i32, b: &'a usize }",
        );

        check_assist(
            add_lifetime_to_type,
            "struct Foo<T>$0 { a: &T, b: usize }",
            "struct Foo<'a, T> { a: &'a T, b: usize }",
        );

        check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a>$0 { a: &'a i32 }");
        check_assist_not_applicable(add_lifetime_to_type, "struct Foo$0 { a: &'a i32 }");
    }

    #[test]
    fn add_lifetime_to_enum() {
        check_assist(
            add_lifetime_to_type,
            "enum Foo$0 { Bar { a: i32 }, Other, Tuple(u32, &u32)}",
            "enum Foo<'a> { Bar { a: i32 }, Other, Tuple(u32, &'a u32)}",
        );

        check_assist(
            add_lifetime_to_type,
            "enum Foo$0 { Bar { a: &i32 }}",
            "enum Foo<'a> { Bar { a: &'a i32 }}",
        );

        check_assist(
            add_lifetime_to_type,
            "enum Foo<T>$0 { Bar { a: &i32, b: &T }}",
            "enum Foo<'a, T> { Bar { a: &'a i32, b: &'a T }}",
        );

        check_assist_not_applicable(add_lifetime_to_type, "enum Foo<'a>$0 { Bar { a: &'a i32 }}");
        check_assist_not_applicable(add_lifetime_to_type, "enum Foo$0 { Bar, Misc }");
    }

    #[test]
    fn add_lifetime_to_union() {
        check_assist(
            add_lifetime_to_type,
            "union Foo$0 { a: &i32 }",
            "union Foo<'a> { a: &'a i32 }",
        );

        check_assist(
            add_lifetime_to_type,
            "union Foo$0 { a: &i32, b: &usize }",
            "union Foo<'a> { a: &'a i32, b: &'a usize }",
        );

        check_assist(
            add_lifetime_to_type,
            "union Foo<T>$0 { a: &T, b: usize }",
            "union Foo<'a, T> { a: &'a T, b: usize }",
        );

        check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a>$0 { a: &'a i32 }");
    }
}
<commit_msg>Add assist: add lifetime to type #7200<commit_after>use ast::FieldList;
use syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner, RefType, Type};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: add_lifetime_to_type
//
// Adds a new lifetime to a struct, enum or union.
//
// ```
// struct Point$0 {
//     x: &u32,
//     y: u32,
// }
// ```
// ->
// ```
// struct Point<'a> {
//     x: &'a u32,
//     y: u32,
// }
// ```
pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let node = ctx.find_node_at_offset::<ast::AdtDef>()?;
    let has_lifetime = node
        .generic_param_list()
        .map(|gen_list| gen_list.lifetime_params().count() > 0)
        .unwrap_or_default();

    if has_lifetime {
        return None;
    }

    let ref_types = fetch_borrowed_types(&node)?;
    let target = node.syntax().text_range();

    acc.add(
        AssistId("add_lifetime_to_type", AssistKind::Generate),
        "Add lifetime`",
        target,
        |builder| {
            match node.generic_param_list() {
                Some(gen_param) => {
                    if let Some(left_angle) = gen_param.l_angle_token() {
                        builder.insert(left_angle.text_range().end(), "'a, ");
                    }
                }
                None => {
                    if let Some(name) = node.name() {
                        builder.insert(name.syntax().text_range().end(), "<'a>");
                    }
                }
            }

            for ref_type in ref_types {
                if let Some(amp_token) = ref_type.amp_token() {
                    builder.insert(amp_token.text_range().end(), "'a ");
                }
            }
        },
    )
}

fn fetch_borrowed_types(node: &ast::AdtDef) -> Option<Vec<RefType>> {
    let ref_types: Vec<RefType> = match node {
        ast::AdtDef::Enum(enum_) => {
            let variant_list = enum_.variant_list()?;
            variant_list
                .variants()
                .filter_map(|variant| {
                    let field_list = variant.field_list()?;

                    find_ref_types_from_field_list(&field_list)
                })
                .flatten()
                .collect()
        }
        ast::AdtDef::Struct(strukt) => {
            let field_list = strukt.field_list()?;
            find_ref_types_from_field_list(&field_list)?
        }
        ast::AdtDef::Union(un) => {
            let record_field_list = un.record_field_list()?;
            record_field_list
                .fields()
                .filter_map(|r_field| {
                    if let Type::RefType(ref_type) = r_field.ty()? {
                        if ref_type.lifetime().is_none() {
                            return Some(ref_type);
                        }
                    }

                    None
                })
                .collect()
        }
    };

    if ref_types.is_empty() {
        None
    } else {
        Some(ref_types)
    }
}

fn find_ref_types_from_field_list(field_list: &FieldList) -> Option<Vec<RefType>> {
    let ref_types: Vec<RefType> = match field_list {
        ast::FieldList::RecordFieldList(record_list) => record_list
            .fields()
            .filter_map(|f| {
                if let Type::RefType(ref_type) = f.ty()? {
                    if ref_type.lifetime().is_none() {
                        return Some(ref_type);
                    }
                }

                None
            })
            .collect(),
        ast::FieldList::TupleFieldList(tuple_field_list) => tuple_field_list
            .fields()
            .filter_map(|f| {
                if let Type::RefType(ref_type) = f.ty()? {
                    if ref_type.lifetime().is_none() {
                        return Some(ref_type);
                    }
                }

                None
            })
            .collect(),
    };

    if ref_types.is_empty() {
        None
    } else {
        Some(ref_types)
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn add_lifetime_to_struct() {
        check_assist(
            add_lifetime_to_type,
            "struct Foo$0 { a: &i32 }",
            "struct Foo<'a> { a: &'a i32 }",
        );

        check_assist(
            add_lifetime_to_type,
            "struct Foo$0 { a: &i32, b: &usize }",
            "struct Foo<'a> { a: &'a i32, b: &'a usize }",
        );

        check_assist(
            add_lifetime_to_type,
            "struct Foo { a: &$0i32, b: usize }",
            "struct Foo<'a> { a: &'a i32, b: usize }",
        );

        check_assist(
            add_lifetime_to_type,
            "struct Foo<T>$0 { a: &T, b: usize }",
            "struct Foo<'a, T> { a: &'a T, b: usize }",
        );

        check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a>$0 { a: &'a i32 }");
        check_assist_not_applicable(add_lifetime_to_type, "struct Foo$0 { a: &'a i32 }");
    }

    #[test]
    fn add_lifetime_to_enum() {
        check_assist(
            add_lifetime_to_type,
            "enum Foo$0 { Bar { a: i32 }, Other, Tuple(u32, &u32)}",
            "enum Foo<'a> { Bar { a: i32 }, Other, Tuple(u32, &'a u32)}",
        );

        check_assist(
            add_lifetime_to_type,
            "enum Foo$0 { Bar { a: &i32 }}",
            "enum Foo<'a> { Bar { a: &'a i32 }}",
        );

        check_assist(
            add_lifetime_to_type,
            "enum Foo<T>$0 { Bar { a: &i32, b: &T }}",
            "enum Foo<'a, T> { Bar { a: &'a i32, b: &'a T }}",
        );

        check_assist_not_applicable(add_lifetime_to_type, "enum Foo<'a>$0 { Bar { a: &'a i32 }}");
        check_assist_not_applicable(add_lifetime_to_type, "enum Foo$0 { Bar, Misc }");
    }

    #[test]
    fn add_lifetime_to_union() {
        check_assist(
            add_lifetime_to_type,
            "union Foo$0 { a: &i32 }",
            "union Foo<'a> { a: &'a i32 }",
        );

        check_assist(
            add_lifetime_to_type,
            "union Foo$0 { a: &i32, b: &usize }",
            "union Foo<'a> { a: &'a i32, b: &'a usize }",
        );

        check_assist(
            add_lifetime_to_type,
            "union Foo<T>$0 { a: &T, b: usize }",
            "union Foo<'a, T> { a: &'a T, b: usize }",
        );

        check_assist_not_applicable(add_lifetime_to_type, "struct Foo<'a>$0 { a: &'a i32 }");
    }
}
<|endoftext|>


<commit_before>

/// Logging handle used to execute logging statements
///
/// `Logger` holds logging context (key-value pairs) and handles logging
/// statements by delivering all logging statement information (`Record`)
/// to it's `Drain`.
///
/// Child loggers are build from existing loggers, and inherit their existing
/// key-value pairs, which can be supplemented with new ones.
///
/// Cloning existing loggers and creating new ones is cheap. Loggers can be
/// freely passed around the code and between threads. `Logger`s are also
/// `Sync` - there's no need to synchronize accesses to them.
#[derive(Clone)]
pub struct Logger {
    drain: Arc<Drain<Error=Never>+Send+Sync>,
    list: OwnedKVList,
}

impl Logger {
    /// Build a root `Logger`
    ///
    /// All children and their children and so on form one hierarchy
    /// sharing a common drain.
    ///
    /// Root logger starts a new hierarchy associated with a given `Drain`. Root
    /// logger drain must return no errors. See `DrainExt::ignore_err()` and
    /// `DrainExt::fuse()`.
    ///
    /// Use `o!` macro to build `OwnedKV` object..
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    ///
    /// fn main() {
    ///     let _root = slog::Logger::root(
    ///         slog::Discard,
    ///         o!("key1" => "value1", "key2" => "value2"),
    ///     );
    /// }
    pub fn root<D>(d: D, values: OwnedKV) -> Logger
    where D: 'static + Drain<Error=Never> + Sized+Send+Sync{
        Logger {
            drain: Arc::new(d),
            list: OwnedKVList::root(values),
        }
    }

    /// Build a child logger
    ///
    /// Child logger inherits all existing key-value pairs from it's parent.
    ///
    /// All children, their children and so on, form one hierarchy sharing
    /// a common drain.
    ///
    /// Use `o!` macro to help build key value pairs using nicer syntax.
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    ///
    /// fn main() {
    ///     let root = slog::Logger::root(slog::Discard,
    ///         o!("key1" => "value1", "key2" => "value2"));
    ///     let _log = root.new(o!("key" => "value"));
    /// }
    pub fn new(&self, values: OwnedKV) -> Logger {
        Logger {
            drain: self.drain.clone(),
            list: OwnedKVList::new(values, self.list.node.clone()),
        }
    }

    /// Log one logging record
    ///
    /// Use specific logging functions instead. See `log!` macro
    /// documentation.
    #[inline]
    pub fn log(&self, record: &Record) {
        let _ = self.drain.log(
            &record,
            &self.list,
            );
    }
}

impl fmt::Debug for Logger {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "Logger{:?}", self.list));
        Ok(())
    }
}

impl Drain for Logger {

    type Error = Never;

    fn log(&self, record: &Record, values : &OwnedKVList) -> result::Result<(), Self::Error> {
        debug_assert!(self.list.next_list.is_none());

        let chained = values.append(&self.list);
        self.drain.log(
            &record,
            &chained,
            )
    }
}

<commit_msg>Add more `Logger` documentation<commit_after>

/// Logging handle used to execute logging statements
///
/// `Logger` holds logging context (key-value pairs) and handles logging
/// statements by delivering all logging statement information (`Record`)
/// to it's `Drain`.
///
/// Child loggers are build from existing loggers, and inherit their existing
/// key-value pairs, which can be supplemented with new ones.
///
/// Cloning existing loggers and creating new ones is cheap. Loggers can be
/// freely passed around the code and between threads.
///
/// `Logger`s are also `Sync` - there's no need to synchronize accesses to them,
/// and they can accept logging records from multiple threads at once. Because of
/// that they require the `Drain` to be `Sync+Sync` as well. Not all `Drain`s
/// are `Sync` or `Send` but they can often be made so by wrapping in a `Mutex`
/// and/or `Arc`.
#[derive(Clone)]
pub struct Logger {
    drain: Arc<Drain<Error=Never>+Send+Sync>,
    list: OwnedKVList,
}

impl Logger {
    /// Build a root `Logger`
    ///
    /// All children and their children and so on form one hierarchy
    /// sharing a common drain.
    ///
    /// Root logger starts a new hierarchy associated with a given `Drain`. Root
    /// logger drain must return no errors. See `DrainExt::ignore_err()` and
    /// `DrainExt::fuse()`.
    ///
    /// Use `o!` macro to build `OwnedKV` object..
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    ///
    /// fn main() {
    ///     let _root = slog::Logger::root(
    ///         slog::Discard,
    ///         o!("key1" => "value1", "key2" => "value2"),
    ///     );
    /// }
    pub fn root<D>(d: D, values: OwnedKV) -> Logger
    where D: 'static + Drain<Error=Never> + Sized+Send+Sync{
        Logger {
            drain: Arc::new(d),
            list: OwnedKVList::root(values),
        }
    }

    /// Build a child logger
    ///
    /// Child logger inherits all existing key-value pairs from it's parent.
    ///
    /// All children, their children and so on, form one hierarchy sharing
    /// a common drain.
    ///
    /// Use `o!` macro to help build key value pairs using nicer syntax.
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    ///
    /// fn main() {
    ///     let root = slog::Logger::root(slog::Discard,
    ///         o!("key1" => "value1", "key2" => "value2"));
    ///     let _log = root.new(o!("key" => "value"));
    /// }
    pub fn new(&self, values: OwnedKV) -> Logger {
        Logger {
            drain: self.drain.clone(),
            list: OwnedKVList::new(values, self.list.node.clone()),
        }
    }

    /// Log one logging record
    ///
    /// Use specific logging functions instead. See `log!` macro
    /// documentation.
    #[inline]
    pub fn log(&self, record: &Record) {
        let _ = self.drain.log(
            &record,
            &self.list,
            );
    }
}

impl fmt::Debug for Logger {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "Logger{:?}", self.list));
        Ok(())
    }
}

impl Drain for Logger {

    type Error = Never;

    fn log(&self, record: &Record, values : &OwnedKVList) -> result::Result<(), Self::Error> {
        debug_assert!(self.list.next_list.is_none());

        let chained = values.append(&self.list);
        self.drain.log(
            &record,
            &chained,
            )
    }
}

<|endoftext|>


<commit_before>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(value)
    }
}

fn check_call_ret(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

fn get_keyring(id: KeyringSerial, create: bool) -> Result<Keyring> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, Keyring { id: res, })
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, false)
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, true)
    }

    pub fn join_anonymous_session() -> Result<Self> {
        let res = unsafe { keyctl_join_session_keyring(ptr::null()) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn join_session(name: &str) -> Result<Self> {
        let nameptr = CString::new(name).unwrap().as_ptr();
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn search(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, self.id) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        // TODO: turn bytestream into vec of keys
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn find_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { find_key_by_type_and_desc(typeptr, descptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, ptr::null(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key_with_fallback(&mut self, type_: &str, description: &str, info: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let infoptr = CString::new(info).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, infoptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }
}

pub struct Key {
    id: KeyringSerial,
}

extern fn unlink_cb(
    parent:     key_serial_t,
    key:        key_serial_t,
    desc:       *mut libc::c_char,
    desc_len:   libc::c_int,
    data:       *mut libc::c_void)
    -> libc::c_int {
    unimplemented!()
}

impl Key {
    pub fn request(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key(type_, description)
    }

    pub fn request_with_fallback(type_: &str, description: &str, info: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key_with_fallback(type_, description, info)
    }

    pub fn find(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.find_key(type_, description)
    }

    pub fn search(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.search(type_, description)
    }

    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring(self.id, false)
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn unlink(self, keyring: &Keyring) -> Result<()> {
        check_call(unsafe { keyctl_unlink(self.id, keyring.id) }, ())
    }

    pub fn unlink_from_all(self, keyring: &mut Keyring) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_key_scan(keyring.id, unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn unlink_from_session(self) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_session_key_scan(unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, -1) }, ())
    }

    pub fn chgrp(&mut self, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, -1, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<KeyDescription> {
        self.description_raw().map(|desc| {
            KeyDescription::parse(desc)
        })
    }

    fn description_raw(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }

    pub fn manage(&mut self) -> Result<KeyManager> {
        check_call(unsafe { keyctl_assume_authority(self.id) }, KeyManager {
            key: Key {
                id: self.id,
            },
        })
    }
}

pub struct KeyDescription {
    pub type_:          String,
    pub uid:            uid_t,
    pub gid:            gid_t,
    pub perms:          KeyPermissions,
    pub description:    String,
}

impl KeyDescription {
    fn parse(desc: String) -> KeyDescription {
        unimplemented!()
    }
}

pub struct KeyManager {
    key: Key,
}

impl KeyManager {
    pub fn instantiate(self, keyring: &Keyring, payload: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_instantiate(self.key.id, payload.as_ptr() as *const libc::c_void, payload.len(), keyring.id) }, ())
    }

    pub fn reject(self, keyring: &Keyring, timeout: u32, error: errno::Errno) -> Result<()> {
        let errno::Errno(errval) = error;
        check_call(unsafe { keyctl_reject(self.key.id, timeout, errval as u32, keyring.id) }, ())
    }

    pub fn negate(self, keyring: &Keyring, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_negate(self.key.id, timeout, keyring.id) }, ())
    }
}
<commit_msg>api: add a test for basic key manipulation<commit_after>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(value)
    }
}

fn check_call_ret(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

fn get_keyring(id: KeyringSerial, create: bool) -> Result<Keyring> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, Keyring { id: res, })
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, false)
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, true)
    }

    pub fn join_anonymous_session() -> Result<Self> {
        let res = unsafe { keyctl_join_session_keyring(ptr::null()) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn join_session(name: &str) -> Result<Self> {
        let nameptr = CString::new(name).unwrap().as_ptr();
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn search(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, self.id) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        // TODO: turn bytestream into vec of keys
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn find_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { find_key_by_type_and_desc(typeptr, descptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, ptr::null(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key_with_fallback(&mut self, type_: &str, description: &str, info: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let infoptr = CString::new(info).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, infoptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }
}

pub struct Key {
    id: KeyringSerial,
}

extern fn unlink_cb(
    parent:     key_serial_t,
    key:        key_serial_t,
    desc:       *mut libc::c_char,
    desc_len:   libc::c_int,
    data:       *mut libc::c_void)
    -> libc::c_int {
    unimplemented!()
}

impl Key {
    pub fn request(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key(type_, description)
    }

    pub fn request_with_fallback(type_: &str, description: &str, info: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key_with_fallback(type_, description, info)
    }

    pub fn find(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.find_key(type_, description)
    }

    pub fn search(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.search(type_, description)
    }

    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring(self.id, false)
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn unlink(self, keyring: &Keyring) -> Result<()> {
        check_call(unsafe { keyctl_unlink(self.id, keyring.id) }, ())
    }

    pub fn unlink_from_all(self, keyring: &mut Keyring) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_key_scan(keyring.id, unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn unlink_from_session(self) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_session_key_scan(unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, -1) }, ())
    }

    pub fn chgrp(&mut self, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, -1, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<KeyDescription> {
        self.description_raw().map(|desc| {
            KeyDescription::parse(desc)
        })
    }

    fn description_raw(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }

    pub fn manage(&mut self) -> Result<KeyManager> {
        check_call(unsafe { keyctl_assume_authority(self.id) }, KeyManager {
            key: Key {
                id: self.id,
            },
        })
    }
}

pub struct KeyDescription {
    pub type_:          String,
    pub uid:            uid_t,
    pub gid:            gid_t,
    pub perms:          KeyPermissions,
    pub description:    String,
}

impl KeyDescription {
    fn parse(desc: String) -> KeyDescription {
        unimplemented!()
    }
}

pub struct KeyManager {
    key: Key,
}

impl KeyManager {
    pub fn instantiate(self, keyring: &Keyring, payload: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_instantiate(self.key.id, payload.as_ptr() as *const libc::c_void, payload.len(), keyring.id) }, ())
    }

    pub fn reject(self, keyring: &Keyring, timeout: u32, error: errno::Errno) -> Result<()> {
        let errno::Errno(errval) = error;
        check_call(unsafe { keyctl_reject(self.key.id, timeout, errval as u32, keyring.id) }, ())
    }

    pub fn negate(self, keyring: &Keyring, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_negate(self.key.id, timeout, keyring.id) }, ())
    }
}

#[test]
fn test_add_key() {
    let mut keyring = Keyring::attach_or_create(SpecialKeyring::SessionKeyring.serial()).unwrap();

    // Create the key.
    let payload = "payload";
    let key = keyring.add_key("description", payload.as_bytes()).unwrap();
    assert_eq!(key.read().unwrap(), payload.as_bytes().iter().cloned().collect::<Vec<u8>>());

    // Update the key.
    let new_payload = "payload";
    let updated_key = keyring.add_key("description", new_payload.as_bytes()).unwrap();
    assert_eq!(key.read().unwrap(), new_payload.as_bytes().iter().cloned().collect::<Vec<u8>>());

    // Clean it up.
    key.unlink(&mut keyring);
}
<|endoftext|>


<commit_before>extern crate libc;

use self::libc::{c_int, c_uint, uint8_t};
use crate::defines::{AfError, Backend};
use crate::error::HANDLE_ERROR;

extern "C" {
    fn af_set_backend(bknd: uint8_t) -> c_int;
    fn af_get_backend_count(num_backends: *mut c_uint) -> c_int;
    fn af_get_available_backends(backends: *mut c_int) -> c_int;
    fn af_get_active_backend(backend: *mut c_int) -> c_int;
}

/// Toggle backends between cuda, opencl or cpu
///
/// # Parameters
///
/// - `backend` to which to switch to
pub fn set_backend(backend: Backend) {
    unsafe {
        let err_val = af_set_backend(backend as uint8_t);
        HANDLE_ERROR(AfError::from(err_val));
    }
}

/// Get the available backend count
#[allow(unused_mut)]
pub fn get_backend_count() -> u32 {
    unsafe {
        let mut temp: u32 = 0;
        let err_val = af_get_backend_count(&mut temp as *mut c_uint);
        HANDLE_ERROR(AfError::from(err_val));
        temp
    }
}

/// Get the available backends
#[allow(unused_mut)]
pub fn get_available_backends() -> Vec<Backend> {
    unsafe {
        let mut temp: i32 = 0;
        let err_val = af_get_available_backends(&mut temp as *mut c_int);
        HANDLE_ERROR(AfError::from(err_val));

        let mut b = Vec::new();
        if temp & 0b0100 == 0b0100 {
            b.push(Backend::OPENCL);
        }
        if temp & 0b0010 == 0b0010 {
            b.push(Backend::CUDA);
        }
        if temp & 0b0001 == 0b0001 {
            b.push(Backend::CPU);
        }

        b
    }
}

/// Get current active backend
#[allow(unused_mut)]
pub fn get_active_backend() -> Backend {
    unsafe {
        let mut temp: i32 = 0;
        let err_val = af_get_active_backend(&mut temp as *mut c_int);
        HANDLE_ERROR(AfError::from(err_val));
        match (err_val, temp) {
            (0, 0) => Backend::DEFAULT,
            (0, 1) => Backend::CPU,
            (0, 2) => Backend::CUDA,
            (0, 4) => Backend::OPENCL,
            _ => panic!("Invalid backend retrieved, undefined behavior."),
        }
    }
}
<commit_msg>Replace deprecated uint8_t type with u8<commit_after>extern crate libc;

use self::libc::{c_int, c_uint};
use crate::defines::{AfError, Backend};
use crate::error::HANDLE_ERROR;

extern "C" {
    fn af_set_backend(bknd: u8) -> c_int;
    fn af_get_backend_count(num_backends: *mut c_uint) -> c_int;
    fn af_get_available_backends(backends: *mut c_int) -> c_int;
    fn af_get_active_backend(backend: *mut c_int) -> c_int;
}

/// Toggle backends between cuda, opencl or cpu
///
/// # Parameters
///
/// - `backend` to which to switch to
pub fn set_backend(backend: Backend) {
    unsafe {
        let err_val = af_set_backend(backend as u8);
        HANDLE_ERROR(AfError::from(err_val));
    }
}

/// Get the available backend count
#[allow(unused_mut)]
pub fn get_backend_count() -> u32 {
    unsafe {
        let mut temp: u32 = 0;
        let err_val = af_get_backend_count(&mut temp as *mut c_uint);
        HANDLE_ERROR(AfError::from(err_val));
        temp
    }
}

/// Get the available backends
#[allow(unused_mut)]
pub fn get_available_backends() -> Vec<Backend> {
    unsafe {
        let mut temp: i32 = 0;
        let err_val = af_get_available_backends(&mut temp as *mut c_int);
        HANDLE_ERROR(AfError::from(err_val));

        let mut b = Vec::new();
        if temp & 0b0100 == 0b0100 {
            b.push(Backend::OPENCL);
        }
        if temp & 0b0010 == 0b0010 {
            b.push(Backend::CUDA);
        }
        if temp & 0b0001 == 0b0001 {
            b.push(Backend::CPU);
        }

        b
    }
}

/// Get current active backend
#[allow(unused_mut)]
pub fn get_active_backend() -> Backend {
    unsafe {
        let mut temp: i32 = 0;
        let err_val = af_get_active_backend(&mut temp as *mut c_int);
        HANDLE_ERROR(AfError::from(err_val));
        match (err_val, temp) {
            (0, 0) => Backend::DEFAULT,
            (0, 1) => Backend::CPU,
            (0, 2) => Backend::CUDA,
            (0, 4) => Backend::OPENCL,
            _ => panic!("Invalid backend retrieved, undefined behavior."),
        }
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

/// Balances a chemical reaction using Gaussian elimination
pub fn balance_reaction(reaction: (Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction((lhs, rhs): (Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let mut names = Vec::<&str>::new();
        for molecule in lhs.iter().chain(rhs.iter()) {
            for elem in molecule.iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name.as_slice());
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

mod test {
    use super::*;
    use elem::PerElem;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }
}<commit_msg>Add more tests for the balancer<commit_after>use std::f64;
use std::cmp::min;
use std::num::Float;
use std::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use elem::Molecule;
use error::{CTResult, CTError};
use error::CTErrorKind::InputError;

macro_rules! impl_matrix_index {
    ($idx:ty, $out:ty) => {
        impl Index<$idx> for Matrix {
            type Output = $out;

            fn index(&self, index: &$idx) -> &$out {
                &self.buf[*index]
            }
        }
    }
}

macro_rules! impl_matrix_index_mut {
    ($idx:ty, $out:ty) => {
        impl IndexMut<$idx> for Matrix {
            fn index_mut(&mut self, index: &$idx) -> &mut $out {
                &mut self.buf[*index]
            }
        }
    }
}

/// Balances a chemical reaction using Gaussian elimination
pub fn balance_reaction(reaction: (Vec<Molecule>, Vec<Molecule>)) -> CTResult<Vec<u32>> {
    let reac_mat = Matrix::from_reaction(reaction);
    let reduced_mat = try!(forward_elim(reac_mat));
    let coefs = back_substitute(&reduced_mat);

    // we find the minimum element with fold, since f64 does not implement Ord...
    let min = coefs.iter().fold(f64::INFINITY, |crnt, &num| {
        if num < crnt {
            num
        } else {
            crnt
        }
    });
    // now we divide all elements by the minimum to (hopefully) convert them all to intergers
    // after which we do the actual conversion
    // we also reverse the Vec so the coefs are in the right order
    Ok(coefs.iter().rev().map(|n| (n / min) as u32).collect())
}

fn column_abs_max_index(columns: &[Vec<f64>], column: usize) -> usize {
    let mut max = 0;
    for i in 1..columns.len() {
        if columns[i][column].abs() > columns[max][column].abs() {
            max = i;
        }
    }
    max
}

fn forward_elim(mut mat: Matrix) -> CTResult<Matrix> {
    for k in 0..min(mat.width(), mat.height()) {
        // locate the pivot
        let pivot = column_abs_max_index(&mat[k..], k) + k;
        if mat[pivot][k] == 0_f64 {
            return Err(CTError {
                kind: InputError,
                desc: "Could not balance reaction".to_string(),
                pos: None,
            })
        }
        // move the pivot to its new position
        mat.switch_rows(k, pivot);

        // zero out the rest of the column
        for i in k + 1..mat.height() {
            let mult = -(mat[i][k] / mat[k][k]);
            mat.add_row_to_row(i, k, mult);
        }
    }
    Ok(mat)
}

fn back_substitute(mat: &Matrix) -> Vec<f64> {
    let mut vars = Vec::with_capacity(mat.width());
    for k in (0..mat.width()).rev() {
        if k >= mat.height() {
            // if this coef does not have a corresponding row in the matrix, then treat is as a
            // free variable and set it to 1
            vars.push(1_f64);
        } else {
            let mut var = 0f64;
            for i in k + 1..mat.width() {
                var -= mat[k][i] * vars[mat.width() - 1 - i];
            }
            vars.push(var / mat[k][k]);
        }
    }
    vars
}

#[derive(Debug, PartialEq)]
struct Matrix {
    buf: Vec<Vec<f64>>,
    height: usize,
    width: usize,
}

impl Matrix {
    fn from_reaction((lhs, rhs): (Vec<Molecule>, Vec<Molecule>)) -> Matrix {
        let mut names = Vec::<&str>::new();
        for molecule in lhs.iter().chain(rhs.iter()) {
            for elem in molecule.iter() {
                if names.iter().find(|e| **e == elem.name).is_none() {
                    names.push(elem.name.as_slice());
                }
            }
        }
        let mut buf = Vec::with_capacity(names.len());
        for name in names.iter() {
            let mut row = Vec::with_capacity(lhs.len() + rhs.len());
            for molecule in lhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(e.coef as f64))
                                 .unwrap_or(0_f64));
            }
            // we loop over rhs seperately, since we need to multiply the coefs with -1
            for molecule in rhs.iter() {
                row.push(molecule.iter()
                                 .find(|e| e.name == *name)
                                 .and_then(|e| Some(-1.0*(e.coef as f64)))
                                 .unwrap_or(0_f64));
            }
            buf.push(row);
        }
        let height = names.len();
        let width = lhs.len() + rhs.len();
        Matrix {
            buf: buf,
            height: height,
            width: width,
        }
    }

    fn add_row_to_row(&mut self, dest: usize, row: usize, mult: f64) {
        for i in 0..self.width {
            let incr = self.buf[row][i] * mult;
            self.buf[dest][i] += incr;
        }
    }

    fn switch_rows(&mut self, row1: usize, row2: usize)  {
        self.buf.swap(row1, row2);
    }

    fn width(&self) -> usize {
        self.width
    }

    fn height(&self) -> usize {
        self.height
    }
}

impl_matrix_index!(usize, Vec<f64>);
impl_matrix_index!(Range<usize>, [Vec<f64>]);
impl_matrix_index!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index!(RangeFull, [Vec<f64>]);

impl_matrix_index_mut!(usize, Vec<f64>);
impl_matrix_index_mut!(Range<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeTo<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFrom<usize>, [Vec<f64>]);
impl_matrix_index_mut!(RangeFull, [Vec<f64>]);

mod test {
    use super::*;
    use elem::PerElem;
    use error::CTErrorKind::InputError;

    macro_rules! dummy_elem(
        ($name:expr) => (
            PerElem { name: $name.to_string(), coef: 1, pos: 0, len: 1 }
        );
        ($name:expr, $coef:expr) => (
            PerElem { name: $name.to_string(), coef: $coef, pos: 0, len: 1 }
        );
    );

    #[test]
    fn balance() {
        // attempt to balance C3H8 + O2 -> CO2 + H2O
        let reaction = (vec!(vec!(dummy_elem!("C", 3), dummy_elem!("H", 8)),
                             vec!(dummy_elem!("O", 2))),
                        vec!(vec!(dummy_elem!("C", 1), dummy_elem!("O", 2)),
                             vec!(dummy_elem!("H", 2), dummy_elem!("O", 1))));
        let result = balance_reaction(reaction);
        let expected = Ok(vec!(1, 5, 3, 4));
        assert_eq!(result, expected);
    }

    #[test]
    fn no_balance_needed() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))));
        let result = balance_reaction(reaction);
        let expected = Ok(vec!(1, 1, 1, 1));
        assert_eq!(result, expected);
    }

    #[test]
    fn missing_elem() {
        let reaction = (vec!(vec!(dummy_elem!("C", 1)), vec!(dummy_elem!("H", 1))),
                        vec!(vec!(dummy_elem!("C", 1))));
        let result = balance_reaction(reaction);
        println!("{:?}", result);
        assert!(result.is_err());
        assert_eq!(result.err().unwrap().kind, InputError);
    }
}<|endoftext|>