<commit_before>macro_rules! impl_integer_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {
            /// Produces the sum of the lanes of the vector, with wrapping addition.
            #[inline]
            pub fn wrapping_sum(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0) }
            }

            /// Produces the sum of the lanes of the vector, with wrapping multiplication.
            #[inline]
            pub fn wrapping_product(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1) }
            }

            /// Sequentially performs bitwise "and" between the lanes of the vector.
            #[inline]
            pub fn and_lanes(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_and(self) }
            }

            /// Sequentially performs bitwise "or" between the lanes of the vector.
            #[inline]
            pub fn or_lanes(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_or(self) }
            }

            /// Sequentially performs bitwise "xor" between the lanes of the vector.
            #[inline]
            pub fn xor_lanes(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_xor(self) }
            }

            /// Returns the maximum lane in the vector.
            #[inline]
            pub fn max_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Returns the minimum lane in the vector.
            #[inline]
            pub fn min_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_float_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {

            /// Produces the sum of the lanes of the vector.
            #[inline]
            pub fn sum(self) -> $scalar {
                // f32 SIMD sum is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) && core::mem::size_of::<$scalar>() == 4 {
                    self.as_slice().iter().sum()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
                }
            }

            /// Produces the sum of the lanes of the vector.
            #[inline]
            pub fn product(self) -> $scalar {
                // f32 SIMD product is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) && core::mem::size_of::<$scalar>() == 4 {
                    self.as_slice().iter().product()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
                }
            }

            /// Returns the maximum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn max_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Returns the minimum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn min_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_full_mask_reductions {
    { $name:ident, $inner:ident } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            crate::$inner<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_any(self.to_int()) }
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_all(self.to_int()) }
            }
        }
    }
}

macro_rules! impl_opaque_mask_reductions {
    { $name:ident, $inner:ident, $bits_ty:ident } => {
        impl<const LANES: usize> $name<LANES>
        where
            $bits_ty<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                self.0.any()
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                self.0.all()
            }
        }
    }
}

impl<const LANES: usize> crate::BitMask<LANES>
where
    crate::BitMask<LANES>: crate::LanesAtMost32,
{
    /// Returns true if any lane is set, or false otherwise.
    #[inline]
    pub fn any(self) -> bool {
        self != Self::splat(false)
    }

    /// Returns true if all lanes are set, or false otherwise.
    #[inline]
    pub fn all(self) -> bool {
        self == Self::splat(true)
    }
}
<commit_msg>Enable i586 workaround for both f32 and f64<commit_after>macro_rules! impl_integer_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {
            /// Produces the sum of the lanes of the vector, with wrapping addition.
            #[inline]
            pub fn wrapping_sum(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0) }
            }

            /// Produces the sum of the lanes of the vector, with wrapping multiplication.
            #[inline]
            pub fn wrapping_product(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1) }
            }

            /// Sequentially performs bitwise "and" between the lanes of the vector.
            #[inline]
            pub fn and_lanes(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_and(self) }
            }

            /// Sequentially performs bitwise "or" between the lanes of the vector.
            #[inline]
            pub fn or_lanes(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_or(self) }
            }

            /// Sequentially performs bitwise "xor" between the lanes of the vector.
            #[inline]
            pub fn xor_lanes(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_xor(self) }
            }

            /// Returns the maximum lane in the vector.
            #[inline]
            pub fn max_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Returns the minimum lane in the vector.
            #[inline]
            pub fn min_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_float_reductions {
    { $name:ident, $scalar:ty } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            Self: crate::LanesAtMost32
        {

            /// Produces the sum of the lanes of the vector.
            #[inline]
            pub fn sum(self) -> $scalar {
                // LLVM sum is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
                    self.as_slice().iter().sum()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
                }
            }

            /// Produces the sum of the lanes of the vector.
            #[inline]
            pub fn product(self) -> $scalar {
                // LLVM product is inaccurate on i586
                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
                    self.as_slice().iter().product()
                } else {
                    unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
                }
            }

            /// Returns the maximum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn max_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_max(self) }
            }

            /// Returns the minimum lane in the vector.
            ///
            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
            #[inline]
            pub fn min_lane(self) -> $scalar {
                unsafe { crate::intrinsics::simd_reduce_min(self) }
            }
        }
    }
}

macro_rules! impl_full_mask_reductions {
    { $name:ident, $inner:ident } => {
        impl<const LANES: usize> crate::$name<LANES>
        where
            crate::$inner<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_any(self.to_int()) }
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                unsafe { crate::intrinsics::simd_reduce_all(self.to_int()) }
            }
        }
    }
}

macro_rules! impl_opaque_mask_reductions {
    { $name:ident, $inner:ident, $bits_ty:ident } => {
        impl<const LANES: usize> $name<LANES>
        where
            $bits_ty<LANES>: crate::LanesAtMost32
        {
            /// Returns true if any lane is set, or false otherwise.
            #[inline]
            pub fn any(self) -> bool {
                self.0.any()
            }

            /// Returns true if all lanes are set, or false otherwise.
            #[inline]
            pub fn all(self) -> bool {
                self.0.all()
            }
        }
    }
}

impl<const LANES: usize> crate::BitMask<LANES>
where
    crate::BitMask<LANES>: crate::LanesAtMost32,
{
    /// Returns true if any lane is set, or false otherwise.
    #[inline]
    pub fn any(self) -> bool {
        self != Self::splat(false)
    }

    /// Returns true if all lanes are set, or false otherwise.
    #[inline]
    pub fn all(self) -> bool {
        self == Self::splat(true)
    }
}
<|endoftext|>


<commit_before>use std::net::url::Url;
use url_from_str = std::net::url::from_str;
use std::cell::Cell;
use util::{DataStream, VoidPtrLike};
use values::*;
use color::{Color, rgb};
use select::{SelectCtx, SelectHandler};
use stylesheet::Stylesheet;
use computed::ComputedStyle;
use complete::CompleteSelectResults;

fn test_url() -> Url {
    result::unwrap(url_from_str("http://foo.com"))
}

fn style_stream(style: &str) -> DataStream {
    let style = Cell(style.to_str());
    |move style| if !style.is_empty() {
        Some(str::to_bytes(style.take()))
    } else {
        None
    }
}

enum TestNode = @NodeData;

struct NodeData {
    name: ~str,
    children: ~[TestNode],
    mut parent: Option<TestNode>
}

impl TestNode: VoidPtrLike {
    static fn from_void_ptr(node: *libc::c_void) -> TestNode {
        assert node.is_not_null();
        TestNode(unsafe {
            let box = cast::reinterpret_cast(&node);
            cast::bump_box_refcount(box);
            box
        })
    }

    fn to_void_ptr(&self) -> *libc::c_void {
        unsafe { cast::reinterpret_cast(&(*self)) }
    }
}

struct TestHandler {
    bogus: int
}

impl TestHandler {
    static fn new() -> TestHandler {
        TestHandler {
            bogus: 0
        }
    }
}

impl TestHandler: SelectHandler<TestNode> {
    fn node_name(node: &TestNode) -> ~str { copy (*node).name }
    fn named_parent_node(node: &TestNode, name: &str) -> Option<TestNode> {
        match (**node).parent {
            Some(parent) => {
                if name == (**parent).name {
                    Some(parent)
                } else {
                    None
                }
            }
            None => None
        }
    }
    fn parent_node(node: &TestNode) -> Option<TestNode> { (**node).parent }
}

fn single_div_test(style: &str, f: &fn(&ComputedStyle)) {
    let sheet = Stylesheet::new(test_url(), style_stream(style));
    let mut select_ctx = SelectCtx::new();
    let handler = &TestHandler::new();
    select_ctx.append_sheet(move sheet);
    let dom = &TestNode(@NodeData {
        name: ~"div",
        children: ~[],
        parent: None
    });
    let style = select_ctx.select_style(dom, handler);
    let computed = style.computed_style();
    f(&computed);
}

#[test]
fn test_background_color_simple() {
    let style = "div { background-color: #123456; }";
    do single_div_test(style) |computed| {
        let color = computed.background_color();
        assert color == Specified(rgb(0x12, 0x34, 0x56));
    }
}

