<commit_before>use std::cell::Cell;
use std::cmp::max;

use cairo::{self, ImageSurface, MatrixTrait};
use cssparser;
use nalgebra::Vector3;

use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use filters::{
    context::{FilterContext, FilterOutput, FilterResult},
    light::{
        bottom_left_normal,
        bottom_right_normal,
        bottom_row_normal,
        interior_normal,
        left_column_normal,
        light_source::LightSource,
        right_column_normal,
        top_left_normal,
        top_right_normal,
        top_row_normal,
    },
    Filter,
    FilterError,
    PrimitiveWithInput,
};
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use parsers;
use property_bag::PropertyBag;
use state::ColorInterpolationFilters;
use surface_utils::{
    shared_surface::{SharedImageSurface, SurfaceType},
    ImageSurfaceDataExt,
    Pixel,
};
use util::clamp;

/// Properties specific to either diffuse or specular lighting.
enum Data {
    Diffuse {
        diffuse_constant: Cell<f64>,
    },
    Specular {
        specular_constant: Cell<f64>,
        specular_exponent: Cell<f64>,
    },
}

/// The `feDiffuseLighting` and `feSpecularLighting` filter primitives.
pub struct Lighting {
    base: PrimitiveWithInput,
    surface_scale: Cell<f64>,
    kernel_unit_length: Cell<Option<(f64, f64)>>,
    data: Data,
}

impl Lighting {
    /// Constructs a new diffuse `Lighting` with empty properties.
    #[inline]
    pub fn new_diffuse() -> Lighting {
        Lighting {
            data: Data::Diffuse {
                diffuse_constant: Cell::new(1.0),
            },
            ..Self::default()
        }
    }

    /// Constructs a new specular `Lighting` with empty properties.
    #[inline]
    pub fn new_specular() -> Lighting {
        Lighting {
            data: Data::Specular {
                specular_constant: Cell::new(1.0),
                specular_exponent: Cell::new(1.0),
            },
            ..Self::default()
        }
    }
}

