<commit_before>//! The `pattern` element.

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

use crate::aspect_ratio::*;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId, NodeStack};
use crate::drawing_ctx::{DrawingCtx, ViewParams};
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::length::*;
use crate::node::{Node, NodeBorrow, WeakNode};
use crate::parsers::ParseValue;
use crate::properties::ComputedValues;
use crate::rect::Rect;
use crate::transform::Transform;
use crate::unit_interval::UnitInterval;
use crate::viewbox::*;
use crate::xml::Attributes;

coord_units!(PatternUnits, CoordUnits::ObjectBoundingBox);
coord_units!(PatternContentUnits, CoordUnits::UserSpaceOnUse);

#[derive(Clone, Default)]
struct Common {
    units: Option<PatternUnits>,
    content_units: Option<PatternContentUnits>,
    // This Option<Option<ViewBox>> is a bit strange.  We want a field
    // with value None to mean, "this field isn't resolved yet".  However,
    // the vbox can very well be *not* specified in the SVG file.
    // In that case, the fully resolved pattern will have a .vbox=Some(None) value.
    vbox: Option<Option<ViewBox>>,
    preserve_aspect_ratio: Option<AspectRatio>,
    transform: Option<Transform>,
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<ULength<Horizontal>>,
    height: Option<ULength<Vertical>>,
}

/// State used during the pattern resolution process
///
/// This is the current node's pattern information, plus the fallback
/// that should be used in case that information is not complete for a
/// resolved pattern yet.
struct Unresolved {
    pattern: UnresolvedPattern,
    fallback: Option<NodeId>,
}

/// Keeps track of which Pattern provided a non-empty set of children during pattern resolution
#[derive(Clone)]
enum UnresolvedChildren {
    /// Points back to the original Pattern if it had no usable children
    Unresolved,

    /// Points back to the original Pattern, as no pattern in the
    /// chain of fallbacks had usable children.  This only gets returned
    /// by resolve_from_defaults().
    ResolvedEmpty,

    /// Points back to the Pattern that had usable children.
    WithChildren(WeakNode),
}

/// Keeps track of which Pattern provided a non-empty set of children during pattern resolution
#[derive(Clone)]
enum Children {
    Empty,

    /// Points back to the Pattern that had usable children
    WithChildren(WeakNode),
}

/// Main structure used during pattern resolution.  For unresolved
/// patterns, we store all fields as Option<T> - if None, it means
/// that the field is not specified; if Some(T), it means that the
/// field was specified.
struct UnresolvedPattern {
    common: Common,

    // Point back to our corresponding node, or to the fallback node which has children.
    // If the value is None, it means we are fully resolved and didn't find any children
    // among the fallbacks.
    children: UnresolvedChildren,
}

#[derive(Clone)]
pub struct ResolvedPattern {
    units: PatternUnits,
    content_units: PatternContentUnits,
    vbox: Option<ViewBox>,
    preserve_aspect_ratio: AspectRatio,
    transform: Transform,
    x: Length<Horizontal>,
    y: Length<Vertical>,
    width: ULength<Horizontal>,
    height: ULength<Vertical>,
    opacity: UnitInterval,

    // Link to the node whose children are the pattern's resolved children.
    children: Children,
}

/// Pattern normalized to user-space units.
pub struct UserSpacePattern {
    pub width: f64,
    pub height: f64,
    pub transform: Transform,
    pub coord_transform: Transform,
    pub content_transform: Transform,
    pub opacity: UnitInterval,
    pub node_with_children: Node,
}

#[derive(Default)]
pub struct Pattern {
    common: Common,
    fallback: Option<NodeId>,
}

impl SetAttributes for Pattern {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "patternUnits") => self.common.units = attr.parse(value)?,
                expanded_name!("", "patternContentUnits") => {
                    self.common.content_units = attr.parse(value)?
                }
                expanded_name!("", "viewBox") => self.common.vbox = attr.parse(value)?,
                expanded_name!("", "preserveAspectRatio") => {
                    self.common.preserve_aspect_ratio = attr.parse(value)?
                }
                expanded_name!("", "patternTransform") => {
                    self.common.transform = attr.parse(value)?
                }
                ref a if is_href(a) => {
                    set_href(
                        a,
                        &mut self.fallback,
                        NodeId::parse(value).attribute(attr.clone())?,
                    );
                }
                expanded_name!("", "x") => self.common.x = attr.parse(value)?,
                expanded_name!("", "y") => self.common.y = attr.parse(value)?,
                expanded_name!("", "width") => self.common.width = attr.parse(value)?,
                expanded_name!("", "height") => self.common.height = attr.parse(value)?,
                _ => (),
            }
        }

        Ok(())
    }
}

impl Draw for Pattern {}

impl UnresolvedPattern {
    fn into_resolved(self, opacity: UnitInterval) -> ResolvedPattern {
        assert!(self.is_resolved());

        ResolvedPattern {
            units: self.common.units.unwrap(),
            content_units: self.common.content_units.unwrap(),
            vbox: self.common.vbox.unwrap(),
            preserve_aspect_ratio: self.common.preserve_aspect_ratio.unwrap(),
            transform: self.common.transform.unwrap(),
            x: self.common.x.unwrap(),
            y: self.common.y.unwrap(),
            width: self.common.width.unwrap(),
            height: self.common.height.unwrap(),
            opacity,

            children: self.children.to_resolved(),
        }
    }

    fn is_resolved(&self) -> bool {
        self.common.units.is_some()
            && self.common.content_units.is_some()
            && self.common.vbox.is_some()
            && self.common.preserve_aspect_ratio.is_some()
            && self.common.transform.is_some()
            && self.common.x.is_some()
            && self.common.y.is_some()
            && self.common.width.is_some()
            && self.common.height.is_some()
            && self.children.is_resolved()
    }

    fn resolve_from_fallback(&self, fallback: &UnresolvedPattern) -> UnresolvedPattern {
        let units = self.common.units.or(fallback.common.units);
        let content_units = self.common.content_units.or(fallback.common.content_units);
        let vbox = self.common.vbox.or(fallback.common.vbox);
        let preserve_aspect_ratio = self
            .common
            .preserve_aspect_ratio
            .or(fallback.common.preserve_aspect_ratio);
        let transform = self.common.transform.or(fallback.common.transform);
        let x = self.common.x.or(fallback.common.x);
        let y = self.common.y.or(fallback.common.y);
        let width = self.common.width.or(fallback.common.width);
        let height = self.common.height.or(fallback.common.height);
        let children = self.children.resolve_from_fallback(&fallback.children);

        UnresolvedPattern {
            common: Common {
                units,
                content_units,
                vbox,
                preserve_aspect_ratio,
                transform,
                x,
                y,
                width,
                height,
            },
            children,
        }
    }

    fn resolve_from_defaults(&self) -> UnresolvedPattern {
        let units = self.common.units.or_else(|| Some(PatternUnits::default()));
        let content_units = self
            .common
            .content_units
            .or_else(|| Some(PatternContentUnits::default()));
        let vbox = self.common.vbox.or(Some(None));
        let preserve_aspect_ratio = self
            .common
            .preserve_aspect_ratio
            .or_else(|| Some(AspectRatio::default()));
        let transform = self.common.transform.or_else(|| Some(Transform::default()));
        let x = self.common.x.or_else(|| Some(Default::default()));
        let y = self.common.y.or_else(|| Some(Default::default()));
        let width = self.common.width.or_else(|| Some(Default::default()));
        let height = self.common.height.or_else(|| Some(Default::default()));
        let children = self.children.resolve_from_defaults();

        UnresolvedPattern {
            common: Common {
                units,
                content_units,
                vbox,
                preserve_aspect_ratio,
                transform,
                x,
                y,
                width,
                height,
            },
            children,
        }
    }
}

impl UnresolvedChildren {
    fn from_node(node: &Node) -> UnresolvedChildren {
        let weak = node.downgrade();

        if node.children().any(|child| child.is_element()) {
            UnresolvedChildren::WithChildren(weak)
        } else {
            UnresolvedChildren::Unresolved
        }
    }

    fn is_resolved(&self) -> bool {
        !matches!(*self, UnresolvedChildren::Unresolved)
    }

