<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use std;
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use error::BoolError;
use Error;
use std::ptr;
use gstring::GString;

/// Same as [`get_prgname()`].
///
/// [`get_prgname()`]: fn.get_prgname.html
pub fn get_program_name() -> Option<String> {
    get_prgname()
}

pub fn get_prgname() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_prgname())
    }
}

/// Same as [`set_prgname()`].
///
/// [`set_prgname()`]: fn.set_prgname.html
pub fn set_program_name(name: Option<&str>) {
    set_prgname(name)
}

pub fn set_prgname(name: Option<&str>) {
    unsafe {
        ffi::g_set_prgname(name.to_glib_none().0)
    }
}

pub fn getenv<K: AsRef<OsStr>>(variable_name: K) -> Option<OsString> {
    #[cfg(windows)]
    use ffi::g_getenv_utf8 as g_getenv;
    #[cfg(not(windows))]
    use ffi::g_getenv;

    unsafe {
        from_glib_none(g_getenv(variable_name.as_ref().to_glib_none().0))
    }
}

pub fn setenv<K: AsRef<OsStr>, V: AsRef<OsStr>>(variable_name: K, value: V, overwrite: bool) -> Result<(), BoolError> {
    #[cfg(windows)]
    use ffi::g_setenv_utf8 as g_setenv;
    #[cfg(not(windows))]
    use ffi::g_setenv;

    unsafe {
        glib_result_from_gboolean!(
            g_setenv(
                variable_name.as_ref().to_glib_none().0,
                value.as_ref().to_glib_none().0,
                overwrite.to_glib(),
            ),
            "Failed to set environment variable"
        )
    }
}

pub fn unsetenv<K: AsRef<OsStr>>(variable_name: K) {
    #[cfg(windows)]
    use ffi::g_unsetenv_utf8 as g_unsetenv;
    #[cfg(not(windows))]
    use ffi::g_unsetenv;

    unsafe {
        g_unsetenv(variable_name.as_ref().to_glib_none().0)
    }
}

pub fn environ_getenv<K: AsRef<OsStr>>(envp: &[OsString], variable: K) -> Option<OsString> {
    unsafe {
        from_glib_none(ffi::g_environ_getenv(envp.to_glib_none().0, variable.as_ref().to_glib_none().0))
    }
}

pub fn get_user_name() -> Option<OsString> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_user_name_utf8 as g_get_user_name;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_user_name;

    unsafe {
        from_glib_none(g_get_user_name())
    }
}

pub fn get_real_name() -> Option<OsString> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_real_name_utf8 as g_get_real_name;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_real_name;

    unsafe {
        from_glib_none(g_get_real_name())
    }
}

pub fn get_current_dir() -> Option<PathBuf> {
    #[cfg(windows)]
    use ffi::g_get_current_dir_utf8 as g_get_current_dir;
    #[cfg(not(windows))]
    use ffi::g_get_current_dir;

    unsafe {
        from_glib_full(g_get_current_dir())
    }
}

pub fn filename_to_uri<'a, P: AsRef<Path>, Q: Into<Option<&'a str>>>(filename: P, hostname: Q) -> Result<GString, Error> {
    #[cfg(windows)]
    use ffi::g_filename_to_uri_utf8 as g_filename_to_uri;
    #[cfg(not(windows))]
    use ffi::g_filename_to_uri;

    let hostname = hostname.into();
    let hostname = hostname.to_glib_none();
    unsafe {
        let mut error = std::ptr::null_mut();
        let ret = g_filename_to_uri(filename.as_ref().to_glib_none().0, hostname.0, &mut error);
        if error.is_null() { Ok(from_glib_full(ret)) } else { Err(from_glib_full(error)) }
    }
}

pub fn filename_from_uri(uri: &str) -> Result<(std::path::PathBuf, Option<GString>), Error> {
    #[cfg(windows)]
    use ffi::g_filename_from_uri_utf8 as g_filename_from_uri;
    #[cfg(not(windows))]
    use ffi::g_filename_from_uri;

    unsafe {
        let mut hostname = ptr::null_mut();
        let mut error = ptr::null_mut();
        let ret = g_filename_from_uri(uri.to_glib_none().0, &mut hostname, &mut error);
        if error.is_null() { Ok((from_glib_full(ret), Some(from_glib_full(hostname)))) } else { Err(from_glib_full(error)) }
    }
}

pub fn find_program_in_path<P: AsRef<Path>>(program: P) -> Option<PathBuf> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_find_program_in_path_utf8 as g_find_program_in_path;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_find_program_in_path;

    unsafe {
        from_glib_full(g_find_program_in_path(program.as_ref().to_glib_none().0))
    }
}

pub fn get_home_dir() -> Option<std::path::PathBuf> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_home_dir_utf8 as g_get_home_dir;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_home_dir;

    unsafe {
        from_glib_none(g_get_home_dir())
    }
}

pub fn get_tmp_dir() -> Option<std::path::PathBuf> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_tmp_dir_utf8 as g_get_tmp_dir;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_tmp_dir;

    unsafe {
        from_glib_none(g_get_tmp_dir())
    }
}

pub fn mkstemp<P: AsRef<std::path::Path>>(tmpl: P) -> i32 {
    #[cfg(windows)]
    use ffi::g_mkstemp_utf8 as g_mkstemp;
    #[cfg(not(windows))]
    use ffi::g_mkstemp;

    unsafe {
        g_mkstemp(tmpl.as_ref().to_glib_none().0)
    }
}

#[cfg(test)]
mod tests {
    use std::env;
    use std::sync::Mutex;

    //Mutex to prevent run environment tests parallel
    lazy_static! { static ref LOCK: Mutex<()> = Mutex::new(()); }

    const VAR_NAME: &str = "function_environment_test";

    fn check_getenv(val: &str) {
        let _data = LOCK.lock().unwrap();

        env::set_var(VAR_NAME, val);
        assert_eq!(env::var_os(VAR_NAME), Some(val.into()));
        assert_eq!(::getenv(VAR_NAME), Some(val.into()));

        let environ = ::get_environ();
        assert_eq!(::environ_getenv(&environ, VAR_NAME), Some(val.into()));
    }

    fn check_setenv(val: &str) {
        let _data = LOCK.lock().unwrap();

        ::setenv(VAR_NAME, val, true).unwrap();
        assert_eq!(env::var_os(VAR_NAME), Some(val.into()));
    }

    #[test]
    fn getenv() {
        check_getenv("Test");
        check_getenv("Тест"); // "Test" in Russian
    }

    #[test]
    fn setenv() {
        check_setenv("Test");
        check_setenv("Тест"); // "Test" in Russian
    }
}
<commit_msg>utils: Fix crash in filename_from_uri()<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use std;
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use error::BoolError;
use Error;
use std::ptr;
use gstring::GString;

/// Same as [`get_prgname()`].
///
/// [`get_prgname()`]: fn.get_prgname.html
pub fn get_program_name() -> Option<String> {
    get_prgname()
}

pub fn get_prgname() -> Option<String> {
    unsafe {
        from_glib_none(ffi::g_get_prgname())
    }
}

/// Same as [`set_prgname()`].
///
/// [`set_prgname()`]: fn.set_prgname.html
pub fn set_program_name(name: Option<&str>) {
    set_prgname(name)
}

pub fn set_prgname(name: Option<&str>) {
    unsafe {
        ffi::g_set_prgname(name.to_glib_none().0)
    }
}

pub fn getenv<K: AsRef<OsStr>>(variable_name: K) -> Option<OsString> {
    #[cfg(windows)]
    use ffi::g_getenv_utf8 as g_getenv;
    #[cfg(not(windows))]
    use ffi::g_getenv;

    unsafe {
        from_glib_none(g_getenv(variable_name.as_ref().to_glib_none().0))
    }
}

pub fn setenv<K: AsRef<OsStr>, V: AsRef<OsStr>>(variable_name: K, value: V, overwrite: bool) -> Result<(), BoolError> {
    #[cfg(windows)]
    use ffi::g_setenv_utf8 as g_setenv;
    #[cfg(not(windows))]
    use ffi::g_setenv;

    unsafe {
        glib_result_from_gboolean!(
            g_setenv(
                variable_name.as_ref().to_glib_none().0,
                value.as_ref().to_glib_none().0,
                overwrite.to_glib(),
            ),
            "Failed to set environment variable"
        )
    }
}

pub fn unsetenv<K: AsRef<OsStr>>(variable_name: K) {
    #[cfg(windows)]
    use ffi::g_unsetenv_utf8 as g_unsetenv;
    #[cfg(not(windows))]
    use ffi::g_unsetenv;

    unsafe {
        g_unsetenv(variable_name.as_ref().to_glib_none().0)
    }
}

pub fn environ_getenv<K: AsRef<OsStr>>(envp: &[OsString], variable: K) -> Option<OsString> {
    unsafe {
        from_glib_none(ffi::g_environ_getenv(envp.to_glib_none().0, variable.as_ref().to_glib_none().0))
    }
}

pub fn get_user_name() -> Option<OsString> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_user_name_utf8 as g_get_user_name;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_user_name;

    unsafe {
        from_glib_none(g_get_user_name())
    }
}

