<commit_before>use std::cmp::{max, min};

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{NumberOptionalNumber, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::{PixelRectangle, Pixels},
    shared_surface::SharedImageSurface,
    EdgeMode, ImageSurfaceDataExt, Pixel,
};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible morphology operations.
enum Operator {
    Erode,
    Dilate,
}

/// The `feMorphology` filter primitive.
pub struct FeMorphology {
    base: PrimitiveWithInput,
    operator: Operator,
    radius: (f64, f64),
}

impl Default for FeMorphology {
    /// Constructs a new `Morphology` with empty properties.
    #[inline]
    fn default() -> FeMorphology {
        FeMorphology {
            base: PrimitiveWithInput::new::<Self>(),
            operator: Operator::Erode,
            radius: (0.0, 0.0),
        }
    }
}

impl NodeTrait for FeMorphology {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!("", "operator") => self.operator = attr.parse(value)?,
                expanded_name!("", "radius") => {
                    let NumberOptionalNumber(x, y) =
                        attr.parse_and_validate(value, |v: NumberOptionalNumber<f64>| {
                            if v.0 >= 0.0 && v.1 >= 0.0 {
                                Ok(v)
                            } else {
                                Err(ValueErrorKind::value_error("radius cannot be negative"))
                            }
                        })?;

                    self.radius = (x, y);
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeMorphology {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);

        let (rx, ry) = self.radius;
        let (rx, ry) = ctx.paffine().transform_distance(rx, ry);

        // The radii can become negative here due to the transform.
        let rx = rx.abs();
        let ry = ry.abs();

        let mut output_surface = cairo::ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, _pixel) in Pixels::new(input.surface(), bounds) {
                // Compute the kernel rectangle bounds.
                let kernel_bounds = IRect::new(
                    (f64::from(x) - rx).floor() as i32,
                    (f64::from(y) - ry).floor() as i32,
                    (f64::from(x) + rx).ceil() as i32 + 1,
                    (f64::from(y) + ry).ceil() as i32 + 1,
                );

                // Compute the new pixel values.
                let initial = match self.operator {
                    Operator::Erode => u8::max_value(),
                    Operator::Dilate => u8::min_value(),
                };

                let mut output_pixel = Pixel {
                    r: initial,
                    g: initial,
                    b: initial,
                    a: initial,
                };

                for (_x, _y, pixel) in
                    PixelRectangle::new(&input.surface(), bounds, kernel_bounds, EdgeMode::None)
                {
                    let op = match self.operator {
                        Operator::Erode => min,
                        Operator::Dilate => max,
                    };

                    output_pixel.r = op(output_pixel.r, pixel.r);
                    output_pixel.g = op(output_pixel.g, pixel.g);
                    output_pixel.b = op(output_pixel.b, pixel.b);
                    output_pixel.a = op(output_pixel.a, pixel.a);
                }

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}

impl Parse for Operator {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, CssParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "erode" => Operator::Erode,
            "dilate" => Operator::Dilate,
        )?)
    }
}
<commit_msg>Morphology: shorten code<commit_after>use std::cmp::{max, min};

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{NumberOptionalNumber, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::{PixelRectangle, Pixels},
    shared_surface::SharedImageSurface,
    EdgeMode, ImageSurfaceDataExt, Pixel,
};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible morphology operations.
enum Operator {
    Erode,
    Dilate,
}

/// The `feMorphology` filter primitive.
pub struct FeMorphology {
    base: PrimitiveWithInput,
    operator: Operator,
    radius: (f64, f64),
}

impl Default for FeMorphology {
    /// Constructs a new `Morphology` with empty properties.
    #[inline]
    fn default() -> FeMorphology {
        FeMorphology {
            base: PrimitiveWithInput::new::<Self>(),
            operator: Operator::Erode,
            radius: (0.0, 0.0),
        }
    }
}

impl NodeTrait for FeMorphology {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!("", "operator") => self.operator = attr.parse(value)?,
                expanded_name!("", "radius") => {
                    let NumberOptionalNumber(x, y) =
                        attr.parse_and_validate(value, |v: NumberOptionalNumber<f64>| {
                            if v.0 >= 0.0 && v.1 >= 0.0 {
                                Ok(v)
                            } else {
                                Err(ValueErrorKind::value_error("radius cannot be negative"))
                            }
                        })?;

                    self.radius = (x, y);
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeMorphology {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);

        let (rx, ry) = self.radius;
        let (rx, ry) = ctx.paffine().transform_distance(rx, ry);

        // The radii can become negative here due to the transform.
        let (rx, ry) = (rx.abs(), ry.abs());

        let mut output_surface = cairo::ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, _pixel) in Pixels::new(input.surface(), bounds) {
                // Compute the kernel rectangle bounds.
                let kernel_bounds = IRect::new(
                    (f64::from(x) - rx).floor() as i32,
                    (f64::from(y) - ry).floor() as i32,
                    (f64::from(x) + rx).ceil() as i32 + 1,
                    (f64::from(y) + ry).ceil() as i32 + 1,
                );

                // Compute the new pixel values.
                let initial = match self.operator {
                    Operator::Erode => u8::max_value(),
                    Operator::Dilate => u8::min_value(),
                };

                let mut output_pixel = Pixel {
                    r: initial,
                    g: initial,
                    b: initial,
                    a: initial,
                };

                for (_x, _y, pixel) in
                    PixelRectangle::new(&input.surface(), bounds, kernel_bounds, EdgeMode::None)
                {
                    let op = match self.operator {
                        Operator::Erode => min,
                        Operator::Dilate => max,
                    };

                    output_pixel.r = op(output_pixel.r, pixel.r);
                    output_pixel.g = op(output_pixel.g, pixel.g);
                    output_pixel.b = op(output_pixel.b, pixel.b);
                    output_pixel.a = op(output_pixel.a, pixel.a);
                }

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}

impl Parse for Operator {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, CssParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "erode" => Operator::Erode,
            "dilate" => Operator::Dilate,
        )?)
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Loops/Downward_for

#![feature(inclusive_range_syntax)]

fn main() {
    for i in (1..10).rev() {
        println!("{}", i);
    }
}
<commit_msg>use inclusive range for downward_for<commit_after>// http://rosettacode.org/wiki/Loops/Downward_for

#![feature(inclusive_range_syntax)]

