<commit_before>use core::array::{FixedSizeArray, IntoIter};
use core::convert::TryFrom;

#[test]
fn fixed_size_array() {
    let mut array = [0; 64];
    let mut zero_sized = [(); 64];
    let mut empty_array = [0; 0];
    let mut empty_zero_sized = [(); 0];

    assert_eq!(FixedSizeArray::as_slice(&array).len(), 64);
    assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64);
    assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0);
    assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0);

    assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64);
    assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64);
    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0);
    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0);
}

#[test]
fn array_try_from() {
    macro_rules! test {
        ($($N:expr)+) => {
            $({
                type Array = [u8; $N];
                let array: Array = [0; $N];
                let slice: &[u8] = &array[..];

                let result = <&Array>::try_from(slice);
                assert_eq!(&array, result.unwrap());
            })+
        }
    }
    test! {
         0  1  2  3  4  5  6  7  8  9
        10 11 12 13 14 15 16 17 18 19
        20 21 22 23 24 25 26 27 28 29
        30 31 32
    }
}

#[test]
fn iterator_collect() {
    let arr = [0, 1, 2, 5, 9];
    let v: Vec<_> = IntoIter::new(arr.clone()).collect();
    assert_eq!(&arr[..], &v[..]);
}

#[test]
fn iterator_rev_collect() {
    let arr = [0, 1, 2, 5, 9];
    let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect();
    assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
}

#[test]
fn iterator_nth() {
    let v = [0, 1, 2, 3, 4];
    for i in 0..v.len() {
        assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]);
    }
    assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None);

    let mut iter = IntoIter::new(v);
    assert_eq!(iter.nth(2).unwrap(), v[2]);
    assert_eq!(iter.nth(1).unwrap(), v[4]);
}

#[test]
fn iterator_last() {
    let v = [0, 1, 2, 3, 4];
    assert_eq!(IntoIter::new(v).last().unwrap(), 4);
    assert_eq!(IntoIter::new([0]).last().unwrap(), 0);

    let mut it = IntoIter::new([0, 9, 2, 4]);
    assert_eq!(it.next_back(), Some(4));
    assert_eq!(it.last(), Some(2));
}

#[test]
fn iterator_clone() {
    let mut it = IntoIter::new([0, 2, 4, 6, 8]);
    assert_eq!(it.next(), Some(0));
    assert_eq!(it.next_back(), Some(8));
    let mut clone = it.clone();
    assert_eq!(it.next_back(), Some(6));
    assert_eq!(clone.next_back(), Some(6));
    assert_eq!(it.next_back(), Some(4));
    assert_eq!(clone.next_back(), Some(4));
    assert_eq!(it.next(), Some(2));
    assert_eq!(clone.next(), Some(2));
}

#[test]
fn iterator_fused() {
    let mut it = IntoIter::new([0, 9, 2]);
    assert_eq!(it.next(), Some(0));
    assert_eq!(it.next(), Some(9));
    assert_eq!(it.next(), Some(2));
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
}

#[test]
fn iterator_len() {
    let mut it = IntoIter::new([0, 1, 2, 5, 9]);
    assert_eq!(it.size_hint(), (5, Some(5)));
    assert_eq!(it.len(), 5);
    assert_eq!(it.is_empty(), false);

    assert_eq!(it.next(), Some(0));
    assert_eq!(it.size_hint(), (4, Some(4)));
    assert_eq!(it.len(), 4);
    assert_eq!(it.is_empty(), false);

    assert_eq!(it.next_back(), Some(9));
    assert_eq!(it.size_hint(), (3, Some(3)));
    assert_eq!(it.len(), 3);
    assert_eq!(it.is_empty(), false);

    // Empty
    let it = IntoIter::new([] as [String; 0]);
    assert_eq!(it.size_hint(), (0, Some(0)));
    assert_eq!(it.len(), 0);
    assert_eq!(it.is_empty(), true);
}

#[test]
fn iterator_count() {
    let v = [0, 1, 2, 3, 4];
    assert_eq!(IntoIter::new(v.clone()).count(), 5);

    let mut iter2 = IntoIter::new(v);
    iter2.next();
    iter2.next();
    assert_eq!(iter2.count(), 3);
}

#[test]
fn iterator_flat_map() {
    assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10));
}

#[test]
fn iterator_debug() {
    let arr = [0, 1, 2, 5, 9];
    assert_eq!(format!("{:?}", IntoIter::new(arr)), "IntoIter([0, 1, 2, 5, 9])",);
}

#[test]
fn iterator_drops() {
    use core::cell::Cell;

    // This test makes sure the correct number of elements are dropped. The `R`
    // type is just a reference to a `Cell` that is incremented when an `R` is
    // dropped.

    #[derive(Clone)]
    struct Foo<'a>(&'a Cell<usize>);

    impl Drop for Foo<'_> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
        // This is somewhat verbose because `Foo` does not implement `Copy`
        // since it implements `Drop`. Consequently, we cannot write
        // `[Foo(i); 5]`.
        [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
    }

    // Simple: drop new iterator.
    let i = Cell::new(0);
    {
        IntoIter::new(five(&i));
    }
    assert_eq!(i.get(), 5);

    // Call `next()` once.
    let i = Cell::new(0);
    {
        let mut iter = IntoIter::new(five(&i));
        let _x = iter.next();
        assert_eq!(i.get(), 0);
        assert_eq!(iter.count(), 4);
        assert_eq!(i.get(), 4);
    }
    assert_eq!(i.get(), 5);

    // Check `clone` and calling `next`/`next_back`.
    let i = Cell::new(0);
    {
        let mut iter = IntoIter::new(five(&i));
        iter.next();
        assert_eq!(i.get(), 1);
        iter.next_back();
        assert_eq!(i.get(), 2);

        let mut clone = iter.clone();
        assert_eq!(i.get(), 2);

        iter.next();
        assert_eq!(i.get(), 3);

        clone.next();
        assert_eq!(i.get(), 4);

        assert_eq!(clone.count(), 2);
        assert_eq!(i.get(), 6);
    }
    assert_eq!(i.get(), 8);

    // Check via `nth`.
    let i = Cell::new(0);
    {
        let mut iter = IntoIter::new(five(&i));
        let _x = iter.nth(2);
        assert_eq!(i.get(), 2);
        let _y = iter.last();
        assert_eq!(i.get(), 3);
    }
    assert_eq!(i.get(), 5);

    // Check every element.
    let i = Cell::new(0);
    for (index, _x) in IntoIter::new(five(&i)).enumerate() {
        assert_eq!(i.get(), index);
    }
    assert_eq!(i.get(), 5);

    let i = Cell::new(0);
    for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() {
        assert_eq!(i.get(), index);
    }
    assert_eq!(i.get(), 5);
}

#[test]
fn array_default_impl_avoids_leaks_on_panic() {
    use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
    static COUNTER: AtomicUsize = AtomicUsize::new(0);
    #[derive(Debug)]
    struct Bomb(usize);

    impl Default for Bomb {
        fn default() -> Bomb {
            if COUNTER.load(Relaxed) == 3 {
                panic!("bomb limit exceeded");
            }

            COUNTER.fetch_add(1, Relaxed);
            Bomb(COUNTER.load(Relaxed))
        }
    }

    impl Drop for Bomb {
        fn drop(&mut self) {
            COUNTER.fetch_sub(1, Relaxed);
        }
    }

    let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
    let panic_msg = match res {
        Ok(_) => unreachable!(),
        Err(p) => p.downcast::<&'static str>().unwrap(),
    };
    assert_eq!(*panic_msg, "bomb limit exceeded");
    // check that all bombs are successfully dropped
    assert_eq!(COUNTER.load(Relaxed), 0);
}

#[test]
fn empty_array_is_always_default() {
    struct DoesNotImplDefault;

    let _arr = <[DoesNotImplDefault; 0]>::default();
}
<commit_msg>Skip leak test on targets without panic=unwind<commit_after>use core::array::{FixedSizeArray, IntoIter};
use core::convert::TryFrom;

#[test]
fn fixed_size_array() {
    let mut array = [0; 64];
    let mut zero_sized = [(); 64];
    let mut empty_array = [0; 0];
    let mut empty_zero_sized = [(); 0];

    assert_eq!(FixedSizeArray::as_slice(&array).len(), 64);
    assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64);
    assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0);
    assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0);

    assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64);
    assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64);
    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0);
    assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0);
}

#[test]
fn array_try_from() {
    macro_rules! test {
        ($($N:expr)+) => {
            $({
                type Array = [u8; $N];
                let array: Array = [0; $N];
                let slice: &[u8] = &array[..];

                let result = <&Array>::try_from(slice);
                assert_eq!(&array, result.unwrap());
            })+
        }
    }
    test! {
         0  1  2  3  4  5  6  7  8  9
        10 11 12 13 14 15 16 17 18 19
        20 21 22 23 24 25 26 27 28 29
        30 31 32
    }
}

#[test]
fn iterator_collect() {
    let arr = [0, 1, 2, 5, 9];
    let v: Vec<_> = IntoIter::new(arr.clone()).collect();
    assert_eq!(&arr[..], &v[..]);
}

#[test]
fn iterator_rev_collect() {
    let arr = [0, 1, 2, 5, 9];
    let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect();
    assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
}

#[test]
fn iterator_nth() {
    let v = [0, 1, 2, 3, 4];
    for i in 0..v.len() {
        assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]);
    }
    assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None);

    let mut iter = IntoIter::new(v);
    assert_eq!(iter.nth(2).unwrap(), v[2]);
    assert_eq!(iter.nth(1).unwrap(), v[4]);
}

