<commit_before>use std::f64;

extern crate cairo;
extern crate cairo_sys;

#[repr(C)]
pub struct RsvgPathBuilder {
    path_segments: Vec<cairo::PathSegment>,
}

impl RsvgPathBuilder {
    pub fn new () -> RsvgPathBuilder {
        let builder = RsvgPathBuilder {
            path_segments: Vec::new ()
        };

        builder
    }

    pub fn move_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::MoveTo ((x, y)));
    }

    pub fn line_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::LineTo ((x, y)));
    }

    pub fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_segments.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    pub fn close_path (&mut self) {
        self.path_segments.push (cairo::PathSegment::ClosePath);
    }

    pub fn get_path_segments (&self) -> &Vec<cairo::PathSegment> {
        &self.path_segments
    }

    /**
     * x1/y1: starting coordinates
     * rx/ry: radiuses before rotation
     * x_axis_rotation: Rotation angle for axes, in degrees
     * is_large_arc: false for arc length <= 180, true for arc >= 180
     * is_sweep: false for negative angle, true for positive angle
     * x2/y2: ending coordinates
     */
    pub fn arc (&mut self,
                x1: f64, y1: f64,
                mut rx: f64, mut ry: f64,
                x_axis_rotation: f64,
                is_large_arc: bool,
                is_sweep: bool,
                x2: f64, y2: f64) {
        /* See Appendix F.6 Elliptical arc implementation notes
        http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes */

        let f: f64;
        let sinf: f64;
        let cosf: f64;
        let x1_: f64;
        let y1_: f64;
        let cx_: f64;
        let cy_: f64;
        let cx: f64;
        let cy: f64;
        let gamma: f64;
        let mut theta1: f64;
        let mut delta_theta: f64;
        let mut k1: f64;
        let mut k2: f64;
        let k3: f64;
        let k4: f64;
        let mut k5: f64;
        let n_segs: i32;

        if x1 == x2 && y1 == y2 {
            return;
        }

        /* X-axis */
        f = x_axis_rotation * f64::consts::PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        rx = rx.abs ();
        ry = ry.abs ();

        /* Check the radius against floading point underflow.
        See http://bugs.debian.org/508443 */
        if (rx < f64::EPSILON) || (ry < f64::EPSILON) {
            self.line_to (x2, y2);
            return;
        }

        k1 = (x1 - x2) / 2.0;
        k2 = (y1 - y2) / 2.0;

        x1_ = cosf * k1 + sinf * k2;
        y1_ = -sinf * k1 + cosf * k2;

        gamma = (x1_ * x1_) / (rx * rx) + (y1_ * y1_) / (ry * ry);
        if gamma > 1.0 {
            rx *= gamma.sqrt ();
            ry *= gamma.sqrt ();
        }

        /* Compute the center */

        k1 = rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_;
        if k1 == 0.0 {
            return;
        }

        k1 = ((rx * rx * ry * ry) / k1 - 1.0).abs ().sqrt ();
        if is_sweep == is_large_arc {
            k1 = -k1;
        }

        cx_ = k1 * rx * y1_ / ry;
        cy_ = -k1 * ry * x1_ / rx;

        cx = cosf * cx_ - sinf * cy_ + (x1 + x2) / 2.0;
        cy = sinf * cx_ + cosf * cy_ + (y1 + y2) / 2.0;

        /* Compute start angle */

        k1 = (x1_ - cx_) / rx;
        k2 = (y1_ - cy_) / ry;
        k3 = (-x1_ - cx_) / rx;
        k4 = (-y1_ - cy_) / ry;

        k5 = (k1 * k1 + k2 * k2).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = k1 / k5;
        k5 = clamp (k5, -1.0, 1.0);
        theta1 = k5.acos ();
        if k2 < 0.0 {
            theta1 = -theta1;
        }

        /* Compute delta_theta */

        k5 = ((k1 * k1 + k2 * k2) * (k3 * k3 + k4 * k4)).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = (k1 * k3 + k2 * k4) / k5;
        k5 = clamp (k5, -1.0, 1.0);
        delta_theta = k5.acos ();
        if k1 * k4 - k3 * k2 < 0.0 {
            delta_theta = -delta_theta;
        }

        if is_sweep && delta_theta < 0.0 {
            delta_theta += f64::consts::PI * 2.0;
        } else if !is_sweep && delta_theta > 0.0 {
            delta_theta -= f64::consts::PI * 2.0;
        }

        /* Now draw the arc */

        n_segs = (delta_theta / (f64::consts::PI * 0.5 + 0.001)).abs ().ceil () as i32;
        let n_segs_dbl = n_segs as f64;

        for i in 0 .. n_segs {
            self.arc_segment (cx, cy,
                              theta1 + i as f64 * delta_theta / n_segs_dbl,
                              theta1 + (i + 1) as f64 * delta_theta / n_segs_dbl,
                              rx, ry,
                              x_axis_rotation);
        }
    }

    fn arc_segment (&mut self,
                    xc: f64, yc: f64,
                    th0: f64, th1: f64,
                    rx: f64, ry: f64,
                    x_axis_rotation: f64) {
        let x1: f64;
        let y1: f64;
        let x2: f64;
        let y2: f64;
        let x3: f64;
        let y3: f64;
        let t: f64;
        let th_half: f64;
        let f: f64;
        let sinf: f64;
        let cosf: f64;

        f = x_axis_rotation * f64::consts::PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        th_half = 0.5 * (th1 - th0);
        t = (8.0 / 3.0) * (th_half * 0.5).sin () * (th_half * 0.5).sin () / th_half.sin ();
        x1 = rx * (th0.cos () - t * th0.sin ());
        y1 = ry * (th0.sin () + t * th0.cos ());
        x3 = rx * th1.cos ();
        y3 = ry * th1.sin ();
        x2 = x3 + rx * (t * th1.sin ());
        y2 = y3 + ry * (-t * th1.cos ());

        self.curve_to (xc + cosf * x1 - sinf * y1,
                       yc + sinf * x1 + cosf * y1,
                       xc + cosf * x2 - sinf * y2,
                       yc + sinf * x2 + cosf * y2,
                       xc + cosf * x3 - sinf * y3,
                       yc + sinf * x3 + cosf * y3);
    }
}

fn clamp (val: f64, low: f64, high: f64) -> f64 {
    if val < low {
        low
    } else if val > high {
        high
    } else {
        val
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder::new ();

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_arc (raw_builder: *mut RsvgPathBuilder,
                                     x1: f64, y1: f64,
                                     rx: f64, ry: f64,
                                     x_axis_rotation: f64,
                                     large_arc_flag: bool,
                                     sweep_flag: bool,
                                     x2: f64, y2: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.arc (x1, y1,
                 rx, ry,
                 x_axis_rotation,
                 large_arc_flag,
                 sweep_flag,
                 x2, y2);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.close_path ();
}

#[no_mangle]
pub extern fn rsvg_path_builder_add_to_cairo_context (raw_builder: *mut RsvgPathBuilder, cr: *mut cairo_sys::cairo_t) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    unsafe {
        let path_segments = builder.get_path_segments ();

        for s in path_segments {
            match *s {
                cairo::PathSegment::MoveTo ((x, y)) => {
                    cairo_sys::cairo_move_to (cr, x, y);
                },

                cairo::PathSegment::LineTo ((x, y)) => {
                    cairo_sys::cairo_line_to (cr, x, y);
                },

                cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)) => {
                    cairo_sys::cairo_curve_to (cr, x2, y2, x3, y3, x4, y4);
                },

                cairo::PathSegment::ClosePath => {
                    cairo_sys::cairo_close_path (cr);
                }
            }
        }
    }
}
<commit_msg>path_builder.rs: No need to repr(C) for RsvgPathBuilder; it's opaque<commit_after>use std::f64;

extern crate cairo;
extern crate cairo_sys;

pub struct RsvgPathBuilder {
    path_segments: Vec<cairo::PathSegment>,
}

impl RsvgPathBuilder {
    pub fn new () -> RsvgPathBuilder {
        let builder = RsvgPathBuilder {
            path_segments: Vec::new ()
        };

        builder
    }