    fn resolve_from_fallback(&self, fallback: &UnresolvedChildren) -> UnresolvedChildren {
        use UnresolvedChildren::*;

        match (self, fallback) {
            (&Unresolved, &Unresolved) => Unresolved,
            (&WithChildren(ref wc), _) => WithChildren(wc.clone()),
            (_, &WithChildren(ref wc)) => WithChildren(wc.clone()),
            (_, _) => unreachable!(),
        }
    }

    fn resolve_from_defaults(&self) -> UnresolvedChildren {
        use UnresolvedChildren::*;

        match *self {
            Unresolved => ResolvedEmpty,
            _ => (*self).clone(),
        }
    }

    fn to_resolved(&self) -> Children {
        use UnresolvedChildren::*;

        assert!(self.is_resolved());

        match *self {
            ResolvedEmpty => Children::Empty,
            WithChildren(ref wc) => Children::WithChildren(wc.clone()),
            _ => unreachable!(),
        }
    }
}

impl ResolvedPattern {
    fn node_with_children(&self) -> Option<Node> {
        match self.children {
            // This means we didn't find any children among the fallbacks,
            // so there is nothing to render.
            Children::Empty => None,

            Children::WithChildren(ref wc) => Some(wc.upgrade().unwrap()),
        }
    }

    fn get_rect(&self, values: &ComputedValues, params: &ViewParams) -> Rect {
        let x = self.x.normalize(&values, &params);
        let y = self.y.normalize(&values, &params);
        let w = self.width.normalize(&values, &params);
        let h = self.height.normalize(&values, &params);

        Rect::new(x, y, x + w, y + h)
    }

    pub fn to_user_space(
        &self,
        bbox: &BoundingBox,
        draw_ctx: &DrawingCtx,
        values: &ComputedValues,
    ) -> Option<UserSpacePattern> {
        let node_with_children = self.node_with_children()?;

        let params = draw_ctx.push_coord_units(self.units.0);

        let rect = self.get_rect(values, &params);
        let bbrect = bbox.rect.unwrap();

        // Create the pattern coordinate system
        let (width, height, coord_transform) = match self.units {
            PatternUnits(CoordUnits::ObjectBoundingBox) => (
                rect.width() * bbrect.width(),
                rect.height() * bbrect.height(),
                Transform::new_translate(
                    bbrect.x0 + rect.x0 * bbrect.width(),
                    bbrect.y0 + rect.y0 * bbrect.height(),
                ),
            ),
            PatternUnits(CoordUnits::UserSpaceOnUse) => (
                rect.width(),
                rect.height(),
                Transform::new_translate(rect.x0, rect.y0),
            ),
        };

        let coord_transform = coord_transform.post_transform(&self.transform);

        // Create the pattern contents coordinate system
        let content_transform = if let Some(vbox) = self.vbox {
            // If there is a vbox, use that
            let r = self
                .preserve_aspect_ratio
                .compute(&vbox, &Rect::from_size(width, height));

            let sw = r.width() / vbox.width();
            let sh = r.height() / vbox.height();
            let x = r.x0 - vbox.x0 * sw;
            let y = r.y0 - vbox.y0 * sh;

            Transform::new_scale(sw, sh).pre_translate(x, y)
        } else {
            let PatternContentUnits(content_units) = self.content_units;

            match content_units {
                CoordUnits::ObjectBoundingBox => {
                    Transform::new_scale(bbrect.width(), bbrect.height())
                }
                CoordUnits::UserSpaceOnUse => Transform::identity(),
            }
        };

        Some(UserSpacePattern {
            width,
            height,
            transform: self.transform,
            coord_transform,
            content_transform,
            opacity: self.opacity,
            node_with_children,
        })
    }
}

impl Pattern {
    fn get_unresolved(&self, node: &Node) -> Unresolved {
        let pattern = UnresolvedPattern {
            common: self.common.clone(),
            children: UnresolvedChildren::from_node(node),
        };

        Unresolved {
            pattern,
            fallback: self.fallback.clone(),
        }
    }

    pub fn resolve(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes<'_>,
        opacity: UnitInterval,
    ) -> Result<ResolvedPattern, AcquireError> {
        let Unresolved {
            mut pattern,
            mut fallback,
        } = self.get_unresolved(node);

        let mut stack = NodeStack::new();

        while !pattern.is_resolved() {
            if let Some(ref node_id) = fallback {
                match acquired_nodes.acquire(&node_id) {
                    Ok(acquired) => {
                        let acquired_node = acquired.get();

                        if stack.contains(acquired_node) {
                            return Err(AcquireError::CircularReference(acquired_node.clone()));
                        }

                        match *acquired_node.borrow_element() {
                            Element::Pattern(ref p) => {
                                let unresolved = p.get_unresolved(&acquired_node);
                                pattern = pattern.resolve_from_fallback(&unresolved.pattern);
                                fallback = unresolved.fallback;

                                stack.push(acquired_node);
                            }
                            _ => return Err(AcquireError::InvalidLinkType(node_id.clone())),
                        }
                    }

                    Err(AcquireError::MaxReferencesExceeded) => {
                        return Err(AcquireError::MaxReferencesExceeded)
                    }

                    Err(e) => {
                        rsvg_log!("Stopping pattern resolution: {}", e);
                        pattern = pattern.resolve_from_defaults();
                        break;
                    }
                }
            } else {
                pattern = pattern.resolve_from_defaults();
                break;
            }
        }

        Ok(pattern.into_resolved(opacity))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::node::NodeData;
    use markup5ever::{namespace_url, ns, QualName};

    #[test]
    fn pattern_resolved_from_defaults_is_really_resolved() {
        let node = Node::new(NodeData::new_element(
            &QualName::new(None, ns!(svg), local_name!("pattern")),
            Attributes::new(),
        ));

        let unresolved = borrow_element_as!(node, Pattern).get_unresolved(&node);
        let pattern = unresolved.pattern.resolve_from_defaults();
        assert!(pattern.is_resolved());
    }
}
<commit_msg>pattern.rs: use NormalizeParams<commit_after>//! The `pattern` element.

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

use crate::aspect_ratio::*;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId, NodeStack};
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
use crate::length::*;
use crate::node::{Node, NodeBorrow, WeakNode};
use crate::parsers::ParseValue;
use crate::properties::ComputedValues;
use crate::rect::Rect;
use crate::transform::Transform;
use crate::unit_interval::UnitInterval;
use crate::viewbox::*;
use crate::xml::Attributes;

coord_units!(PatternUnits, CoordUnits::ObjectBoundingBox);
coord_units!(PatternContentUnits, CoordUnits::UserSpaceOnUse);

#[derive(Clone, Default)]
struct Common {
    units: Option<PatternUnits>,
    content_units: Option<PatternContentUnits>,
    // This Option<Option<ViewBox>> is a bit strange.  We want a field
    // with value None to mean, "this field isn't resolved yet".  However,
    // the vbox can very well be *not* specified in the SVG file.
    // In that case, the fully resolved pattern will have a .vbox=Some(None) value.
    vbox: Option<Option<ViewBox>>,
    preserve_aspect_ratio: Option<AspectRatio>,
    transform: Option<Transform>,
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<ULength<Horizontal>>,
    height: Option<ULength<Vertical>>,
}

/// State used during the pattern resolution process
///
/// This is the current node's pattern information, plus the fallback
/// that should be used in case that information is not complete for a
/// resolved pattern yet.
struct Unresolved {
    pattern: UnresolvedPattern,
    fallback: Option<NodeId>,
}

/// Keeps track of which Pattern provided a non-empty set of children during pattern resolution
#[derive(Clone)]
enum UnresolvedChildren {
    /// Points back to the original Pattern if it had no usable children
    Unresolved,

    /// Points back to the original Pattern, as no pattern in the
    /// chain of fallbacks had usable children.  This only gets returned
    /// by resolve_from_defaults().
    ResolvedEmpty,

    /// Points back to the Pattern that had usable children.
    WithChildren(WeakNode),
}

/// Keeps track of which Pattern provided a non-empty set of children during pattern resolution
#[derive(Clone)]
enum Children {
    Empty,

