<commit_before>use std::cmp::PartialOrd;
use std::ops::{Div, Sub};

use degree::Degree;

pub trait Fuzzy<T: PartialOrd> {
    fn membership(&self, value: T) -> Degree;
}

pub struct Boolean<T: PartialOrd>(T);

impl<T: PartialOrd> Boolean<T> {
    pub fn new(x: T) -> Boolean<T> {
        Boolean(x)
    }
}

impl<T: PartialOrd> Fuzzy<T> for Boolean<T> {
    fn membership(&self, value: T) -> Degree {
        if value < self.0 {
            Degree::zero()
        } else {
            Degree::one()
        }
    }
}

pub struct Gradual<T: PartialOrd + Into<f64>>(T, T);

impl<T> Gradual<T>
where T: PartialOrd + Into<f64>
{
    pub fn new(x0: T, x1: T) -> Gradual<T> {
        assert!(&x0 < &x1);
        Gradual(x0, x1)
    }
}

impl<T> Fuzzy<T> for Gradual<T>
where T: PartialOrd + Into<f64> + Div<T, Output = T> + Sub<T, Output = T> + Copy
{
    fn membership(&self, value: T) -> Degree {
        match value {
            _ if value <= self.0 => Degree::zero(),
            _ if value >= self.1 => Degree::one(),
            _ => {
                let d = (value / (self.1 - self.0)) - (self.0 / (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            },
        }
    }
}

pub struct Triangular<T: PartialOrd + Into<f64>>(T, T, T);

impl<T>  Triangular<T>
where T: PartialOrd + Into<f64> {
    pub fn new(x0: T, x1: T, x2: T) -> Triangular<T> {
        assert!(&x0 < &x1 && &x1 < &x2);
        Triangular(x0, x1, x2)
    }
}

impl<T> Fuzzy<T> for Triangular<T>
where T: PartialOrd + Into<f64> + Div<T, Output = T> + Sub<T, Output = T> + Copy
{
    fn membership(&self, value: T) -> Degree {
        match value {
            _ if value <= self.0 => Degree::zero(),
            _ if value >= self.2 => Degree::zero(),
            _ if value >  self.1 => {
                let d = (self.1 / (self.1 - self.0)) - (value / (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            }
            _ if value < self.1 => {
                let d = (value / (self.1 - self.0)) - (self.0 / (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            }
            _ => Degree::one(),
        }
    }
}

pub struct Trapezoid<T: PartialOrd + Into<f64>>(T, T, T, T);

impl<T> Trapezoid<T>
where T: PartialOrd + Into<f64> {
    pub fn new(x0: T, x1: T, x2: T, x3: T) -> Trapezoid<T> {
        assert!(&x0 < &x1 && &x1 < &x2 && &x2 < &x3);
        Trapezoid(x0, x1, x2, x3)
    }
}

impl<T> Fuzzy<T> for Trapezoid<T>
where T: PartialOrd + Into<f64> + Div<T, Output = T> + Sub<T, Output = T> + Copy {
    fn membership(&self, value: T) -> Degree {
        match value {
            _ if value <= self.0 => Degree::zero(),
            _ if value >= self.1 && value <= self.2 => Degree::one(),
            _ if value >  self.0 && value <  self.1 => {
                let d = (value / (self.1 - self.0)) - (self.0 - (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            },
            _ if value > self.2 && value < self.3 => {
                let d = (self.3 / (self.3 - self.2)) - (value / (self.3 - self.2));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            },
            _ => Degree::zero(),
        }
    }
}

#[allow(unused_variables)]
// TODO: handle values as well as references
pub fn gaussian<T>(x: &T, mu: &T, std: &T) -> Degree
    where T : PartialOrd + Into<f64>,
          for <'a> T: Div<&'a T, Output = T> + Sub<&'a T, Output = T>,
          for <'a, 'b> &'a T: Div<&'b T, Output = T> + Sub<&'b T, Output = T>
{
    unimplemented!()
}<commit_msg>whitespace cleanup<commit_after>use std::cmp::PartialOrd;
use std::ops::{Div, Sub};

use degree::Degree;

pub trait Fuzzy<T: PartialOrd> {
    fn membership(&self, value: T) -> Degree;
}

pub struct Boolean<T: PartialOrd>(T);

impl<T: PartialOrd> Boolean<T> {
    pub fn new(x: T) -> Boolean<T> {
        Boolean(x)
    }
}

impl<T: PartialOrd> Fuzzy<T> for Boolean<T> {
    fn membership(&self, value: T) -> Degree {
        if value < self.0 {
            Degree::zero()
        } else {
            Degree::one()
        }
    }
}

pub struct Gradual<T: PartialOrd + Into<f64>>(T, T);

impl<T> Gradual<T>
where T: PartialOrd + Into<f64>
{
    pub fn new(x0: T, x1: T) -> Gradual<T> {
        assert!(&x0 < &x1);
        Gradual(x0, x1)
    }
}

impl<T> Fuzzy<T> for Gradual<T>
where T: PartialOrd + Into<f64> + Div<T, Output = T> + Sub<T, Output = T> + Copy
{
    fn membership(&self, value: T) -> Degree {
        match value {
            _ if value <= self.0 => Degree::zero(),
            _ if value >= self.1 => Degree::one(),
            _ => {
                let d = (value / (self.1 - self.0)) - (self.0 / (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            },
        }
    }
}

pub struct Triangular<T: PartialOrd + Into<f64>>(T, T, T);

impl<T>  Triangular<T>
where T: PartialOrd + Into<f64> {
    pub fn new(x0: T, x1: T, x2: T) -> Triangular<T> {
        assert!(&x0 < &x1 && &x1 < &x2);
        Triangular(x0, x1, x2)
    }
}

impl<T> Fuzzy<T> for Triangular<T>
where T: PartialOrd + Into<f64> + Div<T, Output = T> + Sub<T, Output = T> + Copy
{
    fn membership(&self, value: T) -> Degree {
        match value {
            _ if value <= self.0 => Degree::zero(),
            _ if value >= self.2 => Degree::zero(),
            _ if value >  self.1 => {
                let d = (self.1 / (self.1 - self.0)) - (value / (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            }
            _ if value < self.1 => {
                let d = (value / (self.1 - self.0)) - (self.0 / (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            }
            _ => Degree::one(),
        }
    }
}

pub struct Trapezoid<T: PartialOrd + Into<f64>>(T, T, T, T);

impl<T> Trapezoid<T>
where T: PartialOrd + Into<f64> {
    pub fn new(x0: T, x1: T, x2: T, x3: T) -> Trapezoid<T> {
        assert!(&x0 < &x1 && &x1 < &x2 && &x2 < &x3);
        Trapezoid(x0, x1, x2, x3)
    }
}

impl<T> Fuzzy<T> for Trapezoid<T>
where T: PartialOrd + Into<f64> + Div<T, Output = T> + Sub<T, Output = T> + Copy {
    fn membership(&self, value: T) -> Degree {
        match value {
            _ if value <= self.0 => Degree::zero(),
            _ if value >= self.1 && value <= self.2 => Degree::one(),
            _ if value >  self.0 && value <  self.1 => {
                let d = (value / (self.1 - self.0)) - (self.0 - (self.1 - self.0));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            },
            _ if value > self.2 && value < self.3 => {
                let d = (self.3 / (self.3 - self.2)) - (value / (self.3 - self.2));
                match Degree::new(d.into()) {
                    None    => Degree::zero(),
                    Some(d) => d,
                }
            },
            _ => Degree::zero(),
        }
    }
}

#[allow(unused_variables)]
// TODO: handle values as well as references
pub fn gaussian<T>(x: &T, mu: &T, std: &T) -> Degree
    where T : PartialOrd + Into<f64>,
          for <'a> T: Div<&'a T, Output = T> + Sub<&'a T, Output = T>,
          for <'a, 'b> &'a T: Div<&'b T, Output = T> + Sub<&'b T, Output = T>
{
    unimplemented!()
}<|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 https://mozilla.org/MPL/2.0/.

extern crate crowbook_text_processing;

use crowbook_text_processing::{FrenchFormatter, clean, escape};

use std::env;
use std::io;
use std::io::BufRead;
use std::process::exit;

const TOOLS: &'static[(&'static str, &'static str)] = &[
    ("escape_html", "escape text for HTML display"),
    ("escape_tex", "escape text for LaTeX display"),
    ("escape_nb_spaces", "escape non-breaking spaces using HTML entities"),
    ("escape_nb_spaces_tex", "escape non-breaking spaces using ‘~’ symbol"),
    ("clean_ellipsis", "use unicode character ‘…’ for ellipsis"),
    ("clean_quotes", "try to replace straight quotes with curly ones"),
    ("format_french", "try to apply french typographic rules"),
];

fn print_transformations() {
    for &(name, desc) in TOOLS {
        println!("    {name}: {desc}",
                 name = name,
                 desc = desc);
    }
}

fn main() {
    let args:Vec<_> = env::args()
        .collect();
    if args.len() == 1 {
        println!("\
{bin} {version}

USAGE: {bin} <TRANSFORMATIONS>

Read standard input, sequentially apply each TRANSFORMATION on the text, and print the
result on standard output.

Valid transformations are the following:",
                 bin = env!("CARGO_PKG_NAME"),
                 version = env!("CARGO_PKG_VERSION"));
        print_transformations();
        println!("");
        println!("EXAMPLE: {bin} clean_quotes clean_ellipsis escape_html",
                 bin = env!("CARGO_PKG_NAME"));
    } else {
        let french = FrenchFormatter::new();

        let stdin = io::stdin();
        for line in stdin.lock().lines() {
            let line = line.expect("Error reading from standard input");
            let mut output = clean::whitespaces(line);
            for argument in &args[1..] {
                output = match argument.as_ref() {
                    "escape_html" => escape::html(output),
                    "escape_tex" => escape::tex(output),
                    "escape_nb_spaces" => escape::nb_spaces(output),
                    "escape_nb_spaces_tex" => escape::nb_spaces_tex(output),
                    "clean_quotes" => clean::quotes(output),
                    "clean_ellipsis" => clean::ellipsis(output),
                    "format_french" => french.format(output),
                    t => {
                        println!("Error: transformation “{}” not recognized.", t);
                        println!("Valid transformations are:");
                        print_transformations();
                        exit(0);
                    },
                }
            }
            println!("{}", output);
        }
    }
}
<commit_msg>Don't use CARGO_PKG_NAME as it doesn't seem to work on rust 1.6<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 https://mozilla.org/MPL/2.0/.

extern crate crowbook_text_processing;

use crowbook_text_processing::{FrenchFormatter, clean, escape};

use std::env;
use std::io;
use std::io::BufRead;
use std::process::exit;

const TOOLS: &'static[(&'static str, &'static str)] = &[
    ("escape_html", "escape text for HTML display"),
    ("escape_tex", "escape text for LaTeX display"),
    ("escape_nb_spaces", "escape non-breaking spaces using HTML entities"),
    ("escape_nb_spaces_tex", "escape non-breaking spaces using ‘~’ symbol"),
    ("clean_ellipsis", "use unicode character ‘…’ for ellipsis"),
    ("clean_quotes", "try to replace straight quotes with curly ones"),
    ("format_french", "try to apply french typographic rules"),
];

fn print_transformations() {
    for &(name, desc) in TOOLS {
        println!("    {name}: {desc}",
                 name = name,
                 desc = desc);
    }
}

fn main() {
    let args:Vec<_> = env::args()
        .collect();
    if args.len() == 1 {
        println!("\
{bin} {version}

USAGE: {bin} <TRANSFORMATIONS>

Read standard input, sequentially apply each TRANSFORMATION on the text, and print the
result on standard output.

Valid transformations are the following:",
                 bin = args[0],
                 version = env!("CARGO_PKG_VERSION"));
        print_transformations();
        println!("");
        println!("EXAMPLE: {bin} clean_quotes clean_ellipsis escape_html",
                 bin = args[0]);
    } else {
        let french = FrenchFormatter::new();

        let stdin = io::stdin();
        for line in stdin.lock().lines() {
            let line = line.expect("Error reading from standard input");
            let mut output = clean::whitespaces(line);
            for argument in &args[1..] {
                output = match argument.as_ref() {
                    "escape_html" => escape::html(output),
                    "escape_tex" => escape::tex(output),
                    "escape_nb_spaces" => escape::nb_spaces(output),
                    "escape_nb_spaces_tex" => escape::nb_spaces_tex(output),
                    "clean_quotes" => clean::quotes(output),
                    "clean_ellipsis" => clean::ellipsis(output),
                    "format_french" => french.format(output),
                    t => {
                        println!("Error: transformation “{}” not recognized.", t);
                        println!("Valid transformations are:");
                        print_transformations();
                        exit(0);
                    },
                }
            }
            println!("{}", output);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A typesafe bitmask flag generator.

/// The `bitflags!` macro generates a `struct` that holds a set of C-style
/// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
///
/// The flags should only be defined for integer types, otherwise unexpected
/// type errors may occur at compile time.
///
/// # Example
///
/// ```{.rust}
/// #[macro_use]
/// extern crate bitflags;
///
/// bitflags! {
///     flags Flags: u32 {
///         const FLAG_A       = 0b00000001,
///         const FLAG_B       = 0b00000010,
///         const FLAG_C       = 0b00000100,
///         const FLAG_ABC     = FLAG_A.bits
///                            | FLAG_B.bits
///                            | FLAG_C.bits,
///     }
/// }
///
/// fn main() {
///     let e1 = FLAG_A | FLAG_C;
///     let e2 = FLAG_B | FLAG_C;
///     assert!((e1 | e2) == FLAG_ABC);   // union
///     assert!((e1 & e2) == FLAG_C);     // intersection
///     assert!((e1 - e2) == FLAG_A);     // set difference
///     assert!(!e2 == FLAG_A);           // set complement
/// }
/// ```
///
/// The generated `struct`s can also be extended with type and trait implementations:
///
/// ```{.rust}
/// #[macro_use]
/// extern crate bitflags;
///
/// use std::fmt;
///
/// bitflags! {
///     flags Flags: u32 {
///         const FLAG_A   = 0b00000001,
///         const FLAG_B   = 0b00000010,
///     }
/// }
///
/// impl Flags {
///     pub fn clear(&mut self) {
///         self.bits = 0;  // The `bits` field can be accessed from within the
///                         // same module where the `bitflags!` macro was invoked.
///     }
/// }
///
/// impl fmt::Show for Flags {
///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
///         write!(f, "hi!")
///     }
/// }
///
/// fn main() {
///     let mut flags = FLAG_A | FLAG_B;
///     flags.clear();
///     assert!(flags.is_empty());
///     assert_eq!(format!("{:?}", flags).as_slice(), "hi!");
/// }
/// ```
///
/// # Attributes
///
/// Attributes can be attached to the generated `struct` by placing them
/// before the `flags` keyword.
///
/// # Derived traits
///
/// The `PartialEq` and `Clone` traits are automatically derived for the `struct` using
/// the `deriving` attribute. Additional traits can be derived by providing an
/// explicit `deriving` attribute on `flags`.
///
/// # Operators
///
/// The following operator traits are implemented for the generated `struct`:
///
/// - `BitOr`: union
/// - `BitAnd`: intersection
/// - `BitXor`: toggle
/// - `Sub`: set difference
/// - `Not`: set complement
///
/// # Methods
///
/// The following methods are defined for the generated `struct`:
///
/// - `empty`: an empty set of flags
/// - `all`: the set of all flags
/// - `bits`: the raw value of the flags currently stored
/// - `from_bits`: convert from underlying bit representation, unless that
///                representation contains bits that do not correspond to a flag
/// - `from_bits_truncate`: convert from underlying bit representation, dropping
///                         any bits that do not correspond to flags
/// - `is_empty`: `true` if no flags are currently stored
/// - `is_all`: `true` if all flags are currently set
/// - `intersects`: `true` if there are flags common to both `self` and `other`
/// - `contains`: `true` all of the flags in `other` are contained within `self`
/// - `insert`: inserts the specified flags in-place
/// - `remove`: removes the specified flags in-place
/// - `toggle`: the specified flags will be inserted if not present, and removed
///             if they are.
#[macro_export]
macro_rules! bitflags {
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+
    }) => {
        #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
        $(#[$attr])*
        pub struct $BitFlags {
            bits: $T,
        }

        $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            #[inline]
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the set containing all flags.
            #[inline]
            pub fn all() -> $BitFlags {
                $BitFlags { bits: $($value)|+ }
            }

            /// Returns the raw value of the flags currently stored.
            #[inline]
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Convert from underlying bit representation, unless that
            /// representation contains bits that do not correspond to a flag.
            #[inline]
            pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
                if (bits & !$BitFlags::all().bits()) != 0 {
                    ::std::option::Option::None
                } else {
                    ::std::option::Option::Some($BitFlags { bits: bits })
                }
            }

            /// Convert from underlying bit representation, dropping any bits
            /// that do not correspond to flags.
            #[inline]
            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
                $BitFlags { bits: bits } & $BitFlags::all()
            }

            /// Returns `true` if no flags are currently stored.
            #[inline]
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if all flags are currently set.
            #[inline]
            pub fn is_all(&self) -> bool {
                *self == $BitFlags::all()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            #[inline]
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(*self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            #[inline]
            pub fn contains(&self, other: $BitFlags) -> bool {
                (*self & other) == other
            }

            /// Inserts the specified flags in-place.
            #[inline]
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            #[inline]
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }

            /// Toggles the specified flags in-place.
            #[inline]
            pub fn toggle(&mut self, other: $BitFlags) {
                self.bits ^= other.bits;
            }
        }

        impl ::std::ops::BitOr for $BitFlags {
            type Output = $BitFlags;

            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl ::std::ops::BitXor for $BitFlags {
            type Output = $BitFlags;

            /// Returns the left flags, but with all the right flags toggled.
            #[inline]
            fn bitxor(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits ^ other.bits }
            }
        }

        impl ::std::ops::BitAnd for $BitFlags {
            type Output = $BitFlags;

            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl ::std::ops::Sub for $BitFlags {
            type Output = $BitFlags;

            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }

        impl ::std::ops::Not for $BitFlags {
            type Output = $BitFlags;

            /// Returns the complement of this set of flags.
            #[inline]
            fn not(self) -> $BitFlags {
                $BitFlags { bits: !self.bits } & $BitFlags::all()
            }
        }
    };
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+,
    }) => {
        bitflags! {
            $(#[$attr])*
            flags $BitFlags: $T {
                $($(#[$Flag_attr])* const $Flag = $value),+
            }
        }
    };
}

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
    use std::prelude::v1::*;
    use std::hash::{self, SipHasher};

    bitflags! {
        #[doc = "> The first principle is that you must not fool yourself — and"]
        #[doc = "> you are the easiest person to fool."]
        #[doc = "> "]
        #[doc = "> - Richard Feynman"]
        flags Flags: u32 {
            const FlagA       = 0b00000001,
            #[doc = "<pcwalton> macros are way better at generating code than trans is"]
            const FlagB       = 0b00000010,
            const FlagC       = 0b00000100,
            #[doc = "* cmr bed"]
            #[doc = "* strcat table"]
            #[doc = "<strcat> wait what?"]
            const FlagABC     = FlagA.bits
                               | FlagB.bits
                               | FlagC.bits,
        }
    }

    bitflags! {
        flags AnotherSetOfFlags: i8 {
            const AnotherFlag = -1_i8,
        }
    }

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0b00000000);
        assert_eq!(FlagA.bits(), 0b00000001);
        assert_eq!(FlagABC.bits(), 0b00000111);

        assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
        assert_eq!(AnotherFlag.bits(), !0_i8);
    }

    #[test]
    fn test_from_bits() {
        assert!(Flags::from_bits(0) == Some(Flags::empty()));
        assert!(Flags::from_bits(0b1) == Some(FlagA));
        assert!(Flags::from_bits(0b10) == Some(FlagB));
        assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB));
        assert!(Flags::from_bits(0b1000) == None);

        assert!(AnotherSetOfFlags::from_bits(!0_i8) == Some(AnotherFlag));
    }

    #[test]
    fn test_from_bits_truncate() {
        assert!(Flags::from_bits_truncate(0) == Flags::empty());
        assert!(Flags::from_bits_truncate(0b1) == FlagA);
        assert!(Flags::from_bits_truncate(0b10) == FlagB);
        assert!(Flags::from_bits_truncate(0b11) == (FlagA | FlagB));
        assert!(Flags::from_bits_truncate(0b1000) == Flags::empty());
        assert!(Flags::from_bits_truncate(0b1001) == FlagA);

        assert!(AnotherSetOfFlags::from_bits_truncate(0_i8) == AnotherSetOfFlags::empty());
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());

        assert!(!AnotherFlag.is_empty());
    }

    #[test]
    fn test_is_all() {
        assert!(Flags::all().is_all());
        assert!(!FlagA.is_all());
        assert!(FlagABC.is_all());

        assert!(AnotherFlag.is_all());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));

        assert!(AnotherFlag.intersects(AnotherFlag));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));

        assert!(AnotherFlag.contains(AnotherFlag));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);

        let mut e3 = AnotherSetOfFlags::empty();
        e3.insert(AnotherFlag);
        assert!(e3 == AnotherFlag);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);

        let mut e3 = AnotherFlag;
        e3.remove(AnotherFlag);
        assert!(e3 == AnotherSetOfFlags::empty());
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);     // union
        assert!((e1 & e2) == FlagC);       // intersection
        assert!((e1 - e2) == FlagA);       // set difference
        assert!(!e2 == FlagA);             // set complement
        assert!(e1 ^ e2 == FlagA | FlagB); // toggle
        let mut e3 = e1;
        e3.toggle(e2);
        assert!(e3 == FlagA | FlagB);

        let mut m4 = AnotherSetOfFlags::empty();
        m4.toggle(AnotherSetOfFlags::empty());
        assert!(m4 == AnotherSetOfFlags::empty());
    }

    #[test]
    fn test_lt() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(!(a < b) && !(b < a));
        b = FlagB;
        assert!(a < b);
        a = FlagC;
        assert!(!(a < b) && b < a);
        b = FlagC | FlagB;
        assert!(a < b);
    }

    #[test]
    fn test_ord() {
        let mut a = Flags::empty();
        let mut b = Flags::empty();

        assert!(a <= b && a >= b);
        a = FlagA;
        assert!(a > b && a >= b);
        assert!(b < a && b <= a);
        b = FlagB;
        assert!(b > a && b >= a);
        assert!(a < b && a <= b);
    }

    #[test]
    fn test_hash() {
      let mut x = Flags::empty();
      let mut y = Flags::empty();
      assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
      x = Flags::all();
      y = FlagABC;
      assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
    }
}<commit_msg>Remove bitflag tests.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_export]
macro_rules! bitflags {
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+
    }) => {
        #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
        $(#[$attr])*
        pub struct $BitFlags {
            bits: $T,
        }

        $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            #[inline]
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the set containing all flags.
            #[inline]
            pub fn all() -> $BitFlags {
                $BitFlags { bits: $($value)|+ }
            }

            /// Returns the raw value of the flags currently stored.
            #[inline]
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Convert from underlying bit representation, unless that
            /// representation contains bits that do not correspond to a flag.
            #[inline]
            pub fn from_bits(bits: $T) -> ::std::option::Option<$BitFlags> {
                if (bits & !$BitFlags::all().bits()) != 0 {
                    ::std::option::Option::None
                } else {
                    ::std::option::Option::Some($BitFlags { bits: bits })
                }
            }

            /// Convert from underlying bit representation, dropping any bits
            /// that do not correspond to flags.
            #[inline]
            pub fn from_bits_truncate(bits: $T) -> $BitFlags {
                $BitFlags { bits: bits } & $BitFlags::all()
            }

            /// Returns `true` if no flags are currently stored.
            #[inline]
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if all flags are currently set.
            #[inline]
            pub fn is_all(&self) -> bool {
                *self == $BitFlags::all()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            #[inline]
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(*self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            #[inline]
            pub fn contains(&self, other: $BitFlags) -> bool {
                (*self & other) == other
            }

            /// Inserts the specified flags in-place.
            #[inline]
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            #[inline]
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }

            /// Toggles the specified flags in-place.
            #[inline]
            pub fn toggle(&mut self, other: $BitFlags) {
                self.bits ^= other.bits;
            }
        }

        impl ::std::ops::BitOr for $BitFlags {
            type Output = $BitFlags;

            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl ::std::ops::BitXor for $BitFlags {
            type Output = $BitFlags;

            /// Returns the left flags, but with all the right flags toggled.
            #[inline]
            fn bitxor(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits ^ other.bits }
            }
        }

        impl ::std::ops::BitAnd for $BitFlags {
            type Output = $BitFlags;

            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl ::std::ops::Sub for $BitFlags {
            type Output = $BitFlags;

            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(self, other: $BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }

        impl ::std::ops::Not for $BitFlags {
            type Output = $BitFlags;

            /// Returns the complement of this set of flags.
            #[inline]
            fn not(self) -> $BitFlags {
                $BitFlags { bits: !self.bits } & $BitFlags::all()
            }
        }
    };
    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
        $($(#[$Flag_attr:meta])* const $Flag:ident = $value:expr),+,
    }) => {
        bitflags! {
            $(#[$attr])*
            flags $BitFlags: $T {
                $($(#[$Flag_attr])* const $Flag = $value),+
            }
        }
    };
}<|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/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods};
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference, LayoutJS};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use util::str::{DOMString, parse_unsigned_integer, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::borrow::ToOwned;
use std::cell::Ref;
use std::mem;
use std::ops::Deref;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[derive(JSTraceable, PartialEq, Clone)]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let mut atoms: Vec<Atom> = vec!();
        for token in split_html_space_chars(&tokens).map(Atom::from_slice) {
            if !atoms.iter().any(|atom| *atom == token) {
                atoms.push(token);
            }
        }
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = atoms.iter().map(|x| &**x).collect::<Vec<_>>().connect("\x20");
        AttrValue::TokenList(tokens, atoms)
    }

    // https://html.spec.whatwg.org/multipage/#reflecting-content-attributes-in-idl-attributes:idl-unsigned-long
    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    // https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers-greater-than-zero
    pub fn from_limited_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result == 0 || result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(&string);
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None
        }
    }

    pub fn atom<'a>(&'a self) -> Option<&'a Atom> {
        match *self {
            AttrValue::Atom(ref value) => Some(value),
            _ => None
        }
    }
}

