<commit_before>#![warn(clippy::needless_lifetimes)]
#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps)]

fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}

fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}

// No error; same lifetime on two params.
fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}

// No error; static involved.
fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}

fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}

fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    x
}

// No error; multiple input refs.
fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
    x
}

// No error; multiple input refs.
fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
    x
}

// No error; static involved.
fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
    x
}

// No error.
fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
    Ok(x)
}

// No error; two input refs.
fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
    x.unwrap()
}

fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    Ok(x)
}

// Where-clause, but without lifetimes.
fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
where
    T: Copy,
{
    Ok(x)
}

type Ref<'r> = &'r u8;

// No error; same lifetime on two params.
fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}

fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}

// No error; bounded lifetime.
fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}

// No error; bounded lifetime.
fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
where
    'b: 'a,
{
}

struct Lt<'a, I: 'static> {
    x: &'a I,
}

// No error; fn bound references `'a`.
fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
where
    F: Fn(Lt<'a, I>) -> Lt<'a, I>,
{
    unreachable!()
}

fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
where
    for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
{
    unreachable!()
}

// No error; see below.
fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
    f(x);
}

fn fn_bound_3_cannot_elide() {
    let x = 42;
    let p = &x;
    let mut q = &x;
    // This will fail if we elide lifetimes of `fn_bound_3`.
    fn_bound_3(p, |y| q = y);
}

// No error; multiple input refs.
fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
    if cond { x } else { f() }
}

struct X {
    x: u8,
}

impl X {
    fn self_and_out<'s>(&'s self) -> &'s u8 {
        &self.x
    }

    // No error; multiple input refs.
    fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
        &self.x
    }

    fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}

    // No error; same lifetimes on two params.
    fn self_and_same_in<'s>(&'s self, _x: &'s u8) {}
}

struct Foo<'a>(&'a u8);

impl<'a> Foo<'a> {
    // No error; lifetime `'a` not defined in method.
    fn self_shared_lifetime(&self, _: &'a u8) {}
    // No error; bounds exist.
    fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {}
}

fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
    unimplemented!()
}

fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (named on the reference, anonymous on `Foo`).
fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (anonymous on the reference, named on `Foo`).
fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes.
fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
    unimplemented!()
}

trait WithLifetime<'a> {}

type WithLifetimeAlias<'a> = dyn WithLifetime<'a>;

// Should not warn because it won't build without the lifetime.
fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str {
    unimplemented!()
}

// Should warn because there is no lifetime on `Drop`, so this would be
// unambiguous if we elided the lifetime.
fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    unimplemented!()
}

type FooAlias<'a> = Foo<'a>;

fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`).
fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`).
fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes.
fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
    unimplemented!()
}

fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    unimplemented!()
}

fn elided_input_named_output<'a>(_arg: &str) -> &'a str {
    unimplemented!()
}

fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    unimplemented!()
}
fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
    unimplemented!()
}

// Don't warn on these; see issue #292.
fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
    unimplemented!()
}

// See issue #740.
struct Test {
    vec: Vec<usize>,
}

impl Test {
    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
        unimplemented!()
    }
}

trait LintContext<'a> {}

fn f<'a, T: LintContext<'a>>(_: &T) {}

fn test<'a>(x: &'a [u8]) -> u8 {
    let y: &'a u8 = &x[5];
    *y
}

// Issue #3284: give hint regarding lifetime in return type.
struct Cow<'a> {
    x: &'a str,
}
fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    unimplemented!()
}

// Make sure we still warn on implementations
mod issue4291 {
    trait BadTrait {
        fn needless_lt<'a>(x: &'a u8) {}
    }

    impl BadTrait for () {
        fn needless_lt<'a>(_x: &'a u8) {}
    }
}

mod issue2944 {
    trait Foo {}
    struct Bar {}
    struct Baz<'a> {
        bar: &'a Bar,
    }

    impl<'a> Foo for Baz<'a> {}
    impl Bar {
        fn baz<'a>(&'a self) -> impl Foo + 'a {
            Baz { bar: self }
        }
    }
}

mod nested_elision_sites {
    // issue #issue2944

    // closure trait bounds subject to nested elision
    // don't lint because they refer to outer lifetimes
    fn trait_fn<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
        move || i
    }
    fn trait_fn_mut<'a>(i: &'a i32) -> impl FnMut() -> &'a i32 {
        move || i
    }
    fn trait_fn_once<'a>(i: &'a i32) -> impl FnOnce() -> &'a i32 {
        move || i
    }

    // don't lint
    fn impl_trait_in_input_position<'a>(f: impl Fn() -> &'a i32) -> &'a i32 {
        f()
    }
    fn impl_trait_in_output_position<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
        move || i
    }
    // lint
    fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
        f(i)
    }
    fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
        f(i)
    }

    // don't lint
    fn generics_not_elidable<'a, T: Fn() -> &'a i32>(f: T) -> &'a i32 {
        f()
    }
    // lint
    fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
        f(i)
    }

    // don't lint
    fn where_clause_not_elidable<'a, T>(f: T) -> &'a i32
    where
        T: Fn() -> &'a i32,
    {
        f()
    }
    // lint
    fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    where
        T: Fn(&i32) -> &i32,
    {
        f(i)
    }

    // don't lint
    fn pointer_fn_in_input_position<'a>(f: fn(&'a i32) -> &'a i32, i: &'a i32) -> &'a i32 {
        f(i)
    }
    fn pointer_fn_in_output_position<'a>(_: &'a i32) -> fn(&'a i32) -> &'a i32 {
        |i| i
    }
    // lint
    fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
        f(i)
    }

    // don't lint
    fn nested_fn_pointer_1<'a>(_: &'a i32) -> fn(fn(&'a i32) -> &'a i32) -> i32 {
        |f| 42
    }
    fn nested_fn_pointer_2<'a>(_: &'a i32) -> impl Fn(fn(&'a i32)) {
        |f| ()
    }

    // lint
    fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
        |f| 42
    }
    fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
        |f| ()
    }
}

mod issue6159 {
    use std::ops::Deref;
    pub fn apply_deref<'a, T, F, R>(x: &'a T, f: F) -> R
    where
        T: Deref,
        F: FnOnce(&'a T::Target) -> R,
    {
        f(x.deref())
    }
}

fn main() {}
<commit_msg>fix(clippy): add missing allow(dyn_drop)<commit_after>#![warn(clippy::needless_lifetimes)]
#![allow(dead_code, clippy::needless_pass_by_value, clippy::unnecessary_wraps, dyn_drop)]

fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}

fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}

// No error; same lifetime on two params.
fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}

// No error; static involved.
fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}

fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}

fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
    x
}

// No error; multiple input refs.
fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
    x
}

// No error; multiple input refs.
fn multiple_in_and_out_2<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
    x
}

// No error; static involved.
fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
    x
}

// No error.
fn deep_reference_1<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
    Ok(x)
}

// No error; two input refs.
fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
    x.unwrap()
}

fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
    Ok(x)
}

// Where-clause, but without lifetimes.
fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
where
    T: Copy,
{
    Ok(x)
}

type Ref<'r> = &'r u8;

// No error; same lifetime on two params.
fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}

fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}

// No error; bounded lifetime.
fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}

// No error; bounded lifetime.
fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
where
    'b: 'a,
{
}

struct Lt<'a, I: 'static> {
    x: &'a I,
}

// No error; fn bound references `'a`.
fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
where
    F: Fn(Lt<'a, I>) -> Lt<'a, I>,
{
    unreachable!()
}

fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
where
    for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
{
    unreachable!()
}

// No error; see below.
fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
    f(x);
}

fn fn_bound_3_cannot_elide() {
    let x = 42;
    let p = &x;
    let mut q = &x;
    // This will fail if we elide lifetimes of `fn_bound_3`.
    fn_bound_3(p, |y| q = y);
}

// No error; multiple input refs.
fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
    if cond { x } else { f() }
}

struct X {
    x: u8,
}

impl X {
    fn self_and_out<'s>(&'s self) -> &'s u8 {
        &self.x
    }

    // No error; multiple input refs.
    fn self_and_in_out<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
        &self.x
    }

    fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}

    // No error; same lifetimes on two params.
    fn self_and_same_in<'s>(&'s self, _x: &'s u8) {}
}

struct Foo<'a>(&'a u8);

impl<'a> Foo<'a> {
    // No error; lifetime `'a` not defined in method.
    fn self_shared_lifetime(&self, _: &'a u8) {}
    // No error; bounds exist.
    fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {}
}

fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
    unimplemented!()
}

fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (named on the reference, anonymous on `Foo`).
fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (anonymous on the reference, named on `Foo`).
fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes.
fn struct_with_lt4<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
    unimplemented!()
}

trait WithLifetime<'a> {}

type WithLifetimeAlias<'a> = dyn WithLifetime<'a>;

// Should not warn because it won't build without the lifetime.
fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str {
    unimplemented!()
}

// Should warn because there is no lifetime on `Drop`, so this would be
// unambiguous if we elided the lifetime.
fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
    unimplemented!()
}

type FooAlias<'a> = Foo<'a>;

fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`).
fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`).
fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
    unimplemented!()
}

// No warning; two input lifetimes.
fn alias_with_lt4<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
    unimplemented!()
}

fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
    unimplemented!()
}

fn elided_input_named_output<'a>(_arg: &str) -> &'a str {
    unimplemented!()
}

fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
    unimplemented!()
}
fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
    unimplemented!()
}

// Don't warn on these; see issue #292.
fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
    unimplemented!()
}

// See issue #740.
struct Test {
    vec: Vec<usize>,
}

impl Test {
    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
        unimplemented!()
    }
}

trait LintContext<'a> {}

fn f<'a, T: LintContext<'a>>(_: &T) {}

fn test<'a>(x: &'a [u8]) -> u8 {
    let y: &'a u8 = &x[5];
    *y
}

// Issue #3284: give hint regarding lifetime in return type.
struct Cow<'a> {
    x: &'a str,
}
fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
    unimplemented!()
}

// Make sure we still warn on implementations
mod issue4291 {
    trait BadTrait {
        fn needless_lt<'a>(x: &'a u8) {}
    }

    impl BadTrait for () {
        fn needless_lt<'a>(_x: &'a u8) {}
    }
}

mod issue2944 {
    trait Foo {}
    struct Bar {}
    struct Baz<'a> {
        bar: &'a Bar,
    }

    impl<'a> Foo for Baz<'a> {}
    impl Bar {
        fn baz<'a>(&'a self) -> impl Foo + 'a {
            Baz { bar: self }
        }
    }
}

mod nested_elision_sites {
    // issue #issue2944

    // closure trait bounds subject to nested elision
    // don't lint because they refer to outer lifetimes
    fn trait_fn<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
        move || i
    }
    fn trait_fn_mut<'a>(i: &'a i32) -> impl FnMut() -> &'a i32 {
        move || i
    }
    fn trait_fn_once<'a>(i: &'a i32) -> impl FnOnce() -> &'a i32 {
        move || i
    }

    // don't lint
    fn impl_trait_in_input_position<'a>(f: impl Fn() -> &'a i32) -> &'a i32 {
        f()
    }
    fn impl_trait_in_output_position<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
        move || i
    }
    // lint
    fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
        f(i)
    }
    fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
        f(i)
    }

    // don't lint
    fn generics_not_elidable<'a, T: Fn() -> &'a i32>(f: T) -> &'a i32 {
        f()
    }
    // lint
    fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
        f(i)
    }

    // don't lint
    fn where_clause_not_elidable<'a, T>(f: T) -> &'a i32
    where
        T: Fn() -> &'a i32,
    {
        f()
    }
    // lint
    fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
    where
        T: Fn(&i32) -> &i32,
    {
        f(i)
    }

    // don't lint
    fn pointer_fn_in_input_position<'a>(f: fn(&'a i32) -> &'a i32, i: &'a i32) -> &'a i32 {
        f(i)
    }
    fn pointer_fn_in_output_position<'a>(_: &'a i32) -> fn(&'a i32) -> &'a i32 {
        |i| i
    }
    // lint
    fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
        f(i)
    }

    // don't lint
    fn nested_fn_pointer_1<'a>(_: &'a i32) -> fn(fn(&'a i32) -> &'a i32) -> i32 {
        |f| 42
    }
    fn nested_fn_pointer_2<'a>(_: &'a i32) -> impl Fn(fn(&'a i32)) {
        |f| ()
    }

    // lint
    fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
        |f| 42
    }
    fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
        |f| ()
    }
}

mod issue6159 {
    use std::ops::Deref;
    pub fn apply_deref<'a, T, F, R>(x: &'a T, f: F) -> R
    where
        T: Deref,
        F: FnOnce(&'a T::Target) -> R,
    {
        f(x.deref())
    }
}

fn main() {}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %>

// CSS Basic User Interface Module Level 1
// https://drafts.csswg.org/css-ui-3/
<% data.new_style_struct("UI", inherited=False, gecko_name="UIReset") %>

${helpers.single_keyword("ime-mode", "normal auto active disabled inactive",
                         products="gecko", gecko_ffi_name="mIMEMode",
                         animatable=False)}

${helpers.single_keyword("-moz-user-select", "auto text none all", products="gecko",
                         gecko_ffi_name="mUserSelect",
                         gecko_enum_prefix="StyleUserSelect",
                         gecko_inexhaustive=True,
                         animatable=False)}
<commit_msg>Add spec links for ui properties<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %>

// CSS Basic User Interface Module Level 1
// https://drafts.csswg.org/css-ui-3/
<% data.new_style_struct("UI", inherited=False, gecko_name="UIReset") %>

// TODO spec says that UAs should not support this
// we should probably remove from gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=1328331)
${helpers.single_keyword("ime-mode", "normal auto active disabled inactive",
                         products="gecko", gecko_ffi_name="mIMEMode",
                         animatable=False,
                         spec="https://drafts.csswg.org/css-ui/#input-method-editor")}

${helpers.single_keyword("-moz-user-select", "auto text none all", products="gecko",
                         gecko_ffi_name="mUserSelect",
                         gecko_enum_prefix="StyleUserSelect",
                         gecko_inexhaustive=True,
                         animatable=False,
                         spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select")}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %>

// CSS Basic User Interface Module Level 1
// https://drafts.csswg.org/css-ui-3/
<% data.new_style_struct("UI", inherited=False, gecko_name="UIReset") %>

// TODO spec says that UAs should not support this
// we should probably remove from gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=1328331)
${helpers.single_keyword("ime-mode", "auto normal active disabled inactive",
                         products="gecko", gecko_ffi_name="mIMEMode",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-ui/#input-method-editor")}

${helpers.single_keyword("-moz-user-select", "auto text none all element elements" +
                            " toggle tri-state -moz-all -moz-text",
                         products="gecko",
                         alias="-webkit-user-select",
                         gecko_ffi_name="mUserSelect",
                         gecko_enum_prefix="StyleUserSelect",
                         gecko_strip_moz_prefix=False,
                         aliases="-moz-none=none",
                         animation_value_type="none",
                         spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select")}

${helpers.single_keyword("-moz-window-dragging", "default drag no-drag", products="gecko",
                         gecko_ffi_name="mWindowDragging",
                         gecko_enum_prefix="StyleWindowDragging",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         spec="None (Nonstandard Firefox-only property)")}

${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet", products="gecko",
                         gecko_ffi_name="mWindowShadow",
                         gecko_constant_prefix="NS_STYLE_WINDOW_SHADOW",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         internal=True,
                         spec="None (Nonstandard internal property)")}

<%helpers:longhand name="-moz-force-broken-image-icon"
                   products="gecko"
                   animation_value_type="discrete"
                   spec="None (Nonstandard Firefox-only property)">
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;

    no_viewport_percentage!(SpecifiedValue);

    pub mod computed_value {
        #[derive(Debug, Clone, Copy, PartialEq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub struct T(pub bool);
    }

    pub use self::computed_value::T as SpecifiedValue;

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            dest.write_str(if self.0 { "1" } else { "0" })
        }
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(false)
    }

    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        computed_value::T(false)
    }

    impl ComputedValueAsSpecified for SpecifiedValue {}

    pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        match input.expect_integer()? {
            0 => Ok(computed_value::T(false)),
            1 => Ok(computed_value::T(true)),
            _ => Err(StyleParseError::UnspecifiedError.into()),
        }
    }

    impl From<u8> for SpecifiedValue {
        fn from(bits: u8) -> SpecifiedValue {
            SpecifiedValue(bits == 1)
        }
    }

    impl From<SpecifiedValue> for u8 {
        fn from(v: SpecifiedValue) -> u8 {
            match v.0 {
                true => 1u8,
                false => 0u8,
            }
        }
    }
</%helpers:longhand>
<commit_msg>make -moz-user-select property animatable<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %>

// CSS Basic User Interface Module Level 1
// https://drafts.csswg.org/css-ui-3/
<% data.new_style_struct("UI", inherited=False, gecko_name="UIReset") %>

// TODO spec says that UAs should not support this
// we should probably remove from gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=1328331)
${helpers.single_keyword("ime-mode", "auto normal active disabled inactive",
                         products="gecko", gecko_ffi_name="mIMEMode",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-ui/#input-method-editor")}

${helpers.single_keyword("-moz-user-select", "auto text none all element elements" +
                            " toggle tri-state -moz-all -moz-text",
                         products="gecko",
                         alias="-webkit-user-select",
                         gecko_ffi_name="mUserSelect",
                         gecko_enum_prefix="StyleUserSelect",
                         gecko_inexhaustive=True,
                         gecko_strip_moz_prefix=False,
                         aliases="-moz-none=none",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select")}

${helpers.single_keyword("-moz-window-dragging", "default drag no-drag", products="gecko",
                         gecko_ffi_name="mWindowDragging",
                         gecko_enum_prefix="StyleWindowDragging",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         spec="None (Nonstandard Firefox-only property)")}

${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet", products="gecko",
                         gecko_ffi_name="mWindowShadow",
                         gecko_constant_prefix="NS_STYLE_WINDOW_SHADOW",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         internal=True,
                         spec="None (Nonstandard internal property)")}

<%helpers:longhand name="-moz-force-broken-image-icon"
                   products="gecko"
                   animation_value_type="discrete"
                   spec="None (Nonstandard Firefox-only property)">
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;

    no_viewport_percentage!(SpecifiedValue);

    pub mod computed_value {
        #[derive(Debug, Clone, Copy, PartialEq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub struct T(pub bool);
    }

    pub use self::computed_value::T as SpecifiedValue;

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            dest.write_str(if self.0 { "1" } else { "0" })
        }
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(false)
    }

    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        computed_value::T(false)
    }

    impl ComputedValueAsSpecified for SpecifiedValue {}

    pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        match input.expect_integer()? {
            0 => Ok(computed_value::T(false)),
            1 => Ok(computed_value::T(true)),
            _ => Err(StyleParseError::UnspecifiedError.into()),
        }
    }

    impl From<u8> for SpecifiedValue {
        fn from(bits: u8) -> SpecifiedValue {
            SpecifiedValue(bits == 1)
        }
    }

    impl From<SpecifiedValue> for u8 {
        fn from(v: SpecifiedValue) -> u8 {
            match v.0 {
                true => 1u8,
                false => 0u8,
            }
        }
    }