    /// Points back to the Pattern that had usable children
    WithChildren(WeakNode),
}

/// Main structure used during pattern resolution.  For unresolved
/// patterns, we store all fields as Option<T> - if None, it means
/// that the field is not specified; if Some(T), it means that the
/// field was specified.
struct UnresolvedPattern {
    common: Common,

    // Point back to our corresponding node, or to the fallback node which has children.
    // If the value is None, it means we are fully resolved and didn't find any children
    // among the fallbacks.
    children: UnresolvedChildren,
}

#[derive(Clone)]
pub struct ResolvedPattern {
    units: PatternUnits,
    content_units: PatternContentUnits,
    vbox: Option<ViewBox>,
    preserve_aspect_ratio: AspectRatio,
    transform: Transform,
    x: Length<Horizontal>,
    y: Length<Vertical>,
    width: ULength<Horizontal>,
    height: ULength<Vertical>,
    opacity: UnitInterval,

    // Link to the node whose children are the pattern's resolved children.
    children: Children,
}

/// Pattern normalized to user-space units.
pub struct UserSpacePattern {
    pub width: f64,
    pub height: f64,
    pub transform: Transform,
    pub coord_transform: Transform,
    pub content_transform: Transform,
    pub opacity: UnitInterval,
    pub node_with_children: Node,
}

#[derive(Default)]
pub struct Pattern {
    common: Common,
    fallback: Option<NodeId>,
}

impl SetAttributes for Pattern {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "patternUnits") => self.common.units = attr.parse(value)?,
                expanded_name!("", "patternContentUnits") => {
                    self.common.content_units = attr.parse(value)?
                }
                expanded_name!("", "viewBox") => self.common.vbox = attr.parse(value)?,
                expanded_name!("", "preserveAspectRatio") => {
                    self.common.preserve_aspect_ratio = attr.parse(value)?
                }
                expanded_name!("", "patternTransform") => {
                    self.common.transform = attr.parse(value)?
                }
                ref a if is_href(a) => {
                    set_href(
                        a,
                        &mut self.fallback,
                        NodeId::parse(value).attribute(attr.clone())?,
                    );
                }
                expanded_name!("", "x") => self.common.x = attr.parse(value)?,
                expanded_name!("", "y") => self.common.y = attr.parse(value)?,
                expanded_name!("", "width") => self.common.width = attr.parse(value)?,
                expanded_name!("", "height") => self.common.height = attr.parse(value)?,
                _ => (),
            }
        }

        Ok(())
    }
}

impl Draw for Pattern {}

impl UnresolvedPattern {
    fn into_resolved(self, opacity: UnitInterval) -> ResolvedPattern {
        assert!(self.is_resolved());

        ResolvedPattern {
            units: self.common.units.unwrap(),
            content_units: self.common.content_units.unwrap(),
            vbox: self.common.vbox.unwrap(),
            preserve_aspect_ratio: self.common.preserve_aspect_ratio.unwrap(),
            transform: self.common.transform.unwrap(),
            x: self.common.x.unwrap(),
            y: self.common.y.unwrap(),
            width: self.common.width.unwrap(),
            height: self.common.height.unwrap(),
            opacity,

            children: self.children.to_resolved(),
        }
    }

    fn is_resolved(&self) -> bool {
        self.common.units.is_some()
            && self.common.content_units.is_some()
            && self.common.vbox.is_some()
            && self.common.preserve_aspect_ratio.is_some()
            && self.common.transform.is_some()
            && self.common.x.is_some()
            && self.common.y.is_some()
            && self.common.width.is_some()
            && self.common.height.is_some()
            && self.children.is_resolved()
    }

    fn resolve_from_fallback(&self, fallback: &UnresolvedPattern) -> UnresolvedPattern {
        let units = self.common.units.or(fallback.common.units);
        let content_units = self.common.content_units.or(fallback.common.content_units);
        let vbox = self.common.vbox.or(fallback.common.vbox);
        let preserve_aspect_ratio = self
            .common
            .preserve_aspect_ratio
            .or(fallback.common.preserve_aspect_ratio);
        let transform = self.common.transform.or(fallback.common.transform);
        let x = self.common.x.or(fallback.common.x);
        let y = self.common.y.or(fallback.common.y);
        let width = self.common.width.or(fallback.common.width);
        let height = self.common.height.or(fallback.common.height);
        let children = self.children.resolve_from_fallback(&fallback.children);

        UnresolvedPattern {
            common: Common {
                units,
                content_units,
                vbox,
                preserve_aspect_ratio,
                transform,
                x,
                y,
                width,
                height,
            },
            children,
        }
    }

    fn resolve_from_defaults(&self) -> UnresolvedPattern {
        let units = self.common.units.or_else(|| Some(PatternUnits::default()));
        let content_units = self
            .common
            .content_units
            .or_else(|| Some(PatternContentUnits::default()));
        let vbox = self.common.vbox.or(Some(None));
        let preserve_aspect_ratio = self
            .common
            .preserve_aspect_ratio
            .or_else(|| Some(AspectRatio::default()));
        let transform = self.common.transform.or_else(|| Some(Transform::default()));
        let x = self.common.x.or_else(|| Some(Default::default()));
        let y = self.common.y.or_else(|| Some(Default::default()));
        let width = self.common.width.or_else(|| Some(Default::default()));
        let height = self.common.height.or_else(|| Some(Default::default()));
        let children = self.children.resolve_from_defaults();

        UnresolvedPattern {
            common: Common {
                units,
                content_units,
                vbox,
                preserve_aspect_ratio,
                transform,
                x,
                y,
                width,
                height,
            },
            children,
        }
    }
}

impl UnresolvedChildren {
    fn from_node(node: &Node) -> UnresolvedChildren {
        let weak = node.downgrade();

        if node.children().any(|child| child.is_element()) {
            UnresolvedChildren::WithChildren(weak)
        } else {
            UnresolvedChildren::Unresolved
        }
    }

    fn is_resolved(&self) -> bool {
        !matches!(*self, UnresolvedChildren::Unresolved)
    }

    fn resolve_from_fallback(&self, fallback: &UnresolvedChildren) -> UnresolvedChildren {
        use UnresolvedChildren::*;

        match (self, fallback) {
            (&Unresolved, &Unresolved) => Unresolved,
            (&WithChildren(ref wc), _) => WithChildren(wc.clone()),
            (_, &WithChildren(ref wc)) => WithChildren(wc.clone()),
            (_, _) => unreachable!(),
        }
    }

    fn resolve_from_defaults(&self) -> UnresolvedChildren {
        use UnresolvedChildren::*;

        match *self {
            Unresolved => ResolvedEmpty,
            _ => (*self).clone(),
        }
    }

    fn to_resolved(&self) -> Children {
        use UnresolvedChildren::*;

        assert!(self.is_resolved());

        match *self {
            ResolvedEmpty => Children::Empty,
            WithChildren(ref wc) => Children::WithChildren(wc.clone()),
            _ => unreachable!(),
        }
    }
}

impl ResolvedPattern {
    fn node_with_children(&self) -> Option<Node> {
        match self.children {
            // This means we didn't find any children among the fallbacks,
            // so there is nothing to render.
            Children::Empty => None,

            Children::WithChildren(ref wc) => Some(wc.upgrade().unwrap()),
        }
    }

    fn get_rect(&self, params: &NormalizeParams) -> Rect {
        let x = self.x.to_user(params);
        let y = self.y.to_user(params);
        let w = self.width.to_user(params);
        let h = self.height.to_user(params);

        Rect::new(x, y, x + w, y + h)
    }