#[test]
fn iterator_last() {
    let v = [0, 1, 2, 3, 4];
    assert_eq!(IntoIter::new(v).last().unwrap(), 4);
    assert_eq!(IntoIter::new([0]).last().unwrap(), 0);

    let mut it = IntoIter::new([0, 9, 2, 4]);
    assert_eq!(it.next_back(), Some(4));
    assert_eq!(it.last(), Some(2));
}

#[test]
fn iterator_clone() {
    let mut it = IntoIter::new([0, 2, 4, 6, 8]);
    assert_eq!(it.next(), Some(0));
    assert_eq!(it.next_back(), Some(8));
    let mut clone = it.clone();
    assert_eq!(it.next_back(), Some(6));
    assert_eq!(clone.next_back(), Some(6));
    assert_eq!(it.next_back(), Some(4));
    assert_eq!(clone.next_back(), Some(4));
    assert_eq!(it.next(), Some(2));
    assert_eq!(clone.next(), Some(2));
}

#[test]
fn iterator_fused() {
    let mut it = IntoIter::new([0, 9, 2]);
    assert_eq!(it.next(), Some(0));
    assert_eq!(it.next(), Some(9));
    assert_eq!(it.next(), Some(2));
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
    assert_eq!(it.next(), None);
}

#[test]
fn iterator_len() {
    let mut it = IntoIter::new([0, 1, 2, 5, 9]);
    assert_eq!(it.size_hint(), (5, Some(5)));
    assert_eq!(it.len(), 5);
    assert_eq!(it.is_empty(), false);

    assert_eq!(it.next(), Some(0));
    assert_eq!(it.size_hint(), (4, Some(4)));
    assert_eq!(it.len(), 4);
    assert_eq!(it.is_empty(), false);

    assert_eq!(it.next_back(), Some(9));
    assert_eq!(it.size_hint(), (3, Some(3)));
    assert_eq!(it.len(), 3);
    assert_eq!(it.is_empty(), false);

    // Empty
    let it = IntoIter::new([] as [String; 0]);
    assert_eq!(it.size_hint(), (0, Some(0)));
    assert_eq!(it.len(), 0);
    assert_eq!(it.is_empty(), true);
}

#[test]
fn iterator_count() {
    let v = [0, 1, 2, 3, 4];
    assert_eq!(IntoIter::new(v.clone()).count(), 5);

    let mut iter2 = IntoIter::new(v);
    iter2.next();
    iter2.next();
    assert_eq!(iter2.count(), 3);
}

#[test]
fn iterator_flat_map() {
    assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10));
}

#[test]
fn iterator_debug() {
    let arr = [0, 1, 2, 5, 9];
    assert_eq!(format!("{:?}", IntoIter::new(arr)), "IntoIter([0, 1, 2, 5, 9])",);
}

#[test]
fn iterator_drops() {
    use core::cell::Cell;

    // This test makes sure the correct number of elements are dropped. The `R`
    // type is just a reference to a `Cell` that is incremented when an `R` is
    // dropped.

    #[derive(Clone)]
    struct Foo<'a>(&'a Cell<usize>);

    impl Drop for Foo<'_> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
        // This is somewhat verbose because `Foo` does not implement `Copy`
        // since it implements `Drop`. Consequently, we cannot write
        // `[Foo(i); 5]`.
        [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
    }

    // Simple: drop new iterator.
    let i = Cell::new(0);
    {
        IntoIter::new(five(&i));
    }
    assert_eq!(i.get(), 5);

    // Call `next()` once.
    let i = Cell::new(0);
    {
        let mut iter = IntoIter::new(five(&i));
        let _x = iter.next();
        assert_eq!(i.get(), 0);
        assert_eq!(iter.count(), 4);
        assert_eq!(i.get(), 4);
    }
    assert_eq!(i.get(), 5);

    // Check `clone` and calling `next`/`next_back`.
    let i = Cell::new(0);
    {
        let mut iter = IntoIter::new(five(&i));
        iter.next();
        assert_eq!(i.get(), 1);
        iter.next_back();
        assert_eq!(i.get(), 2);

        let mut clone = iter.clone();
        assert_eq!(i.get(), 2);

        iter.next();
        assert_eq!(i.get(), 3);

        clone.next();
        assert_eq!(i.get(), 4);

        assert_eq!(clone.count(), 2);
        assert_eq!(i.get(), 6);
    }
    assert_eq!(i.get(), 8);

    // Check via `nth`.
    let i = Cell::new(0);
    {
        let mut iter = IntoIter::new(five(&i));
        let _x = iter.nth(2);
        assert_eq!(i.get(), 2);
        let _y = iter.last();
        assert_eq!(i.get(), 3);
    }
    assert_eq!(i.get(), 5);

    // Check every element.
    let i = Cell::new(0);
    for (index, _x) in IntoIter::new(five(&i)).enumerate() {
        assert_eq!(i.get(), index);
    }
    assert_eq!(i.get(), 5);

    let i = Cell::new(0);
    for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() {
        assert_eq!(i.get(), index);
    }
    assert_eq!(i.get(), 5);
}

// This test does not work on targets without panic=unwind support.
// To work around this problem, test is marked is should_panic, so it will
// be automagically skipped on unsuitable targets, such as
// wasm32-unknown-unkown.
//
// It means that we use panic for indicating success.
#[test]
#[should_panic(expected = "test succeeded")]
fn array_default_impl_avoids_leaks_on_panic() {
    use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
    static COUNTER: AtomicUsize = AtomicUsize::new(0);
    #[derive(Debug)]
    struct Bomb(usize);

    impl Default for Bomb {
        fn default() -> Bomb {
            if COUNTER.load(Relaxed) == 3 {
                panic!("bomb limit exceeded");
            }

            COUNTER.fetch_add(1, Relaxed);
            Bomb(COUNTER.load(Relaxed))
        }
    }

    impl Drop for Bomb {
        fn drop(&mut self) {
            COUNTER.fetch_sub(1, Relaxed);
        }
    }

    let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
    let panic_msg = match res {
        Ok(_) => unreachable!(),
        Err(p) => p.downcast::<&'static str>().unwrap(),
    };
    assert_eq!(*panic_msg, "bomb limit exceeded");
    // check that all bombs are successfully dropped
    assert_eq!(COUNTER.load(Relaxed), 0);
    panic!("test succeeded")
}

#[test]
fn empty_array_is_always_default() {
    struct DoesNotImplDefault;

    let _arr = <[DoesNotImplDefault; 0]>::default();
}
<|endoftext|>


<commit_before>extern crate pkg_config;
extern crate cmake;

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cfg.define("STATIC_CRT", "OFF");
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!("/I{}", libssh2_include))
                   .cflag("/DGIT_SSH");
            } else {
                cfg.cflag(format!("-I{}", libssh2_include))
                   .cflag("-DGIT_SSH");
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .define("CURL", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=CoreFoundation");
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<commit_msg>Detect when http_parser is being linked to<commit_after>extern crate pkg_config;
extern crate cmake;

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cfg.define("STATIC_CRT", "OFF");
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!("/I{}", libssh2_include))
                   .cflag("/DGIT_SSH");
            } else {
                cfg.cflag(format!("-I{}", libssh2_include))
                   .cflag("-DGIT_SSH");
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .define("CURL", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    // libgit2 requires the http_parser library for the HTTP transport to be
    // implemented, and it will attempt to use the system http_parser if it's
    // available. Detect this situation and report using the system http parser
    // the same way in this situation.
    //
    // Note that other dependencies of libgit2 like openssl, libz, and libssh2
    // are tracked via crates instead of this. Ideally this should be a crate as
    // well.
    let pkgconfig_file = dst.join("lib/pkgconfig/libgit2.pc");
    if let Ok(mut f) = File::open(&pkgconfig_file) {
        let mut contents = String::new();
        t!(f.read_to_string(&mut contents));
        if contents.contains("-lhttp_parser") {
            println!("cargo:rustc-link-lib=http_parser");
        }
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=CoreFoundation");
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<|endoftext|>


<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! Complex type
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::f64;

use types::{Zero, One};

#[derive(Debug, Clone, Copy, PartialEq, Default)]
/// Complex number, with double precision real and imaginary parts.
///
/// `Complex` implements all the usual arithmetic operations:
///
/// ```
/// # use lumol::types::Complex;
///
/// let w = Complex::cartesian(-1.0, 0.5);
/// let z = Complex::cartesian(4.0, 2.0);
///
/// // Addition
/// let c = w + z;
/// assert_eq!(c, Complex::cartesian(3.0, 2.5));
///
/// // Subtraction
/// let c = w - z;
/// assert_eq!(c, Complex::cartesian(-5.0, -1.5));
///
/// // Multiplication
/// let c = w * z;
/// assert_eq!(c, Complex::cartesian(-5.0, 0.0));
///
/// let c = 42.0 * w;
/// assert_eq!(c, Complex::cartesian(-42.0, 21.0));
///
/// // Division
/// let c = z / 2.0;
/// assert_eq!(c, Complex::cartesian(2.0, 1.0));
/// ```
pub struct Complex {
    /// Real part of the complex
    real: f64,
    /// Imaginary part of the complex
    imag: f64,
}

impl Complex {
    /// Create a new `Complex` from a norm `r` and a phase `phi` in radians.
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// # use std::f64;
    /// let z = Complex::polar(3.0, f64::consts::PI);
    /// assert_eq!(z.norm(), 3.0);
    /// ```
    pub fn polar(r: f64, phi: f64) -> Complex {
        Complex{
            real: r * f64::cos(phi),
            imag: r * f64::sin(phi)
        }
    }

    /// Create a complex from Cartesian coordinates
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.real(), 3.0);
    /// assert_eq!(z.imag(), -2.0);
    /// ```
    pub fn cartesian(x: f64, y: f64) -> Complex {
        Complex{
            real: x,
            imag: y,
        }
    }

    /// Get the real part of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.real(), 3.0);
    /// ```
    #[inline]
    pub fn real(&self) -> f64 {
        self.real
    }

    /// Get the imaginary part of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.imag(), -2.0);
    /// ```
    #[inline]
    pub fn imag(&self) -> f64 {
        self.imag
    }

    /// Get the phase of the complex in the [-π, π) interval
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::polar(2.0, 0.3);
    /// assert_eq!(z.phase(), 0.3);
    /// ```
    #[inline]
    pub fn phase(&self) -> f64 {
        f64::atan2(self.imag, self.real)
    }

    /// Get the norm of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// # use std::f64;
    /// let z = Complex::polar(2.0, 0.3);
    /// assert_eq!(z.norm(), 2.0);
    ///
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.norm(), f64::sqrt(5.0));
    /// ```
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.norm2())
    }

    /// Get the square of the norm if this complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.norm2(), 5.0);
    /// ```
    #[inline]
    pub fn norm2(&self) -> f64 {
        self.real * self.real + self.imag * self.imag
    }

    /// Get the conjugate of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.conj(), Complex::cartesian(2.0, -1.0));
    /// ```
    #[inline]
    pub fn conj(&self) -> Complex {
        Complex {
            real: self.real,
            imag: -self.imag
        }
    }

    /// Get only the imaginary part of the multiplication.
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let a = Complex::cartesian(3.0, -2.0);
    /// let b = Complex::cartesian(1.5, -3.0);
    ///
    /// assert_eq!(a.imag_mul(b), (a * b).imag());
    /// assert_eq!(b.imag_mul(a), (a * b).imag());
    /// ```
    #[inline]
    pub fn imag_mul(self, other: Complex) -> f64 {
        self.real() * other.imag() + self.imag() * other.real()
    }
}

