<commit_before>use std::cell::RefCell;
use std::rc::Rc;

use var::{js_str_key, JsVarValue};

use jsrs_common::backend::Backend;
use jsrs_common::types::coerce::{AsNumber, AsString};
use jsrs_common::types::js_str::JsStrStruct;
use jsrs_common::types::js_var::{JsKey, JsPtrEnum, JsType, JsVar};

fn var_type_as_number(var: &JsVar, ptr: Option<&JsPtrEnum>) -> f64 {
    match ptr {
        Some(ref ptr) => ptr.as_number(),
        None => var.as_number()
    }
}

pub fn array_push(state: Rc<RefCell<Backend>>, this: Option<(JsVar, JsPtrEnum)>, args: Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>) {
    // TODO: Change panics to actual errors
    let (this_var, mut this_obj) = match this.clone() {
        Some((v, JsPtrEnum::JsObj(obj))) => (v, obj),
        Some(_) => panic!("Trying to push onto array, but `this` is not an object"),
        None => panic!("Trying to push onto array, but `this` is None")
    };

    let mut length_ptr = match this_obj.dict.get(&js_str_key("length")) {
        Some(js_var) => {
            let state_ref = state.borrow_mut();
            let alloc_box = state_ref.get_alloc_box();
            let alloc_ref = alloc_box.borrow_mut();
            match alloc_ref.find_id(&js_var.unique).map(|p| p.borrow().clone()) {
                Some(JsPtrEnum::NativeVar(native_var)) => native_var,
                Some(_) => panic!("Array length pointer is not a native variable"),
                None => panic!("No pointer for array length"),
            }
        }
        None => panic!("No length field on array"),
    };

    let length = match length_ptr.get(state.clone(), this.clone().map(|x| x.1)).0.t {
        JsType::JsNum(f) => f,
        _ => panic!("Array length value is not a number"),
    };

    let new_length = JsVar::new(JsType::JsNum(length + args.len() as f64));
    length_ptr.set(state.clone(), this, new_length.clone(), None);
    let state_ref = state.borrow_mut();
    let alloc_box = state_ref.get_alloc_box();

    for (i, (var, ptr)) in args.into_iter().enumerate() {
        let key = JsKey::JsStr(JsStrStruct::new(&JsType::JsNum(length + i as f64).as_string()));
        this_obj.add_key(&this_var.unique, key, var, ptr, &mut *(alloc_box.borrow_mut()));
    }

    (new_length, None)
}

pub fn array_length_setter(state: Rc<RefCell<Backend>>, old_var: JsVar, old_ptr: Option<JsPtrEnum>,
                           this: Option<(JsVar, JsPtrEnum)>,  new_var: JsVar, new_ptr: Option<JsPtrEnum>) -> JsVarValue {
    let new_len = var_type_as_number(&new_var, new_ptr.as_ref());
    let old_len = var_type_as_number(&old_var, old_ptr.as_ref());

    if !(new_len.is_normal() || new_len == 0.0) || new_len.is_sign_negative() || new_len != new_len.trunc() {
        // TODO: Return a `RangeError` instead of panicking.
        panic!("Invalid array length:\n var: {:#?}\nptr: {:#?}", new_var, new_ptr);
    }

    let (this_var, mut this_obj) = match this.clone() {
        Some((v, JsPtrEnum::JsObj(obj))) => (v, obj),
        Some(_) => panic!("Trying to set array length, but `this` is not an object"),
        None => panic!("Trying to set array length, but `this` is None")
    };

    let new_len_int = new_len as i32;
    let old_len_int = old_len as i32;

    let state_ref = state.borrow_mut();

    if new_len > old_len {
        for i in old_len_int..new_len_int {
            let key = JsKey::JsStr(JsStrStruct::new(&JsType::JsNum(i as f64).as_string()));
            let alloc_box = state_ref.get_alloc_box();
            this_obj.add_key(&this_var.unique, key, JsVar::new(JsType::JsUndef), None, &mut *(alloc_box.borrow_mut()));
        }
    }

    if new_len < old_len {
        for i in new_len_int..old_len_int {
            let key = js_str_key(&JsType::JsNum(i as f64).as_string());
            let alloc_box = state_ref.get_alloc_box();
            this_obj.remove_key(&key, &mut *(alloc_box.borrow_mut()));
        }
    }

    (JsVar::new(JsType::JsNum(new_len)), None)
}
<commit_msg>update for partial fix in jsrs-common<commit_after>use std::cell::RefCell;
use std::rc::Rc;

use var::{js_str_key, JsVarValue};

use jsrs_common::backend::Backend;
use jsrs_common::types::coerce::{AsNumber, AsString};
use jsrs_common::types::js_str::JsStrStruct;
use jsrs_common::types::js_var::{JsKey, JsPtrEnum, JsType, JsVar};

fn var_type_as_number(var: &JsVar, ptr: Option<&JsPtrEnum>) -> f64 {
    match ptr {
        Some(ref ptr) => ptr.as_number(),
        None => var.as_number()
    }
}

pub fn array_push(state: Rc<RefCell<Backend>>, this: Option<(JsVar, JsPtrEnum)>, args: Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>) {
    // TODO: Change panics to actual errors
    let (this_var, mut this_obj) = match this.clone() {
        Some((v, JsPtrEnum::JsObj(obj))) => (v, obj),
        Some(_) => panic!("Trying to push onto array, but `this` is not an object"),
        None => panic!("Trying to push onto array, but `this` is None")
    };

    let mut length_ptr = match this_obj.dict.get(&js_str_key("length")) {
        Some(js_var) => {
            let state_ref = state.borrow_mut();
            let alloc_box = state_ref.get_alloc_box();
            let alloc_ref = alloc_box.borrow_mut();
            match alloc_ref.find_id(&js_var.unique).map(|p| p.borrow().clone()) {
                Some(JsPtrEnum::NativeVar(native_var)) => native_var,
                Some(_) => panic!("Array length pointer is not a native variable"),
                None => panic!("No pointer for array length"),
            }
        }
        None => panic!("No length field on array"),
    };

    let length = match length_ptr.get(state.clone(), this.clone().map(|x| x.1)).0.t {
        JsType::JsNum(f) => f,
        _ => panic!("Array length value is not a number"),
    };

    let new_length = JsVar::new(JsType::JsNum(length + args.len() as f64));
    length_ptr.set(state.clone(), this, new_length.clone(), None);
    let state_ref = state.borrow_mut();
    let alloc_box = state_ref.get_alloc_box();

    for (i, (var, ptr)) in args.into_iter().enumerate() {
        let key = JsKey::JsStr(JsStrStruct::new(&JsType::JsNum(length + i as f64).as_string()));
        this_obj.add_key(&this_var.unique, key, var, ptr, &mut *(alloc_box.borrow_mut()));
    }

    (new_length, None)
}

pub fn array_length_setter(state: Rc<RefCell<Backend>>, old_var: JsVar, old_ptr: Option<JsPtrEnum>,
                           this: Option<(JsVar, JsPtrEnum)>,  new_var: JsVar, new_ptr: Option<JsPtrEnum>) -> JsVarValue {
    let new_len = var_type_as_number(&new_var, new_ptr.as_ref());
    let old_len = var_type_as_number(&old_var, old_ptr.as_ref());

    if !(new_len.is_normal() || new_len == 0.0) || new_len.is_sign_negative() || new_len != new_len.trunc() {
        // TODO: Return a `RangeError` instead of panicking.
        panic!("Invalid array length:\n var: {:#?}\nptr: {:#?}", new_var, new_ptr);
    }

    let (this_var, mut this_obj) = match this.clone() {
        Some((v, JsPtrEnum::JsObj(obj))) => (v, obj),
        Some(_) => panic!("Trying to set array length, but `this` is not an object"),
        None => panic!("Trying to set array length, but `this` is None")
    };

    let new_len_int = new_len as i32;
    let old_len_int = old_len as i32;

    let state_ref = state.borrow_mut();

    if new_len > old_len {
        for i in old_len_int..new_len_int {
            let key = JsKey::JsStr(JsStrStruct::new(&JsType::JsNum(i as f64).as_string()));
            let alloc_box = state_ref.get_alloc_box();
            this_obj.add_key(&this_var.unique, key, JsVar::new(JsType::JsUndef), None, &mut *(alloc_box.borrow_mut()));
        }
    }

    if new_len < old_len {
        for i in new_len_int..old_len_int {
            let key = js_str_key(&JsType::JsNum(i as f64).as_string());
            let alloc_box = state_ref.get_alloc_box();
            this_obj.remove_key(&this_var.unique, &key, &mut *(alloc_box.borrow_mut()));
        }
    }

    (JsVar::new(JsType::JsNum(new_len)), None)
}
<|endoftext|>


<commit_before>use std::fmt;

use options::flags;
use options::parser::MatchedFlags;
use fs::feature::xattr;

static OPTIONS: &str = r##"
  -?, --help         show list of command-line options
  -v, --version      show version of exa

DISPLAY OPTIONS
  -1, --oneline      display one entry per line
  -l, --long         display extended file metadata as a table
  -G, --grid         display entries as a grid (default)
  -x, --across       sort the grid across, rather than downwards
  -R, --recurse      recurse into directories
  -T, --tree         recurse into directories as a tree
  -F, --classify     display type indicator by file names
  --colo[u]r=WHEN    when to use terminal colours (always, auto, never)
  --colo[u]r-scale   highlight levels of file sizes distinctly

FILTERING AND SORTING OPTIONS
  -a, --all                  show hidden and 'dot' files
  -d, --list-dirs            list directories like regular files
  -r, --reverse              reverse the sort order
  -s, --sort SORT_FIELD      which field to sort by:
  --group-directories-first  list directories before other files
  -I, --ignore-glob GLOBS    glob patterns (pipe-separated) of files to ignore
  Valid sort fields:         name, Name, extension, Extension, size, type,
                             modified, accessed, created, inode, none
"##;

static LONG_OPTIONS: &str = r##"
LONG VIEW OPTIONS
  -b, --binary       list file sizes with binary prefixes
  -B, --bytes        list file sizes in bytes, without any prefixes
  -g, --group        list each file's group
  -h, --header       add a header row to each column
  -H, --links        list each file's number of hard links
  -i, --inode        list each file's inode number
  -L, --level DEPTH  limit the depth of recursion
  -m, --modified     use the modified timestamp field
  -S, --blocks       show number of file system blocks
  -t, --time FIELD   which timestamp field to list (modified, accessed, created)
  -u, --accessed     use the accessed timestamp field
  -U, --created      use the created timestamp field
  --time-style       how to format timestamps (default, iso, long-iso, full-iso)"##;

static GIT_HELP:      &str = r##"  --git              list each file's Git status, if tracked"##;
static EXTENDED_HELP: &str = r##"  -@, --extended     list each file's extended attributes and sizes"##;

/// All the information needed to display the help text, which depends
/// on which features are enabled and whether the user only wants to
/// see one section’s help.
#[derive(PartialEq, Debug)]
pub struct HelpString {

    /// Only show the help for the long section, not all the help.
    pub only_long: bool,

    /// Whether the --git option should be included in the help.
    pub git: bool,

    /// Whether the --extended option should be included in the help.
    pub xattrs: bool,
}

impl HelpString {

