<commit_before>extern crate cargo;
extern crate cargotest;
extern crate hamcrest;

use std::str::FromStr;
use std::fmt;

use cargo::util::{Cfg, CfgExpr};
use cargotest::rustc_host;
use cargotest::support::registry::Package;
use cargotest::support::{project, execs};
use hamcrest::assert_that;

macro_rules! c {
    ($a:ident) => (
        Cfg::Name(stringify!($a).to_string())
    );
    ($a:ident = $e:expr) => (
        Cfg::KeyPair(stringify!($a).to_string(), $e.to_string())
    );
}

macro_rules! e {
    (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*]));
    (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*]));
    (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*))));
    (($($t:tt)*)) => (e!($($t)*));
    ($($t:tt)*) => (CfgExpr::Value(c!($($t)*)));
}

fn good<T>(s: &str, expected: T)
    where T: FromStr + PartialEq + fmt::Debug,
          T::Err: fmt::Display
{
    let c = match T::from_str(s) {
        Ok(c) => c,
        Err(e) => panic!("failed to parse `{}`: {}", s, e),
    };
    assert_eq!(c, expected);
}

fn bad<T>(s: &str, err: &str)
    where T: FromStr + fmt::Display, T::Err: fmt::Display
{
    let e = match T::from_str(s) {
        Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg),
        Err(e) => e.to_string(),
    };
    assert!(e.contains(err), "when parsing `{}`,\n\"{}\" not contained \
                              inside: {}", s, err, e);
}

#[test]
fn cfg_syntax() {
    good("foo", c!(foo));
    good("_bar", c!(_bar));
    good(" foo", c!(foo));
    good(" foo  ", c!(foo));
    good(" foo  = \"bar\"", c!(foo = "bar"));
    good("foo=\"\"", c!(foo = ""));
    good(" foo=\"3\"      ", c!(foo = "3"));
    good("foo = \"3 e\"", c!(foo = "3 e"));
}

#[test]
fn cfg_syntax_bad() {
    bad::<Cfg>("", "found nothing");
    bad::<Cfg>(" ", "found nothing");
    bad::<Cfg>("\t", "unexpected character");
    bad::<Cfg>("7", "unexpected character");
    bad::<Cfg>("=", "expected identifier");
    bad::<Cfg>(",", "expected identifier");
    bad::<Cfg>("(", "expected identifier");
    bad::<Cfg>("foo (", "malformed cfg value");
    bad::<Cfg>("bar =", "expected a string");
    bad::<Cfg>("bar = \"", "unterminated string");
    bad::<Cfg>("foo, bar", "malformed cfg value");
}

#[test]
fn cfg_expr() {
    good("foo", e!(foo));
    good("_bar", e!(_bar));
    good(" foo", e!(foo));
    good(" foo  ", e!(foo));
    good(" foo  = \"bar\"", e!(foo = "bar"));
    good("foo=\"\"", e!(foo = ""));
    good(" foo=\"3\"      ", e!(foo = "3"));
    good("foo = \"3 e\"", e!(foo = "3 e"));

    good("all()", e!(all()));
    good("all(a)", e!(all(a)));
    good("all(a, b)", e!(all(a, b)));
    good("all(a, )", e!(all(a)));
    good("not(a = \"b\")", e!(not(a = "b")));
    good("not(all(a))", e!(not(all(a))));
}

#[test]
fn cfg_expr_bad() {
    bad::<CfgExpr>(" ", "found nothing");
    bad::<CfgExpr>(" all", "expected `(`");
    bad::<CfgExpr>("all(a", "expected `)`");
    bad::<CfgExpr>("not", "expected `(`");
    bad::<CfgExpr>("not(a", "expected `)`");
    bad::<CfgExpr>("a = ", "expected a string");
    bad::<CfgExpr>("all(not())", "expected identifier");
    bad::<CfgExpr>("foo(a)", "consider using all() or any() explicitly");
}

#[test]
fn cfg_matches() {
    assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)]));
    assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)]));
    assert!(e!(any(foo, bar)).matches(&[c!(bar)]));
    assert!(e!(any(foo, bar)).matches(&[c!(foo)]));
    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
    assert!(e!(not(foo)).matches(&[c!(bar)]));
    assert!(e!(not(foo)).matches(&[]));
    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)]));
    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)]));

    assert!(!e!(foo).matches(&[]));
    assert!(!e!(foo).matches(&[c!(bar)]));
    assert!(!e!(foo).matches(&[c!(fo)]));
    assert!(!e!(any(foo)).matches(&[]));
    assert!(!e!(any(foo)).matches(&[c!(bar)]));
    assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)]));
    assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)]));
    assert!(!e!(all(foo, bar)).matches(&[c!(bar)]));
    assert!(!e!(all(foo, bar)).matches(&[c!(foo)]));
    assert!(!e!(all(foo, bar)).matches(&[]));
    assert!(!e!(not(bar)).matches(&[c!(bar)]));
    assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)]));
    assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)]));
}

#[test]
fn cfg_easy() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(unix)'.dependencies]
            b = { path = 'b' }
            [target."cfg(windows)".dependencies]
            b = { path = 'b' }
        "#)
        .file("src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build").arg("-v"),
                execs().with_status(0));
}

#[test]
fn dont_include() {
    let other_family = if cfg!(unix) {"windows"} else {"unix"};
    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg({})'.dependencies]
            b = {{ path = 'b' }}
        "#, other_family))
        .file("src/lib.rs", "")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build"),
                execs().with_status(0).with_stderr("\
[COMPILING] a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn works_through_the_registry() {
    Package::new("foo", "0.1.0").publish();
    Package::new("bar", "0.1.0")
            .target_dep("foo", "0.1.0", "cfg(unix)")
            .target_dep("foo", "0.1.0", "cfg(windows)")
            .publish();

    let p = project("a")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [dependencies]
            bar = "0.1.0"
        "#)
        .file("src/lib.rs", "extern crate bar;");

    assert_that(p.cargo_process("build"),
                execs().with_status(0).with_stderr("\
[UPDATING] registry [..]
[DOWNLOADING] [..]
[DOWNLOADING] [..]
[COMPILING] foo v0.1.0
[COMPILING] bar v0.1.0
[COMPILING] a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn ignore_version_from_other_platform() {
    let this_family = if cfg!(unix) {"unix"} else {"windows"};
    let other_family = if cfg!(unix) {"windows"} else {"unix"};
    Package::new("foo", "0.1.0").publish();
    Package::new("foo", "0.2.0").publish();

    let p = project("a")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg({})'.dependencies]
            foo = "0.1.0"

            [target.'cfg({})'.dependencies]
            foo = "0.2.0"
        "#, this_family, other_family))
        .file("src/lib.rs", "extern crate foo;");

    assert_that(p.cargo_process("build"),
                execs().with_status(0).with_stderr("\
[UPDATING] registry [..]
[DOWNLOADING] [..]
[COMPILING] foo v0.1.0
[COMPILING] a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn bad_target_spec() {
    let p = project("a")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(4)'.dependencies]
            bar = "0.1.0"
        "#)
        .file("src/lib.rs", "");

    assert_that(p.cargo_process("build"),
                execs().with_status(101).with_stderr("\
[ERROR] failed to parse manifest at `[..]`

Caused by:
  failed to parse `4` as a cfg expression

Caused by:
  unexpected character in cfg `4`, [..]
"));
}

#[test]
fn bad_target_spec2() {
    let p = project("a")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(foo =)'.dependencies]
            bar = "0.1.0"
        "#)
        .file("src/lib.rs", "");

    assert_that(p.cargo_process("build"),
                execs().with_status(101).with_stderr("\
[ERROR] failed to parse manifest at `[..]`

Caused by:
  failed to parse `foo =` as a cfg expression

Caused by:
  expected a string, found nothing
"));
}

#[test]
fn multiple_match_ok() {
    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(unix)'.dependencies]
            b = {{ path = 'b' }}
            [target.'cfg(target_family = "unix")'.dependencies]
            b = {{ path = 'b' }}
            [target."cfg(windows)".dependencies]
            b = {{ path = 'b' }}
            [target.'cfg(target_family = "windows")'.dependencies]
            b = {{ path = 'b' }}
            [target."cfg(any(windows, unix))".dependencies]
            b = {{ path = 'b' }}

            [target.{}.dependencies]
            b = {{ path = 'b' }}
        "#, rustc_host()))
        .file("src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build").arg("-v"),
                execs().with_status(0));
}

#[test]
fn any_ok() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target."cfg(any(windows, unix))".dependencies]
            b = { path = 'b' }
        "#)
        .file("src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build").arg("-v"),
                execs().with_status(0));
}
<commit_msg>tests/cfg: allow unused extern crates<commit_after>extern crate cargo;
extern crate cargotest;
extern crate hamcrest;

use std::str::FromStr;
use std::fmt;

use cargo::util::{Cfg, CfgExpr};
use cargotest::rustc_host;
use cargotest::support::registry::Package;
use cargotest::support::{project, execs};
use hamcrest::assert_that;

macro_rules! c {
    ($a:ident) => (
        Cfg::Name(stringify!($a).to_string())
    );
    ($a:ident = $e:expr) => (
        Cfg::KeyPair(stringify!($a).to_string(), $e.to_string())
    );
}

macro_rules! e {
    (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*]));
    (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*]));
    (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*))));
    (($($t:tt)*)) => (e!($($t)*));
    ($($t:tt)*) => (CfgExpr::Value(c!($($t)*)));
}

fn good<T>(s: &str, expected: T)
    where T: FromStr + PartialEq + fmt::Debug,
          T::Err: fmt::Display
{
    let c = match T::from_str(s) {
        Ok(c) => c,
        Err(e) => panic!("failed to parse `{}`: {}", s, e),
    };
    assert_eq!(c, expected);
}

fn bad<T>(s: &str, err: &str)
    where T: FromStr + fmt::Display, T::Err: fmt::Display
{
    let e = match T::from_str(s) {
        Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg),
        Err(e) => e.to_string(),
    };
    assert!(e.contains(err), "when parsing `{}`,\n\"{}\" not contained \
                              inside: {}", s, err, e);
}

#[test]
fn cfg_syntax() {
    good("foo", c!(foo));
    good("_bar", c!(_bar));
    good(" foo", c!(foo));
    good(" foo  ", c!(foo));
    good(" foo  = \"bar\"", c!(foo = "bar"));
    good("foo=\"\"", c!(foo = ""));
    good(" foo=\"3\"      ", c!(foo = "3"));
    good("foo = \"3 e\"", c!(foo = "3 e"));
}