    pub fn to_user_space(
        &self,
        bbox: &BoundingBox,
        draw_ctx: &DrawingCtx,
        values: &ComputedValues,
    ) -> Option<UserSpacePattern> {
        let node_with_children = self.node_with_children()?;

        let view_params = draw_ctx.push_coord_units(self.units.0);
        let params = NormalizeParams::new(values, &view_params);

        let rect = self.get_rect(&params);
        let bbrect = bbox.rect.unwrap();

        // Create the pattern coordinate system
        let (width, height, coord_transform) = match self.units {
            PatternUnits(CoordUnits::ObjectBoundingBox) => (
                rect.width() * bbrect.width(),
                rect.height() * bbrect.height(),
                Transform::new_translate(
                    bbrect.x0 + rect.x0 * bbrect.width(),
                    bbrect.y0 + rect.y0 * bbrect.height(),
                ),
            ),
            PatternUnits(CoordUnits::UserSpaceOnUse) => (
                rect.width(),
                rect.height(),
                Transform::new_translate(rect.x0, rect.y0),
            ),
        };

        let coord_transform = coord_transform.post_transform(&self.transform);

        // Create the pattern contents coordinate system
        let content_transform = if let Some(vbox) = self.vbox {
            // If there is a vbox, use that
            let r = self
                .preserve_aspect_ratio
                .compute(&vbox, &Rect::from_size(width, height));

            let sw = r.width() / vbox.width();
            let sh = r.height() / vbox.height();
            let x = r.x0 - vbox.x0 * sw;
            let y = r.y0 - vbox.y0 * sh;

            Transform::new_scale(sw, sh).pre_translate(x, y)
        } else {
            let PatternContentUnits(content_units) = self.content_units;

            match content_units {
                CoordUnits::ObjectBoundingBox => {
                    Transform::new_scale(bbrect.width(), bbrect.height())
                }
                CoordUnits::UserSpaceOnUse => Transform::identity(),
            }
        };

        Some(UserSpacePattern {
            width,
            height,
            transform: self.transform,
            coord_transform,
            content_transform,
            opacity: self.opacity,
            node_with_children,
        })
    }
}

impl Pattern {
    fn get_unresolved(&self, node: &Node) -> Unresolved {
        let pattern = UnresolvedPattern {
            common: self.common.clone(),
            children: UnresolvedChildren::from_node(node),
        };

        Unresolved {
            pattern,
            fallback: self.fallback.clone(),
        }
    }

    pub fn resolve(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes<'_>,
        opacity: UnitInterval,
    ) -> Result<ResolvedPattern, AcquireError> {
        let Unresolved {
            mut pattern,
            mut fallback,
        } = self.get_unresolved(node);

        let mut stack = NodeStack::new();

        while !pattern.is_resolved() {
            if let Some(ref node_id) = fallback {
                match acquired_nodes.acquire(&node_id) {
                    Ok(acquired) => {
                        let acquired_node = acquired.get();

                        if stack.contains(acquired_node) {
                            return Err(AcquireError::CircularReference(acquired_node.clone()));
                        }

                        match *acquired_node.borrow_element() {
                            Element::Pattern(ref p) => {
                                let unresolved = p.get_unresolved(&acquired_node);
                                pattern = pattern.resolve_from_fallback(&unresolved.pattern);
                                fallback = unresolved.fallback;

                                stack.push(acquired_node);
                            }
                            _ => return Err(AcquireError::InvalidLinkType(node_id.clone())),
                        }
                    }

                    Err(AcquireError::MaxReferencesExceeded) => {
                        return Err(AcquireError::MaxReferencesExceeded)
                    }

                    Err(e) => {
                        rsvg_log!("Stopping pattern resolution: {}", e);
                        pattern = pattern.resolve_from_defaults();
                        break;
                    }
                }
            } else {
                pattern = pattern.resolve_from_defaults();
                break;
            }
        }

        Ok(pattern.into_resolved(opacity))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::node::NodeData;
    use markup5ever::{namespace_url, ns, QualName};

    #[test]
    fn pattern_resolved_from_defaults_is_really_resolved() {
        let node = Node::new(NodeData::new_element(
            &QualName::new(None, ns!(svg), local_name!("pattern")),
            Attributes::new(),
        ));

        let unresolved = borrow_element_as!(node, Pattern).get_unresolved(&node);
        let pattern = unresolved.pattern.resolve_from_defaults();
        assert!(pattern.is_resolved());
    }
}
<|endoftext|>


<commit_before>use fftw::*;
use ndarray::*;
use std::f64::consts::PI;

use traits::*;

#[derive(Clone)]
pub struct KSE {
    n: usize,
    n_coef: usize,
    k: Array1<c64>,
    u_pair: Pair<f64, c64>,
    ux_pair: Pair<f64, c64>,
}

impl ModelSpec for KSE {
    type Scalar = c64;
    type Dim = Ix1;
    fn model_size(&self) -> usize {
        self.n_coef
    }
}

impl KSE {
    pub fn new(n: usize, length: f64) -> Self {
        let n_coef = n / 2 + 1;
        let k = Array::from_iter((0..n_coef).map(|i| c64::new(0.0, 2.0 * PI * i as f64 / length)));
        let u_pair = Pair::r2c_1d(n, FLAG::FFTW_ESTIMATE);
        let ux_pair = Pair::r2c_1d(n, FLAG::FFTW_ESTIMATE);
        KSE {
            n,
            n_coef,
            k,
            u_pair,
            ux_pair,
        }
    }

    /// Convert the coefficient to the field value for easy visualization
    pub fn convert_u(&mut self, u_coef: &[c64]) -> &[f64] {
        for (c, uc) in self.u_pair.coef.iter_mut().zip(u_coef.iter()) {
            *c = *uc;
        }
        self.u_pair.backward();
        &self.u_pair.field
    }
}

impl SemiImplicit for KSE {
    fn nlin<'a, S>(&mut self, u: &'a mut ArrayBase<S, Self::Dim>) -> &'a mut ArrayBase<S, Self::Dim>
    where
        S: DataMut<Elem = Self::Scalar>,
    {
        for i in 0..self.n_coef {
            self.u_pair.coef[i] = u[i];
            self.ux_pair.coef[i] = self.k[i] * u[i];
        }
        self.u_pair.backward();
        self.ux_pair.backward();
        for (up, uxp) in self.u_pair.field.iter_mut().zip(self.ux_pair.field.iter()) {
            *up = -*up * *uxp;
        }
        self.u_pair.forward();
        for (up, u) in self.u_pair.coef.iter().zip(u.iter_mut()) {
            *u = *up / self.n as f64;
        }
        u
    }
}

impl StiffDiagonal for KSE {
    fn diag(&self) -> Array1<c64> {
        let k2 = &self.k * &self.k;
        let k4 = &k2 * &k2;
        -k2 - k4
    }
}
<commit_msg>Implement Clone for KSE<commit_after>use fftw::*;
use ndarray::*;
use std::f64::consts::PI;

use traits::*;

pub struct KSE {
    n: usize,
    n_coef: usize,
    length: f64,
    k: Array1<c64>,
    u_pair: Pair<f64, c64>,
    ux_pair: Pair<f64, c64>,
}

impl Clone for KSE {
    fn clone(&self) -> Self {
        Self::new(self.n, self.length)
    }
}

impl ModelSpec for KSE {
    type Scalar = c64;
    type Dim = Ix1;
    fn model_size(&self) -> usize {
        self.n_coef
    }
}

impl KSE {
    pub fn new(n: usize, length: f64) -> Self {
        let n_coef = n / 2 + 1;
        let k = Array::from_iter((0..n_coef).map(|i| c64::new(0.0, 2.0 * PI * i as f64 / length)));
        let u_pair = Pair::r2c_1d(n, FLAG::FFTW_ESTIMATE);
        let ux_pair = Pair::r2c_1d(n, FLAG::FFTW_ESTIMATE);
        KSE {
            n,
            n_coef,
            length,
            k,
            u_pair,
            ux_pair,
        }
    }

    /// Convert the coefficient to the field value for easy visualization
    pub fn convert_u(&mut self, u_coef: &[c64]) -> &[f64] {
        for (c, uc) in self.u_pair.coef.iter_mut().zip(u_coef.iter()) {
            *c = *uc;
        }
        self.u_pair.backward();
        &self.u_pair.field
    }
}

impl SemiImplicit for KSE {
    fn nlin<'a, S>(&mut self, u: &'a mut ArrayBase<S, Self::Dim>) -> &'a mut ArrayBase<S, Self::Dim>
    where
        S: DataMut<Elem = Self::Scalar>,
    {
        for i in 0..self.n_coef {
            self.u_pair.coef[i] = u[i];
            self.ux_pair.coef[i] = self.k[i] * u[i];
        }
        self.u_pair.backward();
        self.ux_pair.backward();
        for (up, uxp) in self.u_pair.field.iter_mut().zip(self.ux_pair.field.iter()) {
            *up = -*up * *uxp;
        }
        self.u_pair.forward();
        for (up, u) in self.u_pair.coef.iter().zip(u.iter_mut()) {
            *u = *up / self.n as f64;
        }
        u
    }
}