</%helpers:longhand>
<|endoftext|>


<commit_before>use quick_csv::Csv;
use rustc_serialize;
use utilities::abs_standard_deviation;
use ::std::marker::PhantomData;

pub trait Record<U> {
    fn record_len() -> usize;
    fn data_at(&self, index: usize) -> f32;
    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32));
    fn values(&self) -> Vec<f32>;
    fn get_class(&self) -> &U;
}

#[derive(Debug, RustcDecodable)]
pub struct MpgRecord<U> {
    class: U,
    values: [f32; 5],
}

impl<U> Record<U> for MpgRecord<U> {
    fn record_len() -> usize {
        5
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> &U {
        &self.class
    }
}

#[derive(Debug, RustcDecodable)]
pub struct IrisRecord<U> {
    class: U,
    values: [f32; 4],
}

impl<U> Record<U> for IrisRecord<U> {
    fn record_len() -> usize {
        4
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> &U {
        &self.class
    }
}

#[derive(Debug)]
pub struct Database<T, U>
    where T: Record<U>
{
    data: Vec<T>,
    abs_sd: Vec<(f32, f32)>,
    phantom: PhantomData<U>,
}

impl<T, U> Database<T, U>
    where T: rustc_serialize::Decodable + ::std::fmt::Debug + Record<U>
{
    pub fn new() -> Database<T, U> {
        Database {
            data: Vec::new(),
            abs_sd: Vec::new(),
            phantom: PhantomData
        }
    }

    pub fn from_file(path: &str) -> Database<T, U> {
        let rdr = Csv::from_file(path).unwrap().has_header(true);
        let mut data: Vec<T> = Vec::new();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => data.push(cols),
                Err(error) => println!("{}", error),
            }
        }

        Database {
            data: data,
            abs_sd: Vec::new(),
            phantom: PhantomData
        }
    }

    pub fn add_file(&mut self, path: &str) {
        let rdr = Csv::from_file(path).unwrap();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => self.data.push(cols),
                Err(error) => println!("{}", error),
            }
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        let record_len = T::record_len();
        let mut mult_feat_vec = vec![Vec::<f32>::new(); record_len];

        for rcrd in self.data.iter() {
            for i in 0..record_len {
                mult_feat_vec[i].push(rcrd.data_at(i));
            }
        }

        let mut i = 0;
        for feat_vec in mult_feat_vec.iter() {
            let asd_median_tup = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}", i, asd_median_tup.0, asd_median_tup.1);

            for rcrd in self.data.iter_mut() {
                rcrd.standarize_field(i, &asd_median_tup);
            }

            self.abs_sd.push(asd_median_tup);
            i += 1;
        }
    }

    fn nearest_neighbors(&self, rcrd: &T, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&rcrd.values(), &record.values()), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let indexes = distances.into_iter().map(|x| x.1).collect();
        indexes
    }

    // pub fn predict(&self, vals: Vec<f32>) -> T<U> {
    //     let record_len = T::record_len();
    //     if val
    //     let mut record = T::new();
    //     record.set_values(vals.as_ref());
    //     for i in 0..record_len {
    //         rcrd.standarize_field(i, self.abs_sd[i]);
    //     }
    //     record.set_class()
    // }

    // pub fn cross_validation(training_path: &str, n: usize, prefix: &str) {
    //     let mut precision = 0.0;

    //     for j in 1..n + 1 {
    //         let mut db = MpgDatabase::new();

    //         for i in 1..n + 1 {
    //             if i != j {
    //                 let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                                    prefix,
    //                                    number = i,
    //                                    width = 2);
    //                 db.add_file(path.as_ref());
    //             }
    //         }

    //         db.standarize();
    //         let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                            prefix,
    //                            number = j,
    //                            width = 2);
    //         let mut rdr = csv::Reader::from_file(path)
    //             .unwrap()
    //             .delimiter(b'\t')
    //             .has_headers(false);

    //         let mut n_correct = 0;
    //         let mut n_incorrect = 0;
    //         let mut count = 0;
    //         for record in rdr.decode() {
    //             let mut rcrd: (MpgRecord, String) = record.unwrap();
    //             let pred = db.predict(rcrd.0.cylinders,
    //                                   rcrd.0.ci,
    //                                   rcrd.0.hp,
    //                                   rcrd.0.weight,
    //                                   rcrd.0.secs);

    //             db.standarize_record(&mut rcrd.0);

    //             if rcrd.0.mpg == pred.mpg {
    //                 n_correct += 1;
    //             } else {
    //                 n_incorrect += 1;
    //             }
    //             count += 1;
    //         }

    //         println!("Correct: {}%\nIncorrect: {}%\n",
    //                  n_correct as f32 * 100.0 / count as f32,
    //                  n_incorrect as f32 * 100.0 / count as f32);

    //         presition += n_correct as f32 * 100.0 / count as f32;
    //     }

    //     presition /= n as f32;
    //     println!("Avg pres: {}%", presition);
    // }
}
<commit_msg>Clone trait for generic U<commit_after>use quick_csv::Csv;
use rustc_serialize;
use utilities::abs_standard_deviation;
use ::std::marker::PhantomData;
use ::std::clone::Clone;
use distance::manhattan_dist;

pub trait Record<U>
    where U: Clone
{
    fn record_len() -> usize;
    fn data_at(&self, index: usize) -> f32;
    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32));
    fn values(&self) -> Vec<f32>;
    fn set_values(&mut self, Vec<f32>);
    fn get_class(&self) -> U;
}

#[derive(Debug, RustcDecodable)]
pub struct MpgRecord<U> {
    class: U,
    values: [f32; 5],
}

impl<U> Record<U> for MpgRecord<U>
    where U: Clone
{
    fn record_len() -> usize {
        5
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> U {
        self.class.clone()
    }

    fn set_values(&mut self, values: Vec<f32>) {
        for i in 0..self.values.len() {
            self.values[i] = values[i];
        }
    }
}

#[derive(Debug, RustcDecodable)]
pub struct IrisRecord<U> {
    class: U,
    values: [f32; 4],
}

impl<U> Record<U> for IrisRecord<U>
    where U: Clone
{
    fn record_len() -> usize {
        4
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> U {
        self.class.clone()
    }

    fn set_values(&mut self, values: Vec<f32>) {
        for i in 0..self.values.len() {
            self.values[i] = values[i];
        }
    }
}

#[derive(Debug)]
pub struct Database<T, U>
    where T: Record<U>,
          U: Clone
{
    data: Vec<T>,
    abs_sd: Vec<(f32, f32)>,
    phantom: PhantomData<U>,
}

impl<T, U> Database<T, U>
    where T: rustc_serialize::Decodable + ::std::fmt::Debug + Record<U>,
          U: Clone
{
    pub fn new() -> Database<T, U> {
        Database {
            data: Vec::new(),
            abs_sd: Vec::new(),
            phantom: PhantomData
        }
    }

    pub fn from_file(path: &str) -> Database<T, U> {
        let rdr = Csv::from_file(path).unwrap().has_header(true);
        let mut data: Vec<T> = Vec::new();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => data.push(cols),
                Err(error) => println!("{}", error),
            }
        }

        Database {
            data: data,
            abs_sd: Vec::new(),
            phantom: PhantomData
        }
    }

    pub fn add_file(&mut self, path: &str) {
        let rdr = Csv::from_file(path).unwrap();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => self.data.push(cols),
                Err(error) => println!("{}", error),
            }
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        let record_len = T::record_len();
        let mut mult_feat_vec = vec![Vec::<f32>::new(); record_len];

        for rcrd in self.data.iter() {
            for i in 0..record_len {
                mult_feat_vec[i].push(rcrd.data_at(i));
            }
        }

        let mut i = 0;
        for feat_vec in mult_feat_vec.iter() {
            let asd_median_tup = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}", i, asd_median_tup.0, asd_median_tup.1);

            for rcrd in self.data.iter_mut() {
                rcrd.standarize_field(i, &asd_median_tup);
            }

            self.abs_sd.push(asd_median_tup);
            i += 1;
        }
    }

    fn nearest_neighbors(&self, rcrd: &T, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&rcrd.values(), &record.values()), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let indexes = distances.into_iter().map(|x| x.1).collect();
        indexes
    }

    pub fn predict(&self, mut record: T) -> U {
        let record_len = T::record_len();
        // if record_len != vals.len() {
        //     panic!("vals lenght should be {} instead of {}", record_len, vals.len());
        // }
        for i in 0..record_len {
            record.standarize_field(i, &self.abs_sd[i]);
        }

        self.data[self.nearest_neighbors(&record, manhattan_dist)[0]].get_class()
    }

    // pub fn cross_validation(training_path: &str, n: usize, prefix: &str) {
    //     let mut precision = 0.0;

    //     for j in 1..n + 1 {
    //         let mut db = MpgDatabase::new();

    //         for i in 1..n + 1 {
    //             if i != j {
    //                 let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                                    prefix,
    //                                    number = i,
    //                                    width = 2);
    //                 db.add_file(path.as_ref());
    //             }
    //         }

    //         db.standarize();
    //         let path = format!("../../data/cross-validation/{}-{number:>0width$}",
    //                            prefix,
    //                            number = j,
    //                            width = 2);
    //         let mut rdr = csv::Reader::from_file(path)
    //             .unwrap()
    //             .delimiter(b'\t')
    //             .has_headers(false);

    //         let mut n_correct = 0;
    //         let mut n_incorrect = 0;
    //         let mut count = 0;
    //         for record in rdr.decode() {
    //             let mut rcrd: (MpgRecord, String) = record.unwrap();
    //             let pred = db.predict(rcrd.0.cylinders,
    //                                   rcrd.0.ci,
    //                                   rcrd.0.hp,
    //                                   rcrd.0.weight,
    //                                   rcrd.0.secs);

    //             db.standarize_record(&mut rcrd.0);

    //             if rcrd.0.mpg == pred.mpg {
    //                 n_correct += 1;
    //             } else {
    //                 n_incorrect += 1;
    //             }
    //             count += 1;
    //         }

    //         println!("Correct: {}%\nIncorrect: {}%\n",
    //                  n_correct as f32 * 100.0 / count as f32,
    //                  n_incorrect as f32 * 100.0 / count as f32);

    //         presition += n_correct as f32 * 100.0 / count as f32;
    //     }

    //     presition /= n as f32;
    //     println!("Avg pres: {}%", presition);
    // }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A grid line type.

