<commit_before>extern crate erl_nif_sys;

#[cfg(unix)]
#[test]
fn test1() {
    use erl_nif_sys::*;
    use std::collections::HashMap;
    use std::env;
    use std::iter::FromIterator;
    use std::mem::size_of;
    use std::path::Path;
    use std::process::Command;

    let out_dir = env::var("OUT_DIR").unwrap();

    // use environment escript and cc if available
    let escript = env::var("ESCRIPT").unwrap_or("escript".to_string());
    let cc = env::var("CC").unwrap_or("cc".to_string());

    // get erts include path
    let erts_include = Command::new(escript)
        .arg("get_erts_path.erl")
        .output()
        .map_err(|_| "Can't run escript")
        .map(|out| match out.status.success() {
            true => out.stdout,
            false => panic!("Can't run get_erts_path.erl"),
        })
        .map(String::from_utf8)
        .unwrap()
        .unwrap();

    //println!("include {:?}", erts_include);

    // Compile C program
    let exe = Path::new(&out_dir).join("struct_size");
    match Command::new(cc)
        .arg("-o")
        .arg(&exe)
        .arg("-I")
        .arg(&erts_include)
        .arg("tests/struct_size.c")
        .status()
        .map_err(|_| "Can't find c compiler (cc or value of environment CC)")
        .unwrap()
        .success()
    {
        false => panic!("Can't compile struct_size.c"),
        _ => (),
    }

    // Run C program that lists C NIF runtime information.
    let stdout: Vec<u8> = Command::new(&exe)
        .output()
        .map_err(|_| "Can't run C runtime information program")
        .unwrap()
        .stdout;

    let output: &str = std::str::from_utf8(&stdout).unwrap();

    // Parse C program output into hashmap of (&str, u32)
    let sizemap = HashMap::<&str, usize>::from_iter(
        output
            .lines()
            .map(|ln| ln.split(" "))
            .map(|mut it| (it.next().unwrap(), it.next().unwrap().parse().unwrap())),
    );

    /* types to check are:

    ERL_NIF_UINT
    ERL_NIF_TERM
    ErlNifFunc
    ErlNifEntry
    ErlNifBinary
    ErlNifPid
    ErlNifSysInfo
    ErlNifMapIterator

    */

    assert_eq!(
        &size_of::<ERL_NIF_UINT>(),
        sizemap.get("ERL_NIF_UINT").unwrap()
    );
    assert_eq!(
        &size_of::<ERL_NIF_TERM>(),
        sizemap.get("ERL_NIF_TERM").unwrap()
    );
    assert_eq!(&size_of::<ErlNifFunc>(), sizemap.get("ErlNifFunc").unwrap());

    // Disabling this test because struct size grew in otp-20 but remains
    // backwards compatible.

    // assert_eq!(&size_of::<ErlNifEntry>(),       sizemap.get("ErlNifEntry").unwrap());

    assert_eq!(
        &size_of::<ErlNifBinary>(),
        sizemap.get("ErlNifBinary").unwrap()
    );
    assert_eq!(&size_of::<ErlNifPid>(), sizemap.get("ErlNifPid").unwrap());
    assert_eq!(
        &size_of::<ErlNifSysInfo>(),
        sizemap.get("ErlNifSysInfo").unwrap()
    );
    assert_eq!(
        &size_of::<ErlNifMapIterator>(),
        sizemap.get("ErlNifMapIterator").unwrap()
    );
}
<commit_msg>ErlNifBinary size is different between 19, 20, and 21<commit_after>extern crate erl_nif_sys;

#[cfg(unix)]
#[test]
fn test1() {
    use erl_nif_sys::*;
    use std::collections::HashMap;
    use std::env;
    use std::iter::FromIterator;
    use std::mem::size_of;
    use std::path::Path;
    use std::process::Command;

    let out_dir = env::var("OUT_DIR").unwrap();

    // use environment escript and cc if available
    let escript = env::var("ESCRIPT").unwrap_or("escript".to_string());
    let cc = env::var("CC").unwrap_or("cc".to_string());

    // get erts include path
    let erts_include = Command::new(escript)
        .arg("get_erts_path.erl")
        .output()
        .map_err(|_| "Can't run escript")
        .map(|out| match out.status.success() {
            true => out.stdout,
            false => panic!("Can't run get_erts_path.erl"),
        })
        .map(String::from_utf8)
        .unwrap()
        .unwrap();

    //println!("include {:?}", erts_include);

    // Compile C program
    let exe = Path::new(&out_dir).join("struct_size");
    match Command::new(cc)
        .arg("-o")
        .arg(&exe)
        .arg("-I")
        .arg(&erts_include)
        .arg("tests/struct_size.c")
        .status()
        .map_err(|_| "Can't find c compiler (cc or value of environment CC)")
        .unwrap()
        .success()
    {
        false => panic!("Can't compile struct_size.c"),
        _ => (),
    }

    // Run C program that lists C NIF runtime information.
    let stdout: Vec<u8> = Command::new(&exe)
        .output()
        .map_err(|_| "Can't run C runtime information program")
        .unwrap()
        .stdout;

    let output: &str = std::str::from_utf8(&stdout).unwrap();

    // Parse C program output into hashmap of (&str, u32)
    let sizemap = HashMap::<&str, usize>::from_iter(
        output
            .lines()
            .map(|ln| ln.split(" "))
            .map(|mut it| (it.next().unwrap(), it.next().unwrap().parse().unwrap())),
    );

    /* types to check are:

    ERL_NIF_UINT
    ERL_NIF_TERM
    ErlNifFunc
    ErlNifEntry
    ErlNifBinary
    ErlNifPid
    ErlNifSysInfo
    ErlNifMapIterator

    */

    assert_eq!(
        &size_of::<ERL_NIF_UINT>(),
        sizemap.get("ERL_NIF_UINT").unwrap()
    );
    assert_eq!(
        &size_of::<ERL_NIF_TERM>(),
        sizemap.get("ERL_NIF_TERM").unwrap()
    );
    assert_eq!(&size_of::<ErlNifFunc>(), sizemap.get("ErlNifFunc").unwrap());

    // Disabling this test because struct size grew in otp-20 but remains
    // backwards compatible.

    //assert_eq!(
    //&size_of::<ErlNifEntry>(),
    //sizemap.get("ErlNifEntry").unwrap()
    //);

    //assert_eq!(
    //&size_of::<ErlNifBinary>(),
    //sizemap.get("ErlNifBinary").unwrap()
    //);
    assert_eq!(&size_of::<ErlNifPid>(), sizemap.get("ErlNifPid").unwrap());
    assert_eq!(
        &size_of::<ErlNifSysInfo>(),
        sizemap.get("ErlNifSysInfo").unwrap()
    );
    assert_eq!(
        &size_of::<ErlNifMapIterator>(),
        sizemap.get("ErlNifMapIterator").unwrap()
    );
}
<|endoftext|>


<commit_before>use libc::{c_char, execvp};
use std::io::prelude::*;
use std::ffi::CString;
use std::ptr;

macro_rules! c_ptr {
    ($x:expr) => {{ CString::new($x).unwrap().as_ptr() }};
}

fn exec_ssh(ip: &str, command: &str, verbose: bool) {
    let user_host: &str = &format!("rightscale@{}", ip);
    let ssh_command = format!("ssh -t -o StrictHostKeychecking=no -o UserKnownHostsFile=/dev/null {} \"{}\"", user_host, command);

    if verbose { println!("Running {}", ssh_command) }

    let argv: &[*const c_char] = &[c_ptr!("ssh"),
                                   c_ptr!("-t"),
                                   c_ptr!("-o"),
                                   c_ptr!("StrictHostKeyChecking=no"),
                                   c_ptr!("-o"),
                                   c_ptr!("UserKnownHostsFile=/dev/null"),
                                   c_ptr!(user_host),
                                   c_ptr!(command),
                                   ptr::null()];

    unsafe { execvp(argv[0], &argv[0]); }

    die!("ssh command failed: {}", ssh_command);
}

fn ssh_command_arg(user: Option<String>, command: Option<String>) -> String {
    let user_prefix = user.and_then(|u| Some(format!("sudo -u \"{}\"", u)));
    let escaped_command = command.and_then(|c| Some(c.replace("'", "'\\''")));

    match user_prefix {
        Some(u) =>
            match escaped_command {
                Some(c) => format!("{} -- sh -c '{}'", u, c),
                None => format!("{} -s", u)
            },
        None => escaped_command.unwrap_or("".to_string())
    }
}

pub fn ssh_connect(ip: String, user: Option<String>, command: Option<String>, verbose: bool) {
    exec_ssh(&ip, &ssh_command_arg(user, command), verbose);
}

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

        #[test]
        fn no_user() {
            assert_eq!("pwd".to_string(),
                       ssh_command_arg(None, Some("pwd".to_string())));
        }

        #[test]
        fn no_command() {
            assert_eq!("sudo -u \"sean\" -s".to_string(),
                       ssh_command_arg(Some("sean".to_string()), None));
        }

        #[test]
        fn user_and_command() {
            assert_eq!("sudo -u \"sean\" -- sh -c 'cd / && /bin/bash'".to_string(),
                       ssh_command_arg(Some("sean".to_string()), Some("cd / && /bin/bash".to_string())));
        }
    }
}
<commit_msg>Use login shell when user and command are set<commit_after>use libc::{c_char, execvp};
use std::io::prelude::*;
use std::ffi::CString;
use std::ptr;

macro_rules! c_ptr {
    ($x:expr) => {{ CString::new($x).unwrap().as_ptr() }};
}

fn exec_ssh(ip: &str, command: &str, verbose: bool) {
    let user_host: &str = &format!("rightscale@{}", ip);
    let ssh_command = format!("ssh -t -o StrictHostKeychecking=no -o UserKnownHostsFile=/dev/null {} \"{}\"", user_host, command);

    if verbose { println!("Running {}", ssh_command) }

    let argv: &[*const c_char] = &[c_ptr!("ssh"),
                                   c_ptr!("-t"),
                                   c_ptr!("-o"),
                                   c_ptr!("StrictHostKeyChecking=no"),
                                   c_ptr!("-o"),
                                   c_ptr!("UserKnownHostsFile=/dev/null"),
                                   c_ptr!(user_host),
                                   c_ptr!(command),
                                   ptr::null()];

    unsafe { execvp(argv[0], &argv[0]); }

    die!("ssh command failed: {}", ssh_command);
}

