<commit_before>use std::str::FromStr;

/// Description for new columns
#[derive(Debug, Clone)]
pub struct ColumnDescription {
    pub name: String,

    /// Type of the data, see the cfitsio documentation
    pub data_type: Option<ColumnDataDescription>,
}

#[derive(Debug, Clone)]
pub struct ConcreteColumnDescription {
    pub name: String,
    pub data_type: ColumnDataDescription,
}

impl ColumnDescription {
    pub fn new<T: Into<String>>(name: T) -> Self {
        ColumnDescription {
            name: name.into(),
            data_type: None,
        }
    }

    pub fn with_type(&mut self, typ: ColumnDataType) -> &mut ColumnDescription {
        self.data_type = Some(ColumnDataDescription::scalar(typ));
        self
    }

    pub fn that_repeats(&mut self, repeat: usize) -> &mut ColumnDescription {
        if let Some(ref mut desc) = self.data_type {
            desc.repeat = repeat;
        }
        self
    }

    pub fn with_width(&mut self, width: usize) -> &mut ColumnDescription {
        if let Some(ref mut desc) = self.data_type {
            desc.width = width;
        }
        self
    }

    pub fn create(&self) -> Result<ConcreteColumnDescription, Box<::std::error::Error>> {
        match self.data_type {
            Some(ref d) => {
                Ok(ConcreteColumnDescription {
                    name: self.name.clone(),
                    data_type: d.clone(),
                })
            }
            None => {
                Err(
                    "No data type given. Ensure the `with_type` method has been called.".into(),
                )
            }
        }
    }
}

/// Description of the column data
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ColumnDataDescription {
    pub repeat: usize,
    pub width: usize,
    pub typ: ColumnDataType,
}

impl ColumnDataDescription {
    pub fn new(typ: ColumnDataType, repeat: usize, width: usize) -> Self {
        ColumnDataDescription {
            repeat: repeat,
            width: width,
            typ: typ,
        }
    }

    /// Shortcut for creating a scalar column
    pub fn scalar(typ: ColumnDataType) -> Self {
        ColumnDataDescription::new(typ, 1, 1)
    }

    pub fn vector(typ: ColumnDataType, repeat: usize) -> Self {
        ColumnDataDescription::new(typ, repeat, 1)
    }

    /* XXX These two methods force a call to clone which is wasteful of memory. I do not know if
     * this means that memory is leaked, or that destructors are needlessly called (I suspect the
     * latter) but it is fairly wasteful. On the other hand, it's unlikely this sort of thing will
     * be called in performance-critical code, and is more likely a one-dime definition. I will
     * leave it for now - SRW 2017-03-07
     * */
    pub fn repeats(&mut self, repeat: usize) -> Self {
        // TODO check that repeat >= 1
        self.repeat = repeat;
        self.clone()
    }

    pub fn width(&mut self, width: usize) -> Self {
        // TODO check that width >= 1
        self.width = width;
        self.clone()
    }
}

impl From<ColumnDataDescription> for String {
    fn from(orig: ColumnDataDescription) -> String {
        match orig.typ {
            ColumnDataType::Text => {
                if orig.width > 1 {
                    format!(
                        "{repeat}{data_type}{width}",
                        data_type = String::from(orig.typ),
                        repeat = orig.repeat,
                        width = orig.width
                    )
                } else {
                    format!(
                        "{repeat}{data_type}",
                        data_type = String::from(orig.typ),
                        repeat = orig.repeat
                    )
                }
            }
            _ => {
                format!(
                    "{repeat}{data_type}",
                    data_type = String::from(orig.typ),
                    repeat = orig.repeat
                )
            }
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColumnDataType {
    Int,
    Float,
    Text,
    Double,
    Short,
    Long,
    String,
}

impl From<ColumnDataType> for String {
    fn from(orig: ColumnDataType) -> String {
        use self::ColumnDataType::*;

        match orig {
            Int => "J",
            Float => "E",
            Text | String => "A",
            Double => "D",
            Short => "I",
            Long => "K",
        }.to_string()
    }
}

impl FromStr for ColumnDataDescription {
    type Err = Box<::std::error::Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let chars: Vec<_> = s.chars().collect();

        let mut repeat_str = Vec::new();
        let mut last_position = 0;
        for c in &chars {
            if c.is_digit(10) {
                repeat_str.push(c);
                last_position += 1;
            } else {
                break;
            }
        }

        let repeat = if repeat_str.is_empty() {
            1
        } else {
            /* TODO: in nightly the following line works
            let repeat_str: String = repeat_str.into_iter().collect(); */
            let repeat_str: String = repeat_str.into_iter().cloned().collect();
            repeat_str.parse::<usize>()?
        };

        let data_type_char = chars[last_position];
        last_position += 1;

        let mut width_str = Vec::new();
        for c in chars.iter().skip(last_position) {
            if c.is_digit(10) {
                width_str.push(c);
            } else {
                break;
            }
        }

        /* TODO: validate that the whole string has been used up */

        let width = if width_str.is_empty() {
            1
        } else {
            /* TODO: in nightly the following line works
            let width_str: String = width_str.into_iter().collect(); */
            let width_str: String = width_str.into_iter().cloned().collect();
            width_str.parse::<usize>()?
        };

        let data_type = match data_type_char {
            'E' => ColumnDataType::Float,
            'J' => ColumnDataType::Int,
            'D' => ColumnDataType::Double,
            'I' => ColumnDataType::Short,
            'K' => ColumnDataType::Long,
            'A' => ColumnDataType::String,
            _ => {
                panic!(
                    "Have not implemented str -> ColumnDataType for {}",
                    data_type_char
                )
            }
        };

        Ok(ColumnDataDescription {
            repeat: repeat,
            typ: data_type,
            width: width,
        })
    }
}

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

    #[test]
    fn test_column_data_descriptions_builder_pattern() {
        let desc = ColumnDataDescription::scalar(ColumnDataType::Int)
            .width(100)
            .repeats(5);
        assert_eq!(desc.repeat, 5);
        assert_eq!(desc.width, 100);
    }

    #[test]
    fn from_impls() {
        {
            let desc = ColumnDataDescription::scalar(ColumnDataType::Int).repeats(5);
            assert_eq!(String::from(desc), "5J");
        }

        {
            let desc = ColumnDataDescription::scalar(ColumnDataType::Float);
            assert_eq!(String::from(desc), "1E");
        }

        {
            let desc = ColumnDataDescription::scalar(ColumnDataType::Text).width(100);
            assert_eq!(String::from(desc), "1A100");
        }
    }

    #[test]
    fn parsing() {
        let s = "1E";
        assert_eq!(
            s.parse::<ColumnDataDescription>().unwrap(),
            ColumnDataDescription {
                repeat: 1,
                width: 1,
                typ: ColumnDataType::Float,
            }
        );
    }

    #[test]
    fn parse_many_repeats() {
        let s = "100E";
        assert_eq!(
            s.parse::<ColumnDataDescription>().unwrap(),
            ColumnDataDescription {
                repeat: 100,
                width: 1,
                typ: ColumnDataType::Float,
            }
        );
    }

    #[test]
    fn parse_with_width() {
        let s = "1E26";
        assert_eq!(
            s.parse::<ColumnDataDescription>().unwrap(),
            ColumnDataDescription {
                repeat: 1,
                width: 26,
                typ: ColumnDataType::Float,
            }
        );
    }

    #[test]
    fn creating_data_description() {
        let concrete_desc = ColumnDescription::new("FOO")
            .with_type(ColumnDataType::Int)
            .that_repeats(10)
            .create()
            .unwrap();
        assert_eq!(concrete_desc.name, "FOO".to_string());
        assert_eq!(concrete_desc.data_type.repeat, 10);
        assert_eq!(concrete_desc.data_type.width, 1);

        /* Do not call `with_type` */
        let bad_desc = ColumnDescription::new("FOO").create();
        assert!(bad_desc.is_err());
    }
}
<commit_msg>Fix typo in todo comment<commit_after>use std::str::FromStr;

/// Description for new columns
#[derive(Debug, Clone)]
pub struct ColumnDescription {
    pub name: String,