fn main() {
    for i in (1...10).rev() {
        println!("{}", i);
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `TimeoutAdjuster` is used to dynamically change propose timeout.

use std::fmt::Debug;

use events::Milliseconds;
use storage::Snapshot;
use blockchain::Schema;

/// `TimeoutAdjuster` trait is used to dynamically change propose timeout.
///
/// # Examples
///
/// Implementing `TimeoutAdjuster`:
///
/// ```
/// use exonum::node::State;
/// use exonum::node::timeout_adjuster::TimeoutAdjuster;
/// use exonum::events::Milliseconds;
/// use exonum::storage::Snapshot;
///
/// # #[allow(dead_code)]
/// struct CustomAdjuster {}
///
/// impl TimeoutAdjuster for CustomAdjuster {
///     fn adjust_timeout(&mut self, _: &Snapshot) -> Milliseconds {
///         let schema = Schema::new(snapshot);
///         let transactions = schema.last_block().map_or(0, |block| block.tx_count());
///         // Simply increase propose time after empty blocks.
///         if transactions == 0
///             1000
///         } else {
///             200
///         }
///     }
/// }
/// ```
/// For more examples see `Constant`, `Dynamic` and `MovingAverage` implementations.
pub trait TimeoutAdjuster: Send + Debug {
    /// Called during node initialization and after accepting a new height.
    fn adjust_timeout(&mut self, view: &Snapshot) -> Milliseconds;
}

/// `Adjuster` implementation that always returns the same value.
#[derive(Debug)]
pub struct Constant {
    timeout: Milliseconds,
}

impl Constant {
    /// Creates a new `Constant` timeout adjuster instance with the given timeout.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::node::timeout_adjuster::Constant;
    ///
    /// let mut adjuster = Constant::new(10);
    /// ```
    pub fn new(timeout: Milliseconds) -> Self {
        Constant { timeout }
    }
}

impl TimeoutAdjuster for Constant {
    fn adjust_timeout(&mut self, _: &Snapshot) -> Milliseconds {
        self.timeout
    }
}

/// `Adjuster` implementation that returns minimal or maximal timeout value depending on the
/// transactions amount in the previous block.
#[derive(Debug, Default)]
pub struct Dynamic {
    min: Milliseconds,
    max: Milliseconds,
    threshold: u32,
}

impl Dynamic {
    /// Creates a new `Dynamic` timeout adjuster instance with given parameters.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::node::timeout_adjuster::Dynamic;
    ///
    /// let mut adjuster = Dynamic::new(1, 10, 100);
    /// ```
    pub fn new(min: Milliseconds, max: Milliseconds, threshold: u32) -> Self {
        Dynamic {
            min,
            max,
            threshold,
        }
    }

    fn adjust_timeout_impl(&mut self, current_load: u32) -> Milliseconds {
        if current_load >= self.threshold {
            self.min
        } else {
            self.max
        }
    }
}

impl TimeoutAdjuster for Dynamic {
    fn adjust_timeout(&mut self, snapshot: &Snapshot) -> Milliseconds {
        let schema = Schema::new(snapshot);
        let threshold = self.threshold;
        self.adjust_timeout_impl(schema.last_block().map_or(
            threshold,
            |block| block.tx_count(),
        ))
    }
}

/// Moving average timeout calculation. Initial timeout is equal to `min_timeout`.
#[derive(Debug)]
pub struct MovingAverage {
    min: f64,
    max: f64,
    adjustment_speed: f64,
    txs_block_limit: f64,
    optimal_block_load: f64,
    previous_timeout: f64,
}

impl MovingAverage {
    /// Creates `MovingAverage` that generates values between `min_timeout` and `max_timeout`.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::node::timeout_adjuster::MovingAverage;
    ///
    /// let mut adjuster = MovingAverage::new(1, 10, 0.5, 0.75);
    /// ```
    pub fn new(
        min: Milliseconds,
        max: Milliseconds,
        adjustment_speed: f64,
        txs_block_limit: u32,
        optimal_block_load: f64,
    ) -> Self {
        MovingAverage {
            min: min as f64,
            max: max as f64,
            adjustment_speed,
            txs_block_limit: txs_block_limit as f64,
            optimal_block_load,
            previous_timeout: min as f64,
        }
    }

    fn adjust_timeout_impl(&mut self, current_load: f64) -> Milliseconds {
        let optimal_load = self.txs_block_limit * self.optimal_block_load;
        let load_percent = current_load / optimal_load;

        let target_t = if current_load < optimal_load {
            self.max - (self.max - self.previous_timeout) * load_percent
        } else {
            self.previous_timeout -
                (self.previous_timeout - self.min) * (load_percent - 1.) /
                    (1. / self.optimal_block_load - 1.)
        };

        self.previous_timeout = target_t * self.adjustment_speed +
            self.previous_timeout * (1. - self.adjustment_speed);
        self.previous_timeout.round() as Milliseconds
    }
}

impl TimeoutAdjuster for MovingAverage {
    fn adjust_timeout(&mut self, snapshot: &Snapshot) -> Milliseconds {
        let schema = Schema::new(snapshot);
        self.adjust_timeout_impl(schema.last_block().map_or(
            0.,
            |block| block.tx_count() as f64,
        ))
    }
}

#[cfg(test)]
mod tests {
    use env_logger;

    use super::*;
    use events::Milliseconds;

    #[test]
    fn dynamic_timeout_adjuster() {
        static MIN_TIMEOUT: Milliseconds = 1;
        static MAX_TIMEOUT: Milliseconds = 10;
        static THRESHOLD: u32 = 2;

        let test_data = [
            (0, MAX_TIMEOUT),
            (1, MAX_TIMEOUT),
            (2, MIN_TIMEOUT),
            (3, MIN_TIMEOUT),
            (10, MIN_TIMEOUT),
            (100, MIN_TIMEOUT),
        ];

        let mut adjuster = Dynamic::new(MIN_TIMEOUT, MAX_TIMEOUT, THRESHOLD);

        for data in &test_data {
            assert_eq!(data.1, adjuster.adjust_timeout_impl(data.0));
        }
    }

    #[test]
    fn moving_average_timeout_adjuster() {
        let _ = env_logger::init();

        static MIN_TIMEOUT: Milliseconds = 1;
        static MAX_TIMEOUT: Milliseconds = 10000;
        static TXS_BLOCK_LIMIT: f64 = 5000.;
        static TEST_COUNT: usize = 10;

        let mut adjuster =
            MovingAverage::new(MIN_TIMEOUT, MAX_TIMEOUT, 0.75, TXS_BLOCK_LIMIT as u32, 0.7);

        // Timeout should stay minimal if there are `TXS_BLOCK_LIMIT` or more transactions.
        for _ in 0..TEST_COUNT {
            assert_eq!(MIN_TIMEOUT, adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT));
        }

        for _ in 0..TEST_COUNT {
            assert_eq!(
                MIN_TIMEOUT,
                adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT * 2.)
            );
        }

        static TXS_TEST_DATA: &'static [f64] = &[
            0.,
            100.,
            200.,
            300.,
            400.,
            500.,
            1000.,
            1500.,
            2000.,
            2500.,
            3000.,
            4000.,
            4500.,
            5000.,
            5500.,
            6000.,
        ];

        // As the transaction number declines, timeout should increase until it reaches maximum.
        let mut previous_timeout = adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT);
        for transactions in TXS_TEST_DATA.iter().rev() {
            let timeout = adjuster.adjust_timeout_impl(*transactions);
            info!(
                "Timeout: current = {}, previous = {}",
                timeout,
                previous_timeout
            );
            assert!(timeout >= previous_timeout);
            previous_timeout = timeout;
        }

        // Timeout should stay maximal if there are no transactions for some time.
        for _ in 0..TEST_COUNT {
            assert_eq!(MAX_TIMEOUT, adjuster.adjust_timeout_impl(0.));
        }

        // As the transactions number increases, timeout should decrease until it reaches minimum.
        let mut previous_timeout = adjuster.adjust_timeout_impl(0.);
        for transactions in TXS_TEST_DATA {
            let timeout = adjuster.adjust_timeout_impl(*transactions);
            info!(
                "Timeout: current = {}, previous = {}",
                timeout,
                previous_timeout
            );
            assert!(timeout <= previous_timeout);
            previous_timeout = timeout;
        }
        assert_eq!(MIN_TIMEOUT, adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT));
    }
}
<commit_msg>Fix tests<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `TimeoutAdjuster` is used to dynamically change propose timeout.

use std::fmt::Debug;

use events::Milliseconds;
use storage::Snapshot;
use blockchain::Schema;

/// `TimeoutAdjuster` trait is used to dynamically change propose timeout.
///
/// # Examples
///
/// Implementing `TimeoutAdjuster`:
///
/// ```
/// use exonum::node::timeout_adjuster::TimeoutAdjuster;
/// use exonum::events::Milliseconds;
/// use exonum::storage::Snapshot;
/// use exonum::blockchain::Schema;
///
/// # #[allow(dead_code)]
/// # #[derive(Debug)]
/// struct CustomAdjuster {}
///
/// impl TimeoutAdjuster for CustomAdjuster {
///     fn adjust_timeout(&mut self, snapshot: &Snapshot) -> Milliseconds {
///         let schema = Schema::new(snapshot);
///         let transactions = schema.last_block().map_or(0, |block| block.tx_count());
///         // Simply increase propose time after empty blocks.
///         if transactions == 0 {
///             1000
///         } else {
///             200
///         }
///     }
/// }
/// ```
/// For more examples see `Constant`, `Dynamic` and `MovingAverage` implementations.
pub trait TimeoutAdjuster: Send + Debug {
    /// Called during node initialization and after accepting a new height.
    fn adjust_timeout(&mut self, view: &Snapshot) -> Milliseconds;
}

/// `Adjuster` implementation that always returns the same value.
#[derive(Debug)]
pub struct Constant {
    timeout: Milliseconds,
}

impl Constant {
    /// Creates a new `Constant` timeout adjuster instance with the given timeout.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![allow(unused_mut)]
    /// use exonum::node::timeout_adjuster::Constant;
    ///
    /// let mut adjuster = Constant::new(10);
    /// # drop(adjuster);
    /// ```
    pub fn new(timeout: Milliseconds) -> Self {
        Constant { timeout }
    }
}