fn ssh_command_arg(user: Option<String>, command: Option<String>) -> String {
    let user_prefix = user.and_then(|u| Some(format!("sudo -u \"{}\"", u)));
    let escaped_command = command.and_then(|c| Some(c.replace("'", "'\\''")));

    match user_prefix {
        Some(u) =>
            match escaped_command {
                Some(c) => format!("{} -- sh -cl '{}'", u, c),
                None => format!("{} -s", u)
            },
        None => escaped_command.unwrap_or("".to_string())
    }
}

pub fn ssh_connect(ip: String, user: Option<String>, command: Option<String>, verbose: bool) {
    exec_ssh(&ip, &ssh_command_arg(user, command), verbose);
}

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

        #[test]
        fn no_user() {
            assert_eq!("pwd".to_string(),
                       ssh_command_arg(None, Some("pwd".to_string())));
        }

        #[test]
        fn no_command() {
            assert_eq!("sudo -u \"sean\" -s".to_string(),
                       ssh_command_arg(Some("sean".to_string()), None));
        }

        #[test]
        fn user_and_command() {
            assert_eq!("sudo -u \"sean\" -- sh -cl 'cd / && /bin/bash'".to_string(),
                       ssh_command_arg(Some("sean".to_string()), Some("cd / && /bin/bash".to_string())));
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;
#[cfg(test)]
#[macro_use]
extern crate proptest;

mod actions_process;
mod actions_process_list_provides;
mod autoconf;
mod clap_actions;
mod clap_fern;
mod cli_clap;
mod db;
mod db_enviroment;
mod db_fs_dir;
mod db_fs_dir_type;
mod db_fs_file;
use db::db_job;
mod db_job_depend;
mod db_job_provide;
mod db_job_require_variable;
mod db_job_require_variable_pair;
use db::db_provider;
use db::db_session;
mod db_variable_name;
mod db_variable_pair;
mod elephant;
mod jobs_load;
mod json_loader_elephant;
mod loader;
use uuid::Uuid;

fn main() {
    let some_value = 10;
    let clap_matches = cli_clap::cli_clap(&some_value);
    let actions = clap_actions::actions_get(&clap_matches);
    clap_fern::log_setup(&clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = db::connect_deligate(&clap_matches);
    db::create_tables(&conn);
    loader::deligate(&conn, &actions, &clap_matches);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, pk_session, &clap_matches);
    jobs_load::load(&conn);
    actions_process::process(&conn, &actions)
}
<commit_msg>Move fs_dir_type into db module<commit_after>extern crate clap;
extern crate rusqlite;
#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;
extern crate rustc_serialize;
extern crate serde_yaml;
extern crate uuid;
#[cfg(test)]
#[macro_use]
extern crate proptest;

mod actions_process;
mod actions_process_list_provides;
mod autoconf;
mod clap_actions;
mod clap_fern;
mod cli_clap;
mod db;
mod db_enviroment;
mod db_fs_dir;
use db::fs_dir_type;
mod db_fs_file;
use db::db_job;
mod db_job_depend;
mod db_job_provide;
mod db_job_require_variable;
mod db_job_require_variable_pair;
use db::db_provider;
use db::db_session;
mod db_variable_name;
mod db_variable_pair;
mod elephant;
mod jobs_load;
mod json_loader_elephant;
mod loader;
use uuid::Uuid;

fn main() {
    let some_value = 10;
    let clap_matches = cli_clap::cli_clap(&some_value);
    let actions = clap_actions::actions_get(&clap_matches);
    clap_fern::log_setup(&clap_matches);
    let session_uuid = Uuid::new_v4();
    let session_uuid_string = session_uuid.hyphenated().to_string();
    trace!("session_uuid_string:{}", session_uuid_string);
    let conn = db::connect_deligate(&clap_matches);
    db::create_tables(&conn);
    loader::deligate(&conn, &actions, &clap_matches);
    let pk_session = elephant::elephant_session(&conn, &session_uuid_string);
    loader::enviroment(&conn, pk_session, &clap_matches);
    jobs_load::load(&conn);
    actions_process::process(&conn, &actions)
}
<|endoftext|>


<commit_before>use backend::input::KeyState;
use std::io::{Error as IoError, Write};
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use tempfile::tempfile;
use wayland_server::{Liveness, Resource};
use wayland_server::protocol::{wl_keyboard, wl_surface};
use xkbcommon::xkb;
pub use xkbcommon::xkb::{keysyms, Keysym};

/// Represents the current state of the keyboard modifiers
///
/// Each field of this struct represents a modifier and is `true` if this modifier is active.
///
/// For some modifiers, this means that the key is currently pressed, others are toggled
/// (like caps lock).
#[derive(Copy, Clone, Debug)]
pub struct ModifiersState {
    /// The "control" key
    pub ctrl: bool,
    /// The "alt" key
    pub alt: bool,
    /// The "shift" key
    pub shift: bool,
    /// The "Caps lock" key
    pub caps_lock: bool,
    /// The "logo" key
    ///
    /// Also known as the "windows" key on most keyboards
    pub logo: bool,
    /// The "Num lock" key
    pub num_lock: bool,
}

impl ModifiersState {
    fn new() -> ModifiersState {
        ModifiersState {
            ctrl: false,
            alt: false,
            shift: false,
            caps_lock: false,
            logo: false,
            num_lock: false,
        }
    }

    fn update_with(&mut self, state: &xkb::State) {
        self.ctrl = state.mod_name_is_active(&xkb::MOD_NAME_CTRL, xkb::STATE_MODS_EFFECTIVE);
        self.alt = state.mod_name_is_active(&xkb::MOD_NAME_ALT, xkb::STATE_MODS_EFFECTIVE);
        self.shift = state.mod_name_is_active(&xkb::MOD_NAME_SHIFT, xkb::STATE_MODS_EFFECTIVE);
        self.caps_lock = state.mod_name_is_active(&xkb::MOD_NAME_CAPS, xkb::STATE_MODS_EFFECTIVE);
        self.logo = state.mod_name_is_active(&xkb::MOD_NAME_LOGO, xkb::STATE_MODS_EFFECTIVE);
        self.num_lock = state.mod_name_is_active(&xkb::MOD_NAME_NUM, xkb::STATE_MODS_EFFECTIVE);
    }
}

struct KbdInternal {
    known_kbds: Vec<wl_keyboard::WlKeyboard>,
    focus: Option<wl_surface::WlSurface>,
    pressed_keys: Vec<u32>,
    mods_state: ModifiersState,
    keymap: xkb::Keymap,
    state: xkb::State,
    repeat_rate: i32,
    repeat_delay: i32,
}

impl KbdInternal {
    fn new(rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>,
           repeat_rate: i32, repeat_delay: i32)
           -> Result<KbdInternal, ()> {
        // we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe
        // so confining it inside the KbdInternal allows us to use Rusts mutability rules to make
        // sure nothing goes wrong.
        //
        // FIXME: This is an issue with the xkbcommon-rs crate that does not reflect this
        // non-threadsafety properly.
        let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
        let keymap = xkb::Keymap::new_from_names(
            &context,
            &rules,
            &model,
            &layout,
            &variant,
            options,
            xkb::KEYMAP_COMPILE_NO_FLAGS,
        ).ok_or(())?;
        let state = xkb::State::new(&keymap);
        Ok(KbdInternal {
            known_kbds: Vec::new(),
            focus: None,
            pressed_keys: Vec::new(),
            mods_state: ModifiersState::new(),
            keymap: keymap,
            state: state,
            repeat_rate: repeat_rate,
            repeat_delay: repeat_delay,
        })
    }

    // return true if modifier state has changed
    fn key_input(&mut self, keycode: u32, state: KeyState) -> bool {
        // track pressed keys as xkbcommon does not seem to expose it :(
        let direction = match state {
            KeyState::Pressed => {
                self.pressed_keys.push(keycode);
                xkb::KeyDirection::Down
            }
            KeyState::Released => {
                self.pressed_keys.retain(|&k| k != keycode);
                xkb::KeyDirection::Up
            }
        };

        // update state
        // Offset the keycode by 8, as the evdev XKB rules reflect X's
        // broken keycode system, which starts at 8.
        let state_components = self.state.update_key(keycode + 8, direction);

        println!("KEYCODE: {}", keycode);
        println!("MODS: {:b}", state_components);

        if state_components != 0 {
            self.mods_state.update_with(&self.state);
            true
        } else {
            false
        }
    }

    fn serialize_modifiers(&self) -> (u32, u32, u32, u32) {
        let mods_depressed = self.state.serialize_mods(xkb::STATE_MODS_DEPRESSED);
        let mods_latched = self.state.serialize_mods(xkb::STATE_MODS_LATCHED);
        let mods_locked = self.state.serialize_mods(xkb::STATE_MODS_LOCKED);
        let layout_locked = self.state.serialize_layout(xkb::STATE_LAYOUT_LOCKED);

        (mods_depressed, mods_latched, mods_locked, layout_locked)
    }

    fn serialize_pressed_keys(&self) -> Vec<u8> {
        let serialized = unsafe {
            ::std::slice::from_raw_parts(
                self.pressed_keys.as_ptr() as *const u8,
                self.pressed_keys.len() * 4,
            )
        };
        serialized.into()
    }

    fn with_focused_kbds<F>(&self, mut f: F)
    where
        F: FnMut(&wl_keyboard::WlKeyboard, &wl_surface::WlSurface),
    {
        if let Some(ref surface) = self.focus {
            for kbd in &self.known_kbds {
                if kbd.same_client_as(surface) {
                    f(kbd, surface);
                }
            }
        }
    }
}

/// Errors that can be encountered when creating a keyboard handler
#[derive(Debug)]
pub enum Error {
    /// libxkbcommon could not load the specified keymap
    BadKeymap,
    /// Smithay could not create a tempfile to share the keymap with clients
    IoError(IoError),
}

/// Create a keyboard handler from a set of RMLVO rules
pub(crate) fn create_keyboard_handler(rules: &str, model: &str, layout: &str, variant: &str,
                                      options: Option<String>, repeat_delay: i32, repeat_rate: i32,
                                      logger: ::slog::Logger)
                                      -> Result<KbdHandle, Error> {
    let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
    info!(log, "Initializing a xkbcommon handler with keymap query";
        "rules" => rules, "model" => model, "layout" => layout, "variant" => variant,
        "options" => &options
    );
    let internal = KbdInternal::new(
        rules,
        model,
        layout,
        variant,
        options,
        repeat_rate,
        repeat_delay,
    ).map_err(|_| {
        debug!(log, "Loading keymap failed");
        Error::BadKeymap
    })?;

    info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());

    // prepare a tempfile with the keymap, to send it to clients
    let mut keymap_file = tempfile().map_err(Error::IoError)?;
    let keymap_data = internal.keymap.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);
    keymap_file
        .write_all(keymap_data.as_bytes())
        .map_err(Error::IoError)?;
    keymap_file.flush().map_err(Error::IoError)?;

    trace!(log, "Keymap loaded and copied to tempfile.";
        "fd" => keymap_file.as_raw_fd(), "len" => keymap_data.as_bytes().len()
    );

    Ok(KbdHandle {
        arc: Arc::new(KbdArc {
            internal: Mutex::new(internal),
            keymap_file: keymap_file,
            keymap_len: keymap_data.as_bytes().len() as u32,
            logger: log,
        }),
    })
}