pub fn get_real_name() -> Option<OsString> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_real_name_utf8 as g_get_real_name;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_real_name;

    unsafe {
        from_glib_none(g_get_real_name())
    }
}

pub fn get_current_dir() -> Option<PathBuf> {
    #[cfg(windows)]
    use ffi::g_get_current_dir_utf8 as g_get_current_dir;
    #[cfg(not(windows))]
    use ffi::g_get_current_dir;

    unsafe {
        from_glib_full(g_get_current_dir())
    }
}

pub fn filename_to_uri<'a, P: AsRef<Path>, Q: Into<Option<&'a str>>>(filename: P, hostname: Q) -> Result<GString, Error> {
    #[cfg(windows)]
    use ffi::g_filename_to_uri_utf8 as g_filename_to_uri;
    #[cfg(not(windows))]
    use ffi::g_filename_to_uri;

    let hostname = hostname.into();
    let hostname = hostname.to_glib_none();
    unsafe {
        let mut error = std::ptr::null_mut();
        let ret = g_filename_to_uri(filename.as_ref().to_glib_none().0, hostname.0, &mut error);
        if error.is_null() { Ok(from_glib_full(ret)) } else { Err(from_glib_full(error)) }
    }
}

pub fn filename_from_uri(uri: &str) -> Result<(std::path::PathBuf, Option<GString>), Error> {
    #[cfg(windows)]
    use ffi::g_filename_from_uri_utf8 as g_filename_from_uri;
    #[cfg(not(windows))]
    use ffi::g_filename_from_uri;

    unsafe {
        let mut hostname = ptr::null_mut();
        let mut error = ptr::null_mut();
        let ret = g_filename_from_uri(uri.to_glib_none().0, &mut hostname, &mut error);
        if error.is_null() { Ok((from_glib_full(ret), from_glib_full(hostname))) } else { Err(from_glib_full(error)) }
    }
}

pub fn find_program_in_path<P: AsRef<Path>>(program: P) -> Option<PathBuf> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_find_program_in_path_utf8 as g_find_program_in_path;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_find_program_in_path;

    unsafe {
        from_glib_full(g_find_program_in_path(program.as_ref().to_glib_none().0))
    }
}

pub fn get_home_dir() -> Option<std::path::PathBuf> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_home_dir_utf8 as g_get_home_dir;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_home_dir;

    unsafe {
        from_glib_none(g_get_home_dir())
    }
}

pub fn get_tmp_dir() -> Option<std::path::PathBuf> {
    #[cfg(all(windows,target_arch="x86"))]
    use ffi::g_get_tmp_dir_utf8 as g_get_tmp_dir;
    #[cfg(not(all(windows,target_arch="x86")))]
    use ffi::g_get_tmp_dir;

    unsafe {
        from_glib_none(g_get_tmp_dir())
    }
}

pub fn mkstemp<P: AsRef<std::path::Path>>(tmpl: P) -> i32 {
    #[cfg(windows)]
    use ffi::g_mkstemp_utf8 as g_mkstemp;
    #[cfg(not(windows))]
    use ffi::g_mkstemp;

    unsafe {
        g_mkstemp(tmpl.as_ref().to_glib_none().0)
    }
}

#[cfg(test)]
mod tests {
    use std::env;
    use std::sync::Mutex;

    //Mutex to prevent run environment tests parallel
    lazy_static! { static ref LOCK: Mutex<()> = Mutex::new(()); }

    const VAR_NAME: &str = "function_environment_test";

    fn check_getenv(val: &str) {
        let _data = LOCK.lock().unwrap();

        env::set_var(VAR_NAME, val);
        assert_eq!(env::var_os(VAR_NAME), Some(val.into()));
        assert_eq!(::getenv(VAR_NAME), Some(val.into()));

        let environ = ::get_environ();
        assert_eq!(::environ_getenv(&environ, VAR_NAME), Some(val.into()));
    }

    fn check_setenv(val: &str) {
        let _data = LOCK.lock().unwrap();

        ::setenv(VAR_NAME, val, true).unwrap();
        assert_eq!(env::var_os(VAR_NAME), Some(val.into()));
    }

    #[test]
    fn getenv() {
        check_getenv("Test");
        check_getenv("Тест"); // "Test" in Russian
    }

    #[test]
    fn setenv() {
        check_setenv("Test");
        check_setenv("Тест"); // "Test" in Russian
    }

    #[test]
    fn test_filename_from_uri() {
        use gstring::GString;
        use std::path::PathBuf;
        let uri: GString = "file:///foo/bar.txt".into();
        if let Ok((filename, hostname)) = ::filename_from_uri(&uri) {
            assert_eq!(filename, PathBuf::from(r"/foo/bar.txt"));
            assert_eq!(hostname, None);
        } else {
            unreachable!();
        }

        let uri: GString = "file://host/foo/bar.txt".into();
        if let Ok((filename, hostname)) = ::filename_from_uri(&uri) {
            assert_eq!(filename, PathBuf::from(r"/foo/bar.txt"));
            assert_eq!(hostname, Some(GString::from("host")));
        } else {
            unreachable!();
        }

    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::collections::HashMap;
use std::hash::Hash;
use std;
use log;
use std::process::Command;
use std::env;
use errors::{Result, ChainErr};

#[cfg(all(windows, target_env = "msvc"))]
pub fn is_msvc() -> bool {
  true
}

#[cfg(not(all(windows, target_env = "msvc")))]
pub fn is_msvc() -> bool {
  false
}

pub fn add_to_multihash<K: Eq + Hash + Clone, T, V: Default + Extend<T>>(hash: &mut HashMap<K, V>,
                                                                         key: K,
                                                                         value: T) {
  use std::collections::hash_map::Entry;
  match hash.entry(key) {
    Entry::Occupied(mut entry) => entry.get_mut().extend(std::iter::once(value)),
    Entry::Vacant(entry) => {
      let mut r = V::default();
      r.extend(std::iter::once(value));
      entry.insert(r);
    }
  }
}

/// Runs a command, checks that it is successful, and
/// returns its output if requested
pub fn run_command(command: &mut Command, fetch_stdout: bool, pipe_output: bool) -> Result<String> {
  if pipe_output {
    command.stdout(std::process::Stdio::piped());
    command.stderr(std::process::Stdio::piped());
  }
  log::info(format!("Executing command: {:?}", command));

  let status = try!(command.status()
    .chain_err(|| format!("command execution failed: {:?}", command)));
  if status.success() {
    Ok(if fetch_stdout {
      let output = try!(command.output()
        .chain_err(|| format!("command execution failed: {:?}", command)));
      try!(String::from_utf8(output.stdout).chain_err(|| "comand output is not valid unicode"))
    } else {
      String::new()
    })
  } else {
    if pipe_output {
      use std::io::Write;
      let output = try!(command.output()
        .chain_err(|| format!("command execution failed: {:?}", command)));
      log::error("Stdout:");
      try!(std::io::stderr().write_all(&output.stdout).chain_err(|| "output failed"));
      log::error("Stderr:");
      try!(std::io::stderr().write_all(&output.stderr).chain_err(|| "output failed"));
    }
    Err(format!("command failed with status {:?}: {:?}", status, command).into())
  }
}

#[cfg_attr(feature="clippy", allow(or_fun_call))]
pub fn add_env_path_item(env_var_name: &'static str,
                         mut new_paths: Vec<PathBuf>)
                         -> Result<std::ffi::OsString> {
  for path in env::split_paths(&env::var(env_var_name).unwrap_or(String::new())) {
    if new_paths.iter().find(|&x| x == &path).is_none() {
      new_paths.push(path);
    }
  }
  env::join_paths(new_paths).chain_err(|| "env::join_paths failed")
}

pub fn manifest_dir() -> PathBuf {
  PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}

pub trait MapIfOk<A> {
  fn map_if_ok<B, E, F: Fn(A) -> std::result::Result<B, E>>(self,
                                                            f: F)
                                                            -> std::result::Result<Vec<B>, E>;
}

impl<A, T: Iterator<Item = A>> MapIfOk<A> for T {
  fn map_if_ok<B, E, F: Fn(A) -> std::result::Result<B, E>>(self,
                                                            f: F)
                                                            -> std::result::Result<Vec<B>, E> {
    let mut r = Vec::new();
    r.reserve(self.size_hint().0);
    for item in self {
      r.push(try!(f(item)));
    }
    Ok(r)
  }
}
<commit_msg>run_command freeze fixed<commit_after>use std::path::PathBuf;
use std::collections::HashMap;
use std::hash::Hash;
use std;
use log;
use std::process::Command;
use std::env;
use errors::{Result, ChainErr};

#[cfg(all(windows, target_env = "msvc"))]
pub fn is_msvc() -> bool {
  true
}

#[cfg(not(all(windows, target_env = "msvc")))]
pub fn is_msvc() -> bool {
  false
}

pub fn add_to_multihash<K: Eq + Hash + Clone, T, V: Default + Extend<T>>(hash: &mut HashMap<K, V>,
                                                                         key: K,
                                                                         value: T) {
  use std::collections::hash_map::Entry;
  match hash.entry(key) {
    Entry::Occupied(mut entry) => entry.get_mut().extend(std::iter::once(value)),
    Entry::Vacant(entry) => {
      let mut r = V::default();
      r.extend(std::iter::once(value));
      entry.insert(r);
    }
  }
}

/// Runs a command, checks that it is successful, and
/// returns its output if requested
pub fn run_command(command: &mut Command, fetch_stdout: bool, pipe_output: bool) -> Result<String> {
  if pipe_output {
    command.stdout(std::process::Stdio::piped());
    command.stderr(std::process::Stdio::piped());
  }
  log::info(format!("Executing command: {:?}", command));

  // command.output() must be called before command.status()
  // to avoid freezes on Windows
  let output = if pipe_output || fetch_stdout {
    Some(try!(command.output().chain_err(|| format!("command execution failed: {:?}", command))))
  } else {
    None
  };

  let status = try!(command.status()
    .chain_err(|| format!("command execution failed: {:?}", command)));
  if status.success() {
    Ok(if let Some(output) = output {
      if fetch_stdout {
        try!(String::from_utf8(output.stdout).chain_err(|| "comand output is not valid unicode"))
      } else {
        String::new()
      }
    } else {
      String::new()
    })
  } else {
    if let Some(output) = output {
      use std::io::Write;
      log::error("Stdout:");
      try!(std::io::stderr().write_all(&output.stdout).chain_err(|| "output failed"));
      log::error("Stderr:");
      try!(std::io::stderr().write_all(&output.stderr).chain_err(|| "output failed"));
    }
    Err(format!("command failed with status {:?}: {:?}", status, command).into())
  }
}

#[cfg_attr(feature="clippy", allow(or_fun_call))]
pub fn add_env_path_item(env_var_name: &'static str,
                         mut new_paths: Vec<PathBuf>)
                         -> Result<std::ffi::OsString> {
  for path in env::split_paths(&env::var(env_var_name).unwrap_or(String::new())) {
    if new_paths.iter().find(|&x| x == &path).is_none() {
      new_paths.push(path);
    }
  }
  env::join_paths(new_paths).chain_err(|| "env::join_paths failed")
}

pub fn manifest_dir() -> PathBuf {
  PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}

pub trait MapIfOk<A> {
  fn map_if_ok<B, E, F: Fn(A) -> std::result::Result<B, E>>(self,
                                                            f: F)
                                                            -> std::result::Result<Vec<B>, E>;
}

impl<A, T: Iterator<Item = A>> MapIfOk<A> for T {
  fn map_if_ok<B, E, F: Fn(A) -> std::result::Result<B, E>>(self,
                                                            f: F)
                                                            -> std::result::Result<Vec<B>, E> {
    let mut r = Vec::new();
    r.reserve(self.size_hint().0);
    for item in self {
      r.push(try!(f(item)));
    }
    Ok(r)
  }
}
<|endoftext|>


<commit_before>use std::{mem};

use num::{BigInt, One};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                }
                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        // TODO: allocating the bytes to get the sign is silly.
        let (sign, _) = self.to_bytes_be();
        match sign {
            Sign::Plus => {
                let (_, mut bytes) = self.to_bytes_be();
                if bytes[0] & 0x80 != 0 {
                    // If the data has a leading 0x80, pad with a zero-byte.
                    bytes.insert(0, 0);
                }
                return bytes;
            },
            Sign::NoSign => {
                return b"\x00".to_vec();
            },
            Sign::Minus => {
                // Convert negative numbers to two's-complement by subtracting one and inverting.
                let n_minus_1 = -self - BigInt::one();
                let (_, mut bytes) = n_minus_1.to_bytes_be();
                // TODO: rewrite this in-place.
                bytes = bytes.iter().map(|b| b ^ 0xff).collect();
                if bytes[0] & 0x80 == 0 {
                    bytes.insert(0, 0xff);
                }
                return bytes;
            },
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

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

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }
}
<commit_msg>rewrite in place<commit_after>use std::{mem};