impl NodeTrait for Lighting {
    fn set_atts(
        &self,
        node: &RsvgNode,
        handle: *const RsvgHandle,
        pbag: &PropertyBag,
    ) -> NodeResult {
        self.base.set_atts(node, handle, pbag)?;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::SurfaceScale => self
                    .surface_scale
                    .set(parsers::number(value).map_err(|err| NodeError::parse_error(attr, err))?),
                Attribute::KernelUnitLength => self.kernel_unit_length.set(Some(
                    parsers::number_optional_number(value)
                        .map_err(|err| NodeError::parse_error(attr, err))
                        .and_then(|(x, y)| {
                            if x > 0.0 && y > 0.0 {
                                Ok((x, y))
                            } else {
                                Err(NodeError::value_error(
                                    attr,
                                    "kernelUnitLength can't be less or equal to zero",
                                ))
                            }
                        })?,
                )),
                _ => (),
            }
        }

        match self.data {
            Data::Diffuse {
                ref diffuse_constant,
            } => {
                for (_key, attr, value) in pbag.iter() {
                    match attr {
                        Attribute::DiffuseConstant => diffuse_constant.set(
                            parsers::number(value)
                                .map_err(|err| NodeError::parse_error(attr, err))
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "diffuseConstant can't be negative",
                                        ))
                                    }
                                })?,
                        ),
                        _ => (),
                    }
                }
            }
            Data::Specular {
                ref specular_constant,
                ref specular_exponent,
            } => {
                for (_key, attr, value) in pbag.iter() {
                    match attr {
                        Attribute::SpecularConstant => specular_constant.set(
                            parsers::number(value)
                                .map_err(|err| NodeError::parse_error(attr, err))
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularConstant can't be negative",
                                        ))
                                    }
                                })?,
                        ),
                        Attribute::SpecularExponent => specular_exponent.set(
                            parsers::number(value)
                                .map_err(|err| NodeError::parse_error(attr, err))
                                .and_then(|x| {
                                    if x >= 1.0 && x <= 128.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularExponent should be between 1.0 and 128.0",
                                        ))
                                    }
                                })?,
                        ),
                        _ => (),
                    }
                }
            }
        }

        Ok(())
    }
}

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

        let scale = self
            .kernel_unit_length
            .get()
            .map(|(dx, dy)| ctx.paffine().transform_distance(dx, dy));

        let surface_scale = self.surface_scale.get();

        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();
        let lighting_color = match values.lighting_color.0 {
            cssparser::Color::CurrentColor => values.color.0,
            cssparser::Color::RGBA(rgba) => rgba,
        };

        let mut light_sources = node
            .children()
            .rev()
            .filter(|c| c.get_type() == NodeType::LightSource);
        let light_source = light_sources.next();
        if light_source.is_none() || light_sources.next().is_some() {
            return Err(FilterError::InvalidLightSourceCount);
        }

        let light_source = light_source.unwrap();
        let light_source = light_source.get_impl::<LightSource>().unwrap();

        let mut input_surface = input.surface().clone();

        if let Some((ox, oy)) = scale {
            // Scale the input surface to match kernel_unit_length.
            let (new_surface, new_bounds) = input_surface.scale(bounds, 1.0 / ox, 1.0 / oy)?;

            input_surface = new_surface;
            bounds = new_bounds;
        }

        // Check if the surface is too small for normal computation. This case is unspecified;
        // WebKit doesn't render anything in this case.
        if bounds.x1 < bounds.x0 + 2 || bounds.y1 < bounds.y0 + 2 {
            return Err(FilterError::LightingInputTooSmall);
        }

        let (ox, oy) = scale.unwrap_or((1.0, 1.0));

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

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

            let mut compute_output_pixel = |x, y, normal: Vector3<f64>| {
                let pixel = input_surface.get_pixel(x, y);

                let scaled_x = f64::from(x) * ox;
                let scaled_y = f64::from(y) * oy;
                let z = f64::from(pixel.a) / 255.0 * surface_scale;
                let light_vector = light_source.vector(scaled_x, scaled_y, z, ctx);
                let light_color = light_source.color(lighting_color, light_vector, ctx);

                let output_pixel = match self.data {
                    Data::Diffuse {
                        ref diffuse_constant,
                    } => {
                        let n_dot_l = normal.dot(&light_vector);
                        let compute = |x| {
                            clamp(diffuse_constant.get() * n_dot_l * f64::from(x), 0.0, 255.0)
                                .round() as u8
                        };

                        Pixel {
                            r: compute(light_color.red),
                            g: compute(light_color.green),
                            b: compute(light_color.blue),
                            a: 255,
                        }.premultiply()
                    }
                    Data::Specular {
                        ref specular_constant,
                        ref specular_exponent,
                    } => {
                        let mut h = light_vector + Vector3::new(0.0, 0.0, 1.0);
                        let _ = h.try_normalize_mut(0.0);

                        let n_dot_h = normal.dot(&h);
                        let factor =
                            specular_constant.get() * n_dot_h.powf(specular_exponent.get());
                        let compute = |x| clamp(factor * f64::from(x), 0.0, 255.0).round() as u8;

                        let mut output_pixel = Pixel {
                            r: compute(light_color.red),
                            g: compute(light_color.green),
                            b: compute(light_color.blue),
                            a: 0,
                        };
                        output_pixel.a = max(max(output_pixel.r, output_pixel.g), output_pixel.b);
                        output_pixel
                    }
                };

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

            // Top left.
            compute_output_pixel(
                bounds.x0 as u32,
                bounds.y0 as u32,
                top_left_normal(&input_surface, bounds, surface_scale),
            );

            // Top right.
            compute_output_pixel(
                bounds.x1 as u32 - 1,
                bounds.y0 as u32,
                top_right_normal(&input_surface, bounds, surface_scale),
            );

            // Bottom left.
            compute_output_pixel(
                bounds.x0 as u32,
                bounds.y1 as u32 - 1,
                bottom_left_normal(&input_surface, bounds, surface_scale),
            );

            // Bottom right.
            compute_output_pixel(
                bounds.x1 as u32 - 1,
                bounds.y1 as u32 - 1,
                bottom_right_normal(&input_surface, bounds, surface_scale),
            );

            if bounds.x1 - bounds.x0 >= 3 {
                // Top row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        x,
                        bounds.y0 as u32,
                        top_row_normal(&input_surface, bounds, x, surface_scale),
                    );
                }

                // Bottom row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        x,
                        bounds.y1 as u32 - 1,
                        bottom_row_normal(&input_surface, bounds, x, surface_scale),
                    );
                }
            }

            if bounds.y1 - bounds.y0 >= 3 {
                // Left column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        bounds.x0 as u32,
                        y,
                        left_column_normal(&input_surface, bounds, y, surface_scale),
                    );
                }

                // Right column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        bounds.x1 as u32 - 1,
                        y,
                        right_column_normal(&input_surface, bounds, y, surface_scale),
                    );
                }
            }

            if bounds.x1 - bounds.x0 >= 3 && bounds.y1 - bounds.y0 >= 3 {
                // Interior pixels.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                        compute_output_pixel(
                            x,
                            y,
                            interior_normal(&input_surface, bounds, x, y, surface_scale),
                        );
                    }
                }
            }
        }

        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();
        // The generated color values are in the color space determined by
        // color-interpolation-filters.
        let surface_type =
            if values.color_interpolation_filters == ColorInterpolationFilters::LinearRgb {
                SurfaceType::LinearRgb
            } else {
                SurfaceType::SRgb
            };
        let mut output_surface = SharedImageSurface::new(output_surface, surface_type)?;

        if let Some((ox, oy)) = scale {
            // Scale the output surface back.
            output_surface = output_surface.scale_to(
                ctx.source_graphic().width(),
                ctx.source_graphic().height(),
                original_bounds,
                ox,
                oy,
            )?;

            bounds = original_bounds;
        }

        Ok(FilterResult {
            name: self.base.result.borrow().clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

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

impl Default for Lighting {
    #[inline]
    fn default() -> Self {
        Self {
            base: PrimitiveWithInput::new::<Self>(),
            surface_scale: Cell::new(1.0),
            kernel_unit_length: Cell::new(None),

            // The data field is unused in this case.
            data: Data::Diffuse {
                diffuse_constant: Cell::new(1.0),
            },
        }
    }
}
<commit_msg>Factor out some common code in lighting.rs<commit_after>use std::cell::Cell;
use std::cmp::max;

use cairo::{self, ImageSurface, MatrixTrait};
use cssparser;
use nalgebra::Vector3;

use attributes::Attribute;
use drawing_ctx::DrawingCtx;
use error::NodeError;
use filters::{
    context::{FilterContext, FilterOutput, FilterResult},
    light::{
        bottom_left_normal,
        bottom_right_normal,
        bottom_row_normal,
        interior_normal,
        left_column_normal,
        light_source::LightSource,
        right_column_normal,
        top_left_normal,
        top_right_normal,
        top_row_normal,
    },
    Filter,
    FilterError,
    PrimitiveWithInput,
};
use handle::RsvgHandle;
use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use parsers;
use property_bag::PropertyBag;
use state::ColorInterpolationFilters;
use surface_utils::{
    shared_surface::{SharedImageSurface, SurfaceType},
    ImageSurfaceDataExt,
    Pixel,
};
use util::clamp;

/// Properties specific to either diffuse or specular lighting.
enum Data {
    Diffuse {
        diffuse_constant: Cell<f64>,
    },
    Specular {
        specular_constant: Cell<f64>,
        specular_exponent: Cell<f64>,
    },
}

/// The `feDiffuseLighting` and `feSpecularLighting` filter primitives.
pub struct Lighting {
    base: PrimitiveWithInput,
    surface_scale: Cell<f64>,
    kernel_unit_length: Cell<Option<(f64, f64)>>,
    data: Data,
}

impl Lighting {
    /// Constructs a new diffuse `Lighting` with empty properties.
    #[inline]
    pub fn new_diffuse() -> Lighting {
        Lighting {
            data: Data::Diffuse {
                diffuse_constant: Cell::new(1.0),
            },
            ..Self::default()
        }
    }

    /// Constructs a new specular `Lighting` with empty properties.
    #[inline]
    pub fn new_specular() -> Lighting {
        Lighting {
            data: Data::Specular {
                specular_constant: Cell::new(1.0),
                specular_exponent: Cell::new(1.0),
            },
            ..Self::default()
        }
    }
}

impl NodeTrait for Lighting {
    fn set_atts(
        &self,
        node: &RsvgNode,
        handle: *const RsvgHandle,
        pbag: &PropertyBag,
    ) -> NodeResult {
        self.base.set_atts(node, handle, pbag)?;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::SurfaceScale => self
                    .surface_scale
                    .set(parsers::number(value).map_err(|err| NodeError::parse_error(attr, err))?),
                Attribute::KernelUnitLength => self.kernel_unit_length.set(Some(
                    parsers::number_optional_number(value)
                        .map_err(|err| NodeError::parse_error(attr, err))
                        .and_then(|(x, y)| {
                            if x > 0.0 && y > 0.0 {
                                Ok((x, y))
                            } else {
                                Err(NodeError::value_error(
                                    attr,
                                    "kernelUnitLength can't be less or equal to zero",
                                ))
                            }
                        })?,
                )),
                _ => (),
            }
        }

        match self.data {
            Data::Diffuse {
                ref diffuse_constant,
            } => {
                for (_key, attr, value) in pbag.iter() {
                    match attr {
                        Attribute::DiffuseConstant => diffuse_constant.set(
                            parsers::number(value)
                                .map_err(|err| NodeError::parse_error(attr, err))
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "diffuseConstant can't be negative",
                                        ))
                                    }
                                })?,
                        ),
                        _ => (),
                    }
                }
            }
            Data::Specular {
                ref specular_constant,
                ref specular_exponent,
            } => {
                for (_key, attr, value) in pbag.iter() {
                    match attr {
                        Attribute::SpecularConstant => specular_constant.set(
                            parsers::number(value)
                                .map_err(|err| NodeError::parse_error(attr, err))
                                .and_then(|x| {
                                    if x >= 0.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularConstant can't be negative",
                                        ))
                                    }
                                })?,
                        ),
                        Attribute::SpecularExponent => specular_exponent.set(
                            parsers::number(value)
                                .map_err(|err| NodeError::parse_error(attr, err))
                                .and_then(|x| {
                                    if x >= 1.0 && x <= 128.0 {
                                        Ok(x)
                                    } else {
                                        Err(NodeError::value_error(
                                            attr,
                                            "specularExponent should be between 1.0 and 128.0",
                                        ))
                                    }
                                })?,
                        ),
                        _ => (),
                    }
                }
            }
        }

        Ok(())
    }
}

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

        let scale = self
            .kernel_unit_length
            .get()
            .map(|(dx, dy)| ctx.paffine().transform_distance(dx, dy));

        let surface_scale = self.surface_scale.get();

        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();
        let lighting_color = match values.lighting_color.0 {
            cssparser::Color::CurrentColor => values.color.0,
            cssparser::Color::RGBA(rgba) => rgba,
        };

        let mut light_sources = node
            .children()
            .rev()
            .filter(|c| c.get_type() == NodeType::LightSource);
        let light_source = light_sources.next();
        if light_source.is_none() || light_sources.next().is_some() {
            return Err(FilterError::InvalidLightSourceCount);
        }

        let light_source = light_source.unwrap();
        let light_source = light_source.get_impl::<LightSource>().unwrap();

        let mut input_surface = input.surface().clone();

        if let Some((ox, oy)) = scale {
            // Scale the input surface to match kernel_unit_length.
            let (new_surface, new_bounds) = input_surface.scale(bounds, 1.0 / ox, 1.0 / oy)?;

            input_surface = new_surface;
            bounds = new_bounds;
        }

        // Check if the surface is too small for normal computation. This case is unspecified;
        // WebKit doesn't render anything in this case.
        if bounds.x1 < bounds.x0 + 2 || bounds.y1 < bounds.y0 + 2 {
            return Err(FilterError::LightingInputTooSmall);
        }

        let (ox, oy) = scale.unwrap_or((1.0, 1.0));

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

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

            let mut compute_output_pixel = |x, y, normal: Vector3<f64>| {
                let pixel = input_surface.get_pixel(x, y);

                let scaled_x = f64::from(x) * ox;
                let scaled_y = f64::from(y) * oy;
                let z = f64::from(pixel.a) / 255.0 * surface_scale;
                let light_vector = light_source.vector(scaled_x, scaled_y, z, ctx);
                let light_color = light_source.color(lighting_color, light_vector, ctx);

                let factor = match self.data {
                    Data::Diffuse {
                        ref diffuse_constant,
                    } => {
                        let n_dot_l = normal.dot(&light_vector);
                        diffuse_constant.get() * n_dot_l
                    }
                    Data::Specular {
                        ref specular_constant,
                        ref specular_exponent,
                    } => {
                        let mut h = light_vector + Vector3::new(0.0, 0.0, 1.0);
                        let _ = h.try_normalize_mut(0.0);

                        let n_dot_h = normal.dot(&h);
                        specular_constant.get() * n_dot_h.powf(specular_exponent.get())
                    }
                };

                let compute = |x| clamp(factor * f64::from(x), 0.0, 255.0).round() as u8;

                let mut output_pixel = Pixel {
                    r: compute(light_color.red),
                    g: compute(light_color.green),
                    b: compute(light_color.blue),
                    a: 255,
                };

                if let Data::Specular { .. } = self.data {
                    output_pixel.a = max(max(output_pixel.r, output_pixel.g), output_pixel.b);
                }

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

            // Top left.
            compute_output_pixel(
                bounds.x0 as u32,
                bounds.y0 as u32,
                top_left_normal(&input_surface, bounds, surface_scale),
            );

            // Top right.
            compute_output_pixel(
                bounds.x1 as u32 - 1,
                bounds.y0 as u32,
                top_right_normal(&input_surface, bounds, surface_scale),
            );

            // Bottom left.
            compute_output_pixel(
                bounds.x0 as u32,
                bounds.y1 as u32 - 1,
                bottom_left_normal(&input_surface, bounds, surface_scale),
            );

            // Bottom right.
            compute_output_pixel(
                bounds.x1 as u32 - 1,
                bounds.y1 as u32 - 1,
                bottom_right_normal(&input_surface, bounds, surface_scale),
            );

            if bounds.x1 - bounds.x0 >= 3 {
                // Top row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        x,
                        bounds.y0 as u32,
                        top_row_normal(&input_surface, bounds, x, surface_scale),
                    );
                }

                // Bottom row.
                for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                    compute_output_pixel(
                        x,
                        bounds.y1 as u32 - 1,
                        bottom_row_normal(&input_surface, bounds, x, surface_scale),
                    );
                }
            }

            if bounds.y1 - bounds.y0 >= 3 {
                // Left column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        bounds.x0 as u32,
                        y,
                        left_column_normal(&input_surface, bounds, y, surface_scale),
                    );
                }

                // Right column.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    compute_output_pixel(
                        bounds.x1 as u32 - 1,
                        y,
                        right_column_normal(&input_surface, bounds, y, surface_scale),
                    );
                }
            }

            if bounds.x1 - bounds.x0 >= 3 && bounds.y1 - bounds.y0 >= 3 {
                // Interior pixels.
                for y in bounds.y0 as u32 + 1..bounds.y1 as u32 - 1 {
                    for x in bounds.x0 as u32 + 1..bounds.x1 as u32 - 1 {
                        compute_output_pixel(
                            x,
                            y,
                            interior_normal(&input_surface, bounds, x, y, surface_scale),
                        );
                    }
                }
            }
        }

        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();
        // The generated color values are in the color space determined by
        // color-interpolation-filters.
        let surface_type =
            if values.color_interpolation_filters == ColorInterpolationFilters::LinearRgb {
                SurfaceType::LinearRgb
            } else {
                SurfaceType::SRgb
            };
        let mut output_surface = SharedImageSurface::new(output_surface, surface_type)?;

        if let Some((ox, oy)) = scale {
            // Scale the output surface back.
            output_surface = output_surface.scale_to(
                ctx.source_graphic().width(),
                ctx.source_graphic().height(),
                original_bounds,
                ox,
                oy,
            )?;

            bounds = original_bounds;
        }

        Ok(FilterResult {
            name: self.base.result.borrow().clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

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

impl Default for Lighting {
    #[inline]
    fn default() -> Self {
        Self {
            base: PrimitiveWithInput::new::<Self>(),
            surface_scale: Cell::new(1.0),
            kernel_unit_length: Cell::new(None),

            // The data field is unused in this case.
            data: Data::Diffuse {
                diffuse_constant: Cell::new(1.0),
            },
        }
    }
}
<|endoftext|>


<commit_before>
use pass;
use ir;

/// An IR strength reduction pass.
pub struct Inliner;

impl pass::Metadata for Inliner
{
    fn id(&self) -> pass::Id { pass::Id(0x32bbc291) }
    fn name(&self) -> &'static str { "inliner" }
}

impl pass::Transform<ir::Value> for Inliner
{
}

// TODO: blamket impl for all passes
impl Into<pass::Info<ir::Value>> for Box<Inliner>
{
    fn into(self) -> pass::Info<ir::Value> {
        pass::Info::Transform(self)
    }
}

pub fn inline(inst: ir::Instruction) -> ir::Value {
    match inst {
        ir::Instruction::Call(i) => self::inline_call(i),
        _ => panic!("{} instructions cannot be inlined"),
    }
}

pub fn inline_call(inst: ir::instruction::Call) -> ir::Value {
    unimplemented!();
}
<commit_msg>Add stub implementation for inliner pass<commit_after>
use pass;
use ir;

/// An IR strength reduction pass.
pub struct Inliner;

impl pass::Metadata for Inliner
{
    fn id(&self) -> pass::Id { pass::Id(0x32bbc291) }
    fn name(&self) -> &'static str { "inliner" }
}

impl pass::Transform<ir::Value> for Inliner
{
    fn run_function(&mut self, func: ir::Function)
        -> ir::Function {
        func
    }
}

// TODO: blamket impl for all passes
impl Into<pass::Info<ir::Value>> for Box<Inliner>
{
    fn into(self) -> pass::Info<ir::Value> {
        pass::Info::Transform(self)
    }
}

pub fn inline(inst: ir::Instruction) -> ir::Value {
    match inst {
        ir::Instruction::Call(i) => self::inline_call(i),
        _ => panic!("{} instructions cannot be inlined"),
    }
}

pub fn inline_call(_inst: ir::instruction::Call) -> ir::Value {
    unimplemented!();
}
<|endoftext|>


<commit_before>#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
#[cfg(feature = "arbitrary")]
use core::storage::Owned;

use std::iter;
use num::{Zero, One, Bounded};
use rand::{self, Rand, Rng};
use typenum::{self, Cmp, Greater};

use alga::general::{ClosedAdd, ClosedMul};

use core::{DefaultAllocator, Scalar, Matrix, Vector, Unit, MatrixMN, MatrixN, VectorN,
           MatrixSliceMN, MatrixSliceMutMN};
use core::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6};
use core::allocator::Allocator;
use core::storage::Storage;
use core::matrix_slice::{SliceStorage, SliceStorageMut};

/*
 *
 * Slice constructors.
 *
 */
impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> MatrixSliceMN<'a, N, R, C, RStride, CStride> {
    #[inline]
    pub fn new_slice_with_strides_generic(data: &'a [N], nrows: R, ncols: C, rstride: RStride, cstride: CStride) -> Self {
        // NOTE: The assertion implements the following formula, but without subtractions to avoid
        // underflow panics:
        //      len >= (ncols - 1) * cstride + (nrows - 1) * rstride + 1
        assert!(data.len() + cstride.value() + rstride.value() >=
                ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
                "Matrix slice: input data buffer to small.");

        let data = unsafe {
            SliceStorage::from_raw_parts(data.as_ptr(), (nrows, ncols), (rstride, cstride))
        };
        Self::from_data(data)
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> MatrixSliceMutMN<'a, N, R, C, RStride, CStride> {
    #[inline]
    pub fn new_slice_with_strides_mut_generic(data: &'a mut [N], nrows: R, ncols: C, rstride: RStride, cstride: CStride) -> Self {
        // NOTE: The assertion implements the following formula, but without subtractions to avoid
        // underflow panics:
        //      len >= (ncols - 1) * cstride + (nrows - 1) * rstride + 1
        assert!(data.len() + cstride.value() + rstride.value() >=
                ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
                "Matrix slice: input data buffer to small.");

        let data = unsafe {
            SliceStorageMut::from_raw_parts(data.as_mut_ptr(), (nrows, ncols), (rstride, cstride))
        };
        Self::from_data(data)
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim> MatrixSliceMN<'a, N, R, C> {
    #[inline]
    pub fn new_slice_generic(data: &'a [N], nrows: R, ncols: C) -> Self {
        Self::new_slice_with_strides_generic(data, nrows, ncols, U1, nrows)
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim> MatrixSliceMutMN<'a, N, R, C> {
    #[inline]
    pub fn new_slice_mut_generic(data: &'a mut [N], nrows: R, ncols: C) -> Self {
        Self::new_slice_with_strides_mut_generic(data, nrows, ncols, U1, nrows)
    }
}

macro_rules! impl_constructors(
    ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
        impl<'a, N: Scalar, $($DimIdent: $DimBound),*> MatrixSliceMN<'a, N, $($Dims),*> {
            #[inline]
            pub fn new(data: &'a [N], $($args: usize),*) -> Self {
                Self::new_slice_generic(data, $($gargs),*)
            }
        }

        impl<'a, N: Scalar, $($DimIdent: $DimBound, )*> MatrixSliceMN<'a, N, $($Dims,)* Dynamic, Dynamic> {
            #[inline]
            pub fn new_with_strides(data: &'a [N], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
                Self::new_slice_with_strides_generic(data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
            }
        }
    }
);

// FIXME: this is not very pretty. We could find a better call syntax.
impl_constructors!(R, C;                         // Arguments for Matrix<N, ..., S>
                   => R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
                   R::name(), C::name();         // Arguments for `_generic` constructors.
                   );                            // Arguments for non-generic constructors.

impl_constructors!(R, Dynamic;
                   => R: DimName;
                   R::name(), Dynamic::new(ncols);
                   ncols);

impl_constructors!(Dynamic, C;
                   => C: DimName;
                   Dynamic::new(nrows), C::name();
                   nrows);

impl_constructors!(Dynamic, Dynamic;
                   ;
                   Dynamic::new(nrows), Dynamic::new(ncols);
                   nrows, ncols);

macro_rules! impl_constructors_mut(
    ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
        impl<'a, N: Scalar, $($DimIdent: $DimBound),*> MatrixSliceMutMN<'a, N, $($Dims),*> {

            #[inline]
            pub fn new(data: &'a mut [N], $($args: usize),*) -> Self {
                Self::new_slice_mut_generic(data, $($gargs),*)
            }
        }

        impl<'a, N: Scalar, $($DimIdent: $DimBound, )*> MatrixSliceMutMN<'a, N, $($Dims,)* Dynamic, Dynamic> {
            #[inline]
            pub fn new_with_strides(data: &'a mut [N], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
                Self::new_slice_with_strides_mut_generic(
                    data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
            }
        }
    }
);

// FIXME: this is not very pretty. We could find a better call syntax.
impl_constructors_mut!(R, C;                         // Arguments for Matrix<N, ..., S>
                       => R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
                       R::name(), C::name();         // Arguments for `_generic` constructors.
                       );                            // Arguments for non-generic constructors.

impl_constructors_mut!(R, Dynamic;
                       => R: DimName;
                       R::name(), Dynamic::new(ncols);
                       ncols);

impl_constructors_mut!(Dynamic, C;
                       => C: DimName;
                       Dynamic::new(nrows), C::name();
                       nrows);

impl_constructors_mut!(Dynamic, Dynamic;
                       ;
                       Dynamic::new(nrows), Dynamic::new(ncols);
                       nrows, ncols);
<commit_msg>Add unsafe slice construction.<commit_after>#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
#[cfg(feature = "arbitrary")]
use core::storage::Owned;

use std::iter;
use num::{Zero, One, Bounded};
use rand::{self, Rand, Rng};
use typenum::{self, Cmp, Greater};

use alga::general::{ClosedAdd, ClosedMul};

use core::{DefaultAllocator, Scalar, Matrix, Vector, Unit, MatrixMN, MatrixN, VectorN,
           MatrixSliceMN, MatrixSliceMutMN};
use core::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6};
use core::allocator::Allocator;
use core::storage::Storage;
use core::matrix_slice::{SliceStorage, SliceStorageMut};

/*
 *
 * Slice constructors.
 *
 */
impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> MatrixSliceMN<'a, N, R, C, RStride, CStride> {
    #[inline]
    pub unsafe fn new_slice_with_strides_generic_unchecked(
        data: &'a [N], start: usize, nrows: R, ncols: C, rstride: RStride, cstride: CStride) -> Self {
        let data = unsafe {
            SliceStorage::from_raw_parts(data.as_ptr().offset(start as isize), (nrows, ncols), (rstride, cstride))
        };
        Self::from_data(data)
    }

    #[inline]
    pub fn new_slice_with_strides_generic(data: &'a [N], nrows: R, ncols: C, rstride: RStride, cstride: CStride) -> Self {
        // NOTE: The assertion implements the following formula, but without subtractions to avoid
        // underflow panics:
        //      len >= (ncols - 1) * cstride + (nrows - 1) * rstride + 1
        assert!(data.len() + cstride.value() + rstride.value() >=
                ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
                "Matrix slice: input data buffer to small.");

        unsafe {
            Self::new_slice_with_strides_generic_unchecked(data, 0, nrows, ncols, rstride, cstride)
        }
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> MatrixSliceMutMN<'a, N, R, C, RStride, CStride> {
    #[inline]
    pub unsafe fn new_slice_with_strides_mut_generic_unchecked(
        data: &'a mut [N], start: usize, nrows: R, ncols: C, rstride: RStride, cstride: CStride) -> Self {
        let data = unsafe {
            SliceStorageMut::from_raw_parts(data.as_mut_ptr().offset(start as isize), (nrows, ncols), (rstride, cstride))
        };
        Self::from_data(data)
    }

    #[inline]
    pub fn new_slice_with_strides_mut_generic(data: &'a mut [N], nrows: R, ncols: C, rstride: RStride, cstride: CStride) -> Self {
        // NOTE: The assertion implements the following formula, but without subtractions to avoid
        // underflow panics:
        //      len >= (ncols - 1) * cstride + (nrows - 1) * rstride + 1
        assert!(data.len() + cstride.value() + rstride.value() >=
                ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
                "Matrix slice: input data buffer to small.");

        unsafe {
            Self::new_slice_with_strides_mut_generic_unchecked(data, 0, nrows, ncols, rstride, cstride)
        }
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim> MatrixSliceMN<'a, N, R, C> {
    #[inline]
    pub unsafe fn new_slice_generic_unchecked(data: &'a [N], start: usize, nrows: R, ncols: C) -> Self {
        Self::new_slice_with_strides_generic_unchecked(data, start, nrows, ncols, U1, nrows)
    }

    #[inline]
    pub fn new_slice_generic(data: &'a [N], nrows: R, ncols: C) -> Self {
        Self::new_slice_with_strides_generic(data, nrows, ncols, U1, nrows)
    }
}

impl<'a, N: Scalar, R: Dim, C: Dim> MatrixSliceMutMN<'a, N, R, C> {
    #[inline]
    pub unsafe fn new_slice_mut_generic_unchecked(data: &'a mut [N], start: usize, nrows: R, ncols: C) -> Self {
        Self::new_slice_with_strides_mut_generic_unchecked(data, start, nrows, ncols, U1, nrows)
    }

    #[inline]
    pub fn new_slice_mut_generic(data: &'a mut [N], nrows: R, ncols: C) -> Self {
        Self::new_slice_with_strides_mut_generic(data, nrows, ncols, U1, nrows)
    }
}

macro_rules! impl_constructors(
    ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
        impl<'a, N: Scalar, $($DimIdent: $DimBound),*> MatrixSliceMN<'a, N, $($Dims),*> {
            #[inline]
            pub fn new(data: &'a [N], $($args: usize),*) -> Self {
                Self::new_slice_generic(data, $($gargs),*)
            }

            #[inline]
            pub unsafe fn new_unchecked(data: &'a [N], start: usize, $($args: usize),*) -> Self {
                Self::new_slice_generic_unchecked(data, start, $($gargs),*)
            }
        }

        impl<'a, N: Scalar, $($DimIdent: $DimBound, )*> MatrixSliceMN<'a, N, $($Dims,)* Dynamic, Dynamic> {
            #[inline]
            pub fn new_with_strides(data: &'a [N], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
                Self::new_slice_with_strides_generic(data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
            }

            #[inline]
            pub unsafe fn new_with_strides_unchecked(data: &'a [N], start: usize, $($args: usize,)* rstride: usize, cstride: usize) -> Self {
                Self::new_slice_with_strides_generic_unchecked(data, start, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
            }
        }
    }
);

// FIXME: this is not very pretty. We could find a better call syntax.
impl_constructors!(R, C;                         // Arguments for Matrix<N, ..., S>
                   => R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
                   R::name(), C::name();         // Arguments for `_generic` constructors.
                   );                            // Arguments for non-generic constructors.

impl_constructors!(R, Dynamic;
                   => R: DimName;
                   R::name(), Dynamic::new(ncols);
                   ncols);

impl_constructors!(Dynamic, C;
                   => C: DimName;
                   Dynamic::new(nrows), C::name();
                   nrows);

impl_constructors!(Dynamic, Dynamic;
                   ;
                   Dynamic::new(nrows), Dynamic::new(ncols);
                   nrows, ncols);

macro_rules! impl_constructors_mut(
    ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
        impl<'a, N: Scalar, $($DimIdent: $DimBound),*> MatrixSliceMutMN<'a, N, $($Dims),*> {

            #[inline]
            pub fn new(data: &'a mut [N], $($args: usize),*) -> Self {
                Self::new_slice_mut_generic(data, $($gargs),*)
            }

            #[inline]
            pub unsafe fn new_unchecked(data: &'a mut [N], start: usize, $($args: usize),*) -> Self {
                Self::new_slice_mut_generic_unchecked(data, start, $($gargs),*)
            }
        }

        impl<'a, N: Scalar, $($DimIdent: $DimBound, )*> MatrixSliceMutMN<'a, N, $($Dims,)* Dynamic, Dynamic> {
            #[inline]
            pub fn new_with_strides(data: &'a mut [N], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
                Self::new_slice_with_strides_mut_generic(
                    data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
            }

            #[inline]
            pub unsafe fn new_with_strides_unchecked(data: &'a mut [N], start: usize, $($args: usize,)* rstride: usize, cstride: usize) -> Self {
                Self::new_slice_with_strides_mut_generic_unchecked(
                    data, start, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
            }
        }
    }
);

// FIXME: this is not very pretty. We could find a better call syntax.
impl_constructors_mut!(R, C;                         // Arguments for Matrix<N, ..., S>
                       => R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
                       R::name(), C::name();         // Arguments for `_generic` constructors.
                       );                            // Arguments for non-generic constructors.

impl_constructors_mut!(R, Dynamic;
                       => R: DimName;
                       R::name(), Dynamic::new(ncols);
                       ncols);

impl_constructors_mut!(Dynamic, C;
                       => C: DimName;
                       Dynamic::new(nrows), C::name();
                       nrows);

impl_constructors_mut!(Dynamic, Dynamic;
                       ;
                       Dynamic::new(nrows), Dynamic::new(ncols);
                       nrows, ncols);
<|endoftext|>


<commit_before>extern crate cc;
extern crate bindgen;
use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

fn main() {

    if !Path::new("clingo").exists() {

        Command::new("git")
            .args(&["clone", "https://github.com/sthiele/clingo.git"])
            .status()
            .unwrap();

        Command::new("git")
            .args(&["checkout", "mod_v5.3.0"])
            .current_dir("./clingo")
            .status()
            .unwrap();

        Command::new("git")
            .args(&["submodule", "update", "--init", "--recursive"])
            .current_dir("./clingo")
            .status()
            .unwrap();
    }

    // The bindgen::Builder is the main entry point
    // to bindgen, and lets you build up options for
    // the resulting bindings.
    let bindings = bindgen::Builder::default()
        .header("clingo/libclingo/clingo.h")
//         .bitfield_enum("clingo_show_type")
        .generate()
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

    // libpotassco
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .flag("-O3")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .file("clingo/clasp/libpotassco/src/application.cpp")
        .file("clingo/clasp/libpotassco/src/aspif.cpp")
        .file("clingo/clasp/libpotassco/src/aspif_text.cpp")
        .file("clingo/clasp/libpotassco/src/clingo.cpp")
        .file("clingo/clasp/libpotassco/src/convert.cpp")
        .file("clingo/clasp/libpotassco/src/match_basic_types.cpp")
        .file("clingo/clasp/libpotassco/src/program_options.cpp")
        .file("clingo/clasp/libpotassco/src/rule_utils.cpp")
        .file("clingo/clasp/libpotassco/src/smodels.cpp")
        .file("clingo/clasp/libpotassco/src/string_convert.cpp")
        .file("clingo/clasp/libpotassco/src/theory_data.cpp")
        .file("clingo/clasp/libpotassco/src/value_store.cpp")
        .include("clingo/clasp/libpotassco")
        .compile("libpotassco.a");

    // libclasp
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/clasp/src/asp_preprocessor.cpp")
        .file("clingo/clasp/src/cb_enumerator.cpp")
        .file("clingo/clasp/src/clasp_facade.cpp")
        .file("clingo/clasp/src/clasp_options.cpp")
        .file("clingo/clasp/src/clasp_output.cpp")
        .file("clingo/clasp/src/clause.cpp")
        .file("clingo/clasp/src/clingo.cpp")
        .file("clingo/clasp/src/constraint.cpp")
        .file("clingo/clasp/src/dependency_graph.cpp")
        .file("clingo/clasp/src/enumerator.cpp")
        .file("clingo/clasp/src/heuristics.cpp")
        .file("clingo/clasp/src/logic_program.cpp")
        .file("clingo/clasp/src/logic_program_types.cpp")
        .file("clingo/clasp/src/lookahead.cpp")
        .file("clingo/clasp/src/minimize_constraint.cpp")
        .file("clingo/clasp/src/model_enumerators.cpp")
        .file("clingo/clasp/src/parser.cpp")
        .file("clingo/clasp/src/program_builder.cpp")
        .file("clingo/clasp/src/satelite.cpp")
        .file("clingo/clasp/src/shared_context.cpp")
        .file("clingo/clasp/src/solve_algorithms.cpp")
        .file("clingo/clasp/src/solver.cpp")
        .file("clingo/clasp/src/solver_strategies.cpp")
        .file("clingo/clasp/src/solver_types.cpp")
        .file("clingo/clasp/src/statistics.cpp")
        .file("clingo/clasp/src/timer.cpp")
        .file("clingo/clasp/src/unfounded_check.cpp")
        .file("clingo/clasp/src/weight_constraint.cpp")
        .file("clingo/clasp/src/parallel_solve.cpp")
        .include("clingo/clasp")
        .include("generated")
        .include("clingo/clasp/libpotassco")
        .compile("libclasp.a");

    // libgringo
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .file("clingo/libgringo/src/backend.cc")
        .file("clingo/libgringo/src/primes.cc")
        .file("clingo/libgringo/src/symbol.cc")
        .file("clingo/libgringo/src/term.cc")
        .file("clingo/libgringo/src/terms.cc")
        .file("clingo/libgringo/src/ground/instantiation.cc")
        .file("clingo/libgringo/src/ground/literals.cc")
        .file("clingo/libgringo/src/ground/program.cc")
        .file("clingo/libgringo/src/ground/statements.cc")
        .file("clingo/libgringo/src/input/aggregate.cc")
        .file("clingo/libgringo/src/input/aggregates.cc")
        .file("clingo/libgringo/src/input/groundtermparser.cc")
        .file("clingo/libgringo/src/input/literal.cc")
        .file("clingo/libgringo/src/input/literals.cc")
        .file("clingo/libgringo/src/input/nongroundparser.cc")
        .file("clingo/libgringo/src/input/program.cc")
        .file("clingo/libgringo/src/input/programbuilder.cc")
        .file("clingo/libgringo/src/input/statement.cc")
        .file("clingo/libgringo/src/input/theory.cc")
        .file("generated/input/groundtermgrammar/grammar.cc")
        .file("generated/input/nongroundgrammar/grammar.cc")
        .file("clingo/libgringo/src/output/aggregates.cc")
        .file("clingo/libgringo/src/output/literal.cc")
        .file("clingo/libgringo/src/output/literals.cc")
        .file("clingo/libgringo/src/output/output.cc")
        .file("clingo/libgringo/src/output/statement.cc")
        .file("clingo/libgringo/src/output/statements.cc")
        .file("clingo/libgringo/src/output/theory.cc")
        .include("clingo/libgringo")
        .include("generated")
        .include("clingo/clasp/libpotassco")
        .include("clingo/libreify")
        .compile("libgringo.a");

    // libclingo
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/libclingo/src/ast.cc")
        .file("clingo/libclingo/src/clingo_app.cc")
        .file("clingo/libclingo/src/clingocontrol.cc")
        .file("clingo/libclingo/src/control.cc")
        .file("clingo/libclingo/src/gringo_app.cc")
        .file("clingo/libclingo/src/incmode.cc")
        .file("clingo/libclingo/src/scripts.cc")
        .file("clingo/clasp/app/clasp_app.cpp")
        .include("clingo/libclingo")
        .include("clingo/libgringo")
        .include("clingo/clasp/libpotassco")
        .include("clingo/clasp")
        .include("clingo/clasp/app")
        .include("generated")
        .compile("libclingo.a");

    // libreify
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .file("clingo/libreify/src/program.cc")
        .include("clingo/libreify")
        .include("clingo/libgringo")
        .include("clingo/clasp/libpotassco")
        .compile("libreify.a");

    println!("cargo:rustc-link-lib=static=potassco");
    println!("cargo:rustc-link-lib=static=clasp");
    println!("cargo:rustc-link-lib=static=gringo");
    println!("cargo:rustc-link-lib=static=clingo");
    //     println!("cargo:rustc-link-lib=static=lp");
    //     println!("cargo:rustc-link-lib=static=reify");

    //     println!("cargo:rustc-link-lib=python3.6m");
    //     -DWITH_PYTHON=1 -I/usr/include/python3.6m

}
<commit_msg>fix test failure because of rust-lang/rust-bindgen#550<commit_after>extern crate cc;
extern crate bindgen;
use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

fn main() {

    if !Path::new("clingo").exists() {

        Command::new("git")
            .args(&["clone", "https://github.com/sthiele/clingo.git"])
            .status()
            .unwrap();

        Command::new("git")
            .args(&["checkout", "mod_v5.3.0"])
            .current_dir("./clingo")
            .status()
            .unwrap();

        Command::new("git")
            .args(&["submodule", "update", "--init", "--recursive"])
            .current_dir("./clingo")
            .status()
            .unwrap();
    }

    // The bindgen::Builder is the main entry point
    // to bindgen, and lets you build up options for
    // the resulting bindings.
    let bindings = bindgen::Builder::default()
        .header("clingo/libclingo/clingo.h")
//         .bitfield_enum("clingo_show_type")
        .blacklist_type("max_align_t") // https://github.com/rust-lang/rust-bindgen/issues/550
        .generate()
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");

    // libpotassco
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .flag("-O3")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .file("clingo/clasp/libpotassco/src/application.cpp")
        .file("clingo/clasp/libpotassco/src/aspif.cpp")
        .file("clingo/clasp/libpotassco/src/aspif_text.cpp")
        .file("clingo/clasp/libpotassco/src/clingo.cpp")
        .file("clingo/clasp/libpotassco/src/convert.cpp")
        .file("clingo/clasp/libpotassco/src/match_basic_types.cpp")
        .file("clingo/clasp/libpotassco/src/program_options.cpp")
        .file("clingo/clasp/libpotassco/src/rule_utils.cpp")
        .file("clingo/clasp/libpotassco/src/smodels.cpp")
        .file("clingo/clasp/libpotassco/src/string_convert.cpp")
        .file("clingo/clasp/libpotassco/src/theory_data.cpp")
        .file("clingo/clasp/libpotassco/src/value_store.cpp")
        .include("clingo/clasp/libpotassco")
        .compile("libpotassco.a");

    // libclasp
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/clasp/src/asp_preprocessor.cpp")
        .file("clingo/clasp/src/cb_enumerator.cpp")
        .file("clingo/clasp/src/clasp_facade.cpp")
        .file("clingo/clasp/src/clasp_options.cpp")
        .file("clingo/clasp/src/clasp_output.cpp")
        .file("clingo/clasp/src/clause.cpp")
        .file("clingo/clasp/src/clingo.cpp")
        .file("clingo/clasp/src/constraint.cpp")
        .file("clingo/clasp/src/dependency_graph.cpp")
        .file("clingo/clasp/src/enumerator.cpp")
        .file("clingo/clasp/src/heuristics.cpp")
        .file("clingo/clasp/src/logic_program.cpp")
        .file("clingo/clasp/src/logic_program_types.cpp")
        .file("clingo/clasp/src/lookahead.cpp")
        .file("clingo/clasp/src/minimize_constraint.cpp")
        .file("clingo/clasp/src/model_enumerators.cpp")
        .file("clingo/clasp/src/parser.cpp")
        .file("clingo/clasp/src/program_builder.cpp")
        .file("clingo/clasp/src/satelite.cpp")
        .file("clingo/clasp/src/shared_context.cpp")
        .file("clingo/clasp/src/solve_algorithms.cpp")
        .file("clingo/clasp/src/solver.cpp")
        .file("clingo/clasp/src/solver_strategies.cpp")
        .file("clingo/clasp/src/solver_types.cpp")
        .file("clingo/clasp/src/statistics.cpp")
        .file("clingo/clasp/src/timer.cpp")
        .file("clingo/clasp/src/unfounded_check.cpp")
        .file("clingo/clasp/src/weight_constraint.cpp")
        .file("clingo/clasp/src/parallel_solve.cpp")
        .include("clingo/clasp")
        .include("generated")
        .include("clingo/clasp/libpotassco")
        .compile("libclasp.a");

    // libgringo
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .file("clingo/libgringo/src/backend.cc")
        .file("clingo/libgringo/src/primes.cc")
        .file("clingo/libgringo/src/symbol.cc")
        .file("clingo/libgringo/src/term.cc")
        .file("clingo/libgringo/src/terms.cc")
        .file("clingo/libgringo/src/ground/instantiation.cc")
        .file("clingo/libgringo/src/ground/literals.cc")
        .file("clingo/libgringo/src/ground/program.cc")
        .file("clingo/libgringo/src/ground/statements.cc")
        .file("clingo/libgringo/src/input/aggregate.cc")
        .file("clingo/libgringo/src/input/aggregates.cc")
        .file("clingo/libgringo/src/input/groundtermparser.cc")
        .file("clingo/libgringo/src/input/literal.cc")
        .file("clingo/libgringo/src/input/literals.cc")
        .file("clingo/libgringo/src/input/nongroundparser.cc")
        .file("clingo/libgringo/src/input/program.cc")
        .file("clingo/libgringo/src/input/programbuilder.cc")
        .file("clingo/libgringo/src/input/statement.cc")
        .file("clingo/libgringo/src/input/theory.cc")
        .file("generated/input/groundtermgrammar/grammar.cc")
        .file("generated/input/nongroundgrammar/grammar.cc")
        .file("clingo/libgringo/src/output/aggregates.cc")
        .file("clingo/libgringo/src/output/literal.cc")
        .file("clingo/libgringo/src/output/literals.cc")
        .file("clingo/libgringo/src/output/output.cc")
        .file("clingo/libgringo/src/output/statement.cc")
        .file("clingo/libgringo/src/output/statements.cc")
        .file("clingo/libgringo/src/output/theory.cc")
        .include("clingo/libgringo")
        .include("generated")
        .include("clingo/clasp/libpotassco")
        .include("clingo/libreify")
        .compile("libgringo.a");

    // libclingo
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .define("WITH_THREADS", Some("0"))
        .file("clingo/libclingo/src/ast.cc")
        .file("clingo/libclingo/src/clingo_app.cc")
        .file("clingo/libclingo/src/clingocontrol.cc")
        .file("clingo/libclingo/src/control.cc")
        .file("clingo/libclingo/src/gringo_app.cc")
        .file("clingo/libclingo/src/incmode.cc")
        .file("clingo/libclingo/src/scripts.cc")
        .file("clingo/clasp/app/clasp_app.cpp")
        .include("clingo/libclingo")
        .include("clingo/libgringo")
        .include("clingo/clasp/libpotassco")
        .include("clingo/clasp")
        .include("clingo/clasp/app")
        .include("generated")
        .compile("libclingo.a");

    // libreify
    cc::Build::new()
        .cpp(true)
        .flag("-std=c++14")
        .warnings(false)
        .define("NDEBUG", Some("1"))
        .file("clingo/libreify/src/program.cc")
        .include("clingo/libreify")
        .include("clingo/libgringo")
        .include("clingo/clasp/libpotassco")
        .compile("libreify.a");

    println!("cargo:rustc-link-lib=static=potassco");
    println!("cargo:rustc-link-lib=static=clasp");
    println!("cargo:rustc-link-lib=static=gringo");
    println!("cargo:rustc-link-lib=static=clingo");
    //     println!("cargo:rustc-link-lib=static=lp");
    //     println!("cargo:rustc-link-lib=static=reify");

    //     println!("cargo:rustc-link-lib=python3.6m");
    //     -DWITH_PYTHON=1 -I/usr/include/python3.6m

}
<|endoftext|>


<commit_before>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

use std::ops::{Add, Sub, Mul};

/// 3 dimensional vector type, implementing all usual operations
#[derive(Copy, Clone)]
pub struct Vector3D {
    /// First component of the vector
    pub x: f64,
    /// Second component of the vector
    pub y: f64,
    /// Third component of the vector
    pub z: f64,
}

impl Vector3D {
    /// Create a new Vector3D with components `x`, `y`, `z`
    pub fn new(x: f64, y: f64, z: f64) -> Vector3D {
        Vector3D{x: x, y: y, z: z}
    }
}

/// Add two vectors
impl Add for Vector3D {
    type Output = Vector3D;
    fn add(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x + other.x, self.y + other.y, self.z + other.z)
    }
}

/// Substract two vectors
impl Sub for Vector3D {
    type Output = Vector3D;
    fn sub(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x - other.x, self.y - other.y, self.z - other.z)
    }
}

/// Multiply by a scalar on the right hand side
impl Mul<f64> for Vector3D {
    type Output = Vector3D;
    fn mul(self, other: f64) -> Vector3D {
        Vector3D::new(self.x * other, self.y * other, self.z * other)
    }
}

/// Multiply by a scalar on the left hand side
impl Mul<Vector3D> for f64 {
    type Output = Vector3D;
    fn mul(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self * other.x, self * other.y, self * other.z)
    }
}

/// Scalar product between vectors
impl Mul<Vector3D> for Vector3D {
    type Output = f64;
    fn mul(self, other: Vector3D) -> f64 {
        self.x * other.x + self.y * other.y + self.z * other.z
    }
}

/******************************************************************************/

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

    #[test]
    fn add() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a + b;
        assert_eq!(c.x, 8.1);
        assert_eq!(c.y, -5.0);
        assert_eq!(c.z, 12.1);
    }

    #[test]
    fn sub() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a - b;
        assert_eq!(c.x, -4.1);
        assert_eq!(c.y, 12.0);
        assert_eq!(c.z, -2.5);
    }

    #[test]
    fn mul() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = 2.0;

        let c = b * a;
        assert_eq!(c.x, 4.0);
        assert_eq!(c.y, 7.0);
        assert_eq!(c.z, 9.6);

        let b = 1.5;
        let c = a * b;
        assert_eq!(c.x, 3.0);
        assert_eq!(c.y, 5.25);
        assert_eq!(c.z, 7.199999999999999);
    }

    #[test]
    fn dot_product() {
        let a = Vector3D::new(2.1, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a * b;
        assert_eq!(c, 18.1);
    }
}
<commit_msg>Add Div implementation for Vector3D / scalar<commit_after>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