struct KbdArc {
    internal: Mutex<KbdInternal>,
    keymap_file: ::std::fs::File,
    keymap_len: u32,
    logger: ::slog::Logger,
}

/// An handle to a keyboard handler
///
/// It can be cloned and all clones manipulate the same internal state. Clones
/// can also be sent across threads.
///
/// This handle gives you 3 main ways to interact with the keymap handling:
///
/// - register new `wl_keyboard` instances to it with the `new_kbd` method.
/// - set the current focus for this keyboard: designing the surface that will receive the key inputs
///   using the `KbdHandle::set_focus` method.
/// - process key inputs from the input backend, allowing them to be catched at the compositor-level
///   or forwarded to the client. See the documentation of the `KbdHandle::input` method for
///   details.
#[derive(Clone)]
pub struct KbdHandle {
    arc: Arc<KbdArc>,
}

impl KbdHandle {
    /// Handle a keystroke
    ///
    /// All keystrokes from the input backend should be fed _in order_ to this method of the
    /// keyboard handler. It will internally track the state of the keymap.
    ///
    /// The `filter` argument is expected to be a closure which will peek at the generated input
    /// as interpreted by the keymap before it is forwarded to the focused client. If this closure
    /// returns false, the input will not be sent to the client. This mechanism can be used to
    /// implement compositor-level key bindings for example.
    ///
    /// The module `smithay::keyboard::keysyms` exposes definitions of all possible keysyms
    /// to be compared against. This includes non-characted keysyms, such as XF86 special keys.
    pub fn input<F>(&self, keycode: u32, state: KeyState, serial: u32, filter: F)
    where
        F: FnOnce(&ModifiersState, Keysym) -> bool,
    {
        trace!(self.arc.logger, "Handling keystroke"; "keycode" => keycode, "state" => format_args!("{:?}", state));
        let mut guard = self.arc.internal.lock().unwrap();

        let sym = guard.state.key_get_one_sym(keycode);

        let mods_changed = guard.key_input(keycode, state);

        trace!(self.arc.logger, "Calling input filter";
            "mods_state" => format_args!("{:?}", guard.mods_state), "sym" => xkb::keysym_get_name(sym)
        );

        if !filter(&guard.mods_state, sym) {
            // the filter returned false, we do not forward to client
            trace!(self.arc.logger, "Input was intercepted by filter");
            return;
        }

        // forward to client if no keybinding is triggered
        let modifiers = if mods_changed {
            Some(guard.serialize_modifiers())
        } else {
            None
        };
        let wl_state = match state {
            KeyState::Pressed => wl_keyboard::KeyState::Pressed,
            KeyState::Released => wl_keyboard::KeyState::Released,
        };
        guard.with_focused_kbds(|kbd, _| {
            if let Some((dep, la, lo, gr)) = modifiers {
                kbd.modifiers(serial, dep, la, lo, gr);
            }
            kbd.key(serial, 0, keycode, wl_state);
        });
        if guard.focus.is_some() {
            trace!(self.arc.logger, "Input forwarded to client");
        } else {
            trace!(self.arc.logger, "No client currently focused");
        }
    }

    /// Set the current focus of this keyboard
    ///
    /// If the ne focus is different from the previous one, any previous focus
    /// will be sent a `wl_keyboard::leave` event, and if the new focus is not `None`,
    /// a `wl_keyboard::enter` event will be sent.
    pub fn set_focus(&self, focus: Option<&wl_surface::WlSurface>, serial: u32) {
        let mut guard = self.arc.internal.lock().unwrap();

        let same = guard
            .focus
            .as_ref()
            .and_then(|f| focus.map(|s| s.equals(f)))
            .unwrap_or(false);

        if !same {
            // unset old focus
            guard.with_focused_kbds(|kbd, s| {
                kbd.leave(serial, s);
            });

            // set new focus
            guard.focus = focus.and_then(|s| s.clone());
            let (dep, la, lo, gr) = guard.serialize_modifiers();
            let keys = guard.serialize_pressed_keys();
            guard.with_focused_kbds(|kbd, s| {
                kbd.modifiers(serial, dep, la, lo, gr);
                kbd.enter(serial, s, keys.clone());
            });
            if guard.focus.is_some() {
                trace!(self.arc.logger, "Focus set to new surface");
            } else {
                trace!(self.arc.logger, "Focus unset");
            }
        } else {
            trace!(self.arc.logger, "Focus unchanged");
        }
    }

    /// Register a new keyboard to this handler
    ///
    /// The keymap will automatically be sent to it
    ///
    /// This should be done first, before anything else is done with this keyboard.
    pub(crate) fn new_kbd(&self, kbd: wl_keyboard::WlKeyboard) {
        trace!(self.arc.logger, "Sending keymap to client");
        kbd.keymap(
            wl_keyboard::KeymapFormat::XkbV1,
            self.arc.keymap_file.as_raw_fd(),
            self.arc.keymap_len,
        );
        let mut guard = self.arc.internal.lock().unwrap();
        if kbd.version() >= 4 {
            kbd.repeat_info(guard.repeat_rate, guard.repeat_delay);
        }
        guard.known_kbds.push(kbd);
    }

    /// Change the repeat info configured for this keyboard
    pub fn change_repeat_info(&self, rate: i32, delay: i32) {
        let mut guard = self.arc.internal.lock().unwrap();
        guard.repeat_delay = delay;
        guard.repeat_rate = rate;
        for kbd in &guard.known_kbds {
            kbd.repeat_info(rate, delay);
        }
    }

    /// Performs an internal cleanup of known kbds
    ///
    /// Drops any wl_keyboard that is no longer alive
    pub(crate) fn cleanup_old_kbds(&self) {
        let mut guard = self.arc.internal.lock().unwrap();
        guard
            .known_kbds
            .retain(|kbd| kbd.status() != Liveness::Dead);
    }
}
<commit_msg>seat.keyboard: fix sym peek with +8 offset<commit_after>use backend::input::KeyState;
use std::io::{Error as IoError, Write};
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use tempfile::tempfile;
use wayland_server::{Liveness, Resource};
use wayland_server::protocol::{wl_keyboard, wl_surface};
use xkbcommon::xkb;
pub use xkbcommon::xkb::{keysyms, Keysym};

/// Represents the current state of the keyboard modifiers
///
/// Each field of this struct represents a modifier and is `true` if this modifier is active.
///
/// For some modifiers, this means that the key is currently pressed, others are toggled
/// (like caps lock).
#[derive(Copy, Clone, Debug)]
pub struct ModifiersState {
    /// The "control" key
    pub ctrl: bool,
    /// The "alt" key
    pub alt: bool,
    /// The "shift" key
    pub shift: bool,
    /// The "Caps lock" key
    pub caps_lock: bool,
    /// The "logo" key
    ///
    /// Also known as the "windows" key on most keyboards
    pub logo: bool,
    /// The "Num lock" key
    pub num_lock: bool,
}

impl ModifiersState {
    fn new() -> ModifiersState {
        ModifiersState {
            ctrl: false,
            alt: false,
            shift: false,
            caps_lock: false,
            logo: false,
            num_lock: false,
        }
    }

    fn update_with(&mut self, state: &xkb::State) {
        self.ctrl = state.mod_name_is_active(&xkb::MOD_NAME_CTRL, xkb::STATE_MODS_EFFECTIVE);
        self.alt = state.mod_name_is_active(&xkb::MOD_NAME_ALT, xkb::STATE_MODS_EFFECTIVE);
        self.shift = state.mod_name_is_active(&xkb::MOD_NAME_SHIFT, xkb::STATE_MODS_EFFECTIVE);
        self.caps_lock = state.mod_name_is_active(&xkb::MOD_NAME_CAPS, xkb::STATE_MODS_EFFECTIVE);
        self.logo = state.mod_name_is_active(&xkb::MOD_NAME_LOGO, xkb::STATE_MODS_EFFECTIVE);
        self.num_lock = state.mod_name_is_active(&xkb::MOD_NAME_NUM, xkb::STATE_MODS_EFFECTIVE);
    }
}

struct KbdInternal {
    known_kbds: Vec<wl_keyboard::WlKeyboard>,
    focus: Option<wl_surface::WlSurface>,
    pressed_keys: Vec<u32>,
    mods_state: ModifiersState,
    keymap: xkb::Keymap,
    state: xkb::State,
    repeat_rate: i32,
    repeat_delay: i32,
}