use num::{BigInt, One};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                }
                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        // TODO: allocating the bytes to get the sign is silly.
        let (sign, _) = self.to_bytes_be();
        match sign {
            Sign::Plus => {
                let (_, mut bytes) = self.to_bytes_be();
                if bytes[0] & 0x80 != 0 {
                    // If the data has a leading 0x80, pad with a zero-byte.
                    bytes.insert(0, 0);
                }
                return bytes;
            },
            Sign::NoSign => {
                return b"\x00".to_vec();
            },
            Sign::Minus => {
                // Convert negative numbers to two's-complement by subtracting one and inverting.
                let n_minus_1 = -self - BigInt::one();
                let (_, mut bytes) = n_minus_1.to_bytes_be();

                for i in 0..bytes.len() {
                    bytes[i] ^= 0xff;
                }

                if bytes[0] & 0x80 == 0 {
                    bytes.insert(0, 0xff);
                }
                return bytes;
            },
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

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

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }
}
<|endoftext|>


<commit_before>//! Things we have not found a home for.

use std::sync::Arc;
use std::time::{SystemTime, Duration};
use basetypes::*;
use moves::*;
use tt::*;
use position::*;
use search::*;

/// A sequence of moves from some starting position, together with the
/// value assigned to the final position.
pub struct Variation {
    /// A sequence of moves from some starting position.
    pub moves: Vec<Move>,

    /// The value assigned to the final position.
    pub value: Value,

    /// The accuracy of the assigned value.
    pub bound: BoundType,
}

/// Contains information about the current progress of a search.
pub struct SearchStatus {
    /// The starting time for the search.
    pub started_at: SystemTime,

    /// The starting (root) position for the search.
    pub position: Position,

    /// `true` if the search has stopped, `false` otherwise.
    pub done: bool,

    /// The reached search depth.
    pub depth: u8,

    /// The number of legal moves in the starting (root) position.
    pub legal_moves_count: usize,

    /// The best variations found so far. The first move in each
    /// variation will be different.
    pub variations: Vec<Variation>,

    /// The duration of the search in milliseconds.
    pub duration_millis: u64,

    /// The number of analyzed nodes.
    pub searched_nodes: NodeCount,

    /// Average number of analyzed nodes per second.
    pub nps: NodeCount,
}

/// A thread that executes consecutive searches in different starting
/// positions.
pub struct SearchThread {
    tt: Arc<Tt>,
    status: SearchStatus,
    searcher: DeepeningSearcher<MultipvSearcher<AlphabetaSearcher>>,
}

impl SearchThread {
    /// Creates a new instance.
    pub fn new(tt: Arc<Tt>) -> SearchThread {
        SearchThread {
            tt: tt.clone(),
            status: SearchStatus {
                started_at: SystemTime::now(),
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                done: true,
                depth: 0,
                variations: vec![Variation {
                                     value: VALUE_MIN,
                                     bound: BOUND_LOWER,
                                     moves: vec![],
                                 }],
                legal_moves_count: 20,
                searched_nodes: 0,
                duration_millis: 0,
                nps: 0,
            },
            searcher: DeepeningSearcher::new(tt),
        }
    }

    /// Stops the current search, starts a new search, updates the
    /// status.
    ///
    /// `position` is the starting position for the new
    /// search. `variation_count` specifies how many best lines of
    /// play to calculate (the first move in each line will be
    /// different). `searchmoves` restricts the analysis to the
    /// supplied list of moves only (no restrictions if the suppied
    /// list is empty). The move format is long algebraic
    /// notation. Examples: e2e4, e7e5, e1g1 (white short castling),
    /// e7e8q (for promotion).
    #[allow(unused_variables)]
    pub fn search(&mut self,
                  position: &Position,
                  variation_count: usize,
                  mut searchmoves: Vec<String>) {
        let mut legal_moves = position.legal_moves();
        let legal_moves_count = legal_moves.len();

        // Remove all legal moves not allowed by `searchmoves`.
        if !searchmoves.is_empty() {
            searchmoves.sort();
            let mut moves = vec![];
            for m in legal_moves.iter() {
                if searchmoves.binary_search(&m.notation()).is_ok() {
                    moves.push(*m);
                }
            }
            if !moves.is_empty() {
                legal_moves = moves;
            }
        };

        self.stop();
        self.searcher.start_search(SearchParams {
            search_id: 0,
            position: position.clone(),
            depth: MAX_DEPTH,
            lower_bound: VALUE_MIN,
            upper_bound: VALUE_MAX,
            searchmoves: legal_moves,
            variation_count: variation_count,
        });

        self.status = SearchStatus {
            started_at: SystemTime::now(),
            position: position.clone(),
            done: false,
            depth: 0,
            legal_moves_count: legal_moves_count,
            variations: vec![Variation {
                                 value: VALUE_MIN,
                                 bound: BOUND_LOWER,
                                 moves: vec![],
                             }], // TODO: Set good initial value (vec![best_move]).
            searched_nodes: 0,
            duration_millis: 0,
            ..self.status
        };
    }

    /// Stops the current search, updates the status.
    ///
    /// Does nothing if the current search is already stopped.
    pub fn stop(&mut self) {
        self.searcher.terminate_search();
        while !self.status().done {
            self.wait_status_update(Duration::from_millis(1000));
        }
    }

    /// Returns the status of the current search.
    ///
    /// **Important note:** Consecutive calls to this method will
    /// return the same unchanged result. Only after calling `search`,
    /// `stop`, or `wait_status_update`, the result returned by
    /// `status` may change.
    #[inline(always)]
    pub fn status(&self) -> &SearchStatus {
        &self.status
    }