    pub fn move_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::MoveTo ((x, y)));
    }

    pub fn line_to (&mut self, x: f64, y: f64) {
        self.path_segments.push (cairo::PathSegment::LineTo ((x, y)));
    }

    pub fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_segments.push (cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    pub fn close_path (&mut self) {
        self.path_segments.push (cairo::PathSegment::ClosePath);
    }

    pub fn get_path_segments (&self) -> &Vec<cairo::PathSegment> {
        &self.path_segments
    }

    /**
     * x1/y1: starting coordinates
     * rx/ry: radiuses before rotation
     * x_axis_rotation: Rotation angle for axes, in degrees
     * is_large_arc: false for arc length <= 180, true for arc >= 180
     * is_sweep: false for negative angle, true for positive angle
     * x2/y2: ending coordinates
     */
    pub fn arc (&mut self,
                x1: f64, y1: f64,
                mut rx: f64, mut ry: f64,
                x_axis_rotation: f64,
                is_large_arc: bool,
                is_sweep: bool,
                x2: f64, y2: f64) {
        /* See Appendix F.6 Elliptical arc implementation notes
        http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes */

        let f: f64;
        let sinf: f64;
        let cosf: f64;
        let x1_: f64;
        let y1_: f64;
        let cx_: f64;
        let cy_: f64;
        let cx: f64;
        let cy: f64;
        let gamma: f64;
        let mut theta1: f64;
        let mut delta_theta: f64;
        let mut k1: f64;
        let mut k2: f64;
        let k3: f64;
        let k4: f64;
        let mut k5: f64;
        let n_segs: i32;

        if x1 == x2 && y1 == y2 {
            return;
        }

        /* X-axis */
        f = x_axis_rotation * f64::consts::PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        rx = rx.abs ();
        ry = ry.abs ();

        /* Check the radius against floading point underflow.
        See http://bugs.debian.org/508443 */
        if (rx < f64::EPSILON) || (ry < f64::EPSILON) {
            self.line_to (x2, y2);
            return;
        }

        k1 = (x1 - x2) / 2.0;
        k2 = (y1 - y2) / 2.0;

        x1_ = cosf * k1 + sinf * k2;
        y1_ = -sinf * k1 + cosf * k2;

        gamma = (x1_ * x1_) / (rx * rx) + (y1_ * y1_) / (ry * ry);
        if gamma > 1.0 {
            rx *= gamma.sqrt ();
            ry *= gamma.sqrt ();
        }

        /* Compute the center */

        k1 = rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_;
        if k1 == 0.0 {
            return;
        }

        k1 = ((rx * rx * ry * ry) / k1 - 1.0).abs ().sqrt ();
        if is_sweep == is_large_arc {
            k1 = -k1;
        }

        cx_ = k1 * rx * y1_ / ry;
        cy_ = -k1 * ry * x1_ / rx;

        cx = cosf * cx_ - sinf * cy_ + (x1 + x2) / 2.0;
        cy = sinf * cx_ + cosf * cy_ + (y1 + y2) / 2.0;

        /* Compute start angle */

        k1 = (x1_ - cx_) / rx;
        k2 = (y1_ - cy_) / ry;
        k3 = (-x1_ - cx_) / rx;
        k4 = (-y1_ - cy_) / ry;

        k5 = (k1 * k1 + k2 * k2).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = k1 / k5;
        k5 = clamp (k5, -1.0, 1.0);
        theta1 = k5.acos ();
        if k2 < 0.0 {
            theta1 = -theta1;
        }

        /* Compute delta_theta */

        k5 = ((k1 * k1 + k2 * k2) * (k3 * k3 + k4 * k4)).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = (k1 * k3 + k2 * k4) / k5;
        k5 = clamp (k5, -1.0, 1.0);
        delta_theta = k5.acos ();
        if k1 * k4 - k3 * k2 < 0.0 {
            delta_theta = -delta_theta;
        }

        if is_sweep && delta_theta < 0.0 {
            delta_theta += f64::consts::PI * 2.0;
        } else if !is_sweep && delta_theta > 0.0 {
            delta_theta -= f64::consts::PI * 2.0;
        }

        /* Now draw the arc */

        n_segs = (delta_theta / (f64::consts::PI * 0.5 + 0.001)).abs ().ceil () as i32;
        let n_segs_dbl = n_segs as f64;

        for i in 0 .. n_segs {
            self.arc_segment (cx, cy,
                              theta1 + i as f64 * delta_theta / n_segs_dbl,
                              theta1 + (i + 1) as f64 * delta_theta / n_segs_dbl,
                              rx, ry,
                              x_axis_rotation);
        }
    }

    fn arc_segment (&mut self,
                    xc: f64, yc: f64,
                    th0: f64, th1: f64,
                    rx: f64, ry: f64,
                    x_axis_rotation: f64) {
        let x1: f64;
        let y1: f64;
        let x2: f64;
        let y2: f64;
        let x3: f64;
        let y3: f64;
        let t: f64;
        let th_half: f64;
        let f: f64;
        let sinf: f64;
        let cosf: f64;

        f = x_axis_rotation * f64::consts::PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        th_half = 0.5 * (th1 - th0);
        t = (8.0 / 3.0) * (th_half * 0.5).sin () * (th_half * 0.5).sin () / th_half.sin ();
        x1 = rx * (th0.cos () - t * th0.sin ());
        y1 = ry * (th0.sin () + t * th0.cos ());
        x3 = rx * th1.cos ();
        y3 = ry * th1.sin ();
        x2 = x3 + rx * (t * th1.sin ());
        y2 = y3 + ry * (-t * th1.cos ());

        self.curve_to (xc + cosf * x1 - sinf * y1,
                       yc + sinf * x1 + cosf * y1,
                       xc + cosf * x2 - sinf * y2,
                       yc + sinf * x2 + cosf * y2,
                       xc + cosf * x3 - sinf * y3,
                       yc + sinf * x3 + cosf * y3);
    }
}

fn clamp (val: f64, low: f64, high: f64) -> f64 {
    if val < low {
        low
    } else if val > high {
        high
    } else {
        val
    }
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_new () -> *mut RsvgPathBuilder {
    let builder = RsvgPathBuilder::new ();

    let boxed_builder = Box::new (builder);

    Box::into_raw (boxed_builder)
}

#[no_mangle]
pub unsafe extern fn rsvg_path_builder_destroy (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let _ = Box::from_raw (raw_builder);
}

#[no_mangle]
pub extern fn rsvg_path_builder_move_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.move_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_line_to (raw_builder: *mut RsvgPathBuilder,
                                         x: f64,
                                         y: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.line_to (x, y);
}

#[no_mangle]
pub extern fn rsvg_path_builder_curve_to (raw_builder: *mut RsvgPathBuilder,
                                          x2: f64, y2: f64,
                                          x3: f64, y3: f64,
                                          x4: f64, y4: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.curve_to (x2, y2, x3, y3, x4, y4);
}

#[no_mangle]
pub extern fn rsvg_path_builder_arc (raw_builder: *mut RsvgPathBuilder,
                                     x1: f64, y1: f64,
                                     rx: f64, ry: f64,
                                     x_axis_rotation: f64,
                                     large_arc_flag: bool,
                                     sweep_flag: bool,
                                     x2: f64, y2: f64) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.arc (x1, y1,
                 rx, ry,
                 x_axis_rotation,
                 large_arc_flag,
                 sweep_flag,
                 x2, y2);
}

#[no_mangle]
pub extern fn rsvg_path_builder_close_path (raw_builder: *mut RsvgPathBuilder) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    builder.close_path ();
}