impl KbdInternal {
    fn new(rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>,
           repeat_rate: i32, repeat_delay: i32)
           -> Result<KbdInternal, ()> {
        // we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe
        // so confining it inside the KbdInternal allows us to use Rusts mutability rules to make
        // sure nothing goes wrong.
        //
        // FIXME: This is an issue with the xkbcommon-rs crate that does not reflect this
        // non-threadsafety properly.
        let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
        let keymap = xkb::Keymap::new_from_names(
            &context,
            &rules,
            &model,
            &layout,
            &variant,
            options,
            xkb::KEYMAP_COMPILE_NO_FLAGS,
        ).ok_or(())?;
        let state = xkb::State::new(&keymap);
        Ok(KbdInternal {
            known_kbds: Vec::new(),
            focus: None,
            pressed_keys: Vec::new(),
            mods_state: ModifiersState::new(),
            keymap: keymap,
            state: state,
            repeat_rate: repeat_rate,
            repeat_delay: repeat_delay,
        })
    }

    // return true if modifier state has changed
    fn key_input(&mut self, keycode: u32, state: KeyState) -> bool {
        // track pressed keys as xkbcommon does not seem to expose it :(
        let direction = match state {
            KeyState::Pressed => {
                self.pressed_keys.push(keycode);
                xkb::KeyDirection::Down
            }
            KeyState::Released => {
                self.pressed_keys.retain(|&k| k != keycode);
                xkb::KeyDirection::Up
            }
        };

        // update state
        // Offset the keycode by 8, as the evdev XKB rules reflect X's
        // broken keycode system, which starts at 8.
        let state_components = self.state.update_key(keycode + 8, direction);

        println!("KEYCODE: {}", keycode);
        println!("MODS: {:b}", state_components);

        if state_components != 0 {
            self.mods_state.update_with(&self.state);
            true
        } else {
            false
        }
    }

    fn serialize_modifiers(&self) -> (u32, u32, u32, u32) {
        let mods_depressed = self.state.serialize_mods(xkb::STATE_MODS_DEPRESSED);
        let mods_latched = self.state.serialize_mods(xkb::STATE_MODS_LATCHED);
        let mods_locked = self.state.serialize_mods(xkb::STATE_MODS_LOCKED);
        let layout_locked = self.state.serialize_layout(xkb::STATE_LAYOUT_LOCKED);

        (mods_depressed, mods_latched, mods_locked, layout_locked)
    }

    fn serialize_pressed_keys(&self) -> Vec<u8> {
        let serialized = unsafe {
            ::std::slice::from_raw_parts(
                self.pressed_keys.as_ptr() as *const u8,
                self.pressed_keys.len() * 4,
            )
        };
        serialized.into()
    }

    fn with_focused_kbds<F>(&self, mut f: F)
    where
        F: FnMut(&wl_keyboard::WlKeyboard, &wl_surface::WlSurface),
    {
        if let Some(ref surface) = self.focus {
            for kbd in &self.known_kbds {
                if kbd.same_client_as(surface) {
                    f(kbd, surface);
                }
            }
        }
    }
}

/// Errors that can be encountered when creating a keyboard handler
#[derive(Debug)]
pub enum Error {
    /// libxkbcommon could not load the specified keymap
    BadKeymap,
    /// Smithay could not create a tempfile to share the keymap with clients
    IoError(IoError),
}

/// Create a keyboard handler from a set of RMLVO rules
pub(crate) fn create_keyboard_handler(rules: &str, model: &str, layout: &str, variant: &str,
                                      options: Option<String>, repeat_delay: i32, repeat_rate: i32,
                                      logger: ::slog::Logger)
                                      -> Result<KbdHandle, Error> {
    let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
    info!(log, "Initializing a xkbcommon handler with keymap query";
        "rules" => rules, "model" => model, "layout" => layout, "variant" => variant,
        "options" => &options
    );
    let internal = KbdInternal::new(
        rules,
        model,
        layout,
        variant,
        options,
        repeat_rate,
        repeat_delay,
    ).map_err(|_| {
        debug!(log, "Loading keymap failed");
        Error::BadKeymap
    })?;

    info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());

    // prepare a tempfile with the keymap, to send it to clients
    let mut keymap_file = tempfile().map_err(Error::IoError)?;
    let keymap_data = internal.keymap.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);
    keymap_file
        .write_all(keymap_data.as_bytes())
        .map_err(Error::IoError)?;
    keymap_file.flush().map_err(Error::IoError)?;

    trace!(log, "Keymap loaded and copied to tempfile.";
        "fd" => keymap_file.as_raw_fd(), "len" => keymap_data.as_bytes().len()
    );

    Ok(KbdHandle {
        arc: Arc::new(KbdArc {
            internal: Mutex::new(internal),
            keymap_file: keymap_file,
            keymap_len: keymap_data.as_bytes().len() as u32,
            logger: log,
        }),
    })
}

struct KbdArc {
    internal: Mutex<KbdInternal>,
    keymap_file: ::std::fs::File,
    keymap_len: u32,
    logger: ::slog::Logger,
}

/// An handle to a keyboard handler
///
/// It can be cloned and all clones manipulate the same internal state. Clones
/// can also be sent across threads.
///
/// This handle gives you 3 main ways to interact with the keymap handling:
///
/// - register new `wl_keyboard` instances to it with the `new_kbd` method.
/// - set the current focus for this keyboard: designing the surface that will receive the key inputs
///   using the `KbdHandle::set_focus` method.
/// - process key inputs from the input backend, allowing them to be catched at the compositor-level
///   or forwarded to the client. See the documentation of the `KbdHandle::input` method for
///   details.
#[derive(Clone)]
pub struct KbdHandle {
    arc: Arc<KbdArc>,
}

impl KbdHandle {
    /// Handle a keystroke
    ///
    /// All keystrokes from the input backend should be fed _in order_ to this method of the
    /// keyboard handler. It will internally track the state of the keymap.
    ///
    /// The `filter` argument is expected to be a closure which will peek at the generated input
    /// as interpreted by the keymap before it is forwarded to the focused client. If this closure
    /// returns false, the input will not be sent to the client. This mechanism can be used to
    /// implement compositor-level key bindings for example.
    ///
    /// The module `smithay::keyboard::keysyms` exposes definitions of all possible keysyms
    /// to be compared against. This includes non-characted keysyms, such as XF86 special keys.
    pub fn input<F>(&self, keycode: u32, state: KeyState, serial: u32, filter: F)
    where
        F: FnOnce(&ModifiersState, Keysym) -> bool,
    {
        trace!(self.arc.logger, "Handling keystroke"; "keycode" => keycode, "state" => format_args!("{:?}", state));
        let mut guard = self.arc.internal.lock().unwrap();

        // Offset the keycode by 8, as the evdev XKB rules reflect X's
        // broken keycode system, which starts at 8.
        let sym = guard.state.key_get_one_sym(keycode+8);

        let mods_changed = guard.key_input(keycode, state);

        trace!(self.arc.logger, "Calling input filter";
            "mods_state" => format_args!("{:?}", guard.mods_state), "sym" => xkb::keysym_get_name(sym)
        );

        if !filter(&guard.mods_state, sym) {
            // the filter returned false, we do not forward to client
            trace!(self.arc.logger, "Input was intercepted by filter");
            return;
        }

        // forward to client if no keybinding is triggered
        let modifiers = if mods_changed {
            Some(guard.serialize_modifiers())
        } else {
            None
        };
        let wl_state = match state {
            KeyState::Pressed => wl_keyboard::KeyState::Pressed,
            KeyState::Released => wl_keyboard::KeyState::Released,
        };
        guard.with_focused_kbds(|kbd, _| {
            if let Some((dep, la, lo, gr)) = modifiers {
                kbd.modifiers(serial, dep, la, lo, gr);
            }
            kbd.key(serial, 0, keycode, wl_state);
        });
        if guard.focus.is_some() {
            trace!(self.arc.logger, "Input forwarded to client");
        } else {
            trace!(self.arc.logger, "No client currently focused");
        }
    }

    /// Set the current focus of this keyboard
    ///
    /// If the ne focus is different from the previous one, any previous focus
    /// will be sent a `wl_keyboard::leave` event, and if the new focus is not `None`,
    /// a `wl_keyboard::enter` event will be sent.
    pub fn set_focus(&self, focus: Option<&wl_surface::WlSurface>, serial: u32) {
        let mut guard = self.arc.internal.lock().unwrap();

        let same = guard
            .focus
            .as_ref()
            .and_then(|f| focus.map(|s| s.equals(f)))
            .unwrap_or(false);

        if !same {
            // unset old focus
            guard.with_focused_kbds(|kbd, s| {
                kbd.leave(serial, s);
            });

            // set new focus
            guard.focus = focus.and_then(|s| s.clone());
            let (dep, la, lo, gr) = guard.serialize_modifiers();
            let keys = guard.serialize_pressed_keys();
            guard.with_focused_kbds(|kbd, s| {
                kbd.modifiers(serial, dep, la, lo, gr);
                kbd.enter(serial, s, keys.clone());
            });
            if guard.focus.is_some() {
                trace!(self.arc.logger, "Focus set to new surface");
            } else {
                trace!(self.arc.logger, "Focus unset");
            }
        } else {
            trace!(self.arc.logger, "Focus unchanged");
        }
    }

    /// Register a new keyboard to this handler
    ///
    /// The keymap will automatically be sent to it
    ///
    /// This should be done first, before anything else is done with this keyboard.
    pub(crate) fn new_kbd(&self, kbd: wl_keyboard::WlKeyboard) {
        trace!(self.arc.logger, "Sending keymap to client");
        kbd.keymap(
            wl_keyboard::KeymapFormat::XkbV1,
            self.arc.keymap_file.as_raw_fd(),
            self.arc.keymap_len,
        );
        let mut guard = self.arc.internal.lock().unwrap();
        if kbd.version() >= 4 {
            kbd.repeat_info(guard.repeat_rate, guard.repeat_delay);
        }
        guard.known_kbds.push(kbd);
    }