#[test]
fn cfg_syntax_bad() {
    bad::<Cfg>("", "found nothing");
    bad::<Cfg>(" ", "found nothing");
    bad::<Cfg>("\t", "unexpected character");
    bad::<Cfg>("7", "unexpected character");
    bad::<Cfg>("=", "expected identifier");
    bad::<Cfg>(",", "expected identifier");
    bad::<Cfg>("(", "expected identifier");
    bad::<Cfg>("foo (", "malformed cfg value");
    bad::<Cfg>("bar =", "expected a string");
    bad::<Cfg>("bar = \"", "unterminated string");
    bad::<Cfg>("foo, bar", "malformed cfg value");
}

#[test]
fn cfg_expr() {
    good("foo", e!(foo));
    good("_bar", e!(_bar));
    good(" foo", e!(foo));
    good(" foo  ", e!(foo));
    good(" foo  = \"bar\"", e!(foo = "bar"));
    good("foo=\"\"", e!(foo = ""));
    good(" foo=\"3\"      ", e!(foo = "3"));
    good("foo = \"3 e\"", e!(foo = "3 e"));

    good("all()", e!(all()));
    good("all(a)", e!(all(a)));
    good("all(a, b)", e!(all(a, b)));
    good("all(a, )", e!(all(a)));
    good("not(a = \"b\")", e!(not(a = "b")));
    good("not(all(a))", e!(not(all(a))));
}

#[test]
fn cfg_expr_bad() {
    bad::<CfgExpr>(" ", "found nothing");
    bad::<CfgExpr>(" all", "expected `(`");
    bad::<CfgExpr>("all(a", "expected `)`");
    bad::<CfgExpr>("not", "expected `(`");
    bad::<CfgExpr>("not(a", "expected `)`");
    bad::<CfgExpr>("a = ", "expected a string");
    bad::<CfgExpr>("all(not())", "expected identifier");
    bad::<CfgExpr>("foo(a)", "consider using all() or any() explicitly");
}

#[test]
fn cfg_matches() {
    assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)]));
    assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)]));
    assert!(e!(any(foo, bar)).matches(&[c!(bar)]));
    assert!(e!(any(foo, bar)).matches(&[c!(foo)]));
    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
    assert!(e!(not(foo)).matches(&[c!(bar)]));
    assert!(e!(not(foo)).matches(&[]));
    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)]));
    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)]));

    assert!(!e!(foo).matches(&[]));
    assert!(!e!(foo).matches(&[c!(bar)]));
    assert!(!e!(foo).matches(&[c!(fo)]));
    assert!(!e!(any(foo)).matches(&[]));
    assert!(!e!(any(foo)).matches(&[c!(bar)]));
    assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)]));
    assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)]));
    assert!(!e!(all(foo, bar)).matches(&[c!(bar)]));
    assert!(!e!(all(foo, bar)).matches(&[c!(foo)]));
    assert!(!e!(all(foo, bar)).matches(&[]));
    assert!(!e!(not(bar)).matches(&[c!(bar)]));
    assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)]));
    assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)]));
}

#[test]
fn cfg_easy() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(unix)'.dependencies]
            b = { path = 'b' }
            [target."cfg(windows)".dependencies]
            b = { path = 'b' }
        "#)
        .file("src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build").arg("-v"),
                execs().with_status(0));
}

