<commit_before>extern crate libc;

use self::libc::{c_char, c_uchar};

/// Creates and saves in secured Wallet identity that can be used to
/// issue and verify Identity Ledger transaction.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_json: Identity information as json. For current moment it is NYM transaction
///   data with optional information for creation of sign key (DID, Verkey, Role, Alias, Seed and etc...).
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// String identifier of this Identity.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_create_identity(client_id: i32, command_id: i32,
                                             identity_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           identity_id: *const c_char)) {
    unimplemented!();
}

/// Returns public information for Identity stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_id: Id of Identity stored in secured Wallet.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Public Identity information as json (DID, Verkey, Role, Alias and etc...).
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identity(client_id: i32, command_id: i32,
                                          identity_id: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        identity_json: *const c_char)) {
    unimplemented!();
}

/// Returns list of ids for Identities stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// List of stored identity ids.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identities(client_id: i32, command_id: i32,
                                            cb: extern fn(xcommand_id: i32, err: i32,
                                                          identity_ids: [*const c_char])) {
    unimplemented!();
}

/// Creates all necessary keys and objects depends on received schema and returns schema_id.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_json: Schema as a json. Includes name, version, attributes, keys, accumulator and etc.
///     Every empty field in the schema will be filled with the right value.
///     For example: if schema have an empty public key value, function will generate it. If it's
///         not necessary, value for public key field should be None.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of schema.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_create_schema(client_id: i32, command_id: i32,
                                             schema_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           schema_id: *const c_char)) {
    unimplemented!();
}

// Returns public fields of schema
pub extern fn wallet_anoncreds_get_schema(client_id: i32, command_id: i32,
                                          schema_id: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        schema_json: *const c_char)) {
    unimplemented!();
}

// Generates new issuer keys and crypto variables for stored schema
pub extern fn wallet_anoncreds_schema_update_issuer_key(client_id: i32, command_id: i32,
                                                        schema_id: *const c_char,
                                                        cb: extern fn(xcommand_id: i32, err: i32)) {
    unimplemented!();
}

/// Creates and saves in secured Wallet received claim.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_id: id of schema for which claim was generated.
/// claim_json: Claim as a json.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of claim.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_create_claim(client_id: i32, command_id: i32,
                                            schema_id: *const c_char,
                                            claim_json: *const c_char,
                                            cb: extern fn(xcommand_id: i32, err: i32,
                                                          claim_id: *const c_char)) {
    unimplemented!();
}<commit_msg>* Added new methods to anoncreds wallet<commit_after>extern crate libc;

use self::libc::{c_char, c_uchar};

/// Creates and saves in secured Wallet identity that can be used to
/// issue and verify Identity Ledger transaction.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_json: Identity information as json. For current moment it is NYM transaction
///   data with optional information for creation of sign key (DID, Verkey, Role, Alias, Seed and etc...).
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// String identifier of this Identity.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_create_identity(client_id: i32, command_id: i32,
                                             identity_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           identity_id: *const c_char)) {
    unimplemented!();
}

/// Returns public information for Identity stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// identity_id: Id of Identity stored in secured Wallet.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Public Identity information as json (DID, Verkey, Role, Alias and etc...).
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identity(client_id: i32, command_id: i32,
                                          identity_id: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        identity_json: *const c_char)) {
    unimplemented!();
}

/// Returns list of ids for Identities stored in secured Wallet.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// List of stored identity ids.
///
/// #Errors
/// No method specific errors.
/// See `SovrinError` docs for common errors description.
#[no_mangle]
pub  extern fn wallet_sovrin_get_identities(client_id: i32, command_id: i32,
                                            cb: extern fn(xcommand_id: i32, err: i32,
                                                          identity_ids: [*const c_char])) {
    unimplemented!();
}

/// Creates all necessary keys and objects depends on received schema and returns schema_id.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_json: Schema as a json. Includes name, version, attributes, keys, accumulator and etc.
///     Every empty field in the schema will be filled with the right value.
///     For example: if schema have an empty public key value, function will generate it. If it's
///         not necessary, value for public key field should be None.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of schema.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_create_schema(client_id: i32, command_id: i32,
                                             schema_json: *const c_char,
                                             cb: extern fn(xcommand_id: i32, err: i32,
                                                           schema_id: *const c_char)) {
    unimplemented!();
}

// Returns public fields of schema
pub extern fn wallet_anoncreds_get_schema(client_id: i32, command_id: i32,
                                          schema_id: *const c_char,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        schema_json: *const c_char)) {
    unimplemented!();
}

// Returns list of ides for all saved schemes
pub extern fn wallet_anoncreds_get_schemes(client_id: i32, command_id: i32,
                                          cb: extern fn(xcommand_id: i32, err: i32,
                                                        schema_jsons: [*const c_char])) {
    unimplemented!();
}

// Generates new issuer keys and crypto variables for stored schema
pub extern fn wallet_anoncreds_schema_update_issuer_key(client_id: i32, command_id: i32,
                                                        schema_id: *const c_char,
                                                        cb: extern fn(xcommand_id: i32, err: i32)) {
    unimplemented!();
}

/// Creates and saves in secured Wallet received claim.
///
/// #Params
/// client_id: id of sovrin client instance.
/// command_id: command id to map of callback to user context.
/// schema_id: id of schema for which claim was generated.
/// claim_json: Claim as a json.
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Returns id of claim.
///
/// #Errors
/// No method specific errors.
/// See `AnoncredsError` docs for common errors description.
#[no_mangle]
pub extern fn wallet_anoncreds_create_claim(client_id: i32, command_id: i32,
                                            schema_id: *const c_char,
                                            claim_json: *const c_char,
                                            cb: extern fn(xcommand_id: i32, err: i32,
                                                          claim_id: *const c_char)) {
    unimplemented!();
}<|endoftext|>


<commit_before>#![allow(let_unit_value, new_without_default, non_snake_case, transmute_ptr_to_ref, type_complexity, unused_imports)]

#[macro_use]
extern crate glib;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys;
extern crate gtk;
extern crate libc;

extern crate webkit2gtk_webextension_sys as ffi;

pub use glib::Error;

macro_rules! assert_initialized_main_thread {
    () => (
        if !::gtk::is_initialized_main_thread() {
            if ::gtk::is_initialized() {
                panic!("GTK may only be used from the main thread.");
            }
            else {
                panic!("GTK has not been initialized. Call `gtk::init` first.");
            }
        }
    )
}

macro_rules! skip_assert_initialized {
    () => ()
}

macro_rules! callback_guard {
    () => (
        let _guard = ::glib::CallbackGuard::new();
    )
}

#[macro_export]
macro_rules! web_extension_init {
    () => {
        extern crate glib;
        extern crate glib_sys;
        extern crate webkit2gtk_webextension_sys;

        #[no_mangle]
        pub unsafe fn webkit_web_extension_initialize_with_user_data(extension: *mut ::webkit2gtk_webextension_sys::WebKitWebExtension, user_data: *mut ::glib_sys::GVariant) {
            web_extension_initialize(::glib::translate::FromGlibPtrNone::from_glib_none(extension), ::glib::translate::FromGlibPtr::from_glib_none(user_data));
        }
    };
}

mod auto;
mod dom_dom_selection;
mod dom_dom_window;
mod dom_html_field_set_element;

pub use auto::*;
pub use dom_dom_selection::*;
pub use dom_dom_window::*;
pub use dom_html_field_set_element::*;

unsafe impl Send for WebExtension {}
<commit_msg>Add missing FromGlibPtrNone<commit_after>#![allow(let_unit_value, new_without_default, non_snake_case, transmute_ptr_to_ref, type_complexity, unused_imports)]

#[macro_use]
extern crate glib;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys;
extern crate gtk;
extern crate libc;

extern crate webkit2gtk_webextension_sys as ffi;

pub use glib::Error;

macro_rules! assert_initialized_main_thread {
    () => (
        if !::gtk::is_initialized_main_thread() {
            if ::gtk::is_initialized() {
                panic!("GTK may only be used from the main thread.");
            }
            else {
                panic!("GTK has not been initialized. Call `gtk::init` first.");
            }
        }
    )
}

macro_rules! skip_assert_initialized {
    () => ()
}

macro_rules! callback_guard {
    () => (
        let _guard = ::glib::CallbackGuard::new();
    )
}

#[macro_export]
macro_rules! web_extension_init {
    () => {
        extern crate glib;
        extern crate glib_sys;
        extern crate webkit2gtk_webextension_sys;

        #[no_mangle]
        pub unsafe fn webkit_web_extension_initialize_with_user_data(extension: *mut ::webkit2gtk_webextension_sys::WebKitWebExtension, user_data: *mut ::glib_sys::GVariant) {
            web_extension_initialize(::glib::translate::FromGlibPtrNone::from_glib_none(extension), ::glib::translate::FromGlibPtrNone::from_glib_none(user_data));
        }
    };
}

mod auto;
mod dom_dom_selection;
mod dom_dom_window;
mod dom_html_field_set_element;

pub use auto::*;
pub use dom_dom_selection::*;
pub use dom_dom_window::*;
pub use dom_html_field_set_element::*;

unsafe impl Send for WebExtension {}
<|endoftext|>


<commit_before>extern crate pkg_config;
extern crate semver;

use std::error::Error;
use std::path::{Path, PathBuf};
use std::process;
use std::process::Command;
use std::{env, fs};
use semver::Version;

const LIBRARY: &'static str = "tensorflow_c";
const REPOSITORY: &'static str = "https://github.com/tensorflow/tensorflow.git";
const TARGET: &'static str = "tensorflow:libtensorflow_c.so";
const VERSION: &'static str = "0.11.0";
const MIN_BAZEL: &'static str = "0.3.1";

macro_rules! get(($name:expr) => (ok!(env::var($name))));
macro_rules! ok(($expression:expr) => ($expression.unwrap()));
macro_rules! log {
    ($fmt:expr) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt), line!()));
    ($fmt:expr, $($arg:tt)*) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt), line!(), $($arg)*));
}
macro_rules! log_var(($var:ident) => (log!(concat!(stringify!($var), " = {:?}"), $var)));