impl StiffDiagonal for KSE {
    fn diag(&self) -> Array1<c64> {
        let k2 = &self.k * &self.k;
        let k4 = &k2 * &k2;
        -k2 - k4
    }
}
<|endoftext|>


<commit_before>use libc::*;
use std::mem;
// I tried
// It's a bit hard to write this without a Windows pc on hand...
#[link(name = "XINPUT9_1_0")]
extern "stdcall" {
	fn XInputGetCapabilities(index: u32, flags: u32, capabilities: *mut Capabilities) -> i32;
	fn XInputGetState(index: u32, state: *mut State) -> i32;
}

#[repr(C)]
struct State {
	packet_number: i32,
	gamepad: Gamepad
}

#[repr(C)]
struct Capabilities {
	_type: u8,
	sub_type: u8,
	flags: u32,
	gamepad: Gamepad,
	vibration: Vibration
}

bitflags!(
	flags Buttons: u32 {
		const DPAD_UP = 0x0001,
		const DPAD_DOWN = 0x0002,
		const DPAD_LEFT = 0x0004,
		const DPAD_RIGHT = 0x0008,
		const START = 0x0010,
		const BACK = 0x0020,
		const LEFT_THUMB = 0x0040,
		const RIGHT_THUMB = 0x0080,
		const LEFT_SHOULDER = 0x0100,
		const RIGHT_SHOULDER = 0x0200,
		const A = 0x1000,
		const B = 0x2000,
		const X = 0x4000,
		const Y = 0x8000,
	}
);
#[repr(C)]
#[derive(Copy)]
struct Gamepad {
	buttons: Buttons,
	left_trigger: u8,
	right_trigger: u8,
	thumb_lx: i16,
	thumb_ly: i16,
	thumb_rx: i16,
	thumb_ry: i16
}
#[repr(C)]
struct Vibration {
	left_motor_speed: i32,
	right_motor_speed: i32
}

pub struct NativeJoystick {
	index: u8,
	last: Gamepad
}
impl ::Joystick for NativeJoystick {
	fn new(index: u8) -> Result<NativeJoystick, &'static str> {
		unsafe {
			let mut caps:Capabilities = mem::uninitialized();
			XInputGetCapabilities(index as u32, 0, &mut caps);
			Ok(NativeJoystick {
				index: index,
				last: caps.gamepad
			})
		}
	}
	fn get_index(&self) -> u8 {
		self.index
	}
}
impl ::StatefulJoystick for NativeJoystick {
	fn get_axis(&self, index: usize) -> Option<i16> {
		match index {
			0 => Some(self.last.thumb_lx),
			1 => Some(self.last.thumb_ly),
			2 => Some(self.last.thumb_rx),
			3 => Some(self.last.thumb_ry),
			_ => None
		}
	}
	fn get_button(&self, index: usize) -> Option<bool> {
		let bits = match index {
			0 => Some(A),
			1 => Some(B),
			2 => Some(X),
			3 => Some(Y),
			_ => None
		};
		bits.map(|v| self.last.buttons.contains(v))
	}
}
<commit_msg>Improve windows support<commit_after>use libc::*;
use std::mem;
use std::collections::VecDeque;
// I tried
// It's a bit hard to write this without a Windows pc on hand...
#[link(name = "XINPUT9_1_0")]
extern "stdcall" {
	fn XInputGetCapabilities(index: u32, flags: u32, capabilities: *mut Capabilities) -> i32;
	fn XInputGetState(index: u32, state: *mut State) -> i32;
}

#[repr(C)]
struct State {
	packet: i32,
	gamepad: Gamepad
}

#[repr(C)]
struct Capabilities {
	_type: u8,
	sub_type: u8,
	flags: u32,
	gamepad: Gamepad,
	vibration: Vibration
}

bitflags!(
	flags Buttons: u32 {
		const DPAD_UP = 0x0001,
		const DPAD_DOWN = 0x0002,
		const DPAD_LEFT = 0x0004,
		const DPAD_RIGHT = 0x0008,
		const START = 0x0010,
		const BACK = 0x0020,
		const LEFT_THUMB = 0x0040,
		const RIGHT_THUMB = 0x0080,
		const LEFT_SHOULDER = 0x0100,
		const RIGHT_SHOULDER = 0x0200,
		const A = 0x1000,
		const B = 0x2000,
		const X = 0x4000,
		const Y = 0x8000,
	}
);
#[repr(C)]
#[derive(Copy)]
struct Gamepad {
	buttons: Buttons,
	left_trigger: u8,
	right_trigger: u8,
	thumb_lx: i16,
	thumb_ly: i16,
	thumb_rx: i16,
	thumb_ry: i16
}
#[repr(C)]
struct Vibration {
	left_motor_speed: i32,
	right_motor_speed: i32
}

pub struct NativeJoystick {
	index: u8,
	last: Gamepad,
	last_packet: i32,
	events: VecDeque<::Event>
}
impl ::Joystick for NativeJoystick {
	type WithState = NativeJoystick;
	fn new(index: u8) -> Result<NativeJoystick, &'static str> {
		unsafe {
			let mut caps: Capabilities = mem::uninitialized();
			XInputGetCapabilities(index as u32, 0, &mut caps);
			Ok(NativeJoystick {
				index: index,
				last: caps.gamepad,
				last_packet: 0,
				events: VecDeque::with_capacity(10)
			})
		}
	}
	fn poll(&mut self) -> Option<::Event> {
		use ::StatefulJoystick;
		self.update();
		self.events.pop_back()
	}
	fn is_connected(&self) -> bool {
		true
	}
	fn get_id(&self) -> String {
		String::from_str("XInput Device")
	}
	fn get_index(&self) -> u8 {
		self.index
	}
	fn get_num_buttons(&self) -> u8 {
		4
	}
	fn get_num_axes(&self) -> u8 {
		4
	}
	fn with_state(self) -> NativeJoystick {
		self
	}
}
macro_rules! event{
	(button $this:expr, $now:expr, $last:expr, $btn:expr, $id:expr) => (
		{
			let now_btn = $now.buttons.contains($btn);
			let last_btn = $last.buttons.contains($btn);
			if now_btn && !last_btn {
				$this.events.push_back(::Event::ButtonPressed($id))
			} else if !now_btn && last_btn {
				$this.events.push_back(::Event::ButtonReleased($id))
			}
		}
	);
	(axis $this:expr, $now:expr, $last:expr, $field:ident, $id:expr) => (
		if $now.$field != $last.$field {
			$this.events.push_back(::Event::JoystickMoved($id, $now.$field))
		}
	);
	(axes $this:expr, $now:expr, $last:expr, $($field:ident => $id:expr),+) => ({
		$(event!(axis $this, $now, $last, $field, $id);)+
	});
	(buttons $this:expr, $now:expr, $last:expr, $($btn:ident => $id:expr),+) => ({
		$(event!(button $this, $now, $last, $btn, $id);)+
	});
}
impl ::StatefulJoystick for NativeJoystick {
	fn get_axis(&self, index: u8) -> Option<i16> {
		match index {
			0 => Some(self.last.thumb_lx),
			1 => Some(self.last.thumb_ly),
			2 => Some(self.last.thumb_rx),
			3 => Some(self.last.thumb_ry),
			_ => None
		}
	}
	fn get_button(&self, index: u8) -> Option<bool> {
		let bits = match index {
			1 => Some(A),
			2 => Some(B),
			3 => Some(X),
			0 => Some(Y),
			_ => None
		};
		bits.map(|v| self.last.buttons.contains(v))
	}
	fn update(&mut self) {
		let state = unsafe {
			let mut state: State = mem::uninitialized();
			XInputGetState(self.index as u32, &mut state);
			state
		};
		let now = state.gamepad;
		if state.packet != self.last_packet {
			let last = self.last;
			event!{axes self, now, last,
				thumb_lx => 0,
				thumb_ly => 1,
				thumb_rx => 2,
				thumb_ry => 3
			}
			event!{buttons self, now, last,
				A => 1,
				B => 2,
				X => 3,
				Y => 0
			}
		}
		self.last_packet = state.packet;
		self.last = now;
	}
}
<|endoftext|>