    /// Waits for a search status update, timing out after a specified
    /// duration or earlier.
    pub fn wait_status_update(&mut self, duration: Duration) {
        self.searcher.wait_report(duration);
        while let Ok(r) = self.searcher.try_recv_report() {
            self.process_report(r)
        }
    }

    /// A helper method. It updates the current status according to
    /// the received report message.
    fn process_report(&mut self, report: Report) {
        let duration = self.status.started_at.elapsed().unwrap();
        self.status.duration_millis = 1000 * duration.as_secs() +
                                      (duration.subsec_nanos() / 1000000) as u64;
        self.status.searched_nodes = report.searched_nodes;
        self.status.nps = 1000 * (self.status.nps + self.status.searched_nodes) /
                          (1000 + self.status.duration_millis);
        if self.status.depth < report.depth {
            self.status.depth = report.depth;
            self.status.variations = vec![extract_pv(&self.tt,
                                                     &self.status.position,
                                                     report.depth)];
        }
        self.status.done = report.done;
    }
}

/// A helper function. It extracts the primary variation (PV) from the
/// transposition table (TT) and returns it.
///
/// **Note:** Because the PV is a moving target (the search continues
/// to run in parallel), imperfections in the reported PVs are
/// unavoidable. To deal with this, we turn a blind eye if the value
/// at the root of the PV differs from the value at the leaf by no
/// more than `EPSILON`.
fn extract_pv(tt: &Tt, position: &Position, depth: u8) -> Variation {
    const EPSILON: Value = 8; // A sufficiently small value (in centipawns).

    // Extract the PV, the leaf value, the root value, and the bound
    // type from the TT.
    let mut p = position.clone();
    let mut our_turn = true;
    let mut prev_move = None;
    let mut moves = Vec::new();
    let mut leaf_value = -9999;
    let mut root_value = leaf_value;
    let mut bound = BOUND_LOWER;
    while let Some(entry) = tt.peek(p.hash()) {
        if entry.bound() != BOUND_NONE {
            // Get the value and the bound type. In half of the
            // cases the value stored in `entry` is from other
            // side's perspective.
            if our_turn {
                leaf_value = entry.value();
                bound = entry.bound();
            } else {
                leaf_value = -entry.value();
                bound = match entry.bound() {
                    BOUND_UPPER => BOUND_LOWER,
                    BOUND_LOWER => BOUND_UPPER,
                    x => x,
                };
            }

            // The values under -9999 and over 9999 may look ugly in
            // some GUIs, so we trim them.
            if leaf_value > 9999 {
                leaf_value = 9999;
                if bound == BOUND_LOWER {
                    bound = BOUND_EXACT
                }
            }
            if leaf_value < -9999 {
                leaf_value = 9999;
                if bound == BOUND_UPPER {
                    bound = BOUND_EXACT
                }
            }

            if let Some(m) = prev_move {
                // Extend the PV with the previous move.
                moves.push(m);
            } else {
                // We are at the root -- set the root value.
                root_value = leaf_value;
            }

            if moves.len() < depth as usize && (leaf_value - root_value).abs() <= EPSILON {
                if let Some(m) = p.try_move_digest(entry.move16()) {
                    if p.do_move(m) {
                        if bound == BOUND_EXACT {
                            // Extend the PV with one more move.
                            prev_move = Some(m);
                            our_turn = !our_turn;
                            continue;
                        } else {
                            // This is the last move in the PV.
                            moves.push(m);
                        }
                    }
                }
            }
        }
        break;
    }

    // Change the bound type if the leaf value in the PV differs too
    // much from the root value.
    bound = match leaf_value - root_value {
        x if x > EPSILON && bound != BOUND_UPPER => BOUND_LOWER,
        x if x < -EPSILON && bound != BOUND_LOWER => BOUND_UPPER,
        _ => bound,
    };

    Variation {
        value: root_value,
        bound: bound,
        moves: moves,
    }
}
<commit_msg>bring AspirationSearch back as default<commit_after>//! Things we have not found a home for.

use std::sync::Arc;
use std::time::{SystemTime, Duration};
use basetypes::*;
use moves::*;
use tt::*;
use position::*;
use search::*;

/// A sequence of moves from some starting position, together with the
/// value assigned to the final position.
pub struct Variation {
    /// A sequence of moves from some starting position.
    pub moves: Vec<Move>,

    /// The value assigned to the final position.
    pub value: Value,

    /// The accuracy of the assigned value.
    pub bound: BoundType,
}

/// Contains information about the current progress of a search.
pub struct SearchStatus {
    /// The starting time for the search.
    pub started_at: SystemTime,

    /// The starting (root) position for the search.
    pub position: Position,

    /// `true` if the search has stopped, `false` otherwise.
    pub done: bool,

    /// The reached search depth.
    pub depth: u8,

    /// The number of legal moves in the starting (root) position.
    pub legal_moves_count: usize,

    /// The best variations found so far. The first move in each
    /// variation will be different.
    pub variations: Vec<Variation>,

    /// The duration of the search in milliseconds.
    pub duration_millis: u64,

    /// The number of analyzed nodes.
    pub searched_nodes: NodeCount,

    /// Average number of analyzed nodes per second.
    pub nps: NodeCount,
}

/// A thread that executes consecutive searches in different starting
/// positions.
pub struct SearchThread {
    tt: Arc<Tt>,
    status: SearchStatus,
    searcher: DeepeningSearcher<AspirationSearcher<AlphabetaSearcher>>,
}

impl SearchThread {
    /// Creates a new instance.
    pub fn new(tt: Arc<Tt>) -> SearchThread {
        SearchThread {
            tt: tt.clone(),
            status: SearchStatus {
                started_at: SystemTime::now(),
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                done: true,
                depth: 0,
                variations: vec![Variation {
                                     value: VALUE_MIN,
                                     bound: BOUND_LOWER,
                                     moves: vec![],
                                 }],
                legal_moves_count: 20,
                searched_nodes: 0,
                duration_millis: 0,
                nps: 0,
            },
            searcher: DeepeningSearcher::new(tt),
        }
    }

    /// Stops the current search, starts a new search, updates the
    /// status.
    ///
    /// `position` is the starting position for the new
    /// search. `variation_count` specifies how many best lines of
    /// play to calculate (the first move in each line will be
    /// different). `searchmoves` restricts the analysis to the
    /// supplied list of moves only (no restrictions if the suppied
    /// list is empty). The move format is long algebraic
    /// notation. Examples: e2e4, e7e5, e1g1 (white short castling),
    /// e7e8q (for promotion).
    #[allow(unused_variables)]
    pub fn search(&mut self,
                  position: &Position,
                  variation_count: usize,
                  mut searchmoves: Vec<String>) {
        let mut legal_moves = position.legal_moves();
        let legal_moves_count = legal_moves.len();

        // Remove all legal moves not allowed by `searchmoves`.
        if !searchmoves.is_empty() {
            searchmoves.sort();
            let mut moves = vec![];
            for m in legal_moves.iter() {
                if searchmoves.binary_search(&m.notation()).is_ok() {
                    moves.push(*m);
                }
            }
            if !moves.is_empty() {
                legal_moves = moves;
            }
        };

        self.stop();
        self.searcher.start_search(SearchParams {
            search_id: 0,
            position: position.clone(),
            depth: MAX_DEPTH,
            lower_bound: VALUE_MIN,
            upper_bound: VALUE_MAX,
            searchmoves: legal_moves,
            variation_count: variation_count,
        });

        self.status = SearchStatus {
            started_at: SystemTime::now(),
            position: position.clone(),
            done: false,
            depth: 0,
            legal_moves_count: legal_moves_count,
            variations: vec![Variation {
                                 value: VALUE_MIN,
                                 bound: BOUND_LOWER,
                                 moves: vec![],
                             }], // TODO: Set good initial value (vec![best_move]).
            searched_nodes: 0,
            duration_millis: 0,
            ..self.status
        };
    }

    /// Stops the current search, updates the status.
    ///
    /// Does nothing if the current search is already stopped.
    pub fn stop(&mut self) {
        self.searcher.terminate_search();
        while !self.status().done {
            self.wait_status_update(Duration::from_millis(1000));
        }
    }

    /// Returns the status of the current search.
    ///
    /// **Important note:** Consecutive calls to this method will
    /// return the same unchanged result. Only after calling `search`,
    /// `stop`, or `wait_status_update`, the result returned by
    /// `status` may change.
    #[inline(always)]
    pub fn status(&self) -> &SearchStatus {
        &self.status
    }

    /// Waits for a search status update, timing out after a specified
    /// duration or earlier.
    pub fn wait_status_update(&mut self, duration: Duration) {
        self.searcher.wait_report(duration);
        while let Ok(r) = self.searcher.try_recv_report() {
            self.process_report(r)
        }
    }

    /// A helper method. It updates the current status according to
    /// the received report message.
    fn process_report(&mut self, report: Report) {
        let duration = self.status.started_at.elapsed().unwrap();
        self.status.duration_millis = 1000 * duration.as_secs() +
                                      (duration.subsec_nanos() / 1000000) as u64;
        self.status.searched_nodes = report.searched_nodes;
        self.status.nps = 1000 * (self.status.nps + self.status.searched_nodes) /
                          (1000 + self.status.duration_millis);
        if self.status.depth < report.depth {
            self.status.depth = report.depth;
            self.status.variations = vec![extract_pv(&self.tt,
                                                     &self.status.position,
                                                     report.depth)];
        }
        self.status.done = report.done;
    }
}