    /// Change the repeat info configured for this keyboard
    pub fn change_repeat_info(&self, rate: i32, delay: i32) {
        let mut guard = self.arc.internal.lock().unwrap();
        guard.repeat_delay = delay;
        guard.repeat_rate = rate;
        for kbd in &guard.known_kbds {
            kbd.repeat_info(rate, delay);
        }
    }

    /// Performs an internal cleanup of known kbds
    ///
    /// Drops any wl_keyboard that is no longer alive
    pub(crate) fn cleanup_old_kbds(&self) {
        let mut guard = self.arc.internal.lock().unwrap();
        guard
            .known_kbds
            .retain(|kbd| kbd.status() != Liveness::Dead);
    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

macro_rules! ioreg_old(
  ($io:ident: $ty:ty, $($reg:ident),+) => (
    #[allow(non_snake_case)]
    #[derive(Clone, Copy)]
    pub struct $io {
      $(
        $reg: VolatileCell<$ty>,
      )+
    }
  )
);

macro_rules! reg_r(
  ($t:ident, $ty:ty, $getter_name:ident, $reg:ident) => (
    impl $t {
      #[allow(dead_code,non_snake_case)]
      #[inline(always)]
      pub fn $getter_name(&self) -> $ty {
        self.$reg.get()
      }
    }
  )
);

macro_rules! reg_w(
  ($t:ident, $ty:ty, $setter_name:ident, $reg:ident) => (
    impl $t {
      #[allow(dead_code,non_snake_case)]
      #[inline(always)]
      pub fn $setter_name(&self, val: $ty) {
        self.$reg.set(val);
      }
    }
  )
);

macro_rules! reg_rw(
  ($t:ident, $ty:ty, $getter_name:ident, $setter_name:ident, $reg:ident) => (
    reg_r!($t, $ty, $getter_name, $reg);
    reg_w!($t, $ty, $setter_name, $reg);
  )
);
<commit_msg>Create an lpc17xx specific gpio reg macro and name it very ambiguously<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

macro_rules! ioreg_old(
  ($io:ident: $ty:ty, $($reg:ident),+) => (
    #[allow(non_snake_case)]
    #[derive(Clone, Copy)]
    #[repr(C, packed)]
    pub struct $io {
      $(
        $reg: VolatileCell<$ty>,
      )+
    }
  )
);

macro_rules! gpio_reg(
  ($io:ident: $ty:ty, $(($reg:ident, $padding:ident)),+) => (
    #[allow(non_snake_case)]
    #[derive(Clone, Copy)]
    #[repr(C, packed)]
    pub struct $io {
      $(
        $reg: VolatileCell<$ty>,
        $padding: [u32; 31],
      )+
    }
  )
);

macro_rules! reg_r(
  ($t:ident, $ty:ty, $getter_name:ident, $reg:ident) => (
    impl $t {
      #[allow(dead_code,non_snake_case)]
      #[inline(always)]
      pub fn $getter_name(&self) -> $ty {
        self.$reg.get()
      }
    }
  )
);

macro_rules! reg_w(
  ($t:ident, $ty:ty, $setter_name:ident, $reg:ident) => (
    impl $t {
      #[allow(dead_code,non_snake_case)]
      #[inline(always)]
      pub fn $setter_name(&self, val: $ty) {
        self.$reg.set(val);
      }
    }
  )
);

macro_rules! reg_rw(
  ($t:ident, $ty:ty, $getter_name:ident, $setter_name:ident, $reg:ident) => (
    reg_r!($t, $ty, $getter_name, $reg);
    reg_w!($t, $ty, $setter_name, $reg);
  )
);
<|endoftext|>


<commit_before>use sha2::{Sha512, Digest};
use std::fs::File;
use std::io::{ BufReader, Read };
use std::path::Path;

use error::PackageError;

/// Calculates the SHA-512 of a file.
/// Returns `Box<[u8]>` if there are no errors during the process of
/// calculation.
fn sha2<P: AsRef<Path>>(path: P) -> Result<Box<[u8]>, PackageError> {
    // Create a SHA512 hasher.
    let mut hasher = Sha512::default();
    // Read the file from `path`
    let file = File::open(path)?;
    let file = BufReader::new(file);
    // Hash the bytes read from the file
    for byte in file.bytes() { hasher.input(&[byte?]) };
    // Return the result (it needs to copy 64 bytes though, ouch)
    Ok(Box::from(hasher.result().as_slice()))
}<commit_msg>Implement a struct for hashes<commit_after>use sha2::{Sha512, Digest};
use std::fmt;
use std::fs::File;
use std::io::{ BufReader, Read };
use std::path::Path;

use error::PackageError;

/// This struct represents the hash result.
pub struct Hash(Box<[u8]>);

impl Hash {
    /// Calculates the SHA-512 of a file.
    /// Returns `Box<[u8]>` if there are no errors during the process of
    /// calculation.
    fn sha2<P: AsRef<Path>>(path: P) -> Result<Hash, PackageError> {
        // Create a SHA512 hasher.
        let mut hasher = Sha512::default();
        // Read the file from `path`
        let file = File::open(path)?;
        let file = BufReader::new(file);
        // Hash the bytes read from the file
        for byte in file.bytes() { hasher.input(&[byte?]) };
        // Return the result (it needs to copy 64 bytes though, ouch)
        Ok(Hash(Box::from(hasher.result().as_slice())))
    }
}

impl fmt::Display for Hash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let &Hash(ref hash) = self;
        let mut content = String::new();
        for &h in hash.as_ref() {
            content += &format!("{:x}", h)
        };
        write!(f, "{}", content)
    }
}

impl<'a> From<&'a str> for Hash {
    fn from(s: &'a str) -> Self {
        // A simple function which converts hexadecimal chars into `u8`s.
        let hex_to_dec = |x| match x {
            b'0'...b'9' => x - b'0',
            y @ b'a'...b'f' => 10 + y - b'a',
            _ => panic!("unable to convert hexadecimal string into decimals"),
        };

        let mut result = Vec::with_capacity(64);
        for x in 1 .. 64+1 {
            let (front, _) = s.split_at(2 * x);
            result.push(
                hex_to_dec(front.as_bytes()[0]) * 16 +
                hex_to_dec(front.as_bytes()[1])
            );
        }

        Hash(result.into_boxed_slice())
    }
}<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;

use super::Value;
use map::Map;
use number::Number;

macro_rules! from_integer {
    ($($ty:ident)*) => {
        $(
            impl From<$ty> for Value {
                fn from(n: $ty) -> Self {
                    Value::Number(n.into())
                }
            }
        )*
    };
}

from_integer! {
    i8 i16 i32 i64 isize
    u8 u16 u32 u64 usize
}

impl From<f32> for Value {
    /// Convert 32-bit floating point number to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let f: f32 = 13.37;
    /// let x: Value = f.into();
    /// # }
    /// ```
    fn from(f: f32) -> Self {
        From::from(f as f64)
    }
}

impl From<f64> for Value {
    /// Convert 64-bit floating point number to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let f: f64 = 13.37;
    /// let x: Value = f.into();
    /// # }
    /// ```
    fn from(f: f64) -> Self {
        Number::from_f64(f).map_or(Value::Null, Value::Number)
    }
}

impl From<bool> for Value {
    /// Convert boolean to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let b = false;
    /// let x: Value = b.into();
    /// # }
    /// ```
    fn from(f: bool) -> Self {
        Value::Bool(f)
    }
}

impl From<String> for Value {
    /// Convert `String` to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let s: String = "lorem".to_string();
    /// let x: Value = s.into();
    /// # }
    /// ```
    fn from(f: String) -> Self {
        Value::String(f)
    }
}

impl<'a> From<&'a str> for Value {
    /// Convert string slice to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let s: &str = "lorem";
    /// let x: Value = s.into();
    /// # }
    /// ```
    fn from(f: &str) -> Self {
        Value::String(f.to_string())
    }
}

impl<'a> From<Cow<'a, str>> for Value {
    /// Convert copy-on-write string to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    /// use std::borrow::Cow;
    ///
    /// let s: Cow<str> = Cow::Borrowed("lorem");
    /// let x: Value = s.into();
    /// # }
    /// ```
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    /// use std::borrow::Cow;
    ///
    /// let s: Cow<str> = Cow::Owned("lorem".to_string());
    /// let x: Value = s.into();
    /// # }
    /// ```
    fn from(f: Cow<'a, str>) -> Self {
        Value::String(f.to_string())
    }
}

impl From<Map<String, Value>> for Value {
    /// Convert map (with string keys) to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::{Map, Value};
    ///
    /// let mut m = Map::new();
    /// m.insert("Lorem".to_string(), "ipsum".into());
    /// let x: Value = m.into();
    /// # }
    /// ```
    fn from(f: Map<String, Value>) -> Self {
        Value::Object(f)
    }
}

impl<T: Into<Value>> From<Vec<T>> for Value {
    /// Convert a `Vec` to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v = vec!["lorem", "ipsum", "dolor"];
    /// let x: Value = v.into();
    /// # }
    /// ```
    fn from(f: Vec<T>) -> Self {
        Value::Array(f.into_iter().map(Into::into).collect())
    }
}

impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
    /// Convert a slice to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v: &[&str] = &["lorem", "ipsum", "dolor"];
    /// let x: Value = v.into();
    /// # }
    /// ```
    fn from(f: &'a [T]) -> Self {
        Value::Array(f.into_iter().cloned().map(Into::into).collect())
    }
}

impl<T: Into<Value>> ::std::iter::FromIterator<T> for Value {
    /// Convert an iteratable type to a `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v = std::iter::repeat(42).take(5);
    /// let x: Value = v.collect();
    /// # }
    /// ```
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v: Vec<_> = vec!["lorem", "ipsum", "dolor"];
    /// let x: Value = v.into_iter().collect();
    /// # }
    /// ```
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use std::iter::FromIterator;
    /// use serde_json::Value;
    ///
    /// let x: Value = Value::from_iter(vec!["lorem", "ipsum", "dolor"]);
    /// # }
    /// ```
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let vec: Vec<Value> = iter.into_iter().map(|x| x.into()).collect();

