<commit_before>#[macro_export]
macro_rules! into_property_source {
    ($type:ty $(: $( $ex_type:ty ),*)* ) => {
        impl IntoPropertySource<$type> for $type {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::Value(self)
            }
        }

        impl IntoPropertySource<$type> for Entity {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::Source(self)
            }
        }

        impl IntoPropertySource<$type> for (String, Entity) {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::KeySource(self.0, self.1)
            }
        }

        impl IntoPropertySource<$type> for (&str, Entity) {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::KeySource(self.0.to_string(), self.1)
            }
        }

         $(
            $(
                impl IntoPropertySource<$type> for $ex_type {
                    fn into_source(self) -> PropertySource<$type> {
                        PropertySource::Value(self.into())
                    }
                }
            )*
        )*
    };
}

/// Used to define a widget, with properties and event handlers.
#[macro_export]
macro_rules! widget {
    ( $(#[$widget_doc:meta])* $widget:ident $(<$state:ident>)* $(: $( $handler:ident ),*)*
            $( { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),*
                $( attached_properties: { $($(#[$att_prop_doc:meta])* $att_property:ident: $att_property_type:tt ),* } )*
             } )* ) => {
        $(#[$widget_doc])*
        #[derive(Default, WidgetCtx)]
        #[allow(dead_code)]
        pub struct $widget {
            attached_properties: HashMap<String, ComponentBox>,
            shared_attached_properties: HashMap<(String, String), SharedComponentBox>,
            event_handlers: Vec<Rc<dyn EventHandler>>,
            #[property(Rectangle)]
            bounds: Rectangle,
            #[property(Point)]
            position: Point,
            #[property(Constraint)]
            constraint: Constraint,
            min_width: Option<f64>,
            min_height: Option<f64>,
            max_width: Option<f64>,
            max_height: Option<f64>,
            width: Option<f64>,
            height: Option<f64>,
            name: Option<String>,
            style: Option<String>,
            id: Option<String>,
            #[property(Alignment)]
            h_align: Alignment,
            #[property(Alignment)]
            v_align: Alignment,
            #[property(Thickness)]
            margin: Thickness,
            #[property(bool)]
            enabled: bool,
            #[property(bool)]
            clip: bool,
            #[property(f32)]
            opacity: f32,
            #[property(Visibility)]
            visibility: Visibility,
            #[property(Selector)]
            selector: Selector,
            _empty: Option<RefCell<i32>>,
             $(
                $(
                    #[property($property_type)]
                    $property: Option<PropertySource<$property_type>>,
                )*
             )*
            children: Vec<Entity>,
            $(
                state: Box<$state>
            )*
        }

        impl $widget {
            // internal helper
            fn set_property<P: Component + Debug>(mut self, key: &str, property: impl IntoPropertySource<P>) -> Self {
                match property.into_source() {
                    PropertySource::Value(value) => {
                        self.attached_properties.insert(key.to_string(), ComponentBox::new(value));
                    },
                    PropertySource::Source(source) => {
                        self.shared_attached_properties.insert((key.to_string(), key.to_string()), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                    PropertySource::KeySource(source_key, source) => {
                        self.shared_attached_properties.insert((key.to_string(), source_key), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                }
                self
            }

            /// Sets the id selector.
            pub fn id(mut self, id: impl Into<String>) -> Self {
                if !self.id.is_none() {
                    return self;
                }
                self.id = Some(id.into());
                self
            }

            /// Sets the style selector (replaces the old selector property).
            pub fn style(mut self, style: impl Into<String>) -> Self {
                if !self.style.is_none() {
                    return self;
                }

                self.style = Some(style.into());
                self
            }

            /// Sets or shares the position of the widget. (Be careful the position could be adjusted by layouts).
            pub fn position(self, position: impl IntoPropertySource<Point>) -> Self {
                self.set_property("position", position)
            }

            /// Sets or shares the constraint property.
            pub fn constraint(self, constraint: impl IntoPropertySource<Constraint>) -> Self {
                self.set_property("constraint", constraint)
            }

            /// Sets or shares the vertical alignment property.
            #[inline(always)]
            pub fn v_align(self, v_align: impl IntoPropertySource<Alignment>) -> Self {
                self.set_property("v_align", v_align)
            }

             /// Sets or shares the horizontal alignment property.
             #[inline(always)]
             pub fn h_align(self, h_align: impl IntoPropertySource<Alignment>) -> Self {
                 self.set_property("h_align", h_align)
             }

            /// Sets or shares the vertical alignment property.
            #[inline(always)]
            #[deprecated = "Use v_align instead"]
            pub fn vertical_alignment(self, vertical_alignment: impl IntoPropertySource<Alignment>) -> Self {
                self.v_align(vertical_alignment)
            }

            /// Sets or shares the horizontal alignment property.
            #[inline(always)]
            #[deprecated = "Use h_align instead"]
            pub fn horizontal_alignment(self, horizontal_alignment: impl IntoPropertySource<Alignment>) -> Self {
                self.h_align(horizontal_alignment)
            }

            /// Sets or shares the visibility property.
            pub fn visibility(self, visibility: impl IntoPropertySource<Visibility>) -> Self {
                self.set_property("visibility", visibility)
            }

            /// Sets or shares the margin property.
            pub fn margin(self, margin: impl IntoPropertySource<Thickness>) -> Self {
                self.set_property("margin", margin)
            }

            /// Sets or shares the enabled property.
            pub fn enabled(self, enabled: impl IntoPropertySource<bool>) -> Self {
                self.set_property("enabled", enabled)
            }

            /// Sets or shares the clip property.
            pub fn clip(self, clip: impl IntoPropertySource<bool>) -> Self {
                self.set_property("clip", clip)
            }

            // Sets or shares the opacity property.
            pub fn opacity(self, opacity: impl IntoPropertySource<f32>) -> Self {
                self.set_property("opacity", opacity)
            }

            /// Inserts a new width.
            pub fn width(mut self, width: impl Into<f64>) -> Self {
                if !self.width.is_none() {
                    return self;
                }
                self.width = Some(width.into());
                self
            }

            /// Inserts a new height.
            pub fn height(mut self, height: impl Into<f64>) -> Self {
                if !self.height.is_none() {
                    return self;
                }
                self.height = Some(height.into());
                self
            }

            /// Inserts a new size.
            pub fn size(mut self, width: impl Into<f64>, height: impl Into<f64>) -> Self {
                if self.width.is_none() {
                    self.width = Some(width.into());
                }
                if self.height.is_none() {
                    self.height = Some(height.into());
                }
                self
            }

            /// Inserts a new min_width.
            pub fn min_width(mut self, min_width: impl Into<f64>) -> Self {
                if !self.min_width.is_none() {
                    return self;
                }
                self.min_width = Some(min_width.into());
                self
            }

            /// Inserts a new min_height.
            pub fn min_height(mut self, min_height: impl Into<f64>) -> Self {
                if !self.min_height.is_none() {
                    return self;
                }
                self.min_height = Some(min_height.into());
                self
            }

            /// Inserts a new min_size.
            pub fn min_size(mut self, min_width: impl Into<f64>, min_height: impl Into<f64>) -> Self {
                if self.min_width.is_none() {
                    self.min_width = Some(min_width.into());
                }
                if self.min_height.is_none() {
                    self.min_height = Some(min_height.into());
                }
                self
            }

            /// Inserts a new max_width.
            pub fn max_width(mut self, max_width: impl Into<f64>) -> Self {
                if !self.max_width.is_none() {
                    return self;
                }
                self.max_width = Some(max_width.into());
                self
            }

            /// Inserts a new max_height.
            pub fn max_height(mut self, max_height: impl Into<f64>) -> Self {
                if !self.max_height.is_none() {
                    return self;
                }
                self.max_height = Some(max_height.into());
                self
            }

            /// Inserts a new min_size.
            pub fn max_size(mut self, max_width: impl Into<f64>, max_height: impl Into<f64>) -> Self {
                if self.max_width.is_none() {
                    self.max_width = Some(max_width.into());
                }
                if self.max_height.is_none() {
                    self.max_height = Some(max_height.into());
                }
                self
            }

            /// Sets the debug name of the widget.
            pub fn name<P: Into<String>>(mut self, name: P) -> Self {
                self.name = Some(name.into());
                self
            }

            $(
                /// Gets a reference of the state.
                fn state(&self) -> &Box<$state> {
                    &self.state
                }

                /// Gets a mutable reference of the state.
                fn state_mut(&mut self) -> &mut Box<$state> {
                    &mut self.state
                }
            )*

            $(
                $(
                    $(#[$prop_doc])*
                    pub fn $property<P: IntoPropertySource<$property_type>>(mut self, $property: P) -> Self {
                        if !self.$property.is_none() {
                            return self;
                        }

                        self.$property = Some($property.into_source());
                        self
                    }
                )*
            )*

            $(
                $(
                    $(
                        $(#[$att_prop_doc])*
                        pub fn $att_property(property: impl IntoPropertySource<$att_property_type>) -> AttachedProperty<$att_property_type> {
                            AttachedProperty::new(stringify!($att_property), property)
                        }
                    )*
                )*
            )*
        }

        $(
            $(
                impl $handler for $widget {}
            )*
        )*

        impl Widget for $widget {
            /// Creates a new widget.
            #[inline]
            fn new() -> Self {
                $widget {
                    event_handlers: vec![],
                    enabled: true,
                    opacity: 1.,
                    clip: false,
                    $(
                        $(
                            $property: None,
                        )*
                    )*
                    children: vec![],
                    ..Default::default()
                }
            }

            fn attach<P: Component + Debug>(mut self, property: AttachedProperty<P>) -> Self {
                match property.property_source {
                    PropertySource::Value(value) => {
                        self.attached_properties.insert(property.key, ComponentBox::new(value));
                    }
                    PropertySource::Source(source) => {
                        self.shared_attached_properties.insert((property.key.clone(), property.key), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                    PropertySource::KeySource(source_key, source) => {
                        self.shared_attached_properties.insert((property.key, source_key), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                }
                self
            }

            fn insert_handler(mut self, handler: impl Into<Rc<dyn EventHandler>>) -> Self {
                self.event_handlers.push(handler.into());
                self
            }

            fn child(mut self, child: Entity) -> Self {
                self.children.push(child);
                self
            }

            fn build(self, ctx: &mut BuildContext) -> Entity {
                let entity = ctx.create_entity();

                let this = self.template(entity, ctx);

                ctx.register_render_object(entity, this.render_object());
                ctx.register_layout(entity, this.layout());

                $(
                    // workaround
                    let _ = TypeId::of::<$state>();
                    ctx.register_state(entity, this.state);
                )*

                // register default set of properties
                ctx.register_property("bounds", entity, this.bounds);
                ctx.register_property("position", entity, this.position);
                ctx.register_property("v_align", entity, this.v_align);
                ctx.register_property("h_align", entity, this.h_align);
                ctx.register_property("visibility", entity, this.visibility);
                ctx.register_property("margin", entity, this.margin);
                ctx.register_property("enabled", entity, this.enabled);
                ctx.register_property("clip", entity, this.clip);
                ctx.register_property("opacity", entity, this.opacity);
                ctx.register_property("type_id", entity, TypeId::of::<$widget>());
                ctx.register_property("type_name", entity, std::any::type_name::<$widget>().to_string());

                if let Some(id) = this.id {
                    ctx.register_property("id", entity, id);
                }

                if let Some(style) = this.style {
                    ctx.register_property("selector", entity, Selector::new(style));
                } else {
                    ctx.register_property("selector", entity, this.selector);
                }

                let mut constraint = this.constraint;

                if let Some(width) = this.width {
                    constraint.set_width(width);
                }
                if let Some(height) = this.height {
                    constraint.set_height(height);
                }
                if let Some(min_width) = this.min_width {
                    constraint.set_min_width(min_width);
                }
                if let Some(min_height) = this.min_height {
                    constraint.set_min_height(min_height);
                }
                if let Some(max_width) = this.max_width {
                    constraint.set_max_width(max_width);
                }
                if let Some(max_height) = this.max_height {
                    constraint.set_max_height(max_height);
                }
                ctx.register_property("constraint", entity, constraint);

                // register attached properties
                for (key, property) in this.attached_properties {
                    ctx.register_property_box(key.as_str(), entity, property);
                }

                for (key, property) in this.shared_attached_properties {
                    ctx.register_property_shared_box_by_source_key(key.0.as_str(), key.1.as_str(), entity, property);
                }

                // register properties
                $(
                    $(
                        if let Some($property) = this.$property {
                            match $property {
                                PropertySource::Value(value) => {
                                    ctx.register_property(stringify!($property), entity, value);
                                }
                                PropertySource::Source(source) => {
                                    ctx.register_shared_property::<$property_type>(stringify!($property), entity, source);
                                }
                                PropertySource::KeySource(source_key, source) => {
                                    ctx.register_shared_property_by_source_key::<$property_type>(stringify!($property), source_key.as_str(), entity, source);
                                }
                            }
                        }
                        else {
                            ctx.register_property(stringify!($property), entity, $property_type::default());
                        }
                    )*
                )*

                ctx.update_theme_by_state(entity);

                // register event handlers
                for handler in this.event_handlers {
                    ctx.register_handler(entity, handler);
                }

                // register name
                if let Some(name) = this.name {
                    ctx.register_property("name", entity, name);
                }

                for child in this.children {
                    ctx.append_child(entity, child);
                }

                entity
            }
        }
    };
}
<commit_msg>Added widget!() macro docs<commit_after>#[macro_export]
macro_rules! into_property_source {
    ($type:ty $(: $( $ex_type:ty ),*)* ) => {
        impl IntoPropertySource<$type> for $type {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::Value(self)
            }
        }

        impl IntoPropertySource<$type> for Entity {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::Source(self)
            }
        }

        impl IntoPropertySource<$type> for (String, Entity) {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::KeySource(self.0, self.1)
            }
        }

        impl IntoPropertySource<$type> for (&str, Entity) {
            fn into_source(self) -> PropertySource<$type> {
                PropertySource::KeySource(self.0.to_string(), self.1)
            }
        }

         $(
            $(
                impl IntoPropertySource<$type> for $ex_type {
                    fn into_source(self) -> PropertySource<$type> {
                        PropertySource::Value(self.into())
                    }
                }
            )*
        )*
    };
}

/// Defines a new type of `Widget` with its properties and event handlers.
/// Widgets defined by this macro can be instantiated by calling the new() method.
/// Inherits default properties from a base widget.
/// Implements the [`Widget`] trait automatically.
/// Also the struct serves as a [`builder`] of the [`builder pattern`].
///
/// Syntax:
///
/// ```
/// widget!(MyWidgetName<MyWidgetStateStruct>: Handler1, Handler2, Handler3 {
///     property_name_1: PropertyType1,
///     property_name_2: PropertyType2
/// });
/// ```
///
/// # Examples
///
/// Creates a widget named PersonWidget with three properties, without handlers, and with
/// a state struct called WidgetState.
/// ```
/// widget!(PersonWidget<WidgetState> {
///     name: String16,
///     age: usize,
///     average: f64
/// });
/// ```
///
/// [`Widget`]: ./widget/trait.Widget.html
/// [`builder`]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html
/// [`builder pattern`]: https://en.wikipedia.org/wiki/Builder_pattern
#[macro_export]
macro_rules! widget {
    ( $(#[$widget_doc:meta])* $widget:ident $(<$state:ident>)* $(: $( $handler:ident ),*)*
            $( { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),*
                $( attached_properties: { $($(#[$att_prop_doc:meta])* $att_property:ident: $att_property_type:tt ),* } )*
             } )* ) => {
        $(#[$widget_doc])*
        #[derive(Default, WidgetCtx)]
        #[allow(dead_code)]
        pub struct $widget {
            attached_properties: HashMap<String, ComponentBox>,
            shared_attached_properties: HashMap<(String, String), SharedComponentBox>,
            event_handlers: Vec<Rc<dyn EventHandler>>,
            #[property(Rectangle)]
            bounds: Rectangle,
            #[property(Point)]
            position: Point,
            #[property(Constraint)]
            constraint: Constraint,
            min_width: Option<f64>,
            min_height: Option<f64>,
            max_width: Option<f64>,
            max_height: Option<f64>,
            width: Option<f64>,
            height: Option<f64>,
            name: Option<String>,
            style: Option<String>,
            id: Option<String>,
            #[property(Alignment)]
            h_align: Alignment,
            #[property(Alignment)]
            v_align: Alignment,
            #[property(Thickness)]
            margin: Thickness,
            #[property(bool)]
            enabled: bool,
            #[property(bool)]
            clip: bool,
            #[property(f32)]
            opacity: f32,
            #[property(Visibility)]
            visibility: Visibility,
            #[property(Selector)]
            selector: Selector,
            _empty: Option<RefCell<i32>>,
             $(
                $(
                    #[property($property_type)]
                    $property: Option<PropertySource<$property_type>>,
                )*
             )*
            children: Vec<Entity>,
            $(
                state: Box<$state>
            )*
        }

        impl $widget {
            // internal helper
            fn set_property<P: Component + Debug>(mut self, key: &str, property: impl IntoPropertySource<P>) -> Self {
                match property.into_source() {
                    PropertySource::Value(value) => {
                        self.attached_properties.insert(key.to_string(), ComponentBox::new(value));
                    },
                    PropertySource::Source(source) => {
                        self.shared_attached_properties.insert((key.to_string(), key.to_string()), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                    PropertySource::KeySource(source_key, source) => {
                        self.shared_attached_properties.insert((key.to_string(), source_key), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                }
                self
            }

            /// Sets the id selector.
            pub fn id(mut self, id: impl Into<String>) -> Self {
                if !self.id.is_none() {
                    return self;
                }
                self.id = Some(id.into());
                self
            }

            /// Sets the style selector (replaces the old selector property).
            pub fn style(mut self, style: impl Into<String>) -> Self {
                if !self.style.is_none() {
                    return self;
                }

                self.style = Some(style.into());
                self
            }

            /// Sets or shares the position of the widget. (Be careful the position could be adjusted by layouts).
            pub fn position(self, position: impl IntoPropertySource<Point>) -> Self {
                self.set_property("position", position)
            }

            /// Sets or shares the constraint property.
            pub fn constraint(self, constraint: impl IntoPropertySource<Constraint>) -> Self {
                self.set_property("constraint", constraint)
            }

            /// Sets or shares the vertical alignment property.
            #[inline(always)]
            pub fn v_align(self, v_align: impl IntoPropertySource<Alignment>) -> Self {
                self.set_property("v_align", v_align)
            }

             /// Sets or shares the horizontal alignment property.
             #[inline(always)]
             pub fn h_align(self, h_align: impl IntoPropertySource<Alignment>) -> Self {
                 self.set_property("h_align", h_align)
             }

            /// Sets or shares the vertical alignment property.
            #[inline(always)]
            #[deprecated = "Use v_align instead"]
            pub fn vertical_alignment(self, vertical_alignment: impl IntoPropertySource<Alignment>) -> Self {
                self.v_align(vertical_alignment)
            }

            /// Sets or shares the horizontal alignment property.
            #[inline(always)]
            #[deprecated = "Use h_align instead"]
            pub fn horizontal_alignment(self, horizontal_alignment: impl IntoPropertySource<Alignment>) -> Self {
                self.h_align(horizontal_alignment)
            }

            /// Sets or shares the visibility property.
            pub fn visibility(self, visibility: impl IntoPropertySource<Visibility>) -> Self {
                self.set_property("visibility", visibility)
            }

            /// Sets or shares the margin property.
            pub fn margin(self, margin: impl IntoPropertySource<Thickness>) -> Self {
                self.set_property("margin", margin)
            }

            /// Sets or shares the enabled property.
            pub fn enabled(self, enabled: impl IntoPropertySource<bool>) -> Self {
                self.set_property("enabled", enabled)
            }

            /// Sets or shares the clip property.
            pub fn clip(self, clip: impl IntoPropertySource<bool>) -> Self {
                self.set_property("clip", clip)
            }

            /// Sets or shares the opacity property.
            pub fn opacity(self, opacity: impl IntoPropertySource<f32>) -> Self {
                self.set_property("opacity", opacity)
            }

            /// Inserts a new width.
            pub fn width(mut self, width: impl Into<f64>) -> Self {
                if !self.width.is_none() {
                    return self;
                }
                self.width = Some(width.into());
                self
            }

            /// Inserts a new height.
            pub fn height(mut self, height: impl Into<f64>) -> Self {
                if !self.height.is_none() {
                    return self;
                }
                self.height = Some(height.into());
                self
            }

            /// Inserts a new size.
            pub fn size(mut self, width: impl Into<f64>, height: impl Into<f64>) -> Self {
                if self.width.is_none() {
                    self.width = Some(width.into());
                }
                if self.height.is_none() {
                    self.height = Some(height.into());
                }
                self
            }

            /// Inserts a new min_width.
            pub fn min_width(mut self, min_width: impl Into<f64>) -> Self {
                if !self.min_width.is_none() {
                    return self;
                }
                self.min_width = Some(min_width.into());
                self
            }

            /// Inserts a new min_height.
            pub fn min_height(mut self, min_height: impl Into<f64>) -> Self {
                if !self.min_height.is_none() {
                    return self;
                }
                self.min_height = Some(min_height.into());
                self
            }

            /// Inserts a new min_size.
            pub fn min_size(mut self, min_width: impl Into<f64>, min_height: impl Into<f64>) -> Self {
                if self.min_width.is_none() {
                    self.min_width = Some(min_width.into());
                }
                if self.min_height.is_none() {
                    self.min_height = Some(min_height.into());
                }
                self
            }

            /// Inserts a new max_width.
            pub fn max_width(mut self, max_width: impl Into<f64>) -> Self {
                if !self.max_width.is_none() {
                    return self;
                }
                self.max_width = Some(max_width.into());
                self
            }

            /// Inserts a new max_height.
            pub fn max_height(mut self, max_height: impl Into<f64>) -> Self {
                if !self.max_height.is_none() {
                    return self;
                }
                self.max_height = Some(max_height.into());
                self
            }

            /// Inserts a new min_size.
            pub fn max_size(mut self, max_width: impl Into<f64>, max_height: impl Into<f64>) -> Self {
                if self.max_width.is_none() {
                    self.max_width = Some(max_width.into());
                }
                if self.max_height.is_none() {
                    self.max_height = Some(max_height.into());
                }
                self
            }

            /// Sets the debug name of the widget.
            pub fn name<P: Into<String>>(mut self, name: P) -> Self {
                self.name = Some(name.into());
                self
            }

            $(
                /// Gets a reference of the state.
                fn state(&self) -> &Box<$state> {
                    &self.state
                }

                /// Gets a mutable reference of the state.
                fn state_mut(&mut self) -> &mut Box<$state> {
                    &mut self.state
                }
            )*

            $(
                $(
                    $(#[$prop_doc])*
                    pub fn $property<P: IntoPropertySource<$property_type>>(mut self, $property: P) -> Self {
                        if !self.$property.is_none() {
                            return self;
                        }

                        self.$property = Some($property.into_source());
                        self
                    }
                )*
            )*

            $(
                $(
                    $(
                        $(#[$att_prop_doc])*
                        pub fn $att_property(property: impl IntoPropertySource<$att_property_type>) -> AttachedProperty<$att_property_type> {
                            AttachedProperty::new(stringify!($att_property), property)
                        }
                    )*
                )*
            )*
        }

        $(
            $(
                impl $handler for $widget {}
            )*
        )*

        impl Widget for $widget {
            /// Creates a new widget.
            #[inline]
            fn new() -> Self {
                $widget {
                    event_handlers: vec![],
                    enabled: true,
                    opacity: 1.,
                    clip: false,
                    $(
                        $(
                            $property: None,
                        )*
                    )*
                    children: vec![],
                    ..Default::default()
                }
            }

            fn attach<P: Component + Debug>(mut self, property: AttachedProperty<P>) -> Self {
                match property.property_source {
                    PropertySource::Value(value) => {
                        self.attached_properties.insert(property.key, ComponentBox::new(value));
                    }
                    PropertySource::Source(source) => {
                        self.shared_attached_properties.insert((property.key.clone(), property.key), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                    PropertySource::KeySource(source_key, source) => {
                        self.shared_attached_properties.insert((property.key, source_key), SharedComponentBox::new(TypeId::of::<P>(), source));
                    }
                }
                self
            }

            fn insert_handler(mut self, handler: impl Into<Rc<dyn EventHandler>>) -> Self {
                self.event_handlers.push(handler.into());
                self
            }

            fn child(mut self, child: Entity) -> Self {
                self.children.push(child);
                self
            }

            fn build(self, ctx: &mut BuildContext) -> Entity {
                let entity = ctx.create_entity();

                let this = self.template(entity, ctx);

                ctx.register_render_object(entity, this.render_object());
                ctx.register_layout(entity, this.layout());

                $(
                    // workaround
                    let _ = TypeId::of::<$state>();
                    ctx.register_state(entity, this.state);
                )*

                // register default set of properties
                ctx.register_property("bounds", entity, this.bounds);
                ctx.register_property("position", entity, this.position);
                ctx.register_property("v_align", entity, this.v_align);
                ctx.register_property("h_align", entity, this.h_align);
                ctx.register_property("visibility", entity, this.visibility);
                ctx.register_property("margin", entity, this.margin);
                ctx.register_property("enabled", entity, this.enabled);
                ctx.register_property("clip", entity, this.clip);
                ctx.register_property("opacity", entity, this.opacity);
                ctx.register_property("type_id", entity, TypeId::of::<$widget>());
                ctx.register_property("type_name", entity, std::any::type_name::<$widget>().to_string());

                if let Some(id) = this.id {
                    ctx.register_property("id", entity, id);
                }

                if let Some(style) = this.style {
                    ctx.register_property("selector", entity, Selector::new(style));
                } else {
                    ctx.register_property("selector", entity, this.selector);
                }

                let mut constraint = this.constraint;

                if let Some(width) = this.width {
                    constraint.set_width(width);
                }
                if let Some(height) = this.height {
                    constraint.set_height(height);
                }
                if let Some(min_width) = this.min_width {
                    constraint.set_min_width(min_width);
                }
                if let Some(min_height) = this.min_height {
                    constraint.set_min_height(min_height);
                }
                if let Some(max_width) = this.max_width {
                    constraint.set_max_width(max_width);
                }
                if let Some(max_height) = this.max_height {
                    constraint.set_max_height(max_height);
                }
                ctx.register_property("constraint", entity, constraint);

                // register attached properties
                for (key, property) in this.attached_properties {
                    ctx.register_property_box(key.as_str(), entity, property);
                }

                for (key, property) in this.shared_attached_properties {
                    ctx.register_property_shared_box_by_source_key(key.0.as_str(), key.1.as_str(), entity, property);
                }

                // register properties
                $(
                    $(
                        if let Some($property) = this.$property {
                            match $property {
                                PropertySource::Value(value) => {
                                    ctx.register_property(stringify!($property), entity, value);
                                }
                                PropertySource::Source(source) => {
                                    ctx.register_shared_property::<$property_type>(stringify!($property), entity, source);
                                }
                                PropertySource::KeySource(source_key, source) => {
                                    ctx.register_shared_property_by_source_key::<$property_type>(stringify!($property), source_key.as_str(), entity, source);
                                }
                            }
                        }
                        else {
                            ctx.register_property(stringify!($property), entity, $property_type::default());
                        }
                    )*
                )*

                ctx.update_theme_by_state(entity);

                // register event handlers
                for handler in this.event_handlers {
                    ctx.register_handler(entity, handler);
                }

                // register name
                if let Some(name) = this.name {
                    ctx.register_property("name", entity, name);
                }

                for child in this.children {
                    ctx.append_child(entity, child);
                }

                entity
            }
        }
    };
}
<|endoftext|>


<commit_before>
use std::sync::Mutex;
use rand;
use rand::Rng;
use std::ptr;
use std::thread;

static GRID_WDH : i32 = 256;

lazy_static! {
    static ref GRID: Mutex<Vec<u8>> = {
        let mut v = Vec::new();
        v.resize((GRID_WDH * GRID_WDH) as usize, 0);
        Mutex::new(v)
    };
}

#[no_mangle]
pub extern fn gol_randomize() -> () {
    let mut grid = GRID.lock().unwrap();
    let mut rng = rand::thread_rng();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx = (x + y * GRID_WDH) as usize;
            grid[idx] = if rng.gen() { 1 } else { 0 };
        }
    }
}

#[no_mangle]
pub extern fn gol_step(num_workers : i32) -> () {
    // Allocate new grid without wasting time setting it to any value
    let grid_size = (GRID_WDH * GRID_WDH) as usize;
    let mut new_grid = Vec::with_capacity(grid_size);
    unsafe { new_grid.set_len(grid_size); }
    let new_grid_ptr = new_grid.as_mut_ptr();

    let mut grid = GRID.lock().unwrap();
    let grid_ptr = grid.as_mut_ptr();

    // Compute the four borders
    for side in 0..4 {
        let mut x;
        let mut y;
        let xincr;
        let yincr;
        match side {
            0 => { x = 0           ; y = 0           ; xincr = 1; yincr = 0; },
            1 => { x = 0           ; y = GRID_WDH - 1; xincr = 1; yincr = 0; },
            2 => { x = 0           ; y = 0           ; xincr = 0; yincr = 1; },
            3 => { x = GRID_WDH - 1; y = 0           ; xincr = 0; yincr = 1; },
            _ => panic!("invalid side")
        }

        while x < GRID_WDH && y < GRID_WDH {
            // We're at the boundary, wrap
            let torus_idx = |x: i32, y: i32| -> u8 {
                let wrapx = if x < 0 { GRID_WDH - 1 } else { if x > GRID_WDH - 1 { 0 } else { x } };
                let wrapy = if y < 0 { GRID_WDH - 1 } else { if y > GRID_WDH - 1 { 0 } else { y } };
                let idx = wrapx + wrapy * GRID_WDH;
                unsafe { * grid_ptr.offset(idx as isize) }
            };

            // 2D indexing, faster to wrap
            let idx = (x + y * GRID_WDH) as isize;
            let alive = unsafe { * grid_ptr.offset(idx as isize) };
            let alive_nb = torus_idx(x + 1, y    ) +
                           torus_idx(x    , y + 1) +
                           torus_idx(x - 1, y    ) +
                           torus_idx(x    , y - 1) +
                           torus_idx(x + 1, y + 1) +
                           torus_idx(x - 1, y - 1) +
                           torus_idx(x + 1, y - 1) +
                           torus_idx(x - 1, y + 1);

            unsafe {
                * new_grid_ptr.offset(idx as isize) =
                    if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
            }

            x += xincr;
            y += yincr;
        }
    }

    /*
    let nthreads = 2;
    let threads: Vec<_> = (0..nthreads).map(|i| {
        let range = (GRID_WDH - 2) / nthreads;
        let seg_low = 1 + range * i;
        let seg_high = if i == nthreads - 1 { GRID_WDH - 1 } else { 1 + range * (i + 1) };

        // Allow sharing of pointers with our threads
        struct SendPtr {
            ptr : *mut u8
        }
        unsafe impl Send for SendPtr { }
        let grid_ptr_send     = SendPtr { ptr: grid_ptr     };
        let new_grid_ptr_send = SendPtr { ptr: new_grid_ptr };

        thread::spawn(move || {
            let grid_ptr     = grid_ptr_send.ptr;
            let new_grid_ptr = new_grid_ptr_send.ptr;
            // Compute interior
            for y in seg_low..seg_high {
                for x in 1..GRID_WDH - 1 {
                    // 1D indexing, no wrapping needed
                    let idx = x + y * GRID_WDH;
                    let alive = unsafe { * grid_ptr.offset(idx as isize) };
                    let alive_nb = unsafe {
                        * grid_ptr.offset((idx + 1           ) as isize) +
                        * grid_ptr.offset((idx - 1           ) as isize) +
                        * grid_ptr.offset((idx     + GRID_WDH) as isize) +
                        * grid_ptr.offset((idx     - GRID_WDH) as isize) +
                        * grid_ptr.offset((idx + 1 + GRID_WDH) as isize) +
                        * grid_ptr.offset((idx + 1 - GRID_WDH) as isize) +
                        * grid_ptr.offset((idx - 1 + GRID_WDH) as isize) +
                        * grid_ptr.offset((idx - 1 - GRID_WDH) as isize)
                    };

                    unsafe {
                        * new_grid_ptr.offset(idx as isize) =
                            if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
                    }
                }
            }
        })
    }).collect();

    for thread in threads {
        thread.join().unwrap();
    }
    */

    // Compute interior
    for y in 1..GRID_WDH - 1 {
        for x in 1..GRID_WDH - 1 {
            // 1D indexing, no wrapping needed
            let idx = x + y * GRID_WDH;
            let alive = unsafe { * grid_ptr.offset(idx as isize) };
            let alive_nb = unsafe {
                * grid_ptr.offset((idx + 1           ) as isize) +
                * grid_ptr.offset((idx - 1           ) as isize) +
                * grid_ptr.offset((idx     + GRID_WDH) as isize) +
                * grid_ptr.offset((idx     - GRID_WDH) as isize) +
                * grid_ptr.offset((idx + 1 + GRID_WDH) as isize) +
                * grid_ptr.offset((idx + 1 - GRID_WDH) as isize) +
                * grid_ptr.offset((idx - 1 + GRID_WDH) as isize) +
                * grid_ptr.offset((idx - 1 - GRID_WDH) as isize)
            };

            unsafe {
                * new_grid_ptr.offset(idx as isize) =
                    if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
            }
        }
    }

    * grid = new_grid;
}

#[no_mangle]
pub extern fn gol_draw(w: i32, h: i32, fb: *mut u32) -> () {
    // Clear background
    unsafe { ptr::write_bytes(fb, 64, (w * h) as usize); }

    let grid = GRID.lock().unwrap();

    // Center
    let xoffs = w / 2 - GRID_WDH / 2;
    let yoffs = h / 2 - GRID_WDH / 2;

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx_fb = (xoffs + x) + (yoffs + y) * w;

            // Out of bounds check for the FB
            if idx_fb < 0 || idx_fb > w * h - 1 { continue; }

            let idx_grid = x + y * GRID_WDH;

            unsafe {
                * fb.offset(idx_fb as isize) =
                    if grid[idx_grid as usize] == 1 { 0x00FFFFFF } else { 0 };
            }
        }
    }
}

#[no_mangle]
pub extern fn gol_set_pattern(w: i32, h: i32, pat: *mut u8) -> () {
    let mut grid = GRID.lock().unwrap();

    // Clear grid
    let grid_size = GRID_WDH * GRID_WDH;
    grid.clear();
    grid.resize(grid_size as usize, 0);

    // Center
    let xoffs = GRID_WDH / 2 - w / 2;
    let yoffs = GRID_WDH / 2 - h / 2;

    for y in 0..h {
        for x in 0..w {
            let idx_grid = (xoffs + x) + (yoffs + y) * GRID_WDH;

            // Out of bounds check for the grid
            if idx_grid < 0 || idx_grid > grid_size - 1 { continue; }

            let idx_pat = x + y * w;
            unsafe { grid[idx_grid as usize] = * pat.offset(idx_pat as isize); }
        }
    }
}

<commit_msg>Parallel GoL code now enabled and working<commit_after>
use std::sync::Mutex;
use rand;
use rand::Rng;
use std::ptr;
use std::thread;

static GRID_WDH : i32 = 256;

lazy_static! {
    static ref GRID: Mutex<Vec<u8>> = {
        let mut v = Vec::new();
        v.resize((GRID_WDH * GRID_WDH) as usize, 0);
        Mutex::new(v)
    };
}

#[no_mangle]
pub extern fn gol_randomize() -> () {
    let mut grid = GRID.lock().unwrap();
    let mut rng = rand::thread_rng();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx = (x + y * GRID_WDH) as usize;
            grid[idx] = if rng.gen() { 1 } else { 0 };
        }
    }
}

#[no_mangle]
pub extern fn gol_step(nthreads : i32) -> () {
    // Allocate new grid without wasting time setting it to any value
    let grid_size = (GRID_WDH * GRID_WDH) as usize;
    let mut new_grid = Vec::with_capacity(grid_size);
    unsafe { new_grid.set_len(grid_size); }
    let new_grid_ptr = new_grid.as_mut_ptr();

    let mut grid = GRID.lock().unwrap();
    let grid_ptr = grid.as_mut_ptr();

    // Compute the four borders
    for side in 0..4 {
        let mut x;
        let mut y;
        let xincr;
        let yincr;
        match side {
            0 => { x = 0           ; y = 0           ; xincr = 1; yincr = 0; },
            1 => { x = 0           ; y = GRID_WDH - 1; xincr = 1; yincr = 0; },
            2 => { x = 0           ; y = 0           ; xincr = 0; yincr = 1; },
            3 => { x = GRID_WDH - 1; y = 0           ; xincr = 0; yincr = 1; },
            _ => panic!("invalid side")
        }

        while x < GRID_WDH && y < GRID_WDH {
            // We're at the boundary, wrap
            let torus_idx = |x: i32, y: i32| -> u8 {
                let wrapx = if x < 0 { GRID_WDH - 1 } else { if x > GRID_WDH - 1 { 0 } else { x } };
                let wrapy = if y < 0 { GRID_WDH - 1 } else { if y > GRID_WDH - 1 { 0 } else { y } };
                let idx = wrapx + wrapy * GRID_WDH;
                unsafe { * grid_ptr.offset(idx as isize) }
            };

            // 2D indexing, faster to wrap
            let idx = (x + y * GRID_WDH) as isize;
            let alive = unsafe { * grid_ptr.offset(idx as isize) };
            let alive_nb = torus_idx(x + 1, y    ) +
                           torus_idx(x    , y + 1) +
                           torus_idx(x - 1, y    ) +
                           torus_idx(x    , y - 1) +
                           torus_idx(x + 1, y + 1) +
                           torus_idx(x - 1, y - 1) +
                           torus_idx(x + 1, y - 1) +
                           torus_idx(x - 1, y + 1);

            unsafe {
                * new_grid_ptr.offset(idx as isize) =
                    if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
            }

            x += xincr;
            y += yincr;
        }
    }

    // Compute interior
    if nthreads == 1 {
        // Single-threaded version. There's quite a bit of overhead for the threads, make
        // sure no performance is lost

        // TODO: Duplicate code between serial / parallel version
        for y in 1..GRID_WDH - 1 {
            for x in 1..GRID_WDH - 1 {
                // 1D indexing, no wrapping needed
                let idx = x + y * GRID_WDH;
                let alive = unsafe { * grid_ptr.offset(idx as isize) };
                let alive_nb = unsafe {
                    * grid_ptr.offset((idx + 1           ) as isize) +
                    * grid_ptr.offset((idx - 1           ) as isize) +
                    * grid_ptr.offset((idx     + GRID_WDH) as isize) +
                    * grid_ptr.offset((idx     - GRID_WDH) as isize) +
                    * grid_ptr.offset((idx + 1 + GRID_WDH) as isize) +
                    * grid_ptr.offset((idx + 1 - GRID_WDH) as isize) +
                    * grid_ptr.offset((idx - 1 + GRID_WDH) as isize) +
                    * grid_ptr.offset((idx - 1 - GRID_WDH) as isize)
                };

                unsafe {
                    * new_grid_ptr.offset(idx as isize) =
                        if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
                }
            }
        }
    } else {
        // Multi-threaded version

        let threads: Vec<_> = (0..nthreads).map(|i| {
            // Vertical slice to be processed by the current thread
            let range = (GRID_WDH - 2) / nthreads;
            let seg_low = 1 + range * i;
            let seg_high = if i == nthreads - 1 { GRID_WDH - 1 } else { 1 + range * (i + 1) };

            // Allow sharing of pointers with our threads
            struct SendPtr {
                ptr : *mut u8
            }
            unsafe impl Send for SendPtr { }
            let grid_ptr_send     = SendPtr { ptr: grid_ptr     };
            let new_grid_ptr_send = SendPtr { ptr: new_grid_ptr };

            // TODO: Thread creation seems expensive compared to our computation, need to
            //       re-use threads between steps for more scalability
            thread::spawn(move || {
                // Unwrap
                let grid_ptr     = grid_ptr_send.ptr;
                let new_grid_ptr = new_grid_ptr_send.ptr;

                for y in seg_low..seg_high {
                    for x in 1..GRID_WDH - 1 {
                        // 1D indexing, no wrapping needed
                        let idx = x + y * GRID_WDH;
                        let alive = unsafe { * grid_ptr.offset(idx as isize) };
                        let alive_nb = unsafe {
                            * grid_ptr.offset((idx + 1           ) as isize) +
                            * grid_ptr.offset((idx - 1           ) as isize) +
                            * grid_ptr.offset((idx     + GRID_WDH) as isize) +
                            * grid_ptr.offset((idx     - GRID_WDH) as isize) +
                            * grid_ptr.offset((idx + 1 + GRID_WDH) as isize) +
                            * grid_ptr.offset((idx + 1 - GRID_WDH) as isize) +
                            * grid_ptr.offset((idx - 1 + GRID_WDH) as isize) +
                            * grid_ptr.offset((idx - 1 - GRID_WDH) as isize)
                        };

                        unsafe {
                            * new_grid_ptr.offset(idx as isize) =
                                if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
                        }
                    }
                }
            })
        }).collect();

        for thread in threads {
            thread.join().unwrap();
        }
    }

    * grid = new_grid;
}

#[no_mangle]
pub extern fn gol_draw(w: i32, h: i32, fb: *mut u32) -> () {
    // Clear background
    unsafe { ptr::write_bytes(fb, 64, (w * h) as usize); }

    let grid = GRID.lock().unwrap();

    // Center
    let xoffs = w / 2 - GRID_WDH / 2;
    let yoffs = h / 2 - GRID_WDH / 2;

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx_fb = (xoffs + x) + (yoffs + y) * w;

            // Out of bounds check for the FB
            if idx_fb < 0 || idx_fb > w * h - 1 { continue; }

            let idx_grid = x + y * GRID_WDH;

            unsafe {
                * fb.offset(idx_fb as isize) =
                    if grid[idx_grid as usize] == 1 { 0x00FFFFFF } else { 0 };
            }
        }
    }
}

#[no_mangle]
pub extern fn gol_set_pattern(w: i32, h: i32, pat: *mut u8) -> () {
    let mut grid = GRID.lock().unwrap();

    // Clear grid
    let grid_size = GRID_WDH * GRID_WDH;
    grid.clear();
    grid.resize(grid_size as usize, 0);

    // Center
    let xoffs = GRID_WDH / 2 - w / 2;
    let yoffs = GRID_WDH / 2 - h / 2;

    for y in 0..h {
        for x in 0..w {
            let idx_grid = (xoffs + x) + (yoffs + y) * GRID_WDH;

            // Out of bounds check for the grid
            if idx_grid < 0 || idx_grid > grid_size - 1 { continue; }

            let idx_pat = x + y * w;
            unsafe { grid[idx_grid as usize] = * pat.offset(idx_pat as isize); }
        }
    }
}

<|endoftext|>


<commit_before>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

#[macro_export]
macro_rules! cubeb_log_internal {
    ($level: expr, $msg: expr) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ $msg);
            }
        }
    };
    ($level: expr, $fmt: expr, $($arg: expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ format!($fmt, $($arg),*));
            }
        }
    };
    (__INTERNAL__ $msg: expr) => {
        if let Some(log_callback) = $crate::ffi::g_cubeb_log_callback {
            use std::io::Write;

            let mut buf = [0 as u8; 1024];
            let filename = std::path::Path::new(file!())
                .file_name()
                .unwrap()
                .to_str()
                .unwrap();
            // 2 for ':', 1 for ' ', 1 for '\n', and 1 for converting `line!()` to number of digits
            let len = filename.len() + ((line!() as f32).log10() as usize) + $msg.len() + 5;
            assert!(len < buf.len(), "log is too long!");
            write!(&mut buf[..], "{}:{}: {}\n", filename, line!(), $msg).unwrap();
            buf[len] = 0;
            let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..len + 1]) };
            log_callback(cstr.as_ptr());
        }
    }
}

#[macro_export]
macro_rules! cubeb_logv {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Verbose, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Verbose, $fmt, $($arg),*));
}

#[macro_export]
macro_rules! cubeb_log {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Normal, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Normal, $fmt, $($arg),*));
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_normal_logging() {
        cubeb_log!("This is log at normal level");
        cubeb_log!("{} Formatted log", 1);
        cubeb_log!("{} Formatted {} log {}", 1, 2, 3);
    }

    #[test]
    fn test_verbose_logging() {
        cubeb_logv!("This is a log at verbose level");
        cubeb_logv!("{} Formatted log", 1);
        cubeb_logv!("{} Formatted {} log {}", 1, 2, 3);
    }
}
<commit_msg>Truncate log silently in release build<commit_after>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

#[macro_export]
macro_rules! cubeb_log_internal {
    ($level: expr, $msg: expr) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ $msg);
            }
        }
    };
    ($level: expr, $fmt: expr, $($arg: expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ format!($fmt, $($arg),*));
            }
        }
    };
    (__INTERNAL__ $msg: expr) => {
        if let Some(log_callback) = $crate::ffi::g_cubeb_log_callback {
            use std::io::Write;

            let mut buf = [0 as u8; 1024];
            let filename = std::path::Path::new(file!())
                .file_name()
                .unwrap()
                .to_str()
                .unwrap();
            // 2 for ':', 1 for ' ', 1 for '\n', and 1 for converting `line!()` to number of digits
            let len = filename.len() + ((line!() as f32).log10() as usize) + $msg.len() + 5;
            debug_assert!(len < buf.len(), "log will be truncated");
            let _ = write!(&mut buf[..], "{}:{}: {}\n", filename, line!(), $msg);
            let last = std::cmp::min(len, buf.len() - 1);
            buf[last] = 0;
            let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..last + 1]) };
            log_callback(cstr.as_ptr());
        }
    }
}