#[test]
fn dont_include() {
    let other_family = if cfg!(unix) {"windows"} else {"unix"};
    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg({})'.dependencies]
            b = {{ path = 'b' }}
        "#, other_family))
        .file("src/lib.rs", "")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build"),
                execs().with_status(0).with_stderr("\
[COMPILING] a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn works_through_the_registry() {
    Package::new("foo", "0.1.0").publish();
    Package::new("bar", "0.1.0")
            .target_dep("foo", "0.1.0", "cfg(unix)")
            .target_dep("foo", "0.1.0", "cfg(windows)")
            .publish();

    let p = project("a")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [dependencies]
            bar = "0.1.0"
        "#)
        .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate bar;");

    assert_that(p.cargo_process("build"),
                execs().with_status(0).with_stderr("\
[UPDATING] registry [..]
[DOWNLOADING] [..]
[DOWNLOADING] [..]
[COMPILING] foo v0.1.0
[COMPILING] bar v0.1.0
[COMPILING] a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn ignore_version_from_other_platform() {
    let this_family = if cfg!(unix) {"unix"} else {"windows"};
    let other_family = if cfg!(unix) {"windows"} else {"unix"};
    Package::new("foo", "0.1.0").publish();
    Package::new("foo", "0.2.0").publish();

    let p = project("a")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg({})'.dependencies]
            foo = "0.1.0"

            [target.'cfg({})'.dependencies]
            foo = "0.2.0"
        "#, this_family, other_family))
        .file("src/lib.rs", "#[allow(unused_extern_crates)] extern crate foo;");

    assert_that(p.cargo_process("build"),
                execs().with_status(0).with_stderr("\
[UPDATING] registry [..]
[DOWNLOADING] [..]
[COMPILING] foo v0.1.0
[COMPILING] a v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
"));
}

#[test]
fn bad_target_spec() {
    let p = project("a")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(4)'.dependencies]
            bar = "0.1.0"
        "#)
        .file("src/lib.rs", "");

    assert_that(p.cargo_process("build"),
                execs().with_status(101).with_stderr("\
[ERROR] failed to parse manifest at `[..]`

Caused by:
  failed to parse `4` as a cfg expression

Caused by:
  unexpected character in cfg `4`, [..]
"));
}

#[test]
fn bad_target_spec2() {
    let p = project("a")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(foo =)'.dependencies]
            bar = "0.1.0"
        "#)
        .file("src/lib.rs", "");

    assert_that(p.cargo_process("build"),
                execs().with_status(101).with_stderr("\
[ERROR] failed to parse manifest at `[..]`

Caused by:
  failed to parse `foo =` as a cfg expression

Caused by:
  expected a string, found nothing
"));
}

#[test]
fn multiple_match_ok() {
    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target.'cfg(unix)'.dependencies]
            b = {{ path = 'b' }}
            [target.'cfg(target_family = "unix")'.dependencies]
            b = {{ path = 'b' }}
            [target."cfg(windows)".dependencies]
            b = {{ path = 'b' }}
            [target.'cfg(target_family = "windows")'.dependencies]
            b = {{ path = 'b' }}
            [target."cfg(any(windows, unix))".dependencies]
            b = {{ path = 'b' }}

            [target.{}.dependencies]
            b = {{ path = 'b' }}
        "#, rustc_host()))
        .file("src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build").arg("-v"),
                execs().with_status(0));
}

#[test]
fn any_ok() {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [target."cfg(any(windows, unix))".dependencies]
            b = { path = 'b' }
        "#)
        .file("src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");
    assert_that(p.cargo_process("build").arg("-v"),
                execs().with_status(0));
}
<|endoftext|>


<commit_before>extern crate fitsio;
extern crate libc;
extern crate tempdir;

use std::ffi;
use std::ptr;
use fitsio::raw::*;

#[test]
fn raw_opening_an_existing_file() {
    let mut fptr = ptr::null_mut();
    let mut status = -1;
    let c_filename = ffi::CString::new("testdata/full_example.fits").unwrap();

    unsafe {
        ffopen(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               0,
               &mut status);
        ffclos(fptr, &mut status);
    }

    assert_eq!(status, 0);
}

#[test]
fn raw_creating_a_new_file() {
    // Set up the test filename
    let tdir = tempdir::TempDir::new("rust-fitsio-").unwrap();
    let filename = tdir.path().join("test.fits");
    assert!(!filename.exists());

    let mut fptr = ptr::null_mut();
    let mut status = 0;
    let c_filename = ffi::CString::new(filename.to_str().unwrap()).unwrap();

    unsafe {
        ffinit(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               &mut status);
    }

    assert!(filename.exists());
}

#[test]
fn getting_current_hdu_number() {
    let mut fptr = ptr::null_mut();
    let mut status = -1;
    let c_filename = ffi::CString::new("testdata/full_example.fits").unwrap();
    let mut hdu_num = -1;

    unsafe {
        ffopen(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               0,
               &mut status);
        ffghdn(fptr, &mut hdu_num);
        ffclos(fptr, &mut status);
    }

    assert_eq!(hdu_num, 1);
}

#[test]
fn changing_hdu_by_absolute_number() {
    let mut fptr = ptr::null_mut();
    let mut status = -1;
    let c_filename = ffi::CString::new("testdata/full_example.fits").unwrap();

    let mut hdu_type = 0;
    let mut hdu_num = 0;

    unsafe {
        ffopen(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               0,
               &mut status);
        ffmahd(fptr, 2, &mut hdu_type, &mut status);
        ffghdn(fptr, &mut hdu_num);
        ffclos(fptr, &mut status);
    }

    assert_eq!(hdu_num, 2);
}
<commit_msg>Add proposed usage example<commit_after>extern crate fitsio;
extern crate libc;
extern crate tempdir;

use std::ffi;
use std::ptr;
use fitsio::raw::*;

#[test]
fn raw_opening_an_existing_file() {
    let mut fptr = ptr::null_mut();
    let mut status = -1;
    let c_filename = ffi::CString::new("testdata/full_example.fits").unwrap();

    unsafe {
        ffopen(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               0,
               &mut status);
        ffclos(fptr, &mut status);
    }

    assert_eq!(status, 0);
}

#[test]
fn raw_creating_a_new_file() {
    // Set up the test filename
    let tdir = tempdir::TempDir::new("rust-fitsio-").unwrap();
    let filename = tdir.path().join("test.fits");
    assert!(!filename.exists());

    let mut fptr = ptr::null_mut();
    let mut status = 0;
    let c_filename = ffi::CString::new(filename.to_str().unwrap()).unwrap();

    unsafe {
        ffinit(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               &mut status);
    }

    assert!(filename.exists());
}

#[test]
fn getting_current_hdu_number() {
    let mut fptr = ptr::null_mut();
    let mut status = -1;
    let c_filename = ffi::CString::new("testdata/full_example.fits").unwrap();
    let mut hdu_num = -1;

    unsafe {
        ffopen(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               0,
               &mut status);
        ffghdn(fptr, &mut hdu_num);
        ffclos(fptr, &mut status);
    }

    assert_eq!(hdu_num, 1);
}

#[test]
fn changing_hdu_by_absolute_number() {
    let mut fptr = ptr::null_mut();
    let mut status = -1;
    let c_filename = ffi::CString::new("testdata/full_example.fits").unwrap();

    let mut hdu_type = 0;
    let mut hdu_num = 0;

    unsafe {
        ffopen(&mut fptr as *mut *mut fitsfile,
               c_filename.as_ptr(),
               0,
               &mut status);
        ffmahd(fptr, 2, &mut hdu_type, &mut status);
        ffghdn(fptr, &mut hdu_num);
        ffclos(fptr, &mut status);
    }

    assert_eq!(hdu_num, 2);
}

/*
#[test]
fn api_usage() {
    use fitsio::FitsFile;

    let mut f = FitsFile::open("testdata/full_example.fits");
    let mut primary_hdu = f.primary_hdu();
    let header = primary_hdu.header();
    let exposure_time: f32 = header["exposure"];
}
*/
<|endoftext|>


<commit_before>use crate::utils::get_test_path;
use cargo_tarpaulin::config::Config;
use cargo_tarpaulin::launch_tarpaulin;
use std::env;
use std::time::Duration;

mod compile_fail;
mod line_coverage;
mod doc_coverage;
mod utils;

pub fn check_percentage(project_name: &str, minimum_coverage: f64, has_lines: bool) {
    let mut config = Config::default();
    config.verbose = true;
    config.test_timeout = Duration::from_secs(60);
    let restore_dir = env::current_dir().unwrap();
    let test_dir = get_test_path(project_name);
    env::set_current_dir(&test_dir).unwrap();
    config.manifest = test_dir;
    config.manifest.push("Cargo.toml");

    let (res, _) = launch_tarpaulin(&config).unwrap();

    env::set_current_dir(restore_dir).unwrap();
    assert!(res.coverage_percentage() >= minimum_coverage);
    if has_lines {
        assert!(res.total_coverable() > 0);
    }
}

#[test]
fn incorrect_manifest_path() {
    let mut config = Config::default();
    config.manifest.push("__invalid_dir__");
    assert!(launch_tarpaulin(&config).is_err());
}

#[test]
fn proc_macro_link() {
    let mut config = Config::default();
    config.test_timeout = Duration::from_secs(60);
    let test_dir = get_test_path("proc_macro");
    config.manifest = test_dir.join("Cargo.toml");
    assert!(launch_tarpaulin(&config).is_ok());
}

#[test]
fn array_coverage() {
    check_percentage("arrays", 1.0f64, true);
}

#[test]
fn lets_coverage() {
    check_percentage("lets", 1.0f64, true);
}

#[test]
fn struct_expr_coverage() {
    check_percentage("structs", 1.0f64, true);
}

#[test]
fn ifelse_expr_coverage() {
    check_percentage("ifelse", 1.0f64, true);
}

#[test]
fn returns_expr_coverage() {
    check_percentage("returns", 1.0f64, true);
}

#[test]
fn loops_expr_coverage() {
    check_percentage("loops", 1.0f64, true);
}

#[test]
fn loops_assigns_coverage() {
    check_percentage("assigns", 1.0f64, true);
}

#[test]
fn paths_coverage() {
    check_percentage("paths", 1.0f64, true);
}

#[test]
#[ignore]
fn futures_coverage() {
    check_percentage("futures", 1.0f64, true);
}

#[test]
fn breaks_expr_coverage() {
    check_percentage("breaks", 1.0f64, true);
}

#[test]
fn continues_expr_coverage() {
    check_percentage("continues", 1.0f64, true);
}

#[test]
#[ignore]
fn method_calls_expr_coverage() {
    check_percentage("method_calls", 1.0f64, true);
}
<commit_msg>Add note about why the test is ignored<commit_after>use crate::utils::get_test_path;
use cargo_tarpaulin::config::Config;
use cargo_tarpaulin::launch_tarpaulin;
use std::env;
use std::time::Duration;

mod compile_fail;
mod line_coverage;
mod doc_coverage;
mod utils;

pub fn check_percentage(project_name: &str, minimum_coverage: f64, has_lines: bool) {
    let mut config = Config::default();
    config.verbose = true;
    config.test_timeout = Duration::from_secs(60);
    let restore_dir = env::current_dir().unwrap();
    let test_dir = get_test_path(project_name);
    env::set_current_dir(&test_dir).unwrap();
    config.manifest = test_dir;
    config.manifest.push("Cargo.toml");

    let (res, _) = launch_tarpaulin(&config).unwrap();

    env::set_current_dir(restore_dir).unwrap();
    assert!(res.coverage_percentage() >= minimum_coverage);
    if has_lines {
        assert!(res.total_coverable() > 0);
    }
}

#[test]
fn incorrect_manifest_path() {
    let mut config = Config::default();
    config.manifest.push("__invalid_dir__");
    assert!(launch_tarpaulin(&config).is_err());
}

#[test]
fn proc_macro_link() {
    let mut config = Config::default();
    config.test_timeout = Duration::from_secs(60);
    let test_dir = get_test_path("proc_macro");
    config.manifest = test_dir.join("Cargo.toml");
    assert!(launch_tarpaulin(&config).is_ok());
}

#[test]
fn array_coverage() {
    check_percentage("arrays", 1.0f64, true);
}

#[test]
fn lets_coverage() {
    check_percentage("lets", 1.0f64, true);
}

#[test]
fn struct_expr_coverage() {
    check_percentage("structs", 1.0f64, true);
}

#[test]
fn ifelse_expr_coverage() {
    check_percentage("ifelse", 1.0f64, true);
}

#[test]
fn returns_expr_coverage() {
    check_percentage("returns", 1.0f64, true);
}

#[test]
fn loops_expr_coverage() {
    check_percentage("loops", 1.0f64, true);
}

#[test]
fn loops_assigns_coverage() {
    check_percentage("assigns", 1.0f64, true);
}

#[test]
fn paths_coverage() {
    check_percentage("paths", 1.0f64, true);
}

#[test]
#[ignore]
fn futures_coverage() {
    check_percentage("futures", 1.0f64, true);
}

#[test]
fn breaks_expr_coverage() {
    check_percentage("breaks", 1.0f64, true);
}

#[test]
fn continues_expr_coverage() {
    check_percentage("continues", 1.0f64, true);
}

// This test is currently being ignored because it contains cases which Tarpaulin
// does not handle correctly yet. So, once (#136) [https://github.com/xd009642/tarpaulin/issues/136]
// is updated to resolve method call coverage and multi-line expressions, then
// the #[ignore] can be removed from this test.
#[test]
#[ignore]
fn method_calls_expr_coverage() {
    check_percentage("method_calls", 1.0f64, true);
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016 Skylor R. Schermer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! Defines elements, which encapsulates the component of a Palette that is
//! needed to provide a single color.
use color::Color;

use std::cell::{RefCell, Cell};
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use std::fmt;

/// A wrapper for ColorElement to enable building them into mutable tree
/// structures. Acts as a slot for a color element in the palette.
pub type PaletteSlot = Rc<PaletteElement>;

#[derive(Debug)]
pub struct PaletteElement {
	color_element: RefCell<ColorElement>,
	valid: Cell<bool>,
}

impl PaletteElement {
	pub fn new(element: ColorElement) -> Self {
		PaletteElement {
			color_element: RefCell::new(element),
			valid: Cell::new(false),
		}
	}

	pub fn get_color(&self) -> Option<Color> {
		if self.is_valid() {
			Some(self.color_element.borrow().get_color())
		} else {
			None
		}
	}

	pub fn restore(&mut self) {
		self.valid.set(true);
	}

	pub fn invalidate(&mut self) {
		self.valid.set(false);
	}

	pub fn is_valid(&self) -> bool {
		match &*self.color_element.borrow() {
			&ColorElement::FirstOrder {ref parent, ..} => {
					self.valid.set(parent.is_valid());
				},

			&ColorElement::SecondOrder {ref parents, ..} => {
					self.valid.set(parents.0.is_valid() && parents.1.is_valid());
				},
			_ => ()
		};
		self.valid.get()
	}
}

impl Deref for PaletteElement {
	type Target = RefCell<ColorElement>;
	fn deref(&self) -> &Self::Target {
		&self.color_element
	}
}

impl DerefMut for PaletteElement {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.color_element
	}
}

/// Encapsulates a Palette component for generating a single color.
pub enum ColorElement {
	/// An element with no dependencies. Generates the given color.
	ZerothOrder {
		/// The color to be generated by the ColorElement.
		color: Color
	},

	/// An element with a single dependency. Generates a color from another.
	FirstOrder {
		/// The function that builds the color from its dependencies.
		build: Box<Fn(&ColorElement) -> Color>,
		/// The PaletteSlot to use for building a color.
		parent: PaletteSlot,
	},

	/// An element with two dependencies. Generates a color from two others.
	SecondOrder {
		/// The function that builds the color from its dependencies.
		build: Box<Fn(&ColorElement, &ColorElement) -> Color>,
		/// The PaletteSlots to use for building a color.
		parents: (PaletteSlot, PaletteSlot),
	},
}

impl ColorElement {
	/// Returns the Color generated by the ColorElement.
	pub fn get_color(&self) -> Color {
		match *self {
			ColorElement::ZerothOrder {color}
				=> color,

			ColorElement::FirstOrder {ref build, ref parent}
				=> build(&*parent.borrow()),

			ColorElement::SecondOrder {ref build, ref parents}
				=> build(&*parents.0.borrow(), &*parents.1.borrow())
		}
	}

	/// Returns the element's dependency order.
	pub fn get_order(&self) -> u8 {
		match self {
			&ColorElement::ZerothOrder {..} => 0,
			&ColorElement::FirstOrder {..} => 1,
			&ColorElement::SecondOrder {..} => 2
		}
	}
}

impl fmt::Debug for ColorElement {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		match *self {
			ColorElement::ZerothOrder {ref color}
				=> write!(f,
					"ColorElement::ZerothOrder {{ color: {:?} }}",
					color),

			ColorElement::FirstOrder {ref parent, ..}
				=> write!(f,
					"ColorElement::FirstOrder {{ parent: {:?}, build: {:?} }}",
					parent,
					self.get_color()),

			ColorElement::SecondOrder {ref parents, ..}
				=> write!(f,
					"ColorElement::SecondOrder {{ parents: {:?}, build: {:?} }}",
					parents,
					self.get_color()),
		}
	}
}

impl Default for ColorElement {
	fn default() -> Self {
		ColorElement::ZerothOrder {color: Default::default()}
	}
}<commit_msg>DOCS: Added documentation to PaletteElement.<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016 Skylor R. Schermer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

//! Defines elements, which encapsulates the component of a Palette that is
//! needed to provide a single color.
use color::Color;

use std::cell::{RefCell, Cell};
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use std::fmt;

/// A 'slot' in the `Palette` in which to insert colors and related data.
/// Enables tree structured arrangements of `ColorElement`s.
pub type PaletteSlot = Rc<PaletteElement>;

/// A wrapper around a `ColorElement` for tracking its status and enabling
/// interior mutability.
#[derive(Debug)]
pub struct PaletteElement {
	/// The `ColorElement` being wrapped.
	color_element: RefCell<ColorElement>,
	/// The status of the `ColorElement`. An invalid status means that the
	/// `ColorElement` refers to something that is also invalid or not in the
	/// `Palette`.
	valid: Cell<bool>,
}

impl PaletteElement {
	/// Creates a new `PaletteElement` wrapping the given `ColorElement`.
	pub fn new(element: ColorElement) -> Self {
		PaletteElement {
			color_element: RefCell::new(element),
			valid: Cell::new(false),
		}
	}

	/// Returns the `Color` of the internal `ColorElement`, or `None` if it is
	/// invalid.
	pub fn get_color(&self) -> Option<Color> {
		if self.is_valid() {
			Some(self.color_element.borrow().get_color())
		} else {
			None
		}
	}

	/// Makes the internal `ColorElement` valid. This will only persist if all
	/// of this `ColorElement`'s referants are also valid and present in the
	/// `Palette`.
	pub fn restore(&mut self) {
		self.valid.set(true);
	}

	/// Makes the internal `ColorElement` invalid. This will always persist, but
	/// it will not remove the `PaletteSlot` from the `Palette`.
	pub fn invalidate(&mut self) {
		self.valid.set(false);
	}

	/// Returns whether the internal `ColorElement` is valid. This function will
	/// check on and update the status of any of its referants.
	pub fn is_valid(&self) -> bool {
		match &*self.color_element.borrow() {
			&ColorElement::FirstOrder {ref parent, ..} => {
					self.valid.set(parent.is_valid());
				},

			&ColorElement::SecondOrder {ref parents, ..} => {
					self.valid.set(parents.0.is_valid() && parents.1.is_valid());
				},
			_ => ()
		};
		self.valid.get()
	}
}

impl Deref for PaletteElement {
	type Target = RefCell<ColorElement>;
	fn deref(&self) -> &Self::Target {
		&self.color_element
	}
}

impl DerefMut for PaletteElement {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.color_element
	}
}

/// Encapsulates a `Palette` component for generating a single `Color`.
pub enum ColorElement {
	/// An element with no dependencies. Generates the given `Color`.
	ZerothOrder {
		/// The color to be generated by the ColorElement.
		color: Color
	},

	/// An element with a single dependency. Generates a color from another.
	FirstOrder {
		/// The function that builds the color from its dependencies.
		build: Box<Fn(&ColorElement) -> Color>,
		/// The PaletteSlot to use for building a color.
		parent: PaletteSlot,
	},

	/// An element with two dependencies. Generates a color from two others.
	SecondOrder {
		/// The function that builds the color from its dependencies.
		build: Box<Fn(&ColorElement, &ColorElement) -> Color>,
		/// The PaletteSlots to use for building a color.
		parents: (PaletteSlot, PaletteSlot),
	},
}

impl ColorElement {
	/// Returns the Color generated by the ColorElement.
	pub fn get_color(&self) -> Color {
		match *self {
			ColorElement::ZerothOrder {color}
				=> color,

			ColorElement::FirstOrder {ref build, ref parent}
				=> build(&*parent.borrow()),

			ColorElement::SecondOrder {ref build, ref parents}
				=> build(&*parents.0.borrow(), &*parents.1.borrow())
		}
	}

	/// Returns the element's dependency order.
	pub fn get_order(&self) -> u8 {
		match self {
			&ColorElement::ZerothOrder {..} => 0,
			&ColorElement::FirstOrder {..} => 1,
			&ColorElement::SecondOrder {..} => 2
		}
	}
}

impl fmt::Debug for ColorElement {
	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		match *self {
			ColorElement::ZerothOrder {ref color}
				=> write!(f,
					"ColorElement::ZerothOrder {{ color: {:?} }}",
					color),

			ColorElement::FirstOrder {ref parent, ..}
				=> write!(f,
					"ColorElement::FirstOrder {{ parent: {:?}, build: {:?} }}",
					parent,
					self.get_color()),

			ColorElement::SecondOrder {ref parents, ..}
				=> write!(f,
					"ColorElement::SecondOrder {{ parents: {:?}, build: {:?} }}",
					parents,
					self.get_color()),
		}
	}
}

impl Default for ColorElement {
	fn default() -> Self {
		ColorElement::ZerothOrder {color: Default::default()}
	}
}<|endoftext|>


<commit_before>mod common;

use crate::common::assert_linked_with;
use linkify::LinkFinder;

#[test]
fn no_links() {
    assert_not_linked("");
    assert_not_linked("foo");
    assert_not_linked(":");
    assert_not_linked("://");
    assert_not_linked(":::");
}

#[test]
fn schemes() {
    assert_not_linked("://foo");
    assert_not_linked("1://foo");
    assert_not_linked("123://foo");
    assert_not_linked("+://foo");
    assert_not_linked("-://foo");
    assert_not_linked(".://foo");
    assert_not_linked("1abc://foo");
    assert_linked("a://foo", "|a://foo|");
    assert_linked("a123://foo", "|a123://foo|");
    assert_linked("a123b://foo", "|a123b://foo|");
    assert_linked("a+b://foo", "|a+b://foo|");
    assert_linked("a-b://foo", "|a-b://foo|");
    assert_linked("a.b://foo", "|a.b://foo|");
    assert_linked("ABC://foo", "|ABC://foo|");
    assert_linked(".http://example.org/", ".|http://example.org/|");
    assert_linked("1.http://example.org/", "1.|http://example.org/|");
}

#[test]
fn authority() {
    assert_not_linked("ab://");
    assert_not_linked("http://");
    assert_not_linked("http:// ");
    assert_not_linked("\"http://\"");
    assert_not_linked("\"http://...\", ");

    assert_linked("http://a.", "|http://a|.");
}

#[test]
fn single_links() {
    assert_linked("ab://c", "|ab://c|");
    assert_linked("http://example.org/", "|http://example.org/|");
    assert_linked("http://example.org/123", "|http://example.org/123|");
    assert_linked(
        "http://example.org/?foo=test&bar=123",
        "|http://example.org/?foo=test&bar=123|",
    );
    assert_linked(
        "http://example.org/?foo=%20",
        "|http://example.org/?foo=%20|",
    );
    assert_linked("http://example.org/%3C", "|http://example.org/%3C|");
}

#[test]
fn space_characters_stop_url() {
    assert_linked("foo http://example.org/", "foo |http://example.org/|");
    assert_linked("http://example.org/ bar", "|http://example.org/| bar");
    assert_linked("http://example.org/\tbar", "|http://example.org/|\tbar");
    assert_linked("http://example.org/\nbar", "|http://example.org/|\nbar");
    assert_linked(
        "http://example.org/\u{0B}bar",
        "|http://example.org/|\u{0B}bar",
    );
    assert_linked(
        "http://example.org/\u{0C}bar",
        "|http://example.org/|\u{0C}bar",
    );
    assert_linked("http://example.org/\rbar", "|http://example.org/|\rbar");
}

#[test]
fn illegal_characters_stop_url() {
    assert_linked("http://example.org/<", "|http://example.org/|<");
    assert_linked("http://example.org/>", "|http://example.org/|>");
    assert_linked("http://example.org/<>", "|http://example.org/|<>");
    assert_linked("http://example.org/\u{00}", "|http://example.org/|\u{00}");
    assert_linked("http://example.org/\u{0E}", "|http://example.org/|\u{0E}");
    assert_linked("http://example.org/\u{7F}", "|http://example.org/|\u{7F}");
    assert_linked("http://example.org/\u{9F}", "|http://example.org/|\u{9F}");
}

#[test]
fn delimiter_at_end() {
    assert_linked("http://example.org/.", "|http://example.org/|.");
    assert_linked("http://example.org/..", "|http://example.org/|..");
    assert_linked("http://example.org/,", "|http://example.org/|,");
    assert_linked("http://example.org/:", "|http://example.org/|:");
    assert_linked("http://example.org/?", "|http://example.org/|?");
    assert_linked("http://example.org/!", "|http://example.org/|!");
    assert_linked("http://example.org/;", "|http://example.org/|;");
}

#[test]
fn matching_punctuation() {
    assert_linked("http://example.org/a(b)", "|http://example.org/a(b)|");
    assert_linked("http://example.org/a[b]", "|http://example.org/a[b]|");
    assert_linked("http://example.org/a{b}", "|http://example.org/a{b}|");
    assert_linked("http://example.org/a'b'", "|http://example.org/a'b'|");
    assert_linked("(http://example.org/)", "(|http://example.org/|)");
    assert_linked("[http://example.org/]", "[|http://example.org/|]");
    assert_linked("{http://example.org/}", "{|http://example.org/|}");
    assert_linked("\"http://example.org/\"", "\"|http://example.org/|\"");
    assert_linked("'http://example.org/'", "'|http://example.org/|'");
}

#[test]
fn matching_punctuation_tricky() {
    assert_linked("((http://example.org/))", "((|http://example.org/|))");
    assert_linked(
        "((http://example.org/a(b)))",
        "((|http://example.org/a(b)|))",
    );
    assert_linked("[(http://example.org/)]", "[(|http://example.org/|)]");
    assert_linked("(http://example.org/).", "(|http://example.org/|).");
    assert_linked("(http://example.org/.)", "(|http://example.org/|.)");
    assert_linked("http://example.org/>", "|http://example.org/|>");
    // not sure about these
    assert_linked("http://example.org/(", "|http://example.org/|(");
    assert_linked("http://example.org/(.", "|http://example.org/|(.");
    assert_linked("http://example.org/]()", "|http://example.org/|]()");
}

#[test]
fn single_quote() {
    assert_linked(
        "http://example.org/\'_(foo)",
        "|http://example.org/\'_(foo)|",
    );
    assert_linked(
        "http://example.org/\'_(foo)\'",
        "|http://example.org/\'_(foo)\'|",
    );
    assert_linked("http://example.org/\'\'", "|http://example.org/\'\'|");
    assert_linked("http://example.org/\'\'\'", "|http://example.org/\'\'|\'");
    assert_linked("http://example.org/\'.", "|http://example.org/|\'.");
    assert_linked("http://example.org/\'a", "|http://example.org/\'a|");
    assert_linked("http://example.org/it's", "|http://example.org/it's|");
}

#[test]
fn double_quote() {
    // " not allowed in URLs
    assert_linked("http://example.org/\"a", "|http://example.org/|\"a");
    assert_linked("http://example.org/\"a\"", "|http://example.org/|\"a\"");
}

#[test]
fn grave_quote() {
    // ` not allowed in URLs
    assert_linked("http://example.org/`a", "|http://example.org/|`a");
    assert_linked("http://example.org/`a`", "|http://example.org/|`a`");
}

#[test]
fn asterisk() {
    assert_linked("https://example.org*", "|https://example.org|*");
    assert_linked("https://example.org/*", "|https://example.org/|*");
    assert_linked("https://example.org/**", "|https://example.org/|**");
    assert_linked("https://example.org/*/a", "|https://example.org/*/a|");
}

#[test]
fn html() {
    assert_linked("http://example.org\">", "|http://example.org|\">");
    assert_linked("http://example.org'>", "|http://example.org|'>");
    assert_linked("http://example.org\"/>", "|http://example.org|\"/>");
    assert_linked("http://example.org'/>", "|http://example.org|'/>");
    assert_linked("http://example.org
", "|http://example.org|
");
    assert_linked("http://example.org
", "|http://example.org|
");
}

#[test]
fn css() {
    assert_linked("http://example.org\");", "|http://example.org|\");");
    assert_linked("http://example.org');", "|http://example.org|');");
}

#[test]
fn images() {
    assert_linked(
        r#""#,
        r#""#,
    );
}

#[test]
fn complex_html() {
    assert_linked(
        r#"

"#,
        r#"

"#,
    );

    assert_linked(
        r#"

"#,
        r#"

"#,
    );

    assert_linked(
        r#"

"#,
        r#"

"#,
    )
}

#[test]
fn slash() {
    assert_linked("http://example.org/", "|http://example.org/|");
    assert_linked("http://example.org/a/", "|http://example.org/a/|");
    assert_linked("http://example.org//", "|http://example.org//|");
}

#[test]
fn multiple() {
    assert_linked(
        "http://one.org/ http://two.org/",
        "|http://one.org/| |http://two.org/|",
    );
    assert_linked(
        "http://one.org/ : http://two.org/",
        "|http://one.org/| : |http://two.org/|",
    );
    assert_linked(
        "(http://one.org/)(http://two.org/)",
        "(|http://one.org/|)(|http://two.org/|)",
    );
}

#[test]
fn international() {
    assert_linked("http://üñîçøðé.com/ä", "|http://üñîçøðé.com/ä|");
    assert_linked("http://example.org/\u{A1}", "|http://example.org/\u{A1}|");
    assert_linked("http://example.org/\u{A2}", "|http://example.org/\u{A2}|");
    assert_linked(
        "http://example.org/\u{1F600}",
        "|http://example.org/\u{1F600}|",
    );
    assert_linked("http://example.org/\u{A2}/", "|http://example.org/\u{A2}/|");
    assert_linked(
        "http://xn--c1h.example.com/",
        "|http://xn--c1h.example.com/|",
    );
}

#[test]
fn fuzz() {
    assert_not_linked("ab:/ϸ");
}

fn assert_not_linked(s: &str) {
    assert_linked(s, s);
}

fn assert_linked(input: &str, expected: &str) {
    let finder = LinkFinder::new();
    assert_linked_with(&finder, input, expected);
}
<commit_msg>Add tests for ipv4/ipv6 local addresses<commit_after>mod common;

use crate::common::assert_linked_with;
use linkify::LinkFinder;

#[test]
fn no_links() {
    assert_not_linked("");
    assert_not_linked("foo");
    assert_not_linked(":");
    assert_not_linked("://");
    assert_not_linked(":::");
}

#[test]
fn schemes() {
    assert_not_linked("://foo");
    assert_not_linked("1://foo");
    assert_not_linked("123://foo");
    assert_not_linked("+://foo");
    assert_not_linked("-://foo");
    assert_not_linked(".://foo");
    assert_not_linked("1abc://foo");
    assert_linked("a://foo", "|a://foo|");
    assert_linked("a123://foo", "|a123://foo|");
    assert_linked("a123b://foo", "|a123b://foo|");
    assert_linked("a+b://foo", "|a+b://foo|");
    assert_linked("a-b://foo", "|a-b://foo|");
    assert_linked("a.b://foo", "|a.b://foo|");
    assert_linked("ABC://foo", "|ABC://foo|");
    assert_linked(".http://example.org/", ".|http://example.org/|");
    assert_linked("1.http://example.org/", "1.|http://example.org/|");
}

#[test]
fn authority() {
    assert_not_linked("ab://");
    assert_not_linked("http://");
    assert_not_linked("http:// ");
    assert_not_linked("\"http://\"");
    assert_not_linked("\"http://...\", ");

    assert_linked("http://a.", "|http://a|.");
}

#[test]
fn local_links() {
    assert_linked("http://127.0.0.1", "|http://127.0.0.1|");
    assert_linked("http://127.0.0.1/", "|http://127.0.0.1/|");
    assert_linked("http://::1", "|http://::1|");
    assert_linked("http://::1/", "|http://::1/|");
}

#[test]
fn single_links() {
    assert_linked("ab://c", "|ab://c|");
    assert_linked("http://example.org/", "|http://example.org/|");
    assert_linked("http://example.org/123", "|http://example.org/123|");
    assert_linked(
        "http://example.org/?foo=test&bar=123",
        "|http://example.org/?foo=test&bar=123|",
    );
    assert_linked(
        "http://example.org/?foo=%20",
        "|http://example.org/?foo=%20|",
    );
    assert_linked("http://example.org/%3C", "|http://example.org/%3C|");
}

#[test]
fn space_characters_stop_url() {
    assert_linked("foo http://example.org/", "foo |http://example.org/|");
    assert_linked("http://example.org/ bar", "|http://example.org/| bar");
    assert_linked("http://example.org/\tbar", "|http://example.org/|\tbar");
    assert_linked("http://example.org/\nbar", "|http://example.org/|\nbar");
    assert_linked(
        "http://example.org/\u{0B}bar",
        "|http://example.org/|\u{0B}bar",
    );
    assert_linked(
        "http://example.org/\u{0C}bar",
        "|http://example.org/|\u{0C}bar",
    );
    assert_linked("http://example.org/\rbar", "|http://example.org/|\rbar");
}

#[test]
fn illegal_characters_stop_url() {
    assert_linked("http://example.org/<", "|http://example.org/|<");
    assert_linked("http://example.org/>", "|http://example.org/|>");
    assert_linked("http://example.org/<>", "|http://example.org/|<>");
    assert_linked("http://example.org/\u{00}", "|http://example.org/|\u{00}");
    assert_linked("http://example.org/\u{0E}", "|http://example.org/|\u{0E}");
    assert_linked("http://example.org/\u{7F}", "|http://example.org/|\u{7F}");
    assert_linked("http://example.org/\u{9F}", "|http://example.org/|\u{9F}");
}

#[test]
fn delimiter_at_end() {
    assert_linked("http://example.org/.", "|http://example.org/|.");
    assert_linked("http://example.org/..", "|http://example.org/|..");
    assert_linked("http://example.org/,", "|http://example.org/|,");
    assert_linked("http://example.org/:", "|http://example.org/|:");
    assert_linked("http://example.org/?", "|http://example.org/|?");
    assert_linked("http://example.org/!", "|http://example.org/|!");
    assert_linked("http://example.org/;", "|http://example.org/|;");
}

#[test]
fn matching_punctuation() {
    assert_linked("http://example.org/a(b)", "|http://example.org/a(b)|");
    assert_linked("http://example.org/a[b]", "|http://example.org/a[b]|");
    assert_linked("http://example.org/a{b}", "|http://example.org/a{b}|");
    assert_linked("http://example.org/a'b'", "|http://example.org/a'b'|");
    assert_linked("(http://example.org/)", "(|http://example.org/|)");
    assert_linked("[http://example.org/]", "[|http://example.org/|]");
    assert_linked("{http://example.org/}", "{|http://example.org/|}");
    assert_linked("\"http://example.org/\"", "\"|http://example.org/|\"");
    assert_linked("'http://example.org/'", "'|http://example.org/|'");
}

#[test]
fn matching_punctuation_tricky() {
    assert_linked("((http://example.org/))", "((|http://example.org/|))");
    assert_linked(
        "((http://example.org/a(b)))",
        "((|http://example.org/a(b)|))",
    );
    assert_linked("[(http://example.org/)]", "[(|http://example.org/|)]");
    assert_linked("(http://example.org/).", "(|http://example.org/|).");
    assert_linked("(http://example.org/.)", "(|http://example.org/|.)");
    assert_linked("http://example.org/>", "|http://example.org/|>");
    // not sure about these
    assert_linked("http://example.org/(", "|http://example.org/|(");
    assert_linked("http://example.org/(.", "|http://example.org/|(.");
    assert_linked("http://example.org/]()", "|http://example.org/|]()");
}

#[test]
fn single_quote() {
    assert_linked(
        "http://example.org/\'_(foo)",
        "|http://example.org/\'_(foo)|",
    );
    assert_linked(
        "http://example.org/\'_(foo)\'",
        "|http://example.org/\'_(foo)\'|",
    );
    assert_linked("http://example.org/\'\'", "|http://example.org/\'\'|");
    assert_linked("http://example.org/\'\'\'", "|http://example.org/\'\'|\'");
    assert_linked("http://example.org/\'.", "|http://example.org/|\'.");
    assert_linked("http://example.org/\'a", "|http://example.org/\'a|");
    assert_linked("http://example.org/it's", "|http://example.org/it's|");
}

#[test]
fn double_quote() {
    // " not allowed in URLs
    assert_linked("http://example.org/\"a", "|http://example.org/|\"a");
    assert_linked("http://example.org/\"a\"", "|http://example.org/|\"a\"");
}

#[test]
fn grave_quote() {
    // ` not allowed in URLs
    assert_linked("http://example.org/`a", "|http://example.org/|`a");
    assert_linked("http://example.org/`a`", "|http://example.org/|`a`");
}

#[test]
fn asterisk() {
    assert_linked("https://example.org*", "|https://example.org|*");
    assert_linked("https://example.org/*", "|https://example.org/|*");
    assert_linked("https://example.org/**", "|https://example.org/|**");
    assert_linked("https://example.org/*/a", "|https://example.org/*/a|");
}

#[test]
fn html() {
    assert_linked("http://example.org\">", "|http://example.org|\">");
    assert_linked("http://example.org'>", "|http://example.org|'>");
    assert_linked("http://example.org\"/>", "|http://example.org|\"/>");
    assert_linked("http://example.org'/>", "|http://example.org|'/>");
    assert_linked("http://example.org
", "|http://example.org|
");
    assert_linked("http://example.org
", "|http://example.org|
");
}

#[test]
fn css() {
    assert_linked("http://example.org\");", "|http://example.org|\");");
    assert_linked("http://example.org');", "|http://example.org|');");
}

#[test]
fn images() {
    assert_linked(
        r#""#,
        r#""#,
    );
}

#[test]
fn complex_html() {
    assert_linked(
        r#"

"#,
        r#"

"#,
    );

    assert_linked(
        r#"

"#,
        r#"

"#,
    );

    assert_linked(
        r#"

"#,
        r#"

"#,
    )
}

#[test]
fn slash() {
    assert_linked("http://example.org/", "|http://example.org/|");
    assert_linked("http://example.org/a/", "|http://example.org/a/|");
    assert_linked("http://example.org//", "|http://example.org//|");
}

#[test]
fn multiple() {
    assert_linked(
        "http://one.org/ http://two.org/",
        "|http://one.org/| |http://two.org/|",
    );
    assert_linked(
        "http://one.org/ : http://two.org/",
        "|http://one.org/| : |http://two.org/|",
    );
    assert_linked(
        "(http://one.org/)(http://two.org/)",
        "(|http://one.org/|)(|http://two.org/|)",
    );
}

#[test]
fn international() {
    assert_linked("http://üñîçøðé.com/ä", "|http://üñîçøðé.com/ä|");
    assert_linked("http://example.org/\u{A1}", "|http://example.org/\u{A1}|");
    assert_linked("http://example.org/\u{A2}", "|http://example.org/\u{A2}|");
    assert_linked(
        "http://example.org/\u{1F600}",
        "|http://example.org/\u{1F600}|",
    );
    assert_linked("http://example.org/\u{A2}/", "|http://example.org/\u{A2}/|");
    assert_linked(
        "http://xn--c1h.example.com/",
        "|http://xn--c1h.example.com/|",
    );
}

#[test]
fn fuzz() {
    assert_not_linked("ab:/ϸ");
}

fn assert_not_linked(s: &str) {
    assert_linked(s, s);
}

fn assert_linked(input: &str, expected: &str) {
    let finder = LinkFinder::new();
    assert_linked_with(&finder, input, expected);
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, rustc_private)]

extern crate itertools;
extern crate rustc_plugin;
extern crate syntax;

use itertools::Itertools;
use rustc_plugin::Registry;
use syntax::ast::{self, Ident, TraitRef, Ty, TyKind};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::quote::rt::Span;
use syntax::parse::{self, token, str_lit, PResult};
use syntax::parse::parser::{Parser, PathStyle};
use syntax::symbol::Symbol;
use syntax::ptr::P;
use syntax::tokenstream::{TokenTree, TokenStream};
use syntax::util::small_vector::SmallVector;

fn snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.into());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.

    let mut item = match parser.parse_trait_item(&mut false) {
        Ok(s) => s,
        Err(mut diagnostic) => {
            diagnostic.emit();
            return DummyResult::any(sp);
        }
    };

    if let Err(mut diagnostic) = parser.expect(&token::Eof) {
        diagnostic.emit();
        return DummyResult::any(sp);
    }

    let old_ident = convert(&mut item.ident);

    // As far as I know, it's not possible in macro_rules! to reference an $ident in a doc string,
    // so this is the hacky workaround.
    //
    // This code looks intimidating, but it's just iterating through the trait item's attributes
    // copying non-doc attributes, and modifying doc attributes such that replacing any {} in the
    // doc string instead holds the original, snake_case ident.
    let attrs: Vec<_> = item.attrs
        .drain(..)
        .map(|mut attr| {
            if !attr.is_sugared_doc {
                return attr;
            }

            // Getting at the underlying doc comment is surprisingly painful.
            // The call-chain goes something like:
            //
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L283
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L1067
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L1196
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/parse/mod.rs#L399
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/parse/mod.rs#L268
            //
            // Note that a docstring (i.e., something with is_sugared_doc) *always* has exactly two
            // tokens: an Eq followed by a Literal, where the Literal contains a Str_. We therefore
            // match against that, modifying the inner Str with our modified Symbol.
            let mut tokens = attr.tokens.clone().into_trees();
            if let Some(tt @ TokenTree::Token(_, token::Eq)) = tokens.next() {
                let mut docstr = tokens.next().expect("Docstrings must have literal docstring");
                if let TokenTree::Token(_, token::Literal(token::Str_(ref mut doc), _)) = docstr {
                    *doc = Symbol::intern(&str_lit(&doc.as_str()).replace("{}", &old_ident));
                } else {
                    unreachable!();
                }
                attr.tokens = TokenStream::concat(vec![tt.into(), docstr.into()]);
            } else {
                unreachable!();
            }

            attr
        })
        .collect();
    item.attrs.extend(attrs.into_iter());

    MacEager::trait_items(SmallVector::one(item))
}

fn impl_snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.into());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.

    let mut item = match parser.parse_impl_item(&mut false) {
        Ok(s) => s,
        Err(mut diagnostic) => {
            diagnostic.emit();
            return DummyResult::any(sp);
        }
    };

    if let Err(mut diagnostic) = parser.expect(&token::Eof) {
        diagnostic.emit();
        return DummyResult::any(sp);
    }

    convert(&mut item.ident);
    MacEager::impl_items(SmallVector::one(item))
}

fn ty_snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.into());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.

    let mut path = match parser.parse_path(PathStyle::Type) {
        Ok(s) => s,
        Err(mut diagnostic) => {
            diagnostic.emit();
            return DummyResult::any(sp);
        }
    };

    if let Err(mut diagnostic) = parser.expect(&token::Eof) {
        diagnostic.emit();
        return DummyResult::any(sp);
    }

    // Only capitalize the final segment
    convert(&mut path.segments
                     .last_mut()
                     .unwrap()
                     .identifier);
    MacEager::ty(P(Ty {
        id: ast::DUMMY_NODE_ID,
        node: TyKind::Path(None, path),
        span: sp,
    }))
}

/// Converts an ident in-place to CamelCase and returns the previous ident.
fn convert(ident: &mut Ident) -> String {
    let ident_str = ident.to_string();
    let mut camel_ty = String::new();

    {
        // Find the first non-underscore and add it capitalized.
        let mut chars = ident_str.chars();

        // Find the first non-underscore char, uppercase it, and append it.
        // Guaranteed to succeed because all idents must have at least one non-underscore char.
        camel_ty.extend(chars.find(|&c| c != '_').unwrap().to_uppercase());

        // When we find an underscore, we remove it and capitalize the next char. To do this,
        // we need to ensure the next char is not another underscore.
        let mut chars = chars.coalesce(|c1, c2| {
            if c1 == '_' && c2 == '_' {
                Ok(c1)
            } else {
                Err((c1, c2))
            }
        });

        while let Some(c) = chars.next() {
            if c != '_' {
                camel_ty.push(c);
            } else {
                if let Some(c) = chars.next() {
                    camel_ty.extend(c.to_uppercase());
                }
            }
        }
    }

    // The Fut suffix is hardcoded right now; this macro isn't really meant to be general-purpose.
    camel_ty.push_str("Fut");

    *ident = Ident::with_empty_ctxt(Symbol::intern(&camel_ty));
    ident_str
}

trait ParseTraitRef {
    fn parse_trait_ref(&mut self) -> PResult<TraitRef>;
}

impl<'a> ParseTraitRef for Parser<'a> {
    /// Parse a::B<String,i32>
    fn parse_trait_ref(&mut self) -> PResult<TraitRef> {
        Ok(TraitRef {
            path: self.parse_path(PathStyle::Type)?,
            ref_id: ast::DUMMY_NODE_ID,
        })
    }
}

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("snake_to_camel", snake_to_camel);
    reg.register_macro("impl_snake_to_camel", impl_snake_to_camel);
    reg.register_macro("ty_snake_to_camel", ty_snake_to_camel);
}
<commit_msg>Fix breakage from nightly compiler changes.<commit_after>#![feature(plugin_registrar, rustc_private)]

extern crate itertools;
extern crate rustc_plugin;
extern crate syntax;

use itertools::Itertools;
use rustc_plugin::Registry;
use syntax::ast::{self, Ident, TraitRef, Ty, TyKind};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::quote::rt::Span;
use syntax::parse::{self, token, str_lit, PResult};
use syntax::parse::parser::{Parser, PathStyle};
use syntax::symbol::Symbol;
use syntax::ptr::P;
use syntax::tokenstream::{TokenTree, TokenStream};
use syntax::util::small_vector::SmallVector;

fn snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.into());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.

    let mut item = match parser.parse_trait_item(&mut false) {
        Ok(s) => s,
        Err(mut diagnostic) => {
            diagnostic.emit();
            return DummyResult::any(sp);
        }
    };

    if let Err(mut diagnostic) = parser.expect(&token::Eof) {
        diagnostic.emit();
        return DummyResult::any(sp);
    }

    let old_ident = convert(&mut item.ident);

    // As far as I know, it's not possible in macro_rules! to reference an $ident in a doc string,
    // so this is the hacky workaround.
    //
    // This code looks intimidating, but it's just iterating through the trait item's attributes
    // copying non-doc attributes, and modifying doc attributes such that replacing any {} in the
    // doc string instead holds the original, snake_case ident.
    let attrs: Vec<_> = item.attrs
        .drain(..)
        .map(|mut attr| {
            if !attr.is_sugared_doc {
                return attr;
            }

            // Getting at the underlying doc comment is surprisingly painful.
            // The call-chain goes something like:
            //
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L283
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L1067
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/attr.rs#L1196
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/parse/mod.rs#L399
            //  - https://github.com/rust-lang/rust/blob/9c15de4fd59bee290848b5443c7e194fd5afb02c/src/libsyntax/parse/mod.rs#L268
            //
            // Note that a docstring (i.e., something with is_sugared_doc) *always* has exactly two
            // tokens: an Eq followed by a Literal, where the Literal contains a Str_. We therefore
            // match against that, modifying the inner Str with our modified Symbol.
            let mut tokens = attr.tokens.clone().into_trees();
            if let Some(tt @ TokenTree::Token(_, token::Eq)) = tokens.next() {
                let mut docstr = tokens.next().expect("Docstrings must have literal docstring");
                if let TokenTree::Token(_, token::Literal(token::Str_(ref mut doc), _)) = docstr {
                    *doc = Symbol::intern(&str_lit(&doc.as_str(), None).replace("{}", &old_ident));
                } else {
                    unreachable!();
                }
                attr.tokens = TokenStream::concat(vec![tt.into(), docstr.into()]);
            } else {
                unreachable!();
            }

            attr
        })
        .collect();
    item.attrs.extend(attrs.into_iter());

    MacEager::trait_items(SmallVector::one(item))
}