#[no_mangle]
pub extern fn rsvg_path_builder_add_to_cairo_context (raw_builder: *mut RsvgPathBuilder, cr: *mut cairo_sys::cairo_t) {
    assert! (!raw_builder.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };

    unsafe {
        let path_segments = builder.get_path_segments ();

        for s in path_segments {
            match *s {
                cairo::PathSegment::MoveTo ((x, y)) => {
                    cairo_sys::cairo_move_to (cr, x, y);
                },

                cairo::PathSegment::LineTo ((x, y)) => {
                    cairo_sys::cairo_line_to (cr, x, y);
                },

                cairo::PathSegment::CurveTo ((x2, y2), (x3, y3), (x4, y4)) => {
                    cairo_sys::cairo_curve_to (cr, x2, y2, x3, y3, x4, y4);
                },

                cairo::PathSegment::ClosePath => {
                    cairo_sys::cairo_close_path (cr);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use cairo_sys;
use cairo;
use glib::translate::*;

use std::f64;
use std::f64::consts::*;

#[derive(Debug, PartialEq)]
pub struct LargeArc(pub bool);

#[derive(Debug, PartialEq)]
pub enum Sweep {
    Negative,
    Positive
}

#[derive(Debug, PartialEq)]
pub enum PathCommand {
    MoveTo (f64, f64),
    LineTo (f64, f64),
    CurveTo ((f64, f64), (f64, f64), (f64, f64)), // (x2, y2), (x3, y3), (x4, y4) <- this is the destination point
    ClosePath
}

#[repr(C)]
pub struct RsvgPathBuilder {
    path_commands: Vec<PathCommand>,
}

impl Default for RsvgPathBuilder {
    fn default() -> RsvgPathBuilder {
        RsvgPathBuilder {
            path_commands: Vec::new ()
        }
    }
}

impl PathCommand {
    fn to_cairo(&self, cr: &cairo::Context) {
        match *self {
            PathCommand::MoveTo(x, y) => {
                cr.move_to(x, y);
            },

            PathCommand::LineTo(x, y) => {
                cr.line_to(x, y);
            },

            PathCommand::CurveTo((x2, y2), (x3, y3), (x4, y4)) => {
                cr.curve_to(x2, y2, x3, y3, x4, y4);
            },

            PathCommand::ClosePath => {
                cr.close_path();
            }
        }
    }
}

impl RsvgPathBuilder {
    pub fn new () -> RsvgPathBuilder {
        RsvgPathBuilder::default()
    }

    pub fn move_to (&mut self, x: f64, y: f64) {
        self.path_commands.push (PathCommand::MoveTo (x, y));
    }

    pub fn line_to (&mut self, x: f64, y: f64) {
        self.path_commands.push (PathCommand::LineTo (x, y));
    }

    pub fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_commands.push (PathCommand::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    pub fn close_path (&mut self) {
        self.path_commands.push (PathCommand::ClosePath);
    }

    pub fn get_path_commands (&self) -> &[PathCommand] {
        &self.path_commands
    }

    /**
     * x1/y1: starting coordinates
     * rx/ry: radiuses before rotation
     * x_axis_rotation: Rotation angle for axes, in degrees
     * large_arc: false for arc length <= 180, true for arc >= 180
     * sweep: negative or positive angle
     * x2/y2: ending coordinates
     */
    pub fn arc (&mut self,
                x1: f64, y1: f64,
                mut rx: f64, mut ry: f64,
                x_axis_rotation: f64,
                large_arc: LargeArc,
                sweep: Sweep,
                x2: f64, y2: f64) {
        /* See Appendix F.6 Elliptical arc implementation notes
        http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes */

        let f: f64;
        let sinf: f64;
        let cosf: f64;
        let x1_: f64;
        let y1_: f64;
        let cx_: f64;
        let cy_: f64;
        let cx: f64;
        let cy: f64;
        let gamma: f64;
        let mut theta1: f64;
        let mut delta_theta: f64;
        let mut k1: f64;
        let mut k2: f64;
        let k3: f64;
        let k4: f64;
        let mut k5: f64;
        let n_segs: i32;

        if x1 == x2 && y1 == y2 {
            return;
        }

        let is_positive_sweep = sweep == Sweep::Positive;

        let is_large_arc = large_arc.0;

        /* X-axis */
        f = x_axis_rotation * PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        rx = rx.abs ();
        ry = ry.abs ();

        /* Check the radius against floading point underflow.
        See http://bugs.debian.org/508443 */
        if (rx < f64::EPSILON) || (ry < f64::EPSILON) {
            self.line_to (x2, y2);
            return;
        }

        k1 = (x1 - x2) / 2.0;
        k2 = (y1 - y2) / 2.0;

        x1_ = cosf * k1 + sinf * k2;
        y1_ = -sinf * k1 + cosf * k2;

        gamma = (x1_ * x1_) / (rx * rx) + (y1_ * y1_) / (ry * ry);
        if gamma > 1.0 {
            rx *= gamma.sqrt ();
            ry *= gamma.sqrt ();
        }

        /* Compute the center */

        k1 = rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_;
        if k1 == 0.0 {
            return;
        }

        k1 = ((rx * rx * ry * ry) / k1 - 1.0).abs ().sqrt ();
        if is_positive_sweep == is_large_arc {
            k1 = -k1;
        }

        cx_ = k1 * rx * y1_ / ry;
        cy_ = -k1 * ry * x1_ / rx;

        cx = cosf * cx_ - sinf * cy_ + (x1 + x2) / 2.0;
        cy = sinf * cx_ + cosf * cy_ + (y1 + y2) / 2.0;

        /* Compute start angle */

        k1 = (x1_ - cx_) / rx;
        k2 = (y1_ - cy_) / ry;
        k3 = (-x1_ - cx_) / rx;
        k4 = (-y1_ - cy_) / ry;

        k5 = (k1 * k1 + k2 * k2).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = k1 / k5;
        k5 = clamp (k5, -1.0, 1.0);
        theta1 = k5.acos ();
        if k2 < 0.0 {
            theta1 = -theta1;
        }

        /* Compute delta_theta */

        k5 = ((k1 * k1 + k2 * k2) * (k3 * k3 + k4 * k4)).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = (k1 * k3 + k2 * k4) / k5;
        k5 = clamp (k5, -1.0, 1.0);
        delta_theta = k5.acos ();
        if k1 * k4 - k3 * k2 < 0.0 {
            delta_theta = -delta_theta;
        }

        if is_positive_sweep && delta_theta < 0.0 {
            delta_theta += PI * 2.0;
        } else if !is_positive_sweep && delta_theta > 0.0 {
            delta_theta -= PI * 2.0;
        }

        /* Now draw the arc */

        n_segs = (delta_theta / (PI * 0.5 + 0.001)).abs ().ceil () as i32;
        let n_segs_dbl = f64::from(n_segs);

        for i in 0 .. n_segs {
            self.arc_segment (cx, cy,
                              theta1 + f64::from(i)  * delta_theta / n_segs_dbl,
                              theta1 + f64::from(i + 1) * delta_theta / n_segs_dbl,
                              rx, ry,
                              x_axis_rotation);
        }
    }

    fn arc_segment (&mut self,
                    xc: f64, yc: f64,
                    th0: f64, th1: f64,
                    rx: f64, ry: f64,
                    x_axis_rotation: f64) {
        let x1: f64;
        let y1: f64;
        let x2: f64;
        let y2: f64;
        let x3: f64;
        let y3: f64;
        let t: f64;
        let th_half: f64;
        let f: f64;
        let sinf: f64;
        let cosf: f64;

        f = x_axis_rotation * PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        th_half = 0.5 * (th1 - th0);
        t = (8.0 / 3.0) * (th_half * 0.5).sin () * (th_half * 0.5).sin () / th_half.sin ();
        x1 = rx * (th0.cos () - t * th0.sin ());
        y1 = ry * (th0.sin () + t * th0.cos ());
        x3 = rx * th1.cos ();
        y3 = ry * th1.sin ();
        x2 = x3 + rx * (t * th1.sin ());
        y2 = y3 + ry * (-t * th1.cos ());

        self.curve_to (xc + cosf * x1 - sinf * y1,
                       yc + sinf * x1 + cosf * y1,
                       xc + cosf * x2 - sinf * y2,
                       yc + sinf * x2 + cosf * y2,
                       xc + cosf * x3 - sinf * y3,
                       yc + sinf * x3 + cosf * y3);
    }

    fn to_cairo(&self, cr: &cairo::Context) {
        for s in &self.path_commands {
            s.to_cairo(cr);
        }
    }
}

fn clamp (val: f64, low: f64, high: f64) -> f64 {
    if val < low {
        low
    } else if val > high {
        high
    } else {
        val
    }
}

#[no_mangle]
pub extern fn rsvg_path_builder_add_to_cairo_context (raw_builder: *mut RsvgPathBuilder,
                                                      raw_cr: *mut cairo_sys::cairo_t) {
    assert! (!raw_builder.is_null ());
    assert! (!raw_cr.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };
    let cr = unsafe { cairo::Context::from_glib_none(raw_cr) };
    builder.to_cairo(&cr);
}
<commit_msg>cargo-clippy: path_builder.rs: Copy some enums instead of moving them<commit_after>use cairo_sys;
use cairo;
use glib::translate::*;

use std::f64;
use std::f64::consts::*;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct LargeArc(pub bool);

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Sweep {
    Negative,
    Positive
}

#[derive(Debug, PartialEq)]
pub enum PathCommand {
    MoveTo (f64, f64),
    LineTo (f64, f64),
    CurveTo ((f64, f64), (f64, f64), (f64, f64)), // (x2, y2), (x3, y3), (x4, y4) <- this is the destination point
    ClosePath
}

#[repr(C)]
pub struct RsvgPathBuilder {
    path_commands: Vec<PathCommand>,
}

impl Default for RsvgPathBuilder {
    fn default() -> RsvgPathBuilder {
        RsvgPathBuilder {
            path_commands: Vec::new ()
        }
    }
}

impl PathCommand {
    fn to_cairo(&self, cr: &cairo::Context) {
        match *self {
            PathCommand::MoveTo(x, y) => {
                cr.move_to(x, y);
            },

            PathCommand::LineTo(x, y) => {
                cr.line_to(x, y);
            },

            PathCommand::CurveTo((x2, y2), (x3, y3), (x4, y4)) => {
                cr.curve_to(x2, y2, x3, y3, x4, y4);
            },

            PathCommand::ClosePath => {
                cr.close_path();
            }
        }
    }
}

impl RsvgPathBuilder {
    pub fn new () -> RsvgPathBuilder {
        RsvgPathBuilder::default()
    }

    pub fn move_to (&mut self, x: f64, y: f64) {
        self.path_commands.push (PathCommand::MoveTo (x, y));
    }

    pub fn line_to (&mut self, x: f64, y: f64) {
        self.path_commands.push (PathCommand::LineTo (x, y));
    }

    pub fn curve_to (&mut self, x2: f64, y2: f64, x3: f64, y3: f64, x4: f64, y4: f64) {
        self.path_commands.push (PathCommand::CurveTo ((x2, y2), (x3, y3), (x4, y4)));
    }

    pub fn close_path (&mut self) {
        self.path_commands.push (PathCommand::ClosePath);
    }

    pub fn get_path_commands (&self) -> &[PathCommand] {
        &self.path_commands
    }

    /**
     * x1/y1: starting coordinates
     * rx/ry: radiuses before rotation
     * x_axis_rotation: Rotation angle for axes, in degrees
     * large_arc: false for arc length <= 180, true for arc >= 180
     * sweep: negative or positive angle
     * x2/y2: ending coordinates
     */
    pub fn arc (&mut self,
                x1: f64, y1: f64,
                mut rx: f64, mut ry: f64,
                x_axis_rotation: f64,
                large_arc: LargeArc,
                sweep: Sweep,
                x2: f64, y2: f64) {
        /* See Appendix F.6 Elliptical arc implementation notes
        http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes */

        let f: f64;
        let sinf: f64;
        let cosf: f64;
        let x1_: f64;
        let y1_: f64;
        let cx_: f64;
        let cy_: f64;
        let cx: f64;
        let cy: f64;
        let gamma: f64;
        let mut theta1: f64;
        let mut delta_theta: f64;
        let mut k1: f64;
        let mut k2: f64;
        let k3: f64;
        let k4: f64;
        let mut k5: f64;
        let n_segs: i32;

        if x1 == x2 && y1 == y2 {
            return;
        }

        let is_positive_sweep = sweep == Sweep::Positive;

        let is_large_arc = large_arc.0;

        /* X-axis */
        f = x_axis_rotation * PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        rx = rx.abs ();
        ry = ry.abs ();

        /* Check the radius against floading point underflow.
        See http://bugs.debian.org/508443 */
        if (rx < f64::EPSILON) || (ry < f64::EPSILON) {
            self.line_to (x2, y2);
            return;
        }

        k1 = (x1 - x2) / 2.0;
        k2 = (y1 - y2) / 2.0;

        x1_ = cosf * k1 + sinf * k2;
        y1_ = -sinf * k1 + cosf * k2;

        gamma = (x1_ * x1_) / (rx * rx) + (y1_ * y1_) / (ry * ry);
        if gamma > 1.0 {
            rx *= gamma.sqrt ();
            ry *= gamma.sqrt ();
        }

        /* Compute the center */

        k1 = rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_;
        if k1 == 0.0 {
            return;
        }

        k1 = ((rx * rx * ry * ry) / k1 - 1.0).abs ().sqrt ();
        if is_positive_sweep == is_large_arc {
            k1 = -k1;
        }

        cx_ = k1 * rx * y1_ / ry;
        cy_ = -k1 * ry * x1_ / rx;

        cx = cosf * cx_ - sinf * cy_ + (x1 + x2) / 2.0;
        cy = sinf * cx_ + cosf * cy_ + (y1 + y2) / 2.0;

        /* Compute start angle */

        k1 = (x1_ - cx_) / rx;
        k2 = (y1_ - cy_) / ry;
        k3 = (-x1_ - cx_) / rx;
        k4 = (-y1_ - cy_) / ry;

        k5 = (k1 * k1 + k2 * k2).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = k1 / k5;
        k5 = clamp (k5, -1.0, 1.0);
        theta1 = k5.acos ();
        if k2 < 0.0 {
            theta1 = -theta1;
        }

        /* Compute delta_theta */

        k5 = ((k1 * k1 + k2 * k2) * (k3 * k3 + k4 * k4)).abs ().sqrt ();
        if k5 == 0.0 {
            return;
        }

        k5 = (k1 * k3 + k2 * k4) / k5;
        k5 = clamp (k5, -1.0, 1.0);
        delta_theta = k5.acos ();
        if k1 * k4 - k3 * k2 < 0.0 {
            delta_theta = -delta_theta;
        }

        if is_positive_sweep && delta_theta < 0.0 {
            delta_theta += PI * 2.0;
        } else if !is_positive_sweep && delta_theta > 0.0 {
            delta_theta -= PI * 2.0;
        }

        /* Now draw the arc */

        n_segs = (delta_theta / (PI * 0.5 + 0.001)).abs ().ceil () as i32;
        let n_segs_dbl = f64::from(n_segs);

        for i in 0 .. n_segs {
            self.arc_segment (cx, cy,
                              theta1 + f64::from(i)  * delta_theta / n_segs_dbl,
                              theta1 + f64::from(i + 1) * delta_theta / n_segs_dbl,
                              rx, ry,
                              x_axis_rotation);
        }
    }

    fn arc_segment (&mut self,
                    xc: f64, yc: f64,
                    th0: f64, th1: f64,
                    rx: f64, ry: f64,
                    x_axis_rotation: f64) {
        let x1: f64;
        let y1: f64;
        let x2: f64;
        let y2: f64;
        let x3: f64;
        let y3: f64;
        let t: f64;
        let th_half: f64;
        let f: f64;
        let sinf: f64;
        let cosf: f64;

        f = x_axis_rotation * PI / 180.0;
        sinf = f.sin ();
        cosf = f.cos ();

        th_half = 0.5 * (th1 - th0);
        t = (8.0 / 3.0) * (th_half * 0.5).sin () * (th_half * 0.5).sin () / th_half.sin ();
        x1 = rx * (th0.cos () - t * th0.sin ());
        y1 = ry * (th0.sin () + t * th0.cos ());
        x3 = rx * th1.cos ();
        y3 = ry * th1.sin ();
        x2 = x3 + rx * (t * th1.sin ());
        y2 = y3 + ry * (-t * th1.cos ());

        self.curve_to (xc + cosf * x1 - sinf * y1,
                       yc + sinf * x1 + cosf * y1,
                       xc + cosf * x2 - sinf * y2,
                       yc + sinf * x2 + cosf * y2,
                       xc + cosf * x3 - sinf * y3,
                       yc + sinf * x3 + cosf * y3);
    }

    fn to_cairo(&self, cr: &cairo::Context) {
        for s in &self.path_commands {
            s.to_cairo(cr);
        }
    }
}

fn clamp (val: f64, low: f64, high: f64) -> f64 {
    if val < low {
        low
    } else if val > high {
        high
    } else {
        val
    }
}

#[no_mangle]
pub extern fn rsvg_path_builder_add_to_cairo_context (raw_builder: *mut RsvgPathBuilder,
                                                      raw_cr: *mut cairo_sys::cairo_t) {
    assert! (!raw_builder.is_null ());
    assert! (!raw_cr.is_null ());

    let builder: &mut RsvgPathBuilder = unsafe { &mut (*raw_builder) };
    let cr = unsafe { cairo::Context::from_glib_none(raw_cr) };
    builder.to_cairo(&cr);
}
<|endoftext|>


<commit_before><commit_msg>Add interface to query available converter names<commit_after>// Copyright 2021 Luis Cáceres
//
// 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.

use std::ffi::CStr;

use {rust_icu_sys as sys, rust_icu_sys::versioned_function, rust_icu_sys::*};

/// Get an iterator over all canonical converter names available to ICU.
///
/// The [AvailableConverters] iterator efficiently implements [Iterator::count] and [Iterator::nth]
/// to avoid calling `ucnv_getAvailableName` unnecessarily.
///
/// This interface wraps around `ucnv_countAvailable` and `ucnv_getAvailableName`.
pub fn available_converters() -> AvailableConverters {
    AvailableConverters {
        n: 0,
        count: unsafe { versioned_function!(ucnv_countAvailable)() } as u32,
    }
}

/// See [available_converters()]
pub struct AvailableConverters {
    n: u32,
    count: u32,
}

impl AvailableConverters {
    #[inline(always)]
    fn elements_left(&self) -> usize {
        self.count.saturating_sub(self.n) as usize
    }
}

impl Iterator for AvailableConverters {
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        let name_c_str = unsafe { versioned_function!(ucnv_getAvailableName)(self.n as i32) };
        if name_c_str.is_null() {
            return None;
        }

        self.n += 1;
        unsafe {
            Some(
                CStr::from_ptr(name_c_str)
                    .to_str()
                    .expect("converter name should be UTF-8 compatible")
                    .to_string(),
            )
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let count = self.elements_left();
        (count, Some(count))
    }

    fn count(self) -> usize {
        self.elements_left()
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        if n >= self.elements_left() {
            self.n = self.count;
            None
        } else {
            self.n += n as u32;
            self.next()
        }
    }
}

impl ExactSizeIterator for AvailableConverters {}

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

    #[test]
    fn test_available_converter_names() {
        let converters = available_converters();
        let converters_count = converters.len();

        let mut count = 0usize;
        for _ in converters {
            count += 1;
        }

        assert_eq!(converters_count, count);
    }
}<|endoftext|>


<commit_before>use beacon_chain::{BeaconChain, BeaconChainTypes};
use environment::RuntimeContext;
use exit_future::Signal;
use futures::{Future, Stream};
use network::Service as NetworkService;
use parking_lot::Mutex;
use slog::{debug, error, info, warn};
use slot_clock::SlotClock;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::timer::Interval;
use types::{EthSpec, Slot};

/// Create a warning log whenever the peer count is at or below this value.
pub const WARN_PEER_COUNT: usize = 1;

const SECS_PER_MINUTE: u64 = 60;
const SECS_PER_HOUR: u64 = 3600;
const SECS_PER_DAY: u64 = 86400; // non-leap
const SECS_PER_WEEK: u64 = 604800; // non-leap
const DAYS_PER_WEEK: u64 = 7;
const HOURS_PER_DAY: u64 = 24;
const MINUTES_PER_HOUR: u64 = 60;

/// Spawns a notifier service which periodically logs information about the node.
pub fn spawn_notifier<T: BeaconChainTypes>(
    context: RuntimeContext<T::EthSpec>,
    beacon_chain: Arc<BeaconChain<T>>,
    network: Arc<NetworkService<T>>,
    milliseconds_per_slot: u64,
) -> Result<Signal, String> {
    let log_1 = context.log.clone();
    let log_2 = context.log.clone();

    let slot_duration = Duration::from_millis(milliseconds_per_slot);
    let duration_to_next_slot = beacon_chain
        .slot_clock
        .duration_to_next_slot()
        .ok_or_else(|| "slot_notifier unable to determine time to next slot")?;

    // Run this half way through each slot.
    let start_instant = Instant::now() + duration_to_next_slot + (slot_duration / 2);

    // Run this each slot.
    let interval_duration = slot_duration;

    let previous_head_slot = Mutex::new(Slot::new(0));

    let interval_future = Interval::new(start_instant, interval_duration)
        .map_err(
            move |e| error!(log_1, "Slot notifier timer failed"; "error" => format!("{:?}", e)),
        )
        .for_each(move |_| {
            let log = log_2.clone();

            let connected_peer_count = network.libp2p_service().lock().swarm.connected_peers();

            let head = beacon_chain.head();

            let head_slot = head.beacon_block.slot;
            let head_epoch = head_slot.epoch(T::EthSpec::slots_per_epoch());
            let current_slot = beacon_chain.slot().map_err(|e| {
                error!(
                    log,
                    "Unable to read current slot";
                    "error" => format!("{:?}", e)
                )
            })?;
            let current_epoch = current_slot.epoch(T::EthSpec::slots_per_epoch());
            let finalized_epoch = head.beacon_state.finalized_checkpoint.epoch;
            let finalized_root = head.beacon_state.finalized_checkpoint.root;
            let head_root = head.beacon_block_root;

            let mut previous_head_slot = previous_head_slot.lock();

            // The next two lines take advantage of saturating subtraction on `Slot`.
            let head_distance = current_slot - head_slot;
            let slots_since_last_update = head_slot - *previous_head_slot;

            *previous_head_slot = head_slot;

            if connected_peer_count <= WARN_PEER_COUNT {
                warn!(log, "Low peer count"; "peer_count" => connected_peer_count);
            }

            debug!(
                log,
                "Slot timer";
                "peers" => connected_peer_count,
                "finalized_root" => format!("{}", finalized_root),
                "finalized_epoch" => finalized_epoch,
                "head_block" => format!("{}", head_root),
                "head_slot" => head_slot,
                "current_slot" => current_slot,
            );

            if head_epoch + 1 < current_epoch {
                let distance = format!(
                    "{} slots ({})",
                    head_distance.as_u64(),
                    slot_distance_pretty(head_distance, slot_duration)
                );

                info!(
                    log,
                    "Syncing";
                    "peers" => connected_peer_count,
                    "speed" => sync_rate_pretty(slots_since_last_update, interval_duration.as_secs()),
                    "distance" => distance
                );

                return Ok(());
            };

            macro_rules! not_quite_synced_log {
                ($message: expr) => {
                    info!(
                        log_2,
                        $message;
                        "peers" => connected_peer_count,
                        "finalized_root" => format!("{}", finalized_root),
                        "finalized_epoch" => finalized_epoch,
                        "head_slot" => head_slot,
                        "current_slot" => current_slot,
                    );
                }
            }

            if head_epoch + 1 == current_epoch {
                not_quite_synced_log!("Synced to previous epoch")
            } else if head_slot != current_slot {
                not_quite_synced_log!("Synced to current epoch")
            } else {
                info!(
                    log_2,
                    "Synced";
                    "peers" => connected_peer_count,
                    "finalized_root" => format!("{}", finalized_root),
                    "finalized_epoch" => finalized_epoch,
                    "epoch" => current_epoch,
                    "slot" => current_slot,
                );
            };

            Ok(())
        });

    let (exit_signal, exit) = exit_future::signal();
    context
        .executor
        .spawn(exit.until(interval_future).map(|_| ()));

    Ok(exit_signal)
}

/// Returns a nicely formated string describing the rate of slot imports per second.
fn sync_rate_pretty(slots_since_last_update: Slot, update_interval_secs: u64) -> String {
    if update_interval_secs == 0 {
        return "Error".into();
    }

    if slots_since_last_update == 0 {
        "No progress".into()
    } else {
        let distance = f64::from(slots_since_last_update.as_u64() as u32);
        let time = f64::from(update_interval_secs as u32);

        format!("{:.2} slots/sec", distance / time)
    }
}

/// Returns a nicely formatted string describing the `slot_span` in terms of weeks, days, hours
/// and/or minutes.
fn slot_distance_pretty(slot_span: Slot, slot_duration: Duration) -> String {
    if slot_duration == Duration::from_secs(0) {
        return String::from("Unknown");
    }

    let secs = (slot_duration * slot_span.as_u64() as u32).as_secs();

    let weeks = secs / SECS_PER_WEEK;
    let days = secs / SECS_PER_DAY;
    let hours = secs / SECS_PER_HOUR;
    let minutes = secs / SECS_PER_MINUTE;

    if weeks > 0 {
        format!("{} weeks {} days", weeks, days % DAYS_PER_WEEK)
    } else if days > 0 {
        format!("{} days {} hrs", days, hours % HOURS_PER_DAY)
    } else if hours > 0 {
        format!("{} hrs {} mins", hours, minutes % MINUTES_PER_HOUR)
    } else {
        format!("{} mins", minutes)
    }
}
<commit_msg>Add timeout when notifier waits for libp2p lock (#676)<commit_after>use beacon_chain::{BeaconChain, BeaconChainTypes};
use environment::RuntimeContext;
use exit_future::Signal;
use futures::{Future, Stream};
use network::Service as NetworkService;
use parking_lot::Mutex;
use slog::{debug, error, info, warn};
use slot_clock::SlotClock;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::timer::Interval;
use types::{EthSpec, Slot};

/// Create a warning log whenever the peer count is at or below this value.
pub const WARN_PEER_COUNT: usize = 1;

const SECS_PER_MINUTE: u64 = 60;
const SECS_PER_HOUR: u64 = 3600;
const SECS_PER_DAY: u64 = 86400; // non-leap
const SECS_PER_WEEK: u64 = 604800; // non-leap
const DAYS_PER_WEEK: u64 = 7;
const HOURS_PER_DAY: u64 = 24;
const MINUTES_PER_HOUR: u64 = 60;

/// How long to wait for the lock on `network.libp2p_service()` before we give up.
const LIBP2P_LOCK_TIMEOUT: Duration = Duration::from_millis(50);

/// Spawns a notifier service which periodically logs information about the node.
pub fn spawn_notifier<T: BeaconChainTypes>(
    context: RuntimeContext<T::EthSpec>,
    beacon_chain: Arc<BeaconChain<T>>,
    network: Arc<NetworkService<T>>,
    milliseconds_per_slot: u64,
) -> Result<Signal, String> {
    let log_1 = context.log.clone();
    let log_2 = context.log.clone();

    let slot_duration = Duration::from_millis(milliseconds_per_slot);
    let duration_to_next_slot = beacon_chain
        .slot_clock
        .duration_to_next_slot()
        .ok_or_else(|| "slot_notifier unable to determine time to next slot")?;

    // Run this half way through each slot.
    let start_instant = Instant::now() + duration_to_next_slot + (slot_duration / 2);

    // Run this each slot.
    let interval_duration = slot_duration;

    let previous_head_slot = Mutex::new(Slot::new(0));

    let interval_future = Interval::new(start_instant, interval_duration)
        .map_err(
            move |e| error!(log_1, "Slot notifier timer failed"; "error" => format!("{:?}", e)),
        )
        .for_each(move |_| {
            let log = log_2.clone();

            let connected_peer_count = if let Some(libp2p) = network
                .libp2p_service()
                .try_lock_until(Instant::now() + LIBP2P_LOCK_TIMEOUT)
            {
                libp2p.swarm.connected_peers()
            } else {
                // Use max_value here and we'll print something pretty later.
                usize::max_value()
            };

            let head = beacon_chain.head();

            let head_slot = head.beacon_block.slot;
            let head_epoch = head_slot.epoch(T::EthSpec::slots_per_epoch());
            let current_slot = beacon_chain.slot().map_err(|e| {
                error!(
                    log,
                    "Unable to read current slot";
                    "error" => format!("{:?}", e)
                )
            })?;
            let current_epoch = current_slot.epoch(T::EthSpec::slots_per_epoch());
            let finalized_epoch = head.beacon_state.finalized_checkpoint.epoch;
            let finalized_root = head.beacon_state.finalized_checkpoint.root;
            let head_root = head.beacon_block_root;

            let mut previous_head_slot = previous_head_slot.lock();

            // The next two lines take advantage of saturating subtraction on `Slot`.
            let head_distance = current_slot - head_slot;
            let slots_since_last_update = head_slot - *previous_head_slot;

            *previous_head_slot = head_slot;

            if connected_peer_count <= WARN_PEER_COUNT {
                warn!(log, "Low peer count"; "peer_count" => peer_count_pretty(connected_peer_count));
            }

            debug!(
                log,
                "Slot timer";
                "peers" => peer_count_pretty(connected_peer_count),
                "finalized_root" => format!("{}", finalized_root),
                "finalized_epoch" => finalized_epoch,
                "head_block" => format!("{}", head_root),
                "head_slot" => head_slot,
                "current_slot" => current_slot,
            );

            if head_epoch + 1 < current_epoch {
                let distance = format!(
                    "{} slots ({})",
                    head_distance.as_u64(),
                    slot_distance_pretty(head_distance, slot_duration)
                );

                info!(
                    log,
                    "Syncing";
                    "peers" => peer_count_pretty(connected_peer_count),
                    "speed" => sync_rate_pretty(slots_since_last_update, interval_duration.as_secs()),
                    "distance" => distance
                );

                return Ok(());
            };

            macro_rules! not_quite_synced_log {
                ($message: expr) => {
                    info!(
                        log_2,
                        $message;
                        "peers" => peer_count_pretty(connected_peer_count),
                        "finalized_root" => format!("{}", finalized_root),
                        "finalized_epoch" => finalized_epoch,
                        "head_slot" => head_slot,
                        "current_slot" => current_slot,
                    );
                }
            }

            if head_epoch + 1 == current_epoch {
                not_quite_synced_log!("Synced to previous epoch")
            } else if head_slot != current_slot {
                not_quite_synced_log!("Synced to current epoch")
            } else {
                info!(
                    log_2,
                    "Synced";
                    "peers" => peer_count_pretty(connected_peer_count),
                    "finalized_root" => format!("{}", finalized_root),
                    "finalized_epoch" => finalized_epoch,
                    "epoch" => current_epoch,
                    "slot" => current_slot,
                );
            };

            Ok(())
        });

    let (exit_signal, exit) = exit_future::signal();
    context
        .executor
        .spawn(exit.until(interval_future).map(|_| ()));

    Ok(exit_signal)
}

/// Returns the peer count, returning something helpful if it's `usize::max_value` (effectively a
/// `None` value).
fn peer_count_pretty(peer_count: usize) -> String {
    if peer_count == usize::max_value() {
        String::from("--")
    } else {
        format!("{}", peer_count)
    }
}

/// Returns a nicely formated string describing the rate of slot imports per second.
fn sync_rate_pretty(slots_since_last_update: Slot, update_interval_secs: u64) -> String {
    if update_interval_secs == 0 {
        return "Error".into();
    }

    if slots_since_last_update == 0 {
        "No progress".into()
    } else {
        let distance = f64::from(slots_since_last_update.as_u64() as u32);
        let time = f64::from(update_interval_secs as u32);

        format!("{:.2} slots/sec", distance / time)
    }
}

/// Returns a nicely formatted string describing the `slot_span` in terms of weeks, days, hours
/// and/or minutes.
fn slot_distance_pretty(slot_span: Slot, slot_duration: Duration) -> String {
    if slot_duration == Duration::from_secs(0) {
        return String::from("Unknown");
    }

    let secs = (slot_duration * slot_span.as_u64() as u32).as_secs();

    let weeks = secs / SECS_PER_WEEK;
    let days = secs / SECS_PER_DAY;
    let hours = secs / SECS_PER_HOUR;
    let minutes = secs / SECS_PER_MINUTE;

    if weeks > 0 {
        format!("{} weeks {} days", weeks, days % DAYS_PER_WEEK)
    } else if days > 0 {
        format!("{} days {} hrs", days, hours % HOURS_PER_DAY)
    } else if hours > 0 {
        format!("{} hrs {} mins", hours, minutes % MINUTES_PER_HOUR)
    } else {
        format!("{} mins", minutes)
    }
}
<|endoftext|>


<commit_before>//! Implements support for the LM4F120 UARTs

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use core::intrinsics::{volatile_store, volatile_load};
use core::ptr::Unique;
use super::registers;
use super::gpio;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

/// This chip has 8 UARTs
#[derive(PartialEq, Clone, Copy)]
pub enum UartId {
    Uart0,
    Uart1,
    Uart2,
    Uart3,
    Uart4,
    Uart5,
    Uart6,
    Uart7,
}

/// Controls a single UART
/// Only supports 8/N/1 - who needs anything else?
pub struct Uart {
    id: UartId,
    baud: u32,
    nl_mode: NewlineMode,
    reg: Unique<registers::UartRegisters>,
}

/// writeln!() emits LF chars, so this is useful
/// if you're writing text with your UART
#[derive(PartialEq, Clone, Copy)]
pub enum NewlineMode {
    Binary,
    SwapLFtoCRLF,
}

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

impl Uart {
    pub fn new(id: UartId, baud: u32, nl_mode: NewlineMode) -> Uart {
        let mut uart = Uart {
            id: id,
            baud: baud,
            nl_mode: nl_mode,
            reg: get_uart_registers(id),
        };
        uart.init();
        uart
    }

    pub fn init(&mut self) -> () {
        // Do GPIO pin muxing
        gpio::enable_uart(self.id);
        // Enable UART module in RCGUART register p306
        unsafe {
            self.enable_uart();
            let uart_reg = self.reg.get_mut();

            // Disable UART and all features
            uart_reg.ctl = 0;
            // Calculate the baud rate values
            // baud_div = CLOCK_RATE / (16 * baud_rate);
            // baud_int = round(baud_div * 64)
            let baud_int: u32 = (((66000000 * 8) / self.baud) + 1) / 2;
            // Store the upper and lower parts of the divider
            uart_reg.ibrd = (baud_int / 64) as usize;
            uart_reg.fbrd = (baud_int % 64) as usize;
            // Calculate the UART Line Control register value
            // 8N1
            uart_reg.lcrh = registers::UART_LCRH_WLEN_8;
            // Clear the flags
            uart_reg.rf = 0;
            // Enable
            uart_reg.ctl = registers::UART_CTL_RXE | registers::UART_CTL_TXE |
                           registers::UART_CTL_UARTEN;
        }
    }

    unsafe fn enable_uart(&mut self) {
        let mut reg: usize = volatile_load(registers::SYSCTL_RCGCUART_R);
        reg |= match self.id {
            UartId::Uart0 => 1 << 0,
            UartId::Uart1 => 1 << 1,
            UartId::Uart2 => 1 << 2,
            UartId::Uart3 => 1 << 3,
            UartId::Uart4 => 1 << 4,
            UartId::Uart5 => 1 << 5,
            UartId::Uart6 => 1 << 6,
            UartId::Uart7 => 1 << 7,
        };
        volatile_store(registers::SYSCTL_RCGCUART_R, reg);
    }

    fn putc(&mut self, value: u8) {
        unsafe {
            let uart_reg = self.reg.get_mut();
            while (uart_reg.rf & registers::UART_FR_TXFF) != 0 {
                asm!("NOP");
            }
            uart_reg.data = value as usize;
        }
    }
}

impl ::core::fmt::Write for Uart {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        match self.nl_mode {
            NewlineMode::Binary => {
                for byte in s.bytes() {
                    self.putc(byte)
                }
            }
            NewlineMode::SwapLFtoCRLF => {
                for byte in s.bytes() {
                    if byte == 0x0A {
                        // Prefix every \n with a \r
                        self.putc(0x0D)
                    }
                    self.putc(byte)
                }
            }
        }
        Ok(())
    }
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

fn get_uart_registers(uart: UartId) -> Unique<registers::UartRegisters> {
    match uart {
        UartId::Uart0 => unsafe { Unique::new(registers::UART0_DR_R as *mut _) },
        UartId::Uart1 => unsafe { Unique::new(registers::UART1_DR_R as *mut _) },
        UartId::Uart2 => unsafe { Unique::new(registers::UART2_DR_R as *mut _) },
        UartId::Uart3 => unsafe { Unique::new(registers::UART3_DR_R as *mut _) },
        UartId::Uart4 => unsafe { Unique::new(registers::UART4_DR_R as *mut _) },
        UartId::Uart5 => unsafe { Unique::new(registers::UART5_DR_R as *mut _) },
        UartId::Uart6 => unsafe { Unique::new(registers::UART6_DR_R as *mut _) },
        UartId::Uart7 => unsafe { Unique::new(registers::UART7_DR_R as *mut _) },
    }
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>uart::init doesn't need to be public.<commit_after>//! Implements support for the LM4F120 UARTs

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use core::intrinsics::{volatile_store, volatile_load};
use core::ptr::Unique;
use super::registers;
use super::gpio;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

/// This chip has 8 UARTs
#[derive(PartialEq, Clone, Copy)]
pub enum UartId {
    Uart0,
    Uart1,
    Uart2,
    Uart3,
    Uart4,
    Uart5,
    Uart6,
    Uart7,
}

/// Controls a single UART
/// Only supports 8/N/1 - who needs anything else?
pub struct Uart {
    id: UartId,
    baud: u32,
    nl_mode: NewlineMode,
    reg: Unique<registers::UartRegisters>,
}

/// writeln!() emits LF chars, so this is useful
/// if you're writing text with your UART
#[derive(PartialEq, Clone, Copy)]
pub enum NewlineMode {
    Binary,
    SwapLFtoCRLF,
}

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

impl Uart {
    pub fn new(id: UartId, baud: u32, nl_mode: NewlineMode) -> Uart {
        let mut uart = Uart {
            id: id,
            baud: baud,
            nl_mode: nl_mode,
            reg: get_uart_registers(id),
        };
        uart.init();
        uart
    }

    fn init(&mut self) -> () {
        // Do GPIO pin muxing
        gpio::enable_uart(self.id);
        // Enable UART module in RCGUART register p306
        unsafe {
            self.enable_uart();
            let uart_reg = self.reg.get_mut();

            // Disable UART and all features
            uart_reg.ctl = 0;
            // Calculate the baud rate values
            // baud_div = CLOCK_RATE / (16 * baud_rate);
            // baud_int = round(baud_div * 64)
            let baud_int: u32 = (((66000000 * 8) / self.baud) + 1) / 2;
            // Store the upper and lower parts of the divider
            uart_reg.ibrd = (baud_int / 64) as usize;
            uart_reg.fbrd = (baud_int % 64) as usize;
            // Calculate the UART Line Control register value
            // 8N1
            uart_reg.lcrh = registers::UART_LCRH_WLEN_8;
            // Clear the flags
            uart_reg.rf = 0;
            // Enable
            uart_reg.ctl = registers::UART_CTL_RXE | registers::UART_CTL_TXE |
                           registers::UART_CTL_UARTEN;
        }
    }

    unsafe fn enable_uart(&mut self) {
        let mut reg: usize = volatile_load(registers::SYSCTL_RCGCUART_R);
        reg |= match self.id {
            UartId::Uart0 => 1 << 0,
            UartId::Uart1 => 1 << 1,
            UartId::Uart2 => 1 << 2,
            UartId::Uart3 => 1 << 3,
            UartId::Uart4 => 1 << 4,
            UartId::Uart5 => 1 << 5,
            UartId::Uart6 => 1 << 6,
            UartId::Uart7 => 1 << 7,
        };
        volatile_store(registers::SYSCTL_RCGCUART_R, reg);
    }

    fn putc(&mut self, value: u8) {
        unsafe {
            let uart_reg = self.reg.get_mut();
            while (uart_reg.rf & registers::UART_FR_TXFF) != 0 {
                asm!("NOP");
            }
            uart_reg.data = value as usize;
        }
    }
}

impl ::core::fmt::Write for Uart {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        match self.nl_mode {
            NewlineMode::Binary => {
                for byte in s.bytes() {
                    self.putc(byte)
                }
            }
            NewlineMode::SwapLFtoCRLF => {
                for byte in s.bytes() {
                    if byte == 0x0A {
                        // Prefix every \n with a \r
                        self.putc(0x0D)
                    }
                    self.putc(byte)
                }
            }
        }
        Ok(())
    }
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

fn get_uart_registers(uart: UartId) -> Unique<registers::UartRegisters> {
    match uart {
        UartId::Uart0 => unsafe { Unique::new(registers::UART0_DR_R as *mut _) },
        UartId::Uart1 => unsafe { Unique::new(registers::UART1_DR_R as *mut _) },
        UartId::Uart2 => unsafe { Unique::new(registers::UART2_DR_R as *mut _) },
        UartId::Uart3 => unsafe { Unique::new(registers::UART3_DR_R as *mut _) },
        UartId::Uart4 => unsafe { Unique::new(registers::UART4_DR_R as *mut _) },
        UartId::Uart5 => unsafe { Unique::new(registers::UART5_DR_R as *mut _) },
        UartId::Uart6 => unsafe { Unique::new(registers::UART6_DR_R as *mut _) },
        UartId::Uart7 => unsafe { Unique::new(registers::UART7_DR_R as *mut _) },
    }
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>mod compositor;
mod xdg_shell;

use crate::Smallvil;

//
// Wl Seat
//

use smithay::delegate_seat;
use smithay::wayland::seat::{SeatHandler, SeatState};

use wayland_server::{delegate_dispatch, delegate_global_dispatch};

impl SeatHandler for Smallvil {
    fn seat_state(&mut self) -> &mut SeatState<Smallvil> {
        &mut self.seat_state
    }
}

delegate_seat!(Smallvil);

//
// Wl Outpu & Xdg Output
//

use smithay::wayland::output::OutputManagerState;
use wayland_protocols::unstable::xdg_output::v1::server::{
    zxdg_output_manager_v1::ZxdgOutputManagerV1, zxdg_output_v1::ZxdgOutputV1,
};
use wayland_server::protocol::wl_output::WlOutput;

// Wl Output
delegate_global_dispatch!(Smallvil: [WlOutput, ZxdgOutputManagerV1] => OutputManagerState);
delegate_dispatch!(Smallvil: [WlOutput, ZxdgOutputManagerV1, ZxdgOutputV1] => OutputManagerState);
<commit_msg>smallvil: typo<commit_after>mod compositor;
mod xdg_shell;

use crate::Smallvil;

//
// Wl Seat
//

use smithay::delegate_seat;
use smithay::wayland::seat::{SeatHandler, SeatState};

use wayland_server::{delegate_dispatch, delegate_global_dispatch};

impl SeatHandler for Smallvil {
    fn seat_state(&mut self) -> &mut SeatState<Smallvil> {
        &mut self.seat_state
    }
}

delegate_seat!(Smallvil);

//
// Wl Output & Xdg Output
//

use smithay::wayland::output::OutputManagerState;
use wayland_protocols::unstable::xdg_output::v1::server::{
    zxdg_output_manager_v1::ZxdgOutputManagerV1, zxdg_output_v1::ZxdgOutputV1,
};
use wayland_server::protocol::wl_output::WlOutput;

// Wl Output
delegate_global_dispatch!(Smallvil: [WlOutput, ZxdgOutputManagerV1] => OutputManagerState);
delegate_dispatch!(Smallvil: [WlOutput, ZxdgOutputManagerV1, ZxdgOutputV1] => OutputManagerState);
<|endoftext|>


<commit_before>/* Copyright 2017 Christopher Bacher
 *
 * 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.
 */

use super::super::*;

/// Takes a list of matchers for the same type combines them conjunctively.
#[macro_export]
macro_rules! all_of {
    ( $matcher: expr ) => {
        Box::new(All::of($matcher))
    };
    ( $matcher: expr, $($matchers: expr),* ) => {
        Box::new(All::of($matcher)$(.and($matchers))*)
    };
}

/// A `Matcher` struct which joins multiple `Matcher`s conjunctively.
///
/// Use `of()` to create a new `Matcher` and `and()` to add further `Matcher`s.
pub struct All<'a, T:'a> {
    pub matcher: Box<Matcher<'a,T> + 'a>,
    pub next: Option<Box<All<'a,T>>>
}

impl<'a,T:'a> All<'a, T> {
    /// Creates a new conjunctive `Matcher` starting with the given `Matcher`.
    pub fn of(matcher: Box<Matcher<'a,T> + 'a>) -> All<'a,T> {
        All {
            matcher: matcher,
            next: None
        }
    }

    /// Adds the given `Matcher` conjunctively.
    pub fn and(self, matcher: Box<Matcher<'a,T> + 'a>) -> All<'a,T> {
        All {
            matcher: matcher,
            next: Some(Box::new(self))
        }
    }
}

impl<'a,T:'a> Matcher<'a,T> for All<'a,T> {
    fn check(&self, actual: &'a T) -> MatchResult {
        match self.matcher.check(actual) {
            x@MatchResult::Matched {..} => {
                match self.next {
                    None => x,
                    Some(ref next) => next.check(actual)
                }
            },
            x@MatchResult::Failed {..} => x
        }
    }
}

/// Takes a list of matchers for the same type combines them disjunctively.
#[macro_export]
macro_rules! any_of {
    ( $matcher: expr ) => {
        Box::new(Any::of($matcher))
    };
    ( $matcher: expr, $($matchers: expr),* ) => {
        Box::new(Any::of($matcher)$(.or($matchers))*)
    };
}

/// A `Matcher` struct which joins multiple `Matcher`s disjunctively.
///
/// Use `of()` to create a new `Matcher` and `or()` to add further `Matcher`s.
pub struct Any<'a, T:'a> {
    pub matcher: Box<Matcher<'a,T> + 'a>,
    pub next: Option<Box<Any<'a,T>>>
}

impl<'a,T:'a> Any<'a, T> {
    /// Creates a new conjunctive `Matcher` starting with the given `Matcher`.
    pub fn of(matcher: Box<Matcher<'a,T> + 'a>) -> Any<'a,T> {
        Any {
            matcher: matcher,
            next: None
        }
    }

    /// Adds the given `Matcher` disjunctively.
    pub fn or(self, matcher: Box<Matcher<'a,T> + 'a>) -> Any<'a,T> {
        Any {
            matcher: matcher,
            next: Some(Box::new(self))
        }
    }
}

impl<'a,T:'a> Matcher<'a,T> for Any<'a,T> {
    fn check(&self, actual: &'a T) -> MatchResult {
        match self.matcher.check(actual) {
            MatchResult::Matched {..} => MatchResult::Matched { name: "any_of".to_owned() },
            x@MatchResult::Failed {..} => match self.next {
                None => x,
                Some(ref next) => next.check(actual)
            }
        }
    }
}
<commit_msg>add examples to the docs of matcher combinators<commit_after>/* Copyright 2017 Christopher Bacher
 *
 * 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.
 */

use super::super::*;

/// Takes a list of matchers for the same type combines them conjunctively.
///
/// #Examples
/// ```rust
/// # #[macro_use] extern crate galvanic_assert;
/// use galvanic_assert::matchers::*;
/// # fn main() {
/// assert_that!(&(1+1), all_of![gt(0), lt(5), not(eq(3))]);
/// # }
#[macro_export]
macro_rules! all_of {
    ( $matcher: expr ) => {
        Box::new(All::of($matcher))
    };
    ( $matcher: expr, $($matchers: expr),* ) => {
        Box::new(All::of($matcher)$(.and($matchers))*)
    };
}

/// A `Matcher` struct which joins multiple `Matcher`s conjunctively.
///
/// Use `of()` to create a new `Matcher` and `and()` to add further `Matcher`s.
///
/// #Examples
/// ```rust
/// # #[macro_use] extern crate galvanic_assert;
/// use galvanic_assert::matchers::*;
/// # fn main() {
/// assert_that!(&(1+1), All::of(gt(0)).and(lt(5)).and(not(eq(3))));
/// # }
pub struct All<'a, T:'a> {
    pub matcher: Box<Matcher<'a,T> + 'a>,
    pub next: Option<Box<All<'a,T>>>
}

impl<'a,T:'a> All<'a, T> {
    /// Creates a new conjunctive `Matcher` starting with the given `Matcher`.
    pub fn of(matcher: Box<Matcher<'a,T> + 'a>) -> All<'a,T> {
        All {
            matcher: matcher,
            next: None
        }
    }

    /// Adds the given `Matcher` conjunctively.
    pub fn and(self, matcher: Box<Matcher<'a,T> + 'a>) -> All<'a,T> {
        All {
            matcher: matcher,
            next: Some(Box::new(self))
        }
    }
}