use std::ops::{Add, Sub, Mul, Div};

/// 3 dimensional vector type, implementing all usual operations
#[derive(Copy, Clone)]
pub struct Vector3D {
    /// First component of the vector
    pub x: f64,
    /// Second component of the vector
    pub y: f64,
    /// Third component of the vector
    pub z: f64,
}

impl Vector3D {
    /// Create a new Vector3D with components `x`, `y`, `z`
    pub fn new(x: f64, y: f64, z: f64) -> Vector3D {
        Vector3D{x: x, y: y, z: z}
    }
}

/// Add two vectors
impl Add for Vector3D {
    type Output = Vector3D;
    fn add(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x + other.x, self.y + other.y, self.z + other.z)
    }
}

/// Substract two vectors
impl Sub for Vector3D {
    type Output = Vector3D;
    fn sub(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x - other.x, self.y - other.y, self.z - other.z)
    }
}

/// Multiply by a scalar on the right hand side
impl Mul<f64> for Vector3D {
    type Output = Vector3D;
    fn mul(self, other: f64) -> Vector3D {
        Vector3D::new(self.x * other, self.y * other, self.z * other)
    }
}

/// Multiply by a scalar on the left hand side
impl Mul<Vector3D> for f64 {
    type Output = Vector3D;
    fn mul(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self * other.x, self * other.y, self * other.z)
    }
}