    /// Type of the data, see the cfitsio documentation
    pub data_type: Option<ColumnDataDescription>,
}

#[derive(Debug, Clone)]
pub struct ConcreteColumnDescription {
    pub name: String,
    pub data_type: ColumnDataDescription,
}

impl ColumnDescription {
    pub fn new<T: Into<String>>(name: T) -> Self {
        ColumnDescription {
            name: name.into(),
            data_type: None,
        }
    }

    pub fn with_type(&mut self, typ: ColumnDataType) -> &mut ColumnDescription {
        self.data_type = Some(ColumnDataDescription::scalar(typ));
        self
    }

    pub fn that_repeats(&mut self, repeat: usize) -> &mut ColumnDescription {
        if let Some(ref mut desc) = self.data_type {
            desc.repeat = repeat;
        }
        self
    }

    pub fn with_width(&mut self, width: usize) -> &mut ColumnDescription {
        if let Some(ref mut desc) = self.data_type {
            desc.width = width;
        }
        self
    }

    pub fn create(&self) -> Result<ConcreteColumnDescription, Box<::std::error::Error>> {
        match self.data_type {
            Some(ref d) => {
                Ok(ConcreteColumnDescription {
                    name: self.name.clone(),
                    data_type: d.clone(),
                })
            }
            None => {
                Err(
                    "No data type given. Ensure the `with_type` method has been called.".into(),
                )
            }
        }
    }
}

/// Description of the column data
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ColumnDataDescription {
    pub repeat: usize,
    pub width: usize,
    pub typ: ColumnDataType,
}

impl ColumnDataDescription {
    pub fn new(typ: ColumnDataType, repeat: usize, width: usize) -> Self {
        ColumnDataDescription {
            repeat: repeat,
            width: width,
            typ: typ,
        }
    }

    /// Shortcut for creating a scalar column
    pub fn scalar(typ: ColumnDataType) -> Self {
        ColumnDataDescription::new(typ, 1, 1)
    }

    pub fn vector(typ: ColumnDataType, repeat: usize) -> Self {
        ColumnDataDescription::new(typ, repeat, 1)
    }

    /* XXX These two methods force a call to clone which is wasteful of memory. I do not know if
     * this means that memory is leaked, or that destructors are needlessly called (I suspect the
     * latter) but it is fairly wasteful. On the other hand, it's unlikely this sort of thing will
     * be called in performance-critical code, and is more likely a one-time definition. I will
     * leave it for now - SRW 2017-03-07
     * */
    pub fn repeats(&mut self, repeat: usize) -> Self {
        // TODO check that repeat >= 1
        self.repeat = repeat;
        self.clone()
    }

    pub fn width(&mut self, width: usize) -> Self {
        // TODO check that width >= 1
        self.width = width;
        self.clone()
    }
}

impl From<ColumnDataDescription> for String {
    fn from(orig: ColumnDataDescription) -> String {
        match orig.typ {
            ColumnDataType::Text => {
                if orig.width > 1 {
                    format!(
                        "{repeat}{data_type}{width}",
                        data_type = String::from(orig.typ),
                        repeat = orig.repeat,
                        width = orig.width
                    )
                } else {
                    format!(
                        "{repeat}{data_type}",
                        data_type = String::from(orig.typ),
                        repeat = orig.repeat
                    )
                }
            }
            _ => {
                format!(
                    "{repeat}{data_type}",
                    data_type = String::from(orig.typ),
                    repeat = orig.repeat
                )
            }
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColumnDataType {
    Int,
    Float,
    Text,
    Double,
    Short,
    Long,
    String,
}

impl From<ColumnDataType> for String {
    fn from(orig: ColumnDataType) -> String {
        use self::ColumnDataType::*;

        match orig {
            Int => "J",
            Float => "E",
            Text | String => "A",
            Double => "D",
            Short => "I",
            Long => "K",
        }.to_string()
    }
}

impl FromStr for ColumnDataDescription {
    type Err = Box<::std::error::Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let chars: Vec<_> = s.chars().collect();

        let mut repeat_str = Vec::new();
        let mut last_position = 0;
        for c in &chars {
            if c.is_digit(10) {
                repeat_str.push(c);
                last_position += 1;
            } else {
                break;
            }
        }

        let repeat = if repeat_str.is_empty() {
            1
        } else {
            /* TODO: in nightly the following line works
            let repeat_str: String = repeat_str.into_iter().collect(); */
            let repeat_str: String = repeat_str.into_iter().cloned().collect();
            repeat_str.parse::<usize>()?
        };

        let data_type_char = chars[last_position];
        last_position += 1;

        let mut width_str = Vec::new();
        for c in chars.iter().skip(last_position) {
            if c.is_digit(10) {
                width_str.push(c);
            } else {
                break;
            }
        }

        /* TODO: validate that the whole string has been used up */

        let width = if width_str.is_empty() {
            1
        } else {
            /* TODO: in nightly the following line works
            let width_str: String = width_str.into_iter().collect(); */
            let width_str: String = width_str.into_iter().cloned().collect();
            width_str.parse::<usize>()?
        };

        let data_type = match data_type_char {
            'E' => ColumnDataType::Float,
            'J' => ColumnDataType::Int,
            'D' => ColumnDataType::Double,
            'I' => ColumnDataType::Short,
            'K' => ColumnDataType::Long,
            'A' => ColumnDataType::String,
            _ => {
                panic!(
                    "Have not implemented str -> ColumnDataType for {}",
                    data_type_char
                )
            }
        };

        Ok(ColumnDataDescription {
            repeat: repeat,
            typ: data_type,
            width: width,
        })
    }
}

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

    #[test]
    fn test_column_data_descriptions_builder_pattern() {
        let desc = ColumnDataDescription::scalar(ColumnDataType::Int)
            .width(100)
            .repeats(5);
        assert_eq!(desc.repeat, 5);
        assert_eq!(desc.width, 100);
    }

    #[test]
    fn from_impls() {
        {
            let desc = ColumnDataDescription::scalar(ColumnDataType::Int).repeats(5);
            assert_eq!(String::from(desc), "5J");
        }

        {
            let desc = ColumnDataDescription::scalar(ColumnDataType::Float);
            assert_eq!(String::from(desc), "1E");
        }

        {
            let desc = ColumnDataDescription::scalar(ColumnDataType::Text).width(100);
            assert_eq!(String::from(desc), "1A100");
        }
    }

    #[test]
    fn parsing() {
        let s = "1E";
        assert_eq!(
            s.parse::<ColumnDataDescription>().unwrap(),
            ColumnDataDescription {
                repeat: 1,
                width: 1,
                typ: ColumnDataType::Float,
            }
        );
    }

    #[test]
    fn parse_many_repeats() {
        let s = "100E";
        assert_eq!(
            s.parse::<ColumnDataDescription>().unwrap(),
            ColumnDataDescription {
                repeat: 100,
                width: 1,
                typ: ColumnDataType::Float,
            }
        );
    }

    #[test]
    fn parse_with_width() {
        let s = "1E26";
        assert_eq!(
            s.parse::<ColumnDataDescription>().unwrap(),
            ColumnDataDescription {
                repeat: 1,
                width: 26,
                typ: ColumnDataType::Float,
            }
        );
    }

    #[test]
    fn creating_data_description() {
        let concrete_desc = ColumnDescription::new("FOO")
            .with_type(ColumnDataType::Int)
            .that_repeats(10)
            .create()
            .unwrap();
        assert_eq!(concrete_desc.name, "FOO".to_string());
        assert_eq!(concrete_desc.data_type.repeat, 10);
        assert_eq!(concrete_desc.data_type.width, 1);

        /* Do not call `with_type` */
        let bad_desc = ColumnDescription::new("FOO").create();
        assert!(bad_desc.is_err());
    }
}
<|endoftext|>


<commit_before>use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::aspect_ratio::AspectRatio;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::href::{is_href, set_href};
use crate::node::{CascadedValues, Node};
use crate::parsers::ParseValue;
use crate::rect::Rect;
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::viewbox::ViewBox;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Primitive, PrimitiveParams, ResolvedPrimitive};

/// The `feImage` filter primitive.
#[derive(Clone)]
pub struct FeImage {
    base: Primitive,
    aspect: AspectRatio,
    href: Option<String>,
}

/// Resolved `feImage` primitive for rendering.
pub struct Image {
    aspect: AspectRatio,
    href: Option<String>,
}

impl Default for FeImage {
    /// Constructs a new `FeImage` with empty properties.
    #[inline]
    fn default() -> FeImage {
        FeImage {
            base: Default::default(),
            aspect: AspectRatio::default(),
            href: None,
        }
    }
}

impl Image {
    /// Renders the filter if the source is an existing node.
    fn render_node(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
        bounds: Rect,
        node_id: &NodeId,
    ) -> Result<SharedImageSurface, FilterError> {
        let acquired_drawable = acquired_nodes
            .acquire(node_id)
            .map_err(|_| FilterError::InvalidInput)?;
        let drawable = acquired_drawable.get();

        let node_being_filtered_values = ctx.get_computed_values_from_node_being_filtered();
        let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);