    /// Determines how to show help, if at all, based on the user’s
    /// command-line arguments. This one works backwards from the other
    /// ‘deduce’ functions, returning Err if help needs to be shown.
    pub fn deduce(matches: &MatchedFlags) -> Result<(), HelpString> {
        if matches.has(&flags::HELP) {
            let only_long = matches.has(&flags::LONG);
            let git       = cfg!(feature="git");
            let xattrs    = xattr::ENABLED;
            Err(HelpString { only_long, git, xattrs })
        }
        else {
            Ok(())  // no help needs to be shown
        }
    }
}

impl fmt::Display for HelpString {

    /// Format this help options into an actual string of help
    /// text to be displayed to the user.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "Usage:\n  exa [options] [files...]\n"));

        if !self.only_long {
            try!(write!(f, "{}", OPTIONS));
        }

        try!(write!(f, "{}", LONG_OPTIONS));

        if self.git {
            try!(write!(f, "\n{}", GIT_HELP));
        }

        if self.xattrs {
            try!(write!(f, "\n{}", EXTENDED_HELP));
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    use options::Options;
    use std::ffi::OsString;

    fn os(input: &'static str) -> OsString {
        let mut os = OsString::new();
        os.push(input);
        os
    }

    #[test]
    fn help() {
        let args = [ os("--help") ];
        let opts = Options::getopts(&args);
        assert!(opts.is_err())
    }

    #[test]
    fn help_with_file() {
        let args = [ os("--help"), os("me") ];
        let opts = Options::getopts(&args);
        assert!(opts.is_err())
    }

    #[test]
    fn unhelpful() {
        let args = [];
        let opts = Options::getopts(&args);
        assert!(opts.is_ok())  // no help when --help isn’t passed
    }
}
<commit_msg>These help fields don’t need to be pub<commit_after>use std::fmt;

use options::flags;
use options::parser::MatchedFlags;
use fs::feature::xattr;

static OPTIONS: &str = r##"
  -?, --help         show list of command-line options
  -v, --version      show version of exa

DISPLAY OPTIONS
  -1, --oneline      display one entry per line
  -l, --long         display extended file metadata as a table
  -G, --grid         display entries as a grid (default)
  -x, --across       sort the grid across, rather than downwards
  -R, --recurse      recurse into directories
  -T, --tree         recurse into directories as a tree
  -F, --classify     display type indicator by file names
  --colo[u]r=WHEN    when to use terminal colours (always, auto, never)
  --colo[u]r-scale   highlight levels of file sizes distinctly

FILTERING AND SORTING OPTIONS
  -a, --all                  show hidden and 'dot' files
  -d, --list-dirs            list directories like regular files
  -r, --reverse              reverse the sort order
  -s, --sort SORT_FIELD      which field to sort by:
  --group-directories-first  list directories before other files
  -I, --ignore-glob GLOBS    glob patterns (pipe-separated) of files to ignore
  Valid sort fields:         name, Name, extension, Extension, size, type,
                             modified, accessed, created, inode, none
"##;

static LONG_OPTIONS: &str = r##"
LONG VIEW OPTIONS
  -b, --binary       list file sizes with binary prefixes
  -B, --bytes        list file sizes in bytes, without any prefixes
  -g, --group        list each file's group
  -h, --header       add a header row to each column
  -H, --links        list each file's number of hard links
  -i, --inode        list each file's inode number
  -L, --level DEPTH  limit the depth of recursion
  -m, --modified     use the modified timestamp field
  -S, --blocks       show number of file system blocks
  -t, --time FIELD   which timestamp field to list (modified, accessed, created)
  -u, --accessed     use the accessed timestamp field
  -U, --created      use the created timestamp field
  --time-style       how to format timestamps (default, iso, long-iso, full-iso)"##;

static GIT_HELP:      &str = r##"  --git              list each file's Git status, if tracked"##;
static EXTENDED_HELP: &str = r##"  -@, --extended     list each file's extended attributes and sizes"##;

/// All the information needed to display the help text, which depends
/// on which features are enabled and whether the user only wants to
/// see one section’s help.
#[derive(PartialEq, Debug)]
pub struct HelpString {

    /// Only show the help for the long section, not all the help.
    only_long: bool,

    /// Whether the --git option should be included in the help.
    git: bool,

    /// Whether the --extended option should be included in the help.
    xattrs: bool,
}

impl HelpString {

    /// Determines how to show help, if at all, based on the user’s
    /// command-line arguments. This one works backwards from the other
    /// ‘deduce’ functions, returning Err if help needs to be shown.
    pub fn deduce(matches: &MatchedFlags) -> Result<(), HelpString> {
        if matches.has(&flags::HELP) {
            let only_long = matches.has(&flags::LONG);
            let git       = cfg!(feature="git");
            let xattrs    = xattr::ENABLED;
            Err(HelpString { only_long, git, xattrs })
        }
        else {
            Ok(())  // no help needs to be shown
        }
    }
}

impl fmt::Display for HelpString {

    /// Format this help options into an actual string of help
    /// text to be displayed to the user.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "Usage:\n  exa [options] [files...]\n"));

        if !self.only_long {
            try!(write!(f, "{}", OPTIONS));
        }

        try!(write!(f, "{}", LONG_OPTIONS));

        if self.git {
            try!(write!(f, "\n{}", GIT_HELP));
        }

        if self.xattrs {
            try!(write!(f, "\n{}", EXTENDED_HELP));
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    use options::Options;
    use std::ffi::OsString;

    fn os(input: &'static str) -> OsString {
        let mut os = OsString::new();
        os.push(input);
        os
    }

    #[test]
    fn help() {
        let args = [ os("--help") ];
        let opts = Options::getopts(&args);
        assert!(opts.is_err())
    }

    #[test]
    fn help_with_file() {
        let args = [ os("--help"), os("me") ];
        let opts = Options::getopts(&args);
        assert!(opts.is_err())
    }

    #[test]
    fn unhelpful() {
        let args = [];
        let opts = Options::getopts(&args);
        assert!(opts.is_ok())  // no help when --help isn’t passed
    }
}
<|endoftext|>


<commit_before>//! SVG paint servers.

use cssparser::Parser;

use crate::bbox::BoundingBox;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::DrawingCtx;
use crate::element::Element;
use crate::error::{
    AcquireError, ImplementationLimit, NodeIdError, ParseError, RenderingError, ValueErrorKind,
};
use crate::gradient::{ResolvedGradient, UserSpaceGradient};
use crate::node::NodeBorrow;
use crate::parsers::Parse;
use crate::pattern::{ResolvedPattern, UserSpacePattern};
use crate::properties::ComputedValues;
use crate::unit_interval::UnitInterval;
use crate::util;

#[derive(Debug, Clone, PartialEq)]
pub enum PaintServer {
    None,
    Iri {
        iri: Box<NodeId>,
        alternate: Option<cssparser::Color>,
    },
    SolidColor(cssparser::Color),
}

pub enum PaintSource {
    None,
    Gradient(ResolvedGradient, Option<cssparser::RGBA>),
    Pattern(ResolvedPattern, Option<cssparser::RGBA>),
    SolidColor(cssparser::RGBA),
}

pub enum UserSpacePaintSource {
    None,
    Gradient(UserSpaceGradient, Option<cssparser::RGBA>),
    Pattern(UserSpacePattern, Option<cssparser::RGBA>),
    SolidColor(cssparser::RGBA),
}

impl Parse for PaintServer {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<PaintServer, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(PaintServer::None)
        } else if let Ok(url) = parser.try_parse(|i| i.expect_url()) {
            let loc = parser.current_source_location();

            let alternate = if !parser.is_exhausted() {
                if parser
                    .try_parse(|i| i.expect_ident_matching("none"))
                    .is_ok()
                {
                    None
                } else {
                    Some(parser.try_parse(|i| cssparser::Color::parse(i))?)
                }
            } else {
                None
            };

            Ok(PaintServer::Iri {
                iri: Box::new(
                    NodeId::parse(&url)
                        .map_err(|e: NodeIdError| -> ValueErrorKind { e.into() })
                        .map_err(|e| loc.new_custom_error(e))?,
                ),
                alternate,
            })
        } else {
            Ok(cssparser::Color::parse(parser).map(PaintServer::SolidColor)?)
        }
    }
}

impl PaintServer {
    pub fn resolve(
        &self,
        acquired_nodes: &mut AcquiredNodes<'_>,
        opacity: UnitInterval,
        current_color: cssparser::RGBA,
    ) -> Result<PaintSource, RenderingError> {
        match self {
            PaintServer::Iri {
                ref iri,
                ref alternate,
            } => acquired_nodes
                .acquire(iri)
                .and_then(|acquired| {
                    let node = acquired.get();
                    assert!(node.is_element());

                    match *node.borrow_element() {
                        Element::LinearGradient(ref g) => {
                            g.resolve(&node, acquired_nodes).map(|g| {
                                PaintSource::Gradient(
                                    g,
                                    alternate.map(|c| resolve_color(&c, opacity, current_color)),
                                )
                            })
                        }
                        Element::Pattern(ref p) => p.resolve(&node, acquired_nodes).map(|p| {
                            PaintSource::Pattern(
                                p,
                                alternate.map(|c| resolve_color(&c, opacity, current_color)),
                            )
                        }),
                        Element::RadialGradient(ref g) => {
                            g.resolve(&node, acquired_nodes).map(|g| {
                                PaintSource::Gradient(
                                    g,
                                    alternate.map(|c| resolve_color(&c, opacity, current_color)),
                                )
                            })
                        }
                        _ => Err(AcquireError::InvalidLinkType(iri.as_ref().clone())),
                    }
                })
                .or_else(|err| match (err, alternate) {
                    (AcquireError::MaxReferencesExceeded, _) => {
                        rsvg_log!("exceeded maximum number of referenced objects");
                        Err(RenderingError::LimitExceeded(
                            ImplementationLimit::TooManyReferencedElements,
                        ))
                    }

                    // The following two cases catch AcquireError::CircularReference, which for
                    // paint servers may mean that there is a pattern or gradient with a reference
                    // cycle in its "href" attribute.  This is an invalid paint server, and per
                    // https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint we should try to
                    // fall back to the alternate color.
                    (_, Some(color)) => {
                        rsvg_log!(
                            "could not resolve paint server \"{}\", using alternate color",
                            iri
                        );

                        Ok(PaintSource::SolidColor(resolve_color(
                            color,
                            opacity,
                            current_color,
                        )))
                    }

                    (_, _) => {
                        rsvg_log!(
                            "could not resolve paint server \"{}\", no alternate color specified",
                            iri
                        );

                        Ok(PaintSource::None)
                    }
                }),

            PaintServer::SolidColor(color) => Ok(PaintSource::SolidColor(resolve_color(
                color,
                opacity,
                current_color,
            ))),

            PaintServer::None => Ok(PaintSource::None),
        }
    }
}