impl<'a,T:'a> Matcher<'a,T> for All<'a,T> {
    fn check(&self, actual: &'a T) -> MatchResult {
        match self.matcher.check(actual) {
            x@MatchResult::Matched {..} => {
                match self.next {
                    None => x,
                    Some(ref next) => next.check(actual)
                }
            },
            x@MatchResult::Failed {..} => x
        }
    }
}

/// Takes a list of matchers for the same type combines them disjunctively.
///
/// #Examples
/// ```rust
/// # #[macro_use] extern crate galvanic_assert;
/// use galvanic_assert::matchers::*;
/// # fn main() {
/// assert_that!(&(1+1), any_of![lt(0), gt(5), not(eq(3))]);
/// # }
#[macro_export]
macro_rules! any_of {
    ( $matcher: expr ) => {
        Box::new(Any::of($matcher))
    };
    ( $matcher: expr, $($matchers: expr),* ) => {
        Box::new(Any::of($matcher)$(.or($matchers))*)
    };
}

/// A `Matcher` struct which joins multiple `Matcher`s disjunctively.
///
/// Use `of()` to create a new `Matcher` and `or()` to add further `Matcher`s.
///
/// #Examples
/// ```rust
/// # #[macro_use] extern crate galvanic_assert;
/// use galvanic_assert::matchers::*;
/// # fn main() {
/// assert_that!(&(1+1), Any::of(lt(0)).or(gt(5)).or(not(eq(3))));
/// # }
pub struct Any<'a, T:'a> {
    pub matcher: Box<Matcher<'a,T> + 'a>,
    pub next: Option<Box<Any<'a,T>>>
}