use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;

#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line
#[allow(missing_docs)]
pub struct GridLine {
    pub is_span: bool,
    pub ident: Option<String>,
    pub integer: Option<i32>,
}

impl Default for GridLine {
    fn default() -> Self {
        GridLine {
            is_span: false,
            ident: None,
            integer: None,
        }
    }
}

impl ToCss for GridLine {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        if !self.is_span && self.ident.is_none() && self.integer.is_none() {
            return dest.write_str("auto")
        }

        if self.is_span {
            try!(dest.write_str("span"));
        }

        if let Some(i) = self.integer {
            try!(write!(dest, " {}", i));
        }

        if let Some(ref s) = self.ident {
            try!(write!(dest, " {}", s));
        }

        Ok(())
    }
}

impl Parse for GridLine {
    fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        let mut grid_line = Default::default();
        if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
            return Ok(grid_line)
        }

        for _ in 0..3 {     // Maximum possible entities for <grid-line>
            if input.try(|i| i.expect_ident_matching("span")).is_ok() {
                if grid_line.is_span {
                    return Err(())
                }
                grid_line.is_span = true;
            } else if let Ok(i) = input.try(|i| i.expect_integer()) {
                if i == 0 || grid_line.integer.is_some() {
                    return Err(())
                }
                grid_line.integer = Some(i);
            } else if let Ok(name) = input.try(|i| i.expect_ident()) {
                if grid_line.ident.is_some() {
                    return Err(())
                }
                grid_line.ident = Some(name.into_owned());
            } else {
                break
            }
        }

        if grid_line.is_span {
            if let Some(i) = grid_line.integer {
                if i < 0 {      // disallow negative integers for grid spans
                    return Err(())
                }
            } else {
                grid_line.integer = Some(1);
            }
        }

        Ok(grid_line)
    }
}

impl ComputedValueAsSpecified for GridLine {}
no_viewport_percentage!(GridLine);
<commit_msg>Add parsing/serialization for <track-breadth><commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A grid line type.

use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::ToCss;
use values::{CSSFloat, HasViewportPercentage};
use values::computed::ComputedValueAsSpecified;
use values::specified::LengthOrPercentage;

#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line
#[allow(missing_docs)]
pub struct GridLine {
    pub is_span: bool,
    pub ident: Option<String>,
    pub integer: Option<i32>,
}

impl Default for GridLine {
    fn default() -> Self {
        GridLine {
            is_span: false,
            ident: None,
            integer: None,
        }
    }
}

impl ToCss for GridLine {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        if !self.is_span && self.ident.is_none() && self.integer.is_none() {
            return dest.write_str("auto")
        }

        if self.is_span {
            try!(dest.write_str("span"));
        }

        if let Some(i) = self.integer {
            try!(write!(dest, " {}", i));
        }

        if let Some(ref s) = self.ident {
            try!(write!(dest, " {}", s));
        }

        Ok(())
    }
}

impl Parse for GridLine {
    fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        let mut grid_line = Default::default();
        if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
            return Ok(grid_line)
        }

        for _ in 0..3 {     // Maximum possible entities for <grid-line>
            if input.try(|i| i.expect_ident_matching("span")).is_ok() {
                if grid_line.is_span {
                    return Err(())
                }
                grid_line.is_span = true;
            } else if let Ok(i) = input.try(|i| i.expect_integer()) {
                if i == 0 || grid_line.integer.is_some() {
                    return Err(())
                }
                grid_line.integer = Some(i);
            } else if let Ok(name) = input.try(|i| i.expect_ident()) {
                if grid_line.ident.is_some() {
                    return Err(())
                }
                grid_line.ident = Some(name.into_owned());
            } else {
                break
            }
        }

        if grid_line.is_span {
            if let Some(i) = grid_line.integer {
                if i < 0 {      // disallow negative integers for grid spans
                    return Err(())
                }
            } else {
                grid_line.integer = Some(1);
            }
        }

        Ok(grid_line)
    }
}

impl ComputedValueAsSpecified for GridLine {}
no_viewport_percentage!(GridLine);

define_css_keyword_enum!{ TrackKeyword:
    "auto" => Auto,
    "max-content" => MaxContent,
    "min-content" => MinContent
}

#[allow(missing_docs)]
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-grid/#typedef-track-breadth
pub enum TrackBreadth<L> {
    Breadth(L),
    Flex(CSSFloat),
    Keyword(TrackKeyword),
}

/// Parse a single flexible length.
pub fn parse_flex(input: &mut Parser) -> Result<CSSFloat, ()> {
    match try!(input.next()) {
        Token::Dimension(ref value, ref unit) if unit.to_lowercase() == "fr" && value.value.is_sign_positive()
            => Ok(value.value),
        _ => Err(()),
    }
}

impl Parse for TrackBreadth<LengthOrPercentage> {
    fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        if let Ok(lop) = input.try(LengthOrPercentage::parse_non_negative) {
            Ok(TrackBreadth::Breadth(lop))
        } else {
            if let Ok(f) = input.try(parse_flex) {
                Ok(TrackBreadth::Flex(f))
            } else {
                TrackKeyword::parse(input).map(TrackBreadth::Keyword)
            }
        }
    }
}

impl<L: ToCss> ToCss for TrackBreadth<L> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match *self {
            TrackBreadth::Breadth(ref lop) => lop.to_css(dest),
            TrackBreadth::Flex(ref value) => write!(dest, "{}fr", value),
            TrackBreadth::Keyword(ref k) => k.to_css(dest),
        }
    }
}

impl HasViewportPercentage for TrackBreadth<LengthOrPercentage> {
    #[inline]
    fn has_viewport_percentage(&self) -> bool {
        if let TrackBreadth::Breadth(ref lop) = *self {
            lop.has_viewport_percentage()
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>// Chapter 1
// ------------------ print macros start ------------------
// Macros: Macros look like functions, except that their name ends with a bang !,
// but instead of generating a function call, macros are expanded into source code
// that gets compiled with the rest of the program. eg. println!
// println! -> prints statement to console in a new line

// !!!--- start uncommenting from line below ---!!!
// fn main() {
//     println!("April has {} days.", 31);
//     println!("{month} has {numberOfDays} days.",
//         month = "January",
//         numberOfDays = "31");
//     // Special formating is used here
//     // {:b} -> converts 2 to 10 (binary form)
//     println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
//     let width = 6;
//     println!("{number:>width$} {spaces} spaces and {number}", number = 1, width = width, spaces = width - 1);
//     println!("{}", format!("{:05}", 12));

//     // rounds off the number
//     let pi = 3.141592;
//     println!("Pi is roughly {:.3}", pi);
// }
// !!!--- end uncommenting from line above ---!!!
// ------------------ print macros end ------------------

// Chapter 2
// ------------------ Debugging start ------------------
// In JS we use console.log() for logging and debugging purposes.
// console.log() can be used to print pretty any type of object.
// However, in Rust this is not possible as all types which want to use
// std::fmt formatting traits require an implementation to be printable.
// The fmt::Debug trait makes this very straightforward.
// All types can derive (automatically create) the fmt::Debug implementation.
// This is not true for fmt::Display which must be manually implemented.
// Below given example shows automatic derive(Debug) implementation
// and manual Display implementation.

// !!!--- start uncommenting from line below ---!!!
// Import (via `use`) the `fmt` module to make it available.
use std::fmt::{self, Formatter, Display};
#[derive(Debug)]
struct Person<'a> {
    name: &'a str,
    age: u8
}

// Implement `Display` for `Person`.
impl<'a> fmt::Display for Person<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Try `write!` to see if it errors. If it errors, return
        // the error. Otherwise continue.
        write!(f, "(Name is {} and Age is {})", self.name, self.age)?;
        write!(f, "")
    }
}