impl Add<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn add(self, other: Complex) -> Complex {
        let x = self.real() + other.real();
        let y = self.imag() + other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Sub<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn sub(self, other: Complex) -> Complex {
        let x = self.real() - other.real();
        let y = self.imag() - other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Neg for Complex {
    type Output = Complex;

    #[inline]
    fn neg(self) -> Complex {
        Complex{
            real: -self.real,
            imag: -self.imag,
        }
    }
}

impl Mul<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn mul(self, other: Complex) -> Complex {
        let x = self.real() * other.real() - self.imag() * other.imag();
        let y = self.real() * other.imag() + self.imag() * other.real();
        Complex::cartesian(x, y)
    }
}

impl Mul<f64> for Complex {
    type Output = Complex;

    #[inline]
    fn mul(self, other: f64) -> Complex {
        Complex::cartesian(self.real() * other, self.imag() * other)
    }
}

impl Mul<Complex> for f64 {
    type Output = Complex;

    #[inline]
    fn mul(self, other: Complex) -> Complex {
        Complex::cartesian(self * other.real(), self * other.imag())
    }
}

impl Div<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn div(self, other: Complex) -> Complex {
        let r = other.norm2();
        let x = self.real() * other.real() + self.imag() * other.imag();
        let y = - self.real() * other.imag() + self.imag() * other.real();

        Complex::cartesian(x / r, y / r)
    }
}

impl Div<f64> for Complex {
    type Output = Complex;

    #[inline]
    fn div(self, other: f64) -> Complex {
        let norm = self.norm() / other;
        let phase = self.phase();
        Complex::polar(norm, phase)
    }
}

impl Zero for Complex {
    fn zero() -> Complex {
        Complex::cartesian(0.0, 0.0)
    }

    fn is_zero(&self) -> bool {
        self.norm2() == 0.0
    }
}

impl One for Complex {
    fn one() -> Complex {
        Complex::cartesian(1.0, 0.0)
    }
}

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

    use approx::ApproxEq;
    impl ApproxEq for Complex {
        type Epsilon = <f64 as ApproxEq>::Epsilon;

        fn default_epsilon() -> Self::Epsilon {
            f64::default_epsilon()
        }

        fn default_max_relative() -> Self::Epsilon {
            f64::default_max_relative()
        }

        fn default_max_ulps() -> u32 {
            f64::default_max_ulps()
        }

        fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
            f64::relative_eq(&self.real, &other.real, epsilon, max_relative) &&
            f64::relative_eq(&self.imag, &other.imag, epsilon, max_relative)
        }

        fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
            f64::ulps_eq(&self.real, &other.real, epsilon, max_ulps) &&
            f64::ulps_eq(&self.imag, &other.imag, epsilon, max_ulps)
        }
    }

    #[test]
    fn norm() {
        let c = Complex::polar(3.0, 5.0);
        assert_ulps_eq!(c.norm(), 3.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_ulps_eq!(c.norm(), 3.0);
    }

    #[test]
    fn phase() {
        // Phase is between 0 and 2π
        for &phase in &[-consts::PI, -3.1, -1.5, 0.0, 0.1, 2.0, 3.1] {
            let c = Complex::polar(1.0, phase);
            assert_ulps_eq!(c.phase(), phase);
        }

        let c = Complex::polar(1.0, -8.0);
        assert_ulps_eq!(c.phase(), -8.0 + 2.0 * consts::PI);

        let c = Complex::polar(1.0, 12.0);
        assert_ulps_eq!(c.phase(), 12.0 - 4.0 * consts::PI, max_ulps=10);

        let c = Complex::polar(1.0, consts::PI);
        assert_eq!(c.phase(), consts::PI);
        let c = Complex::polar(1.0, -consts::PI);
        assert_eq!(c.phase(), -consts::PI);

        let c = Complex::polar(3.0, 0.0);
        assert_eq!(c.phase(), 0.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_eq!(c.phase(), -consts::PI);
    }

    #[test]
    fn conj() {
        let c = Complex::cartesian(3.0, 5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, -5.0));

        let c = Complex::cartesian(3.0, -5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 5.0));

        let c = Complex::cartesian(3.0, 0.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 0.0));
    }

    #[test]
    fn cartesian() {
        let c = Complex::polar(1.0, 0.0);
        assert_ulps_eq!(c.real(), 1.0);
        assert_ulps_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::PI);
        assert_ulps_eq!(c.real(), -1.0);
        assert_ulps_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_2);
        assert_ulps_eq!(c.real(), 0.0);
        assert_ulps_eq!(c.imag(), 1.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_4);
        assert_ulps_eq!(c.real(), consts::FRAC_1_SQRT_2);
        assert_ulps_eq!(c.imag(), consts::FRAC_1_SQRT_2);

        let c = Complex::cartesian(consts::FRAC_1_SQRT_2, consts::FRAC_1_SQRT_2);
        assert_ulps_eq!(c.norm(), 1.0);
        assert_ulps_eq!(c.phase(), consts::FRAC_PI_4);
    }

    #[test]
    fn add() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a + b;

        assert_eq!(c.real(), a.real() + b.real());
        assert_eq!(c.imag(), a.imag() + b.imag());
    }

    #[test]
    fn sub() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a - b;

        assert_eq!(c.real(), a.real() - b.real());
        assert_eq!(c.imag(), a.imag() - b.imag());
    }

    #[test]
    fn neg() {
        let a = Complex::polar(2.0, 0.2);
        let c = -a;

        assert_ulps_eq!(c.norm(), a.norm());
        assert_ulps_eq!(c.phase(), a.phase() - consts::PI);

        assert_ulps_eq!(c.real(), - a.real());
        assert_ulps_eq!(c.imag(), - a.imag());
    }

    #[test]
    fn mul() {
        let a = Complex::polar(2.0, 1.4);
        let b = Complex::polar(1.0, 0.5);
        let c = a * b;

        assert_eq!(c.norm(), a.norm() * b.norm());
        assert_eq!(c.phase(), a.phase() + b.phase());

        let c = 3.0 * a;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = a * 3.0;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = -2.0 * a;
        assert_eq!(c.norm(), 2.0 * a.norm());
        assert_ulps_eq!(c.phase(), a.phase() - consts::PI);
    }

    #[test]
    fn div() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a / b;

        assert_eq!(c.norm(), a.norm() / b.norm());
        assert_eq!(c.phase(), a.phase() - b.phase());

        let c = a / 3.0;
        assert_eq!(c.norm(), a.norm() / 3.0);
        assert_ulps_eq!(c.phase(), a.phase());

        let c = a / (-2.0);
        assert_eq!(c.norm(), a.norm() / 2.0);
        assert_ulps_eq!(c.phase(), a.phase() - consts::PI);
    }
}
<commit_msg>Remove unused Complex::imag_mul<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! Complex type
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::f64;

use types::{Zero, One};

#[derive(Debug, Clone, Copy, PartialEq, Default)]
/// Complex number, with double precision real and imaginary parts.
///
/// `Complex` implements all the usual arithmetic operations:
///
/// ```
/// # use lumol::types::Complex;
///
/// let w = Complex::cartesian(-1.0, 0.5);
/// let z = Complex::cartesian(4.0, 2.0);
///
/// // Addition
/// let c = w + z;
/// assert_eq!(c, Complex::cartesian(3.0, 2.5));
///
/// // Subtraction
/// let c = w - z;
/// assert_eq!(c, Complex::cartesian(-5.0, -1.5));
///
/// // Multiplication
/// let c = w * z;
/// assert_eq!(c, Complex::cartesian(-5.0, 0.0));
///
/// let c = 42.0 * w;
/// assert_eq!(c, Complex::cartesian(-42.0, 21.0));
///
/// // Division
/// let c = z / 2.0;
/// assert_eq!(c, Complex::cartesian(2.0, 1.0));
/// ```
pub struct Complex {
    /// Real part of the complex
    real: f64,
    /// Imaginary part of the complex
    imag: f64,
}