#[macro_export]
macro_rules! cubeb_logv {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Verbose, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Verbose, $fmt, $($arg),*));
}

#[macro_export]
macro_rules! cubeb_log {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Normal, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Normal, $fmt, $($arg),*));
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_normal_logging() {
        cubeb_log!("This is log at normal level");
        cubeb_log!("{} Formatted log", 1);
        cubeb_log!("{} Formatted {} log {}", 1, 2, 3);
    }

    #[test]
    fn test_verbose_logging() {
        cubeb_logv!("This is a log at verbose level");
        cubeb_logv!("{} Formatted log", 1);
        cubeb_logv!("{} Formatted {} log {}", 1, 2, 3);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

//! Contains support for parsing and constructing MAC addresses
//! More information about MAC addresses can be found [here]
//!
//! [here]: https://en.wikipedia.org/wiki/MAC_address

use std::fmt;
use std::result::Result;

use serde::de::{Deserialize, Deserializer, Error};
use serde::ser::{Serialize, Serializer};

/// The number of tuples (the ones separated by ":") contained in a MAC address.
pub const MAC_ADDR_LEN: usize = 6;

/// Represents a MAC address
#[derive(Clone, Copy, Debug, PartialEq)]
/// Representation of a MAC address.
pub struct MacAddr {
    bytes: [u8; MAC_ADDR_LEN],
}

impl fmt::Display for MacAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let b = &self.bytes;
        write!(
            f,
            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
            b[0], b[1], b[2], b[3], b[4], b[5]
        )
    }
}