impl TimeoutAdjuster for Constant {
    fn adjust_timeout(&mut self, _: &Snapshot) -> Milliseconds {
        self.timeout
    }
}

/// `Adjuster` implementation that returns minimal or maximal timeout value depending on the
/// transactions amount in the previous block.
#[derive(Debug, Default)]
pub struct Dynamic {
    min: Milliseconds,
    max: Milliseconds,
    threshold: u32,
}

impl Dynamic {
    /// Creates a new `Dynamic` timeout adjuster instance with given parameters.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![allow(unused_mut)]
    /// use exonum::node::timeout_adjuster::Dynamic;
    ///
    /// let mut adjuster = Dynamic::new(1, 10, 100);
    /// # drop(adjuster);
    /// ```
    pub fn new(min: Milliseconds, max: Milliseconds, threshold: u32) -> Self {
        Dynamic {
            min,
            max,
            threshold,
        }
    }

    fn adjust_timeout_impl(&mut self, current_load: u32) -> Milliseconds {
        if current_load >= self.threshold {
            self.min
        } else {
            self.max
        }
    }
}

impl TimeoutAdjuster for Dynamic {
    fn adjust_timeout(&mut self, snapshot: &Snapshot) -> Milliseconds {
        let schema = Schema::new(snapshot);
        let threshold = self.threshold;
        self.adjust_timeout_impl(schema.last_block().map_or(
            threshold,
            |block| block.tx_count(),
        ))
    }
}

/// Moving average timeout calculation. Initial timeout is equal to `min_timeout`.
#[derive(Debug)]
pub struct MovingAverage {
    min: f64,
    max: f64,
    adjustment_speed: f64,
    txs_block_limit: f64,
    optimal_block_load: f64,
    previous_timeout: f64,
}

impl MovingAverage {
    /// Creates `MovingAverage` that generates values between `min_timeout` and `max_timeout`.
    ///
    /// # Examples
    ///
    /// ```
    /// # #![allow(unused_mut)]
    /// use exonum::node::timeout_adjuster::MovingAverage;
    ///
    /// let mut adjuster = MovingAverage::new(1, 10, 0.5, 5000, 0.75);
    /// # drop(adjuster);
    /// ```
    pub fn new(
        min: Milliseconds,
        max: Milliseconds,
        adjustment_speed: f64,
        txs_block_limit: u32,
        optimal_block_load: f64,
    ) -> Self {
        MovingAverage {
            min: min as f64,
            max: max as f64,
            adjustment_speed,
            txs_block_limit: txs_block_limit as f64,
            optimal_block_load,
            previous_timeout: min as f64,
        }
    }

    fn adjust_timeout_impl(&mut self, current_load: f64) -> Milliseconds {
        let optimal_load = self.txs_block_limit * self.optimal_block_load;
        let load_percent = current_load / optimal_load;

        let target_t = if current_load < optimal_load {
            self.max - (self.max - self.previous_timeout) * load_percent
        } else {
            self.previous_timeout -
                (self.previous_timeout - self.min) * (load_percent - 1.) /
                    (1. / self.optimal_block_load - 1.)
        };

        self.previous_timeout = target_t * self.adjustment_speed +
            self.previous_timeout * (1. - self.adjustment_speed);
        self.previous_timeout.round() as Milliseconds
    }
}

impl TimeoutAdjuster for MovingAverage {
    fn adjust_timeout(&mut self, snapshot: &Snapshot) -> Milliseconds {
        let schema = Schema::new(snapshot);
        self.adjust_timeout_impl(schema.last_block().map_or(
            0.,
            |block| block.tx_count() as f64,
        ))
    }
}

#[cfg(test)]
mod tests {
    use env_logger;

    use super::*;
    use events::Milliseconds;

    #[test]
    fn dynamic_timeout_adjuster() {
        static MIN_TIMEOUT: Milliseconds = 1;
        static MAX_TIMEOUT: Milliseconds = 10;
        static THRESHOLD: u32 = 2;

        let test_data = [
            (0, MAX_TIMEOUT),
            (1, MAX_TIMEOUT),
            (2, MIN_TIMEOUT),
            (3, MIN_TIMEOUT),
            (10, MIN_TIMEOUT),
            (100, MIN_TIMEOUT),
        ];

        let mut adjuster = Dynamic::new(MIN_TIMEOUT, MAX_TIMEOUT, THRESHOLD);

        for data in &test_data {
            assert_eq!(data.1, adjuster.adjust_timeout_impl(data.0));
        }
    }

    #[test]
    fn moving_average_timeout_adjuster() {
        let _ = env_logger::init();

        static MIN_TIMEOUT: Milliseconds = 1;
        static MAX_TIMEOUT: Milliseconds = 10000;
        static TXS_BLOCK_LIMIT: f64 = 5000.;
        static TEST_COUNT: usize = 10;

        let mut adjuster =
            MovingAverage::new(MIN_TIMEOUT, MAX_TIMEOUT, 0.75, TXS_BLOCK_LIMIT as u32, 0.7);

        // Timeout should stay minimal if there are `TXS_BLOCK_LIMIT` or more transactions.
        for _ in 0..TEST_COUNT {
            assert_eq!(MIN_TIMEOUT, adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT));
        }

        for _ in 0..TEST_COUNT {
            assert_eq!(
                MIN_TIMEOUT,
                adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT * 2.)
            );
        }

        static TXS_TEST_DATA: &'static [f64] = &[
            0.,
            100.,
            200.,
            300.,
            400.,
            500.,
            1000.,
            1500.,
            2000.,
            2500.,
            3000.,
            4000.,
            4500.,
            5000.,
            5500.,
            6000.,
        ];

        // As the transaction number declines, timeout should increase until it reaches maximum.
        let mut previous_timeout = adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT);
        for transactions in TXS_TEST_DATA.iter().rev() {
            let timeout = adjuster.adjust_timeout_impl(*transactions);
            info!(
                "Timeout: current = {}, previous = {}",
                timeout,
                previous_timeout
            );
            assert!(timeout >= previous_timeout);
            previous_timeout = timeout;
        }

        // Timeout should stay maximal if there are no transactions for some time.
        for _ in 0..TEST_COUNT {
            assert_eq!(MAX_TIMEOUT, adjuster.adjust_timeout_impl(0.));
        }

        // As the transactions number increases, timeout should decrease until it reaches minimum.
        let mut previous_timeout = adjuster.adjust_timeout_impl(0.);
        for transactions in TXS_TEST_DATA {
            let timeout = adjuster.adjust_timeout_impl(*transactions);
            info!(
                "Timeout: current = {}, previous = {}",
                timeout,
                previous_timeout
            );
            assert!(timeout <= previous_timeout);
            previous_timeout = timeout;
        }
        assert_eq!(MIN_TIMEOUT, adjuster.adjust_timeout_impl(TXS_BLOCK_LIMIT));
    }
}
<|endoftext|>


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

//! Adapters for various formats for [`Uuid`]s
//!
//! [`Uuid`]: ../struct.Uuid.html

use prelude::*;

mod core_support;

/// An adaptor for formatting an [`Uuid`] as a hyphenated string.
///
/// Takes an owned instance of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Hyphenated(Uuid);

/// An adaptor for formatting an [`Uuid`] as a hyphenated string.
///
/// Takes a reference of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct HyphenatedRef<'a>(&'a Uuid);

/// An adaptor for formatting an [`Uuid`] as a simple string.
///
/// Takes an owned instance of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Simple(Uuid);

/// An adaptor for formatting an [`Uuid`] as a simple string.
///
/// Takes a reference of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct SimpleRef<'a>(&'a Uuid);

/// An adaptor for formatting an [`Uuid`] as a URN string.
///
/// Takes an owned instance of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Urn(Uuid);

/// An adaptor for formatting an [`Uuid`] as a URN string.
///
/// Takes a reference of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UrnRef<'a>(&'a Uuid);