#[test]
fn test_border_top_width_px() {
    let style = "div { border-top-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_top_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_right_width_px() {
    let style = "div { border-right-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_right_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_bottom_width_px() {
    let style = "div { border-bottom-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_bottom_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_left_width_px() {
    let style = "div { border-left-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_width_px() {
    let style = "div { border-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_top_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
        let width = computed.border_right_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
        let width = computed.border_bottom_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_color() {
    let style = "div {\
                 border-top-color: red;\
                 border-right-color: green;\
                 border-bottom-color: blue;\
                 border-left-color: yellow;\
                 }";
    do single_div_test(style) |computed| {
        let top_color = computed.border_top_color();
        let right_color = computed.border_right_color();
        let bottom_color = computed.border_bottom_color();
        let left_color = computed.border_left_color();
        assert top_color == Specified(rgb(255, 0, 0));
        assert right_color == Specified(rgb(0, 128, 0));
        assert bottom_color == Specified(rgb(0, 0, 255));
        assert left_color == Specified(rgb(255, 255, 0));
    }
}

#[test]
fn test_border_color_shorthand() {
    let style = "div {\
                 border-color: red;\
                 }";
    do single_div_test(style) |computed| {
        let top_color = computed.border_top_color();
        let right_color = computed.border_right_color();
        let bottom_color = computed.border_bottom_color();
        let left_color = computed.border_left_color();
        assert top_color == Specified(rgb(255, 0, 0));
        assert right_color == Specified(rgb(255, 0, 0));
        assert bottom_color == Specified(rgb(255, 0, 0));
        assert left_color == Specified(rgb(255, 0, 0));
    }
}

#[test]
fn test_margin() {
    let style = "div {\
                 margin-top: 10px;\
                 margin-right: 20px;\
                 margin-bottom: 30px;\
                 margin-left: auto;\
                 }";
    do single_div_test(style) |computed| {
        assert computed.margin_top() == Specified(CSSMarginLength(Px(10.0)));
        assert computed.margin_right() == Specified(CSSMarginLength(Px(20.0)));
        assert computed.margin_bottom() == Specified(CSSMarginLength(Px(30.0)));
        assert computed.margin_left() == Specified(CSSMarginAuto);
    }
}

#[test]
fn test_display() {
    let style = "div { display: none; }";
    do single_div_test(style) |computed| {
        assert computed.display(false) == Specified(CSSDisplayNone);
    }
}

#[test]
fn test_float() {
    let style = "div { float: right; }";
    do single_div_test(style) |computed| {
        assert computed.float() == Specified(CSSFloatRight);
    }
}

#[test]
fn test_position() {
    let style = "div { position: static; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionStatic);
    }
    let style = "div { position: relative; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionRelative);
    }
    let style = "div { position: absolute; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionAbsolute);
    }
    let style = "div { position: fixed; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionFixed);
    }
}

#[test]
fn test_width() {
    let style = "div { width: 10px; }";
    do single_div_test(style) |computed| {
        assert computed.width() == Specified(CSSWidthLength(Px(10.0)));
    }
}

#[test]
fn test_height() {
    let style = "div { height: 10px; }";
    do single_div_test(style) |computed| {
        assert computed.height() == Specified(CSSHeightLength(Px(10.0)));
    }
}

fn child_test(style: &str, f: &fn(&ComputedStyle)) {
    let sheet = Stylesheet::new(test_url(), style_stream(style));
    let mut select_ctx = SelectCtx::new();
    let handler = &TestHandler::new();
    select_ctx.append_sheet(move sheet);
    let child = TestNode(@NodeData {
        name: ~"span",
        children: ~[],
        parent: None
    });
    let parent = TestNode(@NodeData {
        name: ~"div",
        children: ~[child],
        parent: None
    });
    child.parent = Some(parent);
    let style = select_ctx.select_style(&child, handler);
    let computed = style.computed_style();
    f(&computed);
}