/// A helper function. It extracts the primary variation (PV) from the
/// transposition table (TT) and returns it.
///
/// **Note:** Because the PV is a moving target (the search continues
/// to run in parallel), imperfections in the reported PVs are
/// unavoidable. To deal with this, we turn a blind eye if the value
/// at the root of the PV differs from the value at the leaf by no
/// more than `EPSILON`.
fn extract_pv(tt: &Tt, position: &Position, depth: u8) -> Variation {
    const EPSILON: Value = 8; // A sufficiently small value (in centipawns).

    // Extract the PV, the leaf value, the root value, and the bound
    // type from the TT.
    let mut p = position.clone();
    let mut our_turn = true;
    let mut prev_move = None;
    let mut moves = Vec::new();
    let mut leaf_value = -9999;
    let mut root_value = leaf_value;
    let mut bound = BOUND_LOWER;
    while let Some(entry) = tt.peek(p.hash()) {
        if entry.bound() != BOUND_NONE {
            // Get the value and the bound type. In half of the
            // cases the value stored in `entry` is from other
            // side's perspective.
            if our_turn {
                leaf_value = entry.value();
                bound = entry.bound();
            } else {
                leaf_value = -entry.value();
                bound = match entry.bound() {
                    BOUND_UPPER => BOUND_LOWER,
                    BOUND_LOWER => BOUND_UPPER,
                    x => x,
                };
            }

            // The values under -9999 and over 9999 may look ugly in
            // some GUIs, so we trim them.
            if leaf_value > 9999 {
                leaf_value = 9999;
                if bound == BOUND_LOWER {
                    bound = BOUND_EXACT
                }
            }
            if leaf_value < -9999 {
                leaf_value = 9999;
                if bound == BOUND_UPPER {
                    bound = BOUND_EXACT
                }
            }

            if let Some(m) = prev_move {
                // Extend the PV with the previous move.
                moves.push(m);
            } else {
                // We are at the root -- set the root value.
                root_value = leaf_value;
            }

            if moves.len() < depth as usize && (leaf_value - root_value).abs() <= EPSILON {
                if let Some(m) = p.try_move_digest(entry.move16()) {
                    if p.do_move(m) {
                        if bound == BOUND_EXACT {
                            // Extend the PV with one more move.
                            prev_move = Some(m);
                            our_turn = !our_turn;
                            continue;
                        } else {
                            // This is the last move in the PV.
                            moves.push(m);
                        }
                    }
                }
            }
        }
        break;
    }

    // Change the bound type if the leaf value in the PV differs too
    // much from the root value.
    bound = match leaf_value - root_value {
        x if x > EPSILON && bound != BOUND_UPPER => BOUND_LOWER,
        x if x < -EPSILON && bound != BOUND_LOWER => BOUND_UPPER,
        _ => bound,
    };

    Variation {
        value: root_value,
        bound: bound,
        moves: moves,
    }
}
<|endoftext|>


<commit_before>//! Types representing for data which will be retrieved from the database.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the database to these types.

use structure::Collection;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<String>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A list of values.
  Array(Vec<Value>),
  /// A map of key/value pairs.
  Object(Vec<(String, Value)>)
}

/// A schema detailing what the data received from the database (or inserted
/// into the database) should be. Inspired after [JSON Schema][1]. A JSON
/// Schema general keyword reference may be found [here][2].
///
/// [1]: http://json-schema.org
/// [2]: http://spacetelescope.github.io/understanding-json-schema/reference/generic.html
pub struct Schema {
  /// The types an object may be. Contains some custom validation information
  /// for each type.
  types: Vec<SchemaType>,
  /// The default value of this part of the schema.
  default: Option<Value>,
  /// Equivelent to JSON Schema‘s `enum`. If not `None`, the value must be
  /// exactly equal to one of these.
  one_of: Option<Vec<Value>>
}

/// Type specific schema validations. A reference on JSON Schema type-specific
/// validations may be found [here][1].
///
/// [1]: http://spacetelescope.github.io/understanding-json-schema/reference/type.html
pub enum SchemaType {
  /// The absence of any value is also represented as the absence of any type.
  Null,
  /// Represents a binary true/false value.
  Boolean,
  /// Represents a numeric type.
  Number {
    /// Forces the number to be a multiple of another. This helps specifying
    /// integers if this value is `Some(1)`.
    multiple_of: Option<f32>,
    /// The minimum value the number can be.
    minimum: Option<f64>,
    /// The maximum value the number can be.
    maximum: Option<f64>
  },
  /// Represents a set of characters type.
  String {
    /// The mimimum length of characters in the string.
    min_length: Option<u64>,
    /// The maximum length of characters in the string.
    max_length: Option<u64>,
    /// A regular expression pattern to validate the string against.
    // TODO: Use a regex crate.
    pattern: Option<String>
  },
  /// Represents a set of any type.
  Array {
    /// A schema which all items in the array must match.
    item_schema: Option<Schema>
  },
  /// Represents a set of key/value pairs.
  Object {
    /// Schemas associated to the object keys.
    key_schemas: Vec<(String, Schema)>,
    /// Keys that are required to be present in the object.
    required_keys: Vec<String>,
    /// Whether or not extra keys may be present in the object.
    additional_keys: bool
  }
}

/// Different database collection property updates.
pub enum Patch {
  /// Set a property to a new value.
  Set(Pointer, Value),
  /// Reset a property to its default value.
  Reset(Pointer),
  /// Remove a property from the database entirely.
  Remove(Pointer)
}

/// A recursive filter condition for a `Value`.
pub enum Filter {
  /// Combine multiple filters with an “and” operator.
  And(Vec<Filter>),
  /// Combine multiple filters with an “or” operator.
  Or(Vec<Filter>),
  /// Inverts the filter.
  Not(Box<Filter>),
  /// The basic condition of a filter.
  Condition(Pointer, FilterCondition)
}

pub enum FilterCondition {
  Equal(Value),
  OneOf(Vec<Value>),
  GreaterThan(Value),
  LessThan(Value)
}

/// A single way in which to order a collection of documents.
pub struct Ordering(Pointer, OrderDirection);

pub enum OrderDirection {
  Ascending,
  Descending
}

// TODO: Find a more Rust idiomatic solution for ranges.
pub struct Range(Option<u32>, Option<u32>);
<commit_msg>Use BTreeMap over tuple for objects<commit_after>//! Types representing for data which will be retrieved from the database.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the database to these types.

use std::collections::BTreeMap;
use structure::Collection;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<String>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A list of values.
  Array(Vec<Value>),
  /// A map of key/value pairs.
  Object(BTreeMap<String, Value>)
}

/// A schema detailing what the data received from the database (or inserted
/// into the database) should be. Inspired after [JSON Schema][1]. A JSON
/// Schema general keyword reference may be found [here][2].
///
/// [1]: http://json-schema.org
/// [2]: http://spacetelescope.github.io/understanding-json-schema/reference/generic.html
pub struct Schema {
  /// The types an object may be. Contains some custom validation information
  /// for each type.
  types: Vec<SchemaType>,
  /// The default value of this part of the schema.
  default: Option<Value>,
  /// Equivelent to JSON Schema‘s `enum`. If not `None`, the value must be
  /// exactly equal to one of these.
  one_of: Option<Vec<Value>>
}

/// Type specific schema validations. A reference on JSON Schema type-specific
/// validations may be found [here][1].
///
/// [1]: http://spacetelescope.github.io/understanding-json-schema/reference/type.html
pub enum SchemaType {
  /// The absence of any value is also represented as the absence of any type.
  Null,
  /// Represents a binary true/false value.
  Boolean,
  /// Represents a numeric type.
  Number {
    /// Forces the number to be a multiple of another. This helps specifying
    /// integers if this value is `Some(1)`.
    multiple_of: Option<f32>,
    /// The minimum value the number can be.
    minimum: Option<f64>,
    /// The maximum value the number can be.
    maximum: Option<f64>
  },
  /// Represents a set of characters type.
  String {
    /// The mimimum length of characters in the string.
    min_length: Option<u64>,
    /// The maximum length of characters in the string.
    max_length: Option<u64>,
    /// A regular expression pattern to validate the string against.
    // TODO: Use a regex crate.
    pattern: Option<String>
  },
  /// Represents a set of any type.
  Array {
    /// A schema which all items in the array must match.
    item_schema: Option<Schema>
  },
  /// Represents a set of key/value pairs.
  Object {
    /// Schemas associated to the object keys.
    key_schemas: BTreeMap<String, Schema>,
    /// Keys that are required to be present in the object.
    required_keys: Vec<String>,
    /// Whether or not extra keys may be present in the object.
    additional_keys: bool
  }
}

/// Different database collection property updates.
pub enum Patch {
  /// Set a property to a new value.
  Set(Pointer, Value),
  /// Reset a property to its default value.
  Reset(Pointer),
  /// Remove a property from the database entirely.
  Remove(Pointer)
}