impl Uuid {
    /// Creates a [`UuidHyphenated`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_hyphenated(self) -> Hyphenated {
        Hyphenated::from_uuid(self)
    }

    /// Creates a [`UuidHyphenated`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_hyphenated(self) -> Hyphenated {
        Hyphenated::from_uuid(self)
    }

    /// Creates a [`UuidHyphenatedRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_hyphenated_ref(&self) -> HyphenatedRef {
        HyphenatedRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidHyphenatedRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_hyphenated_ref(&self) -> HyphenatedRef {
        HyphenatedRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidSimple`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_simple(self) -> Simple {
        Simple::from_uuid(self)
    }

    /// Creates a [`UuidSimple`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_simple(self) -> Simple {
        Simple::from_uuid(self)
    }

    /// Creates a [`UuidSimpleRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_simple_ref(&self) -> SimpleRef {
        SimpleRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidSimpleRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_simple_ref(&self) -> SimpleRef {
        SimpleRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidUrn`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_urn(self) -> Urn {
        Urn::from_uuid(self)
    }

    /// Creates a [`UuidUrn`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_urn(self) -> Urn {
        Urn::from_uuid(self)
    }

    /// Creates a [`UuidUrnRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_urn_ref(&self) -> UrnRef {
        UrnRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidUrnRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_urn_ref(&self) -> UrnRef {
        UrnRef::from_uuid_ref(self)
    }
}

impl Hyphenated {
    /// The length of a hyphenated [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 36;

    /// Creates a [`UuidHyphenated`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Hyphenated(uuid)
    }

    /// Creates a [`UuidHyphenated`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(feature = "const_fn")]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Hyphenated(uuid)
    }
}

impl<'a> HyphenatedRef<'a> {
    /// The length of a hyphenated [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 36;

    /// Creates a [`UuidHyphenatedRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        HyphenatedRef(uuid)
    }

    /// Creates a [`UuidHyphenatedRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(feature = "const_fn")]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        HyphenatedRef(uuid)
    }
}

impl Simple {
    /// The length of a simple [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 32;

    /// Creates a [`UuidSimple`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Simple(uuid)
    }

    /// Creates a [`UuidSimple`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(feature = "const_fn")]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Simple(uuid)
    }
}

impl<'a> SimpleRef<'a> {
    /// The length of a simple [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 32;

    /// Creates a [`UuidSimpleRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        SimpleRef(uuid)
    }

    /// Creates a [`UuidSimpleRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(feature = "const_fn")]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        SimpleRef(uuid)
    }
}

impl Urn {
    /// The length of a URN [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 45;

    /// Creates a [`UuidUrn`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Urn(uuid)
    }

    /// Creates a [`UuidUrn`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(feature = "const_fn")]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Urn(uuid)
    }
}

impl<'a> UrnRef<'a> {
    /// The length of a URN [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 45;

    /// Creates a [`UuidUrnRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UrnRef(uuid)
    }

    /// Creates a [`UuidUrnRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(feature = "const_fn")]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UrnRef(&uuid)
    }
}
<commit_msg>fix `const_fn` marked functions not being const for adapters<commit_after>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Adapters for various formats for [`Uuid`]s
//!
//! [`Uuid`]: ../struct.Uuid.html

use prelude::*;

mod core_support;

/// An adaptor for formatting an [`Uuid`] as a hyphenated string.
///
/// Takes an owned instance of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Hyphenated(Uuid);

/// An adaptor for formatting an [`Uuid`] as a hyphenated string.
///
/// Takes a reference of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct HyphenatedRef<'a>(&'a Uuid);

/// An adaptor for formatting an [`Uuid`] as a simple string.
///
/// Takes an owned instance of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Simple(Uuid);

/// An adaptor for formatting an [`Uuid`] as a simple string.
///
/// Takes a reference of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct SimpleRef<'a>(&'a Uuid);

/// An adaptor for formatting an [`Uuid`] as a URN string.
///
/// Takes an owned instance of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Urn(Uuid);

/// An adaptor for formatting an [`Uuid`] as a URN string.
///
/// Takes a reference of the [`Uuid`].
///
/// [`Uuid`]: ../struct.Uuid.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UrnRef<'a>(&'a Uuid);

impl Uuid {
    /// Creates a [`UuidHyphenated`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_hyphenated(self) -> Hyphenated {
        Hyphenated::from_uuid(self)
    }

    /// Creates a [`UuidHyphenated`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub const fn to_hyphenated(self) -> Hyphenated {
        Hyphenated::from_uuid(self)
    }

    /// Creates a [`UuidHyphenatedRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_hyphenated_ref(&self) -> HyphenatedRef {
        HyphenatedRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidHyphenatedRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub const fn to_hyphenated_ref(&self) -> HyphenatedRef {
        HyphenatedRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidSimple`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_simple(self) -> Simple {
        Simple::from_uuid(self)
    }

    /// Creates a [`UuidSimple`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub const fn to_simple(self) -> Simple {
        Simple::from_uuid(self)
    }

    /// Creates a [`UuidSimpleRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_simple_ref(&self) -> SimpleRef {
        SimpleRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidSimpleRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub const fn to_simple_ref(&self) -> SimpleRef {
        SimpleRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidUrn`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_urn(self) -> Urn {
        Urn::from_uuid(self)
    }

    /// Creates a [`UuidUrn`] instance from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub constfn to_urn(self) -> Urn {
        Urn::from_uuid(self)
    }

    /// Creates a [`UuidUrnRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_urn_ref(&self) -> UrnRef {
        UrnRef::from_uuid_ref(self)
    }

    /// Creates a [`UuidUrnRef`] instance from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(feature = "const_fn")]
    #[inline]
    pub const fn to_urn_ref(&self) -> UrnRef {
        UrnRef::from_uuid_ref(self)
    }
}

impl Hyphenated {
    /// The length of a hyphenated [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 36;

    /// Creates a [`UuidHyphenated`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Hyphenated(uuid)
    }

    /// Creates a [`UuidHyphenated`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenated`]: struct.UuidHyphenated.html
    #[cfg(feature = "const_fn")]
    pub const fn from_uuid(uuid: Uuid) -> Self {
        Hyphenated(uuid)
    }
}

impl<'a> HyphenatedRef<'a> {
    /// The length of a hyphenated [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 36;

    /// Creates a [`UuidHyphenatedRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        HyphenatedRef(uuid)
    }

    /// Creates a [`UuidHyphenatedRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidHyphenatedRef`]: struct.UuidHyphenatedRef.html
    #[cfg(feature = "const_fn")]
    pub const fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        HyphenatedRef(uuid)
    }
}

impl Simple {
    /// The length of a simple [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 32;

    /// Creates a [`UuidSimple`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Simple(uuid)
    }

    /// Creates a [`UuidSimple`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimple`]: struct.UuidSimple.html
    #[cfg(feature = "const_fn")]
    pub const fn from_uuid(uuid: Uuid) -> Self {
        Simple(uuid)
    }
}

impl<'a> SimpleRef<'a> {
    /// The length of a simple [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 32;

    /// Creates a [`UuidSimpleRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        SimpleRef(uuid)
    }

    /// Creates a [`UuidSimpleRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidSimpleRef`]: struct.UuidSimpleRef.html
    #[cfg(feature = "const_fn")]
    pub const fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        SimpleRef(uuid)
    }
}

impl Urn {
    /// The length of a URN [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 45;

    /// Creates a [`UuidUrn`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        Urn(uuid)
    }

    /// Creates a [`UuidUrn`] from a [`Uuid`].
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrn`]: struct.UuidUrn.html
    #[cfg(feature = "const_fn")]
    pub const fn from_uuid(uuid: Uuid) -> Self {
        Urn(uuid)
    }
}

impl<'a> UrnRef<'a> {
    /// The length of a URN [`Uuid`] string.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub const LENGTH: usize = 45;

    /// Creates a [`UuidUrnRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UrnRef(uuid)
    }

    /// Creates a [`UuidUrnRef`] from a [`Uuid`] reference.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidUrnRef`]: struct.UuidUrnRef.html
    #[cfg(feature = "const_fn")]
    pub const fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UrnRef(&uuid)
    }
}
<|endoftext|>


<commit_before>//! Awesome compatibility modules

use wlroots;

use rlua::{self, LightUserData, Lua, Table};
use std::{env, mem, path::PathBuf};
use xcb::{xkb, Connection};
use awesome::lua::setup_lua;