impl<'a,T:'a> Any<'a, T> {
    /// Creates a new conjunctive `Matcher` starting with the given `Matcher`.
    pub fn of(matcher: Box<Matcher<'a,T> + 'a>) -> Any<'a,T> {
        Any {
            matcher: matcher,
            next: None
        }
    }

    /// Adds the given `Matcher` disjunctively.
    pub fn or(self, matcher: Box<Matcher<'a,T> + 'a>) -> Any<'a,T> {
        Any {
            matcher: matcher,
            next: Some(Box::new(self))
        }
    }
}

impl<'a,T:'a> Matcher<'a,T> for Any<'a,T> {
    fn check(&self, actual: &'a T) -> MatchResult {
        match self.matcher.check(actual) {
            MatchResult::Matched {..} => MatchResult::Matched { name: "any_of".to_owned() },
            x@MatchResult::Failed {..} => match self.next {
                None => x,
                Some(ref next) => next.check(actual)
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate tiler;
use std::fs::create_dir_all;

fn main() {
    let cache_path = "./examples_data/cache/";
    // The dataset must :
    //  - use the WGS84 coordinate system
    //  - have its longitude and latitiude sorted in ascending order
    //  - have its main variable expressed in (lat, lon)
    let dataset_path = "./examples_data/wind_magnitude_reduced.nc";

    println!("Openning dataset {}", &dataset_path);
    let dataset = tiler::Dataset::new(
        "latitude",
        "longitude",
        "wind_magnitude",
        dataset_path
    ).unwrap();

    let (value_min, value_max) = (0., 20.);
    println!("Creating a RdYlBu_r renderer");
    let renderer = tiler::Renderer::from_dataset(
        dataset,        // input dataset
        tiler::Scale::Linear { // Use a linear range of color
            min: value_min, // minimum value of the colorbar
            max: value_max  // maximum value of the colorbar
        },
        tiler::ColorMap::RdYlBu_r   // Red Yellow Blue colormap
    ).unwrap();

    let mut max: u16 = 2;
    // iter Zoom level
    for z in 0..5 {
        println!("Rendering zoom level {}", &z);
        // iter X tile coordinates
        for x in 0..max {
            let tile_dir = format!("{}/{}/{}", &cache_path, &z, &x);
            match create_dir_all(&tile_dir) {
                Ok(_) => {
                    // iter Y tile coordinates
                    for y in 0..max {
                        // create a Tile using x, y, z
                        let tile = tiler::Tile {x: x, y:y, z:z };
                        let tile_path = format!("{}/{}.png", &tile_dir, &y);

                        // render it into a png
                        if let Ok(img) = renderer.render_tile(&tile) {
                            // save it
                            img.save(&tile_path);
                        }
                    }
                },
                Err(_) => { continue; }
            }
        }
        max *= 2;
    }
    println!("You show see the result by opening ./examples_data/viewer.html with your browser.");
}
<commit_msg>Fix exemple<commit_after>extern crate tiler;
use std::fs::create_dir_all;

fn main() {
    let cache_path = "./examples_data/cache/";
    // The dataset must :
    //  - use the WGS84 coordinate system
    //  - have its longitude and latitiude sorted in ascending order
    //  - have its main variable expressed in (lat, lon)
    let dataset_path = "./examples_data/wind_magnitude_reduced.nc";

    println!("Openning dataset {}", &dataset_path);
    let dataset = tiler::Dataset::new(
        "latitude",
        "longitude",
        "wind_magnitude",
        dataset_path
    ).unwrap();

    let (value_min, value_max) = (0., 20.);
    println!("Creating a RdYlBu_r renderer");
    let renderer = tiler::Renderer::from_dataset(
        dataset,        // input dataset
        tiler::Scale::Linear { // Use a linear range of color
            min: value_min, // minimum value of the colorbar
            max: value_max  // maximum value of the colorbar
        },
        tiler::ColorMap::RdYlBu_r   // Red Yellow Blue colormap
    ).unwrap();

    let mut max: u32 = 2;
    // iter Zoom level
    for z in 0..5 {
        println!("Rendering zoom level {}", &z);
        // iter X tile coordinates
        for x in 0..max {
            let tile_dir = format!("{}/{}/{}", &cache_path, &z, &x);
            match create_dir_all(&tile_dir) {
                Ok(_) => {
                    // iter Y tile coordinates
                    for y in 0..max {
                        // create a Tile using x, y, z
                        let tile = tiler::Tile {x: x, y:y, z:z };
                        let tile_path = format!("{}/{}.png", &tile_dir, &y);

                        // render it into a png
                        if let Ok(img) = renderer.render_tile(&tile) {
                            // save it
                            img.save(&tile_path);
                        }
                    }
                },
                Err(_) => { continue; }
            }
        }
        max *= 2;
    }
    println!("You show see the result by opening ./examples_data/viewer.html with your browser.");
}
<|endoftext|>


<commit_before>extern crate "pkg-config" as pkg_config;

use std::os;

fn main () {
    let target = os::getenv("TARGET").unwrap();
    if target.ends_with("-apple-darwin") {
        // Use libosxfuse on OS X
        pkg_config::find_library("osxfuse").unwrap();
    } else if target.ends_with("-unknown-linux-gnu") || target.ends_with("-unknown-freebsd") {
        // Use libfuse on Linux and FreeBSD
        pkg_config::find_library("fuse").unwrap();
    } else {
        // Fail on unsupported platforms (e.g. Windows)
        panic!("Unsupported target platform");
    }
}
<commit_msg>Also allow unstable features in build script<commit_after>#![allow(unstable)]

extern crate "pkg-config" as pkg_config;

use std::os;

fn main () {
    let target = os::getenv("TARGET").unwrap();
    if target.ends_with("-apple-darwin") {
        // Use libosxfuse on OS X
        pkg_config::find_library("osxfuse").unwrap();
    } else if target.ends_with("-unknown-linux-gnu") || target.ends_with("-unknown-freebsd") {
        // Use libfuse on Linux and FreeBSD
        pkg_config::find_library("fuse").unwrap();
    } else {
        // Fail on unsupported platforms (e.g. Windows)
        panic!("Unsupported target platform");
    }
}
<|endoftext|>


<commit_before>fn main() {
    #[cfg(any(target_os = "macos", target_os = "ios"))]
    println!("cargo:rustc-cfg=apple");

    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    println!("cargo:rustc-cfg=freebsdlike");

    #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "bitrig"))]
    println!("cargo:rust-cfg=netbsdlike");
}
<commit_msg>fix cross build<commit_after>use std::env;

fn main() {
    match env::var("CARGO_CFG_TARGET_OS").as_ref().map(String::as_str) {
        Ok("macos") | Ok("ios") => println!("cargo:rustc-cfg=apple"),
        Ok("freebsd") | Ok("dragonfly") => println!("cargo:rustc-cfg=freebsdlike"),
        Ok("openbsd") | Ok("netbsd") | Ok("bitrig") => println!("cargo:rust-cfg=netbsdlike"),
        _ => ()
    }
}
<|endoftext|>


<commit_before>#![feature(io)]

use std::old_io::Command;
use std::old_io::process::{InheritFd, Ignored};

fn main() {
    let mut cmd = Command::new("make");
    cmd.arg("cargo-prep");
    println!("running: {:?}", cmd);
    assert!(cmd.stdin(Ignored)
               .stdout(InheritFd(1))
               .stderr(InheritFd(2))
               .status()
               .unwrap()
               .success());
}
<commit_msg>Upgrade cargo build script to the new std::process<commit_after>#![feature(process)]

use std::process::{Command,Stdio};

fn main() {
    let mut cmd = Command::new("make");
    cmd.arg("cargo-prep");
    println!("running: {:?}", cmd);
    assert!(cmd.stdin(Stdio::null())
               .status()
               .unwrap()
               .success());
}
<|endoftext|>


<commit_before>fn main() {
    if cfg!(r#static) {
        let static_path = std::env::var("ODBC_SYS_STATIC_PATH").unwrap_or("/usr/lib".to_string());
        println!("cargo:rerun-if-env-changed=ODBC_SYS_STATIC_PATH");
        println!("cargo:rustc-link-search=native={}", static_path);
        println!("cargo:rustc-link-lib=static=odbc");
    }

    if cfg!(target_os = "macos") {
        // if we're on Mac OS X we'll kindly add DYLD_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_paths) = option_env!("DYLD_LIBRARY_PATH") {
            print_paths(dyld_paths);
        }
        // if we're on Mac OS X we'll kindly add DYLD_FALLBACK_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_fallback_paths) = option_env!("DYLD_FALLBACK_LIBRARY_PATH") {
            print_paths(dyld_fallback_paths);
        }
    }
}

fn print_paths(paths: &str) {
    for path in paths.split(':').filter(|x| !x.is_empty()) {
        println!("cargo:rustc-link-search=native={}", path)
    }
}
<commit_msg>Correct static build feature detection in build.rs<commit_after>fn main() {
    if std::env::var("CARGO_FEATURE_STATIC").is_ok() {
        let static_path = std::env::var("ODBC_SYS_STATIC_PATH").unwrap_or("/usr/lib".to_string());
        println!("cargo:rerun-if-env-changed=ODBC_SYS_STATIC_PATH");
        println!("cargo:rustc-link-search=native={}", static_path);
        println!("cargo:rustc-link-lib=static=odbc");
    }

    if cfg!(target_os = "macos") {
        // if we're on Mac OS X we'll kindly add DYLD_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_paths) = option_env!("DYLD_LIBRARY_PATH") {
            print_paths(dyld_paths);
        }
        // if we're on Mac OS X we'll kindly add DYLD_FALLBACK_LIBRARY_PATH to rustc's
        // linker search path
        if let Some(dyld_fallback_paths) = option_env!("DYLD_FALLBACK_LIBRARY_PATH") {
            print_paths(dyld_fallback_paths);
        }
    }
}

fn print_paths(paths: &str) {
    for path in paths.split(':').filter(|x| !x.is_empty()) {
        println!("cargo:rustc-link-search=native={}", path)
    }
}
<|endoftext|>


<commit_before>extern crate gcc;

#[cfg(windows)]
fn opencv_include() -> String {
    if let Ok(dir) = std::env::var("OPENCV_DIR") {
        format!("{}\\include", dir)
    } else {
        eprint!("%OPENCV_DIR% is not set properly.");
        std::process::exit(0x0100);
    }
}

#[cfg(windows)]
fn opencv_link() {
    if let Ok(dir) = std::env::var("OPENCV_LIB") {
        if let Ok(mut files) = std::fs::read_dir(&dir) {
            let opencv_world_entry = files
                .filter_map(|entry| entry.ok())
                .find(|entry| {
                    let file_name = entry.file_name().to_string_lossy().into_owned();
                    (file_name.starts_with("opencv_world") || file_name.starts_with("libopencv_world")) && !file_name.ends_with("d.lib")
                });
            if let Some(opencv_world) = opencv_world_entry {
                let opencv_world = opencv_world.file_name();
                let opencv_world = opencv_world.into_string().unwrap();
                let opencv_world_without_extension = opencv_world.trim_right_matches(|c: char| !c.is_numeric());
                println!("cargo:rustc-link-search=native={}", dir);
                println!("cargo:rustc-link-lib={}", opencv_world_without_extension);
                return;
            }
        }
        eprint!("Cannot find opencv_world file in provided %OPENCV_DIR%");
        std::process::exit(0x0100);
    } else {
        eprint!("%OPENCV_DIR% is not set properly.");
        std::process::exit(0x0100);
    }
}

#[cfg(unix)]
fn opencv_include() -> &'static str {
    "/usr/local/include"
}