#[derive(Debug)]
struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

impl Display for Color {
    // `f` is a buffer, this method must write the formatted string into it
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        // `write!` is like `format!`, but it will write the formatted string
        // into a buffer (the first argument)
        write!(f, "RGB ({}, {}, {}) 0x{:02.X}{:02.X}{:02.X}",
            self.red, self.green, self.blue, self.red, self.green, self.blue)
    }
}

fn main() {
    let name = "Peter";
    let age = 27;
    let peter = Person { name, age };

    println!("Compare Person");
    println!("Debug: Normal {:?}", peter);
    println!("Debug: Pretty {:#?}", peter);
    println!("Display: {}", peter);

    for color in [
        Color { red: 128, green: 255, blue: 90 },
        Color { red: 0, green: 3, blue: 254 },
        Color { red: 0, green: 0, blue: 0 },
    ].iter() {
        // Switch this to use {} once you've added an implementation
        // for fmt::Display
        println!("{:}", *color);
    }
}
// !!!--- end uncommenting from line above ---!!!
// ------------------ Debugging end ------------------<commit_msg>start with chapter 3 primitives<commit_after>// Chapter 1
// ------------------ print macros start ------------------
// Macros: Macros look like functions, except that their name ends with a bang !,
// but instead of generating a function call, macros are expanded into source code
// that gets compiled with the rest of the program. eg. println!
// println! -> prints statement to console in a new line

// !!!--- start uncommenting from line below ---!!!
// fn main() {
//     println!("April has {} days.", 31);
//     println!("{month} has {numberOfDays} days.",
//         month = "January",
//         numberOfDays = "31");
//     // Special formating is used here
//     // {:b} -> converts 2 to 10 (binary form)
//     println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
//     let width = 6;
//     println!("{number:>width$} {spaces} spaces and {number}", number = 1, width = width, spaces = width - 1);
//     println!("{}", format!("{:05}", 12));

//     // rounds off the number
//     let pi = 3.141592;
//     println!("Pi is roughly {:.3}", pi);
// }
// !!!--- end uncommenting from line above ---!!!
// ------------------ print macros end ------------------

// Chapter 2
// ------------------ Debugging start ------------------
// In JS we use console.log() for logging and debugging purposes.
// console.log() can be used to print pretty any type of object.
// However, in Rust this is not possible as all types which want to use
// std::fmt formatting traits require an implementation to be printable.
// The fmt::Debug trait makes this very straightforward.
// All types can derive (automatically create) the fmt::Debug implementation.
// This is not true for fmt::Display which must be manually implemented.
// Below given example shows automatic derive(Debug) implementation
// and manual Display implementation.

// !!!--- start uncommenting from line below ---!!!
// Import (via `use`) the `fmt` module to make it available.
// use std::fmt::{self, Formatter, Display};
// #[derive(Debug)]
// struct Person<'a> {
//     name: &'a str,
//     age: u8
// }

// // Implement `Display` for `Person`.
// impl<'a> fmt::Display for Person<'a> {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         // Try `write!` to see if it errors. If it errors, return
//         // the error. Otherwise continue.
//         write!(f, "(Name is {} and Age is {})", self.name, self.age)?;
//         write!(f, "")
//     }
// }

// #[derive(Debug)]
// struct Color {
//     red: u8,
//     green: u8,
//     blue: u8,
// }

// impl Display for Color {
//     // `f` is a buffer, this method must write the formatted string into it
//     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
//         // `write!` is like `format!`, but it will write the formatted string
//         // into a buffer (the first argument)
//         write!(f, "RGB ({}, {}, {}) 0x{:02.X}{:02.X}{:02.X}",
//             self.red, self.green, self.blue, self.red, self.green, self.blue)
//     }
// }

// fn main() {
//     let name = "Peter";
//     let age = 27;
//     let peter = Person { name, age };

//     println!("Compare Person");
//     println!("Debug: Normal {:?}", peter);
//     println!("Debug: Pretty {:#?}", peter);
//     println!("Display: {}", peter);

//     for color in [
//         Color { red: 128, green: 255, blue: 90 },
//         Color { red: 0, green: 3, blue: 254 },
//         Color { red: 0, green: 0, blue: 0 },
//     ].iter() {
//         // Switch this to use {} once you've added an implementation
//         // for fmt::Display
//         println!("{:}", *color);
//     }
// }
// !!!--- end uncommenting from line above ---!!!
// ------------------ Debugging end ------------------

// Chapter 3
// ------------------ Primitives start ------------------
// Rust provides access to a wide variety of primitives.

// !!!--- start uncommenting from line below ---!!!
fn main() {
    // Variables can be type annotated.
    let logical: bool = true;

    let a_float: f64 = 1.0;  // Regular annotation
    let an_integer   = 5i32; // Suffix annotation

    // Or a default will be used.
    let default_float   = 3.0; // `f64`
    let default_integer = 7;   // `i32`

    // A type can also be inferred from context
    let mut inferred_type = 12; // Type i64 is inferred from another line
    inferred_type = 4294967296i64;

    // A mutable variable's value can be changed.
    let mut mutable = 12; // Mutable `i32`
    mutable = 21;

    // Error! The type of a variable can't be changed.
    //mutable = true;

    // Variables can be overwritten with shadowing.
    let mutable = true;
}
// !!!--- end uncommenting from line above ---!!!
// ------------------ Primitives end ------------------<|endoftext|>


<commit_before>use crate::math::Isometry;
use na::Real;
use crate::query::{ContactManifold, ContactPrediction};
use crate::shape::Shape;
use crate::query::ContactPreprocessor;
use std::any::Any;
use crate::utils::IdAllocator;

/// Trait implemented algorithms that compute contact points, normals and penetration depths.
pub trait ContactManifoldGenerator<N: Real>: Any + Send + Sync {
    /// Runs the collision detection on two objects. It is assumed that the same
    /// collision detector (the same structure) is always used with the same
    /// pair of object.
    fn generate_contacts(
        &mut self,
        dispatcher: &ContactDispatcher<N>,
        ma: &Isometry<N>,
        a: &Shape<N>,
        proc1: Option<&ContactPreprocessor<N>>,
        mb: &Isometry<N>,
        b: &Shape<N>,
        proc2: Option<&ContactPreprocessor<N>>,
        prediction: &ContactPrediction<N>,
        id_alloc: &mut IdAllocator,
        manifold: &mut ContactManifold<N>,
    ) -> bool;

    /// Generate an empty contact manifold configured as required by this contact manifold generator.
    fn init_manifold(&self) -> ContactManifold<N> {
        ContactManifold::new()
    }
}

pub type ContactAlgorithm<N> = Box<ContactManifoldGenerator<N>>;

pub trait ContactDispatcher<N>: Any + Send + Sync {
    /// Allocate a collision algorithm corresponding to the given pair of shapes.
    fn get_contact_algorithm(&self, a: &Shape<N>, b: &Shape<N>) -> Option<ContactAlgorithm<N>>;
}
<commit_msg>Tweak content processing comments<commit_after>use crate::math::Isometry;
use na::Real;
use crate::query::{ContactManifold, ContactPrediction};
use crate::shape::Shape;
use crate::query::ContactPreprocessor;
use std::any::Any;
use crate::utils::IdAllocator;

/// An algorithm to compute contact points, normals and penetration depths between two specific
/// objects.
pub trait ContactManifoldGenerator<N: Real>: Any + Send + Sync {
    /// Runs the collision detection on two objects. It is assumed that the same
    /// collision detector (the same structure) is always used with the same
    /// pair of objects.
    ///
    /// Returns `false` if persisting this algorithm for re-use is unlikely to improve performance,
    /// e.g. due to the objects being distant. Note that if the `ContactManifoldGenerator` would
    /// likely be immediately reconstructed in the next time-step, dropping it is sub-optimal
    /// regardless.
    fn generate_contacts(
        &mut self,
        dispatcher: &ContactDispatcher<N>,
        ma: &Isometry<N>,
        a: &Shape<N>,
        proc1: Option<&ContactPreprocessor<N>>,
        mb: &Isometry<N>,
        b: &Shape<N>,
        proc2: Option<&ContactPreprocessor<N>>,
        prediction: &ContactPrediction<N>,
        id_alloc: &mut IdAllocator,
        manifold: &mut ContactManifold<N>,
    ) -> bool;

    /// Generate an empty contact manifold configured as required by this contact manifold generator.
    fn init_manifold(&self) -> ContactManifold<N> {
        ContactManifold::new()
    }
}

pub type ContactAlgorithm<N> = Box<ContactManifoldGenerator<N>>;

pub trait ContactDispatcher<N>: Any + Send + Sync {
    /// Allocate a collision algorithm corresponding to a pair of objects with the given shapes.
    fn get_contact_algorithm(&self, a: &Shape<N>, b: &Shape<N>) -> Option<ContactAlgorithm<N>>;
}
<|endoftext|>


<commit_before>use super::MessageAction;
use super::InjectMode;
use config::action::ExecCondition;

use handlebars::Template;
use handlebars::Handlebars;
use serde::de::{Deserialize, Deserializer, Error, MapVisitor, Visitor};
use std::collections::BTreeMap;
use super::MESSAGE;

impl Deserialize for MessageAction {
    fn deserialize<D>(deserializer: &mut D) -> Result<MessageAction, D::Error>
        where D: Deserializer
    {
        deserializer.visit_struct("MessageAction", &[], MessageActionVisitor)
    }
}