impl PaintSource {
    pub fn to_user_space(
        &self,
        bbox: &BoundingBox,
        draw_ctx: &DrawingCtx,
        values: &ComputedValues,
    ) -> UserSpacePaintSource {
        match *self {
            PaintSource::None => UserSpacePaintSource::None,
            PaintSource::SolidColor(c) => UserSpacePaintSource::SolidColor(c),

            PaintSource::Gradient(ref g, c) => match (g.to_user_space(bbox, draw_ctx, values), c) {
                (Some(gradient), c) => UserSpacePaintSource::Gradient(gradient, c),
                (None, Some(c)) => UserSpacePaintSource::SolidColor(c),
                (None, None) => UserSpacePaintSource::None,
            },

            PaintSource::Pattern(ref p, c) => match (p.to_user_space(bbox, draw_ctx, values), c) {
                (Some(pattern), c) => UserSpacePaintSource::Pattern(pattern, c),
                (None, Some(c)) => UserSpacePaintSource::SolidColor(c),
                (None, None) => UserSpacePaintSource::None,
            },
        }
    }
}

fn resolve_color(
    color: &cssparser::Color,
    opacity: UnitInterval,
    current_color: cssparser::RGBA,
) -> cssparser::RGBA {
    let rgba = match *color {
        cssparser::Color::RGBA(rgba) => rgba,
        cssparser::Color::CurrentColor => current_color,
    };

    let UnitInterval(o) = opacity;

    let alpha = (f64::from(rgba.alpha) * o).round();
    let alpha = util::clamp(alpha, 0.0, 255.0);

    // For the following I'd prefer to use `cast::u8(alpha).unwrap()`
    // but the cast crate is erroneously returning Overflow for `u8(255.0)`:
    // https://github.com/japaric/cast.rs/issues/23

    let alpha = alpha as u8;

    cssparser::RGBA { alpha, ..rgba }
}

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

    #[test]
    fn catches_invalid_syntax() {
        assert!(PaintServer::parse_str("").is_err());
        assert!(PaintServer::parse_str("42").is_err());
        assert!(PaintServer::parse_str("invalid").is_err());
    }

    #[test]
    fn parses_none() {
        assert_eq!(PaintServer::parse_str("none").unwrap(), PaintServer::None);
    }

    #[test]
    fn parses_solid_color() {
        assert_eq!(
            PaintServer::parse_str("rgb(255, 128, 64, 0.5)").unwrap(),
            PaintServer::SolidColor(cssparser::Color::RGBA(cssparser::RGBA::new(
                255, 128, 64, 128
            )))
        );

        assert_eq!(
            PaintServer::parse_str("currentColor").unwrap(),
            PaintServer::SolidColor(cssparser::Color::CurrentColor)
        );
    }

    #[test]
    fn parses_iri() {
        assert_eq!(
            PaintServer::parse_str("url(#link)").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: None,
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(foo#link) none").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::External("foo".to_string(), "link".to_string())),
                alternate: None,
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) #ff8040").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 255
                ))),
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) rgb(255, 128, 64, 0.5)").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 128
                ))),
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) currentColor").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: Some(cssparser::Color::CurrentColor),
            }
        );

        assert!(PaintServer::parse_str("url(#link) invalid").is_err());
    }
}
<commit_msg>Add tests for resolve_color<commit_after>//! SVG paint servers.

use cssparser::Parser;

use crate::bbox::BoundingBox;
use crate::document::{AcquiredNodes, NodeId};
use crate::drawing_ctx::DrawingCtx;
use crate::element::Element;
use crate::error::{
    AcquireError, ImplementationLimit, NodeIdError, ParseError, RenderingError, ValueErrorKind,
};
use crate::gradient::{ResolvedGradient, UserSpaceGradient};
use crate::node::NodeBorrow;
use crate::parsers::Parse;
use crate::pattern::{ResolvedPattern, UserSpacePattern};
use crate::properties::ComputedValues;
use crate::unit_interval::UnitInterval;
use crate::util;

#[derive(Debug, Clone, PartialEq)]
pub enum PaintServer {
    None,
    Iri {
        iri: Box<NodeId>,
        alternate: Option<cssparser::Color>,
    },
    SolidColor(cssparser::Color),
}

pub enum PaintSource {
    None,
    Gradient(ResolvedGradient, Option<cssparser::RGBA>),
    Pattern(ResolvedPattern, Option<cssparser::RGBA>),
    SolidColor(cssparser::RGBA),
}

pub enum UserSpacePaintSource {
    None,
    Gradient(UserSpaceGradient, Option<cssparser::RGBA>),
    Pattern(UserSpacePattern, Option<cssparser::RGBA>),
    SolidColor(cssparser::RGBA),
}

impl Parse for PaintServer {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<PaintServer, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(PaintServer::None)
        } else if let Ok(url) = parser.try_parse(|i| i.expect_url()) {
            let loc = parser.current_source_location();

            let alternate = if !parser.is_exhausted() {
                if parser
                    .try_parse(|i| i.expect_ident_matching("none"))
                    .is_ok()
                {
                    None
                } else {
                    Some(parser.try_parse(|i| cssparser::Color::parse(i))?)
                }
            } else {
                None
            };

            Ok(PaintServer::Iri {
                iri: Box::new(
                    NodeId::parse(&url)
                        .map_err(|e: NodeIdError| -> ValueErrorKind { e.into() })
                        .map_err(|e| loc.new_custom_error(e))?,
                ),
                alternate,
            })
        } else {
            Ok(cssparser::Color::parse(parser).map(PaintServer::SolidColor)?)
        }
    }
}

impl PaintServer {
    pub fn resolve(
        &self,
        acquired_nodes: &mut AcquiredNodes<'_>,
        opacity: UnitInterval,
        current_color: cssparser::RGBA,
    ) -> Result<PaintSource, RenderingError> {
        match self {
            PaintServer::Iri {
                ref iri,
                ref alternate,
            } => acquired_nodes
                .acquire(iri)
                .and_then(|acquired| {
                    let node = acquired.get();
                    assert!(node.is_element());

                    match *node.borrow_element() {
                        Element::LinearGradient(ref g) => {
                            g.resolve(&node, acquired_nodes).map(|g| {
                                PaintSource::Gradient(
                                    g,
                                    alternate.map(|c| resolve_color(&c, opacity, current_color)),
                                )
                            })
                        }
                        Element::Pattern(ref p) => p.resolve(&node, acquired_nodes).map(|p| {
                            PaintSource::Pattern(
                                p,
                                alternate.map(|c| resolve_color(&c, opacity, current_color)),
                            )
                        }),
                        Element::RadialGradient(ref g) => {
                            g.resolve(&node, acquired_nodes).map(|g| {
                                PaintSource::Gradient(
                                    g,
                                    alternate.map(|c| resolve_color(&c, opacity, current_color)),
                                )
                            })
                        }
                        _ => Err(AcquireError::InvalidLinkType(iri.as_ref().clone())),
                    }
                })
                .or_else(|err| match (err, alternate) {
                    (AcquireError::MaxReferencesExceeded, _) => {
                        rsvg_log!("exceeded maximum number of referenced objects");
                        Err(RenderingError::LimitExceeded(
                            ImplementationLimit::TooManyReferencedElements,
                        ))
                    }

                    // The following two cases catch AcquireError::CircularReference, which for
                    // paint servers may mean that there is a pattern or gradient with a reference
                    // cycle in its "href" attribute.  This is an invalid paint server, and per
                    // https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint we should try to
                    // fall back to the alternate color.
                    (_, Some(color)) => {
                        rsvg_log!(
                            "could not resolve paint server \"{}\", using alternate color",
                            iri
                        );

                        Ok(PaintSource::SolidColor(resolve_color(
                            color,
                            opacity,
                            current_color,
                        )))
                    }

                    (_, _) => {
                        rsvg_log!(
                            "could not resolve paint server \"{}\", no alternate color specified",
                            iri
                        );

                        Ok(PaintSource::None)
                    }
                }),

            PaintServer::SolidColor(color) => Ok(PaintSource::SolidColor(resolve_color(
                color,
                opacity,
                current_color,
            ))),

            PaintServer::None => Ok(PaintSource::None),
        }
    }
}

impl PaintSource {
    pub fn to_user_space(
        &self,
        bbox: &BoundingBox,
        draw_ctx: &DrawingCtx,
        values: &ComputedValues,
    ) -> UserSpacePaintSource {
        match *self {
            PaintSource::None => UserSpacePaintSource::None,
            PaintSource::SolidColor(c) => UserSpacePaintSource::SolidColor(c),

            PaintSource::Gradient(ref g, c) => match (g.to_user_space(bbox, draw_ctx, values), c) {
                (Some(gradient), c) => UserSpacePaintSource::Gradient(gradient, c),
                (None, Some(c)) => UserSpacePaintSource::SolidColor(c),
                (None, None) => UserSpacePaintSource::None,
            },

            PaintSource::Pattern(ref p, c) => match (p.to_user_space(bbox, draw_ctx, values), c) {
                (Some(pattern), c) => UserSpacePaintSource::Pattern(pattern, c),
                (None, Some(c)) => UserSpacePaintSource::SolidColor(c),
                (None, None) => UserSpacePaintSource::None,
            },
        }
    }
}

fn resolve_color(
    color: &cssparser::Color,
    opacity: UnitInterval,
    current_color: cssparser::RGBA,
) -> cssparser::RGBA {
    let rgba = match *color {
        cssparser::Color::RGBA(rgba) => rgba,
        cssparser::Color::CurrentColor => current_color,
    };

    let UnitInterval(o) = opacity;

    let alpha = (f64::from(rgba.alpha) * o).round();
    let alpha = util::clamp(alpha, 0.0, 255.0);

    // For the following I'd prefer to use `cast::u8(alpha).unwrap()`
    // but the cast crate is erroneously returning Overflow for `u8(255.0)`:
    // https://github.com/japaric/cast.rs/issues/23

    let alpha = alpha as u8;

    cssparser::RGBA { alpha, ..rgba }
}

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

    #[test]
    fn catches_invalid_syntax() {
        assert!(PaintServer::parse_str("").is_err());
        assert!(PaintServer::parse_str("42").is_err());
        assert!(PaintServer::parse_str("invalid").is_err());
    }

    #[test]
    fn parses_none() {
        assert_eq!(PaintServer::parse_str("none").unwrap(), PaintServer::None);
    }

    #[test]
    fn parses_solid_color() {
        assert_eq!(
            PaintServer::parse_str("rgb(255, 128, 64, 0.5)").unwrap(),
            PaintServer::SolidColor(cssparser::Color::RGBA(cssparser::RGBA::new(
                255, 128, 64, 128
            )))
        );

        assert_eq!(
            PaintServer::parse_str("currentColor").unwrap(),
            PaintServer::SolidColor(cssparser::Color::CurrentColor)
        );
    }

    #[test]
    fn parses_iri() {
        assert_eq!(
            PaintServer::parse_str("url(#link)").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: None,
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(foo#link) none").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::External("foo".to_string(), "link".to_string())),
                alternate: None,
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) #ff8040").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 255
                ))),
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) rgb(255, 128, 64, 0.5)").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 128
                ))),
            }
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) currentColor").unwrap(),
            PaintServer::Iri {
                iri: Box::new(NodeId::Internal("link".to_string())),
                alternate: Some(cssparser::Color::CurrentColor),
            }
        );

        assert!(PaintServer::parse_str("url(#link) invalid").is_err());
    }

    #[test]
    fn resolves_explicit_color() {
        use cssparser::{Color, RGBA};

        assert_eq!(
            resolve_color(
                &Color::RGBA(RGBA::new(255, 0, 0, 128)),
                UnitInterval::clamp(0.5),
                RGBA::new(0, 255, 0, 255)
            ),
            RGBA::new(255, 0, 0, 64),
        );
    }

    #[test]
    fn resolves_current_color() {
        use cssparser::{Color, RGBA};

        assert_eq!(
            resolve_color(
                &Color::CurrentColor,
                UnitInterval::clamp(0.5),
                RGBA::new(0, 255, 0, 128)
            ),
            RGBA::new(0, 255, 0, 64),
        );
    }
}
<|endoftext|>