impl Complex {
    /// Create a new `Complex` from a norm `r` and a phase `phi` in radians.
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// # use std::f64;
    /// let z = Complex::polar(3.0, f64::consts::PI);
    /// assert_eq!(z.norm(), 3.0);
    /// ```
    pub fn polar(r: f64, phi: f64) -> Complex {
        Complex{
            real: r * f64::cos(phi),
            imag: r * f64::sin(phi)
        }
    }

    /// Create a complex from Cartesian coordinates
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.real(), 3.0);
    /// assert_eq!(z.imag(), -2.0);
    /// ```
    pub fn cartesian(x: f64, y: f64) -> Complex {
        Complex{
            real: x,
            imag: y,
        }
    }

    /// Get the real part of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.real(), 3.0);
    /// ```
    #[inline]
    pub fn real(&self) -> f64 {
        self.real
    }

    /// Get the imaginary part of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(3.0, -2.0);
    /// assert_eq!(z.imag(), -2.0);
    /// ```
    #[inline]
    pub fn imag(&self) -> f64 {
        self.imag
    }

    /// Get the phase of the complex in the [-π, π) interval
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::polar(2.0, 0.3);
    /// assert_eq!(z.phase(), 0.3);
    /// ```
    #[inline]
    pub fn phase(&self) -> f64 {
        f64::atan2(self.imag, self.real)
    }

    /// Get the norm of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// # use std::f64;
    /// let z = Complex::polar(2.0, 0.3);
    /// assert_eq!(z.norm(), 2.0);
    ///
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.norm(), f64::sqrt(5.0));
    /// ```
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.norm2())
    }

    /// Get the square of the norm if this complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.norm2(), 5.0);
    /// ```
    #[inline]
    pub fn norm2(&self) -> f64 {
        self.real * self.real + self.imag * self.imag
    }

    /// Get the conjugate of the complex
    /// # Examples
    /// ```
    /// # use lumol::types::Complex;
    /// let z = Complex::cartesian(2.0, 1.0);
    /// assert_eq!(z.conj(), Complex::cartesian(2.0, -1.0));
    /// ```
    #[inline]
    pub fn conj(&self) -> Complex {
        Complex {
            real: self.real,
            imag: -self.imag
        }
    }
}

impl Add<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn add(self, other: Complex) -> Complex {
        let x = self.real() + other.real();
        let y = self.imag() + other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Sub<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn sub(self, other: Complex) -> Complex {
        let x = self.real() - other.real();
        let y = self.imag() - other.imag();
        return Complex::cartesian(x, y);
    }
}

impl Neg for Complex {
    type Output = Complex;

    #[inline]
    fn neg(self) -> Complex {
        Complex{
            real: -self.real,
            imag: -self.imag,
        }
    }
}

impl Mul<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn mul(self, other: Complex) -> Complex {
        let x = self.real() * other.real() - self.imag() * other.imag();
        let y = self.real() * other.imag() + self.imag() * other.real();
        Complex::cartesian(x, y)
    }
}

impl Mul<f64> for Complex {
    type Output = Complex;

    #[inline]
    fn mul(self, other: f64) -> Complex {
        Complex::cartesian(self.real() * other, self.imag() * other)
    }
}

impl Mul<Complex> for f64 {
    type Output = Complex;

    #[inline]
    fn mul(self, other: Complex) -> Complex {
        Complex::cartesian(self * other.real(), self * other.imag())
    }
}

impl Div<Complex> for Complex {
    type Output = Complex;

    #[inline]
    fn div(self, other: Complex) -> Complex {
        let r = other.norm2();
        let x = self.real() * other.real() + self.imag() * other.imag();
        let y = - self.real() * other.imag() + self.imag() * other.real();

        Complex::cartesian(x / r, y / r)
    }
}

impl Div<f64> for Complex {
    type Output = Complex;

    #[inline]
    fn div(self, other: f64) -> Complex {
        let norm = self.norm() / other;
        let phase = self.phase();
        Complex::polar(norm, phase)
    }
}

impl Zero for Complex {
    fn zero() -> Complex {
        Complex::cartesian(0.0, 0.0)
    }

    fn is_zero(&self) -> bool {
        self.norm2() == 0.0
    }
}

impl One for Complex {
    fn one() -> Complex {
        Complex::cartesian(1.0, 0.0)
    }
}

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

    use approx::ApproxEq;
    impl ApproxEq for Complex {
        type Epsilon = <f64 as ApproxEq>::Epsilon;

        fn default_epsilon() -> Self::Epsilon {
            f64::default_epsilon()
        }

        fn default_max_relative() -> Self::Epsilon {
            f64::default_max_relative()
        }

        fn default_max_ulps() -> u32 {
            f64::default_max_ulps()
        }

        fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
            f64::relative_eq(&self.real, &other.real, epsilon, max_relative) &&
            f64::relative_eq(&self.imag, &other.imag, epsilon, max_relative)
        }

        fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
            f64::ulps_eq(&self.real, &other.real, epsilon, max_ulps) &&
            f64::ulps_eq(&self.imag, &other.imag, epsilon, max_ulps)
        }
    }

    #[test]
    fn norm() {
        let c = Complex::polar(3.0, 5.0);
        assert_ulps_eq!(c.norm(), 3.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_ulps_eq!(c.norm(), 3.0);
    }

    #[test]
    fn phase() {
        // Phase is between 0 and 2π
        for &phase in &[-consts::PI, -3.1, -1.5, 0.0, 0.1, 2.0, 3.1] {
            let c = Complex::polar(1.0, phase);
            assert_ulps_eq!(c.phase(), phase);
        }

        let c = Complex::polar(1.0, -8.0);
        assert_ulps_eq!(c.phase(), -8.0 + 2.0 * consts::PI);

        let c = Complex::polar(1.0, 12.0);
        assert_ulps_eq!(c.phase(), 12.0 - 4.0 * consts::PI, max_ulps=10);

        let c = Complex::polar(1.0, consts::PI);
        assert_eq!(c.phase(), consts::PI);
        let c = Complex::polar(1.0, -consts::PI);
        assert_eq!(c.phase(), -consts::PI);

        let c = Complex::polar(3.0, 0.0);
        assert_eq!(c.phase(), 0.0);

        let c = Complex::polar(-3.0, 0.0);
        assert_eq!(c.phase(), -consts::PI);
    }

    #[test]
    fn conj() {
        let c = Complex::cartesian(3.0, 5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, -5.0));

        let c = Complex::cartesian(3.0, -5.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 5.0));

        let c = Complex::cartesian(3.0, 0.0);
        assert_eq!(c.conj(), Complex::cartesian(3.0, 0.0));
    }

    #[test]
    fn cartesian() {
        let c = Complex::polar(1.0, 0.0);
        assert_ulps_eq!(c.real(), 1.0);
        assert_ulps_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::PI);
        assert_ulps_eq!(c.real(), -1.0);
        assert_ulps_eq!(c.imag(), 0.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_2);
        assert_ulps_eq!(c.real(), 0.0);
        assert_ulps_eq!(c.imag(), 1.0);

        let c = Complex::polar(1.0, consts::FRAC_PI_4);
        assert_ulps_eq!(c.real(), consts::FRAC_1_SQRT_2);
        assert_ulps_eq!(c.imag(), consts::FRAC_1_SQRT_2);

        let c = Complex::cartesian(consts::FRAC_1_SQRT_2, consts::FRAC_1_SQRT_2);
        assert_ulps_eq!(c.norm(), 1.0);
        assert_ulps_eq!(c.phase(), consts::FRAC_PI_4);
    }

    #[test]
    fn add() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a + b;

        assert_eq!(c.real(), a.real() + b.real());
        assert_eq!(c.imag(), a.imag() + b.imag());
    }

    #[test]
    fn sub() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a - b;

        assert_eq!(c.real(), a.real() - b.real());
        assert_eq!(c.imag(), a.imag() - b.imag());
    }

    #[test]
    fn neg() {
        let a = Complex::polar(2.0, 0.2);
        let c = -a;

        assert_ulps_eq!(c.norm(), a.norm());
        assert_ulps_eq!(c.phase(), a.phase() - consts::PI);

        assert_ulps_eq!(c.real(), - a.real());
        assert_ulps_eq!(c.imag(), - a.imag());
    }

    #[test]
    fn mul() {
        let a = Complex::polar(2.0, 1.4);
        let b = Complex::polar(1.0, 0.5);
        let c = a * b;

        assert_eq!(c.norm(), a.norm() * b.norm());
        assert_eq!(c.phase(), a.phase() + b.phase());

        let c = 3.0 * a;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = a * 3.0;
        assert_eq!(c.norm(), 3.0 * a.norm());
        assert_eq!(c.phase(), a.phase());

        let c = -2.0 * a;
        assert_eq!(c.norm(), 2.0 * a.norm());
        assert_ulps_eq!(c.phase(), a.phase() - consts::PI);
    }

    #[test]
    fn div() {
        let a = Complex::polar(2.0, 0.2);
        let b = Complex::polar(1.0, 0.5);
        let c = a / b;

        assert_eq!(c.norm(), a.norm() / b.norm());
        assert_eq!(c.phase(), a.phase() - b.phase());

        let c = a / 3.0;
        assert_eq!(c.norm(), a.norm() / 3.0);
        assert_ulps_eq!(c.phase(), a.phase());

        let c = a / (-2.0);
        assert_eq!(c.norm(), a.norm() / 2.0);
        assert_ulps_eq!(c.phase(), a.phase() - consts::PI);
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, Clone, PartialEq)]
pub enum SimilarityModel {
    TfIdf,
    Bm25{k1: f64, b: f64},
}