enum Field {
    Uuid,
    Name,
    Message,
    Values,
    When,
    InjectMode,
}

impl Deserialize for Field {
    fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
        where D: Deserializer
    {
        struct FieldVisitor;

        impl Visitor for FieldVisitor {
            type Value = Field;

            fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
                where E: Error
            {
                match value {
                    "name" => Ok(Field::Name),
                    "uuid" => Ok(Field::Uuid),
                    "values" => Ok(Field::Values),
                    "message" => Ok(Field::Message),
                    "when" => Ok(Field::When),
                    "inject_mode" => Ok(Field::InjectMode),
                    _ => Err(Error::syntax(&format!("Unexpected field: {}", value))),
                }
            }
        }

        deserializer.visit(FieldVisitor)
    }
}

struct MessageActionVisitor;

impl MessageActionVisitor {
    fn compile_template<V>(template_string: String, uuid: &str) -> Result<Template, V::Error>
        where V: MapVisitor
    {
        match Template::compile(template_string) {
            Ok(message) => Ok(message),
            Err(error) => {
                Err(Error::syntax(&format!("Invalid handlebars template in 'message' field: \
                                            uuid={}, error={}",
                                           uuid,
                                           error)))
            }
        }
    }
}

impl Visitor for MessageActionVisitor {
    type Value = MessageAction;

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<MessageAction, V::Error>
        where V: MapVisitor
    {
        let mut name: Option<String> = None;
        let mut uuid: Option<String> = None;
        let mut message: Option<String> = None;
        let mut values: Option<BTreeMap<String, String>> = None;
        let mut when: ExecCondition = ExecCondition::new();
        let mut inject_mode = Default::default();

        while let Some(field) = try!(visitor.visit_key()) {
            match field {
                Field::Name => name = Some(try!(visitor.visit_value())),
                Field::Uuid => uuid = Some(try!(visitor.visit_value())),
                Field::Message => message = Some(try!(visitor.visit_value())),
                Field::Values => values = Some(try!(visitor.visit_value())),
                Field::When => when = try!(visitor.visit_value()),
                Field::InjectMode => inject_mode = try!(visitor.visit_value()),
            }
        }

        let uuid = match uuid {
            Some(uuid) => uuid,
            None => return visitor.missing_field("uuid"),
        };

        let message = match message {
            Some(message) => try!(MessageActionVisitor::compile_template::<V>(message, &uuid)),
            None => {
                error!("Missing 'message' field: uuid={}", &uuid);
                return visitor.missing_field("message");
            }
        };

        let mut values = match values {
            Some(values) => {
                let mut registry = Handlebars::new();
                for (key, value) in values.into_iter() {
                    let template = try!(MessageActionVisitor::compile_template::<V>(value, &uuid));
                    registry.register_template(&key, template);
                }
                registry
            }
            None => Handlebars::new(),
        };

        try!(visitor.end());

        values.register_template(MESSAGE, message.clone());

        Ok(MessageAction {
            uuid: uuid,
            message: message,
            name: name,
            values: values,
            when: when,
            inject_mode: inject_mode,
        })
    }
}

impl Deserialize for InjectMode {
    fn deserialize<D>(deserializer: &mut D) -> Result<InjectMode, D::Error>
        where D: Deserializer
    {
        struct FieldVisitor;

        impl Visitor for FieldVisitor {
            type Value = InjectMode;

            fn visit_str<E>(&mut self, value: &str) -> Result<InjectMode, E>
                where E: Error
            {
                match value {
                    "log" => Ok(InjectMode::Log),
                    "loopback" => Ok(InjectMode::Loopback),
                    "forward" => Ok(InjectMode::Forward),
                    _ => Err(Error::syntax(&format!("Unexpected field: {}", value))),
                }
            }
        }

        deserializer.visit(FieldVisitor)
    }
}

#[cfg(test)]
mod test {
    use config::action::message::{MessageActionBuilder, MessageAction, InjectMode};

    use handlebars::Template;
    use serde_json::from_str;

    fn assert_message_action_eq(expected: &MessageAction, actual: &MessageAction) {
        assert_eq!(expected.uuid(), actual.uuid());
        assert_eq!(expected.name(), actual.name());
        assert_eq!(expected.message(), actual.message());
    }

    #[test]
    fn test_given_message_as_a_json_string_when_it_is_deserialized_then_we_get_the_expected_message
        () {
        let text = r#"
        {
          "uuid": "UUID",
          "name": "NAME",
          "message": "message",
          "values": {
            "key1": "value1",
            "key2": "value2"
          }
        }
        "#;

        let message = Template::compile("message".to_owned())
                          .expect("Failed to compile a handlebars template");
        let value1 = Template::compile("value1".to_owned())
                         .expect("Failed to compile a handlebars template");
        let value2 = Template::compile("value2".to_owned())
                         .expect("Failed to compile a handlebars template");
        let expected_message = MessageActionBuilder::new("UUID", message)
                                   .name(Some("NAME"))
                                   .pair("key1", value1)
                                   .pair("key2", value2)
                                   .build();
        let result = from_str::<MessageAction>(text);
        let message = result.expect("Failed to deserialize a valid MessageAction object");
        assert_message_action_eq(&expected_message, &message);
    }

    #[test]
    fn test_given_message_as_a_json_string_when_only_the_required_fields_are_present_then_we_can_deserialize_the_message
        () {
        let text = r#"
        {
          "uuid": "UUID",
          "message": "message"
        }
        "#;

        let message = Template::compile("message".to_owned())
                          .expect("Failed to compile a handlebars template");
        let expected_message = MessageActionBuilder::new("UUID", message).build();
        let result = from_str::<MessageAction>(text);
        let message = result.expect("Failed to deserialize a valid MessageAction object");
        assert_message_action_eq(&expected_message, &message);
    }

    #[test]
    fn test_given_message_as_a_json_string_when_one_of_the_required_fields_are_not_present_then_we_get_error
        () {
        let text = r#"
        {
        }
        "#;

        let result = from_str::<MessageAction>(text);
        let _ = result.err().expect("Successfully deserialized an invalid MessageAction object");
    }

    #[test]
    fn test_given_inject_modes_when_they_are_deserialized_then_we_get_the_right_result() {
        let text = r#"
        ["forward", "log", "loopback", "log"]
        "#;
        let expected = vec![InjectMode::Forward,
                            InjectMode::Log,
                            InjectMode::Loopback,
                            InjectMode::Log];

        let result = from_str::<Vec<InjectMode>>(text);
        println!("{:?}", &result);
        let array = result.expect("Failed to deserialize a valid array of inject modes");
        assert_eq!(&expected, &array);
    }

    #[test]
    fn test_given_invalid_inject_mode_when_it_is_deserialized_then_we_get_the_right_result() {
        let text = r#"
        ["invalid inject mode", "log"]
        "#;

        let result = from_str::<Vec<InjectMode>>(text);
        println!("{:?}", &result);
        let _ = result.err().expect("Successfully deserialized an invalid inject mode");
    }

    #[test]
    fn test_given_message_when_it_contains_inject_mode_then_it_can_be_deserialized() {
        let text = r#"
        {
          "uuid": "UUID",
          "message": "message",
          "inject_mode": "forward"
        }
        "#;

        let message = Template::compile("message".to_owned())
                          .expect("Failed to compile a handlebars template");
        let expected_message = MessageActionBuilder::new("UUID", message)
                                   .inject_mode(InjectMode::Forward)
                                   .build();
        let result = from_str::<MessageAction>(text);
        let message = result.expect("Failed to deserialize a valid MessageAction object");
        assert_message_action_eq(&expected_message, &message);
    }
}
<commit_msg>MessageAction: add unit test to cover unknown fields<commit_after>use super::MessageAction;
use super::InjectMode;
use config::action::ExecCondition;

use handlebars::Template;
use handlebars::Handlebars;
use serde::de::{Deserialize, Deserializer, Error, MapVisitor, Visitor};
use std::collections::BTreeMap;
use super::MESSAGE;

impl Deserialize for MessageAction {
    fn deserialize<D>(deserializer: &mut D) -> Result<MessageAction, D::Error>
        where D: Deserializer
    {
        deserializer.visit_struct("MessageAction", &[], MessageActionVisitor)
    }
}

enum Field {
    Uuid,
    Name,
    Message,
    Values,
    When,
    InjectMode,
}

impl Deserialize for Field {
    fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
        where D: Deserializer
    {
        struct FieldVisitor;

        impl Visitor for FieldVisitor {
            type Value = Field;

            fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
                where E: Error
            {
                match value {
                    "name" => Ok(Field::Name),
                    "uuid" => Ok(Field::Uuid),
                    "values" => Ok(Field::Values),
                    "message" => Ok(Field::Message),
                    "when" => Ok(Field::When),
                    "inject_mode" => Ok(Field::InjectMode),
                    _ => Err(Error::syntax(&format!("Unexpected field: {}", value))),
                }
            }
        }

        deserializer.visit(FieldVisitor)
    }
}

struct MessageActionVisitor;

impl MessageActionVisitor {
    fn compile_template<V>(template_string: String, uuid: &str) -> Result<Template, V::Error>
        where V: MapVisitor
    {
        match Template::compile(template_string) {
            Ok(message) => Ok(message),
            Err(error) => {
                Err(Error::syntax(&format!("Invalid handlebars template in 'message' field: \
                                            uuid={}, error={}",
                                           uuid,
                                           error)))
            }
        }
    }
}