fn impl_snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.into());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.

    let mut item = match parser.parse_impl_item(&mut false) {
        Ok(s) => s,
        Err(mut diagnostic) => {
            diagnostic.emit();
            return DummyResult::any(sp);
        }
    };

    if let Err(mut diagnostic) = parser.expect(&token::Eof) {
        diagnostic.emit();
        return DummyResult::any(sp);
    }

    convert(&mut item.ident);
    MacEager::impl_items(SmallVector::one(item))
}

fn ty_snake_to_camel(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.into());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.

    let mut path = match parser.parse_path(PathStyle::Type) {
        Ok(s) => s,
        Err(mut diagnostic) => {
            diagnostic.emit();
            return DummyResult::any(sp);
        }
    };

    if let Err(mut diagnostic) = parser.expect(&token::Eof) {
        diagnostic.emit();
        return DummyResult::any(sp);
    }

    // Only capitalize the final segment
    convert(&mut path.segments
                     .last_mut()
                     .unwrap()
                     .identifier);
    MacEager::ty(P(Ty {
        id: ast::DUMMY_NODE_ID,
        node: TyKind::Path(None, path),
        span: sp,
    }))
}

/// Converts an ident in-place to CamelCase and returns the previous ident.
fn convert(ident: &mut Ident) -> String {
    let ident_str = ident.to_string();
    let mut camel_ty = String::new();

    {
        // Find the first non-underscore and add it capitalized.
        let mut chars = ident_str.chars();

        // Find the first non-underscore char, uppercase it, and append it.
        // Guaranteed to succeed because all idents must have at least one non-underscore char.
        camel_ty.extend(chars.find(|&c| c != '_').unwrap().to_uppercase());

        // When we find an underscore, we remove it and capitalize the next char. To do this,
        // we need to ensure the next char is not another underscore.
        let mut chars = chars.coalesce(|c1, c2| {
            if c1 == '_' && c2 == '_' {
                Ok(c1)
            } else {
                Err((c1, c2))
            }
        });

        while let Some(c) = chars.next() {
            if c != '_' {
                camel_ty.push(c);
            } else {
                if let Some(c) = chars.next() {
                    camel_ty.extend(c.to_uppercase());
                }
            }
        }
    }

    // The Fut suffix is hardcoded right now; this macro isn't really meant to be general-purpose.
    camel_ty.push_str("Fut");

    *ident = Ident::with_empty_ctxt(Symbol::intern(&camel_ty));
    ident_str
}