mod awesome;
mod button;
mod class;
mod client;
mod drawable;
mod drawin;
mod key;
pub mod keygrabber;
pub mod lua;
mod mouse;
pub mod mousegrabber;
mod object;
mod property;
mod root;
mod screen;
pub mod signal;
mod tag;
mod xproperty;

pub use self::lua::{NEXT_LUA, LUA};

pub use self::drawin::{Drawin, DRAWINS_HANDLE};
pub use self::key::Key;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;
pub use self::object::{Object, Objectable};
pub use self::root::ROOT_KEYS_HANDLE;
pub use self::signal::*;

use compositor::Server;

pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

/// Called from `wayland_glib_interface.c` after every call back into the wayland event loop.
///
/// This restarts the Lua thread if there is a new one pending
#[no_mangle]
pub extern "C" fn refresh_awesome() {
    NEXT_LUA.with(|new_lua_check| {
        if new_lua_check.get() {
            new_lua_check.set(false);
            LUA.with(|lua| {
                let mut lua = lua.borrow_mut();
                unsafe {
                    *lua = rlua::Lua::new_with_debug();
                }
            });
            let compositor = wlroots::compositor_handle().unwrap();
            setup_lua(compositor);
        }
    });
}

pub fn init(lua: &Lua, server: &mut Server) -> rlua::Result<()> {
    setup_awesome_path(lua)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua, server)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    Ok(())
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;

    for mut xdg_data_path in env::var("XDG_DATA_DIRS").unwrap_or("/usr/share".into())
                                                      .split(':')
                                                      .map(PathBuf::from)
    {
        xdg_data_path.push("awesome/lib");
        path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                               xdg_data_path.as_os_str().to_string_lossy()));
        cpath.push_str(&format!(";{}/?.so", xdg_data_path.into_os_string().to_string_lossy()));
    }

    for mut xdg_config_path in env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into())
                                                          .split(':')
                                                          .map(PathBuf::from)
    {
        xdg_config_path.push("awesome");
        cpath.push_str(&format!(";{}/?.so",
                                xdg_config_path.into_os_string().to_string_lossy()));
    }

    package.set("path", path)?;
    package.set("cpath", cpath)?;

    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    lua.set_named_registry_value(GLOBAL_SIGNALS, lua.create_table()?)
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = match Connection::connect(None) {
        Err(err) => {
            error!("Way Cooler requires XWayland in order to function");
            error!("However, xcb could not connect to it. Is it running?");
            error!("{:?}", err);
            panic!("Could not connect to XWayland instance");
        }
        Ok(con) => con.0
    };
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        }
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.set_named_registry_value(XCB_CONNECTION_HANDLE,
                                  LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> {
    Ok(())
}
<commit_msg>Include /usr/local/share in default XDG_DATA_DIRS<commit_after>//! Awesome compatibility modules

use wlroots;

use rlua::{self, LightUserData, Lua, Table};
use std::{env, mem, path::PathBuf};
use xcb::{xkb, Connection};
use awesome::lua::setup_lua;

mod awesome;
mod button;
mod class;
mod client;
mod drawable;
mod drawin;
mod key;
pub mod keygrabber;
pub mod lua;
mod mouse;
pub mod mousegrabber;
mod object;
mod property;
mod root;
mod screen;
pub mod signal;
mod tag;
mod xproperty;

pub use self::lua::{NEXT_LUA, LUA};

pub use self::drawin::{Drawin, DRAWINS_HANDLE};
pub use self::key::Key;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;
pub use self::object::{Object, Objectable};
pub use self::root::ROOT_KEYS_HANDLE;
pub use self::signal::*;

use compositor::Server;

pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

/// Called from `wayland_glib_interface.c` after every call back into the wayland event loop.
///
/// This restarts the Lua thread if there is a new one pending
#[no_mangle]
pub extern "C" fn refresh_awesome() {
    NEXT_LUA.with(|new_lua_check| {
        if new_lua_check.get() {
            new_lua_check.set(false);
            LUA.with(|lua| {
                let mut lua = lua.borrow_mut();
                unsafe {
                    *lua = rlua::Lua::new_with_debug();
                }
            });
            let compositor = wlroots::compositor_handle().unwrap();
            setup_lua(compositor);
        }
    });
}

pub fn init(lua: &Lua, server: &mut Server) -> rlua::Result<()> {
    setup_awesome_path(lua)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua, server)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    Ok(())
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;

    for mut xdg_data_path in env::var("XDG_DATA_DIRS").unwrap_or("/usr/local/share:/usr/share".into())
                                                      .split(':')
                                                      .map(PathBuf::from)
    {
        xdg_data_path.push("awesome/lib");
        path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                               xdg_data_path.as_os_str().to_string_lossy()));
        cpath.push_str(&format!(";{}/?.so", xdg_data_path.into_os_string().to_string_lossy()));
    }

    for mut xdg_config_path in env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into())
                                                          .split(':')
                                                          .map(PathBuf::from)
    {
        xdg_config_path.push("awesome");
        cpath.push_str(&format!(";{}/?.so",
                                xdg_config_path.into_os_string().to_string_lossy()));
    }

    package.set("path", path)?;
    package.set("cpath", cpath)?;

    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    lua.set_named_registry_value(GLOBAL_SIGNALS, lua.create_table()?)
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = match Connection::connect(None) {
        Err(err) => {
            error!("Way Cooler requires XWayland in order to function");
            error!("However, xcb could not connect to it. Is it running?");
            error!("{:?}", err);
            panic!("Could not connect to XWayland instance");
        }
        Ok(con) => con.0
    };
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        }
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.set_named_registry_value(XCB_CONNECTION_HANDLE,
                                  LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> {
    Ok(())
}
<|endoftext|>


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

#![crate_name = "bindgen"]
#![crate_type = "bin"]

extern crate bindgen;
#[macro_use] extern crate log;
extern crate syntax;

use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
use std::path;
use std::env;
use std::default::Default;
use std::fs;

struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        error!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        warn!("{}", msg);
    }
}

enum ParseResult {
    CmdUsage,
    ParseOk(BindgenOptions, Box<io::Write+'static>),
    ParseErr(String)
}

fn parse_args(args: &[String]) -> ParseResult {
    let args_len = args.len();

    let mut options: BindgenOptions = Default::default();
    let mut out = Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>;

    if args_len == 0 {
        return ParseResult::CmdUsage;
    }

    let mut ix: usize = 0;
    while ix < args_len {
        if args[ix].len() > 2 && &args[ix][..2] == "-l" {
            options.links.push((args[ix][2..].to_string(), LinkType::Default));
            ix += 1;
        } else {
            match &args[ix][..] {
                "--help" | "-h" => {
                    return ParseResult::CmdUsage;
                }
                "-emit-clang-ast" => {
                    options.emit_ast = true;
                    ix += 1;
                }
                "-o" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing output filename".to_string());
                    }
                    let path = path::Path::new(&args[ix + 1]);
                    match fs::File::create(&path) {
                        Ok(f) => { out = Box::new(io::BufWriter::new(f)) as Box<io::Write>; }
                        Err(_) => { return ParseResult::ParseErr(format!("Open {} failed", args[ix + 1])); }
                    }
                    ix += 2;
                }
                "-l" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing link name".to_string());
                    }
                    options.links.push((args[ix + 1].clone(), LinkType::Default));
                    ix += 2;
                }
                "-static-link" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing link name".to_string());
                    }
                    options.links.push((args[ix + 1].clone(), LinkType::Static));
                    ix += 2;
                }
                "-framework-link" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing link name".to_string());
                    }
                    options.links.push((args[ix + 1].clone(), LinkType::Framework));
                    ix += 2;
                }
                "-match" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing match pattern".to_string());
                    }
                    options.match_pat.push(args[ix + 1].clone());
                    ix += 2;
                }
                "-builtins" => {
                    options.builtins = true;
                    ix += 1;
                }
                "-allow-unknown-types" => {
                    options.fail_on_unknown_type = false;
                    ix += 1;
                }
                "-override-enum-type" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing enum type".to_string());
                    }
                    options.override_enum_ty = args[ix + 1].clone();
                    ix += 2;
                }
                _ => {
                    options.clang_args.push(args[ix].clone());
                    ix += 1;
                }
            }
        }
    }

    return ParseResult::ParseOk(options, out);
}