impl MacAddr {
    /// Try to turn a `&str` into a `MacAddr` object. The method will return the `str` that failed
    /// to be parsed.
    /// # Arguments
    ///
    /// * `s` - reference that can be converted to &str.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();
    /// ```
    pub fn parse_str<S>(s: &S) -> Result<MacAddr, &str>
    where
        S: AsRef<str> + ?Sized,
    {
        let v: Vec<&str> = s.as_ref().split(':').collect();
        let mut bytes = [0u8; MAC_ADDR_LEN];

        if v.len() != MAC_ADDR_LEN {
            return Err(s.as_ref());
        }

        for i in 0..MAC_ADDR_LEN {
            if v[i].len() != 2 {
                return Err(s.as_ref());
            }
            bytes[i] = u8::from_str_radix(v[i], 16).map_err(|_| s.as_ref())?;
        }

        Ok(MacAddr { bytes })
    }

    /// Create a `MacAddr` from a slice.
    /// Does not check whether `src.len()` == `MAC_ADDR_LEN`.
    /// # Arguments
    ///
    /// * `src` - slice from which to copy MAC address content.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// let mac = MacAddr::from_bytes_unchecked(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
    /// println!("{}", mac.to_string());
    /// ```
    #[inline]
    pub fn from_bytes_unchecked(src: &[u8]) -> MacAddr {
        // TODO: using something like std::mem::uninitialized could avoid the extra initialization,
        // if this ever becomes a performance bottleneck.
        let mut bytes = [0u8; MAC_ADDR_LEN];
        bytes[..].copy_from_slice(&src);

        MacAddr { bytes }
    }