        let image = draw_ctx.draw_node_to_surface(
            &drawable,
            acquired_nodes,
            &cascaded,
            ctx.paffine(),
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let surface = ctx.source_graphic().paint_image(bounds, &image, None)?;

        Ok(surface)
    }

    /// Renders the filter if the source is an external image.
    fn render_external_image(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        _draw_ctx: &DrawingCtx,
        bounds: Rect,
        unclipped_bounds: &Rect,
        url: &str,
    ) -> Result<SharedImageSurface, FilterError> {
        // FIXME: translate the error better here
        let image = acquired_nodes
            .lookup_image(url)
            .map_err(|_| FilterError::InvalidInput)?;

        let rect = self.aspect.compute(
            &ViewBox::from(Rect::from_size(
                f64::from(image.width()),
                f64::from(image.height()),
            )),
            &unclipped_bounds,
        );

        let surface = ctx
            .source_graphic()
            .paint_image(bounds, &image, Some(rect))?;

        Ok(surface)
    }
}

impl SetAttributes for FeImage {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.parse_no_inputs(attrs)?;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "preserveAspectRatio") => self.aspect = attr.parse(value)?,

                // "path" is used by some older Adobe Illustrator versions
                ref a if is_href(a) || *a == expanded_name!("", "path") => {
                    set_href(a, &mut self.href, value.to_string());
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl Image {
    pub fn render(
        &self,
        primitive: &ResolvedPrimitive,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let bounds_builder = primitive.get_bounds(ctx)?;
        let (bounds, unclipped_bounds) = bounds_builder.into_rect(ctx, draw_ctx);

        let href = self.href.as_ref().ok_or(FilterError::InvalidInput)?;

        let surface = if let Ok(node_id) = NodeId::parse(href) {
            // if href has a fragment specified, render as a node
            self.render_node(ctx, acquired_nodes, draw_ctx, bounds, &node_id)
        } else {
            self.render_external_image(
                ctx,
                acquired_nodes,
                draw_ctx,
                bounds,
                &unclipped_bounds,
                href,
            )
        }?;

        Ok(FilterResult {
            name: primitive.result.clone(),
            output: FilterOutput {
                surface,
                bounds: bounds.into(),
            },
        })
    }
}

impl FilterEffect for FeImage {
    fn resolve(&self, _node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
        Ok((
            self.base.clone(),
            PrimitiveParams::Image(Image {
                aspect: self.aspect.clone(),
                href: self.href.clone(),
            }),
        ))
    }
}
<commit_msg>feImage: shorten code by implementing Default and Clone for its parameters<commit_after>use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::aspect_ratio::AspectRatio;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::href::{is_href, set_href};
use crate::node::{CascadedValues, Node};
use crate::parsers::ParseValue;
use crate::rect::Rect;
use crate::surface_utils::shared_surface::SharedImageSurface;
use crate::viewbox::ViewBox;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Primitive, PrimitiveParams, ResolvedPrimitive};

/// The `feImage` filter primitive.
#[derive(Default)]
pub struct FeImage {
    base: Primitive,
    params: Image,
}

/// Resolved `feImage` primitive for rendering.
#[derive(Clone, Default)]
pub struct Image {
    aspect: AspectRatio,
    href: Option<String>,
}

impl Image {
    /// Renders the filter if the source is an existing node.
    fn render_node(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
        bounds: Rect,
        node_id: &NodeId,
    ) -> Result<SharedImageSurface, FilterError> {
        let acquired_drawable = acquired_nodes
            .acquire(node_id)
            .map_err(|_| FilterError::InvalidInput)?;
        let drawable = acquired_drawable.get();

        let node_being_filtered_values = ctx.get_computed_values_from_node_being_filtered();
        let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);

        let image = draw_ctx.draw_node_to_surface(
            &drawable,
            acquired_nodes,
            &cascaded,
            ctx.paffine(),
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let surface = ctx.source_graphic().paint_image(bounds, &image, None)?;

        Ok(surface)
    }

    /// Renders the filter if the source is an external image.
    fn render_external_image(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        _draw_ctx: &DrawingCtx,
        bounds: Rect,
        unclipped_bounds: &Rect,
        url: &str,
    ) -> Result<SharedImageSurface, FilterError> {
        // FIXME: translate the error better here
        let image = acquired_nodes
            .lookup_image(url)
            .map_err(|_| FilterError::InvalidInput)?;

        let rect = self.aspect.compute(
            &ViewBox::from(Rect::from_size(
                f64::from(image.width()),
                f64::from(image.height()),
            )),
            &unclipped_bounds,
        );

        let surface = ctx
            .source_graphic()
            .paint_image(bounds, &image, Some(rect))?;

        Ok(surface)
    }
}

impl SetAttributes for FeImage {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.parse_no_inputs(attrs)?;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "preserveAspectRatio") => {
                    self.params.aspect = attr.parse(value)?
                }

                // "path" is used by some older Adobe Illustrator versions
                ref a if is_href(a) || *a == expanded_name!("", "path") => {
                    set_href(a, &mut self.params.href, value.to_string());
                }

                _ => (),
            }
        }

        Ok(())
    }
}

impl Image {
    pub fn render(
        &self,
        primitive: &ResolvedPrimitive,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let bounds_builder = primitive.get_bounds(ctx)?;
        let (bounds, unclipped_bounds) = bounds_builder.into_rect(ctx, draw_ctx);

        let href = self.href.as_ref().ok_or(FilterError::InvalidInput)?;

        let surface = if let Ok(node_id) = NodeId::parse(href) {
            // if href has a fragment specified, render as a node
            self.render_node(ctx, acquired_nodes, draw_ctx, bounds, &node_id)
        } else {
            self.render_external_image(
                ctx,
                acquired_nodes,
                draw_ctx,
                bounds,
                &unclipped_bounds,
                href,
            )
        }?;

        Ok(FilterResult {
            name: primitive.result.clone(),
            output: FilterOutput {
                surface,
                bounds: bounds.into(),
            },
        })
    }
}

impl FilterEffect for FeImage {
    fn resolve(&self, _node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
        Ok((
            self.base.clone(),
            PrimitiveParams::Image(self.params.clone()),
        ))
    }
}
<|endoftext|>


<commit_before>/*! Hex map display demo */

extern crate num;
extern crate tiled;
extern crate image;
extern crate calx;

mod spr;
mod render;
mod world;

use std::collections::{HashMap};
use calx::backend::{CanvasBuilder, CanvasUtil, Event, Key};
use calx::{V2, Rect, Rgba, color, ToColor, convert_color};
use calx::{Projection, Kernel, KernelTerrain};
use calx::{Dir6, LatticeNode, HexGeom, astar_path_with};

use spr::Spr;
use render::RenderTerrain;
use world::World;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum Terrain {
    Floor,
    Grass,
    Water,
    Tree,
    Wall,
    Door,
    Window,
    Magma,
    Rock,
    Void,
}