fn print_usage(bin: String) {
    let mut s = format!("Usage: {} [options] input.h", &bin[..]);
    s.push_str(
"
Options:
    -h or --help               Display help message
    -l <name> or -l<name>      Link to a dynamic library, can be proivded
                               multiple times
    -static-link <name>        Link to a static library
    -framework-link <name>     Link to a framework
    -o <output.rs>             Write bindings to <output.rs> (default stdout)
    -match <name>              Only output bindings for definitions from files
                               whose name contains <name>
                               If multiple -match options are provided, files
                               matching any rule are bound to.
    -builtins                  Output bindings for builtin definitions
                               (for example __builtin_va_list)
    -allow-unknown-types       Don't fail if we encounter types we do not support,
                               instead treat them as void
    -emit-clang-ast            Output the ast (for debugging purposes)
    -override-enum-type <type> Override enum type, type name could be
                                 uchar
                                 schar
                                 ushort
                                 sshort
                                 uint
                                 sint
                                 ulong
                                 slong
                                 ulonglong
                                 slonglong

    Options other than stated above are passed to clang.
"
    );
    print!("{}", &s[..]);
}

pub fn main() {
    let mut bind_args: Vec<_> = env::args().collect();
    let bin = bind_args.remove(0);

    match parse_args(&bind_args[..]) {
        ParseResult::ParseErr(e) => panic!(e),
        ParseResult::CmdUsage => print_usage(bin),
        ParseResult::ParseOk(options, mut out) => {
            let logger = StdLogger;
            match Bindings::generate(&options, Some(&logger as &Logger), None) {
                Ok(bindings) => match bindings.write(&mut out) {
                    Ok(()) => (),
                    Err(e) => {
                        logger.error(&format!("Unable to write bindings to file. {}", e)[..]);
                        env::set_exit_status(-1);
                    }
                },
                Err(()) => env::set_exit_status(-1)
            }
        }
    }
}
<commit_msg>Try to include clang's bundled include files if possible.<commit_after>#![feature(rustc_private, exit_status)]

#![crate_name = "bindgen"]
#![crate_type = "bin"]

extern crate bindgen;
#[macro_use] extern crate log;
extern crate syntax;

use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
use std::path;
use std::env;
use std::default::Default;
use std::fs;
use std::borrow::ToOwned;

struct StdLogger;

impl Logger for StdLogger {
    fn error(&self, msg: &str) {
        error!("{}", msg);
    }

    fn warn(&self, msg: &str) {
        warn!("{}", msg);
    }
}

enum ParseResult {
    CmdUsage,
    ParseOk(BindgenOptions, Box<io::Write+'static>),
    ParseErr(String)
}

fn parse_args(args: &[String]) -> ParseResult {
    let args_len = args.len();

    let mut options: BindgenOptions = Default::default();
    let mut out = Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>;

    if args_len == 0 {
        return ParseResult::CmdUsage;
    }

    let mut ix: usize = 0;
    while ix < args_len {
        if args[ix].len() > 2 && &args[ix][..2] == "-l" {
            options.links.push((args[ix][2..].to_string(), LinkType::Default));
            ix += 1;
        } else {
            match &args[ix][..] {
                "--help" | "-h" => {
                    return ParseResult::CmdUsage;
                }
                "-emit-clang-ast" => {
                    options.emit_ast = true;
                    ix += 1;
                }
                "-o" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing output filename".to_string());
                    }
                    let path = path::Path::new(&args[ix + 1]);
                    match fs::File::create(&path) {
                        Ok(f) => { out = Box::new(io::BufWriter::new(f)) as Box<io::Write>; }
                        Err(_) => { return ParseResult::ParseErr(format!("Open {} failed", args[ix + 1])); }
                    }
                    ix += 2;
                }
                "-l" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing link name".to_string());
                    }
                    options.links.push((args[ix + 1].clone(), LinkType::Default));
                    ix += 2;
                }
                "-static-link" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing link name".to_string());
                    }
                    options.links.push((args[ix + 1].clone(), LinkType::Static));
                    ix += 2;
                }
                "-framework-link" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing link name".to_string());
                    }
                    options.links.push((args[ix + 1].clone(), LinkType::Framework));
                    ix += 2;
                }
                "-match" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing match pattern".to_string());
                    }
                    options.match_pat.push(args[ix + 1].clone());
                    ix += 2;
                }
                "-builtins" => {
                    options.builtins = true;
                    ix += 1;
                }
                "-allow-unknown-types" => {
                    options.fail_on_unknown_type = false;
                    ix += 1;
                }
                "-override-enum-type" => {
                    if ix + 1 >= args_len {
                        return ParseResult::ParseErr("Missing enum type".to_string());
                    }
                    options.override_enum_ty = args[ix + 1].clone();
                    ix += 2;
                }
                _ => {
                    options.clang_args.push(args[ix].clone());
                    ix += 1;
                }
            }
        }
    }

    return ParseResult::ParseOk(options, out);
}

fn print_usage(bin: String) {
    let mut s = format!("Usage: {} [options] input.h", &bin[..]);
    s.push_str(
"
Options:
    -h or --help               Display help message
    -l <name> or -l<name>      Link to a dynamic library, can be proivded
                               multiple times
    -static-link <name>        Link to a static library
    -framework-link <name>     Link to a framework
    -o <output.rs>             Write bindings to <output.rs> (default stdout)
    -match <name>              Only output bindings for definitions from files
                               whose name contains <name>
                               If multiple -match options are provided, files
                               matching any rule are bound to.
    -builtins                  Output bindings for builtin definitions
                               (for example __builtin_va_list)
    -allow-unknown-types       Don't fail if we encounter types we do not support,
                               instead treat them as void
    -emit-clang-ast            Output the ast (for debugging purposes)
    -override-enum-type <type> Override enum type, type name could be
                                 uchar
                                 schar
                                 ushort
                                 sshort
                                 uint
                                 sint
                                 ulong
                                 slong
                                 ulonglong
                                 slonglong

    Options other than stated above are passed to clang.
"
    );
    print!("{}", &s[..]);
}

// Get the first directory in PATH that contains a file named "clang".
fn get_clang_dir() -> Option<path::PathBuf>{
    match env::var_os("PATH") {
        Some(paths) => {
            for p in env::split_paths(&paths) {
                let mut bin_path = p.clone();
                bin_path.push("clang");
                match fs::metadata(bin_path) {
                    Ok(m) => {
                        if m.is_file() {
                            return Some(p);
                        }
                    }
                    _ => (),
                }
            }
            None
        }
        None => None,
    }
}

// Try to find the directory that contains clang's bundled headers. Clang itself does something
// very similar: it takes the parent directory of the current executable, appends
// "../lib/clang/<VERSIONSTRING>/include". We have two problems emulating this behaviour:
// * We don't have a very good way of finding the clang executable, but can fake this by
//   searching $PATH and take one directory that contains "clang".
// * We don't have access to <VERSIONSTRING>. There is clang_getClangVersion(), but it returns
//   a human-readable description string which is not guaranteed to be stable and a pain to parse.
//   We work around that by just taking the first directory in ../lib/clang and hope it's the
//   current version.
// TODO: test if this works on Windows at all.
fn get_include_dir() -> Option<String> {
    match get_clang_dir() {
        Some(mut p) => {
            p.push("..");
            p.push("lib");
            p.push("clang");

            let dir_iter = match fs::read_dir(p) {
                Ok(dir_iter) => dir_iter,
                _ => return None
            };
            for dir in dir_iter {
                match dir {
                    Ok(dir) => {
                        // Let's take the first dir. In my case, there's only one directory
                        // there anyway.
                        let mut p = dir.path();
                        p.push("include");
                        match p.into_os_string().into_string() {
                            Ok(s) => return Some(s),
                            // We found the directory, but can't access it as it contains
                            // invalid unicode.
                            _ => return None,
                        }
                    }
                    _ => return None,
                }
            }
            None
        }
        None => None,
    }
}