/// A recursive filter condition for a `Value`.
pub enum Filter {
  /// Combine multiple filters with an “and” operator.
  And(Vec<Filter>),
  /// Combine multiple filters with an “or” operator.
  Or(Vec<Filter>),
  /// Inverts the filter.
  Not(Box<Filter>),
  /// The basic condition of a filter.
  Condition(Pointer, FilterCondition)
}

pub enum FilterCondition {
  Equal(Value),
  OneOf(Vec<Value>),
  GreaterThan(Value),
  LessThan(Value)
}

/// A single way in which to order a collection of documents.
pub struct Ordering(Pointer, OrderDirection);

pub enum OrderDirection {
  Ascending,
  Descending
}

// TODO: Find a more Rust idiomatic solution for ranges.
pub struct Range(Option<u32>, Option<u32>);
<|endoftext|>


<commit_before>#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
   /// Nil represents nil.
   Nil,
   /// Boolean represents true or false.
   Boolean(bool),
   /// Integer represents an integer.
   Integer(Integer),
   /// Float represents a floating point number.
   Float(Float),
   /// String extending Raw type represents a UTF-8 string.
   String(&'a str),
   /// Binary extending Raw type represents a byte array.
   Binary(&'a [u8]),
   /// Array represents a sequence of objects.
   Array(Vec<ValueRef<'a>>),
   /// Map represents key-value pairs of objects.
   Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
   /// Extended implements Extension interface: represents a tuple of type information and a byte
   /// array where type information is an integer whose meaning is defined by applications.
   Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to the owned one.
    // TODO: Documentation with examples.
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_string()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                let mut vec = Vec::new();
                for item in val {
                    vec.push(item.to_owned());
                }

                Value::Array(vec)
            }
            &ValueRef::Map(ref val) => {
                let mut vec = Vec::new();
                for &(ref key, ref val) in val {
                    vec.push((key.to_owned(), val.to_owned()));
                }

                Value::Map(vec)
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives me: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<commit_msg>Doc: `to_owned` method has been documented.<commit_after>#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
   /// Nil represents nil.
   Nil,
   /// Boolean represents true or false.
   Boolean(bool),
   /// Integer represents an integer.
   Integer(Integer),
   /// Float represents a floating point number.
   Float(Float),
   /// String extending Raw type represents a UTF-8 string.
   String(&'a str),
   /// Binary extending Raw type represents a byte array.
   Binary(&'a [u8]),
   /// Array represents a sequence of objects.
   Array(Vec<ValueRef<'a>>),
   /// Map represents key-value pairs of objects.
   Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
   /// Extended implements Extension interface: represents a tuple of type information and a byte
   /// array where type information is an integer whose meaning is defined by applications.
   Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_string()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                let mut vec = Vec::new();
                for item in val {
                    vec.push(item.to_owned());
                }

                Value::Array(vec)
            }
            &ValueRef::Map(ref val) => {
                let mut vec = Vec::new();
                for &(ref key, ref val) in val {
                    vec.push((key.to_owned(), val.to_owned()));
                }

                Value::Map(vec)
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives me: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<|endoftext|>


<commit_before>use std::fs;
use std::io;
use std::path::Path;

#[cfg(unix)]
use tokio::net::UnixListener;
#[cfg(unix)]
use tokio::net::UnixStream;

use futures::Future;

use crate::net::addr::AnySocketAddr;
use crate::net::connect::ToClientStream;
use crate::net::listen::SocketListener;
use crate::net::listen::ToSocketListener;
use crate::net::listen::ToTokioListener;
use crate::net::socket::SocketStream;
use crate::ServerConf;
use std::fmt;
use std::path::PathBuf;
use std::pin::Pin;
use tokio::runtime::Handle;

/// Unix socket address, which is filesystem path.
///
/// Note although this type is available on Windows, unix sockets don't work on Windows.
#[derive(Debug, Clone, PartialEq)]
pub struct SocketAddrUnix(pub(crate) PathBuf);

impl From<PathBuf> for SocketAddrUnix {
    fn from(p: PathBuf) -> Self {
        SocketAddrUnix(p)
    }
}

impl From<&Path> for SocketAddrUnix {
    fn from(p: &Path) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl From<&str> for SocketAddrUnix {
    fn from(p: &str) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl From<&String> for SocketAddrUnix {
    fn from(p: &String) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl From<String> for SocketAddrUnix {
    fn from(p: String) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl fmt::Display for SocketAddrUnix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0.display(), f)
    }
}

#[cfg(unix)]
impl From<std::os::unix::net::SocketAddr> for SocketAddrUnix {
    fn from(s: std::os::unix::net::SocketAddr) -> Self {
        // can be unnamed
        SocketAddrUnix(s.as_pathname().unwrap_or(Path::new("")).to_owned())
    }
}

#[cfg(unix)]
impl From<tokio::net::unix::SocketAddr> for SocketAddrUnix {
    fn from(s: tokio::net::unix::SocketAddr) -> Self {
        // can be unnamed
        SocketAddrUnix(s.as_pathname().unwrap_or(Path::new("")).to_owned())
    }
}

impl ToSocketListener for SocketAddrUnix {
    #[cfg(unix)]
    fn listen(&self, _conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        debug!("binding socket to {}", self);
        Ok(Box::new(::std::os::unix::net::UnixListener::bind(&self.0)?))
    }

    #[cfg(not(unix))]
    fn listen(&self, _conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "cannot use unix sockets on non-unix",
        ))
    }

    fn cleanup(&self) {
        if self.0.exists() {
            // TODO: do not panic
            fs::remove_file(&self.0).expect("removing socket during shutdown");
        }
    }
}

#[cfg(unix)]
impl ToTokioListener for ::std::os::unix::net::UnixListener {
    fn into_tokio_listener(self: Box<Self>, handle: &Handle) -> Pin<Box<dyn SocketListener>> {
        let _g = handle.enter();
        self.set_nonblocking(true).unwrap();
        Box::pin(UnixListener::from_std(*self).unwrap())
    }

    fn local_addr(&self) -> io::Result<AnySocketAddr> {
        let addr = self.local_addr().unwrap();
        let path = addr.as_pathname().unwrap();
        Ok(AnySocketAddr::Unix(SocketAddrUnix::from(path)))
    }
}

#[cfg(unix)]
impl SocketListener for UnixListener {
    fn accept<'a>(
        self: Pin<&'a mut Self>,
    ) -> Pin<
        Box<
            dyn Future<Output = io::Result<(Pin<Box<dyn SocketStream + Send>>, AnySocketAddr)>>
                + Send
                + 'a,
        >,
    > {
        Box::pin(async move {
            let (socket, peer_addr) = UnixListener::accept(Pin::get_mut(self)).await?;
            Ok((
                Box::pin(socket) as Pin<Box<dyn SocketStream + Send>>,
                AnySocketAddr::Unix(peer_addr.into()),
            ))
        })
    }
}

impl ToClientStream for SocketAddrUnix {
    #[cfg(unix)]
    fn connect(
        &self,
        handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream>>>> + Send>> {
        // TODO: async connect
        let stream = match std::os::unix::net::UnixStream::connect(&self.0) {
            Ok(stream) => stream,
            Err(e) => return Box::pin(async { Err(e) }),
        };
        let _g = handle.enter();
        stream.set_nonblocking(true).unwrap();
        match UnixStream::from_std(stream) {
            Ok(stream) => Box::pin(async { Ok(Box::pin(stream) as Pin<Box<dyn SocketStream>>) }),
            Err(e) => return Box::pin(async { Err(e) }),
        }
    }

    #[cfg(not(unix))]
    fn connect(
        &self,
        _handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream>>>> + Send>> {
        use futures::future;
        Box::pin(future::err(io::Error::new(
            io::ErrorKind::Other,
            "cannot use unix sockets on non-unix",
        )))
    }

    fn socket_addr(&self) -> AnySocketAddr {
        AnySocketAddr::Unix(self.clone())
    }
}

#[cfg(unix)]
impl SocketStream for UnixStream {
    fn is_tcp(&self) -> bool {
        false
    }

    fn set_tcp_nodelay(&self, _no_delay: bool) -> io::Result<()> {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "Cannot set nodelay on unix domain socket",
        ))
    }

    fn peer_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::from(UnixStream::peer_addr(self)?))
    }
}

#[cfg(test)]
mod test {
    use crate::net::connect::ToClientStream;
    use crate::net::unix::SocketAddrUnix;
    use crate::AnySocketAddr;
    use std::path::PathBuf;
    use tokio::runtime::Runtime;

    #[cfg(unix)]
    #[test]
    fn peer_addr() {
        let lp = Runtime::new().unwrap();
        let h = lp.handle().clone();

        let dir = tempdir::TempDir::new("peer_addr").unwrap();
        let p = format!("{}/s", dir.path().display());
        let _server = std::os::unix::net::UnixListener::bind(&p).unwrap();

        let client =
            lp.block_on(async { SocketAddrUnix(PathBuf::from(&p)).connect(&h).await.unwrap() });

        assert_eq!(
            AnySocketAddr::Unix(SocketAddrUnix::from(&p)),
            client.peer_addr().unwrap()
        );
    }
}
<commit_msg>Use UnixStream::connect directly<commit_after>use std::fs;
use std::io;
use std::path::Path;

#[cfg(unix)]
use tokio::net::UnixListener;
#[cfg(unix)]
use tokio::net::UnixStream;

use futures::Future;

use crate::net::addr::AnySocketAddr;
use crate::net::connect::ToClientStream;
use crate::net::listen::SocketListener;
use crate::net::listen::ToSocketListener;
use crate::net::listen::ToTokioListener;
use crate::net::socket::SocketStream;
use crate::ServerConf;
use std::fmt;
use std::path::PathBuf;
use std::pin::Pin;
use tokio::runtime::Handle;

/// Unix socket address, which is filesystem path.
///
/// Note although this type is available on Windows, unix sockets don't work on Windows.
#[derive(Debug, Clone, PartialEq)]
pub struct SocketAddrUnix(pub(crate) PathBuf);

impl From<PathBuf> for SocketAddrUnix {
    fn from(p: PathBuf) -> Self {
        SocketAddrUnix(p)
    }
}

impl From<&Path> for SocketAddrUnix {
    fn from(p: &Path) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl From<&str> for SocketAddrUnix {
    fn from(p: &str) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl From<&String> for SocketAddrUnix {
    fn from(p: &String) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl From<String> for SocketAddrUnix {
    fn from(p: String) -> Self {
        SocketAddrUnix(p.into())
    }
}

impl fmt::Display for SocketAddrUnix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0.display(), f)
    }
}

#[cfg(unix)]
impl From<std::os::unix::net::SocketAddr> for SocketAddrUnix {
    fn from(s: std::os::unix::net::SocketAddr) -> Self {
        // can be unnamed
        SocketAddrUnix(s.as_pathname().unwrap_or(Path::new("")).to_owned())
    }
}

#[cfg(unix)]
impl From<tokio::net::unix::SocketAddr> for SocketAddrUnix {
    fn from(s: tokio::net::unix::SocketAddr) -> Self {
        // can be unnamed
        SocketAddrUnix(s.as_pathname().unwrap_or(Path::new("")).to_owned())
    }
}

impl ToSocketListener for SocketAddrUnix {
    #[cfg(unix)]
    fn listen(&self, _conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        debug!("binding socket to {}", self);
        Ok(Box::new(::std::os::unix::net::UnixListener::bind(&self.0)?))
    }

    #[cfg(not(unix))]
    fn listen(&self, _conf: &ServerConf) -> io::Result<Box<dyn ToTokioListener + Send>> {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "cannot use unix sockets on non-unix",
        ))
    }

    fn cleanup(&self) {
        if self.0.exists() {
            // TODO: do not panic
            fs::remove_file(&self.0).expect("removing socket during shutdown");
        }
    }
}