trait ParseTraitRef {
    fn parse_trait_ref(&mut self) -> PResult<TraitRef>;
}

impl<'a> ParseTraitRef for Parser<'a> {
    /// Parse a::B<String,i32>
    fn parse_trait_ref(&mut self) -> PResult<TraitRef> {
        Ok(TraitRef {
            path: self.parse_path(PathStyle::Type)?,
            ref_id: ast::DUMMY_NODE_ID,
        })
    }
}

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("snake_to_camel", snake_to_camel);
    reg.register_macro("impl_snake_to_camel", impl_snake_to_camel);
    reg.register_macro("ty_snake_to_camel", ty_snake_to_camel);
}
<|endoftext|>


<commit_before>extern crate unicode_names;

use std::marker::PhantomData;

use irc::client::prelude::*;

use plugin::*;
use FrippyClient;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::Fail;

#[derive(PluginName, Default, Debug)]
pub struct Unicode<C> {
    phantom: PhantomData<C>,
}

impl<C: FrippyClient> Unicode<C> {
    pub fn new() -> Unicode<C> {
        Unicode {
            phantom: PhantomData,
        }
    }

    fn get_name(&self, symbol: char) -> String {
        match unicode_names::name(symbol) {
            Some(sym) => sym.to_string().to_lowercase(),
            None => String::from("UNKNOWN"),
        }
    }