/// tf(term_frequency) = log(term_frequency + 1.0) + 1.0
#[inline]
fn tf(term_frequency: u32) -> f64 {
    (term_frequency as f64 + 1.0f64).ln() + 1.0
}

/// idf(term_docs, total_docs) = log((total_docs + 1.0) / (term_docs + 1.0)) + 1.0
#[inline]
fn idf(term_docs: u64, total_docs: u64) -> f64 {
    ((total_docs as f64 + 1.0) / (term_docs as f64 + 1.0)).ln() + 1.0
}

impl SimilarityModel {
    pub fn score(&self, term_frequency: u32, length: f64, total_tokens: u64, total_docs: u64, total_docs_with_term: u64) -> f64 {
        match *self {
            SimilarityModel::TfIdf => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);

                tf * idf
            }
            SimilarityModel::Bm25{k1, b} => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);
                let average_length = (total_tokens as f64 + 1.0f64) / (total_docs as f64 + 1.0f64);

                idf * (k1 + 1.0) * (tf / (tf + (k1 * ((1.0 - b) + b * length.sqrt() / average_length.sqrt())) + 1.0f64))
            }
        }
    }
}

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

    #[test]
    fn test_tf_idf_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(2, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 5));
    }

    #[test]
    fn test_tf_idf_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 10));
    }

    #[test]
    fn test_tf_idf_field_length_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 100, 100, 20, 5) == similarity.score(1, 40, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_total_tokens_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40, 1000, 20, 5) == similarity.score(1, 40, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_handles_zeros() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(0, 0, 0, 0, 0).is_finite());
    }

    #[test]
    fn test_bm25_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(2, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 5));
    }

    #[test]
    fn test_bm25_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40, 100, 10, 5) > similarity.score(1, 40, 100, 10, 10));
    }

    #[test]
    fn test_bm25_lower_field_length_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40, 100, 20, 5) > similarity.score(1, 100, 100, 20, 5));
    }

    #[test]
    fn test_bm25_higher_total_tokens_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40, 1000, 20, 5) > similarity.score(1, 40, 100, 20, 5));
    }

    #[test]
    fn test_bm25_handles_zeros() {
        let similarity = SimilarityModel::Bm25 {
            k1: 0.0,
            b: 0.0,
        };

        assert!(similarity.score(0, 0, 0, 0, 0).is_finite());
    }
}
<commit_msg>Fixed similarity tests<commit_after>#[derive(Debug, Clone, PartialEq)]
pub enum SimilarityModel {
    TfIdf,
    Bm25{k1: f64, b: f64},
}

/// tf(term_frequency) = log(term_frequency + 1.0) + 1.0
#[inline]
fn tf(term_frequency: u32) -> f64 {
    (term_frequency as f64 + 1.0f64).ln() + 1.0
}

/// idf(term_docs, total_docs) = log((total_docs + 1.0) / (term_docs + 1.0)) + 1.0
#[inline]
fn idf(term_docs: u64, total_docs: u64) -> f64 {
    ((total_docs as f64 + 1.0) / (term_docs as f64 + 1.0)).ln() + 1.0
}

impl SimilarityModel {
    pub fn score(&self, term_frequency: u32, length: f64, total_tokens: u64, total_docs: u64, total_docs_with_term: u64) -> f64 {
        match *self {
            SimilarityModel::TfIdf => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);

                tf * idf
            }
            SimilarityModel::Bm25{k1, b} => {
                let tf = tf(term_frequency);
                let idf = idf(total_docs_with_term, total_docs);
                let average_length = (total_tokens as f64 + 1.0f64) / (total_docs as f64 + 1.0f64);

                idf * (k1 + 1.0) * (tf / (tf + (k1 * ((1.0 - b) + b * length.sqrt() / average_length.sqrt())) + 1.0f64))
            }
        }
    }
}

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

    #[test]
    fn test_tf_idf_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(2, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 5));
    }

    #[test]
    fn test_tf_idf_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 10));
    }

    #[test]
    fn test_tf_idf_field_length_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 100.0, 100, 20, 5) == similarity.score(1, 40.0, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_total_tokens_doesnt_affect_score() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(1, 40.0, 1000, 20, 5) == similarity.score(1, 40.0, 100, 20, 5));
    }

    #[test]
    fn test_tf_idf_handles_zeros() {
        let similarity = SimilarityModel::TfIdf;

        assert!(similarity.score(0, 0.0, 0, 0, 0).is_finite());
    }

    #[test]
    fn test_bm25_higher_term_freq_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(2, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 5));
    }

    #[test]
    fn test_bm25_lower_term_docs_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40.0, 100, 10, 5) > similarity.score(1, 40.0, 100, 10, 10));
    }

    #[test]
    fn test_bm25_lower_field_length_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40.0, 100, 20, 5) > similarity.score(1, 100.0, 100, 20, 5));
    }

    #[test]
    fn test_bm25_higher_total_tokens_increases_score() {
        let similarity = SimilarityModel::Bm25 {
            k1: 1.2,
            b: 0.75,
        };

        assert!(similarity.score(1, 40.0, 1000, 20, 5) > similarity.score(1, 40.0, 100, 20, 5));
    }

    #[test]
    fn test_bm25_handles_zeros() {
        let similarity = SimilarityModel::Bm25 {
            k1: 0.0,
            b: 0.0,
        };

        assert!(similarity.score(0, 0.0, 0, 0, 0).is_finite());
    }
}
<|endoftext|>


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

// Utility file to provide a fake clock object representing current time, and a timer driven by
// that time.

use std::time::{Duration, Instant};

use super::Event;
use crate::descriptor::AsRawDescriptor;

#[derive(Debug, Copy, Clone)]
pub struct Clock(Instant);
impl Clock {
    pub fn new() -> Self {
        Clock(Instant::now())
    }

    pub fn now(&self) -> Self {
        Clock(Instant::now())
    }

    pub fn duration_since(&self, earlier: &Self) -> Duration {
        self.0.duration_since(earlier.0)
    }

    pub fn elapsed(&self) -> Duration {
        self.0.elapsed()
    }

    pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
        Some(Clock(self.0.checked_sub(duration)?))
    }
}

impl Default for Clock {
    fn default() -> Self {
        Self::new()
    }
}

const NS_PER_SEC: u64 = 1_000_000_000;
/// A fake clock that can be used in tests to give exact control over the time.
/// For a code example, see the tests in sys_util/src/timer.rs.
#[derive(Debug)]
pub struct FakeClock {
    ns_since_epoch: u64,
    deadlines: Vec<(u64, Event)>,
}

impl FakeClock {
    pub fn new() -> Self {
        FakeClock {
            ns_since_epoch: 1_547_163_599 * NS_PER_SEC,
            deadlines: Vec::new(),
        }
    }

    /// Get the current time, according to this clock.
    pub fn now(&self) -> Self {
        FakeClock {
            ns_since_epoch: self.ns_since_epoch,
            deadlines: Vec::new(),
        }
    }

    ///  Get the current time in ns, according to this clock.
    pub fn nanos(&self) -> u64 {
        self.ns_since_epoch
    }

    /// Get the duration since |earlier|, assuming that earlier < self.
    pub fn duration_since(&self, earlier: &Self) -> Duration {
        let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch;
        Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32)
    }

    /// Get the time that has elapsed since this clock was made. Always returns 0 on a FakeClock.
    pub fn elapsed(&self) -> Duration {
        self.now().duration_since(self)
    }

    pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
        Some(FakeClock {
            ns_since_epoch: self
                .ns_since_epoch
                .checked_sub(duration.as_nanos() as u64)?,
            deadlines: Vec::new(),
        })
    }

    /// Register the event descriptor for a notification when self's time is |deadline_ns|.
    /// Drop any existing events registered to the same raw descriptor.
    pub fn add_event(&mut self, deadline_ns: u64, descriptor: Event) {
        self.deadlines.retain(|(_, old_descriptor)| {
            descriptor.as_raw_descriptor() != old_descriptor.as_raw_descriptor()
        });
        self.deadlines.push((deadline_ns, descriptor));
    }

    pub fn add_ns(&mut self, ns: u64) {
        self.ns_since_epoch += ns;
        let time = self.ns_since_epoch;
        self.deadlines.retain(|(ns, descriptor)| {
            let expired = *ns <= time;
            if expired {
                descriptor.write(1).unwrap();
            }
            !expired
        });
    }
}

impl Default for FakeClock {
    fn default() -> Self {
        Self::new()
    }
}
<commit_msg>base: fix Event import in clock<commit_after>// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Utility file to provide a fake clock object representing current time, and a timer driven by
// that time.

use std::time::{Duration, Instant};

use crate::{descriptor::AsRawDescriptor, Event};

#[derive(Debug, Copy, Clone)]
pub struct Clock(Instant);
impl Clock {
    pub fn new() -> Self {
        Clock(Instant::now())
    }

    pub fn now(&self) -> Self {
        Clock(Instant::now())
    }

    pub fn duration_since(&self, earlier: &Self) -> Duration {
        self.0.duration_since(earlier.0)
    }

    pub fn elapsed(&self) -> Duration {
        self.0.elapsed()
    }

    pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
        Some(Clock(self.0.checked_sub(duration)?))
    }
}

impl Default for Clock {
    fn default() -> Self {
        Self::new()
    }
}

const NS_PER_SEC: u64 = 1_000_000_000;
/// A fake clock that can be used in tests to give exact control over the time.
/// For a code example, see the tests in sys_util/src/timer.rs.
#[derive(Debug)]
pub struct FakeClock {
    ns_since_epoch: u64,
    deadlines: Vec<(u64, Event)>,
}