        Value::Array(vec)
    }
}
<commit_msg>Remove unnecessary copy in Value::from(Cow::Owned)<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;

use super::Value;
use map::Map;
use number::Number;

macro_rules! from_integer {
    ($($ty:ident)*) => {
        $(
            impl From<$ty> for Value {
                fn from(n: $ty) -> Self {
                    Value::Number(n.into())
                }
            }
        )*
    };
}

from_integer! {
    i8 i16 i32 i64 isize
    u8 u16 u32 u64 usize
}

impl From<f32> for Value {
    /// Convert 32-bit floating point number to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let f: f32 = 13.37;
    /// let x: Value = f.into();
    /// # }
    /// ```
    fn from(f: f32) -> Self {
        From::from(f as f64)
    }
}

impl From<f64> for Value {
    /// Convert 64-bit floating point number to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let f: f64 = 13.37;
    /// let x: Value = f.into();
    /// # }
    /// ```
    fn from(f: f64) -> Self {
        Number::from_f64(f).map_or(Value::Null, Value::Number)
    }
}

impl From<bool> for Value {
    /// Convert boolean to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let b = false;
    /// let x: Value = b.into();
    /// # }
    /// ```
    fn from(f: bool) -> Self {
        Value::Bool(f)
    }
}

impl From<String> for Value {
    /// Convert `String` to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let s: String = "lorem".to_string();
    /// let x: Value = s.into();
    /// # }
    /// ```
    fn from(f: String) -> Self {
        Value::String(f)
    }
}

impl<'a> From<&'a str> for Value {
    /// Convert string slice to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let s: &str = "lorem";
    /// let x: Value = s.into();
    /// # }
    /// ```
    fn from(f: &str) -> Self {
        Value::String(f.to_string())
    }
}

impl<'a> From<Cow<'a, str>> for Value {
    /// Convert copy-on-write string to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    /// use std::borrow::Cow;
    ///
    /// let s: Cow<str> = Cow::Borrowed("lorem");
    /// let x: Value = s.into();
    /// # }
    /// ```
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    /// use std::borrow::Cow;
    ///
    /// let s: Cow<str> = Cow::Owned("lorem".to_string());
    /// let x: Value = s.into();
    /// # }
    /// ```
    fn from(f: Cow<'a, str>) -> Self {
        Value::String(f.into_owned())
    }
}

impl From<Map<String, Value>> for Value {
    /// Convert map (with string keys) to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::{Map, Value};
    ///
    /// let mut m = Map::new();
    /// m.insert("Lorem".to_string(), "ipsum".into());
    /// let x: Value = m.into();
    /// # }
    /// ```
    fn from(f: Map<String, Value>) -> Self {
        Value::Object(f)
    }
}

impl<T: Into<Value>> From<Vec<T>> for Value {
    /// Convert a `Vec` to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v = vec!["lorem", "ipsum", "dolor"];
    /// let x: Value = v.into();
    /// # }
    /// ```
    fn from(f: Vec<T>) -> Self {
        Value::Array(f.into_iter().map(Into::into).collect())
    }
}

impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
    /// Convert a slice to `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v: &[&str] = &["lorem", "ipsum", "dolor"];
    /// let x: Value = v.into();
    /// # }
    /// ```
    fn from(f: &'a [T]) -> Self {
        Value::Array(f.into_iter().cloned().map(Into::into).collect())
    }
}

impl<T: Into<Value>> ::std::iter::FromIterator<T> for Value {
    /// Convert an iteratable type to a `Value`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v = std::iter::repeat(42).take(5);
    /// let x: Value = v.collect();
    /// # }
    /// ```
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use serde_json::Value;
    ///
    /// let v: Vec<_> = vec!["lorem", "ipsum", "dolor"];
    /// let x: Value = v.into_iter().collect();
    /// # }
    /// ```
    ///
    /// ```rust
    /// # extern crate serde_json;
    /// #
    /// # fn main() {
    /// use std::iter::FromIterator;
    /// use serde_json::Value;
    ///
    /// let x: Value = Value::from_iter(vec!["lorem", "ipsum", "dolor"]);
    /// # }
    /// ```
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let vec: Vec<Value> = iter.into_iter().map(|x| x.into()).collect();

        Value::Array(vec)
    }
}
<|endoftext|>


<commit_before>use linked_hash_map::LinkedHashMap;

use platform::time::time_now;

use super::errors::CacheError;
use super::key::Key;
use super::typedefs::CacheResult;
use super::value::Value;

struct CacheStats {
    pub bytes: u64, // Bytes currently stored
    pub evictions: u64, // Number of items removed to make space for new items
    pub get_hits: u64,
    pub get_misses: u64,
    pub delete_misses: u64,
    pub delete_hits: u64,
    pub reclaimed: u64, // Number of times an entry was reclaimed to store a new entry
    pub total_items: u64, // Total items stored since server started
}

impl CacheStats {
    pub fn new() -> CacheStats {
        CacheStats {
            bytes: 0,
            delete_hits: 0,
            delete_misses: 0,
            evictions: 0,
            get_hits: 0,
            get_misses: 0,
            reclaimed: 0,
            total_items: 0,
        }
    }

    fn bytes_add(&mut self, key: &Key, value: &Value) {
        self.bytes += key.mem_size() as u64;
        self.bytes += value.mem_size() as u64;
    }

    fn bytes_subtract(&mut self, key: &Key, value: &Value) {
        self.bytes -= key.mem_size() as u64;
        self.bytes -= value.mem_size() as u64;
    }
}

pub struct Cache {
    pub capacity: u64, // in bytes
    storage: LinkedHashMap<Key, Value>,
    item_lifetime: f64, // in seconds, <0 for unlimited
    global_exptime: f64, // unixtime, <0 for unset

    key_maxlen: u64, // in bytes
    value_maxlen: u64, // in bytes

    stats: CacheStats,
}

impl Cache {
    pub fn new(capacity: u64) -> Cache {
        Cache {
            capacity: capacity,
            global_exptime: -1.0,
            item_lifetime: -1.0,
            key_maxlen: 250, // 250b
            stats: CacheStats::new(),
            value_maxlen: 1048576, // 1mb
            storage: LinkedHashMap::new(),
        }
    }

    pub fn with_item_lifetime(&mut self, item_lifetime: f64) -> &mut Cache {
        self.item_lifetime = item_lifetime;
        self
    }

    pub fn with_key_maxlen(&mut self, key_maxlen: u64) -> &mut Cache {
        self.key_maxlen = key_maxlen;
        self
    }

    pub fn with_value_maxlen(&mut self, value_maxlen: u64) -> &mut Cache {
        self.value_maxlen = value_maxlen;
        self
    }

    pub fn get_stats(&self) -> &CacheStats {
        &self.stats
    }

    fn check_key_len(&self, key: &Key) -> bool {
        key.len() as u64 <= self.key_maxlen
    }

    fn check_value_len(&self, value: &Value) -> bool {
        value.len() as u64 <= self.value_maxlen
    }

    fn evict_oldest(&mut self) -> CacheResult<(Key, Value)> {
        let opt = self.storage.pop_back();

        match opt {
            Some((key, value)) => {
                // Update stats
                self.stats.bytes_subtract(&key, &value);
                self.stats.evictions += 1;

                Ok((key, value))
            }
            None => Err(CacheError::EvictionFailed),
        }
    }

    fn value_is_alive(&self, value: &Value) -> bool {
        // If we have a global exptime set, then any item touched before it is
        // dead
        if self.global_exptime > 0.0 {
            if *value.get_atime() < self.global_exptime {
                return false;
            }
        }

        // If the value has an exptime set, that determines lifetime
        // regardless of item_lifetime in the cache
        if *value.get_exptime() > 0.0 {
            if self.global_exptime > 0.0 {
                if *value.get_exptime() < self.global_exptime {
                    return false;
                }
            }

            if *value.get_exptime() < time_now() {
                return false;
            } else {
                return true;
            }
        }

        // if we have no lifetime setting then values are always live
        if self.item_lifetime < 0.0 {
            return true;
        }

        // otherwise use lifetime to determine liveness
        *value.get_atime() + self.item_lifetime > time_now()
    }

    pub fn contains_key(&mut self, key: &Key) -> CacheResult<bool> {
        let result = self.get(key);

        match result {
            // We know how to interpret found and not found
            Ok(_) => Ok(true),
            Err(CacheError::KeyNotFound) => Ok(false),

            // Some other error
            Err(x) => Err(x),
        }
    }

    pub fn flush_all(&mut self, exptime: f64) -> CacheResult<()> {
        self.global_exptime = exptime;
        Ok(())
    }