#[test]
fn test_child() {
    let style = "div > span { border-left-width: 10px; }";
    do child_test(style) |computed| {
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_not_child() {
    let style = "div > not_span { border-left-width: 10px; }";
    do child_test(style) |computed| {
        let width = computed.border_left_width();
        assert width != Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
#[ignore]
fn test_descendant() {
    let style = "div span { border-left-width: 10px; }";
    do child_test(style) |computed| {
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
#[ignore]
fn test_compose() {
    let style = "div { background-color: blue; }";

    let sheet = Stylesheet::new(test_url(), style_stream(style));
    let mut select_ctx = SelectCtx::new();
    let handler = &TestHandler::new();
    select_ctx.append_sheet(move sheet);
    let child = TestNode(@NodeData {
        name: ~"span",
        children: ~[],
        parent: None
    });
    let parent = TestNode(@NodeData {
        name: ~"div",
        children: ~[child],
        parent: None
    });
    child.parent = Some(parent);
    let parent_results = select_ctx.select_style(&parent, handler);
    let child_results = select_ctx.select_style(&child, handler);

    let complete_parent_results = CompleteSelectResults::new_root(move parent_results);
    let complete_child_results = CompleteSelectResults::new_from_parent(&complete_parent_results, move child_results);

    let computed = complete_child_results.computed_style();

    error!("XXX %?", computed.background_color());
    assert computed.background_color() == color::css_colors::blue();
}
<commit_msg>Test style composition<commit_after>use std::net::url::Url;
use url_from_str = std::net::url::from_str;
use std::cell::Cell;
use util::{DataStream, VoidPtrLike};
use values::*;
use color::{Color, rgb};
use select::{SelectCtx, SelectHandler};
use stylesheet::Stylesheet;
use computed::ComputedStyle;
use complete::CompleteSelectResults;

fn test_url() -> Url {
    result::unwrap(url_from_str("http://foo.com"))
}

fn style_stream(style: &str) -> DataStream {
    let style = Cell(style.to_str());
    |move style| if !style.is_empty() {
        Some(str::to_bytes(style.take()))
    } else {
        None
    }
}

enum TestNode = @NodeData;

struct NodeData {
    name: ~str,
    children: ~[TestNode],
    mut parent: Option<TestNode>
}

impl TestNode: VoidPtrLike {
    static fn from_void_ptr(node: *libc::c_void) -> TestNode {
        assert node.is_not_null();
        TestNode(unsafe {
            let box = cast::reinterpret_cast(&node);
            cast::bump_box_refcount(box);
            box
        })
    }

    fn to_void_ptr(&self) -> *libc::c_void {
        unsafe { cast::reinterpret_cast(&(*self)) }
    }
}

struct TestHandler {
    bogus: int
}

impl TestHandler {
    static fn new() -> TestHandler {
        TestHandler {
            bogus: 0
        }
    }
}

impl TestHandler: SelectHandler<TestNode> {
    fn node_name(node: &TestNode) -> ~str { copy (*node).name }
    fn named_parent_node(node: &TestNode, name: &str) -> Option<TestNode> {
        match (**node).parent {
            Some(parent) => {
                if name == (**parent).name {
                    Some(parent)
                } else {
                    None
                }
            }
            None => None
        }
    }
    fn parent_node(node: &TestNode) -> Option<TestNode> { (**node).parent }
}

fn single_div_test(style: &str, f: &fn(&ComputedStyle)) {
    let sheet = Stylesheet::new(test_url(), style_stream(style));
    let mut select_ctx = SelectCtx::new();
    let handler = &TestHandler::new();
    select_ctx.append_sheet(move sheet);
    let dom = &TestNode(@NodeData {
        name: ~"div",
        children: ~[],
        parent: None
    });
    let style = select_ctx.select_style(dom, handler);
    let computed = style.computed_style();
    f(&computed);
}

#[test]
fn test_background_color_simple() {
    let style = "div { background-color: #123456; }";
    do single_div_test(style) |computed| {
        let color = computed.background_color();
        assert color == Specified(rgb(0x12, 0x34, 0x56));
    }
}

#[test]
fn test_border_top_width_px() {
    let style = "div { border-top-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_top_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_right_width_px() {
    let style = "div { border-right-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_right_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_bottom_width_px() {
    let style = "div { border-bottom-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_bottom_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_left_width_px() {
    let style = "div { border-left-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_width_px() {
    let style = "div { border-width: 10px; }";
    do single_div_test(style) |computed| {
        let width = computed.border_top_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
        let width = computed.border_right_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
        let width = computed.border_bottom_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_border_color() {
    let style = "div {\
                 border-top-color: red;\
                 border-right-color: green;\
                 border-bottom-color: blue;\
                 border-left-color: yellow;\
                 }";
    do single_div_test(style) |computed| {
        let top_color = computed.border_top_color();
        let right_color = computed.border_right_color();
        let bottom_color = computed.border_bottom_color();
        let left_color = computed.border_left_color();
        assert top_color == Specified(rgb(255, 0, 0));
        assert right_color == Specified(rgb(0, 128, 0));
        assert bottom_color == Specified(rgb(0, 0, 255));
        assert left_color == Specified(rgb(255, 255, 0));
    }
}

#[test]
fn test_border_color_shorthand() {
    let style = "div {\
                 border-color: red;\
                 }";
    do single_div_test(style) |computed| {
        let top_color = computed.border_top_color();
        let right_color = computed.border_right_color();
        let bottom_color = computed.border_bottom_color();
        let left_color = computed.border_left_color();
        assert top_color == Specified(rgb(255, 0, 0));
        assert right_color == Specified(rgb(255, 0, 0));
        assert bottom_color == Specified(rgb(255, 0, 0));
        assert left_color == Specified(rgb(255, 0, 0));
    }
}

#[test]
fn test_margin() {
    let style = "div {\
                 margin-top: 10px;\
                 margin-right: 20px;\
                 margin-bottom: 30px;\
                 margin-left: auto;\
                 }";
    do single_div_test(style) |computed| {
        assert computed.margin_top() == Specified(CSSMarginLength(Px(10.0)));
        assert computed.margin_right() == Specified(CSSMarginLength(Px(20.0)));
        assert computed.margin_bottom() == Specified(CSSMarginLength(Px(30.0)));
        assert computed.margin_left() == Specified(CSSMarginAuto);
    }
}

#[test]
fn test_display() {
    let style = "div { display: none; }";
    do single_div_test(style) |computed| {
        assert computed.display(false) == Specified(CSSDisplayNone);
    }
}

#[test]
fn test_float() {
    let style = "div { float: right; }";
    do single_div_test(style) |computed| {
        assert computed.float() == Specified(CSSFloatRight);
    }
}

#[test]
fn test_position() {
    let style = "div { position: static; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionStatic);
    }
    let style = "div { position: relative; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionRelative);
    }
    let style = "div { position: absolute; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionAbsolute);
    }
    let style = "div { position: fixed; }";
    do single_div_test(style) |computed| {
        assert computed.position() == Specified(CSSPositionFixed);
    }
}

#[test]
fn test_width() {
    let style = "div { width: 10px; }";
    do single_div_test(style) |computed| {
        assert computed.width() == Specified(CSSWidthLength(Px(10.0)));
    }
}

#[test]
fn test_height() {
    let style = "div { height: 10px; }";
    do single_div_test(style) |computed| {
        assert computed.height() == Specified(CSSHeightLength(Px(10.0)));
    }
}

fn child_test(style: &str, f: &fn(&ComputedStyle)) {
    let sheet = Stylesheet::new(test_url(), style_stream(style));
    let mut select_ctx = SelectCtx::new();
    let handler = &TestHandler::new();
    select_ctx.append_sheet(move sheet);
    let child = TestNode(@NodeData {
        name: ~"span",
        children: ~[],
        parent: None
    });
    let parent = TestNode(@NodeData {
        name: ~"div",
        children: ~[child],
        parent: None
    });
    child.parent = Some(parent);
    let style = select_ctx.select_style(&child, handler);
    let computed = style.computed_style();
    f(&computed);
}

#[test]
fn test_child() {
    let style = "div > span { border-left-width: 10px; }";
    do child_test(style) |computed| {
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_not_child() {
    let style = "div > not_span { border-left-width: 10px; }";
    do child_test(style) |computed| {
        let width = computed.border_left_width();
        assert width != Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
#[ignore]
fn test_descendant() {
    let style = "div span { border-left-width: 10px; }";
    do child_test(style) |computed| {
        let width = computed.border_left_width();
        assert width == Specified(CSSBorderWidthLength(Px(10.0)));
    }
}

#[test]
fn test_compose() {
    let style = "div { background-color: blue; }\
                 span { background-color: inherit; }";

    let sheet = Stylesheet::new(test_url(), style_stream(style));
    let mut select_ctx = SelectCtx::new();
    let handler = &TestHandler::new();
    select_ctx.append_sheet(move sheet);
    let child = TestNode(@NodeData {
        name: ~"span",
        children: ~[],
        parent: None
    });
    let parent = TestNode(@NodeData {
        name: ~"div",
        children: ~[child],
        parent: None
    });
    child.parent = Some(parent);
    let parent_results = select_ctx.select_style(&parent, handler);
    let child_results = select_ctx.select_style(&child, handler);

    let complete_parent_results = CompleteSelectResults::new_root(move parent_results);
    let complete_child_results = CompleteSelectResults::new_from_parent(&complete_parent_results, move child_results);

    let computed = complete_child_results.computed_style();

    assert computed.background_color() == color::css_colors::blue();
}
<|endoftext|>


<commit_before>use std::fs::File;

use flac::{Stream, StreamProducer, StreamReader};

pub const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata streaminfo --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
pub struct Arguments {
  arg_filename: String,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
}

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    let block_size_str = if info.min_block_size == info.max_block_size {
      format!("{} samples", info.max_block_size)
    } else {
      format!("{} - {} samples", info.min_block_size, info.max_block_size)
    };

    format_print!("{}{}", "Block size: ", block_size_str, no_flags);
  }

  if no_flags || args.flag_frame_size {
    println!("Frame size: {} - {} bytes", info.min_frame_size,
                                          info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

pub fn run(args: &Arguments) {
  let stream = StreamReader::<File>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  print_stream_info(&stream, &args);
}
<commit_msg>Use convenience method in `StreamInfo`<commit_after>use std::fs::File;

use flac::{Stream, StreamProducer, StreamReader};

pub const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata streaminfo --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
pub struct Arguments {
  arg_filename: String,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
}

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    let block_size_str = if info.is_fixed_block_size() {
      format!("{} samples", info.max_block_size)
    } else {
      format!("{} - {} samples", info.min_block_size, info.max_block_size)
    };

    format_print!("{}{}", "Block size: ", block_size_str, no_flags);
  }

  if no_flags || args.flag_frame_size {
    println!("Frame size: {} - {} bytes", info.min_frame_size,
                                          info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

pub fn run(args: &Arguments) {
  let stream = StreamReader::<File>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  print_stream_info(&stream, &args);
}
<|endoftext|>


<commit_before>use coresimd::simd::*;
use coresimd::simd_llvm::*;
use coresimd::x86::*;
use mem;

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Computes the absolute values of packed 32-bit integers in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vpabsd))]
pub unsafe fn _mm512_abs_epi32(a: __m512i) -> __m512i {
    let a = a.as_i32x16();
    let zero: i32x16 = mem::zeroed();
    let sub = simd_sub(zero, a);
    let cmp: i32x16 = simd_gt(a, zero);
    mem::transmute(simd_select(cmp, a, sub))
}

/// Compute the absolute value of packed 32-bit integers in `a`, and store the
/// unsigned results in `dst` using writemask `k` (elements are copied from
/// `src` when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vpabsd))]
pub unsafe fn _mm512_mask_abs_epi32(src: __m512i, k: __mmask16, a: __m512i) -> __m512i {
    let abs = _mm512_abs_epi32(a).as_i32x16();
    mem::transmute(simd_select_bitmask(k, abs, src.as_i32x16()))
}

/// Compute the absolute value of packed 32-bit integers in `a`, and store the
/// unsigned results in `dst` using zeromask `k` (elements are zeroed out when
/// the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33,34,35,35&text=_mm512_maskz_abs_epi32)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vpabsd))]
pub unsafe fn _mm512_maskz_abs_epi32(k: __mmask16, a: __m512i) -> __m512i {
    let abs = _mm512_abs_epi32(a).as_i32x16();
    let zero = _mm512_setzero_si512().as_i32x16();
    mem::transmute(simd_select_bitmask(k, abs, zero))
}

/// Return vector of type `__m512i` with all elements set to zero.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990&text=_mm512_setzero_si512)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vxorps))]
pub unsafe fn _mm512_setzero_si512() -> __m512i {
    mem::zeroed()
}

/// Set packed 32-bit integers in `dst` with the supplied values in reverse
/// order.
#[inline]
#[target_feature(enable = "avx512f")]
pub unsafe fn _mm512_setr_epi32(
    e15: i32,
    e14: i32,
    e13: i32,
    e12: i32,
    e11: i32,
    e10: i32,
    e9: i32,
    e8: i32,
    e7: i32,
    e6: i32,
    e5: i32,
    e4: i32,
    e3: i32,
    e2: i32,
    e1: i32,
    e0: i32,
) -> __m512i {
    let r = i32x16(
        e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0,
    );
    mem::transmute(r)
}

#[cfg(test)]
mod tests {
    use std;
    use stdsimd_test::simd_test;

    use coresimd::x86::*;

    #[simd_test(enable = "avx512f")]
    unsafe fn test_mm512_abs_epi32() {
        #[rustfmt::skip]
        let a = _mm512_setr_epi32(
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
        );
        let r = _mm512_abs_epi32(a);
        let e = _mm512_setr_epi32(
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
        );
        assert_eq_m512i(r, e);
    }

    #[simd_test(enable = "avx512f")]
    unsafe fn test_mm512_mask_abs_epi32() {
        #[rustfmt::skip]
        let a = _mm512_setr_epi32(
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
        );
        let r = _mm512_mask_abs_epi32(a, 0, a);
        assert_eq_m512i(r, a);
        let r = _mm512_mask_abs_epi32(a, 0b11111111, a);
        let e = _mm512_setr_epi32(
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
            0,
            1,
            -1,
            std::i32::MAX,
            std::i32::MIN,
            100,
            -100,
            -32,
        );
        assert_eq_m512i(r, e);
    }

    #[simd_test(enable = "avx512f")]
    unsafe fn test_mm512_maskz_abs_epi32() {
        #[rustfmt::skip]
        let a = _mm512_setr_epi32(
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
        );
        let r = _mm512_maskz_abs_epi32(0, a);
        assert_eq_m512i(r, _mm512_setzero_si512());
        let r = _mm512_maskz_abs_epi32(0b11111111, a);
        let e = _mm512_setr_epi32(
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
        );
        assert_eq_m512i(r, e);
    }
}
<commit_msg>avoid deprecated mem::zeroed<commit_after>use coresimd::simd::*;
use coresimd::simd_llvm::*;
use coresimd::x86::*;
use mem::{self, MaybeUninit};

#[cfg(test)]
use stdsimd_test::assert_instr;

/// Computes the absolute values of packed 32-bit integers in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vpabsd))]
pub unsafe fn _mm512_abs_epi32(a: __m512i) -> __m512i {
    let a = a.as_i32x16();
    // all-0 is a properly initialized i32x16
    let zero: i32x16 = MaybeUninit::zeroed().into_inner();
    let sub = simd_sub(zero, a);
    let cmp: i32x16 = simd_gt(a, zero);
    mem::transmute(simd_select(cmp, a, sub))
}

/// Compute the absolute value of packed 32-bit integers in `a`, and store the
/// unsigned results in `dst` using writemask `k` (elements are copied from
/// `src` when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33&text=_mm512_abs_epi32)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vpabsd))]
pub unsafe fn _mm512_mask_abs_epi32(src: __m512i, k: __mmask16, a: __m512i) -> __m512i {
    let abs = _mm512_abs_epi32(a).as_i32x16();
    mem::transmute(simd_select_bitmask(k, abs, src.as_i32x16()))
}

/// Compute the absolute value of packed 32-bit integers in `a`, and store the
/// unsigned results in `dst` using zeromask `k` (elements are zeroed out when
/// the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990,33,34,35,35&text=_mm512_maskz_abs_epi32)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vpabsd))]
pub unsafe fn _mm512_maskz_abs_epi32(k: __mmask16, a: __m512i) -> __m512i {
    let abs = _mm512_abs_epi32(a).as_i32x16();
    let zero = _mm512_setzero_si512().as_i32x16();
    mem::transmute(simd_select_bitmask(k, abs, zero))
}

/// Return vector of type `__m512i` with all elements set to zero.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#avx512techs=AVX512F&expand=33,34,4990&text=_mm512_setzero_si512)
#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vxorps))]
pub unsafe fn _mm512_setzero_si512() -> __m512i {
    // All-0 is a properly initialized __m512i
    MaybeUninit::zeroed().into_inner()
}

/// Set packed 32-bit integers in `dst` with the supplied values in reverse
/// order.
#[inline]
#[target_feature(enable = "avx512f")]
pub unsafe fn _mm512_setr_epi32(
    e15: i32,
    e14: i32,
    e13: i32,
    e12: i32,
    e11: i32,
    e10: i32,
    e9: i32,
    e8: i32,
    e7: i32,
    e6: i32,
    e5: i32,
    e4: i32,
    e3: i32,
    e2: i32,
    e1: i32,
    e0: i32,
) -> __m512i {
    let r = i32x16(
        e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0,
    );
    mem::transmute(r)
}

#[cfg(test)]
mod tests {
    use std;
    use stdsimd_test::simd_test;

    use coresimd::x86::*;

    #[simd_test(enable = "avx512f")]
    unsafe fn test_mm512_abs_epi32() {
        #[rustfmt::skip]
        let a = _mm512_setr_epi32(
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
        );
        let r = _mm512_abs_epi32(a);
        let e = _mm512_setr_epi32(
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
        );
        assert_eq_m512i(r, e);
    }

    #[simd_test(enable = "avx512f")]
    unsafe fn test_mm512_mask_abs_epi32() {
        #[rustfmt::skip]
        let a = _mm512_setr_epi32(
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
        );
        let r = _mm512_mask_abs_epi32(a, 0, a);
        assert_eq_m512i(r, a);
        let r = _mm512_mask_abs_epi32(a, 0b11111111, a);
        let e = _mm512_setr_epi32(
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
            0,
            1,
            -1,
            std::i32::MAX,
            std::i32::MIN,
            100,
            -100,
            -32,
        );
        assert_eq_m512i(r, e);
    }

    #[simd_test(enable = "avx512f")]
    unsafe fn test_mm512_maskz_abs_epi32() {
        #[rustfmt::skip]
        let a = _mm512_setr_epi32(
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
            0, 1, -1, std::i32::MAX,
            std::i32::MIN, 100, -100, -32,
        );
        let r = _mm512_maskz_abs_epi32(0, a);
        assert_eq_m512i(r, _mm512_setzero_si512());
        let r = _mm512_maskz_abs_epi32(0b11111111, a);
        let e = _mm512_setr_epi32(
            0,
            1,
            1,
            std::i32::MAX,
            std::i32::MAX.wrapping_add(1),
            100,
            100,
            32,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
        );
        assert_eq_m512i(r, e);
    }
}
<|endoftext|>


<commit_before>//! [POST /_matrix/client/r0/join/{roomIdOrAlias}](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-join-roomidoralias)

use ruma_api::ruma_api;
use ruma_identifiers::{RoomId, RoomIdOrAliasId};

use super::ThirdPartySigned;

ruma_api! {
    metadata {
        description: "Join a room using its ID or one of its aliases.",
        method: POST,
        name: "join_room_by_id_or_alias",
        path: "/_matrix/client/r0/join/:room_id_or_alias",
        rate_limited: true,
        requires_authentication: true,
    }

    request {
        /// The room where the user should be invited.
        #[ruma_api(path)]
        pub room_id_or_alias: RoomIdOrAliasId,
        /// The servers to attempt to join the room through. One of the servers
        /// must be participating in the room.
        #[ruma_api(query)]
        #[serde(default)]
        pub server_name: String, // TODO: Vec<String> once it is supported (#146, ruma-api#48)
        /// The signature of a `m.third_party_invite` token to prove that this user owns a third
        /// party identity which has been invited to the room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub third_party_signed: Option<ThirdPartySigned>,
    }

    response {
        /// The room that the user joined.
        pub room_id: RoomId,
    }

    error: crate::Error
}
<commit_msg>Update join_room_by_id_or_alias<commit_after>//! [POST /_matrix/client/r0/join/{roomIdOrAlias}](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-join-roomidoralias)

use ruma_api::ruma_api;
use ruma_identifiers::{RoomId, RoomIdOrAliasId};

use super::ThirdPartySigned;

ruma_api! {
    metadata {
        description: "Join a room using its ID or one of its aliases.",
        method: POST,
        name: "join_room_by_id_or_alias",
        path: "/_matrix/client/r0/join/:room_id_or_alias",
        rate_limited: true,
        requires_authentication: true,
    }

    request {
        /// The room where the user should be invited.
        #[ruma_api(path)]
        pub room_id_or_alias: RoomIdOrAliasId,

        /// The servers to attempt to join the room through. One of the servers
        /// must be participating in the room.
        #[ruma_api(query)]
        #[serde(default)]
        pub server_name: Vec<String>,

        /// The signature of a `m.third_party_invite` token to prove that this user owns a third
        /// party identity which has been invited to the room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub third_party_signed: Option<ThirdPartySigned>,
    }

    response {
        /// The room that the user joined.
        pub room_id: RoomId,
    }

    error: crate::Error
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Eq, Debug)]
pub enum Bucket {
    One,
    Two
}

/// A struct to hold your results in.
#[derive(PartialEq, Eq, Debug)]
pub struct BucketStats {
    /// The total number of "moves" it should take to reach the desired number of liters, including
    /// the first fill.
    pub moves: u8,
    /// Which bucket should end up with the desired number of liters? (Either "one" or "two")
    pub goal_bucket: Bucket,
    /// How many liters are left in the other bucket?
    pub other_bucket: u8,
}

/// Solve the bucket problem
pub fn solve(capacity_1: u8,
             capacity_2: u8,
             goal: u8,
             start_bucket: &Bucket) -> BucketStats
{
    unimplemented!();
}
<commit_msg>two-bucket: eliminate stub warnings<commit_after>#[derive(PartialEq, Eq, Debug)]
pub enum Bucket {
    One,
    Two
}

/// A struct to hold your results in.
#[derive(PartialEq, Eq, Debug)]
pub struct BucketStats {
    /// The total number of "moves" it should take to reach the desired number of liters, including
    /// the first fill.
    pub moves: u8,
    /// Which bucket should end up with the desired number of liters? (Either "one" or "two")
    pub goal_bucket: Bucket,
    /// How many liters are left in the other bucket?
    pub other_bucket: u8,
}

/// Solve the bucket problem
pub fn solve(capacity_1: u8,
             capacity_2: u8,
             goal: u8,
             start_bucket: &Bucket) -> BucketStats
{
    unimplemented!(
        "Given one bucket of capacity {}, another of capacity {}, starting with {:?}, find pours to reach {}",
        capacity_1,
        capacity_2,
        start_bucket,
        goal,
    );
}
<|endoftext|>


<commit_before>//! Push and Pull wrappers to maintain counts of messages in channels.

use std::rc::Rc;
use std::cell::RefCell;
use std::collections::VecDeque;

use crate::{Push, Pull};
use crate::allocator::Event;

/// The push half of an intra-thread channel.
pub struct Pusher<T, P: Push<T>> {
    index: usize,
    // count: usize,
    events: Rc<RefCell<VecDeque<(usize, Event)>>>,
    pusher: P,
    phantom: ::std::marker::PhantomData<T>,
}

impl<T, P: Push<T>>  Pusher<T, P> {
    /// Wraps a pusher with a message counter.
    pub fn new(pusher: P, index: usize, events: Rc<RefCell<VecDeque<(usize, Event)>>>) -> Self {
        Pusher {
            index,
            // count: 0,
            events,
            pusher,
            phantom: ::std::marker::PhantomData,
        }
    }
}

impl<T, P: Push<T>> Push<T> for Pusher<T, P> {
    #[inline]
    fn push(&mut self, element: &mut Option<T>) {
        // if element.is_none() {
        //     if self.count != 0 {
        //         self.events
        //             .borrow_mut()
        //             .push_back((self.index, Event::Pushed(self.count)));
        //         self.count = 0;
        //     }
        // }
        // else {
        //     self.count += 1;
        // }
        // TODO: Version above is less chatty, but can be a bit late in
        //       moving information along. Better, but needs cooperation.
        self.events
            .borrow_mut()
            .push_back((self.index, Event::Pushed(1)));

        self.pusher.push(element)
    }
}

use std::sync::mpsc::Sender;

/// The push half of an intra-thread channel.
pub struct ArcPusher<T, P: Push<T>> {
    index: usize,
    // count: usize,
    events: Sender<(usize, Event)>,
    pusher: P,
    phantom: ::std::marker::PhantomData<T>,
}

impl<T, P: Push<T>>  ArcPusher<T, P> {
    /// Wraps a pusher with a message counter.
    pub fn new(pusher: P, index: usize, events: Sender<(usize, Event)>) -> Self {
        ArcPusher {
            index,
            // count: 0,
            events,
            pusher,
            phantom: ::std::marker::PhantomData,
        }
    }
}

impl<T, P: Push<T>> Push<T> for ArcPusher<T, P> {
    #[inline]
    fn push(&mut self, element: &mut Option<T>) {
        // if element.is_none() {
        //     if self.count != 0 {
        //         self.events
        //             .send((self.index, Event::Pushed(self.count)))
        //             .expect("Failed to send message count");
        //         self.count = 0;
        //     }
        // }
        // else {
        //     self.count += 1;
        // }
        self.events
            .send((self.index, Event::Pushed(1)))
            // TODO : Perhaps this shouldn't be a fatal error (e.g. in shutdown).
            .expect("Failed to send message count");

        self.pusher.push(element)
    }
}

/// The pull half of an intra-thread channel.
pub struct Puller<T, P: Pull<T>> {
    index: usize,
    count: usize,
    events: Rc<RefCell<VecDeque<(usize, Event)>>>,
    puller: P,
    phantom: ::std::marker::PhantomData<T>,
}

impl<T, P: Pull<T>>  Puller<T, P> {
    /// Wraps a puller with a message counter.
    pub fn new(puller: P, index: usize, events: Rc<RefCell<VecDeque<(usize, Event)>>>) -> Self {
        Puller {
            index,
            count: 0,
            events,
            puller,
            phantom: ::std::marker::PhantomData,
        }
    }
}
impl<T, P: Pull<T>> Pull<T> for Puller<T, P> {
    #[inline]
    fn pull(&mut self) -> &mut Option<T> {
        let result = self.puller.pull();
        if result.is_none() {
            if self.count != 0 {
                self.events
                    .borrow_mut()
                    .push_back((self.index, Event::Pulled(self.count)));
                self.count = 0;
            }
        }
        else {
            self.count += 1;
        }

        result
    }
}
<commit_msg>decline to panic<commit_after>//! Push and Pull wrappers to maintain counts of messages in channels.

use std::rc::Rc;
use std::cell::RefCell;
use std::collections::VecDeque;

use crate::{Push, Pull};
use crate::allocator::Event;

/// The push half of an intra-thread channel.
pub struct Pusher<T, P: Push<T>> {
    index: usize,
    // count: usize,
    events: Rc<RefCell<VecDeque<(usize, Event)>>>,
    pusher: P,
    phantom: ::std::marker::PhantomData<T>,
}

impl<T, P: Push<T>>  Pusher<T, P> {
    /// Wraps a pusher with a message counter.
    pub fn new(pusher: P, index: usize, events: Rc<RefCell<VecDeque<(usize, Event)>>>) -> Self {
        Pusher {
            index,
            // count: 0,
            events,
            pusher,
            phantom: ::std::marker::PhantomData,
        }
    }
}

impl<T, P: Push<T>> Push<T> for Pusher<T, P> {
    #[inline]
    fn push(&mut self, element: &mut Option<T>) {
        // if element.is_none() {
        //     if self.count != 0 {
        //         self.events
        //             .borrow_mut()
        //             .push_back((self.index, Event::Pushed(self.count)));
        //         self.count = 0;
        //     }
        // }
        // else {
        //     self.count += 1;
        // }
        // TODO: Version above is less chatty, but can be a bit late in
        //       moving information along. Better, but needs cooperation.
        self.events
            .borrow_mut()
            .push_back((self.index, Event::Pushed(1)));

        self.pusher.push(element)
    }
}

use std::sync::mpsc::Sender;

/// The push half of an intra-thread channel.
pub struct ArcPusher<T, P: Push<T>> {
    index: usize,
    // count: usize,
    events: Sender<(usize, Event)>,
    pusher: P,
    phantom: ::std::marker::PhantomData<T>,
}

impl<T, P: Push<T>>  ArcPusher<T, P> {
    /// Wraps a pusher with a message counter.
    pub fn new(pusher: P, index: usize, events: Sender<(usize, Event)>) -> Self {
        ArcPusher {
            index,
            // count: 0,
            events,
            pusher,
            phantom: ::std::marker::PhantomData,
        }
    }
}

impl<T, P: Push<T>> Push<T> for ArcPusher<T, P> {
    #[inline]
    fn push(&mut self, element: &mut Option<T>) {
        // if element.is_none() {
        //     if self.count != 0 {
        //         self.events
        //             .send((self.index, Event::Pushed(self.count)))
        //             .expect("Failed to send message count");
        //         self.count = 0;
        //     }
        // }
        // else {
        //     self.count += 1;
        // }
        let _ =
        self.events
            .send((self.index, Event::Pushed(1)));
            // TODO : Perhaps this shouldn't be a fatal error (e.g. in shutdown).
            // .expect("Failed to send message count");

        self.pusher.push(element)
    }
}

/// The pull half of an intra-thread channel.
pub struct Puller<T, P: Pull<T>> {
    index: usize,
    count: usize,
    events: Rc<RefCell<VecDeque<(usize, Event)>>>,
    puller: P,
    phantom: ::std::marker::PhantomData<T>,
}

impl<T, P: Pull<T>>  Puller<T, P> {
    /// Wraps a puller with a message counter.
    pub fn new(puller: P, index: usize, events: Rc<RefCell<VecDeque<(usize, Event)>>>) -> Self {
        Puller {
            index,
            count: 0,
            events,
            puller,
            phantom: ::std::marker::PhantomData,
        }
    }
}
impl<T, P: Pull<T>> Pull<T> for Puller<T, P> {
    #[inline]
    fn pull(&mut self) -> &mut Option<T> {
        let result = self.puller.pull();
        if result.is_none() {
            if self.count != 0 {
                self.events
                    .borrow_mut()
                    .push_back((self.index, Event::Pulled(self.count)));
                self.count = 0;
            }
        }
        else {
            self.count += 1;
        }

        result
    }
}
<|endoftext|>


<commit_before>extern crate openzwave_stateful as openzwave;
extern crate foxbox_taxonomy as taxonomy;
extern crate transformable_channels;

use taxonomy::util::Id as TaxId;
use taxonomy::services::{ Setter, Getter, AdapterId, ServiceId, Service, Channel, ChannelKind };
use taxonomy::values::{ Value, Range };
use taxonomy::api::{ ResultMap, Error as TaxError };
use taxonomy::adapter::{ AdapterManagerHandle, AdapterWatchGuard, WatchEvent };
use transformable_channels::mpsc::ExtSender;

use openzwave::{ InitOptions, ZWaveManager, ZWaveNotification };
use openzwave::{ CommandClass, ValueGenre, ValueID };
use openzwave::{ Controller };

use std::error;
use std::fmt;
use std::thread;
use std::sync::mpsc;
use std::sync::RwLock;
use std::collections::{ HashMap, HashSet };

#[derive(Debug)]
pub enum OpenzwaveError {
    RegisteringError(TaxError),
    UnknownError
}

impl From<TaxError> for OpenzwaveError {
    fn from(err: TaxError) -> Self {
        OpenzwaveError::RegisteringError(err)
    }
}

impl From<()> for OpenzwaveError {
    fn from(_: ()) -> Self {
        OpenzwaveError::UnknownError
    }
}

impl fmt::Display for OpenzwaveError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpenzwaveError::RegisteringError(ref err) => write!(f, "IO error: {}", err),
            OpenzwaveError::UnknownError => write!(f, "Unknown error"),
        }
    }
}

impl error::Error for OpenzwaveError {
    fn description(&self) -> &str {
        match *self {
            OpenzwaveError::RegisteringError(ref err) => err.description(),
            OpenzwaveError::UnknownError => "Unknown error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            OpenzwaveError::RegisteringError(ref err) => Some(err),
            OpenzwaveError::UnknownError => None,
        }
    }
}

struct IdMap<Kind, Type> {
    map: Vec<(TaxId<Kind>, Type)>
}

impl<Kind, Type> IdMap<Kind, Type> where Type: Eq {
    fn new() -> Self {
        IdMap {
            map: Vec::new()
        }
    }

    fn push(&mut self, id: TaxId<Kind>, ozw_object: Type) {
        self.map.push((id, ozw_object))
    }

    fn find_tax_id(&mut self, ozw_object: Type) -> Option<&TaxId<Kind>> {
        let find_result = self.map.iter().find(|&&(_, ref controller)| controller == &ozw_object);
        find_result.map(|&(ref id, _)| id)
    }
}

fn kind_from_value(value: ValueID) -> Option<ChannelKind> {
    value.get_command_class().map(|cc| match cc {
        CommandClass::SensorBinary => ChannelKind::OpenClosed,
        _ => ChannelKind::Ready // TODO
    })
}

pub struct OpenzwaveAdapter {
    id: TaxId<AdapterId>,
    name: String,
    vendor: String,
    version: [u32; 4],
    ozw: ZWaveManager,
}

impl OpenzwaveAdapter {
    pub fn init<T: AdapterManagerHandle + Clone + Send + 'static> (box_manager: &T) -> Result<(), OpenzwaveError> {
        let options = InitOptions {
            device: None // TODO we should expose this as a Value
        };

        let (ozw, rx) = try!(openzwave::init(&options));

        let name = String::from("OpenZwave Adapter");
        let adapter = Box::new(OpenzwaveAdapter {
            id: TaxId::new(&name),
            name: name,
            vendor: String::from("Mozilla"),
            version: [1, 0, 0, 0],
            ozw: ozw,
        });

        adapter.spawn_notification_thread(rx, box_manager);
        try!(box_manager.add_adapter(adapter));

        Ok(())
    }

    fn spawn_notification_thread<T: AdapterManagerHandle + Clone + Send + 'static>(&self, rx: mpsc::Receiver<ZWaveNotification>, box_manager: &T) {
        let adapter_id = self.id.clone();
        let box_manager = box_manager.clone();

        thread::spawn(move || {
            let mut controller_map: IdMap<ServiceId, Controller> = IdMap::new();
            let mut getter_map: IdMap<Getter, ValueID> = IdMap::new();
            let mut setter_map: IdMap<Setter, ValueID> = IdMap::new();

            for notification in rx {
                match notification {
                    ZWaveNotification::ControllerReady(controller) => {
                        let service = format!("OpenZWave/{}", controller.get_home_id());
                        let service_id = TaxId::new(&service);
                        controller_map.push(service_id.clone(), controller);

                        box_manager.add_service(Service::empty(service_id.clone(), adapter_id.clone()));
                    }
                    ZWaveNotification::NodeNew(node)               => {}
                    ZWaveNotification::NodeAdded(node)             => {}
                    ZWaveNotification::NodeRemoved(node)           => {}
                    ZWaveNotification::ValueAdded(value)           => {
                        if value.get_genre() != ValueGenre::ValueGenre_User { continue }

                        let value_id = format!("OpenZWave/{}", value.get_id());

                        let controller_id = controller_map.find_tax_id(value.get_controller());
                        if controller_id.is_none() { continue }
                        let controller_id = controller_id.unwrap();

                        let has_getter = !value.is_write_only();
                        let has_setter = !value.is_read_only();

                        let kind = kind_from_value(value);
                        if kind.is_none() { continue }
                        let kind = kind.unwrap();

                        if has_getter {
                            let getter_id = TaxId::new(&value_id);
                            box_manager.add_getter(Channel {
                                id: getter_id.clone(),
                                service: controller_id.clone(),
                                adapter: adapter_id.clone(),
                                last_seen: None,
                                tags: HashSet::new(),
                                mechanism: Getter {
                                    kind: kind.clone(),
                                    updated: None
                                }
                            });
                        }

                        if has_setter {
                            let setter_id = TaxId::new(&value_id);
                            box_manager.add_setter(Channel {
                                id: setter_id.clone(),
                                service: controller_id.clone(),
                                adapter: adapter_id.clone(),
                                last_seen: None,
                                tags: HashSet::new(),
                                mechanism: Setter {
                                    kind: kind,
                                    updated: None
                                }
                            });
                        }
                    }
                    ZWaveNotification::ValueChanged(value)         => {}
                    ZWaveNotification::ValueRemoved(value)         => {}
                    ZWaveNotification::Generic(string)             => {}
                }
            }
        });
    }
}

impl taxonomy::adapter::Adapter for OpenzwaveAdapter {
    fn id(&self) -> TaxId<AdapterId> {
        self.id.clone()
    }

    fn name(&self) -> &str {
        &self.name
    }

    fn vendor(&self) -> &str {
        &self.vendor
    }

    fn version(&self) -> &[u32; 4] {
        &self.version
    }

    fn fetch_values(&self, set: Vec<TaxId<Getter>>) -> ResultMap<TaxId<Getter>, Option<Value>, TaxError> {
        let state = self.ozw.get_state();

        unimplemented!()
    }

    fn send_values(&self, values: HashMap<TaxId<Setter>, Value>) -> ResultMap<TaxId<Setter>, (), TaxError> {
        unimplemented!()
    }

    fn register_watch(&self, values: Vec<(TaxId<Getter>, Option<Range>)>, cb: Box<ExtSender<WatchEvent>>) -> ResultMap<TaxId<Getter>, Box<AdapterWatchGuard>, TaxError> {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>[fxbox/openzwave-adapter] fetch_values implementation<commit_after>extern crate openzwave_stateful as openzwave;
extern crate foxbox_taxonomy as taxonomy;
extern crate transformable_channels;

use taxonomy::util::Id as TaxId;
use taxonomy::services::{ Setter, Getter, AdapterId, ServiceId, Service, Channel, ChannelKind };
use taxonomy::values::*;
use taxonomy::api::{ ResultMap, Error as TaxError, InternalError };
use taxonomy::adapter::{ AdapterManagerHandle, AdapterWatchGuard, WatchEvent };
use transformable_channels::mpsc::ExtSender;

use openzwave::{ InitOptions, ZWaveManager, ZWaveNotification };
use openzwave::{ CommandClass, ValueGenre, ValueType, ValueID };
use openzwave::{ Controller };

use std::error;
use std::fmt;
use std::thread;
use std::sync::mpsc;
use std::sync::{ Arc, RwLock };
use std::collections::{ HashMap, HashSet };

#[derive(Debug)]
pub enum OpenzwaveError {
    RegisteringError(TaxError),
    UnknownError
}

impl From<TaxError> for OpenzwaveError {
    fn from(err: TaxError) -> Self {
        OpenzwaveError::RegisteringError(err)
    }
}

impl From<()> for OpenzwaveError {
    fn from(_: ()) -> Self {
        OpenzwaveError::UnknownError
    }
}

impl fmt::Display for OpenzwaveError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpenzwaveError::RegisteringError(ref err) => write!(f, "IO error: {}", err),
            OpenzwaveError::UnknownError => write!(f, "Unknown error"),
        }
    }
}

impl error::Error for OpenzwaveError {
    fn description(&self) -> &str {
        match *self {
            OpenzwaveError::RegisteringError(ref err) => err.description(),
            OpenzwaveError::UnknownError => "Unknown error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            OpenzwaveError::RegisteringError(ref err) => Some(err),
            OpenzwaveError::UnknownError => None,
        }
    }
}

#[derive(Debug, Clone)]
struct IdMap<Kind, Type> {
    map: Arc<RwLock<Vec<(TaxId<Kind>, Type)>>>
}

impl<Kind, Type> IdMap<Kind, Type> where Type: Eq + Clone, Kind: Clone {
    fn new() -> Self {
        IdMap {
            map: Arc::new(RwLock::new(Vec::new()))
        }
    }

    fn push(&mut self, id: TaxId<Kind>, ozw_object: Type) -> Result<(), ()> {
        let mut guard = try!(self.map.write().or(Err(())));
        guard.push((id, ozw_object));
        Ok(())
    }

    fn find_tax_id_from_ozw(&self, needle: &Type) -> Result<Option<TaxId<Kind>>, ()> {
        let guard = try!(self.map.read().or(Err(())));
        let find_result = guard.iter().find(|&&(_, ref controller)| controller == needle);
        Ok(find_result.map(|&(ref id, _)| id.clone()))
    }

    fn find_ozw_from_tax_id(&self, needle: &TaxId<Kind>) -> Result<Option<Type>, ()> {
        let guard = try!(self.map.read().or(Err(())));
        let find_result = guard.iter().find(|&&(ref id, _)| id == needle);
        Ok(find_result.map(|&(_, ref ozw_object)| ozw_object.clone()))
    }
}

fn kind_from_value(value: ValueID) -> Option<ChannelKind> {
    value.get_command_class().map(|cc| match cc {
        CommandClass::SensorBinary => ChannelKind::OpenClosed,
        _ => ChannelKind::Ready // TODO
    })
}

pub struct OpenzwaveAdapter {
    id: TaxId<AdapterId>,
    name: String,
    vendor: String,
    version: [u32; 4],
    ozw: ZWaveManager,
    controller_map: IdMap<ServiceId, Controller>,
    getter_map: IdMap<Getter, ValueID>,
    setter_map: IdMap<Setter, ValueID>,
}

impl OpenzwaveAdapter {
    pub fn init<T: AdapterManagerHandle + Clone + Send + 'static> (box_manager: &T) -> Result<(), OpenzwaveError> {
        let options = InitOptions {
            device: None // TODO we should expose this as a Value
        };

        let (ozw, rx) = try!(openzwave::init(&options));

        let name = String::from("OpenZwave Adapter");
        let adapter = Box::new(OpenzwaveAdapter {
            id: TaxId::new(&name),
            name: name,
            vendor: String::from("Mozilla"),
            version: [1, 0, 0, 0],
            ozw: ozw,
            controller_map: IdMap::new(),
            getter_map: IdMap::new(),
            setter_map: IdMap::new(),
        });

        adapter.spawn_notification_thread(rx, box_manager);
        try!(box_manager.add_adapter(adapter));

        Ok(())
    }

    fn spawn_notification_thread<T: AdapterManagerHandle + Clone + Send + 'static>(&self, rx: mpsc::Receiver<ZWaveNotification>, box_manager: &T) {
        let adapter_id = self.id.clone();
        let box_manager = box_manager.clone();
        let mut controller_map = self.controller_map.clone();
        let mut getter_map = self.getter_map.clone();
        let mut setter_map = self.setter_map.clone();

        thread::spawn(move || {
            for notification in rx {
                match notification {
                    ZWaveNotification::ControllerReady(controller) => {
                        let service = format!("OpenZWave/{}", controller.get_home_id());
                        let service_id = TaxId::new(&service);
                        controller_map.push(service_id.clone(), controller);

                        box_manager.add_service(Service::empty(service_id.clone(), adapter_id.clone()));
                    }
                    ZWaveNotification::NodeNew(node)               => {}
                    ZWaveNotification::NodeAdded(node)             => {}
                    ZWaveNotification::NodeRemoved(node)           => {}
                    ZWaveNotification::ValueAdded(value)           => {
                        if value.get_genre() != ValueGenre::ValueGenre_User { continue }

                        let value_id = format!("OpenZWave/{}", value.get_id());

                        let controller_id = controller_map.find_tax_id_from_ozw(&value.get_controller()).unwrap();
                        if controller_id.is_none() { continue }
                        let controller_id = controller_id.unwrap();

                        let has_getter = !value.is_write_only();
                        let has_setter = !value.is_read_only();

                        let kind = kind_from_value(value);
                        if kind.is_none() { continue }
                        let kind = kind.unwrap();

                        if has_getter {
                            let getter_id = TaxId::new(&value_id);
                            getter_map.push(getter_id.clone(), value);
                            box_manager.add_getter(Channel {
                                id: getter_id.clone(),
                                service: controller_id.clone(),
                                adapter: adapter_id.clone(),
                                last_seen: None,
                                tags: HashSet::new(),
                                mechanism: Getter {
                                    kind: kind.clone(),
                                    updated: None
                                }
                            });
                        }

                        if has_setter {
                            let setter_id = TaxId::new(&value_id);
                            setter_map.push(setter_id.clone(), value);
                            box_manager.add_setter(Channel {
                                id: setter_id.clone(),
                                service: controller_id.clone(),
                                adapter: adapter_id.clone(),
                                last_seen: None,
                                tags: HashSet::new(),
                                mechanism: Setter {
                                    kind: kind,
                                    updated: None
                                }
                            });
                        }
                    }
                    ZWaveNotification::ValueChanged(value)         => {}
                    ZWaveNotification::ValueRemoved(value)         => {}
                    ZWaveNotification::Generic(string)             => {}
                }
            }
        });
    }
}