impl FakeClock {
    pub fn new() -> Self {
        FakeClock {
            ns_since_epoch: 1_547_163_599 * NS_PER_SEC,
            deadlines: Vec::new(),
        }
    }

    /// Get the current time, according to this clock.
    pub fn now(&self) -> Self {
        FakeClock {
            ns_since_epoch: self.ns_since_epoch,
            deadlines: Vec::new(),
        }
    }

    ///  Get the current time in ns, according to this clock.
    pub fn nanos(&self) -> u64 {
        self.ns_since_epoch
    }

    /// Get the duration since |earlier|, assuming that earlier < self.
    pub fn duration_since(&self, earlier: &Self) -> Duration {
        let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch;
        Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32)
    }

    /// Get the time that has elapsed since this clock was made. Always returns 0 on a FakeClock.
    pub fn elapsed(&self) -> Duration {
        self.now().duration_since(self)
    }

    pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
        Some(FakeClock {
            ns_since_epoch: self
                .ns_since_epoch
                .checked_sub(duration.as_nanos() as u64)?,
            deadlines: Vec::new(),
        })
    }

    /// Register the event descriptor for a notification when self's time is |deadline_ns|.
    /// Drop any existing events registered to the same raw descriptor.
    pub fn add_event(&mut self, deadline_ns: u64, descriptor: Event) {
        self.deadlines.retain(|(_, old_descriptor)| {
            descriptor.as_raw_descriptor() != old_descriptor.as_raw_descriptor()
        });
        self.deadlines.push((deadline_ns, descriptor));
    }

    pub fn add_ns(&mut self, ns: u64) {
        self.ns_since_epoch += ns;
        let time = self.ns_since_epoch;
        self.deadlines.retain(|(ns, descriptor)| {
            let expired = *ns <= time;
            if expired {
                descriptor.write(1).unwrap();
            }
            !expired
        });
    }
}

impl Default for FakeClock {
    fn default() -> Self {
        Self::new()
    }
}
<|endoftext|>


<commit_before>//! This contains the functions associated with the demorgan assist.
//! This assist transforms boolean expressions of the form `!a || !b` into
//! `!(a && b)`.
use hir::db::HirDatabase;
use ra_syntax::ast::{AstNode, BinExpr, BinOp, Expr, PrefixOp};
use ra_syntax::SyntaxNode;

use crate::{Assist, AssistCtx, AssistId};

// Return the opposite text for a given logical operator, if it makes sense
fn opposite_logic_op(kind: BinOp) -> Option<&'static str> {
    match kind {
        BinOp::BooleanOr => Some("&&"),
        BinOp::BooleanAnd => Some("||"),
        _ => None,
    }
}

// This function tries to undo unary negation, or inequality
fn undo_negation(node: SyntaxNode) -> Option<String> {
    match Expr::cast(node)? {
        Expr::BinExpr(bin) => match bin.op_kind()? {
            BinOp::NegatedEqualityTest => {
                let lhs = bin.lhs()?.syntax().text();
                let rhs = bin.rhs()?.syntax().text();
                Some(format!("{} == {}", lhs, rhs))
            }
            _ => None,
        },
        Expr::PrefixExpr(pe) => match pe.op_kind()? {
            PrefixOp::Not => {
                let child = pe.expr()?.syntax().text();
                Some(String::from(child))
            }
            _ => None,
        },
        _ => None,
    }
}

/// Assist for applying demorgan's law
///
/// This transforms expressions of the form `!l || !r` into `!(l && r)`.
/// This also works with `&&`. This assist can only be applied with the cursor
/// on either `||` or `&&`, with both operands being a negation of some kind.
/// This means something of the form `!x` or `x != y`.
pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
    let expr = ctx.node_at_offset::<BinExpr>()?;
    let op = expr.op_kind()?;
    let op_range = expr.op_token()?.text_range();
    let opposite_op = opposite_logic_op(op)?;
    let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
    if !cursor_in_range {
        return None;
    }
    let lhs = expr.lhs()?.syntax().clone();
    let lhs_range = lhs.text_range();
    let rhs = expr.rhs()?.syntax().clone();
    let rhs_range = rhs.text_range();
    let not_lhs = undo_negation(lhs)?;
    let not_rhs = undo_negation(rhs)?;

    ctx.add_action(AssistId("apply_demorgan"), "apply demorgan's law", |edit| {
        edit.target(op_range);
        edit.replace(op_range, opposite_op);
        edit.replace(lhs_range, format!("!({}", not_lhs));
        edit.replace(rhs_range, format!("{})", not_rhs));
    });
    ctx.build()
}

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

    use crate::helpers::{check_assist, check_assist_not_applicable};

    #[test]
    fn demorgan_turns_and_into_or() {
        check_assist(apply_demorgan, "fn f() { !x &&<|> !x }", "fn f() { !(x ||<|> x) }")
    }

    #[test]
    fn demorgan_turns_or_into_and() {
        check_assist(apply_demorgan, "fn f() { !x ||<|> !x }", "fn f() { !(x &&<|> x) }")
    }

    #[test]
    fn demorgan_removes_inequality() {
        check_assist(apply_demorgan, "fn f() { x != x ||<|> !x }", "fn f() { !(x == x &&<|> x) }")
    }

    #[test]
    fn demorgan_doesnt_apply_with_cursor_not_on_op() {
        check_assist_not_applicable(apply_demorgan, "fn f() { <|> !x || !x }")
    }

    #[test]
    fn demorgan_doesnt_apply_when_operands_arent_negated_already() {
        check_assist_not_applicable(apply_demorgan, "fn f() { x ||<|> x }")
    }
}
<commit_msg>[#1807] Refactor file structure<commit_after>//! This contains the functions associated with the demorgan assist.
//! This assist transforms boolean expressions of the form `!a || !b` into
//! `!(a && b)`.
use hir::db::HirDatabase;
use ra_syntax::ast::{self, AstNode};
use ra_syntax::SyntaxNode;

use crate::{Assist, AssistCtx, AssistId};

/// Assist for applying demorgan's law
///
/// This transforms expressions of the form `!l || !r` into `!(l && r)`.
/// This also works with `&&`. This assist can only be applied with the cursor
/// on either `||` or `&&`, with both operands being a negation of some kind.
/// This means something of the form `!x` or `x != y`.
pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
    let expr = ctx.node_at_offset::<ast::BinExpr>()?;
    let op = expr.op_kind()?;
    let op_range = expr.op_token()?.text_range();
    let opposite_op = opposite_logic_op(op)?;
    let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
    if !cursor_in_range {
        return None;
    }
    let lhs = expr.lhs()?.syntax().clone();
    let lhs_range = lhs.text_range();
    let rhs = expr.rhs()?.syntax().clone();
    let rhs_range = rhs.text_range();
    let not_lhs = undo_negation(lhs)?;
    let not_rhs = undo_negation(rhs)?;

    ctx.add_action(AssistId("apply_demorgan"), "apply demorgan's law", |edit| {
        edit.target(op_range);
        edit.replace(op_range, opposite_op);
        edit.replace(lhs_range, format!("!({}", not_lhs));
        edit.replace(rhs_range, format!("{})", not_rhs));
    });
    ctx.build()
}

// Return the opposite text for a given logical operator, if it makes sense
fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> {
    match kind {
        ast::BinOp::BooleanOr => Some("&&"),
        ast::BinOp::BooleanAnd => Some("||"),
        _ => None,
    }
}