    pub fn get(&mut self, key: &Key) -> CacheResult<&Value> {
        // Check key size
        if !self.check_key_len(key) {
            return Err(CacheError::KeyTooLong);
        }

        // Pop the value first
        let opt = self.storage.remove(key);

        // We didn't find it
        if opt.is_none() {
            self.stats.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // From here on we can assume we did find it
        let mut value = opt.unwrap();

        // The value has been successfully removed - update stats
        self.stats.bytes_subtract(key, &value);

        // Now check if the value is still alive
        if !self.value_is_alive(&value) {
            self.stats.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // Update the value to mark that it's been accessed just now
        value.touch();

        // We are going to re-instate the key - update stats
        self.stats.bytes_add(key, &value);
        self.stats.get_hits += 1;

        // Now we reinsert the key to refresh it
        self.storage.insert(key.clone(), value);

        // Load since we need to return it
        let value = self.storage.get(key).unwrap();

        // Return success
        Ok(value)
    }

    pub fn len(&self) -> usize {
        self.storage.len()
    }

    pub fn remove(&mut self, key: &Key) -> CacheResult<Value> {
        // Check key size
        if !self.check_key_len(key) {
            return Err(CacheError::KeyTooLong);
        }

        let opt = self.storage.remove(key);

        match opt {
            Some(value) => {
                // Update stats
                self.stats.delete_hits += 1;
                self.stats.bytes_subtract(key, &value);

                Ok((value))
            }
            None => {
                // Update stats
                self.stats.delete_misses += 1;

                Err(CacheError::KeyNotFound)
            }
        }
    }

    pub fn set(&mut self, key: Key, mut value: Value) -> CacheResult<()> {
        // Check key & value sizes
        if !self.check_key_len(&key) {
            return Err(CacheError::KeyTooLong);
        }
        if !self.check_value_len(&value) {
            return Err(CacheError::ValueTooLong);
        }

        // Does this item even fit into our cache at all?
        if key.mem_size() as u64 + value.mem_size() as u64 > self.capacity {
            return Err(CacheError::CapacityExceeded);
        }

        // Do we already store this key?
        if self.storage.contains_key(&key) {
            let mut plus_delta = 0u64;
            {
                // Load the existing value
                let prev_value = self.storage.get(&key).unwrap();

                // We're updating the key, possibly with a different size value
                self.stats.bytes_subtract(&key, &prev_value);

                // Figure out how much more space we need to store the new value
                if value.mem_size() > prev_value.mem_size() {
                    plus_delta = value.mem_size() as u64 - prev_value.mem_size() as u64;
                }
            }

            // Would the new value exceed our capacity? Then we need to reclaim
            loop {
                if self.stats.bytes + key.mem_size() as u64 + plus_delta <=
                   self.capacity {
                    break;
                }

                try!(self.evict_oldest());

                // Update stats
                self.stats.reclaimed += 1;
            }

        } else {
            // Do we have space for the new item?
            loop {
                if self.stats.bytes + key.mem_size() as u64 +
                   value.mem_size() as u64 <= self.capacity {
                    break;
                }

                try!(self.evict_oldest());

                // Update stats
                self.stats.reclaimed += 1;
            }
        }

        // Update stats
        self.stats.bytes_add(&key, &value);
        self.stats.total_items += 1;

        // Update atime for value
        value.touch();

        // Store the value
        self.storage.insert(key, value);

        // Return success
        Ok(())
    }
}
<commit_msg>fix compiler warning<commit_after>use linked_hash_map::LinkedHashMap;

use platform::time::time_now;

use super::errors::CacheError;
use super::key::Key;
use super::typedefs::CacheResult;
use super::value::Value;

pub struct CacheStats {
    pub bytes: u64, // Bytes currently stored
    pub evictions: u64, // Number of items removed to make space for new items
    pub get_hits: u64,
    pub get_misses: u64,
    pub delete_misses: u64,
    pub delete_hits: u64,
    pub reclaimed: u64, // Number of times an entry was reclaimed to store a new entry
    pub total_items: u64, // Total items stored since server started
}

impl CacheStats {
    pub fn new() -> CacheStats {
        CacheStats {
            bytes: 0,
            delete_hits: 0,
            delete_misses: 0,
            evictions: 0,
            get_hits: 0,
            get_misses: 0,
            reclaimed: 0,
            total_items: 0,
        }
    }

    fn bytes_add(&mut self, key: &Key, value: &Value) {
        self.bytes += key.mem_size() as u64;
        self.bytes += value.mem_size() as u64;
    }

    fn bytes_subtract(&mut self, key: &Key, value: &Value) {
        self.bytes -= key.mem_size() as u64;
        self.bytes -= value.mem_size() as u64;
    }
}

pub struct Cache {
    pub capacity: u64, // in bytes
    storage: LinkedHashMap<Key, Value>,
    item_lifetime: f64, // in seconds, <0 for unlimited
    global_exptime: f64, // unixtime, <0 for unset

    key_maxlen: u64, // in bytes
    value_maxlen: u64, // in bytes

    stats: CacheStats,
}

impl Cache {
    pub fn new(capacity: u64) -> Cache {
        Cache {
            capacity: capacity,
            global_exptime: -1.0,
            item_lifetime: -1.0,
            key_maxlen: 250, // 250b
            stats: CacheStats::new(),
            value_maxlen: 1048576, // 1mb
            storage: LinkedHashMap::new(),
        }
    }

    pub fn with_item_lifetime(&mut self, item_lifetime: f64) -> &mut Cache {
        self.item_lifetime = item_lifetime;
        self
    }

    pub fn with_key_maxlen(&mut self, key_maxlen: u64) -> &mut Cache {
        self.key_maxlen = key_maxlen;
        self
    }

    pub fn with_value_maxlen(&mut self, value_maxlen: u64) -> &mut Cache {
        self.value_maxlen = value_maxlen;
        self
    }

    pub fn get_stats(&self) -> &CacheStats {
        &self.stats
    }

    fn check_key_len(&self, key: &Key) -> bool {
        key.len() as u64 <= self.key_maxlen
    }

    fn check_value_len(&self, value: &Value) -> bool {
        value.len() as u64 <= self.value_maxlen
    }

    fn evict_oldest(&mut self) -> CacheResult<(Key, Value)> {
        let opt = self.storage.pop_back();

        match opt {
            Some((key, value)) => {
                // Update stats
                self.stats.bytes_subtract(&key, &value);
                self.stats.evictions += 1;

                Ok((key, value))
            }
            None => Err(CacheError::EvictionFailed),
        }
    }

    fn value_is_alive(&self, value: &Value) -> bool {
        // If we have a global exptime set, then any item touched before it is
        // dead
        if self.global_exptime > 0.0 {
            if *value.get_atime() < self.global_exptime {
                return false;
            }
        }

        // If the value has an exptime set, that determines lifetime
        // regardless of item_lifetime in the cache
        if *value.get_exptime() > 0.0 {
            if self.global_exptime > 0.0 {
                if *value.get_exptime() < self.global_exptime {
                    return false;
                }
            }

            if *value.get_exptime() < time_now() {
                return false;
            } else {
                return true;
            }
        }

        // if we have no lifetime setting then values are always live
        if self.item_lifetime < 0.0 {
            return true;
        }

        // otherwise use lifetime to determine liveness
        *value.get_atime() + self.item_lifetime > time_now()
    }

    pub fn contains_key(&mut self, key: &Key) -> CacheResult<bool> {
        let result = self.get(key);

        match result {
            // We know how to interpret found and not found
            Ok(_) => Ok(true),
            Err(CacheError::KeyNotFound) => Ok(false),

            // Some other error
            Err(x) => Err(x),
        }
    }

    pub fn flush_all(&mut self, exptime: f64) -> CacheResult<()> {
        self.global_exptime = exptime;
        Ok(())
    }

    pub fn get(&mut self, key: &Key) -> CacheResult<&Value> {
        // Check key size
        if !self.check_key_len(key) {
            return Err(CacheError::KeyTooLong);
        }

        // Pop the value first
        let opt = self.storage.remove(key);

        // We didn't find it
        if opt.is_none() {
            self.stats.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // From here on we can assume we did find it
        let mut value = opt.unwrap();

        // The value has been successfully removed - update stats
        self.stats.bytes_subtract(key, &value);

        // Now check if the value is still alive
        if !self.value_is_alive(&value) {
            self.stats.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // Update the value to mark that it's been accessed just now
        value.touch();

        // We are going to re-instate the key - update stats
        self.stats.bytes_add(key, &value);
        self.stats.get_hits += 1;

        // Now we reinsert the key to refresh it
        self.storage.insert(key.clone(), value);

        // Load since we need to return it
        let value = self.storage.get(key).unwrap();

        // Return success
        Ok(value)
    }

    pub fn len(&self) -> usize {
        self.storage.len()
    }

    pub fn remove(&mut self, key: &Key) -> CacheResult<Value> {
        // Check key size
        if !self.check_key_len(key) {
            return Err(CacheError::KeyTooLong);
        }

        let opt = self.storage.remove(key);

        match opt {
            Some(value) => {
                // Update stats
                self.stats.delete_hits += 1;
                self.stats.bytes_subtract(key, &value);

                Ok((value))
            }
            None => {
                // Update stats
                self.stats.delete_misses += 1;

                Err(CacheError::KeyNotFound)
            }
        }
    }

    pub fn set(&mut self, key: Key, mut value: Value) -> CacheResult<()> {
        // Check key & value sizes
        if !self.check_key_len(&key) {
            return Err(CacheError::KeyTooLong);
        }
        if !self.check_value_len(&value) {
            return Err(CacheError::ValueTooLong);
        }

        // Does this item even fit into our cache at all?
        if key.mem_size() as u64 + value.mem_size() as u64 > self.capacity {
            return Err(CacheError::CapacityExceeded);
        }

        // Do we already store this key?
        if self.storage.contains_key(&key) {
            let mut plus_delta = 0u64;
            {
                // Load the existing value
                let prev_value = self.storage.get(&key).unwrap();

                // We're updating the key, possibly with a different size value
                self.stats.bytes_subtract(&key, &prev_value);

                // Figure out how much more space we need to store the new value
                if value.mem_size() > prev_value.mem_size() {
                    plus_delta = value.mem_size() as u64 - prev_value.mem_size() as u64;
                }
            }

            // Would the new value exceed our capacity? Then we need to reclaim
            loop {
                if self.stats.bytes + key.mem_size() as u64 + plus_delta <=
                   self.capacity {
                    break;
                }

                try!(self.evict_oldest());

                // Update stats
                self.stats.reclaimed += 1;
            }

        } else {
            // Do we have space for the new item?
            loop {
                if self.stats.bytes + key.mem_size() as u64 +
                   value.mem_size() as u64 <= self.capacity {
                    break;
                }

                try!(self.evict_oldest());

                // Update stats
                self.stats.reclaimed += 1;
            }
        }

        // Update stats
        self.stats.bytes_add(&key, &value);
        self.stats.total_items += 1;

        // Update atime for value
        value.touch();

        // Store the value
        self.storage.insert(key, value);

        // Return success
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Provide helpers for making ioctl system calls
//!
//! Currently supports Linux on all architectures. Other platforms welcome!
//!
//! This library is pretty low-level and messy. `ioctl` is not fun.
//!
//! What is an `ioctl`?
//! ===================
//!
//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want
//! to add a new syscall? Make it an `ioctl`! `ioctl` refers to both the syscall,
//! and the commands that can be send with it. `ioctl` stands for "IO control",
//! and the commands are always sent to a file descriptor.
//!
//! It is common to see `ioctl`s used for the following purposes:
//!
//! * Provide read/write access to out-of-band data related
//!   to a device such as configuration (for instance, setting
//!   serial port options)
//! * Provide a mechanism for performing full-duplex data
//!   transfers (for instance, xfer on SPI devices).
//! * Provide access to control functions on a device (for example,
//!   on Linux you can send commands like pause, resume, and eject
//!   to the CDROM device.
//! * Do whatever else the device driver creator thought made most sense.
//!
//! `ioctl`s are synchronous system calls and are similar to read and
//! write calls in that regard.
//!
//! What does this module support?
//! ===============================
//!
//! This library provides the `ioctl!` macro, for binding `ioctl`s.
//! Here's a few examples of how that can work for SPI under Linux
//! from [rust-spidev](https://github.com/posborne/rust-spidev).
//!
//! ```
//! #[allow(non_camel_case_types)]
//! pub struct spi_ioc_transfer {
//!     pub tx_buf: u64,
//!     pub rx_buf: u64,
//!     pub len: u32,
//!
//!     // optional overrides
//!     pub speed_hz: u32,
//!     pub delay_usecs: u16,
//!     pub bits_per_word: u8,
//!     pub cs_change: u8,
//!     pub pad: u32,
//! }
//!
//! #[cfg(linux)]
//! mod ioctl {
//!     use super::*;
//!
//!     const SPI_IOC_MAGIC: u8 = 'k' as u8;
//!     const SPI_IOC_NR_TRANSFER: u8 = 0;
//!     const SPI_IOC_NR_MODE: u8 = 1;
//!     const SPI_IOC_NR_LSB_FIRST: u8 = 2;
//!     const SPI_IOC_NR_BITS_PER_WORD: u8 = 3;
//!     const SPI_IOC_NR_MAX_SPEED_HZ: u8 = 4;
//!     const SPI_IOC_NR_MODE32: u8 = 5;
//!
//!     ioctl!(read  get_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8);
//!     ioctl!(read  get_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u32);
//!     ioctl!(write set_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8);
//!     ioctl!(write set_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE32; u32);
//!     ioctl!(read  get_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8);
//!     ioctl!(write set_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8);
//!     ioctl!(read  get_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8);
//!     ioctl!(write set_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8);
//!     ioctl!(read  get_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32);
//!     ioctl!(write set_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32);
//!     ioctl!(write spidev_transfer with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
//!     ioctl!(write buf spidev_transfer_buf with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
//! }
//!
//! // doctest workaround
//! fn main() {}
//! ```
//!
//! Spidev uses the `_IOC` macros that are encouraged (as far as
//! `ioctl` can be encouraged at all) for newer drivers.  Many
//! drivers, however, just use magic numbers with no attached
//! semantics.  For those, the `ioctl!(bad ...)` variant should be
//! used (the "bad" terminology is from the Linux kernel).
//!
//! How do I get the magic numbers?
//! ===============================
//!
//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
//! of lines defining macros which use `_IOR`, `_IOW`, `_IOC`, and `_IORW`.  These macros
//! correspond to the `ior!`, `iow!`, `ioc!`, and `iorw!` macros defined in this crate.
//! Additionally, there is the `ioctl!` macro for creating a wrapper around `ioctl` that is
//! somewhat more type-safe.
//!
//! Most `ioctl`s have no or little documentation. You'll need to scrounge through
//! the source to figure out what they do and how they should be used.
//!
#[cfg(any(target_os = "linux", target_os = "android"))]
#[path = "platform/linux.rs"]
#[macro_use]
mod platform;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "netbsd",
          target_os = "openbsd",
          target_os = "freebsd",
          target_os = "dragonfly"))]
#[path = "platform/bsd.rs"]
#[macro_use]
mod platform;

pub use self::platform::*;

// liblibc has the wrong decl for linux :| hack until #26809 lands.
extern "C" {
    #[doc(hidden)]
    pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int;
}

/// A hack to get the macros to work nicely.
#[doc(hidden)]
pub use ::libc as libc;

/// Convert raw ioctl return value to a Nix result
#[macro_export]
macro_rules! convert_ioctl_res {
    ($w:expr) => (
        {
            $crate::Errno::result($w)
        }
    );
}

#[macro_export]
macro_rules! ioctl {
    ($name:ident with $nr:expr) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            data: *mut u8)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, $nr as $crate::sys::ioctl::libc::c_ulong, data))
        }
        );
    (none $name:ident with $ioty:expr, $nr:expr) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, io!($ioty, $nr) as $crate::sys::ioctl::libc::c_ulong))
        }
        );
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: $ty)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *const $ty,
                            len: usize) -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
}
<commit_msg>Remove old workaround<commit_after>//! Provide helpers for making ioctl system calls
//!
//! Currently supports Linux on all architectures. Other platforms welcome!
//!
//! This library is pretty low-level and messy. `ioctl` is not fun.
//!
//! What is an `ioctl`?
//! ===================
//!
//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want
//! to add a new syscall? Make it an `ioctl`! `ioctl` refers to both the syscall,
//! and the commands that can be send with it. `ioctl` stands for "IO control",
//! and the commands are always sent to a file descriptor.
//!
//! It is common to see `ioctl`s used for the following purposes:
//!
//! * Provide read/write access to out-of-band data related
//!   to a device such as configuration (for instance, setting
//!   serial port options)
//! * Provide a mechanism for performing full-duplex data
//!   transfers (for instance, xfer on SPI devices).
//! * Provide access to control functions on a device (for example,
//!   on Linux you can send commands like pause, resume, and eject
//!   to the CDROM device.
//! * Do whatever else the device driver creator thought made most sense.
//!
//! `ioctl`s are synchronous system calls and are similar to read and
//! write calls in that regard.
//!
//! What does this module support?
//! ===============================
//!
//! This library provides the `ioctl!` macro, for binding `ioctl`s.
//! Here's a few examples of how that can work for SPI under Linux
//! from [rust-spidev](https://github.com/posborne/rust-spidev).
//!
//! ```
//! #[allow(non_camel_case_types)]
//! pub struct spi_ioc_transfer {
//!     pub tx_buf: u64,
//!     pub rx_buf: u64,
//!     pub len: u32,
//!
//!     // optional overrides
//!     pub speed_hz: u32,
//!     pub delay_usecs: u16,
//!     pub bits_per_word: u8,
//!     pub cs_change: u8,
//!     pub pad: u32,
//! }
//!
//! #[cfg(linux)]
//! mod ioctl {
//!     use super::*;
//!
//!     const SPI_IOC_MAGIC: u8 = 'k' as u8;
//!     const SPI_IOC_NR_TRANSFER: u8 = 0;
//!     const SPI_IOC_NR_MODE: u8 = 1;
//!     const SPI_IOC_NR_LSB_FIRST: u8 = 2;
//!     const SPI_IOC_NR_BITS_PER_WORD: u8 = 3;
//!     const SPI_IOC_NR_MAX_SPEED_HZ: u8 = 4;
//!     const SPI_IOC_NR_MODE32: u8 = 5;
//!
//!     ioctl!(read  get_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8);
//!     ioctl!(read  get_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u32);
//!     ioctl!(write set_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8);
//!     ioctl!(write set_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE32; u32);
//!     ioctl!(read  get_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8);
//!     ioctl!(write set_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8);
//!     ioctl!(read  get_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8);
//!     ioctl!(write set_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8);
//!     ioctl!(read  get_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32);
//!     ioctl!(write set_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32);
//!     ioctl!(write spidev_transfer with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
//!     ioctl!(write buf spidev_transfer_buf with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
//! }
//!
//! // doctest workaround
//! fn main() {}
//! ```
//!
//! Spidev uses the `_IOC` macros that are encouraged (as far as
//! `ioctl` can be encouraged at all) for newer drivers.  Many
//! drivers, however, just use magic numbers with no attached
//! semantics.  For those, the `ioctl!(bad ...)` variant should be
//! used (the "bad" terminology is from the Linux kernel).
//!
//! How do I get the magic numbers?
//! ===============================
//!
//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
//! of lines defining macros which use `_IOR`, `_IOW`, `_IOC`, and `_IORW`.  These macros
//! correspond to the `ior!`, `iow!`, `ioc!`, and `iorw!` macros defined in this crate.
//! Additionally, there is the `ioctl!` macro for creating a wrapper around `ioctl` that is
//! somewhat more type-safe.
//!
//! Most `ioctl`s have no or little documentation. You'll need to scrounge through
//! the source to figure out what they do and how they should be used.
//!
#[cfg(any(target_os = "linux", target_os = "android"))]
#[path = "platform/linux.rs"]
#[macro_use]
mod platform;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "netbsd",
          target_os = "openbsd",
          target_os = "freebsd",
          target_os = "dragonfly"))]
#[path = "platform/bsd.rs"]
#[macro_use]
mod platform;

pub use self::platform::*;

/// A hack to get the macros to work nicely.
#[doc(hidden)]
pub use ::libc as libc;

/// Convert raw ioctl return value to a Nix result
#[macro_export]
macro_rules! convert_ioctl_res {
    ($w:expr) => (
        {
            $crate::Errno::result($w)
        }
    );
}

#[macro_export]
macro_rules! ioctl {
    ($name:ident with $nr:expr) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            data: *mut u8)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, $nr as $crate::sys::ioctl::libc::c_ulong, data))
        }
        );
    (none $name:ident with $ioty:expr, $nr:expr) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, io!($ioty, $nr) as $crate::sys::ioctl::libc::c_ulong))
        }
        );
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: $ty)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *const $ty,
                            len: usize) -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
    (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::sys::ioctl::libc::c_int> {
            convert_ioctl_res!($crate::sys::ioctl::libc::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val))
        }
        );
}
<|endoftext|>