    /// Create a `MacAddr` from a slice.
    /// An error will occur if the slice length is different from `MAC_ADDR_LEN`.
    /// # Arguments
    ///
    /// * `src` - slice from which to copy MAC address content.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// let mac = MacAddr::from_bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]).unwrap();
    /// println!("{}", mac.to_string());
    /// ```
    #[inline]
    pub fn from_bytes(src: &[u8]) -> Result<MacAddr, ()> {
        if src.len() != MAC_ADDR_LEN {
            return Err(());
        }
        Ok(MacAddr::from_bytes_unchecked(src))
    }

    /// Return the underlying content of this `MacAddr` in bytes.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// let mac = MacAddr::from_bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]).unwrap();
    /// assert_eq!([0x01, 0x02, 0x03, 0x04, 0x05, 0x06], mac.get_bytes());
    /// ```
    #[inline]
    pub fn get_bytes(&self) -> &[u8] {
        &self.bytes
    }
}

impl Serialize for MacAddr {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.to_string().serialize(serializer)
    }
}

impl<'de> Deserialize<'de> for MacAddr {
    fn deserialize<D>(deserializer: D) -> Result<MacAddr, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        MacAddr::parse_str(&s).map_err(|_| D::Error::custom("The provided MAC address is invalid."))
    }
}

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

    #[test]
    fn test_mac_addr() {
        // too long
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:aa:aa").is_err());

        // invalid hex
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:ax").is_err());

        // single digit mac address component should be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:b").is_err());

        // components with more than two digits should also be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:bbb").is_err());

        let mac = MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();

        println!("parsed MAC address: {}", mac.to_string());

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);
    }

    #[test]
    fn test_from_bytes() {
        let src1 = [0x01, 0x02, 0x03, 0x04, 0x05];
        let src2 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
        let src3 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];

        assert!(MacAddr::from_bytes(&src1[..]).is_err());

        let x = MacAddr::from_bytes(&src2[..]).unwrap();
        assert_eq!(x.to_string(), String::from("01:02:03:04:05:06"));

        assert!(MacAddr::from_bytes(&src3[..]).is_err());
    }

    #[test]
    fn test_mac_addr_serialization_and_deserialization() {
        let mac: MacAddr =
            serde_json::from_str("\"12:34:56:78:9a:bc\"").expect("MacAddr deserialization failed.");

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);

        let s = serde_json::to_string(&mac).expect("MacAddr serialization failed.");
        assert_eq!(s, "\"12:34:56:78:9a:bc\"");
    }
}
<commit_msg>fix clippy::result_unit_err<commit_after>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