// This function tries to undo unary negation, or inequality
fn undo_negation(node: SyntaxNode) -> Option<String> {
    match ast::Expr::cast(node)? {
        ast::Expr::BinExpr(bin) => match bin.op_kind()? {
            ast::BinOp::NegatedEqualityTest => {
                let lhs = bin.lhs()?.syntax().text();
                let rhs = bin.rhs()?.syntax().text();
                Some(format!("{} == {}", lhs, rhs))
            }
            _ => None,
        },
        ast::Expr::PrefixExpr(pe) => match pe.op_kind()? {
            ast::PrefixOp::Not => {
                let child = pe.expr()?.syntax().text();
                Some(String::from(child))
            }
            _ => None,
        },
        _ => None,
    }
}

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

    use crate::helpers::{check_assist, check_assist_not_applicable};

    #[test]
    fn demorgan_turns_and_into_or() {
        check_assist(apply_demorgan, "fn f() { !x &&<|> !x }", "fn f() { !(x ||<|> x) }")
    }

    #[test]
    fn demorgan_turns_or_into_and() {
        check_assist(apply_demorgan, "fn f() { !x ||<|> !x }", "fn f() { !(x &&<|> x) }")
    }

    #[test]
    fn demorgan_removes_inequality() {
        check_assist(apply_demorgan, "fn f() { x != x ||<|> !x }", "fn f() { !(x == x &&<|> x) }")
    }

    #[test]
    fn demorgan_doesnt_apply_with_cursor_not_on_op() {
        check_assist_not_applicable(apply_demorgan, "fn f() { <|> !x || !x }")
    }

    #[test]
    fn demorgan_doesnt_apply_when_operands_arent_negated_already() {
        check_assist_not_applicable(apply_demorgan, "fn f() { x ||<|> x }")
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

type SudokuCandidate = u64;
const SUDOKU_DIGIT_BASE: u32 = 10;
const SUDOKU_CANDIDATE_SIZE: usize = 9;
const SUDOKU_BOX_SIZE: usize = 3;
const SUDOKU_GROUP_SIZE: usize = 9;
const SUDOKU_CELL_SIZE: usize = 81;
const SUDOKU_ALL_CANDIDATES: SudokuCandidate = ((1 << SUDOKU_CANDIDATE_SIZE) - 1);

// Sudoku cell that contains candidates as a bitboard
#[derive(Clone, Copy)]
struct SudokuCell {
    candidates: SudokuCandidate
}

impl SudokuCell {
    fn new() -> SudokuCell {
        SudokuCell { candidates: SUDOKU_ALL_CANDIDATES }
    }

    fn to_string(&self) -> String {
        let mut line = String::new();
        for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
            if self.has_candidate(&candidate) {
                line.push_str(&(candidate+1).to_string());
            }
        }
        line
    }

    // Input '1'..'9'
    fn preset_candidate(&mut self, ch: char) {
        let code_digit_base = '1'.to_digit(SUDOKU_DIGIT_BASE).unwrap();
        match ch {
            '1'...'9' => {
                let number = (ch.to_digit(SUDOKU_DIGIT_BASE).unwrap() - code_digit_base) as SudokuCandidate;
                self.candidates = self.digit_to_candidate(&number);
            }
            _ => {}
        }
    }

    fn clear_candidate(&mut self) {
        self.candidates = 0;
    }

    // Input 0..8
    fn overwrite_candidate(&mut self, candidate: SudokuCandidate) {
        if self.count_candidates() > 1 {
            self.candidates = self.digit_to_candidate(&candidate);
        }
    }

    fn count_candidates(&self) -> usize {
        let f = |candidate| {
            if (self.candidates & self.digit_to_candidate(&candidate))
                != 0 { 1 } else { 0 } };
        (0..SUDOKU_CANDIDATE_SIZE as SudokuCandidate).fold(
            0, |sum, candidates| sum + f(candidates))
    }

    fn has_unique_candidate(&self) -> bool {
        // Check whether only one bit is set
        self.candidates > 0 && (self.candidates & (self.candidates - 1)) == 0
    }

    fn has_all_candidates(&self) -> bool {
        self.candidates == SUDOKU_ALL_CANDIDATES
    }

    // Input 0..8
    fn can_mask(&mut self, candidates: SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidates)) != 0
    }

    fn mask_candidate(&mut self, rhs: &SudokuCell) {
        if rhs.count_candidates() == 1 {
            self.candidates &= !rhs.candidates;
        }
    }

    fn merge_candidate(&mut self, rhs: &SudokuCell) {
        self.candidates |= rhs.candidates;
    }

    // Returns whether no candidates are merged
    fn merge_unique_candidate(&mut self, rhs: &SudokuCell) -> bool {
        if rhs.has_unique_candidate() {
            if (self.candidates & rhs.candidates) != 0 {
                return true;
            }
            self.candidates |= rhs.candidates;
        }
        false
    }

    // Inner methods
    // Input 0..8
    fn digit_to_candidate(&self, candidate: &SudokuCandidate) -> SudokuCandidate {
        (1 as SudokuCandidate) << candidate
    }

    // Input 0..8
    fn has_candidate(&self, candidate: &SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidate)) != 0
    }
}

// Generator for sudoku cellgroups
struct SudokuGroupGen {
    index: usize
}

impl SudokuGroupGen {
    fn new() -> SudokuGroupGen {
        SudokuGroupGen { index:0 }
    }

    fn next(&mut self) -> Option<Vec<usize>> {
        if self.index < SUDOKU_GROUP_SIZE {
            let lower = self.index * SUDOKU_GROUP_SIZE;
            let upper = (self.index + 1) * SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((lower..upper).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 2) {
            let column = self.index - SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((0..SUDOKU_GROUP_SIZE).map(|i| column + i * SUDOKU_GROUP_SIZE).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 3) {
            let box_index = self.index - SUDOKU_GROUP_SIZE * 2;
            let offset = (box_index % 3) * 3  + (box_index / 3) * SUDOKU_GROUP_SIZE * 3;
            let mut indexes : Vec<usize> = Vec::new();
            for row in 0..SUDOKU_BOX_SIZE {
                let x = (0..SUDOKU_BOX_SIZE).map(|column| row * SUDOKU_GROUP_SIZE + column + offset).collect::<Vec<_>>();
                indexes.extend(x);
            }
            self.index += 1;
            Some(indexes)
        } else {
            None
        }
    }
}

// Sudoku cell map
struct SudokuMap {
    cells : Vec<SudokuCell>
}

impl SudokuMap {
    fn new(line: &str) -> SudokuMap {
        let mut cells = vec![SudokuCell::new(); SUDOKU_CELL_SIZE];
        for (index, ch) in line.chars().enumerate() {
            cells[index].preset_candidate(ch);
        }
        SudokuMap { cells:cells }
    }

    fn to_string(&self) -> String {
        let mut full_text = String::new();

        for row in 0..SUDOKU_GROUP_SIZE {
            let mut line = String::new();
            for column in 0..SUDOKU_GROUP_SIZE {
                let index = row * SUDOKU_GROUP_SIZE + column;
                let cell_str = self.cells[index].to_string();
                line.push_str(&cell_str);
                line.push_str(":");
            }
            line.push_str("\n");
            full_text.push_str(&line);
        }
        full_text
    }

    fn solve(&mut self) -> bool {
        self.solve_from(0)
    }

    fn solve_from(&mut self, start_pos : usize) -> bool {
        self.filter_unique_candidates();
        if !self.is_consistent() {
            return false;
        }

        for i in start_pos..SUDOKU_CELL_SIZE {
            let count = self.cells[i].count_candidates();
            match count {
                0 => return false,
                1 => continue,
                _ => (),
            }

            for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
                let mut target_cell = self.cells[i].clone();
                if target_cell.can_mask(candidate) {
                    let mut new_map = SudokuMap::new("");
                    new_map.cells = self.cells.clone();
                    new_map.cells[i].overwrite_candidate(candidate);
                    if new_map.solve_from(start_pos + 1) {
                        self.cells = new_map.cells;
                        return true;
                    }
                }
            }
        }

        self.is_solved()
    }

    fn filter_unique_candidates(&mut self) {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            let froms = indexes.clone();
            for index in froms {
                let cell = self.cells[index];
                let targets = indexes.clone();
                for target in targets {
                    if target != index {
                        self.cells[target].mask_candidate(&cell);
                    }
                }
            }
        }
    }

    fn is_solved(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_solved(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_solved(&self, cell_indexes: Vec<usize>) -> bool {
        let mut sum = SudokuCell::new();
        let mut conflict = false;
        sum.clear_candidate();
        for cell_index in cell_indexes {
            conflict |= sum.merge_unique_candidate(&self.cells[cell_index]);
        }
        sum.has_all_candidates() && !conflict
    }

    fn is_consistent(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_consistent(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_consistent(&self, cell_indexes: Vec<usize>) -> bool {
        let mut all_candidates = SudokuCell::new();
        let mut unique_candidates = SudokuCell::new();
        let mut conflict = false;
        all_candidates.clear_candidate();
        unique_candidates.clear_candidate();

        for cell_index in cell_indexes {
            all_candidates.merge_candidate(&self.cells[cell_index]);
            conflict |= unique_candidates.merge_unique_candidate(&self.cells[cell_index]);
        }
        all_candidates.has_all_candidates() && !conflict
    }
}

fn main() {
    let stdin = io::stdin();

    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let mut sudoku_map = SudokuMap::new(&line);
        let result = sudoku_map.solve();
        let answer = sudoku_map.to_string();
        if result {
            println!("Solved\n{}", answer);
        } else {
            println!("Not solved\n{}", answer);
        }
    }
}
<commit_msg>Mask cells by unique candidates<commit_after>use std::io;
use std::io::prelude::*;
use std::collections::HashMap;

type SudokuCandidate = u64;
const SUDOKU_DIGIT_BASE: u32 = 10;
const SUDOKU_CANDIDATE_SIZE: usize = 9;
const SUDOKU_BOX_SIZE: usize = 3;
const SUDOKU_GROUP_SIZE: usize = 9;
const SUDOKU_CELL_SIZE: usize = 81;
const SUDOKU_ALL_CANDIDATES: SudokuCandidate = ((1 << SUDOKU_CANDIDATE_SIZE) - 1);

// Sudoku cell that contains candidates as a bitboard
#[derive(Clone, Copy)]
struct SudokuCell {
    candidates: SudokuCandidate
}

impl SudokuCell {
    fn new() -> SudokuCell {
        SudokuCell { candidates: SUDOKU_ALL_CANDIDATES }
    }

    fn to_string(&self) -> String {
        let mut line = String::new();
        for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
            if self.has_candidate(&candidate) {
                line.push_str(&(candidate+1).to_string());
            }
        }
        line
    }

    // Input '1'..'9'
    fn preset_candidate(&mut self, ch: char) {
        let code_digit_base = '1'.to_digit(SUDOKU_DIGIT_BASE).unwrap();
        match ch {
            '1'...'9' => {
                let number = (ch.to_digit(SUDOKU_DIGIT_BASE).unwrap() - code_digit_base) as SudokuCandidate;
                self.candidates = self.digit_to_candidate(&number);
            }
            _ => {}
        }
    }

    fn clear_candidate(&mut self) {
        self.candidates = 0;
    }

    // Input 0..8
    fn overwrite_candidate(&mut self, candidate: SudokuCandidate) {
        if self.count_candidates() > 1 {
            self.candidates = self.digit_to_candidate(&candidate);
        }
    }

    fn count_candidates(&self) -> usize {
        let f = |candidate| {
            if (self.candidates & self.digit_to_candidate(&candidate))
                != 0 { 1 } else { 0 } };
        (0..SUDOKU_CANDIDATE_SIZE as SudokuCandidate).fold(
            0, |sum, candidates| sum + f(candidates))
    }

    fn has_unique_candidate(&self) -> bool {
        // Check whether only one bit is set
        self.candidates > 0 && (self.candidates & (self.candidates - 1)) == 0
    }

    fn has_all_candidates(&self) -> bool {
        self.candidates == SUDOKU_ALL_CANDIDATES
    }

    // Input 0..8
    fn can_mask(&mut self, candidates: SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidates)) != 0
    }