<commit_before>extern crate winapi;
extern crate kernel32;

use std::io;
use std::os::windows::prelude::*;
use std::os::windows::process::ExitStatusExt;
use std::process::{self, ExitStatus};

use futures::{self, Future, Poll, Async, Oneshot, Complete, oneshot, Fuse};

use Command;

pub struct Child {
    child: process::Child,
    waiting: Option<Waiting>,
}

struct Waiting {
    rx: Fuse<Oneshot<()>>,
    wait_object: winapi::HANDLE,
    tx: *mut Option<Complete<()>>,
}

unsafe impl Sync for Waiting {}
unsafe impl Send for Waiting {}

pub fn spawn(mut cmd: Command) -> Box<Future<Item=Child, Error=io::Error>> {
    Box::new(futures::done(cmd.inner.spawn().map(|c| {
        Child {
            child: c,
            waiting: None,
        }
    })))
}

impl Child {
    pub fn id(&self) -> u32 {
        self.child.id()
    }

    pub fn kill(&mut self) -> io::Result<()> {
        self.child.kill()
    }
}

impl Future for Child {
    type Item = ExitStatus;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<ExitStatus, io::Error> {
        loop {
            if let Some(ref mut w) = self.waiting {
                match w.rx.poll().expect("should not be canceled") {
                    Async::Ready(()) => {}
                    Async::NotReady => return Ok(Async::NotReady),
                }
                let status = try!(try_wait(&self.child)).expect("not ready yet");
                return Ok(status.into())
            }

            if let Some(e) = try!(try_wait(&self.child)) {
                return Ok(e.into())
            }
            let (tx, rx) = oneshot();
            let ptr = Box::into_raw(Box::new(Some(tx)));
            let mut wait_object = 0 as *mut _;
            let rc = unsafe {
                kernel32::RegisterWaitForSingleObject(&mut wait_object,
                                                      self.child.as_raw_handle(),
                                                      Some(callback),
                                                      ptr as *mut _,
                                                      winapi::INFINITE,
                                                      winapi::WT_EXECUTEINWAITTHREAD |
                                                        winapi::WT_EXECUTEONLYONCE)
            };
            if rc == 0 {
                drop(unsafe { Box::from_raw(ptr) });
                return Err(io::Error::last_os_error())
            }
            self.waiting = Some(Waiting {
                rx: rx.fuse(),
                wait_object: wait_object,
                tx: ptr,
            });
        }
    }
}

impl Drop for Waiting {
    fn drop(&mut self) {
        unsafe {
            let rc = kernel32::UnregisterWaitEx(self.wait_object,
                                                winapi::INVALID_HANDLE_VALUE);
            if rc == 0 {
                panic!("failed to unregister: {}", io::Error::last_os_error());
            }
            drop(Box::from_raw(self.tx));
        }
    }
}

unsafe extern "system" fn callback(ptr: winapi::PVOID,
                                   _timer_fired: winapi::BOOLEAN) {
    let mut complete = Box::from_raw(ptr as *mut Option<Complete<()>>);
    complete.take().unwrap().complete(());
}

pub fn try_wait(child: &process::Child) -> io::Result<Option<ExitStatus>> {
    unsafe {
        match kernel32::WaitForSingleObject(child.as_raw_handle(), 0) {
            winapi::WAIT_OBJECT_0 => {}
            winapi::WAIT_TIMEOUT => return Ok(None),
            _ => return Err(io::Error::last_os_error()),
        }
        let mut status = 0;
        let rc = kernel32::GetExitCodeProcess(child.as_raw_handle(), &mut status);
        if rc == winapi::FALSE {
            Err(io::Error::last_os_error())
        } else {
            Ok(Some(ExitStatus::from_raw(status)))
        }
    }
}
<commit_msg>process: Fix a segfault on windows<commit_after>extern crate winapi;
extern crate kernel32;

use std::io;
use std::os::windows::prelude::*;
use std::os::windows::process::ExitStatusExt;
use std::process::{self, ExitStatus};

use futures::{self, Future, Poll, Async, Oneshot, Complete, oneshot, Fuse};

use Command;

pub struct Child {
    child: process::Child,
    waiting: Option<Waiting>,
}

struct Waiting {
    rx: Fuse<Oneshot<()>>,
    wait_object: winapi::HANDLE,
    tx: *mut Option<Complete<()>>,
}

unsafe impl Sync for Waiting {}
unsafe impl Send for Waiting {}

pub fn spawn(mut cmd: Command) -> Box<Future<Item=Child, Error=io::Error>> {
    Box::new(futures::done(cmd.inner.spawn().map(|c| {
        Child {
            child: c,
            waiting: None,
        }
    })))
}

impl Child {
    pub fn id(&self) -> u32 {
        self.child.id()
    }

    pub fn kill(&mut self) -> io::Result<()> {
        self.child.kill()
    }
}

impl Future for Child {
    type Item = ExitStatus;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<ExitStatus, io::Error> {
        loop {
            if let Some(ref mut w) = self.waiting {
                match w.rx.poll().expect("should not be canceled") {
                    Async::Ready(()) => {}
                    Async::NotReady => return Ok(Async::NotReady),
                }
                let status = try!(try_wait(&self.child)).expect("not ready yet");
                return Ok(status.into())
            }

            if let Some(e) = try!(try_wait(&self.child)) {
                return Ok(e.into())
            }
            let (tx, rx) = oneshot();
            let ptr = Box::into_raw(Box::new(Some(tx)));
            let mut wait_object = 0 as *mut _;
            let rc = unsafe {
                kernel32::RegisterWaitForSingleObject(&mut wait_object,
                                                      self.child.as_raw_handle(),
                                                      Some(callback),
                                                      ptr as *mut _,
                                                      winapi::INFINITE,
                                                      winapi::WT_EXECUTEINWAITTHREAD |
                                                        winapi::WT_EXECUTEONLYONCE)
            };
            if rc == 0 {
                drop(unsafe { Box::from_raw(ptr) });
                return Err(io::Error::last_os_error())
            }
            self.waiting = Some(Waiting {
                rx: rx.fuse(),
                wait_object: wait_object,
                tx: ptr,
            });
        }
    }
}

impl Drop for Waiting {
    fn drop(&mut self) {
        unsafe {
            let rc = kernel32::UnregisterWaitEx(self.wait_object,
                                                winapi::INVALID_HANDLE_VALUE);
            if rc == 0 {
                panic!("failed to unregister: {}", io::Error::last_os_error());
            }
            drop(Box::from_raw(self.tx));
        }
    }
}

unsafe extern "system" fn callback(ptr: winapi::PVOID,
                                   _timer_fired: winapi::BOOLEAN) {
    let mut complete = &mut *(ptr as *mut Option<Complete<()>>);
    complete.take().unwrap().complete(());
}

pub fn try_wait(child: &process::Child) -> io::Result<Option<ExitStatus>> {
    unsafe {
        match kernel32::WaitForSingleObject(child.as_raw_handle(), 0) {
            winapi::WAIT_OBJECT_0 => {}
            winapi::WAIT_TIMEOUT => return Ok(None),
            _ => return Err(io::Error::last_os_error()),
        }
        let mut status = 0;
        let rc = kernel32::GetExitCodeProcess(child.as_raw_handle(), &mut status);
        if rc == winapi::FALSE {
            Err(io::Error::last_os_error())
        } else {
            Ok(Some(ExitStatus::from_raw(status)))
        }
    }
}
<|endoftext|>


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ProgramPatch {
    pub instruction_pointer: usize,
    pub current_depth: u64,
    pub status: ProgramStatus,
}