impl taxonomy::adapter::Adapter for OpenzwaveAdapter {
    fn id(&self) -> TaxId<AdapterId> {
        self.id.clone()
    }

    fn name(&self) -> &str {
        &self.name
    }

    fn vendor(&self) -> &str {
        &self.vendor
    }

    fn version(&self) -> &[u32; 4] {
        &self.version
    }

    fn fetch_values(&self, set: Vec<TaxId<Getter>>) -> ResultMap<TaxId<Getter>, Option<Value>, TaxError> {
        set.iter().map(|id| {
            let ozw_value: Option<ValueID> = self.getter_map.find_ozw_from_tax_id(id).unwrap();

            let ozw_value: Option<Option<Value>> = ozw_value.map(|ozw_value: ValueID| {
                let result: Option<Value> = match ozw_value.get_type() {
                    ValueType::ValueType_Bool => ozw_value.as_bool().map(
                        |bool| Value::OpenClosed(
                            if bool { OpenClosed::Open } else { OpenClosed::Closed }
                        )
                    ).ok(),
                    _ => Some(Value::Unit)
                };
                result
            });
            let value_result: Result<Option<Value>, TaxError> = ozw_value.ok_or(TaxError::InternalError(InternalError::NoSuchGetter(id.clone())));
            (id.clone(), value_result)
        }).collect()
    }