impl Terrain {
    pub fn new(id: u8) -> Terrain {
        // Tiled indexes start from 1.
        let id = id - 1;
        assert!(id <= Terrain::Rock as u8);
        unsafe {
            std::mem::transmute(id)
        }
    }

    pub fn can_walk(self) -> bool {
        use Terrain::*;
        match self {
            Floor | Grass | Door => true,
            _ => false,
        }
    }
}

impl KernelTerrain for Terrain {
    fn is_wall(&self) -> bool {
        use Terrain::*;
        match *self {
            Wall | Door | Window => true,
            _ => false
        }
    }

    fn is_block(&self) -> bool { *self == Terrain::Rock }
}

fn load_tmx_map() -> (u32, u32, HashMap<V2<i32>, Terrain>) {
    let tmx = include_str!("../assets/hexworld.tmx");
    let map = tiled::parse(tmx.as_bytes()).unwrap();
    let mut ret = HashMap::new();

    let (w, h) = (map.width, map.height);
    for layer in map.layers.iter() {
        for (y, row) in layer.tiles.iter().enumerate() {
            for (x, &id) in row.iter().enumerate() {
                ret.insert(V2(x as i32, y as i32), Terrain::new(id as u8));
            }
        }
    }

    (w, h, ret)
}

pub fn terrain_at(pos: V2<i32>) -> Terrain {
    struct Map {
        _w: i32,
        _h: i32,
        terrain: HashMap<V2<i32>, Terrain>,
    }

    // Tiled map data as the backend.
    thread_local!(static MAP: Map = {
        let (w, h, terrain) = load_tmx_map();
        Map { _w: w as i32, _h: h as i32, terrain: terrain }
    });

    //let key = MAP.with(|m| V2(pos.0.mod_floor(&m.w), pos.1.mod_floor(&m.h)));
    let key = pos;

    match MAP.with(|m| m.terrain.get(&key).map(|&x| x)) {
        Some(t) => t,
        None => Terrain::Void,
    }
}

#[derive(Eq, PartialEq, Hash, Clone, Copy, PartialOrd, Ord)]
struct PathPos(pub V2<i32>);

impl LatticeNode for PathPos {
    fn neighbors(&self) -> Vec<PathPos> {
        let mut ret = Vec::new();
        for i in Dir6::iter() {
            let pos = self.0 + i.to_v2();
            if terrain_at(pos).can_walk() {
                ret.push(PathPos(pos));
            }
        }
        ret
    }
}

struct Sprite {
    pub spr: Spr,
    pub fore: Rgba,
    pub back: Rgba,
    pub pos: V2<f32>,
    /// Draw layer, y coordinate.
    pub sort_key: (i8, i32),
}

impl Sprite {
    pub fn new<A: ToColor, B: ToColor>(spr: Spr, pos: V2<f32>, layer: i8, fore: &A, back: &B) -> Sprite {
        Sprite {
            spr: spr,
            fore: convert_color(fore),
            back: convert_color(back),
            pos: pos,
            sort_key: (layer, -pos.1 as i32)
        }
    }
}

fn main() {
    let scroll_speed = 4f32;
    let mut screen_offset = V2(0.0f32, 0.0f32);
    let mut scroll_delta = V2(0.0f32, 0.0f32);
    let mut mouse_pos = V2(-1.0f32, -1.0f32);

    let world = World::new();

    let screen_rect = Rect(V2(0.0f32, 0.0f32), V2(640.0f32, 360.0f32));
    let mut builder = CanvasBuilder::new().set_size((screen_rect.1).0 as u32, (screen_rect.1).1 as u32);
    Spr::init(&mut builder);
    let mut ctx = builder.build();

    loop {
        match ctx.next_event() {
            Event::RenderFrame => {
                screen_offset = screen_offset - scroll_delta;

                let mut sprites = Vec::new();

                let proj = Projection::new(V2(16.0, 8.0), V2(-16.0, 8.0)).unwrap()
                    .view_offset(screen_offset);
                for pt in proj.inv_project_rectangle(&screen_rect).iter() {
                    let pos = proj.project(pt);
                    Kernel::new(terrain_at, pt.map(|x| x as i32)).render(
                        |layer, spr, fore, back| {
                            sprites.push(Sprite::new(spr, pos, layer, fore, back));
                        });
                }

                let mouse_cell = PathPos(proj.inv_project(mouse_pos).map(|x| x.floor() as i32));
                let player_cell = PathPos(world.player_pos.map(|x| x.floor() as i32));
                let path = astar_path_with(|x, y| (x.0-y.0).hex_dist(), player_cell, mouse_cell, 1000);

                if let Some(path) = path {
                    for p in path.iter() {
                        sprites.push(Sprite::new(
                            Spr::Avatar, proj.project(p.0.map(|x| x as f32)), -1, &"#ff000088", &color::BLACK));
                    }
                }

                sprites.push(Sprite::new(Spr::Avatar, proj.project(world.player_pos), 0, &color::WHITE, &color::BLACK));

                sprites.sort_by(|a, b| b.sort_key.partial_cmp(&a.sort_key).unwrap());
                for spr in sprites.iter() {
                    ctx.draw_image(spr.spr.get(), spr.pos, 0.5, &spr.fore, &spr.back);
                }
            }

            Event::Quit => { return; }

            Event::KeyPressed(Key::Escape) => { return; }

            Event::KeyPressed(Key::F12) => {
                ctx.save_screenshot(&"azag");
            }

            Event::KeyPressed(k) => {
                match k {
                    Key::A => { scroll_delta.0 = -1.0 * scroll_speed; }
                    Key::D => { scroll_delta.0 =  1.0 * scroll_speed; }
                    Key::W => { scroll_delta.1 = -1.0 * scroll_speed; }
                    Key::S => { scroll_delta.1 =  1.0 * scroll_speed; }
                    _ => {}
                }
            }

            Event::KeyReleased(k) => {
                match k {
                    Key::A => { scroll_delta.0 = 0.0; }
                    Key::D => { scroll_delta.0 = 0.0; }
                    Key::W => { scroll_delta.1 = 0.0; }
                    Key::S => { scroll_delta.1 = 0.0; }
                    _ => {}
                }
            }
            Event::MouseMoved((x, y)) => {
                mouse_pos = V2(x, y).map(|x| x as f32);
            }

            _ => {}
        }
    }
}
<commit_msg>Hexworld tweak<commit_after>/*! Hex map display demo */

extern crate num;
extern crate tiled;
extern crate image;
extern crate calx;

mod spr;
mod render;
mod world;

use std::collections::{HashMap};
use calx::backend::{CanvasBuilder, CanvasUtil, Event, Key};
use calx::{V2, Rect, Rgba, color, ToColor, convert_color};
use calx::{Projection, Kernel, KernelTerrain};
use calx::{Dir6, LatticeNode, HexGeom, astar_path_with};

use spr::Spr;
use render::RenderTerrain;
use world::World;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum Terrain {
    Floor,
    Grass,
    Water,
    Tree,
    Wall,
    Door,
    Window,
    Magma,
    Rock,
    Void,
}

impl Terrain {
    pub fn new(id: u8) -> Terrain {
        // Tiled indexes start from 1.
        let id = id - 1;
        assert!(id <= Terrain::Rock as u8);
        unsafe {
            std::mem::transmute(id)
        }
    }

    pub fn can_walk(self) -> bool {
        use Terrain::*;
        match self {
            Floor | Grass | Door => true,
            _ => false,
        }
    }
}

impl KernelTerrain for Terrain {
    fn is_wall(&self) -> bool {
        use Terrain::*;
        match *self {
            Wall | Door | Window => true,
            _ => false
        }
    }

    fn is_block(&self) -> bool { *self == Terrain::Rock }
}

fn load_tmx_map() -> (u32, u32, HashMap<V2<i32>, Terrain>) {
    let tmx = include_str!("../assets/hexworld.tmx");
    let map = tiled::parse(tmx.as_bytes()).unwrap();
    let mut ret = HashMap::new();

    let (w, h) = (map.width, map.height);
    for layer in map.layers.iter() {
        for (y, row) in layer.tiles.iter().enumerate() {
            for (x, &id) in row.iter().enumerate() {
                ret.insert(V2(x as i32, y as i32), Terrain::new(id as u8));
            }
        }
    }

    (w, h, ret)
}