<commit_before>//! Sanity checking performed by rustbuild before actually executing anything.
//!
//! This module contains the implementation of ensuring that the build
//! environment looks reasonable before progressing. This will verify that
//! various programs like git and python exist, along with ensuring that all C
//! compilers for cross-compiling are found.
//!
//! In theory if we get past this phase it's a bug if a build fails, but in
//! practice that's likely not true!

use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::PathBuf;
use std::process::Command;

use build_helper::{output, t};

use crate::cache::INTERNER;
use crate::config::Target;
use crate::Build;

pub struct Finder {
    cache: HashMap<OsString, Option<PathBuf>>,
    path: OsString,
}

impl Finder {
    pub fn new() -> Self {
        Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
    }

    pub fn maybe_have<S: Into<OsString>>(&mut self, cmd: S) -> Option<PathBuf> {
        let cmd: OsString = cmd.into();
        let path = &self.path;
        self.cache
            .entry(cmd.clone())
            .or_insert_with(|| {
                for path in env::split_paths(path) {
                    let target = path.join(&cmd);
                    let mut cmd_exe = cmd.clone();
                    cmd_exe.push(".exe");

                    if target.is_file()                   // some/path/git
                    || path.join(&cmd_exe).exists()   // some/path/git.exe
                    || target.join(&cmd_exe).exists()
                    // some/path/git/git.exe
                    {
                        return Some(target);
                    }
                }
                None
            })
            .clone()
    }

    pub fn must_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> PathBuf {
        self.maybe_have(&cmd).unwrap_or_else(|| {
            panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref());
        })
    }
}

pub fn check(build: &mut Build) {
    let path = env::var_os("PATH").unwrap_or_default();
    // On Windows, quotes are invalid characters for filename paths, and if
    // one is present as part of the PATH then that can lead to the system
    // being unable to identify the files properly. See
    // https://github.com/rust-lang/rust/issues/34959 for more details.
    if cfg!(windows) && path.to_string_lossy().contains('\"') {
        panic!("PATH contains invalid character '\"'");
    }

    let mut cmd_finder = Finder::new();
    // If we've got a git directory we're gonna need git to update
    // submodules and learn about various other aspects.
    if build.rust_info.is_git() {
        cmd_finder.must_have("git");
    }

    // We need cmake, but only if we're actually building LLVM or sanitizers.
    let building_llvm = build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
        && build
            .hosts
            .iter()
            .map(|host| {
                build
                    .config
                    .target_config
                    .get(host)
                    .map(|config| config.llvm_config.is_none())
                    .unwrap_or(true)
            })
            .any(|build_llvm_ourselves| build_llvm_ourselves);
    let need_cmake = building_llvm || build.config.any_sanitizers_enabled();
    if need_cmake {
        cmd_finder.must_have("cmake");
    }

    build.config.python = build
        .config
        .python
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
        .or_else(|| Some(cmd_finder.must_have("python")));

    build.config.nodejs = build
        .config
        .nodejs
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("node"))
        .or_else(|| cmd_finder.maybe_have("nodejs"));

    build.config.npm = build
        .config
        .npm
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("npm"));

    build.config.gdb = build
        .config
        .gdb
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("gdb"));

    // We're gonna build some custom C code here and there, host triples
    // also build some C++ shims for LLVM so we need a C++ compiler.
    for target in &build.targets {
        // On emscripten we don't actually need the C compiler to just
        // build the target artifacts, only for testing. For the sake
        // of easier bot configuration, just skip detection.
        if target.contains("emscripten") {
            continue;
        }

        // We don't use a C compiler on wasm32
        if target.contains("wasm32") {
            continue;
        }

        if !build.config.dry_run {
            cmd_finder.must_have(build.cc(*target));
            if let Some(ar) = build.ar(*target) {
                cmd_finder.must_have(ar);
            }
        }
    }

    for host in &build.hosts {
        if !build.config.dry_run {
            cmd_finder.must_have(build.cxx(*host).unwrap());
        }
    }

    if build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
        // Externally configured LLVM requires FileCheck to exist
        let filecheck = build.llvm_filecheck(build.build);
        if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
            panic!("FileCheck executable {:?} does not exist", filecheck);
        }
    }

    for target in &build.targets {
        // Can't compile for iOS unless we're on macOS
        if target.contains("apple-ios") && !build.build.contains("apple-darwin") {
            panic!("the iOS target is only supported on macOS");
        }

        build
            .config
            .target_config
            .entry(*target)
            .or_insert_with(|| Target::from_triple(&target.triple));

        if target.contains("-none-") || target.contains("nvptx") {
            if build.no_std(*target) == Some(false) {
                panic!("All the *-none-* and nvptx* targets are no-std targets")
            }
        }

        // Make sure musl-root is valid
        if target.contains("musl") {
            // If this is a native target (host is also musl) and no musl-root is given,
            // fall back to the system toolchain in /usr before giving up
            if build.musl_root(*target).is_none() && build.config.build == *target {
                let target = build.config.target_config.entry(*target).or_default();
                target.musl_root = Some("/usr".into());
            }
            match build.musl_libdir(*target) {
                Some(libdir) => {
                    if fs::metadata(libdir.join("libc.a")).is_err() {
                        panic!("couldn't find libc.a in musl libdir: {}", libdir.display());
                    }
                }
                None => panic!(
                    "when targeting MUSL either the rust.musl-root \
                            option or the target.$TARGET.musl-root option must \
                            be specified in config.toml"
                ),
            }
        }

        if need_cmake && target.contains("msvc") {
            // There are three builds of cmake on windows: MSVC, MinGW, and
            // Cygwin. The Cygwin build does not have generators for Visual
            // Studio, so detect that here and error.
            let out = output(Command::new("cmake").arg("--help"));
            if !out.contains("Visual Studio") {
                panic!(
                    "
cmake does not support Visual Studio generators.

This is likely due to it being an msys/cygwin build of cmake,
rather than the required windows version, built using MinGW
or Visual Studio.

If you are building under msys2 try installing the mingw-w64-x86_64-cmake
package instead of cmake:

$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
"
                );
            }
        }
    }

    if let Some(ref s) = build.config.ccache {
        cmd_finder.must_have(s);
    }

    if build.config.channel == "stable" {
        let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt")));
        if stage0.contains("\ndev:") {
            panic!(
                "bootstrapping from a dev compiler in a stable release, but \
                    should only be bootstrapping from a released compiler!"
            );
        }
    }
}
<commit_msg>Rollup merge of #88072 - kit-981:feature/build-ios-toolchain-on-linux, r=Mark-Simulacrum<commit_after>//! Sanity checking performed by rustbuild before actually executing anything.
//!
//! This module contains the implementation of ensuring that the build
//! environment looks reasonable before progressing. This will verify that
//! various programs like git and python exist, along with ensuring that all C
//! compilers for cross-compiling are found.
//!
//! In theory if we get past this phase it's a bug if a build fails, but in
//! practice that's likely not true!

use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::PathBuf;
use std::process::Command;

use build_helper::{output, t};

use crate::cache::INTERNER;
use crate::config::Target;
use crate::Build;

pub struct Finder {
    cache: HashMap<OsString, Option<PathBuf>>,
    path: OsString,
}

impl Finder {
    pub fn new() -> Self {
        Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
    }

    pub fn maybe_have<S: Into<OsString>>(&mut self, cmd: S) -> Option<PathBuf> {
        let cmd: OsString = cmd.into();
        let path = &self.path;
        self.cache
            .entry(cmd.clone())
            .or_insert_with(|| {
                for path in env::split_paths(path) {
                    let target = path.join(&cmd);
                    let mut cmd_exe = cmd.clone();
                    cmd_exe.push(".exe");

                    if target.is_file()                   // some/path/git
                    || path.join(&cmd_exe).exists()   // some/path/git.exe
                    || target.join(&cmd_exe).exists()
                    // some/path/git/git.exe
                    {
                        return Some(target);
                    }
                }
                None
            })
            .clone()
    }

    pub fn must_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> PathBuf {
        self.maybe_have(&cmd).unwrap_or_else(|| {
            panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref());
        })
    }
}

pub fn check(build: &mut Build) {
    let path = env::var_os("PATH").unwrap_or_default();
    // On Windows, quotes are invalid characters for filename paths, and if
    // one is present as part of the PATH then that can lead to the system
    // being unable to identify the files properly. See
    // https://github.com/rust-lang/rust/issues/34959 for more details.
    if cfg!(windows) && path.to_string_lossy().contains('\"') {
        panic!("PATH contains invalid character '\"'");
    }

    let mut cmd_finder = Finder::new();
    // If we've got a git directory we're gonna need git to update
    // submodules and learn about various other aspects.
    if build.rust_info.is_git() {
        cmd_finder.must_have("git");
    }

    // We need cmake, but only if we're actually building LLVM or sanitizers.
    let building_llvm = build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
        && build
            .hosts
            .iter()
            .map(|host| {
                build
                    .config
                    .target_config
                    .get(host)
                    .map(|config| config.llvm_config.is_none())
                    .unwrap_or(true)
            })
            .any(|build_llvm_ourselves| build_llvm_ourselves);
    let need_cmake = building_llvm || build.config.any_sanitizers_enabled();
    if need_cmake {
        cmd_finder.must_have("cmake");
    }

    build.config.python = build
        .config
        .python
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
        .or_else(|| Some(cmd_finder.must_have("python")));

    build.config.nodejs = build
        .config
        .nodejs
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("node"))
        .or_else(|| cmd_finder.maybe_have("nodejs"));

    build.config.npm = build
        .config
        .npm
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("npm"));

    build.config.gdb = build
        .config
        .gdb
        .take()
        .map(|p| cmd_finder.must_have(p))
        .or_else(|| cmd_finder.maybe_have("gdb"));

    // We're gonna build some custom C code here and there, host triples
    // also build some C++ shims for LLVM so we need a C++ compiler.
    for target in &build.targets {
        // On emscripten we don't actually need the C compiler to just
        // build the target artifacts, only for testing. For the sake
        // of easier bot configuration, just skip detection.
        if target.contains("emscripten") {
            continue;
        }

        // We don't use a C compiler on wasm32
        if target.contains("wasm32") {
            continue;
        }

        if !build.config.dry_run {
            cmd_finder.must_have(build.cc(*target));
            if let Some(ar) = build.ar(*target) {
                cmd_finder.must_have(ar);
            }
        }
    }

    for host in &build.hosts {
        if !build.config.dry_run {
            cmd_finder.must_have(build.cxx(*host).unwrap());
        }
    }

    if build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
        // Externally configured LLVM requires FileCheck to exist
        let filecheck = build.llvm_filecheck(build.build);
        if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
            panic!("FileCheck executable {:?} does not exist", filecheck);
        }
    }

    for target in &build.targets {
        build
            .config
            .target_config
            .entry(*target)
            .or_insert_with(|| Target::from_triple(&target.triple));

        if target.contains("-none-") || target.contains("nvptx") {
            if build.no_std(*target) == Some(false) {
                panic!("All the *-none-* and nvptx* targets are no-std targets")
            }
        }

        // Make sure musl-root is valid
        if target.contains("musl") {
            // If this is a native target (host is also musl) and no musl-root is given,
            // fall back to the system toolchain in /usr before giving up
            if build.musl_root(*target).is_none() && build.config.build == *target {
                let target = build.config.target_config.entry(*target).or_default();
                target.musl_root = Some("/usr".into());
            }
            match build.musl_libdir(*target) {
                Some(libdir) => {
                    if fs::metadata(libdir.join("libc.a")).is_err() {
                        panic!("couldn't find libc.a in musl libdir: {}", libdir.display());
                    }
                }
                None => panic!(
                    "when targeting MUSL either the rust.musl-root \
                            option or the target.$TARGET.musl-root option must \
                            be specified in config.toml"
                ),
            }
        }

        if need_cmake && target.contains("msvc") {
            // There are three builds of cmake on windows: MSVC, MinGW, and
            // Cygwin. The Cygwin build does not have generators for Visual
            // Studio, so detect that here and error.
            let out = output(Command::new("cmake").arg("--help"));
            if !out.contains("Visual Studio") {
                panic!(
                    "
cmake does not support Visual Studio generators.

This is likely due to it being an msys/cygwin build of cmake,
rather than the required windows version, built using MinGW
or Visual Studio.

If you are building under msys2 try installing the mingw-w64-x86_64-cmake
package instead of cmake:

$ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
"
                );
            }
        }
    }

    if let Some(ref s) = build.config.ccache {
        cmd_finder.must_have(s);
    }

    if build.config.channel == "stable" {
        let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt")));
        if stage0.contains("\ndev:") {
            panic!(
                "bootstrapping from a dev compiler in a stable release, but \
                    should only be bootstrapping from a released compiler!"
            );
        }
    }
}
<|endoftext|>