fn find_by<T, F>(list: &[T], start: Option<usize>, mut predicate: F) -> Option<usize>
where
    F: FnMut(&T) -> bool,
{
    let start = start.unwrap_or(0);
    for (offset, element) in list.iter().enumerate() {
        if predicate(element) {
            return Some(start + offset);
        }
    }

    return None;
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        if let Some(mut index) = self.instruction_pointer {
            while index < self.instructions.len() {
                let current_cell = vm.cells[vm.data_pointer];
                let patch = match (self.instructions[index], self.status) {
                    (_, ProgramStatus::Seeking(goal)) => {
                        Program::attempt_forward_jump(
                            &self.instructions,
                            index,
                            goal,
                            self.current_depth,
                        )
                    }

                    (Command::JumpForward, _) => {
                        match current_cell {
                            0 => {
                                Program::attempt_forward_jump(
                                    &self.instructions,
                                    index,
                                    self.current_depth,
                                    self.current_depth,
                                )
                            }

                            _ => ProgramPatch {
                                instruction_pointer: index + 1,
                                status: ProgramStatus::Normal,
                                current_depth: self.current_depth + 1,
                            },
                        }
                    }

                    (Command::JumpBackward, _) => {
                        match current_cell {
                            0 => ProgramPatch {
                                instruction_pointer: index + 1,
                                status: ProgramStatus::Normal,
                                current_depth: self.current_depth - 1,
                            },

                            _ => {
                                Program::backward_jump(
                                    &self.instructions,
                                    index,
                                    self.current_depth,
                                )
                            }
                        }
                    }

                    (command, _) => {
                        vm.apply(command);
                        ProgramPatch {
                            status: ProgramStatus::Normal,
                            current_depth: self.current_depth,
                            instruction_pointer: index + 1,
                        }
                    }
                };

                self.update(patch);
                index = patch.instruction_pointer;
            }
        }
    }

    fn update(&mut self, patch: ProgramPatch) -> &mut Self {
        self.instruction_pointer = Some(patch.instruction_pointer);
        self.current_depth = patch.current_depth;
        self.status = patch.status;
        return self;
    }

    fn backward_jump(commands: &Vec<Command>, start: usize, depth: u64) -> ProgramPatch {
        let goal_depth = depth - 1;
        let mut current_depth = depth;
        for index in (0..start).rev() {
            match commands[index] {
                Command::JumpBackward => current_depth += 1,
                Command::JumpForward => current_depth -= 1,
                _ => {}
            }
            if goal_depth == current_depth {
                return ProgramPatch {
                    instruction_pointer: index + 1,
                    status: ProgramStatus::Normal,
                    current_depth: current_depth + 1,
                };
            }
        }
        panic!("No opening bracket found?");
    }

    fn attempt_forward_jump(
        commands: &Vec<Command>,
        index: usize,
        goal_depth: u64,
        mut current_depth: u64,
    ) -> ProgramPatch {
        let index = find_by(&commands[index..], Some(index), |command| {
            match command {
                &Command::JumpBackward => current_depth -= 1,
                &Command::JumpForward => current_depth += 1,
                _ => {}
            };
            return current_depth == goal_depth;
        });

        return match index {
            Some(index) => ProgramPatch {
                instruction_pointer: index + 1,
                status: ProgramStatus::Normal,
                current_depth,
            },

            None => ProgramPatch {
                instruction_pointer: commands.len(),
                status: ProgramStatus::Seeking(goal_depth),
                current_depth,
            },
        };
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn attempt_forward_jump() {
        let commands = vec![
            Command::JumpForward,
            Command::JumpForward,
            Command::JumpBackward,
        ];
        let index = 0;
        let goal_depth = 0;
        let current_depth = 0;
        let actual = Program::attempt_forward_jump(&commands, index, goal_depth, current_depth);
        assert_eq!(
            actual,
            ProgramPatch {
                instruction_pointer: 3,
                current_depth: 1,
                status: ProgramStatus::Seeking(0),
            }
        )
    }
}
<commit_msg>Rename attempt_forward_jump -> forward_jump<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ProgramPatch {
    pub instruction_pointer: usize,
    pub current_depth: u64,
    pub status: ProgramStatus,
}

fn find_by<T, F>(list: &[T], start: Option<usize>, mut predicate: F) -> Option<usize>
where
    F: FnMut(&T) -> bool,
{
    let start = start.unwrap_or(0);
    for (offset, element) in list.iter().enumerate() {
        if predicate(element) {
            return Some(start + offset);
        }
    }

    return None;
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        if let Some(mut index) = self.instruction_pointer {
            while index < self.instructions.len() {
                let current_cell = vm.cells[vm.data_pointer];
                let patch = match (self.instructions[index], self.status) {
                    (_, ProgramStatus::Seeking(goal)) => {
                        Program::forward_jump(
                            &self.instructions,
                            index,
                            goal,
                            self.current_depth,
                        )
                    }

                    (Command::JumpForward, _) => {
                        match current_cell {
                            0 => {
                                Program::attempt_forward_jump(
                                    &self.instructions,
                                    index,
                                    self.current_depth,
                                    self.current_depth,
                                )
                            }

                            _ => ProgramPatch {
                                instruction_pointer: index + 1,
                                status: ProgramStatus::Normal,
                                current_depth: self.current_depth + 1,
                            },
                        }
                    }

                    (Command::JumpBackward, _) => {
                        match current_cell {
                            0 => ProgramPatch {
                                instruction_pointer: index + 1,
                                status: ProgramStatus::Normal,
                                current_depth: self.current_depth - 1,
                            },

                            _ => {
                                Program::backward_jump(
                                    &self.instructions,
                                    index,
                                    self.current_depth,
                                )
                            }
                        }
                    }

                    (command, _) => {
                        vm.apply(command);
                        ProgramPatch {
                            status: ProgramStatus::Normal,
                            current_depth: self.current_depth,
                            instruction_pointer: index + 1,
                        }
                    }
                };

                self.update(patch);
                index = patch.instruction_pointer;
            }
        }
    }

    fn update(&mut self, patch: ProgramPatch) -> &mut Self {
        self.instruction_pointer = Some(patch.instruction_pointer);
        self.current_depth = patch.current_depth;
        self.status = patch.status;
        return self;
    }

    fn backward_jump(commands: &Vec<Command>, start: usize, depth: u64) -> ProgramPatch {
        let goal_depth = depth - 1;
        let mut current_depth = depth;
        for index in (0..start).rev() {
            match commands[index] {
                Command::JumpBackward => current_depth += 1,
                Command::JumpForward => current_depth -= 1,
                _ => {}
            }
            if goal_depth == current_depth {
                return ProgramPatch {
                    instruction_pointer: index + 1,
                    status: ProgramStatus::Normal,
                    current_depth: current_depth + 1,
                };
            }
        }
        panic!("No opening bracket found?");
    }

    fn forward_jump(
        commands: &Vec<Command>,
        index: usize,
        goal_depth: u64,
        mut current_depth: u64,
    ) -> ProgramPatch {
        let index = find_by(&commands[index..], Some(index), |command| {
            match command {
                &Command::JumpBackward => current_depth -= 1,
                &Command::JumpForward => current_depth += 1,
                _ => {}
            };
            return current_depth == goal_depth;
        });

        return match index {
            Some(index) => ProgramPatch {
                instruction_pointer: index + 1,
                status: ProgramStatus::Normal,
                current_depth,
            },

            None => ProgramPatch {
                instruction_pointer: commands.len(),
                status: ProgramStatus::Seeking(goal_depth),
                current_depth,
            },
        };
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn attempt_forward_jump() {
        let commands = vec![
            Command::JumpForward,
            Command::JumpForward,
            Command::JumpBackward,
        ];
        let index = 0;
        let goal_depth = 0;
        let current_depth = 0;
        let actual = Program::attempt_forward_jump(&commands, index, goal_depth, current_depth);
        assert_eq!(
            actual,
            ProgramPatch {
                instruction_pointer: 3,
                current_depth: 1,
                status: ProgramStatus::Seeking(0),
            }
        )
    }
}
<|endoftext|>


<commit_before>use super::gl;
use super::gl_lib::types::*;

pub struct Program {
    gl_id: GLuint
}