pub fn terrain_at(pos: V2<i32>) -> Terrain {
    struct Map {
        _w: i32,
        _h: i32,
        terrain: HashMap<V2<i32>, Terrain>,
    }

    // Tiled map data as the backend.
    thread_local!(static MAP: Map = {
        let (w, h, terrain) = load_tmx_map();
        Map { _w: w as i32, _h: h as i32, terrain: terrain }
    });

    //let key = MAP.with(|m| V2(pos.0.mod_floor(&m.w), pos.1.mod_floor(&m.h)));
    let key = pos;

    match MAP.with(|m| m.terrain.get(&key).map(|&x| x)) {
        Some(t) => t,
        None => Terrain::Void,
    }
}

#[derive(Eq, PartialEq, Hash, Clone, Copy, PartialOrd, Ord)]
struct PathPos(pub V2<i32>);

impl LatticeNode for PathPos {
    fn neighbors(&self) -> Vec<PathPos> {
        let mut ret = Vec::new();
        for i in Dir6::iter() {
            let pos = self.0 + i.to_v2();
            if terrain_at(pos).can_walk() {
                ret.push(PathPos(pos));
            }
        }
        ret
    }
}

struct Sprite {
    pub spr: Spr,
    pub fore: Rgba,
    pub back: Rgba,
    pub pos: V2<f32>,

    sort_key: (i8, i32),
}

impl Sprite {
    pub fn new<A: ToColor, B: ToColor>(spr: Spr, pos: V2<f32>, layer: i8, fore: &A, back: &B) -> Sprite {
        Sprite {
            spr: spr,
            fore: convert_color(fore),
            back: convert_color(back),
            pos: pos,
            sort_key: (layer, -pos.1 as i32)
        }
    }

    #[inline]
    pub fn cmp(&self, other: &Sprite) -> std::cmp::Ordering {
        // Cmp backwards, draw order is from large (far away) to small (close by) values.
        other.sort_key.cmp(&self.sort_key)
    }
}

fn main() {
    let scroll_speed = 4f32;
    let mut screen_offset = V2(0.0f32, 0.0f32);
    let mut scroll_delta = V2(0.0f32, 0.0f32);
    let mut mouse_pos = V2(-1.0f32, -1.0f32);

    let world = World::new();

    let screen_rect = Rect(V2(0.0f32, 0.0f32), V2(640.0f32, 360.0f32));
    let mut builder = CanvasBuilder::new().set_size((screen_rect.1).0 as u32, (screen_rect.1).1 as u32);
    Spr::init(&mut builder);
    let mut ctx = builder.build();

    loop {
        match ctx.next_event() {
            Event::RenderFrame => {
                screen_offset = screen_offset - scroll_delta;

                let mut sprites = Vec::new();

                let proj = Projection::new(V2(16.0, 8.0), V2(-16.0, 8.0)).unwrap()
                    .view_offset(screen_offset);
                for pt in proj.inv_project_rectangle(&screen_rect).iter() {
                    let pos = proj.project(pt);
                    Kernel::new(terrain_at, pt.map(|x| x as i32)).render(
                        |layer, spr, fore, back| {
                            sprites.push(Sprite::new(spr, pos, layer, fore, back));
                        });
                }

                let mouse_cell = PathPos(proj.inv_project(mouse_pos).map(|x| x.floor() as i32));
                let player_cell = PathPos(world.player_pos.map(|x| x.floor() as i32));
                let path = astar_path_with(|x, y| (x.0-y.0).hex_dist(), player_cell, mouse_cell, 1000);

                if let Some(path) = path {
                    for p in path.iter() {
                        sprites.push(Sprite::new(
                            Spr::Avatar, proj.project(p.0.map(|x| x as f32)), -1, &"#ff000088", &color::BLACK));
                    }
                }

                sprites.push(Sprite::new(Spr::Avatar, proj.project(world.player_pos), 0, &color::WHITE, &color::BLACK));

                sprites.sort_by(|a, b| a.cmp(&b));
                for spr in sprites.iter() {
                    ctx.draw_image(spr.spr.get(), spr.pos, 0.5, &spr.fore, &spr.back);
                }
            }

            Event::Quit => { return; }

            Event::KeyPressed(Key::Escape) => { return; }

            Event::KeyPressed(Key::F12) => {
                ctx.save_screenshot(&"azag");
            }

            Event::KeyPressed(k) => {
                match k {
                    Key::A => { scroll_delta.0 = -1.0 * scroll_speed; }
                    Key::D => { scroll_delta.0 =  1.0 * scroll_speed; }
                    Key::W => { scroll_delta.1 = -1.0 * scroll_speed; }
                    Key::S => { scroll_delta.1 =  1.0 * scroll_speed; }
                    _ => {}
                }
            }

            Event::KeyReleased(k) => {
                match k {
                    Key::A => { scroll_delta.0 = 0.0; }
                    Key::D => { scroll_delta.0 = 0.0; }
                    Key::W => { scroll_delta.1 = 0.0; }
                    Key::S => { scroll_delta.1 = 0.0; }
                    _ => {}
                }
            }
            Event::MouseMoved((x, y)) => {
                mouse_pos = V2(x, y).map(|x| x as f32);
            }

            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>use clap::{App, Arg};
use std::process;

// This Struct is later given to our main program,
// it contains all the needed information to make suggestions of films
#[derive(Debug, Clone)]
pub struct SearchParams {
    genres: Vec<String>,
    movies: Vec<String>,
    actors: Vec<String>,
    rating: Vec<f32>,
}

impl SearchParams {
    // initialize a SearchParams type with empty fields
    fn init() -> Self {
        SearchParams {
            genres: Vec::new(),
            movies: Vec::new(),
            actors: Vec::new(),
            rating: Vec::new(),
        }
    }
}

// Creates struct SearchParams in which all given parameters are included.
pub fn get_search_params() -> SearchParams {
    // status of program
    println!("Getting Commandline Input ...");

    // later given to main program, contains all arguments given in
    // command line
    let mut search_params = SearchParams::init();

    // our matches, we can later use those to handle our commandline input
    let matches = App::new("Film-O-Mat")
        .arg(Arg::with_name("genre")
            .short("g")
            .help("Takes one or more genres")
            .takes_value(true)
            .multiple(true))
        .arg(Arg::with_name("actor")
            .short("a")
            .help("Takes an actor")
            .takes_value(true))
        .arg(Arg::with_name("movie")
            .short("m")
            .help("Takes one or more movies. e.g. \u{0022}Schindler's List\u{0022}")
            .takes_value(true)
            .multiple(true))
        .arg(Arg::with_name("rating")
            .short("r")
            .help("Takes a rating")
            .takes_value(true))
        .get_matches();

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("genre") {
        let genres: Vec<String> = match matches.values_of("genre") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Genre");
                process::exit(0);
            }
        };
        search_params.genres = genres;
        // Debug
        // println!("Genre: {}", genre);
    }

    // If an actor was given, save it in our SearchParams Type
    if matches.is_present("actor") {
        let actor = match matches.value_of("actor") {
            Some(actor) => actor,
            None => {
                println!("Invalid Actor");
                process::exit(0);
            }
        };
        search_params.actors.push(actor.into());
        // Debug
        // println!("Actor: {}", actor);
    }

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("movie") {
        let movies: Vec<String> = match matches.values_of("movie") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Movie");
                process::exit(0);
            }
        };
        search_params.movies = movies;
        // Debug
        // println!("Movies: {:?}", search_params.genre);
    }

    if matches.is_present("rating") {
        let val = match matches.value_of("rating") {
            Some(vals) => vals,
            None => {
                println!("Invalid Rating");
                process::exit(0);
            }
        };
        search_params.rating.push(
            match val.parse() {
                Ok(val) => val,
                Err(err) => {
                    println!("{:?}", err);
                    process::exit(0);
                }
            }
        );
        // Debug
        // println!("Rating: {:?}", search_params.rating);
    }

    // Debug
    // println!("{:?}", search_params);
    search_params
}
<commit_msg>add comments, delete argument "actor"<commit_after>//! Gets the commandline input and packs it into an usable Stuct.
//! Data that can be included: genres, movies, rating.
use clap::{App, Arg};
use std::process;