impl Visitor for MessageActionVisitor {
    type Value = MessageAction;

    fn visit_map<V>(&mut self, mut visitor: V) -> Result<MessageAction, V::Error>
        where V: MapVisitor
    {
        let mut name: Option<String> = None;
        let mut uuid: Option<String> = None;
        let mut message: Option<String> = None;
        let mut values: Option<BTreeMap<String, String>> = None;
        let mut when: ExecCondition = ExecCondition::new();
        let mut inject_mode = Default::default();

        while let Some(field) = try!(visitor.visit_key()) {
            match field {
                Field::Name => name = Some(try!(visitor.visit_value())),
                Field::Uuid => uuid = Some(try!(visitor.visit_value())),
                Field::Message => message = Some(try!(visitor.visit_value())),
                Field::Values => values = Some(try!(visitor.visit_value())),
                Field::When => when = try!(visitor.visit_value()),
                Field::InjectMode => inject_mode = try!(visitor.visit_value()),
            }
        }

        let uuid = match uuid {
            Some(uuid) => uuid,
            None => return visitor.missing_field("uuid"),
        };

        let message = match message {
            Some(message) => try!(MessageActionVisitor::compile_template::<V>(message, &uuid)),
            None => {
                error!("Missing 'message' field: uuid={}", &uuid);
                return visitor.missing_field("message");
            }
        };

        let mut values = match values {
            Some(values) => {
                let mut registry = Handlebars::new();
                for (key, value) in values.into_iter() {
                    let template = try!(MessageActionVisitor::compile_template::<V>(value, &uuid));
                    registry.register_template(&key, template);
                }
                registry
            }
            None => Handlebars::new(),
        };

        try!(visitor.end());

        values.register_template(MESSAGE, message.clone());

        Ok(MessageAction {
            uuid: uuid,
            message: message,
            name: name,
            values: values,
            when: when,
            inject_mode: inject_mode,
        })
    }
}

impl Deserialize for InjectMode {
    fn deserialize<D>(deserializer: &mut D) -> Result<InjectMode, D::Error>
        where D: Deserializer
    {
        struct FieldVisitor;

        impl Visitor for FieldVisitor {
            type Value = InjectMode;

            fn visit_str<E>(&mut self, value: &str) -> Result<InjectMode, E>
                where E: Error
            {
                match value {
                    "log" => Ok(InjectMode::Log),
                    "loopback" => Ok(InjectMode::Loopback),
                    "forward" => Ok(InjectMode::Forward),
                    _ => Err(Error::syntax(&format!("Unexpected field: {}", value))),
                }
            }
        }

        deserializer.visit(FieldVisitor)
    }
}

#[cfg(test)]
mod test {
    use config::action::message::{MessageActionBuilder, MessageAction, InjectMode};

    use handlebars::Template;
    use serde_json::from_str;

    fn assert_message_action_eq(expected: &MessageAction, actual: &MessageAction) {
        assert_eq!(expected.uuid(), actual.uuid());
        assert_eq!(expected.name(), actual.name());
        assert_eq!(expected.message(), actual.message());
    }

    #[test]
    fn test_given_message_as_a_json_string_when_it_is_deserialized_then_we_get_the_expected_message
        () {
        let text = r#"
        {
          "uuid": "UUID",
          "name": "NAME",
          "message": "message",
          "values": {
            "key1": "value1",
            "key2": "value2"
          }
        }
        "#;

        let message = Template::compile("message".to_owned())
                          .expect("Failed to compile a handlebars template");
        let value1 = Template::compile("value1".to_owned())
                         .expect("Failed to compile a handlebars template");
        let value2 = Template::compile("value2".to_owned())
                         .expect("Failed to compile a handlebars template");
        let expected_message = MessageActionBuilder::new("UUID", message)
                                   .name(Some("NAME"))
                                   .pair("key1", value1)
                                   .pair("key2", value2)
                                   .build();
        let result = from_str::<MessageAction>(text);
        let message = result.expect("Failed to deserialize a valid MessageAction object");
        assert_message_action_eq(&expected_message, &message);
    }

    #[test]
    fn test_given_message_as_a_json_string_when_only_the_required_fields_are_present_then_we_can_deserialize_the_message
        () {
        let text = r#"
        {
          "uuid": "UUID",
          "message": "message"
        }
        "#;

        let message = Template::compile("message".to_owned())
                          .expect("Failed to compile a handlebars template");
        let expected_message = MessageActionBuilder::new("UUID", message).build();
        let result = from_str::<MessageAction>(text);
        let message = result.expect("Failed to deserialize a valid MessageAction object");
        assert_message_action_eq(&expected_message, &message);
    }

    #[test]
    fn test_given_message_as_a_json_string_when_one_of_the_required_fields_are_not_present_then_we_get_error
        () {
        let text = r#"
        {
        }
        "#;

        let result = from_str::<MessageAction>(text);
        let _ = result.err().expect("Successfully deserialized an invalid MessageAction object");
    }

    #[test]
    fn test_given_inject_modes_when_they_are_deserialized_then_we_get_the_right_result() {
        let text = r#"
        ["forward", "log", "loopback", "log"]
        "#;
        let expected = vec![InjectMode::Forward,
                            InjectMode::Log,
                            InjectMode::Loopback,
                            InjectMode::Log];

        let result = from_str::<Vec<InjectMode>>(text);
        println!("{:?}", &result);
        let array = result.expect("Failed to deserialize a valid array of inject modes");
        assert_eq!(&expected, &array);
    }

    #[test]
    fn test_given_invalid_inject_mode_when_it_is_deserialized_then_we_get_the_right_result() {
        let text = r#"
        ["invalid inject mode", "log"]
        "#;

        let result = from_str::<Vec<InjectMode>>(text);
        println!("{:?}", &result);
        let _ = result.err().expect("Successfully deserialized an invalid inject mode");
    }

    #[test]
    fn test_given_message_when_it_contains_inject_mode_then_it_can_be_deserialized() {
        let text = r#"
        {
          "uuid": "UUID",
          "message": "message",
          "inject_mode": "forward"
        }
        "#;

        let message = Template::compile("message".to_owned())
                          .expect("Failed to compile a handlebars template");
        let expected_message = MessageActionBuilder::new("UUID", message)
                                   .inject_mode(InjectMode::Forward)
                                   .build();
        let result = from_str::<MessageAction>(text);
        let message = result.expect("Failed to deserialize a valid MessageAction object");
        assert_message_action_eq(&expected_message, &message);
    }

    #[test]
    fn test_given_message_is_deserialized_when_it_contains_an_unexpected_field_then_an_error_is_returned() {
        let text = r#"{ "unexpected": "UUID" }"#;
        let result = from_str::<MessageAction>(text);
        let _ = result.err().unwrap();
    }
}
<|endoftext|>


<commit_before>#![crate_id(name="uutils", vers="1.0.0", author="Michael Gehring")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

extern crate base64;
extern crate basename;
extern crate cat;
extern crate chroot;
extern crate cksum;
extern crate comm;
extern crate cp;
extern crate dirname;
extern crate du;
extern crate echo;
extern crate env;
extern crate factor;
extern crate fmt;
extern crate fold;
extern crate groups;
extern crate head;
extern crate hostid;
extern crate hostname;
extern crate id;
extern crate kill;
extern crate link;
extern crate logname;
extern crate md5sum;
extern crate mkdir;
extern crate mkfifo;
extern crate nl;
extern crate paste;
extern crate printenv;
extern crate pwd;
extern crate rm;
extern crate rmdir;
extern crate seq;
extern crate sleep;
extern crate sum;
extern crate uusync;
extern crate tac;
extern crate tail;
extern crate tee;
extern crate touch;
extern crate tr;
extern crate truncate;
extern crate tty;
extern crate uname;
extern crate unlink;
extern crate uptime;
extern crate users;
extern crate wc;
extern crate whoami;
extern crate yes;

use std::os;
use std::collections::hashmap::HashMap;

static NAME: &'static str = "uutils";
static VERSION: &'static str = "1.0.0";

fn util_map() -> HashMap<&str, fn(Vec<String>) -> int> {
    fn uutrue(_: Vec<String>) -> int { 0 }
    fn uufalse(_: Vec<String>) -> int { 1 }

    let mut map = HashMap::new();
    map.insert("base64", base64::uumain);
    map.insert("basename", basename::uumain);
    map.insert("cat", cat::uumain);
    map.insert("chroot", chroot::uumain);
    map.insert("cksum", cksum::uumain);
    map.insert("comm", comm::uumain);
    map.insert("cp", cp::uumain);
    map.insert("dirname", dirname::uumain);
    map.insert("du", du::uumain);
    map.insert("echo", echo::uumain);
    map.insert("env", env::uumain);
    map.insert("factor", factor::uumain);
    map.insert("false", uufalse);
    map.insert("fmt", fmt::uumain);
    map.insert("fold", fold::uumain);
    map.insert("groups", groups::uumain);
    map.insert("head", head::uumain);
    map.insert("hostid", hostid::uumain);
    map.insert("hostname", hostname::uumain);
    map.insert("id", id::uumain);
    map.insert("kill", kill::uumain);
    map.insert("link", link::uumain);
    map.insert("logname", logname::uumain);
    map.insert("md5sum", md5sum::uumain);
    map.insert("mkdir", mkdir::uumain);
    map.insert("mkfifo", mkfifo::uumain);
    map.insert("nl", nl::uumain);
    map.insert("paste", paste::uumain);
    map.insert("printenv", printenv::uumain);
    map.insert("pwd", pwd::uumain);
    map.insert("rm", rm::uumain);
    map.insert("rmdir", rmdir::uumain);
    map.insert("seq", seq::uumain);
    map.insert("sleep", sleep::uumain);
    map.insert("sum", sum::uumain);
    map.insert("sync", uusync::uumain);
    map.insert("tac", tac::uumain);
    map.insert("tail", tail::uumain);
    map.insert("tee", tee::uumain);
    map.insert("touch", touch::uumain);
    map.insert("tr", tr::uumain);
    map.insert("true", uutrue);
    map.insert("truncate", truncate::uumain);
    map.insert("tty", tty::uumain);
    map.insert("uname", uname::uumain);
    map.insert("unlink", unlink::uumain);
    map.insert("uptime", uptime::uumain);
    map.insert("users", users::uumain);
    map.insert("wc", wc::uumain);
    map.insert("whoami", whoami::uumain);
    map.insert("yes", yes::uumain);
    map
}