<commit_before>use memory::Memory;
use std::io;

#[allow(dead_assignment)]
pub fn interpret(str: String, mem: &mut Memory) {
	let test_arr = str.into_bytes();
	let mut test_ptr = 0u;
	let mut reader = io::stdin();

	while test_ptr < test_arr.len() {
		let mut ainc = true;
		match test_arr[test_ptr] as char {
			'>' => mem.fwd(),
			'+' => mem.inc(),
			'-' => mem.dcr(),
			'<' => mem.bck(),
			'!' => print!("{}", mem.get() as u8 as char),
			'*' => mem.lft(10),
			'/' => mem.dwn(10),
			')' => mem.adv(10),
			'(' => mem.rwd(10),
			'[' => {
				if mem.get() == 0 {
					while test_ptr < test_arr.len() && test_arr[test_ptr] as char != ']' {
						test_ptr += 1;
					}
					ainc = false;
				}
			},
			']' => {
				if mem.get() != 0 {
					while test_ptr > 0 && test_arr[test_ptr] as char != '[' {
						test_ptr -= 1;
					}
					ainc = false;
				}
			},
			'?' => print!("{}", mem.getptr()),
			'&' => print!("{}", mem.getptr() as u8 as char),
			'.' => print!("{}", mem.get()),
			'`' => {
				let inchr = match reader.read_byte() {
					Ok(val) => val,
					Err(err) => {
						if err.kind != io::EndOfFile {
							fail!(err)
						}
						else {
							0 // EOF
						}
					}
				};

				mem.set(inchr as int);
			},
			'^' => mem.setptr(0),
			'#' => mem.set(0),
			_ => { /* We're a pretty ignorant parser... */ }
		}
		if ainc {
			test_ptr += 1;
		}
		ainc = true;
		//println!("{}", test_arr[test_ptr] as char);
	}

	// Prints the last accessed cell's value
	// println!("{}", mem.get());
}

/*
#[allow(dead_assignment)]
pub fn dummy_interpret(str: String, mem: &mut Memory) {
	let test_arr = str.into_bytes();
	let mut test_ptr = 0u;
	let mut input = io::stdin();

	while test_ptr < test_arr.len() {
		let mut ainc = true;
		match test_arr[test_ptr] as char {
			'>' => {println!("FWD"); mem.fwd()},
			'+' => {println!("INC"); mem.inc()},
			'-' => {println!("DCR"); mem.dcr()},
			'<' => {println!("BCK"); mem.bck()},
			'!' => println!("PCC*"),
			'*' => {println!("LFT"); mem.lft(10)},
			'/' => {println!("DWN"); mem.dwn(10)},
			')' => {println!("ADV"); mem.adv(10)},
			'(' => {println!("RWD"); mem.rwd(10)},
			'[' => {
				println!("LBL");
				if mem.get() == 0 {
					while test_ptr < test_arr.len() && test_arr[test_ptr] as char != ']' {
						test_ptr += 1;
					}
					ainc = false;
				}
			},
			']' => {
				println!("RBL");
				if mem.get() != 0 {
					while test_ptr > 0 && test_arr[test_ptr] as char != '[' {
						test_ptr -= 1;
					}
					ainc = false;
				}
			},
			'?' => println!("PPL*"),
			'&' => println!("PPC*"),
			'.' => println!("PCL*"),
			'`' => {
				println!("INP");
				let inchr = match input.read_byte() {
					Ok(val) => val,
					Err(err) => {
						if err.kind != io::EndOfFile {
							fail!(err)
						}
						else {
							0 // EOF
						}
					}
				};

				mem.set(inchr as int);
			},
			'^' => {println!("RPT"); mem.setptr(0)},
			'#' => {println!("RCV"); mem.set(0)},
			_ => { }
		}
		if ainc {
			test_ptr += 1;
		}
		ainc = true;
		//println!("{}", test_arr[test_ptr] as char);
	}
}
*/<commit_msg>Giving interpret internals proper names.<commit_after>use memory::Memory;
use std::io;

#[allow(dead_assignment)]
pub fn interpret(str: String, mem: &mut Memory) {
	let code_arr = str.into_bytes();
	let mut code_ptr = 0u;
	let mut reader = io::stdin();

	while code_ptr < code_arr.len() {
		let mut ainc = true;
		match code_arr[code_ptr] as char {
			'>' => mem.fwd(),
			'+' => mem.inc(),
			'-' => mem.dcr(),
			'<' => mem.bck(),
			'!' => print!("{}", mem.get() as u8 as char),
			'*' => mem.lft(10),
			'/' => mem.dwn(10),
			')' => mem.adv(10),
			'(' => mem.rwd(10),
			'[' => {
				if mem.get() == 0 {
					while code_ptr < code_arr.len() && code_arr[code_ptr] as char != ']' {
						code_ptr += 1;
					}
					ainc = false;
				}
			},
			']' => {
				if mem.get() != 0 {
					while code_ptr > 0 && code_arr[code_ptr] as char != '[' {
						code_ptr -= 1;
					}
					ainc = false;
				}
			},
			'?' => print!("{}", mem.getptr()),
			'&' => print!("{}", mem.getptr() as u8 as char),
			'.' => print!("{}", mem.get()),
			'`' => {
				let inchr = match reader.read_byte() {
					Ok(val) => val,
					Err(err) => {
						if err.kind != io::EndOfFile {
							fail!(err)
						}
						else {
							0 // EOF
						}
					}
				};

				mem.set(inchr as int);
			},
			'^' => mem.setptr(0),
			'#' => mem.set(0),
			_ => { /* We're a pretty ignorant parser... */ }
		}
		if ainc {
			code_ptr += 1;
		}
		ainc = true;
		//println!("{}", code_arr[code_ptr] as char);
	}

	// Prints the last accessed cell's value
	// println!("{}", mem.get());
}

/*
#[allow(dead_assignment)]
pub fn dummy_interpret(str: String, mem: &mut Memory) {
	let code_arr = str.into_bytes();
	let mut code_ptr = 0u;
	let mut input = io::stdin();

	while code_ptr < code_arr.len() {
		let mut ainc = true;
		match code_arr[code_ptr] as char {
			'>' => {println!("FWD"); mem.fwd()},
			'+' => {println!("INC"); mem.inc()},
			'-' => {println!("DCR"); mem.dcr()},
			'<' => {println!("BCK"); mem.bck()},
			'!' => println!("PCC*"),
			'*' => {println!("LFT"); mem.lft(10)},
			'/' => {println!("DWN"); mem.dwn(10)},
			')' => {println!("ADV"); mem.adv(10)},
			'(' => {println!("RWD"); mem.rwd(10)},
			'[' => {
				println!("LBL");
				if mem.get() == 0 {
					while code_ptr < code_arr.len() && code_arr[code_ptr] as char != ']' {
						code_ptr += 1;
					}
					ainc = false;
				}
			},
			']' => {
				println!("RBL");
				if mem.get() != 0 {
					while code_ptr > 0 && code_arr[code_ptr] as char != '[' {
						code_ptr -= 1;
					}
					ainc = false;
				}
			},
			'?' => println!("PPL*"),
			'&' => println!("PPC*"),
			'.' => println!("PCL*"),
			'`' => {
				println!("INP");
				let inchr = match input.read_byte() {
					Ok(val) => val,
					Err(err) => {
						if err.kind != io::EndOfFile {
							fail!(err)
						}
						else {
							0 // EOF
						}
					}
				};

				mem.set(inchr as int);
			},
			'^' => {println!("RPT"); mem.setptr(0)},
			'#' => {println!("RCV"); mem.set(0)},
			_ => { }
		}
		if ainc {
			code_ptr += 1;
		}
		ainc = true;
		//println!("{}", code_arr[code_ptr] as char);
	}
}
*/<|endoftext|>


<commit_before>use std::num::Float;
use std::f64::consts::PI;

use sdl2::event::Event;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::RenderDrawer;

static PADDLE_COLOR: Color = Color::RGB(255, 255, 255);
static PADDLE_WIDTH: i32 = 12;
static PADDLE_HEIGHT: i32 = 64;
static PADDLE_WALL_PADDING: i32 = 10;

static BALL_COLOR: Color = Color::RGB(175, 175, 175);
static BALL_BREADTH: i32 = 8;
static BALL_VELOCITY: f64 = 15.0;
static BALL_INITIAL_ANGLE_DEGREES: i32 = 0;

pub struct GameController {
    ball_position: (i32, i32),
    ball_angle: f64,
    player_paddle_y: i32,
    opponent_paddle_y: i32
}

impl GameController {
    pub fn new() -> GameController {
        return GameController{
            ball_position: (800 / 2 - BALL_BREADTH / 2, 600 / 2 - BALL_BREADTH / 2),
            ball_angle: (BALL_INITIAL_ANGLE_DEGREES as f64).to_radians(),
            player_paddle_y: 280,
            opponent_paddle_y: 10,
        }
    }

    pub fn tick(&mut self, _: &Event, drawer: &mut RenderDrawer) {
        self.move_ball();
        self.draw_player(drawer);
        self.draw_opponent(drawer);
        self.draw_ball(drawer);
    }