/// Struct contains all the needed information to make suggestions of films
#[derive(Debug, Clone)]
pub struct SearchParams {
    genres: Vec<String>,
    movies: Vec<String>,
    rating: Vec<f32>,
}

impl SearchParams {
    /// initialize a SearchParams type with empty fields
    fn init() -> Self {
        SearchParams {
            genres: Vec::new(),
            movies: Vec::new(),
            rating: Vec::new(),
        }
    }
}

/// Creates struct SearchParams with all given parameters
pub fn get_search_params() -> SearchParams {
    // status of program
    println!("Getting Commandline Input ...");

    // search parameters
    let mut search_params = SearchParams::init();

    // matches, we can later use those to handle our commandline input
    let matches = App::new("Film-O-Mat")
        .arg(Arg::with_name("genre")
            .short("g")
            .help("Takes one or more genres")
            .takes_value(true)
            .multiple(true))
        .arg(Arg::with_name("movie")
            .short("m")
            .help("Takes one or more movies. e.g. \u{0022}Schindler's List\u{0022}")
            .takes_value(true)
            .multiple(true))
        .arg(Arg::with_name("rating")
            .short("r")
            .help("Takes a rating")
            .takes_value(true))
        .get_matches();

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("genre") {
        let genres: Vec<String> = match matches.values_of("genre") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Genre");
                process::exit(0);
            }
        };
        search_params.genres = genres;
        // Debug
        // println!("Genre: {}", genre);
    }

    // If a genre was given, save it in our SearchParams Type
    if matches.is_present("movie") {
        let movies: Vec<String> = match matches.values_of("movie") {
            Some(vals) => {
                vals.map(|x| x.to_string())
                    .collect()
            }
            None => {
                println!("Invalid Movie");
                process::exit(0);
            }
        };
        search_params.movies = movies;
        // Debug
        // println!("Movies: {:?}", search_params.genre);
    }

    // If a rating was given, save it in our SearchParams
    if matches.is_present("rating") {
        let val = match matches.value_of("rating") {
            Some(vals) => vals,
            None => {
                println!("Invalid Rating");
                process::exit(0);
            }
        };
        search_params.rating.push(
            match val.parse() {
                Ok(val) => val,
                Err(err) => {
                    println!("{:?}", err);
                    process::exit(0);
                }
            }
        );
        // Debug
        // println!("Rating: {:?}", search_params.rating);
    }

    // Debug
    // println!("{:?}", search_params);
    search_params
}
<|endoftext|>


<commit_before>//! A DNS query.

use futures::{Async, Future, Poll};
use futures::task::TaskRc;
use rand::random;
use ::bits::{DName, ComposeMode, ComposeResult, MessageBuilder, MessageBuf};
use ::iana::{Class, Rtype};
use super::ResolverTask;
use super::conf::ResolvOptions;
use super::core::Core;
use super::error::Error;
use super::request::QueryRequest;

//------------ Query ---------------------------------------------------------

/// A DNS query.
///
/// A query is a future that resolves a DNS question for all the resource
/// records for a given domain name, record type, and class into either a
/// response or a query error. It will follow the rules set down by the
/// resolver configuration in trying to find an upstream server that
/// replies to the question.
///
/// A query is actually a combinator of sorts. It needs a [`ResolverTask`]
/// to operate on which in itself is the result of a future, namely that
/// returned by [`Resolver::start()`]. As such, you cannot use a query by
/// itself. Please see the module level documentation for some examples on
/// how to start a query.
//
//  Since a query can fail very early on when building the request message,
//  it internally consists of a `Result`. If it is `Ok()`, we really do have
//  a query to poll, otherwise we have an error to take out and return.
pub struct Query(Result<RealQuery, Option<Error>>);

impl Query {
    /// Creates a new query.
    pub fn new<N: DName>(resolv: &ResolverTask, name: N, rtype: Rtype,
                       class: Class) -> Self {
        let core = resolv.core.clone();
        let message = core.with(|core| {
            Self::build_message(name, rtype, class, core.options())
        });
        let message = match message {
            Ok(message) => message,
            Err(err) => return Query(Err(Some(err.into())))
        };
        let dgram = core.with(|core| !core.conf().options.use_vc);
        let (index, request) = core.with(|c| RealQuery::start(c, dgram,
                                                              message));
        Query(Ok(RealQuery {
            core: core, request: request,
            dgram: dgram, start_index: index, curr_index: index,
            attempt: 0
        }))
    }

    /// Builds the message for this query.
    ///
    /// If this function fails, we are done.
    fn build_message<N: DName>(name: N, rtype: Rtype, class: Class,
                                 opts: &ResolvOptions)
                                 -> ComposeResult<MessageBuilder> {
        let mut res = try!(MessageBuilder::new(ComposeMode::Stream, true));
        res.header_mut().set_rd(opts.recurse);
        try!(res.push((name, rtype, class)));
        Ok(res)
    }
}

//--- Future

impl Future for Query {
    type Item = MessageBuf;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            Ok(ref mut query) => query.poll(),
            Err(ref mut err) => {
                match err.take() {
                    Some(err) => Err(err),
                    None => panic!("polling a resolved Query")
                }
            }
        }
    }
}

//------------ RealQuery -----------------------------------------------------

/// An ongoing query.
struct RealQuery {
    /// The resolver core we are working on.
    core: TaskRc<Core>,

    /// The request we are currently processing.
    request: QueryRequest,

    /// Are we on datagram track?
    ///
    /// A query can be in one of two *tracks,* datagram track or stream
    /// track. Unless the config states that we should use the stream
    /// track only, we will start out in datagram track and only switch to
    /// the stream track if we receive a truncated response.
    dgram: bool,

    /// The index of the service we started at.
    ///
    /// The index references either `core.udp` or `core.tcp`, depending on
    /// the value of `dgram`. We need to keep the index we started at
    /// because of the rotate option which makes us start at a random
    /// service.
    start_index: usize,

    /// The index of the service we currently are using.
    curr_index: usize,

    /// The how-many-th attempt this is, starting at attempt 0.
    attempt: usize
}

impl RealQuery {
    /// Starts a new query.
    ///
    /// Takes a reference to the core, whether to use the datagram track,
    /// and the message and returns the index of the service used and a
    /// new request.
    fn start(core: &Core, dgram: bool, message: MessageBuilder)
             -> (usize, QueryRequest) {
        let track = if dgram { core.udp() }
                    else { core.tcp() };
        let index = if core.conf().options.rotate {
            random::<usize>() % track.len()
        }
        else { 0 };
        let request = QueryRequest::new(message, &track[index]);
        (index, request)
    }

    /// Processes a response.
    ///
    /// This will either resolve the future or switch to stream mode.
    fn response(&mut self, response: MessageBuf, message: MessageBuilder)
                -> Poll<MessageBuf, Error> {
        if response.header().tc() && self.dgram
                && !self.core.with(|core| core.options().ign_tc)
        {
            self.start_stream(message)
        }
        else { Ok(response.into()) }
    }

    /// Proceeds to the next request or errors out.
    fn next_request(&mut self, message: MessageBuilder)
                    -> Poll<MessageBuf, Error> {
        self.curr_index += 1;
        if (self.curr_index % self.track_len()) == self.start_index {
            self.attempt += 1;
            if self.attempt == self.core.with(|core| core.conf().attempts) {
                return Err(Error::Timeout)
            }
            let dgram = self.dgram;
            let (index, request) = self.core.with(|core| {
                Self::start(core, dgram, message)
            });
            self.start_index = index;
            self.curr_index = index;
            self.request = request;
        }
        else {
            let dgram = self.dgram;
            let curr_index = self.curr_index;
            self.request = self.core.with(|core| {
                let track = if dgram { core.udp() }
                            else { core.tcp() };
                QueryRequest::new(message, &track[curr_index])
            });
        }
        self.poll()
    }