    fn format_response(&self, content: &str) -> String {
        let character = content.chars().next();
        if let Some(c) = character {
            let mut buf = [0; 4];

            let byte_string = c
                .encode_utf8(&mut buf)
                .as_bytes()
                .iter()
                .map(|b| format!("{:#b}", b))
                .collect::<Vec<String>>()
                .join(",");

            let name = self.get_name(c);

            format!(
                "{} is '{}' | UTF-8: {2:#x} ({2}), Bytes: [{3}]",
                c, name, c as u32, byte_string
            )
        } else {
            String::from("No non-space character was found.")
        }
    }
}

impl<C: FrippyClient> Plugin for Unicode<C> {
    type Client = C;

    fn execute(&self, _: &Self::Client, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Unicode should not use threading")
    }

    fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
        if command.tokens.is_empty() {
            let msg = "No non-space character was found.";

            if let Err(e) = client.send_notice(command.source, msg) {
                Err(e.context(FrippyErrorKind::Connection))?;
            }

            return Ok(());
        }

        let content = &command.tokens[0];

        if let Err(e) = client.send_privmsg(command.target, &self.format_response(&content)) {
            Err(e.context(FrippyErrorKind::Connection))?;
        }

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, command: PluginCommand) -> Result<String, String> {
        let tokens = command.tokens;

        if tokens.is_empty() {
            return Err(String::from("No non-space character was found."));
        }

        Ok(self.format_response(&tokens[0]))
    }
}
<commit_msg>Unicode: Always send a notice on error<commit_after>extern crate unicode_names;