    fn send_values(&self, values: HashMap<TaxId<Setter>, Value>) -> ResultMap<TaxId<Setter>, (), TaxError> {
        unimplemented!()
    }

    fn register_watch(&self, values: Vec<(TaxId<Getter>, Option<Range>)>, cb: Box<ExtSender<WatchEvent>>) -> ResultMap<TaxId<Getter>, Box<AdapterWatchGuard>, TaxError> {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|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/. */

//! Generic types that share their serialization implementations
//! for both specified and computed values.

use counter_style::{Symbols, parse_counter_style_name};
use cssparser::Parser;
use euclid::size::Size2D;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{HasViewportPercentage, OneOrMoreCommaSeparated, ToCss};
use super::CustomIdent;

pub use self::basic_shape::serialize_radius_values;

pub mod background;
pub mod basic_shape;
pub mod border;
pub mod grid;
pub mod image;
pub mod position;
pub mod rect;

#[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A type for representing CSS `width` and `height` values.
pub struct BorderRadiusSize<L>(pub Size2D<L>);

impl<L> HasViewportPercentage for BorderRadiusSize<L> {
    #[inline]
    fn has_viewport_percentage(&self) -> bool { false }
}

impl<L: Clone> From<L> for BorderRadiusSize<L> {
    fn from(other: L) -> Self {
        Self::new(other.clone(), other)
    }
}

impl<L> BorderRadiusSize<L> {
    #[inline]
    /// Create a new `BorderRadiusSize` for an area of given width and height.
    pub fn new(width: L, height: L) -> BorderRadiusSize<L> {
        BorderRadiusSize(Size2D::new(width, height))
    }
}

impl<L: Clone> BorderRadiusSize<L> {
    #[inline]
    /// Create a new `BorderRadiusSize` for a circle of given radius.
    pub fn circle(radius: L) -> BorderRadiusSize<L> {
        BorderRadiusSize(Size2D::new(radius.clone(), radius))
    }
}

impl<L: ToCss> ToCss for BorderRadiusSize<L> {
    #[inline]
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        self.0.width.to_css(dest)?;
        dest.write_str(" ")?;
        self.0.height.to_css(dest)
    }
}

// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
define_css_keyword_enum! { SymbolsType:
    "cyclic" => Cyclic,
    "numeric" => Numeric,
    "alphabetic" => Alphabetic,
    "symbolic" => Symbolic,
    "fixed" => Fixed,
}
add_impls_for_keyword_enum!(SymbolsType);

#[cfg(feature = "gecko")]
impl SymbolsType {
    /// Convert symbols type to their corresponding Gecko values.
    pub fn to_gecko_keyword(self) -> u8 {
        use gecko_bindings::structs;
        match self {
            SymbolsType::Cyclic => structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as u8,
            SymbolsType::Numeric => structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as u8,
            SymbolsType::Alphabetic => structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as u8,
            SymbolsType::Symbolic => structs::NS_STYLE_COUNTER_SYSTEM_SYMBOLIC as u8,
            SymbolsType::Fixed => structs::NS_STYLE_COUNTER_SYSTEM_FIXED as u8,
        }
    }
}

/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
///
/// Since wherever <counter-style> is used, 'none' is a valid value as
/// well, we combine them into one type to make code simpler.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CounterStyleOrNone {
    /// none
    None_,
    /// <counter-style-name>
    Name(CustomIdent),
    /// symbols()
    Symbols(SymbolsType, Symbols),
}