    /// Switches to stream mode and starts the first request or errors out.
    fn start_stream(&mut self, message: MessageBuilder)
                    -> Poll<MessageBuf, Error> {
        self.dgram = false;
        let (index, request) = self.core.with(|core| {
            Self::start(core, false, message)
        });
        self.start_index = index;
        self.curr_index = index;
        self.request = request;
        self.poll()
    }

    /// Returns the number of services in the current track.
    fn track_len(&self) -> usize {
        if self.dgram { self.core.with(|core| core.udp().len()) }
        else { self.core.with(|core| core.tcp().len()) }
    }
}

//--- Future

impl Future for RealQuery {
    type Item = MessageBuf;
    type Error = Error;

    /// Polls for completion.
    ///
    /// Polls the current request. If that succeeded, returns the result. If
    /// it failed fatally, returns an error. If it failed non-fatally,
    /// proceeds to the next request.
    fn poll(&mut self) -> Poll<MessageBuf, Error> {
        match self.request.poll() {
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Ok(Async::Ready((Ok(response), message))) => {
                self.response(response, message)
            }
            Ok(Async::Ready((Err(_), message))) => {
                self.next_request(message)
            }
            Err(err) => Err(err.into())
        }
    }
}

<commit_msg>Turn compression off for resolver requests.<commit_after>//! A DNS query.

use futures::{Async, Future, Poll};
use futures::task::TaskRc;
use rand::random;
use ::bits::{DName, ComposeMode, ComposeResult, MessageBuilder, MessageBuf};
use ::iana::{Class, Rtype};
use super::ResolverTask;
use super::conf::ResolvOptions;
use super::core::Core;
use super::error::Error;
use super::request::QueryRequest;

//------------ Query ---------------------------------------------------------

/// A DNS query.
///
/// A query is a future that resolves a DNS question for all the resource
/// records for a given domain name, record type, and class into either a
/// response or a query error. It will follow the rules set down by the
/// resolver configuration in trying to find an upstream server that
/// replies to the question.
///
/// A query is actually a combinator of sorts. It needs a [`ResolverTask`]
/// to operate on which in itself is the result of a future, namely that
/// returned by [`Resolver::start()`]. As such, you cannot use a query by
/// itself. Please see the module level documentation for some examples on
/// how to start a query.
//
//  Since a query can fail very early on when building the request message,
//  it internally consists of a `Result`. If it is `Ok()`, we really do have
//  a query to poll, otherwise we have an error to take out and return.
pub struct Query(Result<RealQuery, Option<Error>>);

impl Query {
    /// Creates a new query.
    pub fn new<N: DName>(resolv: &ResolverTask, name: N, rtype: Rtype,
                       class: Class) -> Self {
        let core = resolv.core.clone();
        let message = core.with(|core| {
            Self::build_message(name, rtype, class, core.options())
        });
        let message = match message {
            Ok(message) => message,
            Err(err) => return Query(Err(Some(err.into())))
        };
        let dgram = core.with(|core| !core.conf().options.use_vc);
        let (index, request) = core.with(|c| RealQuery::start(c, dgram,
                                                              message));
        Query(Ok(RealQuery {
            core: core, request: request,
            dgram: dgram, start_index: index, curr_index: index,
            attempt: 0
        }))
    }

    /// Builds the message for this query.
    ///
    /// If this function fails, we are done.
    fn build_message<N: DName>(name: N, rtype: Rtype, class: Class,
                                 opts: &ResolvOptions)
                                 -> ComposeResult<MessageBuilder> {
        let mut res = try!(MessageBuilder::new(ComposeMode::Stream, false));
        res.header_mut().set_rd(opts.recurse);
        try!(res.push((name, rtype, class)));
        Ok(res)
    }
}

//--- Future

impl Future for Query {
    type Item = MessageBuf;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0 {
            Ok(ref mut query) => query.poll(),
            Err(ref mut err) => {
                match err.take() {
                    Some(err) => Err(err),
                    None => panic!("polling a resolved Query")
                }
            }
        }
    }
}

//------------ RealQuery -----------------------------------------------------

/// An ongoing query.
struct RealQuery {
    /// The resolver core we are working on.
    core: TaskRc<Core>,

    /// The request we are currently processing.
    request: QueryRequest,

    /// Are we on datagram track?
    ///
    /// A query can be in one of two *tracks,* datagram track or stream
    /// track. Unless the config states that we should use the stream
    /// track only, we will start out in datagram track and only switch to
    /// the stream track if we receive a truncated response.
    dgram: bool,

    /// The index of the service we started at.
    ///
    /// The index references either `core.udp` or `core.tcp`, depending on
    /// the value of `dgram`. We need to keep the index we started at
    /// because of the rotate option which makes us start at a random
    /// service.
    start_index: usize,

    /// The index of the service we currently are using.
    curr_index: usize,

    /// The how-many-th attempt this is, starting at attempt 0.
    attempt: usize
}

impl RealQuery {
    /// Starts a new query.
    ///
    /// Takes a reference to the core, whether to use the datagram track,
    /// and the message and returns the index of the service used and a
    /// new request.
    fn start(core: &Core, dgram: bool, message: MessageBuilder)
             -> (usize, QueryRequest) {
        let track = if dgram { core.udp() }
                    else { core.tcp() };
        let index = if core.conf().options.rotate {
            random::<usize>() % track.len()
        }
        else { 0 };
        let request = QueryRequest::new(message, &track[index]);
        (index, request)
    }

    /// Processes a response.
    ///
    /// This will either resolve the future or switch to stream mode.
    fn response(&mut self, response: MessageBuf, message: MessageBuilder)
                -> Poll<MessageBuf, Error> {
        if response.header().tc() && self.dgram
                && !self.core.with(|core| core.options().ign_tc)
        {
            self.start_stream(message)
        }
        else { Ok(response.into()) }
    }

    /// Proceeds to the next request or errors out.
    fn next_request(&mut self, message: MessageBuilder)
                    -> Poll<MessageBuf, Error> {
        self.curr_index += 1;
        if (self.curr_index % self.track_len()) == self.start_index {
            self.attempt += 1;
            if self.attempt == self.core.with(|core| core.conf().attempts) {
                return Err(Error::Timeout)
            }
            let dgram = self.dgram;
            let (index, request) = self.core.with(|core| {
                Self::start(core, dgram, message)
            });
            self.start_index = index;
            self.curr_index = index;
            self.request = request;
        }
        else {
            let dgram = self.dgram;
            let curr_index = self.curr_index;
            self.request = self.core.with(|core| {
                let track = if dgram { core.udp() }
                            else { core.tcp() };
                QueryRequest::new(message, &track[curr_index])
            });
        }
        self.poll()
    }

    /// Switches to stream mode and starts the first request or errors out.
    fn start_stream(&mut self, message: MessageBuilder)
                    -> Poll<MessageBuf, Error> {
        self.dgram = false;
        let (index, request) = self.core.with(|core| {
            Self::start(core, false, message)
        });
        self.start_index = index;
        self.curr_index = index;
        self.request = request;
        self.poll()
    }

    /// Returns the number of services in the current track.
    fn track_len(&self) -> usize {
        if self.dgram { self.core.with(|core| core.udp().len()) }
        else { self.core.with(|core| core.tcp().len()) }
    }
}

//--- Future

impl Future for RealQuery {
    type Item = MessageBuf;
    type Error = Error;