/// Scalar product between vectors
impl Mul<Vector3D> for Vector3D {
    type Output = f64;
    fn mul(self, other: Vector3D) -> f64 {
        self.x * other.x + self.y * other.y + self.z * other.z
    }
}

impl Div<f64> for Vector3D {
    type Output = Vector3D;
    fn div(self, other: f64) -> Vector3D {
        Vector3D::new(self.x / other, self.y / other, self.z / other)
    }
}

/******************************************************************************/

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

    #[test]
    fn add() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a + b;
        assert_eq!(c.x, 8.1);
        assert_eq!(c.y, -5.0);
        assert_eq!(c.z, 12.1);
    }

    #[test]
    fn sub() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a - b;
        assert_eq!(c.x, -4.1);
        assert_eq!(c.y, 12.0);
        assert_eq!(c.z, -2.5);
    }

    #[test]
    fn mul() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = 2.0;

        let c = b * a;
        assert_eq!(c.x, 4.0);
        assert_eq!(c.y, 7.0);
        assert_eq!(c.z, 9.6);

        let b = 1.5;
        let c = a * b;
        assert_eq!(c.x, 3.0);
        assert_eq!(c.y, 5.25);
        assert_eq!(c.z, 7.199999999999999);
    }

    #[test]
    fn dot_product() {
        let a = Vector3D::new(2.1, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a * b;
        assert_eq!(c, 18.1);
    }
}
<|endoftext|>