//! Contains support for parsing and constructing MAC addresses
//! More information about MAC addresses can be found [here]
//!
//! [here]: https://en.wikipedia.org/wiki/MAC_address

use std::fmt;
use std::result::Result;

use serde::de::{Deserialize, Deserializer, Error};
use serde::ser::{Serialize, Serializer};

/// The number of tuples (the ones separated by ":") contained in a MAC address.
pub const MAC_ADDR_LEN: usize = 6;

/// Represents a MAC address
#[derive(Clone, Copy, Debug, PartialEq)]
/// Representation of a MAC address.
pub struct MacAddr {
    bytes: [u8; MAC_ADDR_LEN],
}

impl fmt::Display for MacAddr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let b = &self.bytes;
        write!(
            f,
            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
            b[0], b[1], b[2], b[3], b[4], b[5]
        )
    }
}

impl MacAddr {
    /// Try to turn a `&str` into a `MacAddr` object. The method will return the `str` that failed
    /// to be parsed.
    /// # Arguments
    ///
    /// * `s` - reference that can be converted to &str.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();
    /// ```
    pub fn parse_str<S>(s: &S) -> Result<MacAddr, &str>
    where
        S: AsRef<str> + ?Sized,
    {
        let v: Vec<&str> = s.as_ref().split(':').collect();
        let mut bytes = [0u8; MAC_ADDR_LEN];

        if v.len() != MAC_ADDR_LEN {
            return Err(s.as_ref());
        }

        for i in 0..MAC_ADDR_LEN {
            if v[i].len() != 2 {
                return Err(s.as_ref());
            }
            bytes[i] = u8::from_str_radix(v[i], 16).map_err(|_| s.as_ref())?;
        }

        Ok(MacAddr { bytes })
    }