    /// Polls for completion.
    ///
    /// Polls the current request. If that succeeded, returns the result. If
    /// it failed fatally, returns an error. If it failed non-fatally,
    /// proceeds to the next request.
    fn poll(&mut self) -> Poll<MessageBuf, Error> {
        match self.request.poll() {
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Ok(Async::Ready((Ok(response), message))) => {
                self.response(response, message)
            }
            Ok(Async::Ready((Err(_), message))) => {
                self.next_request(message)
            }
            Err(err) => Err(err.into())
        }
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;

use criterion::Criterion;

fn fib(n: u64) -> u64 {
    let mut a = 0u64;
    let mut b = 1u64;
    let mut c = 0u64;

    if n == 0 {
        return 0
    }

    for _ in 0..(n+1) {
        c = a + b;
        a = b;
        b = c;
    }

    b
}

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("fib 20", |b| b.iter(|| fib(20)));
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<commit_msg>Swap dummy fib benchmark for opening/closing files<commit_after>#[macro_use]
extern crate criterion;
extern crate fitsio;

use criterion::Criterion;

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("opening and closing files", |b| b.iter(|| {
        let filename = "../testdata/full_example.fits";
        {
            let f = fitsio::FitsFile::open(filename).unwrap();
            /* Implicit drop */
        }
    }));
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Describes a graphical or compute operation.
//!
//! In Vulkan before you can add a draw or a compute command to a command buffer, you have to
//! create a *pipeline object* that describes it.
//!
//! There are two kinds of pipelines:
//!
//! - `ComputePipeline`s, for compute operations that reads/write raw pixels from images and
//!   buffers.
//! - `GraphicsPipeline`s, for graphical operations.
//!
//! All the sub-modules of this module (with the exception of `cache`) correspond to the various
//! steps of pipelines.

pub use self::compute_pipeline::ComputePipeline;
pub use self::compute_pipeline::ComputePipelineAbstract;
pub use self::compute_pipeline::ComputePipelineCreationError;
pub use self::compute_pipeline::ComputePipelineSys;
pub use self::graphics_pipeline::GraphicsPipeline;
pub use self::graphics_pipeline::GraphicsPipelineAbstract;
pub use self::graphics_pipeline::GraphicsPipelineCreationError;
pub use self::graphics_pipeline::GraphicsPipelineParams;
pub use self::graphics_pipeline::GraphicsPipelineParamsTess;
pub use self::graphics_pipeline::GraphicsPipelineSys;

mod compute_pipeline;
mod graphics_pipeline;

pub mod blend;
pub mod cache;
pub mod depth_stencil;
pub mod input_assembly;
pub mod multisample;
pub mod raster;
pub mod shader;
pub mod vertex;
pub mod viewport;
<commit_msg>Some documentation for pipeline objects<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Describes a graphical or compute operation.
//!
//! In Vulkan, before you can add a draw or a compute command to a command buffer you have to
//! create a *pipeline object* that describes this command.
//!
//! When you create a pipeline object, the implementation will usually generate some GPU machine
//! code that will execute the operation (similar to a compiler that generates an executable for
//! the CPU). Consequently it is a CPU-intensive operation that should be performed at
//! initialization or during a loading screen.
//!
//! There are two kinds of pipelines:
//!
//! - `ComputePipeline`s, for compute operations (general-purpose operations that read/write data
//!   in buffers or raw pixels in images).
//! - `GraphicsPipeline`s, for graphical operations (operations that take vertices as input and
//!   write pixels to a framebuffer).
//!
//! # Creating a compute pipeline.
//!
//! In order to create a compute pipeline, you first need a *shader entry point*.
//!
//! TODO: write the rest
//! For now vulkano has no "clean" way to create shaders ; everything's a bit hacky
//!
//! # Creating a graphics pipeline
//!
//! A graphics operation takes vertices or vertices and indices as input, and writes pixels to a
//! framebuffer. It consists of multiple steps:
//!
//! - A *shader* named the *vertex shader* is run once for each vertex of the input.
//! - Vertices are assembled into primitives.
//! - Optionally, a shader named the *tessellation control shader* is run once for each primitive
//!   and indicates the tessellation level to apply for this primitive.
//! - Optionally, a shader named the *tessellation evaluation shader* is run once for each vertex,
//!   including the ones newly created by the tessellation.
//! - Optionally, a shader named the *geometry shader* is run once for each line or triangle.
//! - The vertex coordinates (as outputted by the geometry shader, or by the tessellation
//!   evaluation shader if there's no geometry shader, or by the vertex shader if there's no
//!   geometry shader nor tessellation evaluation shader) are turned into screen-space coordinates.
//! - The list of pixels that cover each triangle are determined.
//! - A shader named the fragment shader is run once for each pixel that covers one of the
//!   triangles.
//! - The depth test and/or the stencil test are performed.
//! - The output of the fragment shader is written to the framebuffer attachments, possibly by
//!   mixing it with the existing values.
//!
//! All the sub-modules of this module (with the exception of `cache`) correspond to the various
//! stages of graphical pipelines.
//!
//! > **Note**: With the exception of the addition of the tessellation shaders and the geometry
//! > shader, these steps haven't changed in the past decade. If you are familiar with shaders in
//! > OpenGL 2 for example, don't worry as it works in the same in Vulkan.
//!
//! > **Note**: All the stages that consist in executing a shader are performed by a microprocessor
//! > (unless you happen to use a software implementation of Vulkan). As for the other stages,
//! > some hardware (usually desktop graphics cards) have dedicated chips that will execute them
//! > while some other hardware (usually mobile) perform them with the microprocessor as well. In
//! > the latter situation, the implementation will usually glue these steps to your shaders.
//!
//! Creating a graphics pipeline follows the same principle as a compute pipeline, except that
//! you must pass multiple shaders alongside with configuration for the other steps.
//!
//! TODO: add an example

pub use self::compute_pipeline::ComputePipeline;
pub use self::compute_pipeline::ComputePipelineAbstract;
pub use self::compute_pipeline::ComputePipelineCreationError;
pub use self::compute_pipeline::ComputePipelineSys;
pub use self::graphics_pipeline::GraphicsPipeline;
pub use self::graphics_pipeline::GraphicsPipelineAbstract;
pub use self::graphics_pipeline::GraphicsPipelineCreationError;
pub use self::graphics_pipeline::GraphicsPipelineParams;
pub use self::graphics_pipeline::GraphicsPipelineParamsTess;
pub use self::graphics_pipeline::GraphicsPipelineSys;

mod compute_pipeline;
mod graphics_pipeline;

pub mod blend;
pub mod cache;
pub mod depth_stencil;
pub mod input_assembly;
pub mod multisample;
pub mod raster;
pub mod shader;
pub mod vertex;
pub mod viewport;
<|endoftext|>


<commit_before>// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;

use stack::Stack;
use super::common::{push, rust_trampoline};

pub const STACK_ALIGN: usize = 16;

#[allow(raw_pointer_derive)]
#[derive(Copy, Clone)]
pub struct Registers {
  rsp: *mut usize
}

impl Registers {
  #[inline]
  pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
    let sp_limit = stack.limit();
    let mut sp = stack.top() as *mut usize;
    let f_ptr = push(&mut sp, f);

    asm!(include_str!("init.s")
          : "={rdi}"(sp)
          : "{rdi}" (sp),
            "{rsi}" (rust_trampoline::<F>),
            "{rdx}" (f_ptr),
            "{rcx}" (sp_limit)
          :
          : "volatile");

    Registers { rsp: sp }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    asm!(include_str!("swap.s")
          :
          : "{rdi}" (&mut self.rsp)
          : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
            "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
            "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
            "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
            "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
            "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
            "cc"
          : "volatile");
  }
}
<commit_msg>there is no point in Registers being Copy + Clone<commit_after>// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;

use stack::Stack;
use super::common::{push, rust_trampoline};

pub const STACK_ALIGN: usize = 16;

pub struct Registers {
  rsp: *mut usize
}

impl Registers {
  #[inline]
  pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
    let sp_limit = stack.limit();
    let mut sp = stack.top() as *mut usize;
    let f_ptr = push(&mut sp, f);

    asm!(include_str!("init.s")
          : "={rdi}"(sp)
          : "{rdi}" (sp),
            "{rsi}" (rust_trampoline::<F>),
            "{rdx}" (f_ptr),
            "{rcx}" (sp_limit)
          :
          : "volatile");

    Registers { rsp: sp }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    asm!(include_str!("swap.s")
          :
          : "{rdi}" (&mut self.rsp)
          : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
            "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
            "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
            "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
            "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
            "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
            "cc"
          : "volatile");
  }
}
<|endoftext|>