use std::marker::PhantomData;

use irc::client::prelude::*;

use plugin::*;
use FrippyClient;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::Fail;

#[derive(PluginName, Default, Debug)]
pub struct Unicode<C> {
    phantom: PhantomData<C>,
}

impl<C: FrippyClient> Unicode<C> {
    pub fn new() -> Unicode<C> {
        Unicode {
            phantom: PhantomData,
        }
    }

    fn get_name(&self, symbol: char) -> String {
        match unicode_names::name(symbol) {
            Some(sym) => sym.to_string().to_lowercase(),
            None => String::from("UNKNOWN"),
        }
    }

    fn format_response(&self, content: &str) -> String {
        let character = content
            .chars()
            .next()
            .expect("content contains at least one character");

        let mut buf = [0; 4];

        let byte_string = character
            .encode_utf8(&mut buf)
            .as_bytes()
            .iter()
            .map(|b| format!("{:#b}", b))
            .collect::<Vec<String>>()
            .join(",");

        let name = self.get_name(character);

        format!(
            "{} is '{}' | UTF-8: {2:#x} ({2}), Bytes: [{3}]",
            character, name, character as u32, byte_string
        )
    }
}

impl<C: FrippyClient> Plugin for Unicode<C> {
    type Client = C;

    fn execute(&self, _: &Self::Client, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Unicode should not use threading")
    }

    fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
        if command.tokens.is_empty() || command.tokens[0].is_empty() {
            let msg = "No non-space character was found.";

            if let Err(e) = client.send_notice(command.source, msg) {
                Err(e.context(FrippyErrorKind::Connection))?;
            }

            return Ok(());
        }

        let content = &command.tokens[0];

        if let Err(e) = client.send_privmsg(command.target, &self.format_response(&content)) {
            Err(e.context(FrippyErrorKind::Connection))?;
        }

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, command: PluginCommand) -> Result<String, String> {
        let tokens = command.tokens;

        if tokens.is_empty() {
            return Err(String::from("No non-space character was found."));
        }

        Ok(self.format_response(&tokens[0]))
    }
}
<|endoftext|>


<commit_before>//! Macros to define CSS properties.

/// Trait which all CSS property types should implement.
///
/// This is generic on `T` for testing purposes; in the actual code `T` needs to
/// be [`ComputedValues`].
///
/// [`ComputedValues`]: ../properties/struct.ComputedValues.html
pub trait Property<T> {
    /// Whether the property's computed value inherits from parent to child elements.
    ///
    /// For each property, the CSS or SVG specs say whether the property inherits
    /// automatically.  When a property is not specified in an element, the return value
    /// of this method determines whether the property's value is copied from the parent
    /// element (`true`), or whether it resets to the initial/default value (`false`).
    fn inherits_automatically() -> bool;

    /// Derive the CSS computed value from the parent element's `ComputedValues` and the `self` value.
    ///
    /// The CSS or SVG specs say how to derive this for each property.
    fn compute(&self, _: &T) -> Self;
}