impl Program {
    pub unsafe fn from_id(id: GLuint) -> Program {
        Program { gl_id: id }
    }
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteProgram(self.gl_id);
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramAttrib {
    pub gl_index: GLuint
}
<commit_msg>Add `Program.attach_shader()`<commit_after>use super::gl;
use super::gl_lib::types::*;
use super::Shader;

pub struct Program {
    gl_id: GLuint
}

impl Program {
    pub unsafe fn from_id(id: GLuint) -> Program {
        Program { gl_id: id }
    }

    pub fn attach_shader(&mut self, shader: &Shader) {
        unsafe {
            gl::AttachShader(self.gl_id, shader.gl_id());
        }
    }
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteProgram(self.gl_id);
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramAttrib {
    pub gl_index: GLuint
}
<|endoftext|>


<commit_before>#[cfg(feature = "reqwest")]
extern crate reqwest;

use Value;
use error::{RequestError, RequestErrorKind};
use utils::escape_xml;
use transport::Transport;
use parser::parse_response;

use std::io::{self, Write};
use std::collections::BTreeMap;

/// A request to call a procedure.
#[derive(Clone, Debug)]
pub struct Request<'a> {
    name: &'a str,
    args: Vec<Value>,
}

impl<'a> Request<'a> {
    /// Creates a new request to call a function named `name`.
    ///
    /// By default, no arguments are passed. Use the `arg` method to append arguments.
    pub fn new(name: &'a str) -> Self {
        Request {
            name,
            args: Vec::new(),
        }
    }

    /// Appends an argument to be passed to the current list of arguments.
    pub fn arg<T: Into<Value>>(mut self, value: T) -> Self {
        self.args.push(value.into());
        self
    }

    /// Performs the request using a [`Transport`].
    ///
    /// Returns a [`RequestResult`] indicating whether the request was sent and processed
    /// successfully (according to the rules of XML-RPC).
    ///
    /// [`Transport`]: trait.Transport.html
    /// [`RequestResult`]: type.RequestResult.html
    pub fn call<T: Transport>(&self, transport: T) -> RequestResult {
        let mut reader = transport.transmit(self)
            .map_err(RequestErrorKind::TransportError)?;

        let response = parse_response(&mut reader).map_err(RequestErrorKind::ParseError)?;

        let value = response.map_err(RequestErrorKind::Fault)?;
        Ok(value)
    }

    /// Performs the request on a URL.
    ///
    /// This is a convenience method that will internally create a new `reqwest::Client` and send a
    /// POST HTTP request to the given URL. If you only use this method to perform requests, you
    /// don't need to depend on `reqwest` yourself.
    ///
    /// This method is only available when the `reqwest` feature is enabled (this is the default).
    #[cfg(feature = "reqwest")]
    pub fn call_url(&self, url: &str) -> RequestResult {
        self.call(reqwest::Client::new().post(url))
    }

    /// Formats this `Request` as XML.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        write!(fmt, r#"<?xml version="1.0" encoding="utf-8"?>"#)?;
        write!(fmt, r#"<methodCall>"#)?;
        write!(fmt, r#"    <methodName>{}</methodName>"#, escape_xml(&self.name))?;
        write!(fmt, r#"    <params>"#)?;
        for value in &self.args {
            write!(fmt, r#"        <param>"#)?;
            value.write_as_xml(fmt)?;
            write!(fmt, r#"        </param>"#)?;
        }
        write!(fmt, r#"    </params>"#)?;
        write!(fmt, r#"</methodCall>"#)?;
        Ok(())
    }

    /// Serialize this `Request` into an XML-RPC struct that can be passed to
    /// the [`system.multicall`](https://mirrors.talideon.com/articles/multicall.html)
    /// XML-RPC method, specifically a struct with two fields:
    ///
    /// * `methodName`: the request name
    /// * `params`: the request arguments
    pub fn into_multicall_struct(self) -> Value {
        let mut multicall_struct: BTreeMap<String, Value> = BTreeMap::new();

        multicall_struct.insert("methodName".into(), self.name.into());
        multicall_struct.insert("params".into(), Value::Array(self.args));

        Value::Struct(multicall_struct)
    }
}

/// The result of executing a request.
pub type RequestResult = Result<Value, RequestError>;

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

    #[test]
    fn escapes_method_names() {
        let mut output: Vec<u8> = Vec::new();
        let req = Request::new("x<&x");

        req.write_as_xml(&mut output).unwrap();
        assert!(
            str::from_utf8(&output)
            .unwrap()
            .contains("<methodName>x<&x</methodName>"));
    }
}
<commit_msg>Slightly better wording in call_url<commit_after>#[cfg(feature = "reqwest")]
extern crate reqwest;

use Value;
use error::{RequestError, RequestErrorKind};
use utils::escape_xml;
use transport::Transport;
use parser::parse_response;

use std::io::{self, Write};
use std::collections::BTreeMap;

/// A request to call a procedure.
#[derive(Clone, Debug)]
pub struct Request<'a> {
    name: &'a str,
    args: Vec<Value>,
}

impl<'a> Request<'a> {
    /// Creates a new request to call a function named `name`.
    ///
    /// By default, no arguments are passed. Use the `arg` method to append arguments.
    pub fn new(name: &'a str) -> Self {
        Request {
            name,
            args: Vec::new(),
        }
    }

    /// Appends an argument to be passed to the current list of arguments.
    pub fn arg<T: Into<Value>>(mut self, value: T) -> Self {
        self.args.push(value.into());
        self
    }

    /// Performs the request using a [`Transport`].
    ///
    /// Returns a [`RequestResult`] indicating whether the request was sent and processed
    /// successfully (according to the rules of XML-RPC).
    ///
    /// [`Transport`]: trait.Transport.html
    /// [`RequestResult`]: type.RequestResult.html
    pub fn call<T: Transport>(&self, transport: T) -> RequestResult {
        let mut reader = transport.transmit(self)
            .map_err(RequestErrorKind::TransportError)?;

        let response = parse_response(&mut reader).map_err(RequestErrorKind::ParseError)?;

        let value = response.map_err(RequestErrorKind::Fault)?;
        Ok(value)
    }

    /// Performs the request on a URL.
    ///
    /// This is a convenience method that will internally create a new `reqwest::Client` and send an
    /// HTTP POST request to the given URL. If you only use this method to perform requests, you
    /// don't need to depend on `reqwest` yourself.
    ///
    /// This method is only available when the `reqwest` feature is enabled (this is the default).
    #[cfg(feature = "reqwest")]
    pub fn call_url(&self, url: &str) -> RequestResult {
        self.call(reqwest::Client::new().post(url))
    }

    /// Formats this `Request` as XML.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        write!(fmt, r#"<?xml version="1.0" encoding="utf-8"?>"#)?;
        write!(fmt, r#"<methodCall>"#)?;
        write!(fmt, r#"    <methodName>{}</methodName>"#, escape_xml(&self.name))?;
        write!(fmt, r#"    <params>"#)?;
        for value in &self.args {
            write!(fmt, r#"        <param>"#)?;
            value.write_as_xml(fmt)?;
            write!(fmt, r#"        </param>"#)?;
        }
        write!(fmt, r#"    </params>"#)?;
        write!(fmt, r#"</methodCall>"#)?;
        Ok(())
    }

    /// Serialize this `Request` into an XML-RPC struct that can be passed to
    /// the [`system.multicall`](https://mirrors.talideon.com/articles/multicall.html)
    /// XML-RPC method, specifically a struct with two fields:
    ///
    /// * `methodName`: the request name
    /// * `params`: the request arguments
    pub fn into_multicall_struct(self) -> Value {
        let mut multicall_struct: BTreeMap<String, Value> = BTreeMap::new();

        multicall_struct.insert("methodName".into(), self.name.into());
        multicall_struct.insert("params".into(), Value::Array(self.args));

        Value::Struct(multicall_struct)
    }
}

/// The result of executing a request.
pub type RequestResult = Result<Value, RequestError>;

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

    #[test]
    fn escapes_method_names() {
        let mut output: Vec<u8> = Vec::new();
        let req = Request::new("x<&x");

        req.write_as_xml(&mut output).unwrap();
        assert!(
            str::from_utf8(&output)
            .unwrap()
            .contains("<methodName>x<&x</methodName>"));
    }
}
<|endoftext|>