    fn merge_candidate(&mut self, rhs: &SudokuCell) {
        self.candidates |= rhs.candidates;
    }

    // Returns whether no candidates are merged
    fn merge_unique_candidate(&mut self, rhs: &SudokuCell) -> bool {
        if rhs.has_unique_candidate() {
            if (self.candidates & rhs.candidates) != 0 {
                return true;
            }
            self.candidates |= rhs.candidates;
        }
        false
    }

    fn filter_by_candidates(&mut self, rhs: &SudokuCell) {
        if !self.has_unique_candidate() {
            self.candidates &= !rhs.candidates;
        }
    }

    // Inner methods
    // Input 0..8
    fn digit_to_candidate(&self, candidate: &SudokuCandidate) -> SudokuCandidate {
        (1 as SudokuCandidate) << candidate
    }

    // Input 0..8
    fn has_candidate(&self, candidate: &SudokuCandidate) -> bool {
        (self.candidates & self.digit_to_candidate(&candidate)) != 0
    }
}

// Generator for sudoku cellgroups
struct SudokuGroupGen {
    index: usize
}

impl SudokuGroupGen {
    fn new() -> SudokuGroupGen {
        SudokuGroupGen { index:0 }
    }

    fn next(&mut self) -> Option<Vec<usize>> {
        if self.index < SUDOKU_GROUP_SIZE {
            let lower = self.index * SUDOKU_GROUP_SIZE;
            let upper = (self.index + 1) * SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((lower..upper).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 2) {
            let column = self.index - SUDOKU_GROUP_SIZE;
            self.index += 1;
            Some((0..SUDOKU_GROUP_SIZE).map(|i| column + i * SUDOKU_GROUP_SIZE).collect::<Vec<_>>())
        } else if self.index < (SUDOKU_GROUP_SIZE * 3) {
            let box_index = self.index - SUDOKU_GROUP_SIZE * 2;
            let offset = (box_index % 3) * 3  + (box_index / 3) * SUDOKU_GROUP_SIZE * 3;
            let mut indexes : Vec<usize> = Vec::new();
            for row in 0..SUDOKU_BOX_SIZE {
                let x = (0..SUDOKU_BOX_SIZE).map(|column| row * SUDOKU_GROUP_SIZE + column + offset).collect::<Vec<_>>();
                indexes.extend(x);
            }
            self.index += 1;
            Some(indexes)
        } else {
            None
        }
    }
}

// Sudoku cell map
struct SudokuMap {
    cells : Vec<SudokuCell>,
    groups : HashMap<usize, Vec<Vec<usize>>>
}

impl SudokuMap {
    fn new(line: &str) -> SudokuMap {
        let mut cells = vec![SudokuCell::new(); SUDOKU_CELL_SIZE];
        let groups = SudokuMap::create_group_index_set();
        for (index, ch) in line.chars().enumerate() {
            cells[index].preset_candidate(ch);
        };
        SudokuMap { cells:cells, groups:groups }
    }

    // Set of sudoku cellgroups
    fn create_group_index_set() -> HashMap<usize, Vec<Vec<usize>>> {
        let mut groups = HashMap::new();
        for cell_index in 0..SUDOKU_CELL_SIZE {
            let mut group_candidates = Vec::new();
            let row_number = cell_index / SUDOKU_GROUP_SIZE;
            let row_lower = row_number * SUDOKU_GROUP_SIZE;
            let row_upper = (row_number + 1) * SUDOKU_GROUP_SIZE;
            let row = (row_lower..row_upper).collect::<Vec<_>>();
            group_candidates.push(row);

            let column_number = cell_index % SUDOKU_GROUP_SIZE;
            let column = (0..SUDOKU_GROUP_SIZE).map(|i| column_number + i * SUDOKU_GROUP_SIZE).collect::<Vec<_>>();
            group_candidates.push(column);

            let box_offset = (row_number / SUDOKU_BOX_SIZE) * SUDOKU_BOX_SIZE * SUDOKU_GROUP_SIZE +
                (column_number / SUDOKU_BOX_SIZE) * SUDOKU_BOX_SIZE;
            let mut cell_box = Vec::new();
            for row_offset in 0..SUDOKU_BOX_SIZE {
                let x = (0..SUDOKU_BOX_SIZE).map(|column_offset| row_offset * SUDOKU_GROUP_SIZE + column_offset + box_offset);
                cell_box.extend(x);
            }
            group_candidates.push(cell_box);
            groups.insert(cell_index, group_candidates);
        }
        groups
    }

    fn to_string(&self) -> String {
        let mut full_text = String::new();

        for row in 0..SUDOKU_GROUP_SIZE {
            let mut line = String::new();
            for column in 0..SUDOKU_GROUP_SIZE {
                let index = row * SUDOKU_GROUP_SIZE + column;
                let cell_str = self.cells[index].to_string();
                line.push_str(&cell_str);
                line.push_str(":");
            }
            line.push_str("\n");
            full_text.push_str(&line);
        }
        full_text
    }

    fn solve(&mut self) -> bool {
        self.solve_from(0)
    }

    fn solve_from(&mut self, start_pos : usize) -> bool {
        self.filter_unique_candidates();
        if self.is_solved() {
            return true;
        }
        if !self.is_consistent() {
            return false;
        }

        for i in start_pos..SUDOKU_CELL_SIZE {
            let count = self.cells[i].count_candidates();
            match count {
                0 => return false,
                1 => continue,
                _ => (),
            }

            for candidate in 0..(SUDOKU_CANDIDATE_SIZE as SudokuCandidate) {
                let mut target_cell = self.cells[i].clone();
                if target_cell.can_mask(candidate) {
                    let mut new_map = SudokuMap::new("");
                    new_map.cells = self.cells.clone();
                    new_map.cells[i].overwrite_candidate(candidate);
                    if new_map.solve_from(start_pos + 1) {
                        self.cells = new_map.cells;
                        return true;
                    }
                }
            }
        }

        self.is_solved()
    }

    fn filter_unique_candidates(&mut self) {
        for target_index in 0..SUDOKU_CELL_SIZE {
            let mut sum = SudokuCell::new();
            sum.clear_candidate();
            for group in self.groups[&target_index].iter() {
                for cell_index in group.iter() {
                    if *cell_index != target_index {
                        sum.merge_unique_candidate(&self.cells[*cell_index]);
                    }
                }
            }
            self.cells[target_index].filter_by_candidates(&sum);
        }
    }

    fn is_solved(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_solved(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_solved(&self, cell_indexes: Vec<usize>) -> bool {
        let mut sum = SudokuCell::new();
        let mut conflict = false;
        sum.clear_candidate();
        for cell_index in cell_indexes {
            conflict |= sum.merge_unique_candidate(&self.cells[cell_index]);
        }
        sum.has_all_candidates() && !conflict
    }

    fn is_consistent(&self) -> bool {
        let mut group_gen = SudokuGroupGen::new();
        while let Some(indexes) = group_gen.next() {
            if !self.is_group_consistent(indexes) {
                return false;
            }
        }
        true
    }

    fn is_group_consistent(&self, cell_indexes: Vec<usize>) -> bool {
        let mut all_candidates = SudokuCell::new();
        let mut unique_candidates = SudokuCell::new();
        let mut conflict = false;
        all_candidates.clear_candidate();
        unique_candidates.clear_candidate();

        for cell_index in cell_indexes {
            all_candidates.merge_candidate(&self.cells[cell_index]);
            conflict |= unique_candidates.merge_unique_candidate(&self.cells[cell_index]);
        }
        all_candidates.has_all_candidates() && !conflict
    }
}

fn main() {
    let stdin = io::stdin();

    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let mut sudoku_map = SudokuMap::new(&line);
        let result = sudoku_map.solve();
        let answer = sudoku_map.to_string();
        if result {
            println!("Solved\n{}", answer);
        } else {
            println!("Not solved\n{}", answer);
        }
    }
}
<|endoftext|>


<commit_before>extern crate secp256k1;
extern crate rand;
extern crate etcommon_bigint as bigint;

mod ecies;
mod util;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>rlpx: basic RLPx struct<commit_after>extern crate secp256k1;
extern crate rand;
extern crate etcommon_bigint as bigint;

mod ecies;
mod util;

use bigint::H512;
use util::pk2id;
use secp256k1::Secp256k1;
use secp256k1::key::{PublicKey, SecretKey};

#[derive(Debug, Clone)]
pub struct Capability {
    pub name: String,
    pub version: usize,
    pub length: usize,
}

pub struct RLPx {
    secret_key: SecretKey,
    id: H512,
    timeout: usize,
    max_peers: usize,
    client_id: String,
    capabilities: Vec<Capability>,
    listen_port: usize,
}

impl RLPx {
    pub fn with_options(
        secp: &Secp256k1, secret_key: SecretKey, capabilities: &[Capability],
        listen_port: usize, timeout: usize, max_peers: usize, client_id: String
    ) -> Self {
        Self {
            secret_key, timeout, max_peers, listen_port, client_id,
            capabilities: capabilities.into(),
            id: pk2id(secp, &PublicKey::from_secret_key(secp, &secret_key).unwrap())
        }
    }

    pub fn new(
        secp: &Secp256k1, secret_key: SecretKey, capabilities: &[Capability], listen_port: usize
    ) -> Self {
        Self::with_options(secp, secret_key, capabilities, listen_port,
                           10 * 1000, 10,
                           format!("Rust etclient/${}",
                                   option_env!("CARGO_PKG_VERSION").unwrap_or("0.0")))
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>