impl CounterStyleOrNone {
    /// disc value
    pub fn disc() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("disc")))
    }

    /// decimal value
    pub fn decimal() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("decimal")))
    }
}

no_viewport_percentage!(CounterStyleOrNone);

impl Parse for CounterStyleOrNone {
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
            return Ok(CounterStyleOrNone::Name(name));
        }
        if input.try(|i| i.expect_ident_matching("none")).is_ok() {
            return Ok(CounterStyleOrNone::None_);
        }
        if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
            return input.parse_nested_block(|input| {
                let symbols_type = input.try(|i| SymbolsType::parse(i))
                    .unwrap_or(SymbolsType::Symbolic);
                let symbols = Symbols::parse(context, input)?;
                // There must be at least two symbols for alphabetic or
                // numeric system.
                if (symbols_type == SymbolsType::Alphabetic ||
                    symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
                    return Err(());
                }
                // Identifier is not allowed in symbols() function.
                if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
                    return Err(());
                }
                Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
            });
        }
        Err(())
    }
}

impl ToCss for CounterStyleOrNone {
    #[inline]
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match self {
            &CounterStyleOrNone::None_ => dest.write_str("none"),
            &CounterStyleOrNone::Name(ref name) => name.to_css(dest),
            &CounterStyleOrNone::Symbols(ref symbols_type, ref symbols) => {
                dest.write_str("symbols(")?;
                symbols_type.to_css(dest)?;
                dest.write_str(" ")?;
                symbols.to_css(dest)?;
                dest.write_str(")")
            }
        }
    }
}