#[cfg(unix)]
fn opencv_link() {
    println!("cargo:rustc-link-search=native=/usr/local/lib");
    println!("cargo:rustc-link-lib=opencv_core");
    println!("cargo:rustc-link-lib=opencv_imgcodecs");
    println!("cargo:rustc-link-lib=opencv_imgproc");
    println!("cargo:rustc-link-lib=opencv_highgui");
    println!("cargo:rustc-link-lib=opencv_videoio");
    println!("cargo:rustc-link-lib=opencv_objdetect");
    println!("cargo:rustc-link-lib=opencv_video");

    if cfg!(feature = "gpu") {
        println!("cargo:rustc-link-lib=opencv_cudaobjdetect");
    }
}

fn main() {
    let mut opencv_config = gcc::Build::new();
    opencv_config
        .cpp(true)
        .file("native/opencv-wrapper.cc")
        .file("native/utils.cc")
        .include("native")
        .include(opencv_include())
        .flag("--std=c++11");

    if cfg!(feature = "gpu") {
        opencv_config.file("native/opencv-gpu.cc");
    }

    opencv_config.compile("libopencv-wrapper.a");
    opencv_link();
}
<commit_msg>Review fix<commit_after>extern crate gcc;

#[cfg(windows)]
fn opencv_include() -> String {
    if let Ok(dir) = std::env::var("OPENCV_DIR") {
        format!("{}\\include", dir)
    } else {
        eprint!("%OPENCV_DIR% is not set properly.");
        std::process::exit(0x0100);
    }
}