<commit_before>use nom::{Err, IResult, Needed};

use std::io;
use std::io::Read;
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Consumed(usize),
  EndOfInput,
  Unknown,
}

pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        if let Err::Position(_, i) = e {
          self.offset += self.len() - i.len();
        }

        Err(ErrorKind::Unknown)
      }
    }
  }
}

pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity();

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      if let Err::Position(_, i) = e {
        Err(ErrorKind::Consumed(buffer.len() - i.len()))
      } else {
        Err(ErrorKind::Unknown)
      }
    }
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        match kind {
          ErrorKind::Incomplete(needed) => self.needed = needed,
          ErrorKind::Consumed(consumed) => buffer.consume(consumed),
          _                             => (),
        }

        Err(kind)
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Fix full parsing of FLAC files using `from_buffer`<commit_after>use nom::{Err, IResult, Needed};

use std::io;
use std::io::Read;
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Consumed(usize),
  EndOfInput,
  Unknown,
}

pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        if let Err::Position(_, i) = e {
          let consumed = self.len() - i.len();

          self.offset += consumed;

          Err(ErrorKind::Consumed(consumed))
        } else {
          Err(ErrorKind::Unknown)
        }
      }
    }
  }
}

pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity();

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      if let Err::Position(_, i) = e {
        Err(ErrorKind::Consumed(buffer.len() - i.len()))
      } else {
        Err(ErrorKind::Unknown)
      }
    }
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        match kind {
          ErrorKind::Incomplete(needed) => self.needed = needed,
          ErrorKind::Consumed(consumed) => buffer.consume(consumed),
          _                             => (),
        }

        Err(kind)
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::{AsyncResult, Error, Executor, IntoAsync, IoSourceExt};
use base::{Result as SysResult, Timer};
use std::time::Duration;