    /// Create a `MacAddr` from a slice.
    /// Does not check whether `src.len()` == `MAC_ADDR_LEN`.
    /// # Arguments
    ///
    /// * `src` - slice from which to copy MAC address content.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// let mac = MacAddr::from_bytes_unchecked(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
    /// println!("{}", mac.to_string());
    /// ```
    #[inline]
    pub fn from_bytes_unchecked(src: &[u8]) -> MacAddr {
        // TODO: using something like std::mem::uninitialized could avoid the extra initialization,
        // if this ever becomes a performance bottleneck.
        let mut bytes = [0u8; MAC_ADDR_LEN];
        bytes[..].copy_from_slice(&src);

        MacAddr { bytes }
    }

    /// Create a `MacAddr` from a slice.
    /// This method will return None if the slice length is different from `MAC_ADDR_LEN`.
    /// # Arguments
    ///
    /// * `src` - slice from which to copy MAC address content.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// let mac = MacAddr::from_bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]).unwrap();
    /// println!("{}", mac.to_string());
    /// ```
    #[inline]
    pub fn from_bytes(src: &[u8]) -> Option<MacAddr> {
        if src.len() != MAC_ADDR_LEN {
            return None;
        }
        Some(MacAddr::from_bytes_unchecked(src))
    }

    /// Return the underlying content of this `MacAddr` in bytes.
    /// # Example
    ///
    /// ```
    /// use self::utils::net::mac::MacAddr;
    /// let mac = MacAddr::from_bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]).unwrap();
    /// assert_eq!([0x01, 0x02, 0x03, 0x04, 0x05, 0x06], mac.get_bytes());
    /// ```
    #[inline]
    pub fn get_bytes(&self) -> &[u8] {
        &self.bytes
    }
}

impl Serialize for MacAddr {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.to_string().serialize(serializer)
    }
}

impl<'de> Deserialize<'de> for MacAddr {
    fn deserialize<D>(deserializer: D) -> Result<MacAddr, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        MacAddr::parse_str(&s).map_err(|_| D::Error::custom("The provided MAC address is invalid."))
    }
}

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

    #[test]
    fn test_mac_addr() {
        // too long
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:aa:aa").is_err());

        // invalid hex
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:ax").is_err());

        // single digit mac address component should be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:b").is_err());

        // components with more than two digits should also be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:bbb").is_err());

        let mac = MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();

        println!("parsed MAC address: {}", mac.to_string());

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);
    }

    #[test]
    fn test_from_bytes() {
        let src1 = [0x01, 0x02, 0x03, 0x04, 0x05];
        let src2 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
        let src3 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];

        assert!(MacAddr::from_bytes(&src1[..]).is_none());

        let x = MacAddr::from_bytes(&src2[..]).unwrap();
        assert_eq!(x.to_string(), String::from("01:02:03:04:05:06"));

        assert!(MacAddr::from_bytes(&src3[..]).is_none());
    }

    #[test]
    fn test_mac_addr_serialization_and_deserialization() {
        let mac: MacAddr =
            serde_json::from_str("\"12:34:56:78:9a:bc\"").expect("MacAddr deserialization failed.");

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);

        let s = serde_json::to_string(&mac).expect("MacAddr serialization failed.");
        assert_eq!(s, "\"12:34:56:78:9a:bc\"");
    }
}
<|endoftext|>


<commit_before>use crate::{Distribution, Float, InverseGaussian, Standard, StandardNormal};
use rand::Rng;

/// Error type returned from `NormalInverseGaussian::new`
#[derive(Debug, PartialEq)]
pub enum Error {
    /// `alpha <= 0` or `nan`.
    AlphaNegativeOrNull,
    /// `|beta| >= alpha` or `nan`.
    AbsoluteBetaNotLessThanAlpha,
}

/// The [normal-inverse Gaussian distribution](https://en.wikipedia.org/wiki/Normal-inverse_Gaussian_distribution)
#[derive(Debug)]
pub struct NormalInverseGaussian<N> {
    alpha: N,
    beta: N,
    inverse_gaussian: InverseGaussian<N>,
}