#[cfg(unix)]
impl ToTokioListener for ::std::os::unix::net::UnixListener {
    fn into_tokio_listener(self: Box<Self>, handle: &Handle) -> Pin<Box<dyn SocketListener>> {
        let _g = handle.enter();
        self.set_nonblocking(true).unwrap();
        Box::pin(UnixListener::from_std(*self).unwrap())
    }

    fn local_addr(&self) -> io::Result<AnySocketAddr> {
        let addr = self.local_addr().unwrap();
        let path = addr.as_pathname().unwrap();
        Ok(AnySocketAddr::Unix(SocketAddrUnix::from(path)))
    }
}

#[cfg(unix)]
impl SocketListener for UnixListener {
    fn accept<'a>(
        self: Pin<&'a mut Self>,
    ) -> Pin<
        Box<
            dyn Future<Output = io::Result<(Pin<Box<dyn SocketStream + Send>>, AnySocketAddr)>>
                + Send
                + 'a,
        >,
    > {
        Box::pin(async move {
            let (socket, peer_addr) = UnixListener::accept(Pin::get_mut(self)).await?;
            Ok((
                Box::pin(socket) as Pin<Box<dyn SocketStream + Send>>,
                AnySocketAddr::Unix(peer_addr.into()),
            ))
        })
    }
}

impl ToClientStream for SocketAddrUnix {
    #[cfg(unix)]
    fn connect<'a>(
        &'a self,
        handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream>>>> + Send + 'a>> {
        let _g = handle.enter();
        Box::pin(async move {
            let stream = UnixStream::connect(&self.0).await?;
            let stream: Pin<Box<dyn SocketStream>> = Box::pin(stream);
            Ok(stream)
        })
    }

    #[cfg(not(unix))]
    fn connect<'a>(
        &'a self,
        _handle: &Handle,
    ) -> Pin<Box<dyn Future<Output = io::Result<Pin<Box<dyn SocketStream>>>> + Send + 'a>> {
        use futures::future;
        Box::pin(future::err(io::Error::new(
            io::ErrorKind::Other,
            "cannot use unix sockets on non-unix",
        )))
    }

    fn socket_addr(&self) -> AnySocketAddr {
        AnySocketAddr::Unix(self.clone())
    }
}

#[cfg(unix)]
impl SocketStream for UnixStream {
    fn is_tcp(&self) -> bool {
        false
    }

    fn set_tcp_nodelay(&self, _no_delay: bool) -> io::Result<()> {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "Cannot set nodelay on unix domain socket",
        ))
    }

    fn peer_addr(&self) -> io::Result<AnySocketAddr> {
        Ok(AnySocketAddr::from(UnixStream::peer_addr(self)?))
    }
}

#[cfg(test)]
mod test {
    use crate::net::connect::ToClientStream;
    use crate::net::unix::SocketAddrUnix;
    use crate::AnySocketAddr;
    use std::path::PathBuf;
    use tokio::runtime::Runtime;

    #[cfg(unix)]
    #[test]
    fn peer_addr() {
        let lp = Runtime::new().unwrap();
        let h = lp.handle().clone();

        let dir = tempdir::TempDir::new("peer_addr").unwrap();
        let p = format!("{}/s", dir.path().display());
        let _server = std::os::unix::net::UnixListener::bind(&p).unwrap();

        let client =
            lp.block_on(async { SocketAddrUnix(PathBuf::from(&p)).connect(&h).await.unwrap() });

        assert_eq!(
            AnySocketAddr::Unix(SocketAddrUnix::from(&p)),
            client.peer_addr().unwrap()
        );
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
use toml::{self, Parser, Table, Value};

use env::Env;
use file_saver::save_to_file;
use nameutil::crate_name;

pub fn generate(env: &Env) {
    println!("manipulating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut parser = Parser::new(&toml_str);
    let mut root_table = parser.parse().unwrap_or_else(BTreeMap::new);

    if empty {
        fill_empty(&mut root_table, env);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup,
        |w| w.write_all(toml::encode_str(&root_table).as_bytes()));
}

fn fill_empty(root: &mut Table, env: &Env) {
    let name = format!("{}_sys", crate_name(&env.config.library_name));
    let package_name = name.replace("_", "-");

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.2.0");
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let ext_package = format!("{}_sys", crate_name(ext_lib))
            .replace("_", "-");
        let dep = upsert_table(deps, &*ext_package);
        set_string(dep, "path", format!("../{}", ext_package));
        set_string(dep, "version", "0.2.0");
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        set_string(package, "links", crate_name(&env.config.library_name));
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "bitflags", "0.3");
        set_string(deps, "libc", "0.1");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "pkg-config", "0.3.5");
    }
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    if let Some(v) = table.get_mut(name) {
        *v = Value::String(new_value.into());
        return;
    }
    table.insert(name.into(), Value::String(new_value.into()));
}

fn upsert_table<'a, S: Into<String>>(parent: &'a mut Table, name: S) -> &'a mut Table {
    if let &mut Value::Table(ref mut table) = parent.entry(name.into())
            .or_insert_with(|| Value::Table(BTreeMap::new())) {
        table
    }
    else {
        unreachable!()
    }
}
<commit_msg>sys: Add version features to Cargo.toml<commit_after>use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
use toml::{self, Parser, Table, Value};

use env::Env;
use file_saver::save_to_file;
use nameutil::crate_name;
use version::Version;

pub fn generate(env: &Env) {
    println!("manipulating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut parser = Parser::new(&toml_str);
    let mut root_table = parser.parse().unwrap_or_else(BTreeMap::new);

    if empty {
        fill_empty(&mut root_table, env);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup,
        |w| w.write_all(toml::encode_str(&root_table).as_bytes()));
}

fn fill_empty(root: &mut Table, env: &Env) {
    let name = format!("{}_sys", crate_name(&env.config.library_name));
    let package_name = name.replace("_", "-");

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.2.0");
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let ext_package = format!("{}_sys", crate_name(ext_lib))
            .replace("_", "-");
        let dep = upsert_table(deps, &*ext_package);
        set_string(dep, "path", format!("../{}", ext_package));
        set_string(dep, "version", "0.2.0");
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        set_string(package, "links", crate_name(&env.config.library_name));
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "bitflags", "0.3");
        set_string(deps, "libc", "0.1");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "pkg-config", "0.3.5");
    }

    {
        let features = upsert_table(root, "features");
        features.clear();
        let versions = env.namespaces.main().versions.iter()
            .filter(|&&v| v > env.config.min_cfg_version);
        versions.fold(None::<Version>, |prev, &version| {
            let prev_array: Vec<Value> = prev.iter()
                .map(|v| Value::String(v.to_string()))
                .collect();
            features.insert(version.to_string(), Value::Array(prev_array));
            Some(version)
        });
    }
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    if let Some(v) = table.get_mut(name) {
        *v = Value::String(new_value.into());
        return;
    }
    table.insert(name.into(), Value::String(new_value.into()));
}