/// An async version of base::Timer.
pub struct TimerAsync {
    pub(crate) io_source: Box<dyn IoSourceExt<Timer>>,
}

impl TimerAsync {
    pub fn new(timer: Timer, ex: &Executor) -> AsyncResult<TimerAsync> {
        ex.async_from(timer)
            .map(|io_source| TimerAsync { io_source })
    }

    /// Gets the next value from the timer.
    pub async fn next_val(&self) -> AsyncResult<u64> {
        self.io_source.wait_for_handle().await
    }

    /// Async sleep for the given duration
    pub async fn sleep(ex: &Executor, dur: Duration) -> std::result::Result<(), Error> {
        let mut tfd = Timer::new().map_err(Error::Timer)?;
        tfd.reset(dur, None).map_err(Error::Timer)?;
        let t = TimerAsync::new(tfd, ex).map_err(Error::TimerAsync)?;
        t.next_val().await.map_err(Error::TimerAsync)?;
        Ok(())
    }

    /// Sets the timer to expire after `dur`.  If `interval` is not `None` it represents
    /// the period for repeated expirations after the initial expiration.  Otherwise
    /// the timer will expire just once.  Cancels any existing duration and repeating interval.
    pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> SysResult<()> {
        self.io_source.as_source_mut().reset(dur, interval)
    }
}