impl<N: Float> NormalInverseGaussian<N>
where StandardNormal: Distribution<N>
{
    /// Construct a new `NormalInverseGaussian` distribution with the given alpha (tail heaviness) and
    /// beta (asymmetry) parameters.
    pub fn new(alpha: N, beta: N) -> Result<NormalInverseGaussian<N>, Error> {
        if !(alpha > N::from(0.0)) {
            return Err(Error::AlphaNegativeOrNull);
        }

        if !(beta.abs() < alpha) {
            return Err(Error::AbsoluteBetaLessThanAlpha);
        }

        let gamma = (alpha.powf(N::from(2.)) - beta.powf(N::from(2.))).sqrt();

        let mu = N::from(1.) / gamma;

        let inverse_gaussian = InverseGaussian::new(mu, N::from(1.)).unwrap();

        Ok(Self {
            alpha,
            beta,
            inverse_gaussian,
        })
    }
}

impl<N: Float> Distribution<N> for NormalInverseGaussian<N>
where
    StandardNormal: Distribution<N>,
    Standard: Distribution<N>,
{
    fn sample<R>(&self, rng: &mut R) -> N
    where R: Rng + ?Sized {
        let inv_gauss = rng.sample(&self.inverse_gaussian);

        self.beta * inv_gauss + inv_gauss.sqrt() * rng.sample(StandardNormal)
    }
}

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

    #[test]
    fn test_normal_inverse_gaussian() {
        let norm_inv_gauss = NormalInverseGaussian::new(2.0, 1.0).unwrap();
        let mut rng = crate::test::rng(210);
        for _ in 0..1000 {
            norm_inv_gauss.sample(&mut rng);
        }
    }

    #[test]
    fn test_normal_inverse_gaussian_invalid_param() {
        assert!(NormalInverseGaussian::new(-1.0, 1.0).is_err());
        assert!(NormalInverseGaussian::new(-1.0, -1.0).is_err());
        assert!(NormalInverseGaussian::new(1.0, 2.0).is_err());
        assert!(NormalInverseGaussian::new(2.0, 1.0).is_ok());
    }

    #[test]
    fn value_stability() {
        fn test_samples<N: Float + core::fmt::Debug, D: Distribution<N>>(
            distr: D, zero: N, expected: &[N],
        ) {
            let mut rng = crate::test::rng(213);
            let mut buf = [zero; 4];
            for x in &mut buf {
                *x = rng.sample(&distr);
            }
            assert_eq!(buf, expected);
        }

        test_samples(NormalInverseGaussian::new(2.0, 1.0).unwrap(), 0f32, &[
            0.6568966, 1.3744819, 2.216063, 0.11488572,
        ]);
        test_samples(NormalInverseGaussian::new(2.0, 1.0).unwrap(), 0f64, &[
            0.6838707059642927,
            2.4447306460569784,
            0.2361045023235968,
            1.7774534624785319,
        ]);
    }
}
<commit_msg>Improve exponentiation performance<commit_after>use crate::{Distribution, Float, InverseGaussian, Standard, StandardNormal};
use rand::Rng;

/// Error type returned from `NormalInverseGaussian::new`
#[derive(Debug, PartialEq)]
pub enum Error {
    /// `alpha <= 0` or `nan`.
    AlphaNegativeOrNull,
    /// `|beta| >= alpha` or `nan`.
    AbsoluteBetaNotLessThanAlpha,
}

/// The [normal-inverse Gaussian distribution](https://en.wikipedia.org/wiki/Normal-inverse_Gaussian_distribution)
#[derive(Debug)]
pub struct NormalInverseGaussian<N> {
    alpha: N,
    beta: N,
    inverse_gaussian: InverseGaussian<N>,
}

impl<N: Float> NormalInverseGaussian<N>
where StandardNormal: Distribution<N>
{
    /// Construct a new `NormalInverseGaussian` distribution with the given alpha (tail heaviness) and
    /// beta (asymmetry) parameters.
    pub fn new(alpha: N, beta: N) -> Result<NormalInverseGaussian<N>, Error> {
        if !(alpha > N::from(0.0)) {
            return Err(Error::AlphaNegativeOrNull);
        }

        if !(beta.abs() < alpha) {
            return Err(Error::AbsoluteBetaLessThanAlpha);
        }

        let gamma = (alpha * alpha - beta * beta).sqrt();

        let mu = N::from(1.) / gamma;

        let inverse_gaussian = InverseGaussian::new(mu, N::from(1.)).unwrap();

        Ok(Self {
            alpha,
            beta,
            inverse_gaussian,
        })
    }
}