/// Generates a type for a CSS property.
///
/// Writing a property by hand takes a bit of boilerplate:
///
/// * Define a type to represent the property's values.
///
/// * A [`Parse`] implementation to parse the property.
///
/// * A `Default` implementation to define the property's *initial* value.
///
/// * A [`Property`] implementation to define whether the property
/// inherits from the parent element, and how the property derives
/// its computed value.
///
/// When going from [`SpecifiedValues`] to [`ComputedValues`], properties
/// which inherit automatically from the parent element will just have
/// their values cloned.  Properties which do not inherit will be reset back
/// to their initial value (i.e. their `Default`).
///
/// The default implementation of `Property::compute()` is to just
/// clone the property's value.  Properties which need more
/// sophisticated computation can override this.
///
/// This macro allows defining properties of different kinds; see the following
/// sections for examples.
///
/// # Simple identifiers
///
/// Many properties are just sets of identifiers and can be represented
/// by simple enums.  In this case, you can use the following:
///
/// ```text
/// make_property!(
///   ComputedValues,
///   StrokeLinejoin,
///   default: Miter,
///   inherits_automatically: true,
///
///   identifiers:
///     "miter" => Miter,
///     "round" => Round,
///     "bevel" => Bevel,
/// );
/// ```
///
/// This generates a simple enum like the following, with implementations of [`Parse`],
/// `Default`, and [`Property`].
///
/// ```
/// pub enum StrokeLinejoin { Miter, Round, Bevel }
/// ```
///
/// # Properties from an existing, general-purpose type
///
/// For example, both the `lightingColor` and `floodColor` properties can be represented
/// with a `cssparser::Color`, but their intial values are different.  In this case, the macro
/// can generate a newtype around `cssparser::Color` for each case:
///
/// ```text
/// make_property!(
///     ComputedValues,
///     FloodColor,
///     default: cssparser::Color::RGBA(cssparser::RGBA::new(0, 0, 0, 0)),
///     inherits_automatically: false,
///     newtype_parse: cssparser::Color,
/// );
/// ```
///
/// # Properties from custom specific types
///
/// For example, font-related properties have custom, complex types that require an
/// implentation of `Property::compute` that is more than a simple `clone`.  In this case,
/// define the custom type separately, and use the macro to specify the default value and
/// the `Property` implementation.
///
/// [`Parse`]: ../trait.Parse.html
/// [`Property`]: ../property_macros/trait.Property.html
/// [`ComputedValues`]: ../properties/struct.ComputedValues.html
/// [`SpecifiedValues`]: ../properties/struct.SpecifiedValues.html
///
#[macro_export]
macro_rules! make_property {
    ($name: ident,
     default: $default: ident,
     inherits_automatically: $inherits_automatically: expr,
     identifiers:
     $($str_prop: expr => $variant: ident,)+
    ) => {
        #[derive(Debug, Copy, Clone, PartialEq)]
        #[repr(C)]
        pub enum $name {
            $($variant),+
        }

        impl_default!($name, $name::$default);
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        impl crate::parsers::Parse for $name {
            fn parse<'i>(parser: &mut ::cssparser::Parser<'i, '_>) -> Result<$name, crate::error::ParseError<'i>> {
                Ok(parse_identifiers!(
                    parser,
                    $($str_prop => $name::$variant,)+
                )?)
            }
        }
    };

    ($name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype_parse: $type: ty,
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        impl crate::parsers::Parse for $name {
            fn parse<'i>(parser: &mut ::cssparser::Parser<'i, '_>) -> Result<$name, crate::error::ParseError<'i>> {
                Ok($name(<$type as crate::parsers::Parse>::parse(parser)?))
            }
        }
    };

    ($name: ident,
     default: $default: expr,
     property_impl: { $prop: item }
    ) => {
        impl_default!($name, $default);

        $prop
    };

    ($name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
    ) => {
        impl_default!($name, $default);
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);
    };

    ($name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     parse_impl: { $parse: item }
    ) => {
        impl_default!($name, $default);
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        $parse
    };

    // pending - only BaselineShift
    ($name: ident,
     default: $default: expr,
     newtype: $type: ty,
     property_impl: { $prop: item },
     parse_impl: { $parse: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        $prop

        $parse
    };

    // pending - only XmlLang
    ($name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype: $type: ty,
     parse_impl: { $parse: item },
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        $parse
    };

    ($name: ident,
     inherits_automatically: $inherits_automatically: expr,
     fields: {
       $($field_name: ident : $field_type: ty, default: $field_default : expr,)+
     }
     parse_impl: { $parse: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name {
            $(pub $field_name: $field_type),+
        }

        impl_default!($name, $name { $($field_name: $field_default),+ });
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        $parse
    };
}

macro_rules! impl_default {
    ($name:ident, $default:expr) => {
        impl Default for $name {
            fn default() -> $name {
                $default
            }
        }
    };
}

macro_rules! impl_property {
    ($computed_values_type:ty, $name:ident, $inherits_automatically:expr) => {
        impl crate::property_macros::Property<$computed_values_type> for $name {
            fn inherits_automatically() -> bool {
                $inherits_automatically
            }

            fn compute(&self, _v: &$computed_values_type) -> Self {
                self.clone()
            }
        }
    };
}
<commit_msg>Allow documentation for the types generated by the make_property macro<commit_after>//! Macros to define CSS properties.

/// Trait which all CSS property types should implement.
///
/// This is generic on `T` for testing purposes; in the actual code `T` needs to
/// be [`ComputedValues`].
///
/// [`ComputedValues`]: ../properties/struct.ComputedValues.html
pub trait Property<T> {
    /// Whether the property's computed value inherits from parent to child elements.
    ///
    /// For each property, the CSS or SVG specs say whether the property inherits
    /// automatically.  When a property is not specified in an element, the return value
    /// of this method determines whether the property's value is copied from the parent
    /// element (`true`), or whether it resets to the initial/default value (`false`).
    fn inherits_automatically() -> bool;

    /// Derive the CSS computed value from the parent element's `ComputedValues` and the `self` value.
    ///
    /// The CSS or SVG specs say how to derive this for each property.
    fn compute(&self, _: &T) -> Self;
}

/// Generates a type for a CSS property.
///
/// Writing a property by hand takes a bit of boilerplate:
///
/// * Define a type to represent the property's values.
///
/// * A [`Parse`] implementation to parse the property.
///
/// * A `Default` implementation to define the property's *initial* value.
///
/// * A [`Property`] implementation to define whether the property
/// inherits from the parent element, and how the property derives
/// its computed value.
///
/// When going from [`SpecifiedValues`] to [`ComputedValues`], properties
/// which inherit automatically from the parent element will just have
/// their values cloned.  Properties which do not inherit will be reset back
/// to their initial value (i.e. their `Default`).
///
/// The default implementation of `Property::compute()` is to just
/// clone the property's value.  Properties which need more
/// sophisticated computation can override this.
///
/// This macro allows defining properties of different kinds; see the following
/// sections for examples.
///
/// # Simple identifiers
///
/// Many properties are just sets of identifiers and can be represented
/// by simple enums.  In this case, you can use the following:
///
/// ```text
/// make_property!(
///   /// Documentation here.
///   StrokeLinejoin,
///   default: Miter,
///   inherits_automatically: true,
///
///   identifiers:
///     "miter" => Miter,
///     "round" => Round,
///     "bevel" => Bevel,
/// );
/// ```
///
/// This generates a simple enum like the following, with implementations of [`Parse`],
/// `Default`, and [`Property`].
///
/// ```
/// pub enum StrokeLinejoin { Miter, Round, Bevel }
/// ```
///
/// # Properties from an existing, general-purpose type
///
/// For example, both the `lightingColor` and `floodColor` properties can be represented
/// with a `cssparser::Color`, but their intial values are different.  In this case, the macro
/// can generate a newtype around `cssparser::Color` for each case:
///
/// ```text
/// make_property!(
///     /// Documentation here.
///     FloodColor,
///     default: cssparser::Color::RGBA(cssparser::RGBA::new(0, 0, 0, 0)),
///     inherits_automatically: false,
///     newtype_parse: cssparser::Color,
/// );
/// ```
///
/// # Properties from custom specific types
///
/// For example, font-related properties have custom, complex types that require an
/// implentation of `Property::compute` that is more than a simple `clone`.  In this case,
/// define the custom type separately, and use the macro to specify the default value and
/// the `Property` implementation.
///
/// [`Parse`]: ../trait.Parse.html
/// [`Property`]: ../property_macros/trait.Property.html
/// [`ComputedValues`]: ../properties/struct.ComputedValues.html
/// [`SpecifiedValues`]: ../properties/struct.SpecifiedValues.html
///
#[macro_export]
macro_rules! make_property {
    ($(#[$attr:meta])*
     $name: ident,
     default: $default: ident,
     inherits_automatically: $inherits_automatically: expr,
     identifiers:
     $($str_prop: expr => $variant: ident,)+
    ) => {
        $(#[$attr])*
        #[derive(Debug, Copy, Clone, PartialEq)]
        #[repr(C)]
        pub enum $name {
            $($variant),+
        }

        impl_default!($name, $name::$default);
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        impl crate::parsers::Parse for $name {
            fn parse<'i>(parser: &mut ::cssparser::Parser<'i, '_>) -> Result<$name, crate::error::ParseError<'i>> {
                Ok(parse_identifiers!(
                    parser,
                    $($str_prop => $name::$variant,)+
                )?)
            }
        }
    };

    ($(#[$attr:meta])*
     $name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype_parse: $type: ty,
    ) => {
        $(#[$attr])*
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        impl crate::parsers::Parse for $name {
            fn parse<'i>(parser: &mut ::cssparser::Parser<'i, '_>) -> Result<$name, crate::error::ParseError<'i>> {
                Ok($name(<$type as crate::parsers::Parse>::parse(parser)?))
            }
        }
    };

    ($(#[$attr:meta])*
     $name: ident,
     default: $default: expr,
     property_impl: { $prop: item }
    ) => {
        impl_default!($name, $default);

        $prop
    };

    ($name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
    ) => {
        impl_default!($name, $default);
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);
    };

    ($name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     parse_impl: { $parse: item }
    ) => {
        impl_default!($name, $default);
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        $parse
    };

    // pending - only BaselineShift
    ($(#[$attr:meta])*
     $name: ident,
     default: $default: expr,
     newtype: $type: ty,
     property_impl: { $prop: item },
     parse_impl: { $parse: item }
    ) => {
        $(#[$attr])*
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        $prop

        $parse
    };

    // pending - only XmlLang
    ($(#[$attr:meta])*
     $name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype: $type: ty,
     parse_impl: { $parse: item },
    ) => {
        $(#[$attr])*
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        $parse
    };

    ($(#[$attr:meta])*
     $name: ident,
     inherits_automatically: $inherits_automatically: expr,
     fields: {
       $($field_name: ident : $field_type: ty, default: $field_default : expr,)+
     }
     parse_impl: { $parse: item }
    ) => {
        $(#[$attr])*
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name {
            $(pub $field_name: $field_type),+
        }

        impl_default!($name, $name { $($field_name: $field_default),+ });
        impl_property!(crate::properties::ComputedValues, $name, $inherits_automatically);

        $parse
    };
}

macro_rules! impl_default {
    ($name:ident, $default:expr) => {
        impl Default for $name {
            fn default() -> $name {
                $default
            }
        }
    };
}

macro_rules! impl_property {
    ($computed_values_type:ty, $name:ident, $inherits_automatically:expr) => {
        impl crate::property_macros::Property<$computed_values_type> for $name {
            fn inherits_automatically() -> bool {
                $inherits_automatically
            }

            fn compute(&self, _v: &$computed_values_type) -> Self {
                self.clone()
            }
        }
    };
}
<|endoftext|>