pub fn main() {
    let mut bind_args: Vec<_> = env::args().collect();
    let bin = bind_args.remove(0);

    match get_include_dir() {
        Some(path) => {
            bind_args.push("-I".to_owned());
            bind_args.push(path);
        }
        None => (),
    }

    match parse_args(&bind_args[..]) {
        ParseResult::ParseErr(e) => panic!(e),
        ParseResult::CmdUsage => print_usage(bin),
        ParseResult::ParseOk(options, mut out) => {
            let logger = StdLogger;
            match Bindings::generate(&options, Some(&logger as &Logger), None) {
                Ok(bindings) => match bindings.write(&mut out) {
                    Ok(()) => (),
                    Err(e) => {
                        logger.error(&format!("Unable to write bindings to file. {}", e)[..]);
                        env::set_exit_status(-1);
                    }
                },
                Err(()) => env::set_exit_status(-1)
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(io)]

extern crate rustc_serialize;
extern crate docopt;
extern crate users;
extern crate glob;
extern crate tempfile;

use tempfile::NamedTempFile;
use docopt::Docopt;
use std::env;
use std::fs;
use std::io::{stdin, stdout, stderr, Write, Read};
use std::fs::File;
use std::os::unix::fs::PermissionsExt;
use std::path::{PathBuf, Path};
use std::process::{Command, exit};
use std::ops::Deref;

static CRONTAB_DIR: &'static str = "/var/spool/cron";
static REBOOT_FILE: &'static str = "/run/crond.reboot";

static USAGE: &'static str = r#"
Usage: crontab [-u USER] -l
       crontab [-u USER] -e [FILE]
       crontab [-u USER] -s
       crontab [-u USER] -r [-i]
       crontab -h | --help

Maintain crontab files for individual users

Options:

  -h, --help            Show this help message and exit.
  -u USER, --user USER  It specifies the name of the user whose crontab is to
                        be tweaked. If this option is not given, crontab
                        examines "your" crontab, i.e., the crontab of the
                        person executing the command. Note that su(8) can
                        confuse crontab and that if you are running inside of
                        su(8) you should always use the -u option for safety's
                        sake. The first form of this command is used to
                        install a new crontab from some named file or standard
                        input if the pseudo-filename "-" is given.
  -l, --list            The current crontab will be displayed on standard
                        output.
  -r, --remove          The current crontab will be removed.
  -e, --edit            This option is used to edit the current crontab using
                        the editor specified by the VISUAL or EDITOR
                        environment variables. After you exit from the editor,
                        the modified crontab will be installed automatically.
  -s, --show            Show all users who have a crontab.
  -i, --ask             This option modifies the -r option to prompt the user
                        for a 'y/Y' response before actually removing the
                        crontab.
"#;

#[derive(Debug, RustcDecodable)]
#[allow(non_snake_case)]
struct Args {
    arg_FILE: Option<String>,
    flag_user: Option<String>,
    flag_list: bool,
    flag_remove: bool,
    flag_edit: bool,
    flag_show: bool,
    flag_ask: bool
}

fn get_editor() -> Option<String> {
    env::var("EDITOR").ok()
        .or_else(|| env::var("VISUAL").ok())
        .or_else(|| ["/usr/bin/editor", "/usr/bin/vim", "/usr/bin/nano", "/usr/bin/mcedit"].iter()
                 .filter(|editor| fs::metadata(editor).map(|meta| meta.is_file() && meta.permissions().mode() & 0o0111 != 0).unwrap_or(false))
                 .next()
                 .map(|&s| s.to_owned()))
}

fn confirm(msg: &str) -> bool {
    let mut stdin = stdin();
    let mut stdout = stdout();
    loop {
        stdout.write_all(msg.as_bytes()).unwrap();
        stdout.flush().unwrap();
        let mut buf = [0u8; 1024];
        match stdin.read(&mut buf) {
            Ok(n) if n > 0 && (buf[0] == 121 || buf[0] == 89) => return true,
            Ok(n) if n > 0 && (buf[0] == 110 || buf[0] == 78) => return false,
            _ => { stdout.write_all("Please reply \"y\" or \"n\"\n".as_bytes()).unwrap(); },
        }
    }
}

fn list(cron_file: &Path, args: &Args) -> i32 {
    if let Err(e) = File::open(cron_file).map(|file| file.tee(stdout()).bytes().count()) {
        use std::io::ErrorKind::*;
        match e.kind() {
            NotFound => println!("no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            PermissionDenied => println!("you can not display {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            _ => println!("failed to read {}", cron_file.display()),
        }
        return 1;
    }
    0
}

fn remove(cron_file: &Path, args: &Args) -> i32 {
    let mut stderr = stderr();

    if !args.flag_ask || confirm(&*format!("Are you sure you want to delete {} (y/n)? ", cron_file.display())) {
        if let Err(e) = fs::remove_file(cron_file) {
            use std::io::ErrorKind::*;
            match e.kind() {
                NotFound => writeln!(stderr, "no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
                PermissionDenied => match args.flag_user {
                    ref user @ Some(_) if user != &users::get_current_username() => writeln!(stderr, "you can not remove {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
                    _ => match File::create(cron_file) {
                        Ok(_) => writeln!(stderr, "couldn't remove {}, wiped it instead", cron_file.display()),
                        Err(_) => writeln!(stderr, "failed to remove {}", cron_file.display()),
                    }
                },
                _ => writeln!(stderr, "failed to remove {}", cron_file.display())
            }.unwrap();
            return 1;
        }
    }
    0
}

fn show(cron_file: &Path, args: &Args) -> i32 {
    let mut stderr = stderr();

    if users::get_current_uid() != 0 {
        writeln!(stderr, "must be privileged to use -s");
        return 2;
    }

    if let Ok(dir) = fs::read_dir(CRONTAB_DIR) {
        for entry in dir {
            let name = entry.ok().and_then(|e| e.path().file_name().map(|s| s.to_string_lossy().into_owned()));
            if let Some(user) = name {
                if users::get_user_by_name(&*user).is_some() {
                    println!("{}", user);
                } else {
                    writeln!(stderr, "WARNING: crontab found with no matching user: {}", user);
                }
            }
        }
    }
    0
}

fn edit(cron_file: &Path, args: &Args) -> i32 {
    use std::io::ErrorKind::*;

    let mut stderr = stderr();

    let editor = match get_editor() {
        None => {
            writeln!(stderr, "no editor found");
            return 1;
        },
        Some(editor) => editor
    };

    let mut tmpfile = NamedTempFile::new_in(CRONTAB_DIR).unwrap();

    if let Err(e) = File::open(cron_file).map(|file| file.tee(&mut tmpfile).bytes().count()) {
        match e.kind() {
            NotFound => tmpfile.write_all("# min hour dom month dow command".as_bytes()).unwrap(),
            _ => {
                writeln!(stderr, "you can not edit {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???"));
                return 1;
            }
        }
    }

    tmpfile.flush().unwrap();
    match Command::new(editor).arg(tmpfile.path()).status() {
        Ok(status) if status.success() => (),
        _ => {
            writeln!(stderr, "edit aborted, your edit is kept here: {}", tmpfile.path().display());
            return 1;
        }
    }

    // TODO: check tmpfile with parser

    if let Err(err) = tmpfile.persist(cron_file) {
        match err.error.kind() {
            PermissionDenied => writeln!(stderr, "you can not edit {}'s crontab, your edit is kept here: {}",
                                         args.flag_user.as_ref().map(String::deref).unwrap_or("???"),
                                         err.file.path().display()),
            _ => writeln!(stderr, "unexpected error: {}, your edit is kept here: {}", err.error, err.file.path().display())
        }.unwrap();
        return 1;
    }

    0
}

fn main() {
    let mut args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let editor = get_editor();

    match fs::metadata(CRONTAB_DIR) {
        Ok(ref meta) if meta.is_dir() => (),
        Ok(_) => return println!("{} is not a directory!", CRONTAB_DIR),
        Err(_) => if let Err(_) = fs::create_dir_all(CRONTAB_DIR) {
            return println!("{} doesn't exist!", CRONTAB_DIR);
        }
    }

    if args.flag_user.is_none() {
        args.flag_user = users::get_current_username();
    }
    let cron_file = PathBuf::from(CRONTAB_DIR).join(args.flag_user.clone().unwrap());

    exit(
        if args.flag_show {
            show(&*cron_file, &args)
        } else if args.flag_list {
            list(&*cron_file, &args)
        } else if args.flag_edit {
            edit(&*cron_file, &args)
        } else if args.flag_remove {
            remove(&*cron_file, &args)
        } else {
            0
        })
}
<commit_msg>crontab: replace mode stab<commit_after>#![feature(io)]

extern crate rustc_serialize;
extern crate docopt;
extern crate users;
extern crate glob;
extern crate tempfile;

use tempfile::NamedTempFile;
use docopt::Docopt;
use std::env;
use std::fs;
use std::io::{stdin, stdout, stderr, Write, Read};
use std::fs::File;
use std::os::unix::fs::PermissionsExt;
use std::path::{PathBuf, Path};
use std::process::{Command, exit};
use std::ops::Deref;

static CRONTAB_DIR: &'static str = "/var/spool/cron";
static REBOOT_FILE: &'static str = "/run/crond.reboot";

static USAGE: &'static str = r#"
Usage: crontab [-u USER] -l
       crontab [-u USER] -e [FILE]
       crontab [-u USER] -s
       crontab [-u USER] -r [-i]
       crontab -h | --help

Maintain crontab files for individual users

Options:

  -h, --help            Show this help message and exit.
  -u USER, --user USER  It specifies the name of the user whose crontab is to
                        be tweaked. If this option is not given, crontab
                        examines "your" crontab, i.e., the crontab of the
                        person executing the command. Note that su(8) can
                        confuse crontab and that if you are running inside of
                        su(8) you should always use the -u option for safety's
                        sake. The first form of this command is used to
                        install a new crontab from some named file or standard
                        input if the pseudo-filename "-" is given.
  -l, --list            The current crontab will be displayed on standard
                        output.
  -r, --remove          The current crontab will be removed.
  -e, --edit            This option is used to edit the current crontab using
                        the editor specified by the VISUAL or EDITOR
                        environment variables. After you exit from the editor,
                        the modified crontab will be installed automatically.
  -s, --show            Show all users who have a crontab.
  -i, --ask             This option modifies the -r option to prompt the user
                        for a 'y/Y' response before actually removing the
                        crontab.
"#;

#[derive(Debug, RustcDecodable)]
#[allow(non_snake_case)]
struct Args {
    arg_FILE: Option<String>,
    flag_user: Option<String>,
    flag_list: bool,
    flag_remove: bool,
    flag_edit: bool,
    flag_show: bool,
    flag_ask: bool
}

fn get_editor() -> Option<String> {
    env::var("EDITOR").ok()
        .or_else(|| env::var("VISUAL").ok())
        .or_else(|| ["/usr/bin/editor", "/usr/bin/vim", "/usr/bin/nano", "/usr/bin/mcedit"].iter()
                 .filter(|editor| fs::metadata(editor).map(|meta| meta.is_file() && meta.permissions().mode() & 0o0111 != 0).unwrap_or(false))
                 .next()
                 .map(|&s| s.to_owned()))
}

fn confirm(msg: &str) -> bool {
    let mut stdin = stdin();
    let mut stdout = stdout();
    loop {
        stdout.write_all(msg.as_bytes()).unwrap();
        stdout.flush().unwrap();
        let mut buf = [0u8; 1024];
        match stdin.read(&mut buf) {
            Ok(n) if n > 0 && (buf[0] == 121 || buf[0] == 89) => return true,
            Ok(n) if n > 0 && (buf[0] == 110 || buf[0] == 78) => return false,
            _ => { stdout.write_all("Please reply \"y\" or \"n\"\n".as_bytes()).unwrap(); },
        }
    }
}

fn list(cron_file: &Path, args: &Args) -> i32 {
    if let Err(e) = File::open(cron_file).map(|file| file.tee(stdout()).bytes().count()) {
        use std::io::ErrorKind::*;
        match e.kind() {
            NotFound => println!("no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            PermissionDenied => println!("you can not display {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
            _ => println!("failed to read {}", cron_file.display()),
        }
        return 1;
    }
    0
}

fn remove(cron_file: &Path, args: &Args) -> i32 {
    let mut stderr = stderr();

    if !args.flag_ask || confirm(&*format!("Are you sure you want to delete {} (y/n)? ", cron_file.display())) {
        if let Err(e) = fs::remove_file(cron_file) {
            use std::io::ErrorKind::*;
            match e.kind() {
                NotFound => writeln!(stderr, "no crontab for {}", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
                PermissionDenied => match args.flag_user {
                    ref user @ Some(_) if user != &users::get_current_username() => writeln!(stderr, "you can not remove {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???")),
                    _ => match File::create(cron_file) {
                        Ok(_) => writeln!(stderr, "couldn't remove {}, wiped it instead", cron_file.display()),
                        Err(_) => writeln!(stderr, "failed to remove {}", cron_file.display()),
                    }
                },
                _ => writeln!(stderr, "failed to remove {}", cron_file.display())
            }.unwrap();
            return 1;
        }
    }
    0
}

fn show(cron_file: &Path, args: &Args) -> i32 {
    let mut stderr = stderr();

    if users::get_current_uid() != 0 {
        writeln!(stderr, "must be privileged to use -s");
        return 2;
    }

    if let Ok(dir) = fs::read_dir(CRONTAB_DIR) {
        for entry in dir {
            let name = entry.ok().and_then(|e| e.path().file_name().map(|s| s.to_string_lossy().into_owned()));
            if let Some(user) = name {
                if users::get_user_by_name(&*user).is_some() {
                    println!("{}", user);
                } else {
                    writeln!(stderr, "WARNING: crontab found with no matching user: {}", user);
                }
            }
        }
    }
    0
}

fn edit(cron_file: &Path, args: &Args) -> i32 {
    use std::io::ErrorKind::*;

    let mut stderr = stderr();

    let editor = match get_editor() {
        None => {
            writeln!(stderr, "no editor found");
            return 1;
        },
        Some(editor) => editor
    };

    let mut tmpfile = NamedTempFile::new_in(CRONTAB_DIR).unwrap();

    if let Err(e) = File::open(cron_file).map(|file| file.tee(&mut tmpfile).bytes().count()) {
        match e.kind() {
            NotFound => tmpfile.write_all("# min hour dom month dow command".as_bytes()).unwrap(),
            _ => {
                writeln!(stderr, "you can not edit {}'s crontab", args.flag_user.as_ref().map(String::deref).unwrap_or("???"));
                return 1;
            }
        }
    }

    tmpfile.flush().unwrap();
    match Command::new(editor).arg(tmpfile.path()).status() {
        Ok(status) if status.success() => (),
        _ => {
            writeln!(stderr, "edit aborted, your edit is kept here: {}", tmpfile.path().display());
            return 1;
        }
    }

    // TODO: check tmpfile with parser

    if let Err(err) = tmpfile.persist(cron_file) {
        match err.error.kind() {
            PermissionDenied => writeln!(stderr, "you can not edit {}'s crontab, your edit is kept here: {}",
                                         args.flag_user.as_ref().map(String::deref).unwrap_or("???"),
                                         err.file.path().display()),
            _ => writeln!(stderr, "unexpected error: {}, your edit is kept here: {}", err.error, err.file.path().display())
        }.unwrap();
        return 1;
    }

    0
}

fn replace(cron_file: &Path, args: &Args) -> i32 {
    // TODO
    0
}

fn main() {
    let mut args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let editor = get_editor();

    match fs::metadata(CRONTAB_DIR) {
        Ok(ref meta) if meta.is_dir() => (),
        Ok(_) => return println!("{} is not a directory!", CRONTAB_DIR),
        Err(_) => if let Err(_) = fs::create_dir_all(CRONTAB_DIR) {
            return println!("{} doesn't exist!", CRONTAB_DIR);
        }
    }

    if args.flag_user.is_none() {
        args.flag_user = users::get_current_username();
    }
    let cron_file = PathBuf::from(CRONTAB_DIR).join(args.flag_user.clone().unwrap());

    exit(
        if args.flag_show {
            show(&*cron_file, &args)
        } else if args.flag_list {
            list(&*cron_file, &args)
        } else if args.flag_edit {
            if args.arg_FILE.is_none() {
                edit(&*cron_file, &args)
            } else {
                replace(&*cron_file, &args)
            }
        } else if args.flag_remove {
            remove(&*cron_file, &args)
        } else {
            0
        })
}
<|endoftext|>