impl IntoAsync for Timer {}
<commit_msg>cros_async: update Timer & sleep docs for Windows.<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::{AsyncResult, Error, Executor, IntoAsync, IoSourceExt};
use base::{Result as SysResult, Timer};
use std::time::Duration;

/// An async version of base::Timer.
pub struct TimerAsync {
    pub(crate) io_source: Box<dyn IoSourceExt<Timer>>,
}

impl TimerAsync {
    pub fn new(timer: Timer, ex: &Executor) -> AsyncResult<TimerAsync> {
        ex.async_from(timer)
            .map(|io_source| TimerAsync { io_source })
    }

    /// Gets the next value from the timer.
    ///
    /// NOTE: on Windows, this may return/wake early. See `base::Timer` docs
    /// for details.
    pub async fn next_val(&self) -> AsyncResult<u64> {
        self.io_source.wait_for_handle().await
    }

    /// Async sleep for the given duration.
    ///
    /// NOTE: on Windows, this sleep may wake early. See `base::Timer` docs
    /// for details.
    pub async fn sleep(ex: &Executor, dur: Duration) -> std::result::Result<(), Error> {
        let mut tfd = Timer::new().map_err(Error::Timer)?;
        tfd.reset(dur, None).map_err(Error::Timer)?;
        let t = TimerAsync::new(tfd, ex).map_err(Error::TimerAsync)?;
        t.next_val().await.map_err(Error::TimerAsync)?;
        Ok(())
    }

    /// Sets the timer to expire after `dur`.  If `interval` is not `None` it represents
    /// the period for repeated expirations after the initial expiration.  Otherwise
    /// the timer will expire just once.  Cancels any existing duration and repeating interval.
    pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> SysResult<()> {
        self.io_source.as_source_mut().reset(dur, interval)
    }
}

impl IntoAsync for Timer {}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! Create buttons bound to a URL

use glib::translate::{FromGlibPtr, ToGlibPtr, ToTmp};
use gtk::cast::GTK_LINKBUTTON;
use gtk::{self, ffi};
use glib::{to_bool, to_gboolean};

/// LinkButton — Create buttons bound to a URL
/*
* # Availables signals :
* * `activate-link` : Run Last
*/
struct_Widget!(LinkButton);

impl LinkButton {
    pub fn new(uri: &str) -> Option<LinkButton> {
        let tmp_pointer = unsafe {
            let mut tmp_uri = uri.to_tmp_for_borrow();
            ffi::gtk_link_button_new(tmp_uri.to_glib_ptr())
        };
        check_pointer!(tmp_pointer, LinkButton)
    }

    pub fn new_with_label(uri: &str, label: &str) -> Option<LinkButton> {
        let tmp_pointer = unsafe {
            let mut tmp_uri = uri.to_tmp_for_borrow();
            let mut tmp_label = label.to_tmp_for_borrow();
            ffi::gtk_link_button_new_with_label(tmp_uri.as_ptr(), tmp_label.as_ptr())
        };
        check_pointer!(tmp_pointer, LinkButton)
    }

    pub fn get_uri(&self) -> Option<String> {
        unsafe {
            FromGlibPtr::borrow(
                ffi::gtk_link_button_get_uri(GTK_LINKBUTTON(self.pointer)))
        }
    }

    pub fn set_uri(&mut self, uri: &str) -> () {
        unsafe {
            let mut tmp_uri = uri.to_tmp_for_borrow();
            ffi::gtk_link_button_set_uri(GTK_LINKBUTTON(self.pointer), tmp_uri.as_ptr())
        }
    }

    pub fn set_visited(&mut self, visited: bool) -> () {
        unsafe { ffi::gtk_link_button_set_visited(GTK_LINKBUTTON(self.pointer), to_gboolean(visited)); }
    }

    pub fn get_visited(&self) -> bool {
        unsafe { to_bool(ffi::gtk_link_button_get_visited(GTK_LINKBUTTON(self.pointer))) }
    }
}

impl_drop!(LinkButton);
impl_TraitWidget!(LinkButton);

impl gtk::ContainerTrait for LinkButton {}
impl gtk::ButtonTrait for LinkButton {}

impl_widget_events!(LinkButton);
impl_button_events!(LinkButton);
<commit_msg>Follow-up to e2d3617a, fix an incomplete change<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! Create buttons bound to a URL

use glib::translate::{FromGlibPtr, ToGlibPtr, ToTmp};
use gtk::cast::GTK_LINKBUTTON;
use gtk::{self, ffi};
use glib::{to_bool, to_gboolean};

/// LinkButton — Create buttons bound to a URL
/*
* # Availables signals :
* * `activate-link` : Run Last
*/
struct_Widget!(LinkButton);