fn main() {
    if pkg_config::find_library(LIBRARY).is_ok() {
        log!("Returning early because {} was already found", LIBRARY);
        return;
    }

    let output = PathBuf::from(&get!("OUT_DIR"));
    log_var!(output);
    let source = PathBuf::from(&get!("CARGO_MANIFEST_DIR")).join(format!("target/source-{}", VERSION));
    log_var!(source);
    let lib_dir = output.join(format!("lib-{}", VERSION));
    log_var!(lib_dir);
    if lib_dir.exists() {
        log!("Directory {:?} already exists", lib_dir);
    } else {
        log!("Creating directory {:?}", lib_dir);
        fs::create_dir(lib_dir.clone()).unwrap();
    }
    let library_path = lib_dir.join(format!("lib{}.so", LIBRARY));
    log_var!(library_path);
    if library_path.exists() {
        log!("{:?} already exists, not building", library_path);
    } else {
        if let Err(e) = check_bazel() {
            println!("cargo:error=Bazel must be installed at be version {} or greater. (Error: {})", MIN_BAZEL, e);
            process::exit(1);
        }
        let target_path = &TARGET.replace(":", "/");
        log_var!(target_path);
        if !Path::new(&source.join(".git")).exists() {
            run("git", |command| command.arg("clone")
                                        .arg(format!("--branch=v{}", VERSION))
                                        .arg("--recursive")
                                        .arg(REPOSITORY)
                                        .arg(&source));
        }
        run("./configure", |command| command.current_dir(&source));
        run("bazel", |command| command.current_dir(&source)
                                      .arg("build")
                                      .arg(format!("--jobs={}", get!("NUM_JOBS")))
                                      .arg("--compilation_mode=opt")
                                      .arg(TARGET));
        let target_bazel_bin = source.join("bazel-bin").join(target_path);
        log!("Copying {:?} to {:?}", target_bazel_bin, library_path);
        fs::copy(target_bazel_bin, library_path).unwrap();
    }

    println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
    println!("cargo:rustc-link-search={}", lib_dir.display());
}

fn run<F>(name: &str, mut configure: F) where F: FnMut(&mut Command) -> &mut Command {
    let mut command = Command::new(name);
    let configured = configure(&mut command);
    log!("Executing {:?}", configured);
    if !ok!(configured.status()).success() {
        panic!("failed to execute {:?}", configured);
    }
    log!("Command {:?} finished successfully", configured);
}

// Building TF 0.11.0rc1 with Bazel 0.3.0 gives this error when running `configure`:
//   expected ConfigurationTransition or NoneType for 'cfg' while calling label_list but got string instead:     data.
//       ERROR: com.google.devtools.build.lib.packages.BuildFileContainsErrorsException: error loading package '': Extension file 'tensorflow/tensorflow.bzl' has errors.
// And the simple solution is to require Bazel 0.3.1 or higher.
fn check_bazel() -> Result<(), Box<Error>> {
    let mut command = Command::new("bazel");
    command.arg("version");
    log!("Executing {:?}", command);
    let out = try!(command.output());
    log!("Command {:?} finished successfully", command);
    let stdout = try!(String::from_utf8(out.stdout));
    let mut found_version = false;
    for line in stdout.lines() {
        if line.starts_with("Build label:") {
            found_version = true;
            let version_str = line.split(":").nth(1).unwrap().trim();
            let version = try!(Version::parse(version_str));
            let want = try!(Version::parse(MIN_BAZEL));
            if version < want {
                return Err(format!("Installed version {} is less than required version {}", version_str, MIN_BAZEL).into());
            }
        }
    }
    if !found_version {
        return Err("Did not find version number in `bazel version` output.".into());
    }
    Ok(())
}
<commit_msg>Bump to TensorFlow version 0.12.0<commit_after>extern crate pkg_config;
extern crate semver;

use std::error::Error;
use std::path::{Path, PathBuf};
use std::process;
use std::process::Command;
use std::{env, fs};
use semver::Version;

const LIBRARY: &'static str = "tensorflow_c";
const REPOSITORY: &'static str = "https://github.com/tensorflow/tensorflow.git";
const TARGET: &'static str = "tensorflow:libtensorflow_c.so";
const TAG: &'static str = "v0.12.0";
const MIN_BAZEL: &'static str = "0.3.1";

macro_rules! get(($name:expr) => (ok!(env::var($name))));
macro_rules! ok(($expression:expr) => ($expression.unwrap()));
macro_rules! log {
    ($fmt:expr) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt), line!()));
    ($fmt:expr, $($arg:tt)*) => (println!(concat!("libtensorflow-sys/build.rs:{}: ", $fmt), line!(), $($arg)*));
}
macro_rules! log_var(($var:ident) => (log!(concat!(stringify!($var), " = {:?}"), $var)));

fn main() {
    if pkg_config::find_library(LIBRARY).is_ok() {
        log!("Returning early because {} was already found", LIBRARY);
        return;
    }

    let output = PathBuf::from(&get!("OUT_DIR"));
    log_var!(output);
    let source = PathBuf::from(&get!("CARGO_MANIFEST_DIR")).join(format!("target/source-{}", TAG));
    log_var!(source);
    let lib_dir = output.join(format!("lib-{}", TAG));
    log_var!(lib_dir);
    if lib_dir.exists() {
        log!("Directory {:?} already exists", lib_dir);
    } else {
        log!("Creating directory {:?}", lib_dir);
        fs::create_dir(lib_dir.clone()).unwrap();
    }
    let library_path = lib_dir.join(format!("lib{}.so", LIBRARY));
    log_var!(library_path);
    if library_path.exists() {
        log!("{:?} already exists, not building", library_path);
    } else {
        if let Err(e) = check_bazel() {
            println!("cargo:error=Bazel must be installed at be version {} or greater. (Error: {})", MIN_BAZEL, e);
            process::exit(1);
        }
        let target_path = &TARGET.replace(":", "/");
        log_var!(target_path);
        if !Path::new(&source.join(".git")).exists() {
            run("git", |command| command.arg("clone")
                                        .arg(format!("--branch={}", TAG))
                                        .arg("--recursive")
                                        .arg(REPOSITORY)
                                        .arg(&source));
        }
        run("bash", |command| command.current_dir(&source).arg("-c").arg("yes ''|./configure"));
        run("bazel", |command| command.current_dir(&source)
                                      .arg("build")
                                      .arg(format!("--jobs={}", get!("NUM_JOBS")))
                                      .arg("--compilation_mode=opt")
                                      .arg(TARGET));
        let target_bazel_bin = source.join("bazel-bin").join(target_path);
        log!("Copying {:?} to {:?}", target_bazel_bin, library_path);
        fs::copy(target_bazel_bin, library_path).unwrap();
    }

    println!("cargo:rustc-link-lib=dylib={}", LIBRARY);
    println!("cargo:rustc-link-search={}", lib_dir.display());
}

fn run<F>(name: &str, mut configure: F) where F: FnMut(&mut Command) -> &mut Command {
    let mut command = Command::new(name);
    let configured = configure(&mut command);
    log!("Executing {:?}", configured);
    if !ok!(configured.status()).success() {
        panic!("failed to execute {:?}", configured);
    }
    log!("Command {:?} finished successfully", configured);
}

// Building TF 0.11.0rc1 with Bazel 0.3.0 gives this error when running `configure`:
//   expected ConfigurationTransition or NoneType for 'cfg' while calling label_list but got string instead:     data.
//       ERROR: com.google.devtools.build.lib.packages.BuildFileContainsErrorsException: error loading package '': Extension file 'tensorflow/tensorflow.bzl' has errors.
// And the simple solution is to require Bazel 0.3.1 or higher.
fn check_bazel() -> Result<(), Box<Error>> {
    let mut command = Command::new("bazel");
    command.arg("version");
    log!("Executing {:?}", command);
    let out = try!(command.output());
    log!("Command {:?} finished successfully", command);
    let stdout = try!(String::from_utf8(out.stdout));
    let mut found_version = false;
    for line in stdout.lines() {
        if line.starts_with("Build label:") {
            found_version = true;
            let version_str = line.split(":").nth(1).unwrap().trim();
            let version = try!(Version::parse(version_str));
            let want = try!(Version::parse(MIN_BAZEL));
            if version < want {
                return Err(format!("Installed version {} is less than required version {}", version_str, MIN_BAZEL).into());
            }
        }
    }
    if !found_version {
        return Err("Did not find version number in `bazel version` output.".into());
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! Raw mode.

use std::io::{self, Write};
use std::ops;

/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(target_os = "redox")]
pub struct RawTerminal<W: Write> {
    output: W,
}

#[cfg(target_os = "redox")]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use control::TermWrite;
        self.csi(b"R").unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
use termios::Termios;
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(not(target_os = "redox"))]
pub struct RawTerminal<W: Write> {
    prev_ios: Termios,
    output: W,
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use termios::set_terminal_attr;
        set_terminal_attr(&mut self.prev_ios as *mut _);
    }
}

impl<W: Write> ops::Deref for RawTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> ops::DerefMut for RawTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for RawTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}

/// Types which can be converted into "raw mode".
pub trait IntoRawMode: Write + Sized {
    /// Switch to raw mode.
    ///
    /// Raw mode means that stdin won't be printed (it will instead have to be written manually by
    /// the program). Furthermore, the input isn't canonicalised or buffered (that is, you can
    /// read from stdin one byte of a time). The output is neither modified in any way.
    fn into_raw_mode(self) -> io::Result<RawTerminal<Self>>;
}

impl<W: Write> IntoRawMode for W {
    #[cfg(not(target_os = "redox"))]
    fn into_raw_mode(self) -> io::Result<RawTerminal<W>> {
        use termios::{cfmakeraw, get_terminal_attr, set_terminal_attr};

        let (mut ios, exit) = get_terminal_attr();
        let prev_ios = ios.clone();
        if exit != 0 {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to get Termios attribute."));
        }

        unsafe {
            cfmakeraw(&mut ios);
        }

        if set_terminal_attr(&mut ios as *mut _) != 0 {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
        } else {
            let res = RawTerminal {
                prev_ios: prev_ios,
                output: self,
            };
            Ok(res)
        }
    }

    #[cfg(target_os = "redox")]
    fn into_raw_mode(mut self) -> io::Result<RawTerminal<W>> {
        use control::TermWrite;

        self.csi(b"r").map(|_| {
            let mut res = RawTerminal { output: self };
            res
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Write, stdout};

    #[test]
    fn test_into_raw_mode() {
        let mut out = stdout().into_raw_mode().unwrap();

        out.write(b"this is a test, muahhahahah").unwrap();
    }
}
<commit_msg>Fix Redox raw mode<commit_after>//! Raw mode.

use std::io::{self, Write};
use std::ops;

/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(target_os = "redox")]
pub struct RawTerminal<W: Write> {
    output: W,
}

#[cfg(target_os = "redox")]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        write!(self, csi!("?82h")).unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
use termios::Termios;
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(not(target_os = "redox"))]
pub struct RawTerminal<W: Write> {
    prev_ios: Termios,
    output: W,
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use termios::set_terminal_attr;
        set_terminal_attr(&mut self.prev_ios as *mut _);
    }
}