    // TODO this shouldn't be framerate/vsync dependent.
    // Thanks StackOverflow!
    // http://stackoverflow.com/questions/5830791/find-radians-reflection-angle
    fn move_ball(&mut self) {
        let x_change = (self.ball_angle.cos() * BALL_VELOCITY) as i32;
        let y_change = (self.ball_angle.sin() * BALL_VELOCITY) as i32;

        let (mut x, mut y) = self.ball_position;
        x += x_change;
        y += y_change;

        // Wall collision
        if y > 600 || y < 0 { self.ball_angle *= -1.0 }
        if y > 600 { y = 600; }
        else if y < 0 { y = 0; }

        // Paddle collision
        // TODO ball dimensions aren't respected. Left side of ball hits on the left, right side of
        // ball hits on the right. Also need to reset ball x on impact.
        let player_paddle_x = PADDLE_WALL_PADDING + PADDLE_WIDTH;
        let player_paddle_impacted = x <= player_paddle_x && y >= self.player_paddle_y && y <= self.player_paddle_y + PADDLE_HEIGHT;
        let opponent_paddle_x = 800 - PADDLE_WALL_PADDING - PADDLE_WIDTH - BALL_BREADTH;
        //let opponent_paddle_impacted = x >= opponent_paddle_x && y >= self.opponent_paddle_y && y <= self.opponent_paddle_y + PADDLE_HEIGHT;
        let opponent_paddle_impacted = x >= opponent_paddle_x; // Invincible opponent until AI.
        if player_paddle_impacted || opponent_paddle_impacted {
            self.ball_angle = 0.0 - PI - self.ball_angle;
        }

        self.ball_position = (x, y);
    }

    fn draw_player(&self, d: &mut RenderDrawer) {
        self.draw_box(d, PADDLE_WALL_PADDING, self.player_paddle_y);
    }

    fn draw_opponent(&self, d: &mut RenderDrawer) {
        self.draw_box(d, 800 - PADDLE_WIDTH - PADDLE_WALL_PADDING, self.opponent_paddle_y);
    }

    fn draw_box(&self, d: &mut RenderDrawer, x: i32, y: i32) {
        d.set_draw_color(PADDLE_COLOR);
        let r = Rect{x: x, y: y, w: PADDLE_WIDTH, h: PADDLE_HEIGHT};
        d.fill_rect(r);
     }

    fn draw_ball(&self, d: &mut RenderDrawer) {
        d.set_draw_color(BALL_COLOR);
        let (x, y) = self.ball_position;
        let r = Rect{x: x, y: y, w: BALL_BREADTH, h: BALL_BREADTH};
        d.fill_rect(r);
    }
}
<commit_msg>Fix ball technically going out of bottom bound.<commit_after>use std::num::Float;
use std::f64::consts::PI;

use sdl2::event::Event;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::RenderDrawer;

static PADDLE_COLOR: Color = Color::RGB(255, 255, 255);
static PADDLE_WIDTH: i32 = 12;
static PADDLE_HEIGHT: i32 = 64;
static PADDLE_WALL_PADDING: i32 = 10;

static BALL_COLOR: Color = Color::RGB(175, 175, 175);
static BALL_BREADTH: i32 = 8;
static BALL_VELOCITY: f64 = 15.0;
static BALL_INITIAL_ANGLE_DEGREES: i32 = 0;

pub struct GameController {
    ball_position: (i32, i32),
    ball_angle: f64,
    player_paddle_y: i32,
    opponent_paddle_y: i32
}

impl GameController {
    pub fn new() -> GameController {
        return GameController{
            ball_position: (800 / 2 - BALL_BREADTH / 2, 600 / 2 - BALL_BREADTH / 2),
            ball_angle: (BALL_INITIAL_ANGLE_DEGREES as f64).to_radians(),
            player_paddle_y: 280,
            opponent_paddle_y: 10,
        }
    }

    pub fn tick(&mut self, _: &Event, drawer: &mut RenderDrawer) {
        self.move_ball();
        self.draw_player(drawer);
        self.draw_opponent(drawer);
        self.draw_ball(drawer);
    }

    // TODO this shouldn't be framerate/vsync dependent.
    // Thanks StackOverflow!
    // http://stackoverflow.com/questions/5830791/find-radians-reflection-angle
    fn move_ball(&mut self) {
        let x_change = (self.ball_angle.cos() * BALL_VELOCITY) as i32;
        let y_change = (self.ball_angle.sin() * BALL_VELOCITY) as i32;

        let (mut x, mut y) = self.ball_position;
        x += x_change;
        y += y_change;

        // Wall collision
        let upper_y_limit = 600 - BALL_BREADTH;
        if y > upper_y_limit || y < 0 { self.ball_angle *= -1.0 }
        if y > upper_y_limit { y = upper_y_limit; }
        else if y < 0 { y = 0; }

        // Paddle collision
        // TODO ball dimensions aren't respected. Left side of ball hits on the left, right side of
        // ball hits on the right. Also need to reset ball x on impact.
        let player_paddle_x = PADDLE_WALL_PADDING + PADDLE_WIDTH;
        let player_paddle_impacted = x <= player_paddle_x && y >= self.player_paddle_y && y <= self.player_paddle_y + PADDLE_HEIGHT;
        let opponent_paddle_x = 800 - PADDLE_WALL_PADDING - PADDLE_WIDTH - BALL_BREADTH;
        //let opponent_paddle_impacted = x >= opponent_paddle_x && y >= self.opponent_paddle_y && y <= self.opponent_paddle_y + PADDLE_HEIGHT;
        let opponent_paddle_impacted = x >= opponent_paddle_x; // Invincible opponent until AI.
        if player_paddle_impacted || opponent_paddle_impacted {
            self.ball_angle = 0.0 - PI - self.ball_angle;
        }

        self.ball_position = (x, y);
    }

    fn draw_player(&self, d: &mut RenderDrawer) {
        self.draw_box(d, PADDLE_WALL_PADDING, self.player_paddle_y);
    }

    fn draw_opponent(&self, d: &mut RenderDrawer) {
        self.draw_box(d, 800 - PADDLE_WIDTH - PADDLE_WALL_PADDING, self.opponent_paddle_y);
    }

    fn draw_box(&self, d: &mut RenderDrawer, x: i32, y: i32) {
        d.set_draw_color(PADDLE_COLOR);
        let r = Rect{x: x, y: y, w: PADDLE_WIDTH, h: PADDLE_HEIGHT};
        d.fill_rect(r);
     }

    fn draw_ball(&self, d: &mut RenderDrawer) {
        d.set_draw_color(BALL_COLOR);
        let (x, y) = self.ball_position;
        let r = Rect{x: x, y: y, w: BALL_BREADTH, h: BALL_BREADTH};
        d.fill_rect(r);
    }
}
<|endoftext|>