#[cfg(windows)]
fn opencv_link() {
    if let Ok(dir) = std::env::var("OPENCV_LIB") {
        if let Ok(mut files) = std::fs::read_dir(&dir) {
            let opencv_world_entry = files
                .filter_map(|entry| entry.ok())
                .find(|entry| {
                    let file_name = entry.file_name().to_string_lossy().into_owned();
                    (file_name.starts_with("opencv_world") || file_name.starts_with("libopencv_world")) && !file_name.ends_with("d.lib")
                });
            if let Some(opencv_world) = opencv_world_entry {
                let opencv_world = opencv_world.file_name();
                let opencv_world = opencv_world.into_string().unwrap();
                let opencv_world_without_extension = opencv_world.trim_right_matches(|c: char| !c.is_numeric()); // we expect filename to be something like 'open_world340.lib' or 'open_world.340.dll.a', so we just consider everything after the version number is an extension
                println!("cargo:rustc-link-search=native={}", dir);
                println!("cargo:rustc-link-lib={}", opencv_world_without_extension);
                return;
            }
        }
        eprint!("Cannot find opencv_world file in provided %OPENCV_DIR%");
        std::process::exit(0x0100);
    } else {
        eprint!("%OPENCV_DIR% is not set properly.");
        std::process::exit(0x0100);
    }
}