fn usage(cmap: &HashMap<&str, fn(Vec<String>) -> int>) {
    println!("{} {}", NAME, VERSION);
    println!("");
    println!("Usage:");
    println!("  {} [util [arguments...]", NAME);
    println!("Currently defined functions:");
    let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect();
    utils.sort();
    for util in utils.iter() {
        println!("\t{}", util);
    }
    println!("");
}

fn main() {
    let umap = util_map();
    let mut args = os::args();

    // try binary name as util name.
    let binary = Path::new(args.get(0).as_slice());
    let binary_as_util = binary.filename_str().unwrap();
    if umap.contains_key(&binary_as_util) {
        let &uumain = umap.get(&binary_as_util);
        os::set_exit_status(uumain(args));
        return
    } else if binary_as_util.starts_with("uutils")
        || binary_as_util.starts_with("busybox") {
            // uutils can be called as either "uutils", "busybox"
            // "uutils-suffix" or "busybox-suffix". Not sure
            // what busybox uses the -suffix pattern for.
    } else {
        println!("{}: applet not found", binary_as_util);
        os::set_exit_status(1);
        return
    }

    // try first arg as util name.
    if args.len() >= 2 {
        args.shift();
        let util = args.get(0).as_slice();
        if umap.contains_key(&util) {
            let &uumain = umap.get(&util);
            os::set_exit_status(uumain(args.clone()));
            return
        } else if args.get(0).as_slice() == "--help" {
            // see if they want help on a specific util
            if args.len() >= 2 {
                let util = args.get(1).as_slice();
                if umap.contains_key(&util) {
                    let &uumain = umap.get(&util);
                    os::set_exit_status(uumain(vec!["--help".to_string()]));
                    return
                } else {
                    println!("{}: applet not found", util);
                    os::set_exit_status(1);
                    return
                }
            }
            usage(&umap);
            os::set_exit_status(0);
            return
        } else {
            println!("{}: applet not found", util);
            os::set_exit_status(1);
            return
        }
    } else {
        // no arguments provided
        usage(&umap);
        os::set_exit_status(0);
        return
    }
}
<commit_msg>uutils: fix hashsum<commit_after>#![crate_id(name="uutils", vers="1.0.0", author="Michael Gehring")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

extern crate base64;
extern crate basename;
extern crate cat;
extern crate chroot;
extern crate cksum;
extern crate comm;
extern crate cp;
extern crate dirname;
extern crate du;
extern crate echo;
extern crate env;
extern crate factor;
extern crate fmt;
extern crate fold;
extern crate groups;
extern crate head;
extern crate hostid;
extern crate hostname;
extern crate id;
extern crate kill;
extern crate link;
extern crate logname;
extern crate hashsum;
extern crate mkdir;
extern crate mkfifo;
extern crate nl;
extern crate paste;
extern crate printenv;
extern crate pwd;
extern crate rm;
extern crate rmdir;
extern crate seq;
extern crate sleep;
extern crate sum;
extern crate uusync;
extern crate tac;
extern crate tail;
extern crate tee;
extern crate touch;
extern crate tr;
extern crate truncate;
extern crate tty;
extern crate uname;
extern crate unlink;
extern crate uptime;
extern crate users;
extern crate wc;
extern crate whoami;
extern crate yes;

use std::os;
use std::collections::hashmap::HashMap;

static NAME: &'static str = "uutils";
static VERSION: &'static str = "1.0.0";

fn util_map() -> HashMap<&str, fn(Vec<String>) -> int> {
    fn uutrue(_: Vec<String>) -> int { 0 }
    fn uufalse(_: Vec<String>) -> int { 1 }

    let mut map = HashMap::new();
    map.insert("base64", base64::uumain);
    map.insert("basename", basename::uumain);
    map.insert("cat", cat::uumain);
    map.insert("chroot", chroot::uumain);
    map.insert("cksum", cksum::uumain);
    map.insert("comm", comm::uumain);
    map.insert("cp", cp::uumain);
    map.insert("dirname", dirname::uumain);
    map.insert("du", du::uumain);
    map.insert("echo", echo::uumain);
    map.insert("env", env::uumain);
    map.insert("factor", factor::uumain);
    map.insert("false", uufalse);
    map.insert("fmt", fmt::uumain);
    map.insert("fold", fold::uumain);
    map.insert("groups", groups::uumain);
    map.insert("head", head::uumain);
    map.insert("hostid", hostid::uumain);
    map.insert("hostname", hostname::uumain);
    map.insert("id", id::uumain);
    map.insert("kill", kill::uumain);
    map.insert("link", link::uumain);
    map.insert("logname", logname::uumain);
    map.insert("md5sum", hashsum::uumain);
    map.insert("sha1sum", hashsum::uumain);
    map.insert("sha224sum", hashsum::uumain);
    map.insert("sha256sum", hashsum::uumain);
    map.insert("sha384sum", hashsum::uumain);
    map.insert("sha512sum", hashsum::uumain);
    map.insert("mkdir", mkdir::uumain);
    map.insert("mkfifo", mkfifo::uumain);
    map.insert("nl", nl::uumain);
    map.insert("paste", paste::uumain);
    map.insert("printenv", printenv::uumain);
    map.insert("pwd", pwd::uumain);
    map.insert("rm", rm::uumain);
    map.insert("rmdir", rmdir::uumain);
    map.insert("seq", seq::uumain);
    map.insert("sleep", sleep::uumain);
    map.insert("sum", sum::uumain);
    map.insert("sync", uusync::uumain);
    map.insert("tac", tac::uumain);
    map.insert("tail", tail::uumain);
    map.insert("tee", tee::uumain);
    map.insert("touch", touch::uumain);
    map.insert("tr", tr::uumain);
    map.insert("true", uutrue);
    map.insert("truncate", truncate::uumain);
    map.insert("tty", tty::uumain);
    map.insert("uname", uname::uumain);
    map.insert("unlink", unlink::uumain);
    map.insert("uptime", uptime::uumain);
    map.insert("users", users::uumain);
    map.insert("wc", wc::uumain);
    map.insert("whoami", whoami::uumain);
    map.insert("yes", yes::uumain);
    map
}

fn usage(cmap: &HashMap<&str, fn(Vec<String>) -> int>) {
    println!("{} {}", NAME, VERSION);
    println!("");
    println!("Usage:");
    println!("  {} [util [arguments...]", NAME);
    println!("Currently defined functions:");
    let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect();
    utils.sort();
    for util in utils.iter() {
        println!("\t{}", util);
    }
    println!("");
}

fn main() {
    let umap = util_map();
    let mut args = os::args();

    // try binary name as util name.
    let binary = Path::new(args.get(0).as_slice());
    let binary_as_util = binary.filename_str().unwrap();
    if umap.contains_key(&binary_as_util) {
        let &uumain = umap.get(&binary_as_util);
        os::set_exit_status(uumain(args));
        return
    } else if binary_as_util.starts_with("uutils")
        || binary_as_util.starts_with("busybox") {
            // uutils can be called as either "uutils", "busybox"
            // "uutils-suffix" or "busybox-suffix". Not sure
            // what busybox uses the -suffix pattern for.
    } else {
        println!("{}: applet not found", binary_as_util);
        os::set_exit_status(1);
        return
    }

    // try first arg as util name.
    if args.len() >= 2 {
        args.shift();
        let util = args.get(0).as_slice();
        if umap.contains_key(&util) {
            let &uumain = umap.get(&util);
            os::set_exit_status(uumain(args.clone()));
            return
        } else if args.get(0).as_slice() == "--help" {
            // see if they want help on a specific util
            if args.len() >= 2 {
                let util = args.get(1).as_slice();
                if umap.contains_key(&util) {
                    let &uumain = umap.get(&util);
                    os::set_exit_status(uumain(vec!["--help".to_string()]));
                    return
                } else {
                    println!("{}: applet not found", util);
                    os::set_exit_status(1);
                    return
                }
            }
            usage(&umap);
            os::set_exit_status(0);
            return
        } else {
            println!("{}: applet not found", util);
            os::set_exit_status(1);
            return
        }
    } else {
        // no arguments provided
        usage(&umap);
        os::set_exit_status(0);
        return
    }
}
<|endoftext|>