fn upsert_table<'a, S: Into<String>>(parent: &'a mut Table, name: S) -> &'a mut Table {
    if let &mut Value::Table(ref mut table) = parent.entry(name.into())
            .or_insert_with(|| Value::Table(BTreeMap::new())) {
        table
    }
    else {
        unreachable!()
    }
}
<|endoftext|>


<commit_before>pub struct Choose<T: Clone> {
    vec: Vec<T>,
    k: usize,
    indices: Vec<usize>,
    first: bool,
}

impl<T: Clone> Choose<T> {
    fn new(vec: Vec<T>, k: usize) -> Choose<T> {
        Choose {
            vec: vec,
            k: k,
            indices: (0..k).collect(),
            first: true,
        }
    }

    fn n(&self) -> usize {
        self.vec.len()
    }
}

impl<T: Clone> Iterator for Choose<T> {
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.first {
            true => match self.n() < self.k {
                true => None,
                false => {
                    self.first = false;
                    Some(
                        self.indices
                            .iter()
                            .map(|&i| self.vec.get(i).unwrap().clone())
                            .collect(),
                    )
                }
            },
            false => {
                let first_thing = (0..self.k)
                    .rev()
                    .filter(|&_i| *self.indices.get(_i).unwrap() != _i + self.n() - self.k)
                    .take(1)
                    .collect::<Vec<usize>>();
                match first_thing.len() {
                    0 => None,
                    _ => {
                        let i = first_thing[0];
                        self.indices[i] += 1;
                        for j in (i + 1)..self.k {
                            self.indices[j] = self.indices[j - 1] + 1;
                        }
                        Some(
                            self.indices
                                .iter()
                                .map(|&i| self.vec.get(i).unwrap().clone())
                                .collect(),
                        )
                    }
                }
            }
        }
    }
}

pub trait Chooseable<T>
where
    T: Clone,
{
    fn choose(self, k: usize) -> Choose<T>;
}

impl<T: Copy> Chooseable<T> for Vec<T>
where
    T: Clone,
{
    fn choose(self, k: usize) -> Choose<T> {
        Choose::new(self, k)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_returns_none_when_choosing_one_from_an_empty_list() {
        let vector: Vec<()> = vec![];
        let mut it = vector.choose(1);
        assert!(it.next().is_none());
    }

    #[test]
    fn it_returns_the_empty_vector_when_choosing_zero_from_an_empty_list() {
        let vector: Vec<()> = vec![];
        let mut it = vector.choose(0);
        assert_eq!(it.next().unwrap(), vec![]);
        assert!(it.next().is_none());
    }

    #[test]
    fn it_returns_the_empty_vector_when_choosing_zero_from_a_list_with_elements() {
        let vector = vec![0, 1, 2];
        let mut it = vector.choose(0);
        assert_eq!(it.next().unwrap().len(), 0);
        assert!(it.next().is_none());
    }

    #[test]
    fn it_returns_each_item_when_choosing_one_from_a_list_with_items() {
        let vector = vec![0, 1, 2];
        let mut it = vector.choose(1);

        assert_eq!(it.next().unwrap(), vec![0]);
        assert_eq!(it.next().unwrap(), vec![1]);
        assert_eq!(it.next().unwrap(), vec![2]);
        assert!(it.next().is_none());
    }

    #[test]
    fn it_returns_each_item_combination_when_choosing_two_from_a_list_with_items() {
        let vector = vec![0, 1, 2];
        let mut it = vector.choose(2);

        assert_eq!(it.next().unwrap(), vec![0, 1]);
        assert_eq!(it.next().unwrap(), vec![0, 2]);
        assert_eq!(it.next().unwrap(), vec![1, 2]);
        assert!(it.next().is_none());
    }

    #[test]
    fn it_returns_each_item_combination_when_choosing_two_from_a_list_with_four_items() {
        let vector = vec![0, 1, 2, 3, 4];
        let mut it = vector.choose(2);

        assert_eq!(it.next().unwrap(), vec![0, 1]);
        assert_eq!(it.next().unwrap(), vec![0, 2]);
        assert_eq!(it.next().unwrap(), vec![0, 3]);
        assert_eq!(it.next().unwrap(), vec![0, 4]);
        assert_eq!(it.next().unwrap(), vec![1, 2]);
        assert_eq!(it.next().unwrap(), vec![1, 3]);
        assert_eq!(it.next().unwrap(), vec![1, 4]);
        assert_eq!(it.next().unwrap(), vec![2, 3]);
        assert_eq!(it.next().unwrap(), vec![2, 4]);
        assert_eq!(it.next().unwrap(), vec![3, 4]);
        assert!(it.next().is_none());
    }
}
<commit_msg>refactor<commit_after>pub struct Choose<T: Clone> {
    vec: Vec<T>,
    k: usize,
    indices: Vec<usize>,
    first: bool,
}

impl<T: Clone> Choose<T> {
    fn new(vec: Vec<T>, k: usize) -> Choose<T> {
        Choose {
            vec: vec,
            k: k,
            indices: (0..k).collect(),
            first: true,
        }
    }

    fn n(&self) -> usize {
        self.vec.len()
    }

    fn from_indices(&self) -> Vec<T> {
        self.indices.iter().map(|&i| self.vec[i].clone()).collect()
    }

    fn increment_indices(&mut self) -> Option<()> {
        let to_increment = (0..self.k)
            .rev()
            .filter(|&i| {
                let max_allowed = self.n() - self.k + i;
                self.indices[i] < max_allowed
            })
            .next();
        let to_increment = match to_increment {
            None => return None,
            Some(i) => i,
        };

        self.indices[to_increment] += 1;

        for j in (to_increment + 1)..self.k {
            let previous_index = self.indices[j - 1];
            self.indices[j] = previous_index + 1;
        }

        Some(())
    }
}

impl<T: Clone> Iterator for Choose<T> {
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.n() < self.k {
            return None;
        }

        if !self.first {
            match self.increment_indices() {
                None => return None,
                Some(()) => {}
            };
        };

        self.first = false;

        Some(self.from_indices())
    }
}

pub trait Chooseable<T>
where
    T: Clone,
{
    fn choose(self, k: usize) -> Choose<T>;
}

impl<T> Chooseable<T> for Vec<T>
where
    T: Clone,
{
    fn choose(self, k: usize) -> Choose<T> {
        Choose::new(self, k)
    }
}

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

    #[test]
    fn it_returns_none_when_choosing_one_from_an_empty_list() {
        let vector: Vec<()> = vec![];
        let mut it = vector.choose(1);
        assert_eq!(it.next(), None);
    }

    #[test]
    fn it_returns_the_empty_vector_when_choosing_zero_from_an_empty_list() {
        let vector: Vec<()> = vec![];
        let mut it = vector.choose(0);
        assert_eq!(it.next().unwrap(), vec![]);
        assert_eq!(it.next(), None);
    }

    #[test]
    fn it_returns_the_empty_vector_when_choosing_zero_from_a_list_with_elements() {
        let vector = vec![0, 1, 2];
        let mut it = vector.choose(0);
        assert_eq!(it.next().unwrap().len(), 0);
        assert_eq!(it.next(), None);
    }

    #[test]
    fn it_returns_each_item_when_choosing_one_from_a_list_with_items() {
        let vector = vec![0, 1, 2];
        let mut it = vector.choose(1);

        assert_eq!(it.next().unwrap(), vec![0]);
        assert_eq!(it.next().unwrap(), vec![1]);
        assert_eq!(it.next().unwrap(), vec![2]);
        assert_eq!(it.next(), None);
    }

    #[test]
    fn it_returns_each_item_combination_when_choosing_two_from_a_list_with_items() {
        let vector = vec![0, 1, 2];
        let mut it = vector.choose(2);

        assert_eq!(it.next().unwrap(), vec![0, 1]);
        assert_eq!(it.next().unwrap(), vec![0, 2]);
        assert_eq!(it.next().unwrap(), vec![1, 2]);
        assert_eq!(it.next(), None);
    }

    #[test]
    fn it_returns_each_item_combination_when_choosing_two_from_a_list_with_five_items() {
        let vector = vec![0, 1, 2, 3, 4];
        let mut it = vector.choose(2);

        assert_eq!(it.next().unwrap(), vec![0, 1]);
        assert_eq!(it.next().unwrap(), vec![0, 2]);
        assert_eq!(it.next().unwrap(), vec![0, 3]);
        assert_eq!(it.next().unwrap(), vec![0, 4]);
        assert_eq!(it.next().unwrap(), vec![1, 2]);
        assert_eq!(it.next().unwrap(), vec![1, 3]);
        assert_eq!(it.next().unwrap(), vec![1, 4]);
        assert_eq!(it.next().unwrap(), vec![2, 3]);
        assert_eq!(it.next().unwrap(), vec![2, 4]);
        assert_eq!(it.next().unwrap(), vec![3, 4]);
        assert_eq!(it.next(), None);
    }
}
<|endoftext|>