/// A settings tag, defined by a four-character tag and a setting value
///
/// For font-feature-settings, this is a tag and an integer,
/// for font-variation-settings this is a tag and a float
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTag<T> {
    /// A four-character tag, packed into a u32 (one byte per character)
    pub tag: u32,
    /// The value
    pub value: T,
}

impl<T> OneOrMoreCommaSeparated for FontSettingTag<T> {}

impl<T: ToCss> ToCss for FontSettingTag<T> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        use byteorder::{WriteBytesExt, BigEndian};
        use cssparser::serialize_string;
        use std::str;

        let mut raw: Vec<u8> = vec!();
        raw.write_u32::<BigEndian>(self.tag).unwrap();
        serialize_string(str::from_utf8(&raw).unwrap_or_default(), dest)?;

        self.value.to_css(dest)
    }
}

impl<T: Parse> Parse for FontSettingTag<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    /// https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-
    /// settings-control-the-font-variation-settings-property
    /// <string> [ on | off | <integer> ]
    /// <string> <number>
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        use byteorder::{ReadBytesExt, BigEndian};
        use std::io::Cursor;

        let tag = try!(input.expect_string());

        // allowed strings of length 4 containing chars: <U+20, U+7E>
        if tag.len() != 4 ||
           tag.chars().any(|c| c < ' ' || c > '~')
        {
            return Err(())
        }

        let mut raw = Cursor::new(tag.as_bytes());
        let u_tag = raw.read_u32::<BigEndian>().unwrap();

        Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? })
    }
}

/// A font settings value for font-variation-settings or font-feature-settings
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum FontSettings<T> {
    /// No settings (default)
    Normal,
    /// Set of settings
    Tag(Vec<FontSettingTag<T>>)
}

impl<T: ToCss> ToCss for FontSettings<T> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match *self {
            FontSettings::Normal => dest.write_str("normal"),
            FontSettings::Tag(ref ftvs) => ftvs.to_css(dest)
        }
    }
}