impl<W: Write> ops::Deref for RawTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> ops::DerefMut for RawTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for RawTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}

/// Types which can be converted into "raw mode".
pub trait IntoRawMode: Write + Sized {
    /// Switch to raw mode.
    ///
    /// Raw mode means that stdin won't be printed (it will instead have to be written manually by
    /// the program). Furthermore, the input isn't canonicalised or buffered (that is, you can
    /// read from stdin one byte of a time). The output is neither modified in any way.
    fn into_raw_mode(self) -> io::Result<RawTerminal<Self>>;
}

impl<W: Write> IntoRawMode for W {
    #[cfg(not(target_os = "redox"))]
    fn into_raw_mode(self) -> io::Result<RawTerminal<W>> {
        use termios::{cfmakeraw, get_terminal_attr, set_terminal_attr};

        let (mut ios, exit) = get_terminal_attr();
        let prev_ios = ios.clone();
        if exit != 0 {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to get Termios attribute."));
        }

        unsafe {
            cfmakeraw(&mut ios);
        }

        if set_terminal_attr(&mut ios as *mut _) != 0 {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
        } else {
            let res = RawTerminal {
                prev_ios: prev_ios,
                output: self,
            };
            Ok(res)
        }
    }

    #[cfg(target_os = "redox")]
    fn into_raw_mode(mut self) -> io::Result<RawTerminal<W>> {
        write!(self, csi!("?82h")).map(|_| {
            RawTerminal { output: self }
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Write, stdout};

    #[test]
    fn test_into_raw_mode() {
        let mut out = stdout().into_raw_mode().unwrap();

        out.write(b"this is a test, muahhahahah").unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::io;
use std::net;
use std::mem;

#[allow(non_snake_case)]
pub mod Domain {
    use super::libc;
    pub const IPV4 : libc::c_int = libc::AF_INET;
    pub const IPV6 : libc::c_int = libc::AF_INET6;
    pub const PACKET : libc::c_int = libc::AF_PACKET;
}

#[allow(non_snake_case)]
pub mod Protocol {
    use super::libc;
    pub const RAW : libc::c_int = libc::IPPROTO_RAW;
    #[cfg(target_endian = "little")]
    pub const ETH_ALL : u16 = 0x0300;                           //TODO: use htons
    #[cfg(target_endian = "big")]
    pub const ETH_ALL : u16 = 0x0003;
}

type SOCKET = libc::c_int;

pub struct Socket {
    fd: SOCKET
}

impl Socket {
    pub fn new(domain : libc::c_int, protocol : libc::c_int) -> io::Result<Socket> {
        unsafe {
            match libc::socket(domain, libc::SOCK_RAW, protocol) {
                -1 => Err(io::Error::last_os_error()),
                fd => Ok(Socket {
                    fd: fd
                })
            }
        }
    }

    pub fn send_to(&self, buffer : &[u8], dest_addr : net::SocketAddr, flags : libc::c_int) -> io::Result<usize> {
        let length = buffer.len();
        let (dst_addr, dst_addr_len) = to_c_sockaddr_struct(dest_addr);

        unsafe {
            match libc::sendto(self.fd, buffer.as_ptr() as *const libc::c_void, length, flags, dst_addr, dst_addr_len) {
                -1 => {
                    let system_error = io::Error::last_os_error();

                    match system_error.raw_os_error().unwrap() {
                        libc::ESHUTDOWN => Ok(0),
                        _ => Err(system_error)
                    }
                },
                n => Ok(n as usize)
            }
        }
    }

    pub fn send(&self, buffer : &[u8], flags : libc::c_int) -> io::Result<usize> {
        unsafe {
            match libc::send(self.fd, buffer.as_ptr() as *const libc::c_void, buffer.len(), flags) {
                -1 => {
                    let system_error = io::Error::last_os_error();

                    match system_error.raw_os_error().unwrap() {
                        libc::ESHUTDOWN => Ok(0),
                        _ => Err(system_error)
                    }
                },
                n => Ok(n as usize)
            }
        }
    }

    pub fn receive(&self, buffer : &mut [u8], flags : libc::c_int) -> io::Result<usize> {
        unsafe {
            match libc::recv(self.fd, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len(), flags) {
                -1 => Err(io::Error::last_os_error()),
                n => Ok(n as usize)
            }
        }
    }

    pub fn receive_from(&self, buffer : &mut [u8], flags : libc::c_int) -> io::Result<(usize, net::SocketAddr)> {
        unsafe {
            let mut dst_addr : libc::sockaddr_storage = mem::zeroed();
            let mut dst_addr_len : libc::socklen_t = mem::size_of_val(&dst_addr) as libc::socklen_t;

            match libc::recvfrom(self.fd, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len(), flags, &mut dst_addr as *mut _ as *mut _, &mut dst_addr_len) {
                -1 => Err(io::Error::last_os_error()),
                n => Ok((n as usize, to_rust_socketaddr(&dst_addr)?))
            }
        }
    }

    pub fn close(&self) -> io::Result<()> {
        unsafe {
            match libc::close(self.fd) {
                0 => Ok(()),
                _ => Err(io::Error::last_os_error())
            }
        }
    }
}

fn to_c_sockaddr_struct(address : net::SocketAddr) -> (*const libc::sockaddr, libc::socklen_t) {
    match address {
        net::SocketAddr::V4(ref addr) =>
            (addr as *const _ as *const _, mem::size_of_val(addr) as libc::socklen_t),
        net::SocketAddr::V6(ref addr) =>
            (addr as *const _ as *const _, mem::size_of_val(addr) as libc::socklen_t)

    }
}

fn to_rust_socketaddr(c_struct : &libc::sockaddr_storage) -> io::Result<net::SocketAddr> {
    match c_struct.ss_family as libc::c_int {
        libc::AF_INET => {
            let ipv4_c_struct = unsafe { *(c_struct as *const _ as *const libc::sockaddr_in) };
            let ipv4_addr = unsafe { *(&ipv4_c_struct as *const _ as *const _ as *const [u8; 4]) };
            let ipv4_addr = net::Ipv4Addr::from(ipv4_addr);

            #[cfg(target_endian = "little")]
            let socket_addr = net::SocketAddrV4::new(ipv4_addr, ipv4_c_struct.sin_port.to_be());
            #[cfg(target_endian = "big")]
            let socket_addr = net::SocketAddrV4::new(ipv4_addr, ipv4_c_struct.sin_port);

            Ok(net::SocketAddr::V4(socket_addr))
        },
        libc::AF_INET6 => {
            let ipv6_c_struct = unsafe { *(c_struct as *const _ as *const libc::sockaddr_in6) };
            let ipv6_addr = net::Ipv6Addr::from(ipv6_c_struct.sin6_addr.s6_addr.clone());

            #[cfg(target_endian = "little")]
            let socket_addr = net::SocketAddrV6::new(ipv6_addr, ipv6_c_struct.sin6_port.to_be(), ipv6_c_struct.sin6_flowinfo, ipv6_c_struct.sin6_scope_id);
            #[cfg(target_endian = "big")]
            let socket_addr = net::SocketAddrV6::new(ipv6_addr, ipv6_c_struct.sin6_port, ipv6_c_struct.sin6_flowinfo, ipv6_c_struct.sin6_scope_id);

            Ok(net::SocketAddr::V6(socket_addr))
        },
        _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Unknown address type! This version only supports IPv4 and IPv6."))
    }
}

impl Drop for Socket {
    fn drop(&mut self) {
        let _ = self.close();
    }
}
<commit_msg>implemented bind<commit_after>extern crate libc;

use std::io;
use std::net;
use std::mem;

#[allow(non_snake_case)]
pub mod Domain {
    use super::libc;
    pub const IPV4 : libc::c_int = libc::AF_INET;
    pub const IPV6 : libc::c_int = libc::AF_INET6;
    pub const PACKET : libc::c_int = libc::AF_PACKET;
}

#[allow(non_snake_case)]
pub mod Protocol {
    use super::libc;
    pub const RAW : libc::c_int = libc::IPPROTO_RAW;
    #[cfg(target_endian = "little")]
    pub const ETH_ALL : u16 = 0x0300;                           //TODO: use htons
    #[cfg(target_endian = "big")]
    pub const ETH_ALL : u16 = 0x0003;
}

type SOCKET = libc::c_int;

pub struct Socket {
    fd: SOCKET
}

impl Socket {
    pub fn new(domain : libc::c_int, protocol : libc::c_int) -> io::Result<Socket> {
        unsafe {
            match libc::socket(domain, libc::SOCK_RAW, protocol) {
                -1 => Err(io::Error::last_os_error()),
                fd => Ok(Socket {
                    fd: fd
                })
            }
        }
    }

    pub fn bind(&self, dest_addr : net::SocketAddr) -> io::Result<()> {
        let (dest_addr, dst_addr_len) = to_c_sockaddr_struct(dest_addr);

        unsafe {
            match libc::bind(self.fd, dest_addr, dest_addr_len) {
                0 => Ok(()),
                _ => Err(io::Error::last_os_error())
            }
        }
    }

    pub fn send_to(&self, buffer : &[u8], dest_addr : net::SocketAddr, flags : libc::c_int) -> io::Result<usize> {
        let length = buffer.len();
        let (dest_addr, dest_addr_len) = to_c_sockaddr_struct(dest_addr);

        unsafe {
            match libc::sendto(self.fd, buffer.as_ptr() as *const libc::c_void, length, flags, dest_addr, dest_addr_len) {
                -1 => {
                    let system_error = io::Error::last_os_error();

                    match system_error.raw_os_error().unwrap() {
                        libc::ESHUTDOWN => Ok(0),
                        _ => Err(system_error)
                    }
                },
                n => Ok(n as usize)
            }
        }
    }

    pub fn send(&self, buffer : &[u8], flags : libc::c_int) -> io::Result<usize> {
        unsafe {
            match libc::send(self.fd, buffer.as_ptr() as *const libc::c_void, buffer.len(), flags) {
                -1 => {
                    let system_error = io::Error::last_os_error();

                    match system_error.raw_os_error().unwrap() {
                        libc::ESHUTDOWN => Ok(0),
                        _ => Err(system_error)
                    }
                },
                n => Ok(n as usize)
            }
        }
    }

    pub fn receive(&self, buffer : &mut [u8], flags : libc::c_int) -> io::Result<usize> {
        unsafe {
            match libc::recv(self.fd, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len(), flags) {
                -1 => Err(io::Error::last_os_error()),
                n => Ok(n as usize)
            }
        }
    }

    pub fn receive_from(&self, buffer : &mut [u8], flags : libc::c_int) -> io::Result<(usize, net::SocketAddr)> {
        unsafe {
            let mut dst_addr : libc::sockaddr_storage = mem::zeroed();
            let mut dst_addr_len : libc::socklen_t = mem::size_of_val(&dst_addr) as libc::socklen_t;

            match libc::recvfrom(self.fd, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len(), flags, &mut dst_addr as *mut _ as *mut _, &mut dst_addr_len) {
                -1 => Err(io::Error::last_os_error()),
                n => Ok((n as usize, to_rust_socketaddr(&dst_addr)?))
            }
        }
    }

    pub fn close(&self) -> io::Result<()> {
        unsafe {
            match libc::close(self.fd) {
                0 => Ok(()),
                _ => Err(io::Error::last_os_error())
            }
        }
    }
}

fn to_c_sockaddr_struct(address : net::SocketAddr) -> (*const libc::sockaddr, libc::socklen_t) {
    match address {
        net::SocketAddr::V4(ref addr) =>
            (addr as *const _ as *const _, mem::size_of_val(addr) as libc::socklen_t),
        net::SocketAddr::V6(ref addr) =>
            (addr as *const _ as *const _, mem::size_of_val(addr) as libc::socklen_t)

    }
}

fn to_rust_socketaddr(c_struct : &libc::sockaddr_storage) -> io::Result<net::SocketAddr> {
    match c_struct.ss_family as libc::c_int {
        libc::AF_INET => {
            let ipv4_c_struct = unsafe { *(c_struct as *const _ as *const libc::sockaddr_in) };
            let ipv4_addr = unsafe { *(&ipv4_c_struct as *const _ as *const _ as *const [u8; 4]) };
            let ipv4_addr = net::Ipv4Addr::from(ipv4_addr);

            #[cfg(target_endian = "little")]
            let socket_addr = net::SocketAddrV4::new(ipv4_addr, ipv4_c_struct.sin_port.to_be());
            #[cfg(target_endian = "big")]
            let socket_addr = net::SocketAddrV4::new(ipv4_addr, ipv4_c_struct.sin_port);

            Ok(net::SocketAddr::V4(socket_addr))
        },
        libc::AF_INET6 => {
            let ipv6_c_struct = unsafe { *(c_struct as *const _ as *const libc::sockaddr_in6) };
            let ipv6_addr = net::Ipv6Addr::from(ipv6_c_struct.sin6_addr.s6_addr.clone());

            #[cfg(target_endian = "little")]
            let socket_addr = net::SocketAddrV6::new(ipv6_addr, ipv6_c_struct.sin6_port.to_be(), ipv6_c_struct.sin6_flowinfo, ipv6_c_struct.sin6_scope_id);
            #[cfg(target_endian = "big")]
            let socket_addr = net::SocketAddrV6::new(ipv6_addr, ipv6_c_struct.sin6_port, ipv6_c_struct.sin6_flowinfo, ipv6_c_struct.sin6_scope_id);

            Ok(net::SocketAddr::V6(socket_addr))
        },
        _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Unknown address type! This version only supports IPv4 and IPv6."))
    }
}

impl Drop for Socket {
    fn drop(&mut self) {
        let _ = self.close();
    }
}
<|endoftext|>


<commit_before><commit_msg>more useful SSH error output<commit_after><|endoftext|>


<commit_before>use std::str::FromStr;
use temperature::circuit::ThreeDICE;
use temperature::{self, Simulator};
use threed_ice::{StackElement, System};

use profile::Profile;
use schedule::Decision;
use {Config, Error, Job, Result};

pub struct Platform {
    elements: Vec<Element>,
    simulator: Simulator,
    power: Profile,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Element {
    pub id: usize,
    pub kind: Kind,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Kind {
    Core,
    L3,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Capacity {
    Single,
    Infinite,
}

impl Platform {
    pub fn new(config: &Config) -> Result<Platform> {
        let path = path!(config, "a stack description");

        info!(target: "Platform", "Reading {:?}...", &path);
        let system = ok!(System::new(&path));

        let mut elements = vec![];
        for element in system.stack.elements.iter().rev() {
            let die = match element {
                &StackElement::Die(ref die) => die,
                _ => continue,
            };
            for element in die.floorplan.elements.iter() {
                let id = elements.len();
                let kind = try!(Kind::from_str(&element.id));
                elements.push(Element { id: id, kind: kind });
            }
        }
        info!(target: "Platform", "Found {} processing elements.", elements.len());

        info!(target: "Platform", "Constructing a thermal circuit...");
        let circuit = ok!(ThreeDICE::from(&system));
        info!(target: "Platform", "Obtained {} thermal nodes.", circuit.capacitance.len());

        info!(target: "Platform", "Initializing the temperature simulator...");
        let config = try!(new_temperature_config(&config));
        let simulator = ok!(Simulator::new(&circuit, &config));

        let power = Profile::new(elements.len(), config.time_step);

        Ok(Platform { elements: elements, simulator: simulator, power: power })
    }

    pub fn push(&mut self, job: &Job, decision: &Decision) -> Result<()> {
        let pattern = &job.pattern;
        let (from, onto) = (&pattern.elements, &self.elements);
        for &(i, j) in &decision.mapping {
            let (from, onto) = (&from[i], &onto[j]);
            self.power.push(onto.id, decision.start, pattern.time_step, &from.dynamic_power,
                            from.leakage_power);
        }
        Ok(())
    }

    pub fn next(&mut self, time: f64) -> Option<(Profile, Profile)> {
        let power = self.power.pull(time);
        let mut temperature = power.clone_zero();
        self.simulator.next(&power, &mut temperature);
        Some((power, temperature))
    }

    getters! {
        ref elements: [Element],
    }
}

impl Element {
    #[inline(always)]
    pub fn capacity(&self) -> Capacity {
        if self.kind == Kind::Core {
            Capacity::Single
        } else {
            Capacity::Infinite
        }
    }
}

impl FromStr for Kind {
    type Err = Error;

    fn from_str(id: &str) -> Result<Self> {
        let lower = id.to_lowercase();
        if lower.starts_with("core") {
            return Ok(Kind::Core);
        } else if lower.starts_with("l3") {
            return Ok(Kind::L3);
        }
        raise!("found an unknown id {:?}", id);
    }
}

fn new_temperature_config(config: &Config) -> Result<temperature::Config> {
    Ok(temperature::Config {
        ambience: *some!(config.get::<f64>("ambience"), "an ambient temperature is required"),
        time_step: *some!(config.get::<f64>("time_step"), "a time step is required"),
    })
}

#[cfg(test)]
mod tests {
    use configuration::format::TOML;
    use super::{Kind, Element, Platform};

    #[test]
    fn new() {
        let config = TOML::open("tests/fixtures/streamer.toml").unwrap()
                                                               .branch("platform")
                                                               .unwrap();
        let platform = Platform::new(&config).unwrap();
        assert_eq!(platform.elements, &[
            Element { id: 0, kind: Kind::Core },
            Element { id: 1, kind: Kind::Core },
            Element { id: 2, kind: Kind::Core },
            Element { id: 3, kind: Kind::Core },
            Element { id: 4, kind: Kind::L3 },
        ]);
    }
}
<commit_msg>Platform: extract 3D-ICE stuff into a separate function<commit_after>use std::str::FromStr;
use temperature::{self, Simulator};

use profile::Profile;
use schedule::Decision;
use {Config, Error, Job, Result};

pub struct Platform {
    elements: Vec<Element>,
    simulator: Simulator,
    power: Profile,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Element {
    pub id: usize,
    pub kind: Kind,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Kind {
    Core,
    L3,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Capacity {
    Single,
    Infinite,
}

impl Platform {
    pub fn new(config: &Config) -> Result<Platform> {
        let (elements, circuit) = try!(construct_threed_ice_cirucit(config));

        info!(target: "Platform", "Initializing the temperature simulator...");
        let config = try!(extract_temperature_config(config));
        let simulator = ok!(Simulator::new(&circuit, &config));

        let power = Profile::new(elements.len(), config.time_step);

        Ok(Platform { elements: elements, simulator: simulator, power: power })
    }

    pub fn push(&mut self, job: &Job, decision: &Decision) -> Result<()> {
        let pattern = &job.pattern;
        let (from, onto) = (&pattern.elements, &self.elements);
        for &(i, j) in &decision.mapping {
            let (from, onto) = (&from[i], &onto[j]);
            self.power.push(onto.id, decision.start, pattern.time_step, &from.dynamic_power,
                            from.leakage_power);
        }
        Ok(())
    }

    pub fn next(&mut self, time: f64) -> Option<(Profile, Profile)> {
        let power = self.power.pull(time);
        let mut temperature = power.clone_zero();
        self.simulator.next(&power, &mut temperature);
        Some((power, temperature))
    }

    getters! {
        ref elements: [Element],
    }
}

impl Element {
    #[inline(always)]
    pub fn capacity(&self) -> Capacity {
        if self.kind == Kind::Core {
            Capacity::Single
        } else {
            Capacity::Infinite
        }
    }
}

impl FromStr for Kind {
    type Err = Error;

    fn from_str(id: &str) -> Result<Self> {
        let lower = id.to_lowercase();
        if lower.starts_with("core") {
            return Ok(Kind::Core);
        } else if lower.starts_with("l3") {
            return Ok(Kind::L3);
        }
        raise!("found an unknown id {:?}", id);
    }
}

fn construct_threed_ice_cirucit(config: &Config) -> Result<(Vec<Element>, temperature::Circuit)> {
    use temperature::circuit::ThreeDICE;
    use threed_ice::{StackElement, System};

    let path = path!(config, "a stack description");

    info!(target: "Platform", "Reading {:?}...", &path);
    let system = ok!(System::new(&path));

    let mut elements = vec![];
    for element in system.stack.elements.iter().rev() {
        let die = match element {
            &StackElement::Die(ref die) => die,
            _ => continue,
        };
        for element in die.floorplan.elements.iter() {
            let id = elements.len();
            let kind = try!(Kind::from_str(&element.id));
            elements.push(Element { id: id, kind: kind });
        }
    }
    info!(target: "Platform", "Found {} processing elements.", elements.len());

    info!(target: "Platform", "Constructing a thermal circuit...");
    let circuit = ok!(ThreeDICE::from(&system));
    info!(target: "Platform", "Obtained {} thermal nodes.", circuit.capacitance.len());

    Ok((elements, circuit))
}

fn extract_temperature_config(config: &Config) -> Result<temperature::Config> {
    Ok(temperature::Config {
        ambience: *some!(config.get::<f64>("ambience"), "an ambient temperature is required"),
        time_step: *some!(config.get::<f64>("time_step"), "a time step is required"),
    })
}

#[cfg(test)]
mod tests {
    use configuration::format::TOML;
    use super::{Kind, Element, Platform};

    #[test]
    fn new() {
        let config = TOML::open("tests/fixtures/streamer.toml").unwrap()
                                                               .branch("platform")
                                                               .unwrap();
        let platform = Platform::new(&config).unwrap();
        assert_eq!(platform.elements, &[
            Element { id: 0, kind: Kind::Core },
            Element { id: 1, kind: Kind::Core },
            Element { id: 2, kind: Kind::Core },
            Element { id: 3, kind: Kind::Core },
            Element { id: 4, kind: Kind::L3 },
        ]);
    }
}
<|endoftext|>


<commit_before>use constants::VoiceOpCode;
use gateway::InterMessage;
use model::{
    id::{
        ChannelId,
        GuildId,
        UserId
    },
    voice::VoiceState
};
use parking_lot::Mutex;
use std::sync::{
    mpsc::{self, Sender as MpscSender},
    Arc
};
use super::connection_info::ConnectionInfo;
use super::{Audio, AudioReceiver, AudioSource, Status as VoiceStatus, threading, LockedAudio};

/// The handler is responsible for "handling" a single voice connection, acting
/// as a clean API above the inner connection.
///
/// Look into the [`Manager`] for a slightly higher-level interface for managing
/// the existence of handlers.
///
/// **Note**: You should _not_ manually mutate any struct fields. You should
/// _only_ read them. Use methods to mutate them.
///
/// # Examples
///
/// Assuming that you already have a `Manager`, most likely retrieved via a
/// [`Shard`], you can join a guild's voice channel and deafen yourself like so:
///
/// ```rust,ignore
/// // assuming a `manager` has already been bound, hopefully retrieved through
/// // a websocket's connection.
/// use serenity::model::{ChannelId, GuildId};
///
/// let guild_id = GuildId(81384788765712384);
/// let channel_id = ChannelId(85482585546833920);
///
/// let handler = manager.join(Some(guild_id), channel_id);
/// handler.deafen(true);
/// ```
///
/// [`Manager`]: struct.Manager.html
/// [`Shard`]: ../gateway/struct.Shard.html
#[derive(Clone, Debug)]
pub struct Handler {
    /// The ChannelId to be connected to, if any.
    ///
    /// **Note**: This _must not_ be manually mutated. Call [`switch_to`] to
    /// mutate this value.
    ///
    /// [`Group`]: ../../model/channel/struct.Group.html
    /// [`guild`]: #structfield.guild
    /// [`switch_to`]: #method.switch_to
    pub channel_id: Option<ChannelId>,
    /// The voice server endpoint.
    pub endpoint: Option<String>,
    /// The Id of the guild to be connected to.
    pub guild_id: GuildId,
    /// Whether the current handler is set to deafen voice connections.
    ///
    /// **Note**: This _must not_ be manually mutated. Call [`deafen`] to
    /// mutate this value.
    ///
    /// [`deafen`]: #method.deafen
    pub self_deaf: bool,
    /// Whether the current handler is set to mute voice connections.
    ///
    /// **Note**: This _must not_ be manually mutated. Call [`mute`] to mutate
    /// this value.
    ///
    /// [`mute`]: #method.mute
    pub self_mute: bool,
    /// The internal sender to the voice connection monitor thread.
    sender: MpscSender<VoiceStatus>,
    /// The session Id of the current voice connection, if any.
    ///
    /// **Note**: This _should_ be set through an [`update_state`] call.
    ///
    /// [`update_state`]: #method.update_state
    pub session_id: Option<String>,
    /// The token of the current voice connection, if any.
    ///
    /// **Note**: This _should_ be set through an [`update_server`] call.
    ///
    /// [`update_server`]: #method.update_server
    pub token: Option<String>,
    /// The Id of the current user.
    ///
    /// This is configured via [`new`] or [`standalone`].
    ///
    /// [`new`]: #method.new
    /// [`standalone`]: #method.standalone
    pub user_id: UserId,
    /// Will be set when a `Handler` is made via the [`new`][`Handler::new`]
    /// method.
    ///
    /// When set via [`standalone`][`Handler::standalone`], it will not be
    /// present.
    ws: Option<MpscSender<InterMessage>>,
}

impl Handler {
    /// Creates a new Handler.
    #[inline]
    pub(crate) fn new(
        guild_id: GuildId,
        ws: MpscSender<InterMessage>,
        user_id: UserId,
    ) -> Self {
        Self::new_raw(guild_id, Some(ws), user_id)
    }

    /// Creates a new, standalone Handler which is not connected to the primary
    /// WebSocket to the Gateway.
    ///
    /// Actions such as muting, deafening, and switching channels will not
    /// function through this Handler and must be done through some other
    /// method, as the values will only be internally updated.
    ///
    /// For most use cases you do not want this. Only use it if you are using
    /// the voice component standalone from the rest of the library.
    #[inline]
    pub fn standalone(guild_id: GuildId, user_id: UserId) -> Self {
        Self::new_raw(guild_id, None, user_id)
    }

    /// Connects to the voice channel if the following are present:
    ///
    /// - [`endpoint`]
    /// - [`session_id`]
    /// - [`token`]
    ///
    /// If they _are_ all present, then `true` is returned. Otherwise, `false`
    /// is.
    ///
    /// This will automatically be called by [`update_server`] or
    /// [`update_state`] when all three values become present.
    ///
    /// [`endpoint`]: #structfield.endpoint
    /// [`session_id`]: #structfield.session_id
    /// [`token`]: #structfield.token
    /// [`update_server`]: #method.update_server
    /// [`update_state`]: #method.update_state
    pub fn connect(&mut self) -> bool {
        if self.endpoint.is_none() || self.session_id.is_none() || self.token.is_none() {
            return false;
        }

        let endpoint = self.endpoint.clone().unwrap();
        let guild_id = self.guild_id;
        let session_id = self.session_id.clone().unwrap();
        let token = self.token.clone().unwrap();
        let user_id = self.user_id;

        // Safe as all of these being present was already checked.
        self.send(VoiceStatus::Connect(ConnectionInfo {
            endpoint,
            guild_id,
            session_id,
            token,
            user_id,
        }));

        true
    }

    /// Sets whether the current connection to be deafened.
    ///
    /// If there is no live voice connection, then this only acts as a settings
    /// update for future connections.
    ///
    /// **Note**: Unlike in the official client, you _can_ be deafened while
    /// not being muted.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally deafened.
    ///
    /// [`standalone`]: #method.standalone
    pub fn deafen(&mut self, deaf: bool) {
        self.self_deaf = deaf;

        // Only send an update if there is currently a connected channel.
        //
        // Otherwise, this can be treated as a "settings" update for a
        // connection.
        if self.channel_id.is_some() {
            self.update();
        }
    }

    /// Connect - or switch - to the given voice channel by its Id.
    pub fn join(&mut self, channel_id: ChannelId) {
        self.channel_id = Some(channel_id);

        self.send_join();
    }

    /// Leaves the current voice channel, disconnecting from it.
    ///
    /// This does _not_ forget settings, like whether to be self-deafened or
    /// self-muted.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally connected to a
    /// voice channel.
    ///
    /// [`standalone`]: #method.standalone
    pub fn leave(&mut self) {
        // Only send an update if we were in a voice channel.
        if self.channel_id.is_some() {
            self.channel_id = None;

            self.update();
        }
    }

    /// Sets a receiver, i.e. a way to receive audio. Most use cases for bots do
    /// not require this.
    ///
    /// The `receiver` argument can be thought of as an "optional Option". You
    /// can pass in just a boxed receiver, and do not need to specify `Some`.
    ///
    /// Pass `None` to drop the current receiver, if one exists.
    pub fn listen(&mut self, receiver: Option<Box<AudioReceiver>>) {
        self.send(VoiceStatus::SetReceiver(receiver))
    }

    /// Sets whether the current connection is to be muted.
    ///
    /// If there is no live voice connection, then this only acts as a settings
    /// update for future connections.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally muted.
    ///
    /// [`standalone`]: #method.standalone
    pub fn mute(&mut self, mute: bool) {
        self.self_mute = mute;

        if self.channel_id.is_some() {
            self.update();
        }
    }

    /// Plays audio from a source.
    ///
    /// This can be a source created via [`voice::ffmpeg`] or [`voice::ytdl`].
    ///
    /// [`voice::ffmpeg`]: fn.ffmpeg.html
    /// [`voice::ytdl`]: fn.ytdl.html
    pub fn play(&mut self, source: Box<AudioSource>) {
        self.play_returning(source);
    }

    /// Plays audio from a source, returning the locked audio source.
    pub fn play_returning(&mut self, source: Box<AudioSource>) -> LockedAudio {
        let player = Arc::new(Mutex::new(Audio::new(source)));
        self.send(VoiceStatus::AddSender(player.clone()));

        player
    }

    /// Plays audio from a source.
    ///
    /// Unlike [`play`] or [`play_returning`], this stops all other sources attached
    /// to the channel.
    ///
    /// [`play`]: #method.play
    /// [`play_returning`]: #method.play_returning
    pub fn play_only(&mut self, source: Box<AudioSource>) -> LockedAudio {
        let player = Arc::new(Mutex::new(Audio::new(source)));
        self.send(VoiceStatus::SetSender(Some(player.clone())));

        player
    }

    /// Stops playing audio from a source, if one is set.
    pub fn stop(&mut self) { self.send(VoiceStatus::SetSender(None)) }

    /// Switches the current connected voice channel to the given `channel_id`.
    ///
    /// This has 3 separate behaviors:
    ///
    /// - if the given `channel_id` is equivalent to the current connected
    ///   `channel_id`, then do nothing;
    /// - if the given `channel_id` is _not_ equivalent to the current connected
    ///   `channel_id`, then switch to the given `channel_id`;
    /// - if not currently connected to a voice channel, connect to the given
    ///   one.
    ///
    /// If you are dealing with switching from one group to another, then open
    /// another handler, and optionally drop this one via [`Manager::remove`].
    ///
    /// **Note**: The given `channel_id`, if in a guild, _must_ be in the
    /// current handler's associated guild.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally switched to a
    /// different channel.
    ///
    /// [`Manager::remove`]: struct.Manager.html#method.remove
    /// [`standalone`]: #method.standalone
    pub fn switch_to(&mut self, channel_id: ChannelId) {
        match self.channel_id {
            Some(current_id) if current_id == channel_id => {
                // If already connected to the given channel, do nothing.
                return;
            },
            _ => {
                self.channel_id = Some(channel_id);

                self.update();
            },
        }
    }

    /// Updates the voice server data.
    ///
    /// You should only need to use this if you initialized the `Handler` via
    /// [`standalone`].
    ///
    /// Refer to the documentation for [`connect`] for when this will
    /// automatically connect to a voice channel.
    ///
    /// [`connect`]: #method.connect
    /// [`standalone`]: #method.standalone
    pub fn update_server(&mut self, endpoint: &Option<String>, token: &str) {
        self.token = Some(token.to_string());

        if let Some(endpoint) = endpoint.clone() {
            self.endpoint = Some(endpoint);

            if self.session_id.is_some() {
                self.connect();
            }
        } else {
            self.leave();
        }
    }

    /// Updates the internal voice state of the current user.
    ///
    /// You should only need to use this if you initialized the `Handler` via
    /// [`standalone`].
    ///
    /// refer to the documentation for [`connect`] for when this will
    /// automatically connect to a voice channel.
    ///
    /// [`connect`]: #method.connect
    /// [`standalone`]: #method.standalone
    pub fn update_state(&mut self, voice_state: &VoiceState) {
        if self.user_id != voice_state.user_id.0 {
            return;
        }

        self.channel_id = voice_state.channel_id;

        if voice_state.channel_id.is_some() {
            self.session_id = Some(voice_state.session_id.clone());

            if self.endpoint.is_some() && self.token.is_some() {
                self.connect();
            }
        } else {
            self.leave();
        }
    }

    fn new_raw(
        guild_id: GuildId,
        ws: Option<MpscSender<InterMessage>>,
        user_id: UserId,
    ) -> Self {
        let (tx, rx) = mpsc::channel();

        threading::start(guild_id, rx);

        Handler {
            channel_id: None,
            endpoint: None,
            guild_id,
            self_deaf: false,
            self_mute: false,
            sender: tx,
            session_id: None,
            token: None,
            user_id,
            ws,
        }
    }

    /// Sends a message to the thread.
    fn send(&mut self, status: VoiceStatus) {
        // Restart thread if it errored.
        if let Err(mpsc::SendError(status)) = self.sender.send(status) {
            let (tx, rx) = mpsc::channel();

            self.sender = tx;
            self.sender.send(status).unwrap();

            threading::start(self.guild_id, rx);

            self.update();
        }
    }

    fn send_join(&self) {
        // Do _not_ try connecting if there is not at least a channel. There
        // does not _necessarily_ need to be a guild.
        if self.channel_id.is_none() {
            return;
        }

        self.update();
    }

    /// Send an update for the current session over WS.
    ///
    /// Does nothing if initialized via [`standalone`].
    ///
    /// [`standalone`]: #method.standalone
    fn update(&self) {
        if let Some(ref ws) = self.ws {
            let map = json!({
                "op": VoiceOpCode::SessionDescription.num(),
                "d": {
                    "channel_id": self.channel_id.map(|c| c.0),
                    "guild_id": self.guild_id.0,
                    "self_deaf": self.self_deaf,
                    "self_mute": self.self_mute,
                }
            });

            let _ = ws.send(InterMessage::Json(map));
        }
    }
}

impl Drop for Handler {
    /// Leaves the current connected voice channel, if connected to one, and
    /// forgets all configurations relevant to this Handler.
    fn drop(&mut self) { self.leave(); }
}
<commit_msg>Fix connection error being thrown on leaving voice (#471)<commit_after>use constants::VoiceOpCode;
use gateway::InterMessage;
use model::{
    id::{
        ChannelId,
        GuildId,
        UserId
    },
    voice::VoiceState
};
use parking_lot::Mutex;
use std::sync::{
    mpsc::{self, Sender as MpscSender},
    Arc
};
use super::connection_info::ConnectionInfo;
use super::{Audio, AudioReceiver, AudioSource, Status as VoiceStatus, threading, LockedAudio};

/// The handler is responsible for "handling" a single voice connection, acting
/// as a clean API above the inner connection.
///
/// Look into the [`Manager`] for a slightly higher-level interface for managing
/// the existence of handlers.
///
/// **Note**: You should _not_ manually mutate any struct fields. You should
/// _only_ read them. Use methods to mutate them.
///
/// # Examples
///
/// Assuming that you already have a `Manager`, most likely retrieved via a
/// [`Shard`], you can join a guild's voice channel and deafen yourself like so:
///
/// ```rust,ignore
/// // assuming a `manager` has already been bound, hopefully retrieved through
/// // a websocket's connection.
/// use serenity::model::{ChannelId, GuildId};
///
/// let guild_id = GuildId(81384788765712384);
/// let channel_id = ChannelId(85482585546833920);
///
/// let handler = manager.join(Some(guild_id), channel_id);
/// handler.deafen(true);
/// ```
///
/// [`Manager`]: struct.Manager.html
/// [`Shard`]: ../gateway/struct.Shard.html
#[derive(Clone, Debug)]
pub struct Handler {
    /// The ChannelId to be connected to, if any.
    ///
    /// **Note**: This _must not_ be manually mutated. Call [`switch_to`] to
    /// mutate this value.
    ///
    /// [`Group`]: ../../model/channel/struct.Group.html
    /// [`guild`]: #structfield.guild
    /// [`switch_to`]: #method.switch_to
    pub channel_id: Option<ChannelId>,
    /// The voice server endpoint.
    pub endpoint: Option<String>,
    /// The Id of the guild to be connected to.
    pub guild_id: GuildId,
    /// Whether the current handler is set to deafen voice connections.
    ///
    /// **Note**: This _must not_ be manually mutated. Call [`deafen`] to
    /// mutate this value.
    ///
    /// [`deafen`]: #method.deafen
    pub self_deaf: bool,
    /// Whether the current handler is set to mute voice connections.
    ///
    /// **Note**: This _must not_ be manually mutated. Call [`mute`] to mutate
    /// this value.
    ///
    /// [`mute`]: #method.mute
    pub self_mute: bool,
    /// The internal sender to the voice connection monitor thread.
    sender: MpscSender<VoiceStatus>,
    /// The session Id of the current voice connection, if any.
    ///
    /// **Note**: This _should_ be set through an [`update_state`] call.
    ///
    /// [`update_state`]: #method.update_state
    pub session_id: Option<String>,
    /// The token of the current voice connection, if any.
    ///
    /// **Note**: This _should_ be set through an [`update_server`] call.
    ///
    /// [`update_server`]: #method.update_server
    pub token: Option<String>,
    /// The Id of the current user.
    ///
    /// This is configured via [`new`] or [`standalone`].
    ///
    /// [`new`]: #method.new
    /// [`standalone`]: #method.standalone
    pub user_id: UserId,
    /// Will be set when a `Handler` is made via the [`new`][`Handler::new`]
    /// method.
    ///
    /// When set via [`standalone`][`Handler::standalone`], it will not be
    /// present.
    ws: Option<MpscSender<InterMessage>>,
}

impl Handler {
    /// Creates a new Handler.
    #[inline]
    pub(crate) fn new(
        guild_id: GuildId,
        ws: MpscSender<InterMessage>,
        user_id: UserId,
    ) -> Self {
        Self::new_raw(guild_id, Some(ws), user_id)
    }

    /// Creates a new, standalone Handler which is not connected to the primary
    /// WebSocket to the Gateway.
    ///
    /// Actions such as muting, deafening, and switching channels will not
    /// function through this Handler and must be done through some other
    /// method, as the values will only be internally updated.
    ///
    /// For most use cases you do not want this. Only use it if you are using
    /// the voice component standalone from the rest of the library.
    #[inline]
    pub fn standalone(guild_id: GuildId, user_id: UserId) -> Self {
        Self::new_raw(guild_id, None, user_id)
    }

    /// Connects to the voice channel if the following are present:
    ///
    /// - [`endpoint`]
    /// - [`session_id`]
    /// - [`token`]
    ///
    /// If they _are_ all present, then `true` is returned. Otherwise, `false`
    /// is.
    ///
    /// This will automatically be called by [`update_server`] or
    /// [`update_state`] when all three values become present.
    ///
    /// [`endpoint`]: #structfield.endpoint
    /// [`session_id`]: #structfield.session_id
    /// [`token`]: #structfield.token
    /// [`update_server`]: #method.update_server
    /// [`update_state`]: #method.update_state
    pub fn connect(&mut self) -> bool {
        if self.endpoint.is_none() || self.session_id.is_none() || self.token.is_none() {
            return false;
        }

        let endpoint = self.endpoint.clone().unwrap();
        let guild_id = self.guild_id;
        let session_id = self.session_id.clone().unwrap();
        let token = self.token.clone().unwrap();
        let user_id = self.user_id;

        // Safe as all of these being present was already checked.
        self.send(VoiceStatus::Connect(ConnectionInfo {
            endpoint,
            guild_id,
            session_id,
            token,
            user_id,
        }));

        true
    }

    /// Sets whether the current connection to be deafened.
    ///
    /// If there is no live voice connection, then this only acts as a settings
    /// update for future connections.
    ///
    /// **Note**: Unlike in the official client, you _can_ be deafened while
    /// not being muted.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally deafened.
    ///
    /// [`standalone`]: #method.standalone
    pub fn deafen(&mut self, deaf: bool) {
        self.self_deaf = deaf;

        // Only send an update if there is currently a connected channel.
        //
        // Otherwise, this can be treated as a "settings" update for a
        // connection.
        if self.channel_id.is_some() {
            self.update();
        }
    }

    /// Connect - or switch - to the given voice channel by its Id.
    pub fn join(&mut self, channel_id: ChannelId) {
        self.channel_id = Some(channel_id);

        self.send_join();
    }

    /// Leaves the current voice channel, disconnecting from it.
    ///
    /// This does _not_ forget settings, like whether to be self-deafened or
    /// self-muted.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally connected to a
    /// voice channel.
    ///
    /// [`standalone`]: #method.standalone
    pub fn leave(&mut self) {
        // Only send an update if we were in a voice channel.
        if self.channel_id.is_some() {
            self.channel_id = None;
            self.send(VoiceStatus::Disconnect);

            self.update();
        }
    }

    /// Sets a receiver, i.e. a way to receive audio. Most use cases for bots do
    /// not require this.
    ///
    /// The `receiver` argument can be thought of as an "optional Option". You
    /// can pass in just a boxed receiver, and do not need to specify `Some`.
    ///
    /// Pass `None` to drop the current receiver, if one exists.
    pub fn listen(&mut self, receiver: Option<Box<AudioReceiver>>) {
        self.send(VoiceStatus::SetReceiver(receiver))
    }

    /// Sets whether the current connection is to be muted.
    ///
    /// If there is no live voice connection, then this only acts as a settings
    /// update for future connections.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally muted.
    ///
    /// [`standalone`]: #method.standalone
    pub fn mute(&mut self, mute: bool) {
        self.self_mute = mute;

        if self.channel_id.is_some() {
            self.update();
        }
    }

    /// Plays audio from a source.
    ///
    /// This can be a source created via [`voice::ffmpeg`] or [`voice::ytdl`].
    ///
    /// [`voice::ffmpeg`]: fn.ffmpeg.html
    /// [`voice::ytdl`]: fn.ytdl.html
    pub fn play(&mut self, source: Box<AudioSource>) {
        self.play_returning(source);
    }

    /// Plays audio from a source, returning the locked audio source.
    pub fn play_returning(&mut self, source: Box<AudioSource>) -> LockedAudio {
        let player = Arc::new(Mutex::new(Audio::new(source)));
        self.send(VoiceStatus::AddSender(player.clone()));

        player
    }

    /// Plays audio from a source.
    ///
    /// Unlike [`play`] or [`play_returning`], this stops all other sources attached
    /// to the channel.
    ///
    /// [`play`]: #method.play
    /// [`play_returning`]: #method.play_returning
    pub fn play_only(&mut self, source: Box<AudioSource>) -> LockedAudio {
        let player = Arc::new(Mutex::new(Audio::new(source)));
        self.send(VoiceStatus::SetSender(Some(player.clone())));

        player
    }

    /// Stops playing audio from a source, if one is set.
    pub fn stop(&mut self) { self.send(VoiceStatus::SetSender(None)) }

    /// Switches the current connected voice channel to the given `channel_id`.
    ///
    /// This has 3 separate behaviors:
    ///
    /// - if the given `channel_id` is equivalent to the current connected
    ///   `channel_id`, then do nothing;
    /// - if the given `channel_id` is _not_ equivalent to the current connected
    ///   `channel_id`, then switch to the given `channel_id`;
    /// - if not currently connected to a voice channel, connect to the given
    ///   one.
    ///
    /// If you are dealing with switching from one group to another, then open
    /// another handler, and optionally drop this one via [`Manager::remove`].
    ///
    /// **Note**: The given `channel_id`, if in a guild, _must_ be in the
    /// current handler's associated guild.
    ///
    /// **Note**: If the `Handler` was created via [`standalone`], then this
    /// will _only_ update whether the connection is internally switched to a
    /// different channel.
    ///
    /// [`Manager::remove`]: struct.Manager.html#method.remove
    /// [`standalone`]: #method.standalone
    pub fn switch_to(&mut self, channel_id: ChannelId) {
        match self.channel_id {
            Some(current_id) if current_id == channel_id => {
                // If already connected to the given channel, do nothing.
                return;
            },
            _ => {
                self.channel_id = Some(channel_id);

                self.update();
            },
        }
    }

    /// Updates the voice server data.
    ///
    /// You should only need to use this if you initialized the `Handler` via
    /// [`standalone`].
    ///
    /// Refer to the documentation for [`connect`] for when this will
    /// automatically connect to a voice channel.
    ///
    /// [`connect`]: #method.connect
    /// [`standalone`]: #method.standalone
    pub fn update_server(&mut self, endpoint: &Option<String>, token: &str) {
        self.token = Some(token.to_string());

        if let Some(endpoint) = endpoint.clone() {
            self.endpoint = Some(endpoint);

            if self.session_id.is_some() {
                self.connect();
            }
        } else {
            self.leave();
        }
    }

    /// Updates the internal voice state of the current user.
    ///
    /// You should only need to use this if you initialized the `Handler` via
    /// [`standalone`].
    ///
    /// refer to the documentation for [`connect`] for when this will
    /// automatically connect to a voice channel.
    ///
    /// [`connect`]: #method.connect
    /// [`standalone`]: #method.standalone
    pub fn update_state(&mut self, voice_state: &VoiceState) {
        if self.user_id != voice_state.user_id.0 {
            return;
        }

        self.channel_id = voice_state.channel_id;

        if voice_state.channel_id.is_some() {
            self.session_id = Some(voice_state.session_id.clone());

            if self.endpoint.is_some() && self.token.is_some() {
                self.connect();
            }
        } else {
            self.leave();
        }
    }

    fn new_raw(
        guild_id: GuildId,
        ws: Option<MpscSender<InterMessage>>,
        user_id: UserId,
    ) -> Self {
        let (tx, rx) = mpsc::channel();

        threading::start(guild_id, rx);

        Handler {
            channel_id: None,
            endpoint: None,
            guild_id,
            self_deaf: false,
            self_mute: false,
            sender: tx,
            session_id: None,
            token: None,
            user_id,
            ws,
        }
    }

    /// Sends a message to the thread.
    fn send(&mut self, status: VoiceStatus) {
        // Restart thread if it errored.
        if let Err(mpsc::SendError(status)) = self.sender.send(status) {
            let (tx, rx) = mpsc::channel();

            self.sender = tx;
            self.sender.send(status).unwrap();

            threading::start(self.guild_id, rx);

            self.update();
        }
    }

    fn send_join(&self) {
        // Do _not_ try connecting if there is not at least a channel. There
        // does not _necessarily_ need to be a guild.
        if self.channel_id.is_none() {
            return;
        }

        self.update();
    }

    /// Send an update for the current session over WS.
    ///
    /// Does nothing if initialized via [`standalone`].
    ///
    /// [`standalone`]: #method.standalone
    fn update(&self) {
        if let Some(ref ws) = self.ws {
            let map = json!({
                "op": VoiceOpCode::SessionDescription.num(),
                "d": {
                    "channel_id": self.channel_id.map(|c| c.0),
                    "guild_id": self.guild_id.0,
                    "self_deaf": self.self_deaf,
                    "self_mute": self.self_mute,
                }
            });

            let _ = ws.send(InterMessage::Json(map));
        }
    }
}

impl Drop for Handler {
    /// Leaves the current connected voice channel, if connected to one, and
    /// forgets all configurations relevant to this Handler.
    fn drop(&mut self) { self.leave(); }
}
<|endoftext|>


<commit_before>use core::intrinsics::transmute;
use core::num::Wrapping;
use core::mem::size_of;
use core::slice;

pub unsafe trait VSpaceWindow<'a> {
    fn base(&self) -> usize;
    fn size(&self) -> usize;
    unsafe fn make<T: Sized>(&self, b: usize) -> &'a T {
        unimplemented!()
    }
    unsafe fn make_slice<T: Sized>(&self, b:usize, num: usize) -> &'a [T] {
        if !self.range_valid(b, size_of::<T>() * num) {
            panic!("Cannot make array with {} elements at {}", num, b);
        }
        return slice::from_raw_parts(transmute(b), num);
    }
    /* Passing in a window to describe the window you want to create
     * is a little backwards, but it provides the nicest API as far
     * as I can tell */
    unsafe fn subwindow<'i, I, O: ?Sized>(&self, window: I) -> &'a O where O: VSpaceWindow<'a> + Default, I: VSpaceWindow<'i> {
        /* Validate the range for this window */
        if !self.range_valid(window.base(), window.size()) {
            panic!("Cannot construct window with range {} {}, from {} {}");
        }
        /* transmate to extend the lifetime. This is safe as
         * it is a zero sized object */
        transmute(&O::default())
    }
    fn range_valid(&self, b: usize, s: usize) -> bool {
        /* We have moved the `- s` to the other side of the equation
         * so that if `self.base() + self.size()` overflowed
         * then subtracting `s` will either correct if the range is
         * valid, or not correct in which case the range is invalid
         * and the comparison will fail */
        b >= self.base() && b <= (Wrapping(self.base()) + Wrapping(self.size()) - Wrapping(s)).0
    }
}
<commit_msg>Implement 'make' function vspace window<commit_after>use core::intrinsics::transmute;
use core::num::Wrapping;
use core::mem::size_of;
use core::slice;

pub unsafe trait VSpaceWindow<'a> {
    fn base(&self) -> usize;
    fn size(&self) -> usize;
    unsafe fn make<T: Sized>(&self, b: usize) -> &'a T {
        if !self.range_valid(b, size_of::<T>()) {
            panic!("Cannot make object at {}", b);
        }
        return transmute(b);
    }
    unsafe fn make_slice<T: Sized>(&self, b:usize, num: usize) -> &'a [T] {
        if !self.range_valid(b, size_of::<T>() * num) {
            panic!("Cannot make array with {} elements at {}", num, b);
        }
        return slice::from_raw_parts(transmute(b), num);
    }
    /* Passing in a window to describe the window you want to create
     * is a little backwards, but it provides the nicest API as far
     * as I can tell */
    unsafe fn subwindow<'i, I, O: ?Sized>(&self, window: I) -> &'a O where O: VSpaceWindow<'a> + Default, I: VSpaceWindow<'i> {
        /* Validate the range for this window */
        if !self.range_valid(window.base(), window.size()) {
            panic!("Cannot construct window with range {} {}, from {} {}");
        }
        /* transmate to extend the lifetime. This is safe as
         * it is a zero sized object */
        transmute(&O::default())
    }
    fn range_valid(&self, b: usize, s: usize) -> bool {
        /* We have moved the `- s` to the other side of the equation
         * so that if `self.base() + self.size()` overflowed
         * then subtracting `s` will either correct if the range is
         * valid, or not correct in which case the range is invalid
         * and the comparison will fail */
        b >= self.base() && b <= (Wrapping(self.base()) + Wrapping(self.size()) - Wrapping(s)).0
    }
}
<|endoftext|>


<commit_before>use failure::{Error, ResultExt};
use mal::{self, MAL};
use regex::Regex;
use process;
use serde_json;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::process::ExitStatus;

#[derive(Fail, Debug)]
pub enum SeriesError {
    #[fail(display = "multiple series found")] MultipleSeriesFound,
    #[fail(display = "no episodes found")] NoEpisodesFound,
    #[fail(display = "episode {} not found", _0)] EpisodeNotFound(u32),
    #[fail(display = "season {} information not found", _0)] SeasonInfoNotFound(u32),
}

#[derive(Debug)]
pub struct Series {
    pub name: String,
    pub data: SeriesData,
    pub episodes: HashMap<u32, PathBuf>,
    data_path: PathBuf,
}

impl Series {
    pub const DATA_FILE_NAME: &'static str = ".anitrack";

    pub fn from_path(path: &Path) -> Result<Series, Error> {
        let data_path = PathBuf::from(path).join(Series::DATA_FILE_NAME);
        let data = SeriesData::from_path_or_default(&data_path)?;

        let ep_data = EpisodeData::parse(path)?;

        Ok(Series {
            name: ep_data.series_name,
            data,
            episodes: ep_data.paths,
            data_path,
        })
    }

    pub fn play_episode(&self, ep_num: u32) -> Result<ExitStatus, Error> {
        let path = self.episodes.get(&ep_num)
            .ok_or(SeriesError::EpisodeNotFound(ep_num))?;

        let output = process::open_with_default(path).output()?;
        Ok(output.status)
    }

    pub fn set_season_data(&mut self, season: u32, info: SeasonInfo) {
        self.data.seasons.insert(season, info);
    }

    pub fn get_season_data(&self, season: u32) -> Result<&SeasonInfo, SeriesError> {
        self.data.seasons.get(&season).ok_or(SeriesError::SeasonInfoNotFound(season))
    }

    pub fn has_season_data(&self, season: u32) -> bool {
        self.data.seasons.contains_key(&season)
    }

    pub fn save_data(&self) -> Result<(), Error> {
        self.data.write_to(&self.data_path)
    }
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct SeriesData {
    pub seasons: HashMap<u32, SeasonInfo>,
}

impl SeriesData {
    fn from_path(path: &Path) -> Result<SeriesData, Error> {
        let file = File::open(path)?;
        let data = serde_json::from_reader(file)?;

        Ok(data)
    }

    fn from_path_or_default(path: &Path) -> Result<SeriesData, Error> {
        if path.exists() {
            SeriesData::from_path(path)
        } else {
            Ok(SeriesData::default())
        }
    }

    fn write_to(&self, path: &Path) -> Result<(), Error> {
        let file = File::create(path)?;
        serde_json::to_writer_pretty(file, self)?;

        Ok(())
    }
}

#[derive(Fail, Debug)]
pub enum SeasonInfoError {
    #[fail(display = "no anime with id {} found with name [{}] on MAL", _0, _1)]
    UnknownAnimeID(u32, String),
}

#[derive(Debug, Serialize, Deserialize)]
pub struct SeasonInfo {
    pub series_id: u32,
    pub episodes: u32,
    pub search_title: String,
    pub title_format: Option<String>,
}

impl SeasonInfo {
    pub fn create_basic(id: u32, episodes: u32, search_title: String) -> SeasonInfo {
        SeasonInfo {
            series_id: id,
            episodes,
            search_title,
            title_format: None,
        }
    }

    pub fn request_mal_info(&self, mal: &MAL) -> Result<mal::SeriesInfo, Error> {
        mal.search(&self.search_title)
            .context("MAL search failed")?
            .into_iter()
            .find(|i| i.id == self.series_id)
            .ok_or(SeasonInfoError::UnknownAnimeID(self.series_id, self.search_title.clone()).into())
    }
}

#[derive(Debug)]
pub struct EpisodeData {
    pub series_name: String,
    pub paths: HashMap<u32, PathBuf>,
}

impl EpisodeData {
    pub fn parse(path: &Path) -> Result<EpisodeData, Error> {
        let mut series = None;
        let mut episodes = HashMap::new();

        for entry in std::fs::read_dir(path)? {
            let entry = entry?;
            let path = entry.path();

            let ep_info = match EpisodeInfo::from_path(&path) {
                Some(info) => info,
                None => continue,
            };

            match series {
                Some(ref set_series) if set_series != &ep_info.series => {
                    bail!(SeriesError::MultipleSeriesFound);
                }
                None => series = Some(ep_info.series),
                _ => (),
            }

            episodes.insert(ep_info.number, path);
        }

        let series = series.ok_or(SeriesError::NoEpisodesFound)?;

        Ok(EpisodeData {
            series_name: series,
            paths: episodes,
        })
    }
}

#[derive(Debug)]
struct EpisodeInfo {
    pub series: String,
    pub number: u32,
}

impl EpisodeInfo {
    fn from_path(path: &Path) -> Option<EpisodeInfo> {
        if !path.is_file() {
            return None;
        }

        lazy_static! {
            static ref RE: Regex = Regex::new(r"(?:\[.+?\]\s*)?(?P<series>.+?)\s*-?\s*(?P<episode>\d+)\s*(?:\(|\[|\.)")
                .unwrap();
        }

        let filename = path.file_name()?.to_str().unwrap().replace('_', " ");

        let caps = RE.captures(&filename)?;

        Some(EpisodeInfo {
            series: caps["series"].into(),
            number: caps["episode"].parse().ok()?,
        })
    }
}
<commit_msg>Remove unused title_format field from saved series data Refactor EpisodeData and EpisodeInfo struct<commit_after>use failure::{Error, ResultExt};
use mal::{self, MAL};
use regex::Regex;
use process;
use serde_json;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::process::ExitStatus;

#[derive(Fail, Debug)]
pub enum SeriesError {
    #[fail(display = "multiple series found")] MultipleSeriesFound,
    #[fail(display = "episode {} not found", _0)] EpisodeNotFound(u32),
    #[fail(display = "season {} information not found", _0)] SeasonInfoNotFound(u32),
}

#[derive(Debug)]
pub struct Series {
    pub name: String,
    pub data: SeriesData,
    pub episodes: HashMap<u32, PathBuf>,
    data_path: PathBuf,
}

impl Series {
    pub const DATA_FILE_NAME: &'static str = ".anitrack";

    pub fn from_path(path: &Path) -> Result<Series, Error> {
        let data_path = PathBuf::from(path).join(Series::DATA_FILE_NAME);
        let data = SeriesData::from_path_or_default(&data_path)?;

        let ep_data = EpisodeData::parse(path)?;

        Ok(Series {
            name: ep_data.series_name,
            data,
            episodes: ep_data.paths,
            data_path,
        })
    }

    pub fn play_episode(&self, ep_num: u32) -> Result<ExitStatus, Error> {
        let path = self.episodes.get(&ep_num)
            .ok_or(SeriesError::EpisodeNotFound(ep_num))?;

        let output = process::open_with_default(path).output()?;
        Ok(output.status)
    }

    pub fn set_season_data(&mut self, season: u32, info: SeasonInfo) {
        self.data.seasons.insert(season, info);
    }

    pub fn get_season_data(&self, season: u32) -> Result<&SeasonInfo, SeriesError> {
        self.data.seasons.get(&season).ok_or(SeriesError::SeasonInfoNotFound(season))
    }

    pub fn has_season_data(&self, season: u32) -> bool {
        self.data.seasons.contains_key(&season)
    }

    pub fn save_data(&self) -> Result<(), Error> {
        self.data.write_to(&self.data_path)
    }
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct SeriesData {
    pub seasons: HashMap<u32, SeasonInfo>,
}

impl SeriesData {
    fn from_path(path: &Path) -> Result<SeriesData, Error> {
        let file = File::open(path)?;
        let data = serde_json::from_reader(file)?;

        Ok(data)
    }

    fn from_path_or_default(path: &Path) -> Result<SeriesData, Error> {
        if path.exists() {
            SeriesData::from_path(path)
        } else {
            Ok(SeriesData::default())
        }
    }

    fn write_to(&self, path: &Path) -> Result<(), Error> {
        let file = File::create(path)?;
        serde_json::to_writer_pretty(file, self)?;

        Ok(())
    }
}

#[derive(Fail, Debug)]
pub enum SeasonInfoError {
    #[fail(display = "no anime with id {} found with name [{}] on MAL", _0, _1)]
    UnknownAnimeID(u32, String),
}

#[derive(Debug, Serialize, Deserialize)]
pub struct SeasonInfo {
    pub series_id: u32,
    pub episodes: u32,
    pub search_title: String,
}

impl SeasonInfo {
    pub fn create_basic(id: u32, episodes: u32, search_title: String) -> SeasonInfo {
        SeasonInfo {
            series_id: id,
            episodes,
            search_title,
        }
    }

    pub fn request_mal_info(&self, mal: &MAL) -> Result<mal::SeriesInfo, Error> {
        mal.search(&self.search_title)
            .context("MAL search failed")?
            .into_iter()
            .find(|i| i.id == self.series_id)
            .ok_or(SeasonInfoError::UnknownAnimeID(self.series_id, self.search_title.clone()).into())
    }
}

#[derive(Fail, Debug)]
pub enum EpisodeDataError {
    #[fail(display = "no episodes found")]
    NoEpisodesFound,
}

#[derive(Debug)]
pub struct EpisodeData {
    pub series_name: String,
    pub paths: HashMap<u32, PathBuf>,
}

impl EpisodeData {
    pub fn parse(path: &Path) -> Result<EpisodeData, Error> {
        let mut series = None;
        let mut episodes = HashMap::new();

        for entry in std::fs::read_dir(path)? {
            let path = entry?.path();

            let info = match EpisodeInfo::parse(&path) {
                Some(info) => info,
                None => continue,
            };

            if let Some(ref series) = series {
                if series != &info.series {
                    bail!(SeriesError::MultipleSeriesFound);
                }
            } else {
                series = Some(info.series);
            }

            episodes.insert(info.episode, path);
        }

        let series = series.ok_or(EpisodeDataError::NoEpisodesFound)?;

        Ok(EpisodeData {
            series_name: series,
            paths: episodes,
        })
    }
}

#[derive(Debug)]
struct EpisodeInfo {
    series: String,
    episode: u32,
}

impl EpisodeInfo {
    fn parse(path: &Path) -> Option<EpisodeInfo> {
        if !path.is_file() {
            return None;
        }

        lazy_static! {
            static ref EP_FORMAT: Regex = Regex::new(r"(?:\[.+?\]\s*)?(?P<series>.+?)\s*-?\s*(?P<episode>\d+)\s*(?:\(|\[|\.)")
                .unwrap();
        }

        let filename = path.file_name()?.to_str().unwrap().replace('_', " ");
        let caps = EP_FORMAT.captures(&filename)?;

        let info = EpisodeInfo {
            series: caps["series"].into(),
            episode: caps["episode"].parse().ok()?,
        };

        Some(info)
    }
}<|endoftext|>