<commit_before>/**
 * 5.3 Tuples
 * http://static.rust-lang.org/doc/master/tutorial.html#tuples
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
fn main() {
	// A Tuple is an immutable fixed-size collection of values.

	let tuple0 = ();
	println!("{:?}", tuple0);

	let mytup: (int, int, f64) = (10, 20, 30.0);
	match mytup {
		(a, b, c) => info!("{}", a + b + (c as int))
	}

	let tuple1 = (5i, 6i);
	let (first, _) = tuple1;
	println!("{}", first);
}
<commit_msg>Changes to version 0.10-pre (af93684 2014-03-17 11:57:08)<commit_after>/**
 * 5.3 Tuples
 * http://static.rust-lang.org/doc/master/tutorial.html#tuples
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
fn main() {
	// A Tuple is an immutable fixed-size collection of values.

	let tuple0 = ();
	println!("{:?}", tuple0);

	let mytup: (int, int, f64) = (10, 20, 30.0);
	match mytup {
		(a, b, c) => println!("{}", a + b + (c as int))
	}

	let tuple1 = (5i, 6i);
	let (first, _) = tuple1;
	println!("{}", first);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

{
    macro_rules! move_ref(
        { $x:expr } => { unsafe { let y <- *ptr::addr_of(*$x); y } }
    )

    macro_rules! move_val(
        { $x:expr } => { unsafe { let y <- *ptr::addr_of(*$x); y } }
    )

    // select!
    macro_rules! select_if(

        {
            $index:expr,
            $count:expr
        } => {
            fail
        };

        {
            $index:expr,
            $count:expr,
            $port:path => [
                $(type_this $message:path$(($(x $x: ident),+))dont_type_this*
                  -> $next:ident => { $e:expr }),+
            ]
            $(, $ports:path => [
                $(type_this $messages:path$(($(x $xs: ident),+))dont_type_this*
                  -> $nexts:ident => { $es:expr }),+
            ] )*
        } => {
            if $index == $count {
                match pipes::try_recv($port) {
                  $(Some($message($($(ref $x,)+)* ref next)) => {
                    // FIXME (#2329) we really want move out of enum here.
                    let $next = move_ref!(next);
                    $e
                  })+
                  _ => fail
                }
            } else {
                select_if!(
                    $index,
                    $count + 1
                    $(, $ports => [
                        $(type_this $messages$(($(x $xs),+))dont_type_this*
                          -> $nexts => { $es }),+
                    ])*
                )
            }
        };
    )

    macro_rules! select(
        {
            $( $port:path => {
                $($message:path$(($($x: ident),+))dont_type_this*
                  -> $next:ident $e:expr),+
            } )+
        } => {
            let index = pipes::selecti([$(($port).header()),+]/_);
            select_if!(index, 0 $(, $port => [
                $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { $e }),+
            ])+)
        }
    )
}
<commit_msg>update: servo for rust language change<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

{
    macro_rules! move_ref(
        { $x:expr } => { unsafe { let y <- *ptr::to_unsafe_ptr(*$x); y } }
    )

    macro_rules! move_val(
        { $x:expr } => { unsafe { let y <- *ptr::to_unsafe_ptr(*$x); y } }
    )

    // select!
    macro_rules! select_if(

        {
            $index:expr,
            $count:expr
        } => {
            fail
        };

        {
            $index:expr,
            $count:expr,
            $port:path => [
                $(type_this $message:path$(($(x $x: ident),+))dont_type_this*
                  -> $next:ident => { $e:expr }),+
            ]
            $(, $ports:path => [
                $(type_this $messages:path$(($(x $xs: ident),+))dont_type_this*
                  -> $nexts:ident => { $es:expr }),+
            ] )*
        } => {
            if $index == $count {
                match pipes::try_recv($port) {
                  $(Some($message($($(ref $x,)+)* ref next)) => {
                    // FIXME (#2329) we really want move out of enum here.
                    let $next = move_ref!(next);
                    $e
                  })+
                  _ => fail
                }
            } else {
                select_if!(
                    $index,
                    $count + 1
                    $(, $ports => [
                        $(type_this $messages$(($(x $xs),+))dont_type_this*
                          -> $nexts => { $es }),+
                    ])*
                )
            }
        };
    )

    macro_rules! select(
        {
            $( $port:path => {
                $($message:path$(($($x: ident),+))dont_type_this*
                  -> $next:ident $e:expr),+
            } )+
        } => {
            let index = pipes::selecti([$(($port).header()),+]/_);
            select_if!(index, 0 $(, $port => [
                $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { $e }),+
            ])+)
        }
    )
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Definitions and utilities for working with sinks.
//!
//! Sinks ("well-known flows" in terms of GRR nomenclature) are ever-existing
//! sessions on the GRR server that listen for various kinds of data. They are
//! a way to break away from the usual request-response workflow.
//!
//! For example, sinks can be used to notify the server about agent startup
//! (which is clearly not a response to a particular request) or to transfer
//! file blobs to a specialized storage.

use crate::action;
use crate::session;

/// Handle to a specific sink.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Sink {
    /// An underlying identifier of the sink.
    id: &'static str,
}

impl Sink {

    /// A handle to the sink expecting startup information.
    pub const STARTUP: Sink = Sink { id: "/flows/F:Startup" };

    /// Wraps an action response to a sink-specific session response.
    pub fn wrap<R>(&self, response: R) -> session::Response<R>
    where
        R: action::Response,
    {
        session::Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }
    }
}
<commit_msg>Derive the `Hash` trait for sinks.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Definitions and utilities for working with sinks.
//!
//! Sinks ("well-known flows" in terms of GRR nomenclature) are ever-existing
//! sessions on the GRR server that listen for various kinds of data. They are
//! a way to break away from the usual request-response workflow.
//!
//! For example, sinks can be used to notify the server about agent startup
//! (which is clearly not a response to a particular request) or to transfer
//! file blobs to a specialized storage.

use crate::action;
use crate::session;

/// Handle to a specific sink.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub struct Sink {
    /// An underlying identifier of the sink.
    id: &'static str,
}

impl Sink {

    /// A handle to the sink expecting startup information.
    pub const STARTUP: Sink = Sink { id: "/flows/F:Startup" };

    /// Wraps an action response to a sink-specific session response.
    pub fn wrap<R>(&self, response: R) -> session::Response<R>
    where
        R: action::Response,
    {
        session::Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }
    }
}
<|endoftext|>


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

//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
//! and margins in CSS.

use std::num::{NumCast, Zero};

/// A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
/// and margins in CSS.
#[deriving(Clone, PartialEq)]
pub struct SideOffsets2D<T> {
    pub top: T,
    pub right: T,
    pub bottom: T,
    pub left: T,
}

impl<T> SideOffsets2D<T> {
    pub fn new(top: T, right: T, bottom: T, left: T) -> SideOffsets2D<T> {
        SideOffsets2D {
            top: top,
            right: right,
            bottom: bottom,
            left: left,
        }
    }
}

impl<T:Clone> SideOffsets2D<T> {
    pub fn new_all_same(all: T) -> SideOffsets2D<T> {
        SideOffsets2D::new(all.clone(), all.clone(), all.clone(), all.clone())
    }
}

impl<T:Num> SideOffsets2D<T> {
    pub fn horizontal(&self) -> T {
        self.left + self.right
    }

    pub fn vertical(&self) -> T {
        self.top + self.bottom
    }
}

impl<T:Num> Add<SideOffsets2D<T>, SideOffsets2D<T>> for SideOffsets2D<T> {
    fn add(&self, other: &SideOffsets2D<T>) -> SideOffsets2D<T> {
        SideOffsets2D {
            top: self.top + other.top,
            right: self.right + other.right,
            bottom: self.bottom + other.bottom,
            left: self.left + other.left,
        }
    }
}

impl<T:Num> Zero for SideOffsets2D<T> {
    fn zero() -> SideOffsets2D<T> {
        SideOffsets2D {
            top: Zero::zero(),
            right: Zero::zero(),
            bottom: Zero::zero(),
            left: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.top.is_zero() && self.right.is_zero() && self.bottom.is_zero() && self.left.is_zero()
    }
}

/// A SIMD enabled version of SideOffsets2D specialized for i32.
#[deriving(Clone, PartialEq, Rand)]
#[simd]
pub struct SideOffsets2DSimdI32 {
    pub top: i32,
    pub bottom: i32,
    pub right: i32,
    pub left: i32,
}

impl SideOffsets2DSimdI32 {
    #[inline]
    pub fn new(top: i32, right: i32, bottom: i32, left: i32) -> SideOffsets2DSimdI32 {
        SideOffsets2DSimdI32 {
            top: top,
            bottom: bottom,
            right: right,
            left: left,
        }
    }
}

impl SideOffsets2DSimdI32 {
    #[inline]
    pub fn new_all_same(all: i32) -> SideOffsets2DSimdI32 {
        SideOffsets2DSimdI32::new(all.clone(), all.clone(), all.clone(), all.clone())
    }
}

impl SideOffsets2DSimdI32 {
    #[inline]
    pub fn horizontal(&self) -> i32 {
        self.left + self.right
    }

    #[inline]
    pub fn vertical(&self) -> i32 {
        self.top + self.bottom
    }
}

impl Add<SideOffsets2DSimdI32, SideOffsets2DSimdI32> for SideOffsets2DSimdI32 {
    #[inline]
    fn add(&self, other: &SideOffsets2DSimdI32) -> SideOffsets2DSimdI32 {
        *self + *other // Use SIMD addition
    }
}

impl Zero for SideOffsets2DSimdI32 {
    #[inline]
    fn zero() -> SideOffsets2DSimdI32 {
        SideOffsets2DSimdI32 {
            top: Zero::zero(),
            bottom: Zero::zero(),
            right: Zero::zero(),
            left: Zero::zero(),
        }
    }

    #[cfg(not(target_arch = "x86_64"))]
    #[inline]
    fn is_zero(&self) -> bool {
        self.top.is_zero() && self.right.is_zero() && self.bottom.is_zero() && self.left.is_zero()
    }

    #[cfg(target_arch = "x86_64")]
    #[inline]
    fn is_zero(&self) -> bool {
        let is_zero: bool;
        unsafe {
            asm! {
                "ptest $1, $1
                 setz $0"
                : "=r"(is_zero)
                : "x"(*self)
                :
                : "intel"
            };
        }
        is_zero
    }
}

#[cfg(test)]
mod tests {
    use std::num::Zero;
    use super::SideOffsets2DSimdI32;

    #[test]
    fn test_is_zero() {
        assert!(SideOffsets2DSimdI32::new_all_same(0).is_zero());
        assert!(!SideOffsets2DSimdI32::new_all_same(1).is_zero());
        assert!(!SideOffsets2DSimdI32::new(1, 0, 0, 0).is_zero());
        assert!(!SideOffsets2DSimdI32::new(0, 1, 0, 0).is_zero());
        assert!(!SideOffsets2DSimdI32::new(0, 0, 1, 0).is_zero());
        assert!(!SideOffsets2DSimdI32::new(0, 0, 0, 1).is_zero());
    }
}

#[cfg(bench)]
mod bench {
    use test::BenchHarness;
    use std::num::Zero;
    use rand::{XorShiftRng, Rng};
    use super::SideOffsets2DSimdI32;

    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "x86_64")]
    #[bench]
    fn bench_naive_is_zero(bh: &mut BenchHarness) {
        fn is_zero(x: &SideOffsets2DSimdI32) -> bool {
            x.top.is_zero() && x.right.is_zero() && x.bottom.is_zero() && x.left.is_zero()
        }
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| is_zero(&rng.gen::<SideOffsets2DSimdI32>()))
    }

    #[bench]
    fn bench_is_zero(bh: &mut BenchHarness) {
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| rng.gen::<SideOffsets2DSimdI32>().is_zero())
    }

    #[bench]
    fn bench_naive_add(bh: &mut BenchHarness) {
        fn add(x: &SideOffsets2DSimdI32, y: &SideOffsets2DSimdI32) -> SideOffsets2DSimdI32 {
            SideOffsets2DSimdI32 {
                top: x.top + y.top,
                right: x.right + y.right,
                bottom: x.bottom + y.bottom,
                left: x.left + y.left,
            }
        }
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| add(&rng.gen::<SideOffsets2DSimdI32>(), &rng.gen::<SideOffsets2DSimdI32>()))
    }

    #[bench]
    fn bench_add(bh: &mut BenchHarness) {
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| rng.gen::<SideOffsets2DSimdI32>() + rng.gen::<SideOffsets2DSimdI32>())
    }
}
<commit_msg>Import std::num::Num explicitly.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
//! and margins in CSS.

use std::num::{Num, NumCast, Zero};

/// A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
/// and margins in CSS.
#[deriving(Clone, PartialEq)]
pub struct SideOffsets2D<T> {
    pub top: T,
    pub right: T,
    pub bottom: T,
    pub left: T,
}

impl<T> SideOffsets2D<T> {
    pub fn new(top: T, right: T, bottom: T, left: T) -> SideOffsets2D<T> {
        SideOffsets2D {
            top: top,
            right: right,
            bottom: bottom,
            left: left,
        }
    }
}

impl<T:Clone> SideOffsets2D<T> {
    pub fn new_all_same(all: T) -> SideOffsets2D<T> {
        SideOffsets2D::new(all.clone(), all.clone(), all.clone(), all.clone())
    }
}

impl<T:Num> SideOffsets2D<T> {
    pub fn horizontal(&self) -> T {
        self.left + self.right
    }

    pub fn vertical(&self) -> T {
        self.top + self.bottom
    }
}

impl<T:Num> Add<SideOffsets2D<T>, SideOffsets2D<T>> for SideOffsets2D<T> {
    fn add(&self, other: &SideOffsets2D<T>) -> SideOffsets2D<T> {
        SideOffsets2D {
            top: self.top + other.top,
            right: self.right + other.right,
            bottom: self.bottom + other.bottom,
            left: self.left + other.left,
        }
    }
}

impl<T:Num> Zero for SideOffsets2D<T> {
    fn zero() -> SideOffsets2D<T> {
        SideOffsets2D {
            top: Zero::zero(),
            right: Zero::zero(),
            bottom: Zero::zero(),
            left: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.top.is_zero() && self.right.is_zero() && self.bottom.is_zero() && self.left.is_zero()
    }
}

/// A SIMD enabled version of SideOffsets2D specialized for i32.
#[deriving(Clone, PartialEq, Rand)]
#[simd]
pub struct SideOffsets2DSimdI32 {
    pub top: i32,
    pub bottom: i32,
    pub right: i32,
    pub left: i32,
}

impl SideOffsets2DSimdI32 {
    #[inline]
    pub fn new(top: i32, right: i32, bottom: i32, left: i32) -> SideOffsets2DSimdI32 {
        SideOffsets2DSimdI32 {
            top: top,
            bottom: bottom,
            right: right,
            left: left,
        }
    }
}

impl SideOffsets2DSimdI32 {
    #[inline]
    pub fn new_all_same(all: i32) -> SideOffsets2DSimdI32 {
        SideOffsets2DSimdI32::new(all.clone(), all.clone(), all.clone(), all.clone())
    }
}

impl SideOffsets2DSimdI32 {
    #[inline]
    pub fn horizontal(&self) -> i32 {
        self.left + self.right
    }

    #[inline]
    pub fn vertical(&self) -> i32 {
        self.top + self.bottom
    }
}

impl Add<SideOffsets2DSimdI32, SideOffsets2DSimdI32> for SideOffsets2DSimdI32 {
    #[inline]
    fn add(&self, other: &SideOffsets2DSimdI32) -> SideOffsets2DSimdI32 {
        *self + *other // Use SIMD addition
    }
}

impl Zero for SideOffsets2DSimdI32 {
    #[inline]
    fn zero() -> SideOffsets2DSimdI32 {
        SideOffsets2DSimdI32 {
            top: Zero::zero(),
            bottom: Zero::zero(),
            right: Zero::zero(),
            left: Zero::zero(),
        }
    }

    #[cfg(not(target_arch = "x86_64"))]
    #[inline]
    fn is_zero(&self) -> bool {
        self.top.is_zero() && self.right.is_zero() && self.bottom.is_zero() && self.left.is_zero()
    }

    #[cfg(target_arch = "x86_64")]
    #[inline]
    fn is_zero(&self) -> bool {
        let is_zero: bool;
        unsafe {
            asm! {
                "ptest $1, $1
                 setz $0"
                : "=r"(is_zero)
                : "x"(*self)
                :
                : "intel"
            };
        }
        is_zero
    }
}

#[cfg(test)]
mod tests {
    use std::num::Zero;
    use super::SideOffsets2DSimdI32;

    #[test]
    fn test_is_zero() {
        assert!(SideOffsets2DSimdI32::new_all_same(0).is_zero());
        assert!(!SideOffsets2DSimdI32::new_all_same(1).is_zero());
        assert!(!SideOffsets2DSimdI32::new(1, 0, 0, 0).is_zero());
        assert!(!SideOffsets2DSimdI32::new(0, 1, 0, 0).is_zero());
        assert!(!SideOffsets2DSimdI32::new(0, 0, 1, 0).is_zero());
        assert!(!SideOffsets2DSimdI32::new(0, 0, 0, 1).is_zero());
    }
}

#[cfg(bench)]
mod bench {
    use test::BenchHarness;
    use std::num::Zero;
    use rand::{XorShiftRng, Rng};
    use super::SideOffsets2DSimdI32;

    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "x86_64")]
    #[bench]
    fn bench_naive_is_zero(bh: &mut BenchHarness) {
        fn is_zero(x: &SideOffsets2DSimdI32) -> bool {
            x.top.is_zero() && x.right.is_zero() && x.bottom.is_zero() && x.left.is_zero()
        }
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| is_zero(&rng.gen::<SideOffsets2DSimdI32>()))
    }

    #[bench]
    fn bench_is_zero(bh: &mut BenchHarness) {
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| rng.gen::<SideOffsets2DSimdI32>().is_zero())
    }

    #[bench]
    fn bench_naive_add(bh: &mut BenchHarness) {
        fn add(x: &SideOffsets2DSimdI32, y: &SideOffsets2DSimdI32) -> SideOffsets2DSimdI32 {
            SideOffsets2DSimdI32 {
                top: x.top + y.top,
                right: x.right + y.right,
                bottom: x.bottom + y.bottom,
                left: x.left + y.left,
            }
        }
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| add(&rng.gen::<SideOffsets2DSimdI32>(), &rng.gen::<SideOffsets2DSimdI32>()))
    }

    #[bench]
    fn bench_add(bh: &mut BenchHarness) {
        let mut rng = XorShiftRng::new().unwrap();
        bh.iter(|| rng.gen::<SideOffsets2DSimdI32>() + rng.gen::<SideOffsets2DSimdI32>())
    }
}
<|endoftext|>


<commit_before>
fn add(uint x, uint y) -> uint { ret x + y; }
fn sub(uint x, uint y) -> uint { ret x - y; }
fn mul(uint x, uint y) -> uint { ret x * y; }
fn div(uint x, uint y) -> uint { ret x / y; }
fn rem(uint x, uint y) -> uint { ret x % y; }

fn lt(uint x, uint y) -> bool { ret x < y; }
fn le(uint x, uint y) -> bool { ret x <= y; }
fn eq(uint x, uint y) -> bool { ret x == y; }
fn ne(uint x, uint y) -> bool { ret x != y; }
fn ge(uint x, uint y) -> bool { ret x >= y; }
fn gt(uint x, uint y) -> bool { ret x > y; }

iter range(uint lo, uint hi) -> uint {
    auto lo_ = lo;
    while (lo_ < hi) {
        put lo_;
        lo_ += 1u;
    }
}

fn next_power_of_two(uint n) -> uint {
    // FIXME change |* uint(4)| below to |* uint(8) / uint(2)| and watch the
    // world explode.
    let uint halfbits = sys.rustrt.size_of[uint]() * 4u;
    let uint tmp = n - 1u;
    let uint shift = 1u;
    while (shift <= halfbits) {
        tmp |= tmp >> shift;
        shift <<= 1u;
    }
    ret tmp + 1u;
}

fn parse_buf(vec[u8] buf, uint radix) -> uint {
    auto i = _vec.len[u8](buf) - 1u;
    auto power = 1u;
    auto n = 0u;
    while (true) {
        n += (((buf.(i)) - ('0' as u8)) as uint) * power;
        power *= radix;
        if (i == 0u) { ret n; }
    }
}

fn to_str(uint num, uint radix) -> str
{
    auto n = num;

    check (0u < radix && radix <= 16u);
    fn digit(uint n) -> char {
        alt (n) {
            case (0u) { ret '0'; }
            case (1u) { ret '1'; }
            case (2u) { ret '2'; }
            case (3u) { ret '3'; }
            case (4u) { ret '4'; }
            case (5u) { ret '5'; }
            case (6u) { ret '6'; }
            case (7u) { ret '7'; }
            case (8u) { ret '8'; }
            case (9u) { ret '9'; }
            case (10u) { ret 'a'; }
            case (11u) { ret 'b'; }
            case (12u) { ret 'c'; }
            case (13u) { ret 'd'; }
            case (14u) { ret 'e'; }
            case (15u) { ret 'f'; }
        }
        fail;
    }

    if (n == 0u) { ret "0"; }

    let str s = "";
    while (n != 0u) {
        s += _str.unsafe_from_byte(digit(n % radix) as u8);
        n /= radix;
    }

    let str s1 = "";
    let uint len = _str.byte_len(s);
    while (len != 0u) {
        len -= 1u;
        s1 += _str.unsafe_from_byte(s.(len));
    }
    ret s1;

}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>stdlib: Real fix for _uint.parse_buf().<commit_after>
fn add(uint x, uint y) -> uint { ret x + y; }
fn sub(uint x, uint y) -> uint { ret x - y; }
fn mul(uint x, uint y) -> uint { ret x * y; }
fn div(uint x, uint y) -> uint { ret x / y; }
fn rem(uint x, uint y) -> uint { ret x % y; }

fn lt(uint x, uint y) -> bool { ret x < y; }
fn le(uint x, uint y) -> bool { ret x <= y; }
fn eq(uint x, uint y) -> bool { ret x == y; }
fn ne(uint x, uint y) -> bool { ret x != y; }
fn ge(uint x, uint y) -> bool { ret x >= y; }
fn gt(uint x, uint y) -> bool { ret x > y; }

iter range(uint lo, uint hi) -> uint {
    auto lo_ = lo;
    while (lo_ < hi) {
        put lo_;
        lo_ += 1u;
    }
}

fn next_power_of_two(uint n) -> uint {
    // FIXME change |* uint(4)| below to |* uint(8) / uint(2)| and watch the
    // world explode.
    let uint halfbits = sys.rustrt.size_of[uint]() * 4u;
    let uint tmp = n - 1u;
    let uint shift = 1u;
    while (shift <= halfbits) {
        tmp |= tmp >> shift;
        shift <<= 1u;
    }
    ret tmp + 1u;
}

fn parse_buf(vec[u8] buf, uint radix) -> uint {
    if (_vec.len[u8](buf) == 0u) {
        log_err "parse_buf(): buf is empty";
        fail;
    }

    auto i = _vec.len[u8](buf) - 1u;
    auto power = 1u;
    auto n = 0u;
    while (true) {
        n += (((buf.(i)) - ('0' as u8)) as uint) * power;
        power *= radix;
        if (i == 0u) { ret n; }
        i -= 1u;
    }

    fail;
}

fn to_str(uint num, uint radix) -> str
{
    auto n = num;

    check (0u < radix && radix <= 16u);
    fn digit(uint n) -> char {
        alt (n) {
            case (0u) { ret '0'; }
            case (1u) { ret '1'; }
            case (2u) { ret '2'; }
            case (3u) { ret '3'; }
            case (4u) { ret '4'; }
            case (5u) { ret '5'; }
            case (6u) { ret '6'; }
            case (7u) { ret '7'; }
            case (8u) { ret '8'; }
            case (9u) { ret '9'; }
            case (10u) { ret 'a'; }
            case (11u) { ret 'b'; }
            case (12u) { ret 'c'; }
            case (13u) { ret 'd'; }
            case (14u) { ret 'e'; }
            case (15u) { ret 'f'; }
        }
        fail;
    }

    if (n == 0u) { ret "0"; }

    let str s = "";
    while (n != 0u) {
        s += _str.unsafe_from_byte(digit(n % radix) as u8);
        n /= radix;
    }

    let str s1 = "";
    let uint len = _str.byte_len(s);
    while (len != 0u) {
        len -= 1u;
        s1 += _str.unsafe_from_byte(s.(len));
    }
    ret s1;

}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>import option::none;
import option::some;

// A very naive implementation of union-find with unsigned integer nodes.

type node = option::t[uint];
type ufind = rec(mutable vec[mutable node] nodes);

fn make() -> ufind {
    let vec[mutable node] v = [mutable none[uint]];
    vec::pop(v);  // FIXME: botch
    ret rec(mutable nodes=v);
}

fn make_set(&ufind ufnd) -> uint {
    auto idx = vec::len(ufnd.nodes);
    ufnd.nodes += [mutable none[uint]];
    ret idx;
}

fn find(&ufind ufnd, uint n) -> uint {
    alt (ufnd.nodes.(n)) {
    case (none[uint]) { ret n; }
    case (some[uint](?m)) {
        // TODO: "be"
        ret find(ufnd, m);
    }
    }
}

fn union(&ufind ufnd, uint m, uint n) {
    auto m_root = find(ufnd, m);
    auto n_root = find(ufnd, n);
    auto ptr = some[uint](n_root);
    ufnd.nodes.(m_root) = ptr;
}

<commit_msg>stdlib: Modify union-find to guarantee that root nodes are always less than or equal to leaf nodes; add a "prune" method<commit_after>import option::none;
import option::some;

// A very naive implementation of union-find with unsigned integer nodes.
// Maintains the invariant that the root of a node is always equal to or less
// than the node itself.

type node = option::t[uint];
type ufind = rec(mutable vec[mutable node] nodes);

fn make() -> ufind {
    let vec[mutable node] v = [mutable none[uint]];
    vec::pop(v);  // FIXME: botch
    ret rec(mutable nodes=v);
}

fn make_set(&ufind ufnd) -> uint {
    auto idx = vec::len(ufnd.nodes);
    ufnd.nodes += [mutable none[uint]];
    ret idx;
}

fn find(&ufind ufnd, uint n) -> uint {
    alt (ufnd.nodes.(n)) {
        case (none[uint]) { ret n; }
        case (some[uint](?m)) { be find(ufnd, m); }
    }
}

fn union(&ufind ufnd, uint m, uint n) {
    auto m_root = find(ufnd, m);
    auto n_root = find(ufnd, n);
    if (m_root < n_root) {
        ufnd.nodes.(n_root) = some[uint](m_root);
    } else {
        ufnd.nodes.(m_root) = some[uint](n_root);
    }
}

// Removes all sets with IDs greater than or equal to the given value.
fn prune(&ufind ufnd, uint n) {
    // TODO: Use "slice" once we get rid of "mutable?"
    while (n != 0u) {
        vec::pop[node](ufnd.nodes);
        n -= 1u;
    }
}

<|endoftext|>