impl<T: Parse> Parse for FontSettings<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
            return Ok(FontSettings::Normal);
        }
        Vec::parse(context, input).map(FontSettings::Tag)
    }
}

/// An integer that can also parse "on" and "off",
/// for font-feature-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagInt(pub u32);
/// A number value to be used for font-variation-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagFloat(pub f32);

impl ToCss for FontSettingTagInt {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match self.0 {
            1 => Ok(()),
            0 => dest.write_str(" off"),
            x => write!(dest, " {}", x)
        }
    }
}

impl Parse for FontSettingTagInt {
    fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        if let Ok(value) = input.try(|input| input.expect_integer()) {
            // handle integer, throw if it is negative
            if value >= 0 {
                Ok(FontSettingTagInt(value as u32))
            } else {
                Err(())
            }
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
            // on is an alias for '1'
            Ok(FontSettingTagInt(1))
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) {
            // off is an alias for '0'
            Ok(FontSettingTagInt(0))
        } else {
            // empty value is an alias for '1'
            Ok(FontSettingTagInt(1))
        }
    }
}

impl Parse for FontSettingTagFloat {
    fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        input.expect_number().map(FontSettingTagFloat)
    }
}

impl ToCss for FontSettingTagFloat {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str(" ")?;
        self.0.to_css(dest)
    }
}

<commit_msg>Auto merge of #16987 - tictakk:ticbranch, r=emilio<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/. */

//! Generic types that share their serialization implementations
//! for both specified and computed values.

use counter_style::{Symbols, parse_counter_style_name};
use cssparser::Parser;
use euclid::size::Size2D;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{HasViewportPercentage, OneOrMoreCommaSeparated, ToCss};
use super::CustomIdent;

pub use self::basic_shape::serialize_radius_values;

pub mod background;
pub mod basic_shape;
pub mod border;
pub mod grid;
pub mod image;
pub mod position;
pub mod rect;

#[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A type for representing CSS `width` and `height` values.
pub struct BorderRadiusSize<L>(pub Size2D<L>);

impl<L> HasViewportPercentage for BorderRadiusSize<L> {
    #[inline]
    fn has_viewport_percentage(&self) -> bool { false }
}

impl<L: Clone> From<L> for BorderRadiusSize<L> {
    fn from(other: L) -> Self {
        Self::new(other.clone(), other)
    }
}

impl<L> BorderRadiusSize<L> {
    #[inline]
    /// Create a new `BorderRadiusSize` for an area of given width and height.
    pub fn new(width: L, height: L) -> BorderRadiusSize<L> {
        BorderRadiusSize(Size2D::new(width, height))
    }
}

impl<L: Clone> BorderRadiusSize<L> {
    #[inline]
    /// Create a new `BorderRadiusSize` for a circle of given radius.
    pub fn circle(radius: L) -> BorderRadiusSize<L> {
        BorderRadiusSize(Size2D::new(radius.clone(), radius))
    }
}

impl<L: ToCss> ToCss for BorderRadiusSize<L> {
    #[inline]
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        self.0.width.to_css(dest)?;
        dest.write_str(" ")?;
        self.0.height.to_css(dest)
    }
}

// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
define_css_keyword_enum! { SymbolsType:
    "cyclic" => Cyclic,
    "numeric" => Numeric,
    "alphabetic" => Alphabetic,
    "symbolic" => Symbolic,
    "fixed" => Fixed,
}
add_impls_for_keyword_enum!(SymbolsType);

#[cfg(feature = "gecko")]
impl SymbolsType {
    /// Convert symbols type to their corresponding Gecko values.
    pub fn to_gecko_keyword(self) -> u8 {
        use gecko_bindings::structs;
        match self {
            SymbolsType::Cyclic => structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as u8,
            SymbolsType::Numeric => structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as u8,
            SymbolsType::Alphabetic => structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as u8,
            SymbolsType::Symbolic => structs::NS_STYLE_COUNTER_SYSTEM_SYMBOLIC as u8,
            SymbolsType::Fixed => structs::NS_STYLE_COUNTER_SYSTEM_FIXED as u8,
        }
    }
}

/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
///
/// Since wherever <counter-style> is used, 'none' is a valid value as
/// well, we combine them into one type to make code simpler.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CounterStyleOrNone {
    /// none
    None_,
    /// <counter-style-name>
    Name(CustomIdent),
    /// symbols()
    Symbols(SymbolsType, Symbols),
}

impl CounterStyleOrNone {
    /// disc value
    pub fn disc() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("disc")))
    }

    /// decimal value
    pub fn decimal() -> Self {
        CounterStyleOrNone::Name(CustomIdent(atom!("decimal")))
    }
}

no_viewport_percentage!(CounterStyleOrNone);

impl Parse for CounterStyleOrNone {
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
            return Ok(CounterStyleOrNone::Name(name));
        }
        if input.try(|i| i.expect_ident_matching("none")).is_ok() {
            return Ok(CounterStyleOrNone::None_);
        }
        if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
            return input.parse_nested_block(|input| {
                let symbols_type = input.try(|i| SymbolsType::parse(i))
                    .unwrap_or(SymbolsType::Symbolic);
                let symbols = Symbols::parse(context, input)?;
                // There must be at least two symbols for alphabetic or
                // numeric system.
                if (symbols_type == SymbolsType::Alphabetic ||
                    symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
                    return Err(());
                }
                // Identifier is not allowed in symbols() function.
                if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
                    return Err(());
                }
                Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
            });
        }
        Err(())
    }
}

impl ToCss for CounterStyleOrNone {
    #[inline]
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match self {
            &CounterStyleOrNone::None_ => dest.write_str("none"),
            &CounterStyleOrNone::Name(ref name) => name.to_css(dest),
            &CounterStyleOrNone::Symbols(ref symbols_type, ref symbols) => {
                dest.write_str("symbols(")?;
                symbols_type.to_css(dest)?;
                dest.write_str(" ")?;
                symbols.to_css(dest)?;
                dest.write_str(")")
            }
        }
    }
}

/// A settings tag, defined by a four-character tag and a setting value
///
/// For font-feature-settings, this is a tag and an integer,
/// for font-variation-settings this is a tag and a float
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTag<T> {
    /// A four-character tag, packed into a u32 (one byte per character)
    pub tag: u32,
    /// The value
    pub value: T,
}

impl<T> OneOrMoreCommaSeparated for FontSettingTag<T> {}

impl<T: ToCss> ToCss for FontSettingTag<T> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        use byteorder::{BigEndian, ByteOrder};
        use cssparser::serialize_string;
        use std::str;

        let mut raw = [0u8; 4];
        BigEndian::write_u32(&mut raw, self.tag);
        serialize_string(str::from_utf8(&raw).unwrap_or_default(), dest)?;

        self.value.to_css(dest)
    }
}

impl<T: Parse> Parse for FontSettingTag<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    /// https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-
    /// settings-control-the-font-variation-settings-property
    /// <string> [ on | off | <integer> ]
    /// <string> <number>
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        use byteorder::{ReadBytesExt, BigEndian};
        use std::io::Cursor;

        let tag = try!(input.expect_string());

        // allowed strings of length 4 containing chars: <U+20, U+7E>
        if tag.len() != 4 ||
           tag.chars().any(|c| c < ' ' || c > '~')
        {
            return Err(())
        }

        let mut raw = Cursor::new(tag.as_bytes());
        let u_tag = raw.read_u32::<BigEndian>().unwrap();

        Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? })
    }
}

/// A font settings value for font-variation-settings or font-feature-settings
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum FontSettings<T> {
    /// No settings (default)
    Normal,
    /// Set of settings
    Tag(Vec<FontSettingTag<T>>)
}

impl<T: ToCss> ToCss for FontSettings<T> {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match *self {
            FontSettings::Normal => dest.write_str("normal"),
            FontSettings::Tag(ref ftvs) => ftvs.to_css(dest)
        }
    }
}

impl<T: Parse> Parse for FontSettings<T> {
    /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
            return Ok(FontSettings::Normal);
        }
        Vec::parse(context, input).map(FontSettings::Tag)
    }
}

/// An integer that can also parse "on" and "off",
/// for font-feature-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagInt(pub u32);
/// A number value to be used for font-variation-settings
///
/// Do not use this type anywhere except within FontSettings
/// because it serializes with the preceding space
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontSettingTagFloat(pub f32);

impl ToCss for FontSettingTagInt {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match self.0 {
            1 => Ok(()),
            0 => dest.write_str(" off"),
            x => write!(dest, " {}", x)
        }
    }
}

impl Parse for FontSettingTagInt {
    fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        if let Ok(value) = input.try(|input| input.expect_integer()) {
            // handle integer, throw if it is negative
            if value >= 0 {
                Ok(FontSettingTagInt(value as u32))
            } else {
                Err(())
            }
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
            // on is an alias for '1'
            Ok(FontSettingTagInt(1))
        } else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) {
            // off is an alias for '0'
            Ok(FontSettingTagInt(0))
        } else {
            // empty value is an alias for '1'
            Ok(FontSettingTagInt(1))
        }
    }
}

impl Parse for FontSettingTagFloat {
    fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
        input.expect_number().map(FontSettingTagFloat)
    }
}

impl ToCss for FontSettingTagFloat {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str(" ")?;
        self.0.to_css(dest)
    }
}
<|endoftext|>


<commit_before><commit_msg>events: Link to main content struct from redacted content struct docs<commit_after><|endoftext|>