#[cfg(unix)]
fn opencv_include() -> &'static str {
    "/usr/local/include"
}

#[cfg(unix)]
fn opencv_link() {
    println!("cargo:rustc-link-search=native=/usr/local/lib");
    println!("cargo:rustc-link-lib=opencv_core");
    println!("cargo:rustc-link-lib=opencv_imgcodecs");
    println!("cargo:rustc-link-lib=opencv_imgproc");
    println!("cargo:rustc-link-lib=opencv_highgui");
    println!("cargo:rustc-link-lib=opencv_videoio");
    println!("cargo:rustc-link-lib=opencv_objdetect");
    println!("cargo:rustc-link-lib=opencv_video");

    if cfg!(feature = "gpu") {
        println!("cargo:rustc-link-lib=opencv_cudaobjdetect");
    }
}

fn main() {
    let mut opencv_config = gcc::Build::new();
    opencv_config
        .cpp(true)
        .file("native/opencv-wrapper.cc")
        .file("native/utils.cc")
        .include("native")
        .include(opencv_include())
        .flag("--std=c++11");

    if cfg!(feature = "gpu") {
        opencv_config.file("native/opencv-gpu.cc");
    }

    opencv_config.compile("libopencv-wrapper.a");
    opencv_link();
}
<|endoftext|>


<commit_before>extern crate daemonize;

use std::fs::File;
use daemonize::Daemonize;

const STDERR_FILE: &str = "./stderr.txt";
const PID_FILE: &str = "./rshanghai.pid";

/// Create an stderr redirect file, and do daemonize.
/// If succeeded, the main process will exit successfully and
/// the forked child process continues to run as a daemon process.
/// If failed, the main process will exit(1).
fn daemon() {
    let stderr = File::create(STDERR_FILE);
    if let Err(e) = stderr {
        eprintln!("Open {} error: {}", STDERR_FILE, e);
        std::process::exit(1);
    }
    let stderr = stderr.unwrap();

    let daemonize = Daemonize::new()
        .pid_file(PID_FILE)
        //.chown_pid_file(true)
        .working_directory(".")
        //.user("nobody")
        //.group("daemon")
        //.stdout(stdout)
        .stderr(stderr);

    if let Err(e) = daemonize.start() {
        eprintln!("Daemonize error: {}", e);
        std::process::exit(1);
    }
}

fn main() {
    daemon();
}
<commit_msg>Japanese comment<commit_after>extern crate daemonize;

use std::fs::File;
use daemonize::Daemonize;

const STDERR_FILE: &str = "./stderr.txt";
const PID_FILE: &str = "./rshanghai.pid";

/// stderr をリダイレクトし、デーモン化する。
/// stderr 用のファイルオープンに失敗したら exit(1) する。
/// デーモン化に失敗したら exit(1) する。
/// 成功した場合は元の親プロセスは正常終了し、子プロセスが以降の処理を続行する。
fn daemon() {
    let stderr = File::create(STDERR_FILE);
    if let Err(e) = stderr {
        eprintln!("Open {} error: {}", STDERR_FILE, e);
        std::process::exit(1);
    }
    let stderr = stderr.unwrap();

    let daemonize = Daemonize::new()
        .pid_file(PID_FILE)
        //.chown_pid_file(true)
        .working_directory(".")
        //.user("nobody")
        //.group("daemon")
        //.stdout(stdout)
        .stderr(stderr);

    if let Err(e) = daemonize.start() {
        eprintln!("Daemonize error: {}", e);
        std::process::exit(1);
    }
}

fn main() {
    daemon();
}
<|endoftext|>