impl LinkButton {
    pub fn new(uri: &str) -> Option<LinkButton> {
        let tmp_pointer = unsafe {
            let mut tmp_uri = uri.to_tmp_for_borrow();
            ffi::gtk_link_button_new(tmp_uri.to_glib_ptr())
        };
        check_pointer!(tmp_pointer, LinkButton)
    }

    pub fn new_with_label(uri: &str, label: &str) -> Option<LinkButton> {
        let tmp_pointer = unsafe {
            let mut tmp_uri = uri.to_tmp_for_borrow();
            let mut tmp_label = label.to_tmp_for_borrow();
            ffi::gtk_link_button_new_with_label(tmp_uri.to_glib_ptr(), tmp_label.to_glib_ptr())
        };
        check_pointer!(tmp_pointer, LinkButton)
    }

    pub fn get_uri(&self) -> Option<String> {
        unsafe {
            FromGlibPtr::borrow(
                ffi::gtk_link_button_get_uri(GTK_LINKBUTTON(self.pointer)))
        }
    }

    pub fn set_uri(&mut self, uri: &str) -> () {
        unsafe {
            let mut tmp_uri = uri.to_tmp_for_borrow();
            ffi::gtk_link_button_set_uri(GTK_LINKBUTTON(self.pointer), tmp_uri.to_glib_ptr())
        }
    }

    pub fn set_visited(&mut self, visited: bool) -> () {
        unsafe { ffi::gtk_link_button_set_visited(GTK_LINKBUTTON(self.pointer), to_gboolean(visited)); }
    }

    pub fn get_visited(&self) -> bool {
        unsafe { to_bool(ffi::gtk_link_button_get_visited(GTK_LINKBUTTON(self.pointer))) }
    }
}

impl_drop!(LinkButton);
impl_TraitWidget!(LinkButton);

impl gtk::ContainerTrait for LinkButton {}
impl gtk::ButtonTrait for LinkButton {}

impl_widget_events!(LinkButton);
impl_button_events!(LinkButton);
<|endoftext|>


<commit_before>use std::borrow::Cow;
use http::Method;

#[derive(Clone, Debug)]
pub enum RequestParameters {
    Query(String),
    Body(String),
}

use std::iter::Map;
use std::slice::Iter;

impl RequestParameters {
    pub fn new<S: AsRef<str>>(method: &Method, params: &[(S, S)]) -> Self {
        let params_s = Self::params_to_query(params);

        if Self::method_requires_body(method) {
            RequestParameters::Body(params_s)
        } else {
            RequestParameters::Query(params_s)
        }
    }

    #[inline]
    fn method_requires_body(method: &Method) -> bool {
        match *method {
            Method::GET | Method::HEAD | Method::DELETE => false,
            _ => true,
        }
    }

    pub fn path_and_query<'p>(&self, path: &'p str) -> Cow<'p, str> {
        self.query().map_or_else(|| {
            Cow::Borrowed(path)
        }, |q| {
            let mut url = path.to_string();
            url.push('?');
            url.push_str(q);
            Cow::Owned(url)
        })
    }

    pub fn query(&self) -> Option<&str> {
        match self {
            RequestParameters::Query(query) => Some(query.as_str()),
            _ => None,
        }
    }

    pub fn body(&self) -> Option<&str> {
        match self {
            RequestParameters::Body(body) => Some(body.as_str()),
            _ => None,
        }
    }

    pub fn into_inner(self) -> String {
        match self {
            RequestParameters::Query(s) => s,
            RequestParameters::Body(s) => s,
        }
    }

    pub fn as_mut_string(&mut self) -> &mut String {
        match self {
            RequestParameters::Query(ref mut query) => query,
            RequestParameters::Body(ref mut body) => body,
        }
    }

    pub fn query_as_mut_string(&mut self) -> Option<&mut String> {
        match self {
            RequestParameters::Query(ref mut query) => Some(query),
            _ => None,
        }
    }

    pub fn body_as_mut_string(&mut self) -> Option<&mut String> {
        match self {
            RequestParameters::Body(ref mut body) => Some(body),
            _ => None,
        }
    }

    pub fn push<S: AsRef<str>>(&mut self, extra_params: &[(S, S)]) {
        let q = Self::params_to_query(extra_params);
        let s = self.as_mut_string();

        if !s.is_empty() {
            s.push('&');
        }

        s.push_str(q.as_str());
    }

    #[allow(clippy::type_complexity)]
    fn params_to_string_collection<S: AsRef<str>>(params: &[(S, S)]) -> Map<Iter<(S, S)>, fn(&(S, S)) -> String> {
        params.iter().map(|(k, v)| {
            //[self::encoding::encode(k.as_ref()), Cow::Borrowed("="), self::encoding::encode(v.as_ref())].concat()
            [k.as_ref(), "=", v.as_ref()].concat()
        })
    }

    fn params_to_vec<S: AsRef<str>>(params: &[(S, S)]) -> Vec<String> {
        Self::params_to_string_collection(params).collect()
    }

    fn params_to_query<S: AsRef<str>>(params: &[(S, S)]) -> String {
        Self::params_to_vec(params).join("&")
    }
}

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

    #[bench]
    fn bench_params_to_query(b: &mut Bencher) {
        let params = (1..10).map(|i| {
            (format!("unakey{}", i), format!("unvalor{}", i))
        }).collect::<Vec<_>>();

        b.iter(||
            RequestParameters::params_to_query(&params)
        );
    }
}
<commit_msg>request_parameters: newtype for parameter mapping<commit_after>use std::borrow::Cow;
use http::Method;

#[derive(Clone, Debug)]
pub enum RequestParameters {
    Query(String),
    Body(String),
}

use std::iter::Map;
use std::slice::Iter;

// This newtype is currently only used internally here, but we might want to move it elsewhere where
// it could be more useful because of genericity. We could also aim at reducing the amount of
// conversions in requests by having a type that only maps parameters once unless changed.
type ParamsMapper<'a, S, T> = Map<Iter<'a, (S, S)>, fn(&(S, S)) -> T>;

impl RequestParameters {
    pub fn new<S: AsRef<str>>(method: &Method, params: &[(S, S)]) -> Self {
        let params_s = Self::params_to_query(params);

        if Self::method_requires_body(method) {
            RequestParameters::Body(params_s)
        } else {
            RequestParameters::Query(params_s)
        }
    }

    #[inline]
    fn method_requires_body(method: &Method) -> bool {
        match *method {
            Method::GET | Method::HEAD | Method::DELETE => false,
            _ => true,
        }
    }

    pub fn path_and_query<'p>(&self, path: &'p str) -> Cow<'p, str> {
        self.query().map_or_else(|| {
            Cow::Borrowed(path)
        }, |q| {
            let mut url = path.to_string();
            url.push('?');
            url.push_str(q);
            Cow::Owned(url)
        })
    }

    pub fn query(&self) -> Option<&str> {
        match self {
            RequestParameters::Query(query) => Some(query.as_str()),
            _ => None,
        }
    }

    pub fn body(&self) -> Option<&str> {
        match self {
            RequestParameters::Body(body) => Some(body.as_str()),
            _ => None,
        }
    }

    pub fn into_inner(self) -> String {
        match self {
            RequestParameters::Query(s) => s,
            RequestParameters::Body(s) => s,
        }
    }

    pub fn as_mut_string(&mut self) -> &mut String {
        match self {
            RequestParameters::Query(ref mut query) => query,
            RequestParameters::Body(ref mut body) => body,
        }
    }

    pub fn query_as_mut_string(&mut self) -> Option<&mut String> {
        match self {
            RequestParameters::Query(ref mut query) => Some(query),
            _ => None,
        }
    }

    pub fn body_as_mut_string(&mut self) -> Option<&mut String> {
        match self {
            RequestParameters::Body(ref mut body) => Some(body),
            _ => None,
        }
    }

    pub fn push<S: AsRef<str>>(&mut self, extra_params: &[(S, S)]) {
        let q = Self::params_to_query(extra_params);
        let s = self.as_mut_string();

        if !s.is_empty() {
            s.push('&');
        }

        s.push_str(q.as_str());
    }

    fn params_to_string_collection<S: AsRef<str>>(params: &[(S, S)]) -> ParamsMapper<S, String> {
        params.iter().map(|(k, v)| {
            //[self::encoding::encode(k.as_ref()), Cow::Borrowed("="), self::encoding::encode(v.as_ref())].concat()
            [k.as_ref(), "=", v.as_ref()].concat()
        })
    }

    fn params_to_vec<S: AsRef<str>>(params: &[(S, S)]) -> Vec<String> {
        Self::params_to_string_collection(params).collect()
    }

    fn params_to_query<S: AsRef<str>>(params: &[(S, S)]) -> String {
        Self::params_to_vec(params).join("&")
    }
}

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

    #[bench]
    fn bench_params_to_query(b: &mut Bencher) {
        let params = (1..10).map(|i| {
            (format!("unakey{}", i), format!("unvalor{}", i))
        }).collect::<Vec<_>>();

        b.iter(||
            RequestParameters::params_to_query(&params)
        );
    }
}
<|endoftext|>