impl Deref for AttrValue {
    type Target = str;

    fn deref<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
                AttrValue::TokenList(ref value, _) |
                AttrValue::UInt(ref value, _) => &value,
            AttrValue::Atom(ref value) => &value,
        }
    }
}

// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<Atom>,

    /// the element that owns this attribute.
    owner: MutNullableHeap<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace,
                     prefix: Option<Atom>, owner: Option<&Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: MutNullableHeap::new(owner.map(JS::from_ref)),
        }
    }

    pub fn new(window: &Window, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<Atom>, owner: Option<&Element>) -> Root<Attr> {
        reflect_dom_object(
            box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
            GlobalRef::Window(window),
            AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<Atom> {
        &self.prefix
    }
}

impl<'a> AttrMethods for &'a Attr {
    // https://dom.spec.whatwg.org/#dom-attr-localname
    fn LocalName(self) -> DOMString {
        (**self.local_name()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn Value(self) -> DOMString {
        (**self.value()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn SetValue(self, value: DOMString) {
        match self.owner() {
            None => *self.value.borrow_mut() = AttrValue::String(value),
            Some(owner) => {
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn TextContent(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-name
    fn Name(self) -> DOMString {
        (*self.name).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match &**atom {
            "" => None,
            url => Some(url.to_owned()),
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-prefix
    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix().as_ref().map(|p| (**p).to_owned())
    }

    // https://dom.spec.whatwg.org/#dom-attr-ownerelement
    fn GetOwnerElement(self) -> Option<Root<Element>> {
        self.owner()
    }

    // https://dom.spec.whatwg.org/#dom-attr-specified
    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn set_owner(self, owner: Option<&Element>);
    fn owner(self) -> Option<Root<Element>>;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for &'a Attr {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
        assert!(Some(owner) == self.owner().r());

        let node = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.local_name
    }

    /// Sets the owner element. Should be called after the attribute is added
    /// or removed from its older parent.
    fn set_owner(self, owner: Option<&Element>) {
        let ref ns = self.namespace;
        match (self.owner().r(), owner) {
            (None, Some(new)) => {
                // Already in the list of attributes of new owner.
                assert!(new.get_attribute(&ns, &self.local_name) == Some(Root::from_ref(self)))
            }
            (Some(old), None) => {
                // Already gone from the list of attributes of old owner.
                assert!(old.get_attribute(&ns, &self.local_name).is_none())
            }
            (old, new) => assert!(old == new)
        }
        self.owner.set(owner.map(JS::from_ref))
    }

    fn owner(self) -> Option<Root<Element>> {
        self.owner.get().map(Root::from_rooted)
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: (**ns).to_owned(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout {
    unsafe fn value_forever(&self) -> &'static AttrValue;
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
    unsafe fn value_for_layout(&self) -> &AttrValue;
}

#[allow(unsafe_code)]
impl AttrHelpersForLayout for LayoutJS<Attr> {
    #[inline]
    unsafe fn value_forever(&self) -> &'static AttrValue {
        // This transmute is used to cheat the lifetime restriction.
        mem::transmute::<&AttrValue, &AttrValue>((*self.unsafe_get()).value.borrow_for_layout())
    }

    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        &**self.value_forever()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = (*self.unsafe_get()).value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        match *self.value_forever() {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        (*self.unsafe_get()).local_name.clone()
    }

    #[inline]
    unsafe fn value_for_layout(&self) -> &AttrValue {
        (*self.unsafe_get()).value.borrow_for_layout()
    }
}
<commit_msg>Utilize iterators for AttrValue::from_serialized_tokenlist<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/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods};
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference, LayoutJS};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use util::str::{DOMString, parse_unsigned_integer, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::borrow::ToOwned;
use std::cell::Ref;
use std::mem;
use std::ops::Deref;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[derive(JSTraceable, PartialEq, Clone)]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let atoms =
            split_html_space_chars(&tokens)
            .map(Atom::from_slice)
            .fold(vec![], |mut acc, atom| {
                if !acc.contains(&atom) { acc.push(atom) }
                acc
            });
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = atoms.iter().map(|x| &**x).collect::<Vec<_>>().connect("\x20");
        AttrValue::TokenList(tokens, atoms)
    }

    // https://html.spec.whatwg.org/multipage/#reflecting-content-attributes-in-idl-attributes:idl-unsigned-long
    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    // https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers-greater-than-zero
    pub fn from_limited_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result == 0 || result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(&string);
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None
        }
    }

    pub fn atom<'a>(&'a self) -> Option<&'a Atom> {
        match *self {
            AttrValue::Atom(ref value) => Some(value),
            _ => None
        }
    }
}

impl Deref for AttrValue {
    type Target = str;

    fn deref<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
                AttrValue::TokenList(ref value, _) |
                AttrValue::UInt(ref value, _) => &value,
            AttrValue::Atom(ref value) => &value,
        }
    }
}

// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<Atom>,

    /// the element that owns this attribute.
    owner: MutNullableHeap<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace,
                     prefix: Option<Atom>, owner: Option<&Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: MutNullableHeap::new(owner.map(JS::from_ref)),
        }
    }

    pub fn new(window: &Window, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<Atom>, owner: Option<&Element>) -> Root<Attr> {
        reflect_dom_object(
            box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
            GlobalRef::Window(window),
            AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<Atom> {
        &self.prefix
    }
}

impl<'a> AttrMethods for &'a Attr {
    // https://dom.spec.whatwg.org/#dom-attr-localname
    fn LocalName(self) -> DOMString {
        (**self.local_name()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn Value(self) -> DOMString {
        (**self.value()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn SetValue(self, value: DOMString) {
        match self.owner() {
            None => *self.value.borrow_mut() = AttrValue::String(value),
            Some(owner) => {
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn TextContent(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-name
    fn Name(self) -> DOMString {
        (*self.name).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match &**atom {
            "" => None,
            url => Some(url.to_owned()),
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-prefix
    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix().as_ref().map(|p| (**p).to_owned())
    }

    // https://dom.spec.whatwg.org/#dom-attr-ownerelement
    fn GetOwnerElement(self) -> Option<Root<Element>> {
        self.owner()
    }

    // https://dom.spec.whatwg.org/#dom-attr-specified
    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn set_owner(self, owner: Option<&Element>);
    fn owner(self) -> Option<Root<Element>>;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for &'a Attr {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
        assert!(Some(owner) == self.owner().r());

        let node = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.local_name
    }

    /// Sets the owner element. Should be called after the attribute is added
    /// or removed from its older parent.
    fn set_owner(self, owner: Option<&Element>) {
        let ref ns = self.namespace;
        match (self.owner().r(), owner) {
            (None, Some(new)) => {
                // Already in the list of attributes of new owner.
                assert!(new.get_attribute(&ns, &self.local_name) == Some(Root::from_ref(self)))
            }
            (Some(old), None) => {
                // Already gone from the list of attributes of old owner.
                assert!(old.get_attribute(&ns, &self.local_name).is_none())
            }
            (old, new) => assert!(old == new)
        }
        self.owner.set(owner.map(JS::from_ref))
    }

    fn owner(self) -> Option<Root<Element>> {
        self.owner.get().map(Root::from_rooted)
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: (**ns).to_owned(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout {
    unsafe fn value_forever(&self) -> &'static AttrValue;
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
    unsafe fn value_for_layout(&self) -> &AttrValue;
}

#[allow(unsafe_code)]
impl AttrHelpersForLayout for LayoutJS<Attr> {
    #[inline]
    unsafe fn value_forever(&self) -> &'static AttrValue {
        // This transmute is used to cheat the lifetime restriction.
        mem::transmute::<&AttrValue, &AttrValue>((*self.unsafe_get()).value.borrow_for_layout())
    }

    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        &**self.value_forever()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = (*self.unsafe_get()).value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        match *self.value_forever() {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        (*self.unsafe_get()).local_name.clone()
    }

    #[inline]
    unsafe fn value_for_layout(&self) -> &AttrValue {
        (*self.unsafe_get()).value.borrow_for_layout()
    }
}
<|endoftext|>


<commit_before>
use clap::ArgMatches;

use doapi::{DoManager, DoRequest};

use config::Config;
use message::CliMessage;

pub fn run(m: &ArgMatches, cfg: &mut Config) {
    if m.is_present("verbose") { cfg.verbose = true; }
    if m.is_present("nosend") { cfg.no_send = true; }
    let domgr = DoManager::with_token(&cfg.auth[..]);
    match m.subcommand() {
        ("regions", Some(m))         => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.regions()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.regions().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Regions.display();
            match domgr.regions().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for reg in v.iter() {
                        CliMessage::Region.display();
                        println!("\t{}\n", &reg.to_string()[..].replace("\n", "\n\t"));
                    }
                    if v.is_empty() { println!("\tNo regions to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("sizes", Some(m))           => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.sizes()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.sizes().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Sizes.display();
            match domgr.sizes().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for siz in v.iter() {
                        CliMessage::Size.display();
                        println!("\t{}", siz);
                    }
                    if v.is_empty() { println!("\tNo sizes to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("images", Some(m))          => {
            let request = if m.is_present("applications") {
                domgr.images().applications()
            } else if m.is_present("distributions") {
                domgr.images().distributions()
            } else if m.is_present("private") {
                domgr.images().private()
            } else if m.is_present("available") {
                domgr.images().available()
            } else {
                domgr.images()
            };
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &request.to_string()
                        .replace("\n", "\n\t")[..]
                ).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match request.retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Images.display();
            match request.retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for img in v.iter() {
                        CliMessage::ImageList.display();
                        println!("\t{}", &img.to_string()[..].replace("$", ""));
                    }
                    if v.is_empty() { println!("\tNo images to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("ssh-keys", Some(m))        => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.ssh_keys()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.ssh_keys().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::SshKeys.display();
            match domgr.ssh_keys().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for k in v.iter() {
                        CliMessage::SshKeys.display();
                        println!("\t{}", k);
                    }
                    if v.is_empty() { println!("\tNo SSH keys to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("droplets", Some(m))        => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Droplets.display();
            match domgr.droplets().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for d in v.iter() {
                        CliMessage::AnonDroplet.display();
                        println!("\t{}", &d.to_string()[..].replace("\n", "\n\t"));
                    }
                    if v.is_empty() { println!("\tNo droplets to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("domains", Some(m))         => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.domains()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.domains().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Domains.display();
            match domgr.domains().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for d in v.iter() {
                        CliMessage::Domains.display();
                        println!("\t{}", d);
                    }
                    if v.is_empty() { println!("\tNo domains to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("account-actions", Some(m)) => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.account()
                         .actions()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.account().actions().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Actions.display();
            match domgr.account().actions().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for act in v.iter() {
                        CliMessage::Action.display();
                        println!("\t{}", act);
                    }
                    if v.is_empty() { println!("\tNo account actions to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        _                      => unreachable!()
    }
}
<commit_msg>imp: fixes list sizes command output<commit_after>
use clap::ArgMatches;

use doapi::{DoManager, DoRequest};

use config::Config;
use message::CliMessage;

pub fn run(m: &ArgMatches, cfg: &mut Config) {
    if m.is_present("verbose") { cfg.verbose = true; }
    if m.is_present("nosend") { cfg.no_send = true; }
    let domgr = DoManager::with_token(&cfg.auth[..]);
    match m.subcommand() {
        ("regions", Some(m))         => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.regions()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.regions().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Regions.display();
            match domgr.regions().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for reg in v.iter() {
                        CliMessage::Region.display();
                        println!("\t{}\n", &reg.to_string()[..].replace("\n", "\n\t"));
                    }
                    if v.is_empty() { println!("\tNo regions to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("sizes", Some(m))           => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.sizes()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.sizes().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Sizes.display();
            match domgr.sizes().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for siz in v.iter() {
                        CliMessage::Size.display();
                        println!("\t{}\n", &siz.to_string()[..].replace("\n", "\n\t"));
                    }
                    if v.is_empty() { println!("\tNo sizes to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("images", Some(m))          => {
            let request = if m.is_present("applications") {
                domgr.images().applications()
            } else if m.is_present("distributions") {
                domgr.images().distributions()
            } else if m.is_present("private") {
                domgr.images().private()
            } else if m.is_present("available") {
                domgr.images().available()
            } else {
                domgr.images()
            };
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &request.to_string()
                        .replace("\n", "\n\t")[..]
                ).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match request.retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Images.display();
            match request.retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for img in v.iter() {
                        CliMessage::ImageList.display();
                        println!("\t{}", &img.to_string()[..].replace("$", ""));
                    }
                    if v.is_empty() { println!("\tNo images to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("ssh-keys", Some(m))        => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.ssh_keys()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.ssh_keys().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::SshKeys.display();
            match domgr.ssh_keys().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for k in v.iter() {
                        CliMessage::SshKeys.display();
                        println!("\t{}", k);
                    }
                    if v.is_empty() { println!("\tNo SSH keys to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("droplets", Some(m))        => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Droplets.display();
            match domgr.droplets().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for d in v.iter() {
                        CliMessage::AnonDroplet.display();
                        println!("\t{}", &d.to_string()[..].replace("\n", "\n\t"));
                    }
                    if v.is_empty() { println!("\tNo droplets to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("domains", Some(m))         => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.domains()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.domains().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Domains.display();
            match domgr.domains().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for d in v.iter() {
                        CliMessage::Domains.display();
                        println!("\t{}", d);
                    }
                    if v.is_empty() { println!("\tNo domains to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("account-actions", Some(m)) => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.account()
                         .actions()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.account().actions().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Actions.display();
            match domgr.account().actions().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for act in v.iter() {
                        CliMessage::Action.display();
                        println!("\t{}", act);
                    }
                    if v.is_empty() { println!("\tNo account actions to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        _                      => unreachable!()
    }
}
<|endoftext|>


<commit_before>use getopts::Options;
use std::env::Args;

pub struct Arguments {
    pub program_name: String,
    pub has_month: bool,
    pub month: usize,
    pub has_year: bool,
    pub year: usize,
    pub date_only: bool,
    pub exit: bool,
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&*brief));
}

pub fn parse_args(arguments: Args) -> Arguments {
    let mut opts = Options::new();
    opts.optflag("d", "date", "only print today's date");
    opts.optflag("h", "help", "print this help menu");
    opts.optflagopt("m", "month", "only print the month's calendar", "MONTH");
    opts.optflagopt("y", "year", "only print the year's calendar", "YEAR");

    let matches = match opts.parse(arguments) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    let mut args = Arguments {
        program_name: "".to_string(),
        date_only: matches.opt_present("d"),
        has_month: matches.opt_present("m"),
        month: match matches.opt_str("m") {
            Some(m) => match m.parse::<usize>() {
                Ok(mm) => mm - 1,
                Err(_) => usize::max_value(),
            },
            None => usize::max_value(),
        },
        has_year: matches.opt_present("y"),
        year: match matches.opt_str("y") {
            Some(y) => match y.parse::<usize>() {
                Ok(mm) => mm,
                Err(_) => usize::max_value(),
            },
            None => usize::max_value(),
        },
        exit: matches.opt_present("h"),
    };

    if args.month > 10 {
        args.has_month = false;
        args.month = usize::max_value();
    }

    if args.exit {
        print_usage(&*args.program_name, opts);
    }

    args
}

<commit_msg>Sanitize month input<commit_after>use getopts::Options;
use std::env::Args;

pub struct Arguments {
    pub program_name: String,
    pub has_month: bool,
    pub month: usize,
    pub has_year: bool,
    pub year: usize,
    pub date_only: bool,
    pub exit: bool,
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&*brief));
}

pub fn parse_args(arguments: Args) -> Arguments {
    let mut opts = Options::new();
    opts.optflag("d", "date", "only print today's date");
    opts.optflag("h", "help", "print this help menu");
    opts.optflagopt("m", "month", "only print the month's calendar", "MONTH");
    opts.optflagopt("y", "year", "only print the year's calendar", "YEAR");

    let matches = match opts.parse(arguments) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    let mut args = Arguments {
        program_name: "".to_string(),
        date_only: matches.opt_present("d"),
        has_month: matches.opt_present("m"),
        month: match matches.opt_str("m") {
            Some(m) => match m.parse::<usize>() {
                Ok(mm) => if mm == 0 { usize::max_value() } else { mm - 1 },
                Err(_) => usize::max_value(),
            },
            None => usize::max_value(),
        },
        has_year: matches.opt_present("y"),
        year: match matches.opt_str("y") {
            Some(y) => match y.parse::<usize>() {
                Ok(mm) => mm,
                Err(_) => usize::max_value(),
            },
            None => usize::max_value(),
        },
        exit: matches.opt_present("h"),
    };

    if args.month > 10 {
        args.has_month = false;
        args.month = usize::max_value();
    }

    if args.exit {
        print_usage(&*args.program_name, opts);
    }

    args
}

<|endoftext|>


<commit_before>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API

extern crate rav1e;
extern crate libc;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_int;

use libc::size_t;
use libc::ptrdiff_t;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame>);

type EncoderStatus=rav1e::EncoderStatus;

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
    last_err: Option<EncoderStatus>,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context,
    last_err: Option<EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: size_t,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSampling=rav1e::ChromaSampling;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default(
    width: u32,
    height: u32,
    bit_depth: u8,
    chroma_sampling: ChromaSampling,
    timebase: Rational,
) -> *mut Config {
    let cfg = rav1e::Config {
        frame_info: rav1e::FrameInfo {
            width: width as usize,
            height: height as usize,
            bit_depth: bit_depth as usize,
            chroma_sampling,
        },
        timebase,
        enc: Default::default(),
    };

    let c = Box::new(Config {
        cfg,
        last_err: None,
    });

    Box::into_raw(c)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    let _ = Box::from_raw(cfg);
}

/// Set a configuration parameter using its key and value
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Returns a negative value on non-zero.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    let key = CStr::from_ptr(key).to_string_lossy();
    let value = CStr::from_ptr(value).to_string_lossy();

    (*cfg)
        .cfg
        .parse(&key, &value)
        .map(|_v| {
            (*cfg).last_err = None;
            0
        }).map_err(|e| (*cfg).last_err = Some(e))
        .unwrap_or(-1)
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    let _ = Box::from_raw(ctx);
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    let _ = Arc::from_raw(frame);
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> c_int {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            (*ctx).last_err = None;
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

/// Receive encoded data
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> c_int {
    (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            (*ctx).last_err = None;
            let packet = Packet {
                data: p.data.as_ptr(),
                len: p.data.len(),
                number: p.number,
                frame_type: p.frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    let _ = Box::from_raw(pkt);
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
///
/// Use rav1e_container_sequence_header_unref() to free it.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut size_t) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    let _ = Box::from_raw(sequence);
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
///
/// frame: A frame provided by rav1e_frame_new()
/// plane: The index of the plane starting from 0
/// data: The data to be copied
/// data_len: Lenght of the buffer
/// stride: Plane line in bytes, including padding
/// bytewidth: Number of bytes per component, either 1 or 2
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: c_int,
    data: *const u8,
    data_len: size_t,
    stride: ptrdiff_t,
    bytewidth: c_int,
) {
    let input = Arc::get_mut(&mut (*frame).0).unwrap();
    let data_slice = slice::from_raw_parts(data, data_len as usize);

    input.planes[plane as usize].copy_from_raw_u8(data_slice, stride as usize, bytewidth as usize);
}
<commit_msg>crav1e: Support new color parameters<commit_after>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API

extern crate rav1e;
extern crate libc;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_int;

use libc::size_t;
use libc::ptrdiff_t;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame>);

type EncoderStatus=rav1e::EncoderStatus;

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
    last_err: Option<EncoderStatus>,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context,
    last_err: Option<EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: size_t,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSamplePosition=rav1e::ChromaSamplePosition;
type ChromaSampling=rav1e::ChromaSampling;
type ColorDescription=rav1e::ColorDescription;
type EncoderConfig=rav1e::EncoderConfig;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default(
    width: u32,
    height: u32,
    bit_depth: u8,
    chroma_sampling: ChromaSampling,
    chroma_sample_position: ChromaSamplePosition,
    color_description: Option<ColorDescription>,
    timebase: Rational,
) -> *mut Config {
    let mut enc: EncoderConfig = Default::default();
    enc.color_description = color_description;

    let cfg = rav1e::Config {
        frame_info: rav1e::FrameInfo {
            width: width as usize,
            height: height as usize,
            bit_depth: bit_depth as usize,
            chroma_sampling,
            chroma_sample_position,
        },
        timebase,
        enc,
    };

    let c = Box::new(Config {
        cfg,
        last_err: None,
    });

    Box::into_raw(c)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    let _ = Box::from_raw(cfg);
}

/// Set a configuration parameter using its key and value
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Returns a negative value on non-zero.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    let key = CStr::from_ptr(key).to_string_lossy();
    let value = CStr::from_ptr(value).to_string_lossy();

    (*cfg)
        .cfg
        .parse(&key, &value)
        .map(|_v| {
            (*cfg).last_err = None;
            0
        }).map_err(|e| (*cfg).last_err = Some(e))
        .unwrap_or(-1)
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    let _ = Box::from_raw(ctx);
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    let _ = Arc::from_raw(frame);
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> c_int {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            (*ctx).last_err = None;
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

/// Receive encoded data
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> c_int {
    (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            (*ctx).last_err = None;
            let packet = Packet {
                data: p.data.as_ptr(),
                len: p.data.len(),
                number: p.number,
                frame_type: p.frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            0
        }).map_err(|e| (*ctx).last_err = Some(e))
        .unwrap_or(-1)
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    let _ = Box::from_raw(pkt);
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
///
/// Use rav1e_container_sequence_header_unref() to free it.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut size_t) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    let _ = Box::from_raw(sequence);
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
///
/// frame: A frame provided by rav1e_frame_new()
/// plane: The index of the plane starting from 0
/// data: The data to be copied
/// data_len: Lenght of the buffer
/// stride: Plane line in bytes, including padding
/// bytewidth: Number of bytes per component, either 1 or 2
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: c_int,
    data: *const u8,
    data_len: size_t,
    stride: ptrdiff_t,
    bytewidth: c_int,
) {
    let input = Arc::get_mut(&mut (*frame).0).unwrap();
    let data_slice = slice::from_raw_parts(data, data_len as usize);

    input.planes[plane as usize].copy_from_raw_u8(data_slice, stride as usize, bytewidth as usize);
}
<|endoftext|>