impl<N: Float> Distribution<N> for NormalInverseGaussian<N>
where
    StandardNormal: Distribution<N>,
    Standard: Distribution<N>,
{
    fn sample<R>(&self, rng: &mut R) -> N
    where R: Rng + ?Sized {
        let inv_gauss = rng.sample(&self.inverse_gaussian);

        self.beta * inv_gauss + inv_gauss.sqrt() * rng.sample(StandardNormal)
    }
}

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

    #[test]
    fn test_normal_inverse_gaussian() {
        let norm_inv_gauss = NormalInverseGaussian::new(2.0, 1.0).unwrap();
        let mut rng = crate::test::rng(210);
        for _ in 0..1000 {
            norm_inv_gauss.sample(&mut rng);
        }
    }

    #[test]
    fn test_normal_inverse_gaussian_invalid_param() {
        assert!(NormalInverseGaussian::new(-1.0, 1.0).is_err());
        assert!(NormalInverseGaussian::new(-1.0, -1.0).is_err());
        assert!(NormalInverseGaussian::new(1.0, 2.0).is_err());
        assert!(NormalInverseGaussian::new(2.0, 1.0).is_ok());
    }

    #[test]
    fn value_stability() {
        fn test_samples<N: Float + core::fmt::Debug, D: Distribution<N>>(
            distr: D, zero: N, expected: &[N],
        ) {
            let mut rng = crate::test::rng(213);
            let mut buf = [zero; 4];
            for x in &mut buf {
                *x = rng.sample(&distr);
            }
            assert_eq!(buf, expected);
        }

        test_samples(NormalInverseGaussian::new(2.0, 1.0).unwrap(), 0f32, &[
            0.6568966, 1.3744819, 2.216063, 0.11488572,
        ]);
        test_samples(NormalInverseGaussian::new(2.0, 1.0).unwrap(), 0f64, &[
            0.6838707059642927,
            2.4447306460569784,
            0.2361045023235968,
            1.7774534624785319,
        ]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 Patrick Marks
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! BIT-tree (Binary Indexed Trees, aka Fenwick Tree) maintains a prefix-sum or
//! prefix-max that can be efficiently queried and updated. From: Peter M. Fenwick (1994). "A new data structure for cumulative frequency tables". Software: Practice and Experience. 24 (3): 327–336.
//! Implementation outlined here: https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/
//!
//! # Example
//!
//! ```
//! use bio::data_structures::bit_tree::*;
//!
//! let mut bit = MaxBitTree::new(10);
//! bit.set(0, (1,0));
//! bit.set(1, (0,1));
//! bit.set(2, (2,2));
//! bit.set(3, (4,3));
//!
//! assert_eq!(bit.get(0), (1, 0));
//! assert_eq!(bit.get(1), (1, 0));
//! assert_eq!(bit.get(2), (2, 2));
//! assert_eq!(bit.get(3), (4, 3));
//! assert_eq!(bit.get(4), (4, 3));

use std::cmp::max;
use std::marker::PhantomData;
use std::ops::Add;

/// Fenwick tree prefix operator
pub trait PrefixOp<T> {
    fn operation(t1: T, t2: T) -> T;
}

/// Max Bit Tree. get(i) will return the largest element e that has been added
/// to the bit tree with set(j, e), where j <= i. Initially all positions have
/// the value T::default(). Note that a set cannot be 'undone' by inserting
/// a smaller element at the same index.
pub struct FenwickTree<T: Default + Ord, Op: PrefixOp<T>> {
    tree: Vec<T>,
    phantom: PhantomData<Op>,
}

impl<T: Ord + Default + Copy, Op: PrefixOp<T>> FenwickTree<T, Op> {
    /// Create a new bit tree with len elements
    pub fn new(len: usize) -> FenwickTree<T, Op> {
        let mut tree = Vec::new();

        // Pad length by one. The first element is unused.
        // Done this way to make the tree structure work correctly.
        for _ in 0..(len + 2) {
            tree.push(T::default());
        }

        FenwickTree {
            tree,
            phantom: PhantomData,
        }
    }

    /// get(i) returns the largest element e that has been added
    /// to the bit tree with set(j, e), where j <= i.
    pub fn get(&self, idx: usize) -> T {
        let mut idx = idx + 1;
        let mut sum = T::default();
        while idx > 0 {
            sum = Op::operation(sum, self.tree[idx]);
            idx -= (idx as isize & -(idx as isize)) as usize;
        }

        sum
    }

    /// Set the value val at position idx. val will
    /// be returned for any get(j) where j >= idx, if
    /// it is the maximum value inserted between 0 and j.
    /// Inserting a value val2 after inserting val1 where val1 > val2
    // will have no effect.
    pub fn set(&mut self, idx: usize, val: T) {
        let mut idx = idx + 1;
        while idx < self.tree.len() {
            self.tree[idx] = max(self.tree[idx], val);
            idx += (idx as isize & -(idx as isize)) as usize;
        }
    }
}

pub struct MaxOp;
impl<T: Copy + Ord> PrefixOp<T> for MaxOp {
    fn operation(t1: T, t2: T) -> T {
        max(t1, t2)
    }
}

/// Fenwick tree specialized for prefix-max
pub type MaxBitTree<T> = FenwickTree<T, MaxOp>;

pub struct SumOp;
impl<T: Copy + Add> PrefixOp<T> for SumOp
where
    T: Add<Output = T>,
{
    fn operation(t1: T, t2: T) -> T {
        t1 + t2
    }
}

/// Fenwick tree specialized for prefix-sum
pub type SumBitTree<T> = FenwickTree<T, SumOp>;

#[cfg(test)]
mod test_bit_tree {
    use super::MaxBitTree;

    #[test]
    pub fn test_bit_tree() {
        let mut bit = MaxBitTree::new(10);

        bit.set(0, (1, 0));
        bit.set(1, (1, 1));
        bit.set(2, (2, 2));
        bit.set(3, (3, 3));
        bit.set(4, (2, 4));
        bit.set(5, (2, 5));
        bit.set(6, (4, 6));
        bit.set(7, (5, 7));

        assert_eq!(bit.get(0), (1, 0));
        assert_eq!(bit.get(1), (1, 1));
        assert_eq!(bit.get(2), (2, 2));
        assert_eq!(bit.get(3), (3, 3));
        assert_eq!(bit.get(4), (3, 3));
        assert_eq!(bit.get(5), (3, 3));
        assert_eq!(bit.get(6), (4, 6));
        assert_eq!(bit.get(7), (5, 7));
    }
}
<commit_msg>Updated docs for data_structures::bit_tree (#313)<commit_after>// Copyright 2014-2015 Patrick Marks
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! BIT-tree (Binary Indexed Trees, aka Fenwick Tree) maintains a prefix-sum or
//! prefix-max that can be efficiently queried and updated. From: Peter M. Fenwick (1994). "A new data structure for cumulative frequency tables". Software: Practice and Experience. 24 (3): 327–336.
//! Implementation outlined here: https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/
//!
//! Time Complexity: O(log n) where `n = tree.len()`.
//! Memory Complexity: O(n) where `n = tree.len()`.
//! # Example for a max bit tree
//!
//! ```
//! use bio::data_structures::bit_tree::*;
//!
//! let mut bit = MaxBitTree::new(10);
//! bit.set(0, (1,0));
//! bit.set(1, (0,1));
//! bit.set(2, (2,2));
//! bit.set(3, (4,3));
//!
//! assert_eq!(bit.get(0), (1, 0));
//! assert_eq!(bit.get(1), (1, 0));
//! assert_eq!(bit.get(2), (2, 2));
//! assert_eq!(bit.get(3), (4, 3));
//! assert_eq!(bit.get(4), (4, 3));

use std::cmp::max;
use std::marker::PhantomData;
use std::ops::Add;

/// Fenwick tree prefix operator
pub trait PrefixOp<T> {
    fn operation(t1: T, t2: T) -> T;
}

/// In a max bit tree or Fenwick Tree, get(i) will return the largest element e that has been added
/// to the bit tree with set(j, e), where j <= i. Initially all positions have
/// the value T::default(). Note that a set cannot be 'undone' by inserting
/// a smaller element at the same index.
/// Time Complexity: O(n) to build a new tree or O(log n) for get() and set() operations,
/// where `n = tree.len()`.
pub struct FenwickTree<T: Default + Ord, Op: PrefixOp<T>> {
    tree: Vec<T>,
    phantom: PhantomData<Op>,
}

impl<T: Ord + Default + Copy, Op: PrefixOp<T>> FenwickTree<T, Op> {
    /// Create a new bit tree with len elements
    pub fn new(len: usize) -> FenwickTree<T, Op> {
        let mut tree = Vec::new();

        // Pad length by one. The first element is unused.
        // Done this way to make the tree structure work correctly.
        for _ in 0..(len + 2) {
            tree.push(T::default());
        }

        FenwickTree {
            tree,
            phantom: PhantomData,
        }
    }

    /// Returns the largest element e that has been added
    /// to the bit tree with set(j, e), where j <= i.
    pub fn get(&self, idx: usize) -> T {
        let mut idx = idx + 1;
        let mut sum = T::default();
        while idx > 0 {
            sum = Op::operation(sum, self.tree[idx]);
            idx -= (idx as isize & -(idx as isize)) as usize;
        }

        sum
    }

    /// Set the value `val` at position `idx`; `val` will
    /// be returned for any get(j) where j >= idx, if
    /// it is the maximum value inserted between 0 and j.
    /// Inserting a value val2 after inserting val1 where val1 > val2
    /// will have no effect.
    pub fn set(&mut self, idx: usize, val: T) {
        let mut idx = idx + 1;
        while idx < self.tree.len() {
            self.tree[idx] = Op::operation(self.tree[idx], val);
            idx += (idx as isize & -(idx as isize)) as usize;
        }
    }
}

pub struct MaxOp;
impl<T: Copy + Ord> PrefixOp<T> for MaxOp {
    fn operation(t1: T, t2: T) -> T {
        max(t1, t2)
    }
}

/// Fenwick tree specialized for prefix-max
pub type MaxBitTree<T> = FenwickTree<T, MaxOp>;

pub struct SumOp;
impl<T: Copy + Add> PrefixOp<T> for SumOp
where
    T: Add<Output = T>,
{
    fn operation(t1: T, t2: T) -> T {
        t1 + t2
    }
}

/// Fenwick tree specialized for prefix-sum
pub type SumBitTree<T> = FenwickTree<T, SumOp>;

#[cfg(test)]
mod test_bit_tree {
    use super::MaxBitTree;

    #[test]
    pub fn test_bit_tree() {
        let mut bit = MaxBitTree::new(10);

        bit.set(0, (1, 0));
        bit.set(1, (1, 1));
        bit.set(2, (2, 2));
        bit.set(3, (3, 3));
        bit.set(4, (2, 4));
        bit.set(5, (2, 5));
        bit.set(6, (4, 6));
        bit.set(7, (5, 7));

        assert_eq!(bit.get(0), (1, 0));
        assert_eq!(bit.get(1), (1, 1));
        assert_eq!(bit.get(2), (2, 2));
        assert_eq!(bit.get(3), (3, 3));
        assert_eq!(bit.get(4), (3, 3));
        assert_eq!(bit.get(5), (3, 3));
        assert_eq!(bit.get(6), (4, 6));
        assert_eq!(bit.get(7), (5, 7));
    }
}
<|endoftext|>


<commit_before>use crate::stable_hasher::{HashStable, StableHasher};
use crate::sync::{MappedReadGuard, ReadGuard, RwLock};

/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
/// where we create a large, complex value that we want to iteratively
/// update (e.g., optimize). We could clone the value for each
/// optimization, but that'd be expensive. And yet we don't just want
/// to mutate it in place, because that would spoil the idea that
/// queries are these pure functions that produce an immutable value
/// (since if you did the query twice, you could observe the mutations).
/// So instead we have the query produce a `&'tcx Steal<mir::Body<'tcx>>`
/// (to be very specific). Now we can read from this
/// as much as we want (using `borrow()`), but you can also
/// `steal()`. Once you steal, any further attempt to read will panic.
/// Therefore, we know that -- assuming no ICE -- nobody is observing
/// the fact that the MIR was updated.
///
/// Obviously, whenever you have a query that yields a `Steal` value,
/// you must treat it with caution, and make sure that you know that
/// -- once the value is stolen -- it will never be read from again.
//
// FIXME(#41710): what is the best way to model linear queries?
#[derive(Debug)]
pub struct Steal<T> {
    value: RwLock<Option<T>>,
}

impl<T> Steal<T> {
    pub fn new(value: T) -> Self {
        Steal { value: RwLock::new(Some(value)) }
    }

    #[track_caller]
    pub fn borrow(&self) -> MappedReadGuard<'_, T> {
        ReadGuard::map(self.value.borrow(), |opt| match *opt {
            None => panic!("attempted to read from stolen value"),
            Some(ref v) => v,
        })
    }

    #[track_caller]
    pub fn steal(&self) -> T {
        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
        let value = value_ref.take();
        value.expect("attempt to steal from stolen value")
    }
}

impl<CTX, T: HashStable<CTX>> HashStable<CTX> for Steal<T> {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        self.borrow().hash_stable(hcx, hasher);
    }
}
<commit_msg>arrr caught ya caller<commit_after>use crate::stable_hasher::{HashStable, StableHasher};
use crate::sync::{MappedReadGuard, ReadGuard, RwLock};

/// The `Steal` struct is intended to used as the value for a query.
/// Specifically, we sometimes have queries (*cough* MIR *cough*)
/// where we create a large, complex value that we want to iteratively
/// update (e.g., optimize). We could clone the value for each
/// optimization, but that'd be expensive. And yet we don't just want
/// to mutate it in place, because that would spoil the idea that
/// queries are these pure functions that produce an immutable value
/// (since if you did the query twice, you could observe the mutations).
/// So instead we have the query produce a `&'tcx Steal<mir::Body<'tcx>>`
/// (to be very specific). Now we can read from this
/// as much as we want (using `borrow()`), but you can also
/// `steal()`. Once you steal, any further attempt to read will panic.
/// Therefore, we know that -- assuming no ICE -- nobody is observing
/// the fact that the MIR was updated.
///
/// Obviously, whenever you have a query that yields a `Steal` value,
/// you must treat it with caution, and make sure that you know that
/// -- once the value is stolen -- it will never be read from again.
//
// FIXME(#41710): what is the best way to model linear queries?
#[derive(Debug)]
pub struct Steal<T> {
    value: RwLock<Option<T>>,
}

impl<T> Steal<T> {
    pub fn new(value: T) -> Self {
        Steal { value: RwLock::new(Some(value)) }
    }

    #[track_caller]
    pub fn borrow(&self) -> MappedReadGuard<'_, T> {
        let borrow = self.value.borrow();
        if let None = &*borrow {
            panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
        }
        ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
    }

    #[track_caller]
    pub fn steal(&self) -> T {
        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
        let value = value_ref.take();
        value.expect("attempt to steal from stolen value")
    }
}

impl<CTX, T: HashStable<CTX>> HashStable<CTX> for Steal<T> {
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        self.borrow().hash_stable(hcx, hasher);
    }
}
<|endoftext|>