<commit_before>use std::env;
use std::io;
use std::path::Path;
use std::process;
use std::str;

use console::strip_ansi_codes;
use failure::{err_msg, Error};
use glob::{glob_with, MatchOptions};
use serde_json;

use utils::releases::{get_xcode_release_name, infer_gradle_release_name};
use utils::xcode::{InfoPlist, XcodeProjectInfo};

static APPCENTER_BIN_PATH: &'static str = "appcenter";
static APPCENTER_NPM_PATH: &'static str = "node_modules/.bin/appcenter";

#[derive(Debug, Deserialize)]
pub struct CodePushPackage {
    pub label: String,
}

#[derive(Debug, Deserialize)]
pub struct CodePushDeployment {
    pub name: String,
    pub package: Option<CodePushPackage>,
}

fn get_codepush_error(output: process::Output) -> Error {
    if let Ok(message) = str::from_utf8(&output.stderr) {
        let stripped = strip_ansi_codes(message);
        err_msg(
            if stripped.starts_with("[Error]  ") {
                &stripped[9..]
            } else if stripped.starts_with("[Error] ") {
                &stripped[8..]
            } else {
                &stripped
            }.to_string(),
        )
    } else {
        err_msg("Unknown Error")
    }
}

pub fn get_codepush_deployments(app: &str) -> Result<Vec<CodePushDeployment>, Error> {
    let appcenter_bin = if Path::new(APPCENTER_NPM_PATH).exists() {
        APPCENTER_NPM_PATH
    } else {
        APPCENTER_BIN_PATH
    };

    let output = process::Command::new(appcenter_bin)
        .arg("codepush")
        .arg("deployment")
        .arg("list")
        .arg("--app")
        .arg(app)
        .arg("--output")
        .arg("json")
        .output()
        .map_err(|e| {
            if e.kind() == io::ErrorKind::NotFound {
                "App Center CLI not found. Is it installed and configured on the PATH?".into()
            } else {
                Error::from(e).context("Failed to run appcenter")
            }
        })?;

    if output.status.success() {
        let raw_data: Vec<Vec<String>> = serde_json::from_slice(&output.stdout)?;

        let mapped: Vec<CodePushDeployment> = raw_data
            .iter()
            .map(|&ref pair| CodePushDeployment {
                name: pair[0].clone(),
                package: if let Some(lbl) = pair.get(1) {
                    Some(CodePushPackage { label: lbl.clone() })
                } else {
                    None
                },
            })
            .collect();

        Ok(mapped)
    } else {
        Err(get_codepush_error(output)
            .context("Failed to get codepush deployments")
            .into())
    }
}

pub fn get_codepush_package(app: &str, deployment: &str) -> Result<CodePushPackage, Error> {
    let deployments = get_codepush_deployments(app)?;
    for dep in deployments {
        if_chain! {
            if &dep.name == deployment;
            if let Some(pkg) = dep.package;
            then {
                return Ok(pkg);
            }
        }
    }

    bail!("Could not find deployment {} for {}", deployment, app)
}

pub fn get_react_native_codepush_release(
    package: &CodePushPackage,
    platform: &str,
    bundle_id_override: Option<&str>,
) -> Result<String, Error> {
    if let Some(bundle_id) = bundle_id_override {
        return Ok(format!("{}-codepush:{}", bundle_id, package.label));
    }

    if platform == "ios" {
        if !cfg!(target_os = "macos") {
            bail!("Codepush releases for iOS require OS X if no bundle ID is specified");
        }
        let mut opts = MatchOptions::new();
        opts.case_sensitive = false;
        for entry_rv in glob_with("ios/*.xcodeproj", &opts)? {
            if let Ok(entry) = entry_rv {
                let pi = XcodeProjectInfo::from_path(&entry)?;
                if let Some(ipl) = InfoPlist::from_project_info(&pi)? {
                    if let Some(release_name) = get_xcode_release_name(Some(ipl))? {
                        return Ok(format!("{}-codepush:{}", release_name, package.label));
                    }
                }
            }
        }
        bail!("Could not find plist");
    } else if platform == "android" {
        if_chain! {
            if let Ok(here) = env::current_dir();
            if let Ok(android_folder) = here.join("android").metadata();
            if android_folder.is_dir();
            then {
                if let Some(release_name) = infer_gradle_release_name(Some(here.join("android")))? {
                    return Ok(format!("{}-codepush:{}", release_name, package.label));
                } else {
                    bail!("Could not parse app id from build.gradle");
                }
            }
        }
        bail!("Could not find AndroidManifest.xml");
    }
    bail!("Unsupported platform '{}'", platform);
}
<commit_msg>fix: Revert switch from codepush to App Center CLI (#325)<commit_after>use std::env;
use std::io;
use std::path::Path;
use std::process;
use std::str;

use console::strip_ansi_codes;
use failure::{err_msg, Error};
use glob::{glob_with, MatchOptions};
use serde_json;

use utils::releases::{get_xcode_release_name, infer_gradle_release_name};
use utils::xcode::{InfoPlist, XcodeProjectInfo};

static CODEPUSH_BIN_PATH: &'static str = "code-push";
static CODEPUSH_NPM_PATH: &'static str = "node_modules/.bin/code-push";

#[derive(Debug, Deserialize)]
pub struct CodePushPackage {
    pub label: String,
}

#[derive(Debug, Deserialize)]
pub struct CodePushDeployment {
    pub name: String,
    pub package: Option<CodePushPackage>,
}

fn get_codepush_error(output: process::Output) -> Error {
    if let Ok(message) = str::from_utf8(&output.stderr) {
        let stripped = strip_ansi_codes(message);
        err_msg(
            if stripped.starts_with("[Error]  ") {
                &stripped[9..]
            } else if stripped.starts_with("[Error] ") {
                &stripped[8..]
            } else {
                &stripped
            }.to_string(),
        )
    } else {
        err_msg("Unknown Error")
    }
}

pub fn get_codepush_deployments(app: &str) -> Result<Vec<CodePushDeployment>, Error> {
    let codepush_bin = if Path::new(CODEPUSH_NPM_PATH).exists() {
        CODEPUSH_NPM_PATH
    } else {
        CODEPUSH_BIN_PATH
    };

    let output = process::Command::new(codepush_bin)
        .arg("deployment")
        .arg("ls")
        .arg(app)
        .arg("--format")
        .arg("json")
        .output()
        .map_err(|e| {
            if e.kind() == io::ErrorKind::NotFound {
                "Codepush not found. Is it installed and configured on the PATH?".into()
            } else {
                Error::from(e).context("Failed to run codepush")
            }
        })?;

    if output.status.success() {
        Ok(serde_json::from_slice(&output.stdout)?)
    } else {
        Err(get_codepush_error(output)
            .context("Failed to get codepush deployments")
            .into())
    }
}

pub fn get_codepush_package(app: &str, deployment: &str) -> Result<CodePushPackage, Error> {
    let deployments = get_codepush_deployments(app)?;
    for dep in deployments {
        if_chain! {
            if &dep.name == deployment;
            if let Some(pkg) = dep.package;
            then {
                return Ok(pkg);
            }
        }
    }

    bail!("Could not find deployment {} for {}", deployment, app)
}

pub fn get_react_native_codepush_release(
    package: &CodePushPackage,
    platform: &str,
    bundle_id_override: Option<&str>,
) -> Result<String, Error> {
    if let Some(bundle_id) = bundle_id_override {
        return Ok(format!("{}-codepush:{}", bundle_id, package.label));
    }

    if platform == "ios" {
        if !cfg!(target_os = "macos") {
            bail!("Codepush releases for iOS require OS X if no bundle ID is specified");
        }
        let mut opts = MatchOptions::new();
        opts.case_sensitive = false;
        for entry_rv in glob_with("ios/*.xcodeproj", &opts)? {
            if let Ok(entry) = entry_rv {
                let pi = XcodeProjectInfo::from_path(&entry)?;
                if let Some(ipl) = InfoPlist::from_project_info(&pi)? {
                    if let Some(release_name) = get_xcode_release_name(Some(ipl))? {
                        return Ok(format!("{}-codepush:{}", release_name, package.label));
                    }
                }
            }
        }
        bail!("Could not find plist");
    } else if platform == "android" {
        if_chain! {
            if let Ok(here) = env::current_dir();
            if let Ok(android_folder) = here.join("android").metadata();
            if android_folder.is_dir();
            then {
                if let Some(release_name) = infer_gradle_release_name(Some(here.join("android")))? {
                    return Ok(format!("{}-codepush:{}", release_name, package.label));
                } else {
                    bail!("Could not parse app id from build.gradle");
                }
            }
        }
        bail!("Could not find AndroidManifest.xml");
    }
    bail!("Unsupported platform '{}'", platform);
}
<|endoftext|>


<commit_before>use webcore::value::Reference;
use webcore::try_from::TryInto;
use webapi::dom_exception::{InvalidCharacterError, InvalidPointerId, NoModificationAllowedError, SyntaxError};
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::node::{INode, Node};
use webapi::token_list::TokenList;
use webapi::parent_node::IParentNode;
use webapi::child_node::IChildNode;
use webcore::try_from::TryFrom;

/// The `IElement` interface represents an object of a [Document](struct.Document.html).
/// This interface describes methods and properties common to all
/// kinds of elements.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
// https://dom.spec.whatwg.org/#element
pub trait IElement: INode + IParentNode + IChildNode {
    /// The Element.classList is a read-only property which returns a live
    /// [TokenList](struct.TokenList.html) collection of the class attributes
    /// of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-classlist
    fn class_list( &self ) -> TokenList {
        unsafe {
            js!( return @{self.as_ref()}.classList; ).into_reference_unchecked().unwrap()
        }
    }

    /// The Element.hasAttribute() method returns a Boolean value indicating whether
    /// the specified element has the specified attribute or not.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-hasattribute
    fn has_attribute( &self, name: &str ) -> bool {
        js!(
            return @{self.as_ref()}.hasAttribute( @{name} );
        ).try_into().unwrap()
    }

    /// Element.getAttribute() returns the value of a specified attribute on the element.
    /// If the given attribute does not exist, the value returned will either be
    /// null or "" (the empty string);
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-getattribute
    fn get_attribute( &self, name: &str ) -> Option< String > {
        js!(
            return @{self.as_ref()}.getAttribute( @{name} );
        ).try_into().unwrap()
    }

    /// Sets the value of an attribute on the specified element. If the attribute already
    /// exists, the value is updated; otherwise a new attribute is added with the
    /// specified name and value.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-setattribute
    fn set_attribute( &self, name: &str, value: &str ) -> Result< (), InvalidCharacterError > {
        js_try!(
            return @{self.as_ref()}.setAttribute( @{name}, @{value} );
        ).unwrap()
    }

    /// Gets the the number of pixels that an element's content is scrolled vertically.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrolltop%E2%91%A0
    fn scroll_top( &self ) -> f64 {
        js!(
            return @{self.as_ref()}.scrollTop;
        ).try_into().unwrap()
    }

    /// Sets the the number of pixels that an element's content is scrolled vertically.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrolltop%E2%91%A0
    fn set_scroll_top( &self, value: f64 ) {
        js! { @(no_return)
            @{self.as_ref()}.scrollTop = @{value};
        }
    }

    /// Gets the the number of pixels that an element's content is scrolled to the left.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrollleft%E2%91%A0
    fn scroll_left( &self ) -> f64 {
        js!(
            return @{self.as_ref()}.scrollLeft;
        ).try_into().unwrap()
    }

    /// Sets the the number of pixels that an element's content is scrolled to the left.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrollleft%E2%91%A0
    fn set_scroll_left( &self, value: f64 ) {
        js! { @(no_return)
            @{self.as_ref()}.scrollLeft = @{value};
        }
    }

    /// Element.getAttributeNames() returns the attribute names of the element
    /// as an Array of strings. If the element has no attributes it returns an empty array.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNames)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-getattributenames
    fn get_attribute_names( &self ) -> Vec<String> {
        js!(
            return @{self.as_ref()}.getAttributeNames();
        ).try_into().unwrap()
    }

    /// Element.removeAttribute removes an attribute from the specified element.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-removeattribute
    fn remove_attribute( &self, name: &str ) {
        js! { @(no_return)
            @{self.as_ref()}.removeAttribute( @{name} );
        }
    }

    /// The Element.hasAttributes() method returns Boolean value, indicating if
    /// the current element has any attributes or not.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttributes)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-hasattributes
    fn has_attributes( &self ) -> bool {
        js!(
            return @{self.as_ref()}.hasAttributes();
        ).try_into().unwrap()
    }

    /// Designates a specific element as the capture target of future pointer events.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture)
    // https://w3c.github.io/pointerevents/#dom-element-setpointercapture
    #[inline]
    fn set_pointer_capture( &self, pointer_id: i32 ) -> Result< (), InvalidPointerId > {
        js_try!(
            return @{self.as_ref()}.setPointerCapture( @{pointer_id} );
        ).unwrap()
    }

    /// Releases pointer capture that was previously set for a specific pointer
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/releasePointerCapture)
    // https://w3c.github.io/pointerevents/#dom-element-releasepointercapture
    #[inline]
    fn release_pointer_capture( &self, pointer_id: i32 ) -> Result< (), InvalidPointerId > {
        js_try!(
            return @{self.as_ref()}.releasePointerCapture( @{pointer_id} );
        ).unwrap()
    }

    /// Returns a boolean indicating if the element has captured the specified pointer
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasPointerCapture)
    // https://w3c.github.io/pointerevents/#dom-element-haspointercapture
    #[inline]
    fn has_pointer_capture( &self, pointer_id: i32 ) -> bool {
        js!( return @{self.as_ref()}.hasPointerCapture( @{pointer_id} ); ).try_into().unwrap()
    }

    /// Insert nodes from HTML fragment into specified position.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-insertadjacentelement
    fn insert_adjacent_html( &self, position: InsertPosition, html: &str ) -> Result<(), InsertAdjacentError> {
        js_try!( @(no_return)
            @{self.as_ref()}.insertAdjacentHTML( @{position.as_str()}, @{html} );
        ).unwrap()
    }

    /// Insert nodes from HTML fragment before element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn insert_html_before( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::BeforeBegin, html)
    }

    /// Insert nodes from HTML fragment as the first children of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn prepend_html( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::AfterBegin, html)
    }

    /// Insert nodes from HTML fragment as the last children of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn append_html( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::BeforeEnd, html)
    }

    /// Insert nodes from HTML fragment after element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn insert_html_after( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::AfterEnd, html)
    }
}

/// A reference to a JavaScript object which implements the [IElement](trait.IElement.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
// https://dom.spec.whatwg.org/#element
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Element")]
#[reference(subclass_of(EventTarget, Node))]
pub struct Element( Reference );

impl IEventTarget for Element {}
impl INode for Element {}
impl IElement for Element {}

impl< T: IElement > IParentNode for T {}
impl< T: IElement > IChildNode for T {}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum InsertPosition {
    /// Insert into the parent directly before the reference element.
    BeforeBegin,
    /// Insert at the start of the reference element.
    AfterBegin,
    /// Insert at the end of the reference element.
    BeforeEnd,
    /// Insert into the parent directly after the reference element.
    AfterEnd,
}

/// Errors thrown by `Element::insert_adjacent_html`.
error_enum_boilerplate! {
    InsertAdjacentError,
    NoModificationAllowedError, SyntaxError
}

impl InsertPosition {
    fn as_str(&self) -> &str {
        match *self {
            InsertPosition::BeforeBegin => "beforebegin",
            InsertPosition::AfterBegin => "afterbegin",
            InsertPosition::BeforeEnd => "beforeend",
            InsertPosition::AfterEnd => "afterend",
        }
    }
}

#[cfg(all(test, feature = "web_test"))]
mod tests {
    use super::*;
    use webapi::document::document;

    #[test]
    fn insert_adjacent_html() {
        let root = document().create_element("div").unwrap();
        let child = document().create_element("span").unwrap();
        child.set_text_content("child");
        root.append_child(&child);

        child.insert_html_before(" <button>before begin</button> foo ").unwrap();
        child.prepend_html("afterbegin").unwrap();
        child.append_html("
 Before end
").unwrap();
        child.insert_html_after("after end ").unwrap();

        let html = js!(return @{root}.innerHTML);
        assert_eq!(html, " <button>before begin</button> foo afterbeginchild
 Before end
after end ");
    }

    #[test]
    fn insert_adjacent_html_empty() {
        let root = document().create_element("div").unwrap();
        root.append_html("").unwrap();

        let html = js!(return @{root}.innerHTML);
        assert_eq!(html, "");
    }

    #[test]
    fn insert_adjacent_html_not_modifiable() {
        let doc = document().document_element().unwrap();
        assert!(match doc.insert_html_before("foobar").unwrap_err() {
            InsertAdjacentError::NoModificationAllowedError(_) => true,
            _ => false,
        });
    }
}
<commit_msg>Fix specs link for `IElement::insert_adjacent_html`<commit_after>use webcore::value::Reference;
use webcore::try_from::TryInto;
use webapi::dom_exception::{InvalidCharacterError, InvalidPointerId, NoModificationAllowedError, SyntaxError};
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::node::{INode, Node};
use webapi::token_list::TokenList;
use webapi::parent_node::IParentNode;
use webapi::child_node::IChildNode;
use webcore::try_from::TryFrom;

/// The `IElement` interface represents an object of a [Document](struct.Document.html).
/// This interface describes methods and properties common to all
/// kinds of elements.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
// https://dom.spec.whatwg.org/#element
pub trait IElement: INode + IParentNode + IChildNode {
    /// The Element.classList is a read-only property which returns a live
    /// [TokenList](struct.TokenList.html) collection of the class attributes
    /// of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-classlist
    fn class_list( &self ) -> TokenList {
        unsafe {
            js!( return @{self.as_ref()}.classList; ).into_reference_unchecked().unwrap()
        }
    }

    /// The Element.hasAttribute() method returns a Boolean value indicating whether
    /// the specified element has the specified attribute or not.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-hasattribute
    fn has_attribute( &self, name: &str ) -> bool {
        js!(
            return @{self.as_ref()}.hasAttribute( @{name} );
        ).try_into().unwrap()
    }

    /// Element.getAttribute() returns the value of a specified attribute on the element.
    /// If the given attribute does not exist, the value returned will either be
    /// null or "" (the empty string);
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-getattribute
    fn get_attribute( &self, name: &str ) -> Option< String > {
        js!(
            return @{self.as_ref()}.getAttribute( @{name} );
        ).try_into().unwrap()
    }

    /// Sets the value of an attribute on the specified element. If the attribute already
    /// exists, the value is updated; otherwise a new attribute is added with the
    /// specified name and value.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-setattribute
    fn set_attribute( &self, name: &str, value: &str ) -> Result< (), InvalidCharacterError > {
        js_try!(
            return @{self.as_ref()}.setAttribute( @{name}, @{value} );
        ).unwrap()
    }

    /// Gets the the number of pixels that an element's content is scrolled vertically.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrolltop%E2%91%A0
    fn scroll_top( &self ) -> f64 {
        js!(
            return @{self.as_ref()}.scrollTop;
        ).try_into().unwrap()
    }

    /// Sets the the number of pixels that an element's content is scrolled vertically.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrolltop%E2%91%A0
    fn set_scroll_top( &self, value: f64 ) {
        js! { @(no_return)
            @{self.as_ref()}.scrollTop = @{value};
        }
    }

    /// Gets the the number of pixels that an element's content is scrolled to the left.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrollleft%E2%91%A0
    fn scroll_left( &self ) -> f64 {
        js!(
            return @{self.as_ref()}.scrollLeft;
        ).try_into().unwrap()
    }

    /// Sets the the number of pixels that an element's content is scrolled to the left.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-element-scrollleft%E2%91%A0
    fn set_scroll_left( &self, value: f64 ) {
        js! { @(no_return)
            @{self.as_ref()}.scrollLeft = @{value};
        }
    }

    /// Element.getAttributeNames() returns the attribute names of the element
    /// as an Array of strings. If the element has no attributes it returns an empty array.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNames)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-getattributenames
    fn get_attribute_names( &self ) -> Vec<String> {
        js!(
            return @{self.as_ref()}.getAttributeNames();
        ).try_into().unwrap()
    }

    /// Element.removeAttribute removes an attribute from the specified element.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-removeattribute
    fn remove_attribute( &self, name: &str ) {
        js! { @(no_return)
            @{self.as_ref()}.removeAttribute( @{name} );
        }
    }

    /// The Element.hasAttributes() method returns Boolean value, indicating if
    /// the current element has any attributes or not.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttributes)
    // https://dom.spec.whatwg.org/#ref-for-dom-element-hasattributes
    fn has_attributes( &self ) -> bool {
        js!(
            return @{self.as_ref()}.hasAttributes();
        ).try_into().unwrap()
    }

    /// Designates a specific element as the capture target of future pointer events.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture)
    // https://w3c.github.io/pointerevents/#dom-element-setpointercapture
    #[inline]
    fn set_pointer_capture( &self, pointer_id: i32 ) -> Result< (), InvalidPointerId > {
        js_try!(
            return @{self.as_ref()}.setPointerCapture( @{pointer_id} );
        ).unwrap()
    }

    /// Releases pointer capture that was previously set for a specific pointer
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/releasePointerCapture)
    // https://w3c.github.io/pointerevents/#dom-element-releasepointercapture
    #[inline]
    fn release_pointer_capture( &self, pointer_id: i32 ) -> Result< (), InvalidPointerId > {
        js_try!(
            return @{self.as_ref()}.releasePointerCapture( @{pointer_id} );
        ).unwrap()
    }

    /// Returns a boolean indicating if the element has captured the specified pointer
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasPointerCapture)
    // https://w3c.github.io/pointerevents/#dom-element-haspointercapture
    #[inline]
    fn has_pointer_capture( &self, pointer_id: i32 ) -> bool {
        js!( return @{self.as_ref()}.hasPointerCapture( @{pointer_id} ); ).try_into().unwrap()
    }

    /// Insert nodes from HTML fragment into specified position.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    // https://w3c.github.io/DOM-Parsing/#widl-Element-insertAdjacentHTML-void-DOMString-position-DOMString-text
    fn insert_adjacent_html( &self, position: InsertPosition, html: &str ) -> Result<(), InsertAdjacentError> {
        js_try!( @(no_return)
            @{self.as_ref()}.insertAdjacentHTML( @{position.as_str()}, @{html} );
        ).unwrap()
    }

    /// Insert nodes from HTML fragment before element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn insert_html_before( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::BeforeBegin, html)
    }

    /// Insert nodes from HTML fragment as the first children of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn prepend_html( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::AfterBegin, html)
    }

    /// Insert nodes from HTML fragment as the last children of the element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn append_html( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::BeforeEnd, html)
    }

    /// Insert nodes from HTML fragment after element.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML)
    fn insert_html_after( &self, html: &str ) -> Result<(), InsertAdjacentError> {
        self.insert_adjacent_html(InsertPosition::AfterEnd, html)
    }
}

/// A reference to a JavaScript object which implements the [IElement](trait.IElement.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Element)
// https://dom.spec.whatwg.org/#element
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Element")]
#[reference(subclass_of(EventTarget, Node))]
pub struct Element( Reference );

impl IEventTarget for Element {}
impl INode for Element {}
impl IElement for Element {}

impl< T: IElement > IParentNode for T {}
impl< T: IElement > IChildNode for T {}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum InsertPosition {
    /// Insert into the parent directly before the reference element.
    BeforeBegin,
    /// Insert at the start of the reference element.
    AfterBegin,
    /// Insert at the end of the reference element.
    BeforeEnd,
    /// Insert into the parent directly after the reference element.
    AfterEnd,
}

/// Errors thrown by `Element::insert_adjacent_html`.
error_enum_boilerplate! {
    InsertAdjacentError,
    NoModificationAllowedError, SyntaxError
}

impl InsertPosition {
    fn as_str(&self) -> &str {
        match *self {
            InsertPosition::BeforeBegin => "beforebegin",
            InsertPosition::AfterBegin => "afterbegin",
            InsertPosition::BeforeEnd => "beforeend",
            InsertPosition::AfterEnd => "afterend",
        }
    }
}

#[cfg(all(test, feature = "web_test"))]
mod tests {
    use super::*;
    use webapi::document::document;

    #[test]
    fn insert_adjacent_html() {
        let root = document().create_element("div").unwrap();
        let child = document().create_element("span").unwrap();
        child.set_text_content("child");
        root.append_child(&child);

        child.insert_html_before(" <button>before begin</button> foo ").unwrap();
        child.prepend_html("afterbegin").unwrap();
        child.append_html("
 Before end
").unwrap();
        child.insert_html_after("after end ").unwrap();

        let html = js!(return @{root}.innerHTML);
        assert_eq!(html, " <button>before begin</button> foo afterbeginchild
 Before end
after end ");
    }

    #[test]
    fn insert_adjacent_html_empty() {
        let root = document().create_element("div").unwrap();
        root.append_html("").unwrap();

        let html = js!(return @{root}.innerHTML);
        assert_eq!(html, "");
    }

    #[test]
    fn insert_adjacent_html_not_modifiable() {
        let doc = document().document_element().unwrap();
        assert!(match doc.insert_html_before("foobar").unwrap_err() {
            InsertAdjacentError::NoModificationAllowedError(_) => true,
            _ => false,
        });
    }
}
<|endoftext|>


<commit_before>use crate::prelude::*;
use winapi::shared::guiddef;

#[cfg(feature = "guid")]
impl Uuid {
    /// Converts a little endian winapi `GUID` into a [`Uuid`]
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn from_guid(guid: guiddef::GUID) -> Self {
        Uuid::from_fields_le(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        )
        .unwrap() // Note: The result in this particular instance is always Ok, so we can
                  //       safely unwrap.
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.to_fields_le();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(feature = "guid")]
#[cfg(test)]
mod tests {
    use super::*;

    use crate::std::string::ToString;
    use winapi::shared::guiddef;

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid).unwrap();
        assert_eq!(
            "9d22354a-2755-304f-8647-9dc54e1ee1e8",
            uuid.to_hyphenated().to_string()
        );
    }

    #[test]
    fn test_guid_roundtrip() {
        let guid_in = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid_in).unwrap();
        let guid_out = uuid.to_guid();

        assert_eq!(
            (guid_in.Data1, guid_in.Data2, guid_in.Data3, guid_in.Data4),
            (
                guid_out.Data1,
                guid_out.Data2,
                guid_out.Data3,
                guid_out.Data4
            )
        );
    }
}
<commit_msg>fix test<commit_after>use crate::prelude::*;
use winapi::shared::guiddef;

#[cfg(feature = "guid")]
impl Uuid {
    /// Converts a little endian winapi `GUID` into a [`Uuid`]
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn from_guid(guid: guiddef::GUID) -> Self {
        Uuid::from_fields_le(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        )
        .unwrap() // Note: The result in this particular instance is always Ok, so we can
                  //       safely unwrap.
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.to_fields_le();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(feature = "guid")]
#[cfg(test)]
mod tests {
    use super::*;

    use crate::std::string::ToString;
    use winapi::shared::guiddef;

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid);
        assert_eq!(
            "9d22354a-2755-304f-8647-9dc54e1ee1e8",
            uuid.to_hyphenated().to_string()
        );
    }

    #[test]
    fn test_guid_roundtrip() {
        let guid_in = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid_in).unwrap();
        let guid_out = uuid.to_guid();

        assert_eq!(
            (guid_in.Data1, guid_in.Data2, guid_in.Data3, guid_in.Data4),
            (
                guid_out.Data1,
                guid_out.Data2,
                guid_out.Data3,
                guid_out.Data4
            )
        );
    }
}
<|endoftext|>


<commit_before>use std::net::TcpStream;
use std::io;
use std::io::prelude::*;
use std::thread;
use std::str;

const COMMAND_BUF_SIZE: usize = 4096;

struct IrcMessage {
	msg: [u8; COMMAND_BUF_SIZE],
	length: usize,
}

struct IrcReader {
	stream: TcpStream,

}

impl IrcReader {
	pub fn new(base_stream: &TcpStream) -> std::io::Result<IrcReader> {
		let stream = try!(base_stream.try_clone());
		Ok(IrcReader {
			stream: stream,
		})
	}
}

impl Iterator for IrcReader {
	type Item = IrcMessage;
	fn next(&mut self) -> Option<IrcMessage> {
		let mut command_buf: [u8; COMMAND_BUF_SIZE] = [0; COMMAND_BUF_SIZE];
		let mut buf_ind = 0;
		let mut command_end = false;
		let stream = &self.stream;
		let bytes = stream.bytes();
		for x in bytes {
			if x.is_err() {
				return None;
			}
			let next_char = x.unwrap();
			command_buf[buf_ind] = next_char;
			buf_ind = buf_ind + 1;
			if command_end && next_char == 10 {
				return Some(IrcMessage { msg: command_buf, length: buf_ind - 2 });
			} else if next_char == 102 {
				command_end = true;
			} else {
				command_end = false;
			}

			if buf_ind >= COMMAND_BUF_SIZE {
				buf_ind = 0;
			}
		}
		None
	}
}

struct IrcWriter {
	stream: TcpStream,
}

impl IrcWriter {
	pub fn new(base_stream: &TcpStream) -> std::io::Result<IrcWriter> {
		let stream = try!(base_stream.try_clone());
		Ok(IrcWriter {
			stream: stream,
		})
	}

	pub fn write(&mut self, bytes: &[u8]) {
		let _ = &self.stream.write(&bytes);
	}
}

fn main() {
	let connection_result = TcpStream::connect("127.0.0.1:6667");
	if connection_result.is_err() {
		return;
	}

	let connection = connection_result.unwrap();
	let reader = IrcReader::new(&connection).unwrap();
	let mut writer = IrcWriter::new(&connection).unwrap();

	thread::spawn(move || {
		let mut stdin = io::stdin();
		let mut buf = String::new();
		loop {
			let _= stdin.read_line(&mut buf).unwrap();
			writer.write(&buf.as_bytes());
		}
	});

	for irc_msg in reader {
		parse_command(&irc_msg.msg[0..irc_msg.length]);
	}
}

fn parse_command(command: &[u8]) {
	let command_str = str::from_utf8(command);
	if command_str.is_err() {
		return;
	}
	println!("{}", command_str.unwrap());
}
<commit_msg>Switch to parsing crlf<commit_after>use std::net::TcpStream;
use std::io;
use std::io::prelude::*;
use std::thread;
use std::str;

const COMMAND_BUF_SIZE: usize = 4096;

struct IrcMessage {
	msg: [u8; COMMAND_BUF_SIZE],
	length: usize,
}

struct IrcReader {
	stream: TcpStream,

}

impl IrcReader {
	pub fn new(base_stream: &TcpStream) -> std::io::Result<IrcReader> {
		let stream = try!(base_stream.try_clone());
		Ok(IrcReader {
			stream: stream,
		})
	}
}

impl Iterator for IrcReader {
	type Item = IrcMessage;
	fn next(&mut self) -> Option<IrcMessage> {
		let mut command_buf: [u8; COMMAND_BUF_SIZE] = [0; COMMAND_BUF_SIZE];
		let mut buf_ind = 0;
		let mut command_end = false;
		let stream = &self.stream;
		let bytes = stream.bytes();
		for x in bytes {
			if x.is_err() {
				return None;
			}
			let next_char = x.unwrap();
			command_buf[buf_ind] = next_char;
			buf_ind = buf_ind + 1;
			if command_end && next_char == 10 {
				return Some(IrcMessage { msg: command_buf, length: buf_ind - 2 });
			} else if next_char == 13 {
				command_end = true;
			} else {
				command_end = false;
			}

			if buf_ind >= COMMAND_BUF_SIZE {
				buf_ind = 0;
			}
		}
		None
	}
}

struct IrcWriter {
	stream: TcpStream,
}

impl IrcWriter {
	pub fn new(base_stream: &TcpStream) -> std::io::Result<IrcWriter> {
		let stream = try!(base_stream.try_clone());
		Ok(IrcWriter {
			stream: stream,
		})
	}

	pub fn write(&mut self, bytes: &[u8]) {
		let _ = &self.stream.write(&bytes);
	}
}

fn main() {
	let connection_result = TcpStream::connect("127.0.0.1:6667");
	if connection_result.is_err() {
		return;
	}

	let connection = connection_result.unwrap();
	let reader = IrcReader::new(&connection).unwrap();
	let mut writer = IrcWriter::new(&connection).unwrap();

	thread::spawn(move || {
		let mut stdin = io::stdin();
		let mut buf = String::new();
		loop {
			let _= stdin.read_line(&mut buf).unwrap();
			writer.write(&buf.as_bytes());
		}
	});

	for irc_msg in reader {
		parse_command(&irc_msg.msg[0..irc_msg.length]);
	}
}

fn parse_command(command: &[u8]) {
	let command_str = str::from_utf8(command);
	if command_str.is_err() {
		return;
	}
	println!("{}", command_str.unwrap());
}
<|endoftext|>


<commit_before>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use sdl2::mouse::Mouse;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    (gl::VERTEX_SHADER, vertex_shader),
    (gl::FRAGMENT_SHADER, fragment_shader),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, btn, x, y) => {
        let y = WINDOW_HEIGHT as i32 - y;
        match btn {
          Mouse::Left => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.low_x += (x as f64) * mdlbt.width / ww;
            mdlbt.low_y += (y as f64) * mdlbt.height / wh;
            mdlbt.width /= ww;
            mdlbt.height /= wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          },
          Mouse::Right => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.width *= ww;
            mdlbt.height *= wh;
            mdlbt.low_x -= (x as f64) * mdlbt.width / ww;
            mdlbt.low_y -= (y as f64) * mdlbt.height / wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          }
          _ => {},
        };
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          match key {
            KeyCode::Up => {
              mdlbt.max_iter *= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            KeyCode::Down => {
              mdlbt.max_iter /= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            _ => {},
          }
        }
      },
      _ => {},
    }
  }
}
<commit_msg>Make the scaling square.<commit_after>use gl;
use mandelbrot::Mandelbrot;
use std::io::timer;
use std::mem;
use std::time::duration::Duration;
use sdl2;
use sdl2::event::Event;
use sdl2::keycode::KeyCode;
use sdl2::mouse::Mouse;
use stopwatch::TimerSet;
use yaglw::gl_context::{GLContext, GLContextExistence};
use yaglw::shader::Shader;
use yaglw::vertex_buffer::{GLArray, GLBuffer, GLType, VertexAttribData, DrawMode};

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 800;

#[repr(C)]
pub struct RGB {
  pub r: f32,
  pub g: f32,
  pub b: f32,
}

pub fn main() {
  let timers = TimerSet::new();

  let window = make_window();

  let _sdl_gl_context = window.gl_create_context().unwrap();

  // Load the OpenGL function pointers.
  gl::load_with(|s| unsafe {
    mem::transmute(sdl2::video::gl_get_proc_address(s))
  });

  let (gl, mut gl_context) = unsafe {
    GLContext::new()
  };

  match gl_context.get_error() {
    gl::NO_ERROR => {},
    err => {
      println!("OpenGL error 0x{:x} in setup", err);
      return;
    },
  }

  let shader = make_shader(&gl);
  shader.use_shader(&mut gl_context);

  let mut vao = make_vao(&gl, &mut gl_context, &shader);
  vao.bind(&mut gl_context);

  let mut mdlbt =
    Mandelbrot {
      low_x: -2.0,
      low_y: -2.0,
      width: 4.0,
      height: 4.0,
      max_iter: 128,
    };

  timers.time("update", || {
    vao.push(&mut gl_context, mdlbt.render().as_slice());
  });

  while process_events(&timers, &mut gl_context, &mut mdlbt, &mut vao) {
    timers.time("draw", || {
      gl_context.clear_buffer();
      vao.draw(&mut gl_context);
      // swap buffers
      window.gl_swap_window();
    });

    timer::sleep(Duration::milliseconds(10));
  }

  timers.print();
}

fn make_shader<'a>(
  gl: &'a GLContextExistence,
) -> Shader<'a> {
  let vertex_shader: String = format!("
    #version 330 core

    const int W = {};
    const int H = {};

    in vec3 color;
    out vec4 v_color;

    void main() {{
      v_color = vec4(color, 1);
      gl_Position =
        vec4(
          float(gl_VertexID % W) / W * 2 - 1,
          float(gl_VertexID / W) / H * 2 - 1,
          0, 1
        );
    }}
  ", WINDOW_WIDTH, WINDOW_HEIGHT);

  let fragment_shader: String = "
    #version 330 core

    in vec4 v_color;

    void main() {
      gl_FragColor = v_color;
    }
  ".to_string();

  let components = vec!(
    (gl::VERTEX_SHADER, vertex_shader),
    (gl::FRAGMENT_SHADER, fragment_shader),
  );

  Shader::new(gl, components.into_iter())
}

fn make_window() -> sdl2::video::Window {
  sdl2::init(sdl2::INIT_EVERYTHING);

  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMajorVersion, 3);
  sdl2::video::gl_set_attribute(sdl2::video::GLAttr::GLContextMinorVersion, 3);
  sdl2::video::gl_set_attribute(
    sdl2::video::GLAttr::GLContextProfileMask,
    sdl2::video::GLProfile::GLCoreProfile as isize
  );

  let window = sdl2::video::Window::new(
    "OpenCL",
    sdl2::video::WindowPos::PosCentered,
    sdl2::video::WindowPos::PosCentered,
    WINDOW_WIDTH as isize,
    WINDOW_HEIGHT as isize,
    sdl2::video::OPENGL,
  ).unwrap();

  window
}

fn make_vao<'a>(
  gl: &'a GLContextExistence,
  gl_context: &mut GLContext,
  shader: &Shader<'a>,
) -> GLArray<'a, RGB> {
  let attribs = [
    VertexAttribData {
      name: "color",
      size: 3,
      unit: GLType::Float,
    },
  ];

  let capacity = WINDOW_WIDTH as usize * WINDOW_HEIGHT as usize;
  let vbo = GLBuffer::new(gl, gl_context, capacity);

  GLArray::new(
    gl,
    gl_context,
    shader,
    &attribs,
    DrawMode::Points,
    vbo,
  )
}

fn process_events<'a>(
  timers: &TimerSet,
  gl: &mut GLContext,
  mdlbt: &mut Mandelbrot,
  vao: &mut GLArray<'a, RGB>,
) -> bool {
  loop {
    match sdl2::event::poll_event() {
      Event::None => {
        return true;
      },
      Event::Quit(_) => {
        return false;
      },
      Event::AppTerminating(_) => {
        return false;
      },
      Event::MouseButtonDown(_, _, _, btn, x, y) => {
        let y = WINDOW_HEIGHT as i32 - y;
        match btn {
          Mouse::Left => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.low_x += (x as f64) * mdlbt.width / ww;
            mdlbt.low_y += (y as f64) * mdlbt.height / wh;
            mdlbt.width /= ww;
            mdlbt.height /= wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          },
          Mouse::Right => {
            let ww = WINDOW_WIDTH as f64;
            let wh = WINDOW_HEIGHT as f64;
            mdlbt.width *= ww;
            mdlbt.height *= wh;
            mdlbt.low_x -= (x as f64) * mdlbt.width / ww;
            mdlbt.low_y -= (y as f64) * mdlbt.height / wh;

            timers.time("update", || {
              vao.buffer.update(gl, 0, mdlbt.render().as_slice());
            });
          }
          _ => {},
        };
      },
      Event::KeyDown(_, _, key, _, _, repeat) => {
        if !repeat {
          match key {
            KeyCode::Up => {
              mdlbt.max_iter *= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            KeyCode::Down => {
              mdlbt.max_iter /= 2;

              timers.time("update", || {
                vao.buffer.update(gl, 0, mdlbt.render().as_slice());
              });
            },
            _ => {},
          }
        }
      },
      _ => {},
    }
  }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(needless_return))]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::raw::c_void;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

unsafe fn allow_syscall(ctx : *mut c_void, nr : u32) {
    assert_eq!(seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, nr as i32, 0, std::ptr::null()), 0);
}

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx.is_null());
        allow_syscall(ctx, __NR_execve);
        allow_syscall(ctx, __NR_brk);
        allow_syscall(ctx, __NR_access);
        allow_syscall(ctx, __NR_mmap);
        allow_syscall(ctx, __NR_open);
        allow_syscall(ctx, __NR_read);
        allow_syscall(ctx, __NR_write);
        allow_syscall(ctx, __NR_stat);
        allow_syscall(ctx, __NR_fstat);
        allow_syscall(ctx, __NR_close);
        allow_syscall(ctx, __NR_mprotect);
        allow_syscall(ctx, __NR_arch_prctl);
        allow_syscall(ctx, __NR_munmap);
        allow_syscall(ctx, __NR_set_tid_address);
        allow_syscall(ctx, __NR_set_robust_list);
        allow_syscall(ctx, __NR_rt_sigaction);
        allow_syscall(ctx, __NR_rt_sigprocmask);
        allow_syscall(ctx, __NR_getrlimit);
        allow_syscall(ctx, __NR_statfs);
        allow_syscall(ctx, __NR_fcntl);
        allow_syscall(ctx, __NR_geteuid);
        allow_syscall(ctx, __NR_umask);
        allow_syscall(ctx, __NR_pipe);
        allow_syscall(ctx, __NR_clone);
        allow_syscall(ctx, __NR_wait4);
        allow_syscall(ctx, __NR_exit_group);
        allow_syscall(ctx, __NR_dup);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIOCLEX, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIONBIO, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TCGETS, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TIOCGWINSZ, datum_b: 0,
        }), 0);
        allow_syscall(ctx, __NR_getpid);
        allow_syscall(ctx, __NR_gettid);
        allow_syscall(ctx, __NR_tgkill);
        allow_syscall(ctx, __NR_rt_sigreturn);
        allow_syscall(ctx, __NR_socket);
        allow_syscall(ctx, __NR_connect);
        allow_syscall(ctx, __NR_lseek);
        allow_syscall(ctx, __NR_openat);
        allow_syscall(ctx, __NR_unlinkat);
        allow_syscall(ctx, __NR_utimensat);
        allow_syscall(ctx, __NR_lstat);
        allow_syscall(ctx, __NR_fchmod);
        allow_syscall(ctx, __NR_unlink);
        allow_syscall(ctx, __NR_utime);
        allow_syscall(ctx, __NR_futex);
        allow_syscall(ctx, __NR_chmod);
        allow_syscall(ctx, __NR_getuid);
        allow_syscall(ctx, __NR_getgid);
        allow_syscall(ctx, __NR_getppid);
        allow_syscall(ctx, __NR_getcwd);
        allow_syscall(ctx, __NR_getegid);
        allow_syscall(ctx, __NR_getdents);
        allow_syscall(ctx, __NR_readlink);
        allow_syscall(ctx, __NR_mkdirat);
        allow_syscall(ctx, __NR_mkdir);
        allow_syscall(ctx, __NR_madvise);
        allow_syscall(ctx, __NR_exit);
        assert_eq!(seccomp_load(ctx), 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn path_to_cstring(path : &Path) -> CString {
    return CString::new(path.as_os_str().as_bytes()).unwrap();
}

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, path_to_cstring(path0).as_ptr(), libc::AT_FDCWD, path_to_cstring(path1).as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".part1.rar",
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".7z",
            ],
            extract_cmd: vec!["7z", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        let arch_bytes = arch.as_os_str().as_bytes();
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                let ext_bytes = ext.as_bytes();
                if !arch_bytes.ends_with(ext_bytes) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch_bytes[0..arch_bytes.len()-ext_bytes.len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(fs::canonicalize(&arch).expect("Unable to find archive"))
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        let newname = rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                    } else {
                        let newname = rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<commit_msg>Allow more syscalls for tar and PAM<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(needless_return))]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::raw::c_void;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

unsafe fn allow_syscall(ctx : *mut c_void, nr : u32) {
    assert_eq!(seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, nr as i32, 0, std::ptr::null()), 0);
}

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx.is_null());
        allow_syscall(ctx, __NR_execve);
        allow_syscall(ctx, __NR_brk);
        allow_syscall(ctx, __NR_access);
        allow_syscall(ctx, __NR_mmap);
        allow_syscall(ctx, __NR_open);
        allow_syscall(ctx, __NR_read);
        allow_syscall(ctx, __NR_write);
        allow_syscall(ctx, __NR_stat);
        allow_syscall(ctx, __NR_fstat);
        allow_syscall(ctx, __NR_close);
        allow_syscall(ctx, __NR_mprotect);
        allow_syscall(ctx, __NR_arch_prctl);
        allow_syscall(ctx, __NR_munmap);
        allow_syscall(ctx, __NR_set_tid_address);
        allow_syscall(ctx, __NR_set_robust_list);
        allow_syscall(ctx, __NR_rt_sigaction);
        allow_syscall(ctx, __NR_rt_sigprocmask);
        allow_syscall(ctx, __NR_getrlimit);
        allow_syscall(ctx, __NR_statfs);
        allow_syscall(ctx, __NR_fcntl);
        allow_syscall(ctx, __NR_geteuid);
        allow_syscall(ctx, __NR_umask);
        allow_syscall(ctx, __NR_pipe);
        allow_syscall(ctx, __NR_clone);
        allow_syscall(ctx, __NR_wait4);
        allow_syscall(ctx, __NR_exit_group);
        allow_syscall(ctx, __NR_dup);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIOCLEX, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::FIONBIO, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TCGETS, datum_b: 0,
        }), 0);
        assert_eq!(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, __NR_ioctl as i32, 1, scmp_arg_cmp {
            arg: 1, op: scmp_compare::SCMP_CMP_EQ, datum_a: libc::TIOCGWINSZ, datum_b: 0,
        }), 0);
        allow_syscall(ctx, __NR_getpid);
        allow_syscall(ctx, __NR_gettid);
        allow_syscall(ctx, __NR_tgkill);
        allow_syscall(ctx, __NR_rt_sigreturn);
        allow_syscall(ctx, __NR_socket);
        allow_syscall(ctx, __NR_connect);
        allow_syscall(ctx, __NR_sendto);
        allow_syscall(ctx, __NR_poll);
        allow_syscall(ctx, __NR_recvmsg);
        allow_syscall(ctx, __NR_lseek);
        allow_syscall(ctx, __NR_openat);
        allow_syscall(ctx, __NR_unlinkat);
        allow_syscall(ctx, __NR_utimensat);
        allow_syscall(ctx, __NR_lstat);
        allow_syscall(ctx, __NR_fchmod);
        allow_syscall(ctx, __NR_unlink);
        allow_syscall(ctx, __NR_utime);
        allow_syscall(ctx, __NR_futex);
        allow_syscall(ctx, __NR_chmod);
        allow_syscall(ctx, __NR_getuid);
        allow_syscall(ctx, __NR_getgid);
        allow_syscall(ctx, __NR_getppid);
        allow_syscall(ctx, __NR_getcwd);
        allow_syscall(ctx, __NR_getegid);
        allow_syscall(ctx, __NR_getdents);
        allow_syscall(ctx, __NR_readlink);
        allow_syscall(ctx, __NR_mkdirat);
        allow_syscall(ctx, __NR_mkdir);
        allow_syscall(ctx, __NR_madvise);
        allow_syscall(ctx, __NR_exit);
        assert_eq!(seccomp_load(ctx), 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn path_to_cstring(path : &Path) -> CString {
    return CString::new(path.as_os_str().as_bytes()).unwrap();
}

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, path_to_cstring(path0).as_ptr(), libc::AT_FDCWD, path_to_cstring(path1).as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".part1.rar",
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".7z",
            ],
            extract_cmd: vec!["7z", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        let arch_bytes = arch.as_os_str().as_bytes();
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                let ext_bytes = ext.as_bytes();
                if !arch_bytes.ends_with(ext_bytes) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch_bytes[0..arch_bytes.len()-ext_bytes.len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(fs::canonicalize(&arch).expect("Unable to find archive"))
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        let newname = rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                    } else {
                        let newname = rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Oliver Bone
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate getopts;

use getopts::Options;
use std::env;
use std::iter::FromIterator;
use std::io::prelude::*;
use std::io::BufStream;
use std::io::Error as IoError;
use std::str::FromStr;
use std::net::TcpStream;

static DEFAULT_PORT_NUMBER: u16 = 6667;

fn main() {
    let mut opts = Options::new();
    opts.optopt("s", "server", "Address", "ADDRESS");
    opts.optopt("p", "port", "Port", "PORT");

    let args = Vec::from_iter(env::args());
    let program = args[0].clone();

    let matches = match opts.parse(args) {
        Ok(m) => { m }
        Err(e) => {
            println!("Invalid address: {}", e);
            return usage(&program[..], opts);
        }
    };

    let hostname = match matches.opt_str("s") {
        Some(a) => { a }
        None => { return usage(&program[..], opts); }
    };

    let port = if let Some(p) = matches.opt_str("p") {
        match u16::from_str(&p[..]) {
            Ok(p) => { p }
            Err(e) => {
                println!("Invalid port: {}", e);
                return usage(&program[..], opts);
            }
        }
    }
    else {
        DEFAULT_PORT_NUMBER
    };

    println!("Connecting to {}:{}...", hostname, port);

    match connect(&hostname[..], port) {
        Ok(stream) => {
            println!("Connected.");

            for line in stream.lines() {
                match line {
                    Ok(line) => {
                        println!("{}", line);
                    }
                    Err(e) => {
                        println!("Read error: {}", e);
                        break;
                    }
                }
            }
        }
        Err(e) => {
            println!("{}", e);
            println!("Failed to connect!");
        }
    }
}

fn usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn connect(hostname: &str, port: u16) -> Result<BufStream<TcpStream>, IoError> {
    let address = format!("{}:{}", hostname, port);

    match TcpStream::connect(&address[..]) {
        Ok(stream) => { return Ok(BufStream::new(stream)); }
        Err(e) => { return Err(e); }
    };
}
<commit_msg>Use try! rather than match.<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Oliver Bone
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate getopts;

use getopts::Options;
use std::env;
use std::iter::FromIterator;
use std::io::prelude::*;
use std::io::BufStream;
use std::io::Error as IoError;
use std::str::FromStr;
use std::net::TcpStream;

static DEFAULT_PORT_NUMBER: u16 = 6667;

fn main() {
    let mut opts = Options::new();
    opts.optopt("s", "server", "Address", "ADDRESS");
    opts.optopt("p", "port", "Port", "PORT");

    let args = Vec::from_iter(env::args());
    let program = args[0].clone();

    let matches = match opts.parse(args) {
        Ok(m) => { m }
        Err(e) => {
            println!("Invalid address: {}", e);
            return usage(&program[..], opts);
        }
    };

    let hostname = match matches.opt_str("s") {
        Some(a) => { a }
        None => { return usage(&program[..], opts); }
    };

    let port = if let Some(p) = matches.opt_str("p") {
        match u16::from_str(&p[..]) {
            Ok(p) => { p }
            Err(e) => {
                println!("Invalid port: {}", e);
                return usage(&program[..], opts);
            }
        }
    }
    else {
        DEFAULT_PORT_NUMBER
    };

    println!("Connecting to {}:{}...", hostname, port);

    match connect(&hostname[..], port) {
        Ok(stream) => {
            println!("Connected.");

            for line in stream.lines() {
                match line {
                    Ok(line) => {
                        println!("{}", line);
                    }
                    Err(e) => {
                        println!("Read error: {}", e);
                        break;
                    }
                }
            }
        }
        Err(e) => {
            println!("Failed to connect: {}!", e);
        }
    }
}

fn usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn connect(hostname: &str, port: u16) -> Result<BufStream<TcpStream>, IoError> {
    let address = format!("{}:{}", hostname, port);
    let tcp_stream = try!(TcpStream::connect(&address[..]));
    return Ok(BufStream::new(tcp_stream));
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: AGPL-3.0-only

extern crate staticfile;
extern crate mount;
extern crate chrono;
extern crate serde;
extern crate iron;
extern crate router;
extern crate urlencoded;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate serde_json;
extern crate rand;

#[macro_use]
extern crate include_repo;

use std::path::Path;

use rand::Rng;
use chrono::prelude::*;
use iron::prelude::*;
use iron::status;
use iron::headers;
use iron::mime;
use router::Router;
use urlencoded::UrlEncodedQuery;
use staticfile::Static;

lazy_static! {
    static ref BIRTHDAY: chrono::Date<Utc> = Utc.ymd(1953, 3, 16);
    static ref IMAGES: Vec<String> = images();
    static ref IMAGE_JSON: String = serde_json::to_string(&*IMAGES).unwrap();
}

struct RMS404Handler;

impl iron::middleware::AfterMiddleware for RMS404Handler {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
	// 404 image
	match err.response.status {
	    Some(status::NotFound) => {
		Ok(Response::with((status::NotFound, Path::new("./static/404.jpg"))))
	    },
	    _ => Err(err),
	}
    }
}

fn main() {
    // Lazy static, make sure they don't panic
    let _ = &*BIRTHDAY;
    let _ = &*IMAGE_JSON;

    let s = Static::new(Path::new("./static/"));

    let mut router = Router::new();
    router.any("/code.tar.gz", source_code, "source code");
    router.any("/index.php", index, "backwards-compat-index");
    router.any("/", index, "index");
    router.any("/*", s, "static");

    let mut chain = iron::middleware::Chain::new(router);
    chain.link_after(RMS404Handler);

    let _server = Iron::new(chain)
	.http("0.0.0.0:3000").unwrap();
    println!("Listening on 3000");
}

// AGPL compliance. We exclude the images to avoid increasing build and download size too much;
// people can easily enough download them from the repo or via checking the image json regardless.
include_repo_gz!(SOURCE_CODE, ".", ":!**/*.jpg", ":!**/*.JPG", ":!**/*.png");

fn source_code(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((headers::ContentType(mime::Mime(mime::TopLevel::Application, mime::SubLevel::Ext("gzip".to_string()), vec![])).0, status::Ok, &SOURCE_CODE[..])))
}

fn index(req: &mut Request) -> IronResult<Response> {
    let js_enabled = match req.get_ref::<UrlEncodedQuery>() {
	Ok(query) => {
	    if query.contains_key("images") {
		return list_images()
	    }
	    query.contains_key("js")
	}
	Err(e) => {
	    warn!("Could not decode query: {}", e);
	    false
	}
    };
    let now = Utc::now();
    let title = if BIRTHDAY.month() == now.month() && BIRTHDAY.day() == now.day() {
	"Happy GNU/Birthday"
    } else {
	"Our GNU/Lord and GNU/Savior is 100% sexy!"
    };

let resp = format!(r#"<!DOCTYPE html>

		<meta charset="utf-8">
		<title>{}</title>
		{}
		<link rel="stylesheet" href="/style.css">
		<link rel="license" href="/license.txt">

"#,
title,
if js_enabled { "" } else { r#"<meta http-equiv="refresh" content="3;/">"# },
random_image());
    Ok(Response::with(
	(headers::ContentType::html().0, status::Ok, resp)
    ))
}

fn list_images() -> IronResult<Response> {
    Ok(Response::with(
	    (headers::ContentType::json().0, status::Ok, &*IMAGE_JSON.clone())
    ))
}

fn random_image() -> &'static str {
    rand::thread_rng().choose(&IMAGES)
	.unwrap()
}

fn images() -> Vec<String> {
    let imgs = std::fs::read_dir("./static/img").expect("could  not read img dir");

    imgs.filter_map(|entry| {
	let entry = entry.expect("error reading item");
	match entry.file_type().expect("file type") {
	    t if t.is_file() => {
		// Images can be found relative to '/' in the api, so prefix their relative paths
		// with '/' here.
		Some("/".to_string() + entry.path().strip_prefix("./static/").unwrap().to_str().unwrap())
	    },
	    _=> {
		None
	    }
	}
    }).collect()
}

<commit_msg>Add healthz endpoint<commit_after>// SPDX-License-Identifier: AGPL-3.0-only

extern crate staticfile;
extern crate mount;
extern crate chrono;
extern crate serde;
extern crate iron;
extern crate router;
extern crate urlencoded;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate serde_json;
extern crate rand;

#[macro_use]
extern crate include_repo;

use std::path::Path;

use rand::Rng;
use chrono::prelude::*;
use iron::prelude::*;
use iron::status;
use iron::headers;
use iron::mime;
use router::Router;
use urlencoded::UrlEncodedQuery;
use staticfile::Static;

lazy_static! {
    static ref BIRTHDAY: chrono::Date<Utc> = Utc.ymd(1953, 3, 16);
    static ref IMAGES: Vec<String> = images();
    static ref IMAGE_JSON: String = serde_json::to_string(&*IMAGES).unwrap();
}

struct RMS404Handler;

impl iron::middleware::AfterMiddleware for RMS404Handler {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
	// 404 image
	match err.response.status {
	    Some(status::NotFound) => {
		Ok(Response::with((status::NotFound, Path::new("./static/404.jpg"))))
	    },
	    _ => Err(err),
	}
    }
}

fn main() {
    // Lazy static, make sure they don't panic
    let _ = &*BIRTHDAY;
    let _ = &*IMAGE_JSON;

    let s = Static::new(Path::new("./static/"));

    let mut router = Router::new();
    router.any("/code.tar.gz", source_code, "source code");
    router.any("/index.php", index, "backwards-compat-index");
    router.any("/", index, "index");
    router.any("/*", s, "static");
    router.get("/healthz", healthz, "healthz");

    let mut chain = iron::middleware::Chain::new(router);
    chain.link_after(RMS404Handler);

    let _server = Iron::new(chain)
	.http("0.0.0.0:3000").unwrap();
    println!("Listening on 3000");
}

// AGPL compliance. We exclude the images to avoid increasing build and download size too much;
// people can easily enough download them from the repo or via checking the image json regardless.
include_repo_gz!(SOURCE_CODE, ".", ":!**/*.jpg", ":!**/*.JPG", ":!**/*.png");

fn source_code(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((headers::ContentType(mime::Mime(mime::TopLevel::Application, mime::SubLevel::Ext("gzip".to_string()), vec![])).0, status::Ok, &SOURCE_CODE[..])))
}

fn healthz(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "healthy")))
}

fn index(req: &mut Request) -> IronResult<Response> {
    let js_enabled = match req.get_ref::<UrlEncodedQuery>() {
	Ok(query) => {
	    if query.contains_key("images") {
		return list_images()
	    }
	    query.contains_key("js")
	}
	Err(e) => {
	    warn!("Could not decode query: {}", e);
	    false
	}
    };
    let now = Utc::now();
    let title = if BIRTHDAY.month() == now.month() && BIRTHDAY.day() == now.day() {
	"Happy GNU/Birthday"
    } else {
	"Our GNU/Lord and GNU/Savior is 100% sexy!"
    };

let resp = format!(r#"<!DOCTYPE html>

		<meta charset="utf-8">
		<title>{}</title>
		{}
		<link rel="stylesheet" href="/style.css">
		<link rel="license" href="/license.txt">

"#,
title,
if js_enabled { "" } else { r#"<meta http-equiv="refresh" content="3;/">"# },
random_image());
    Ok(Response::with(
	(headers::ContentType::html().0, status::Ok, resp)
    ))
}

fn list_images() -> IronResult<Response> {
    Ok(Response::with(
	    (headers::ContentType::json().0, status::Ok, &*IMAGE_JSON.clone())
    ))
}

fn random_image() -> &'static str {
    rand::thread_rng().choose(&IMAGES)
	.unwrap()
}

fn images() -> Vec<String> {
    let imgs = std::fs::read_dir("./static/img").expect("could  not read img dir");

    imgs.filter_map(|entry| {
	let entry = entry.expect("error reading item");
	match entry.file_type().expect("file type") {
	    t if t.is_file() => {
		// Images can be found relative to '/' in the api, so prefix their relative paths
		// with '/' here.
		Some("/".to_string() + entry.path().strip_prefix("./static/").unwrap().to_str().unwrap())
	    },
	    _=> {
		None
	    }
	}
    }).collect()
}

<|endoftext|>


<commit_before>extern crate chrono;
#[macro_use] extern crate lazy_static;

#[macro_use] mod util;
mod config;
mod feed;
mod notification;

use std::thread;
use std::time::Duration;
use std::collections::HashMap;
use feed::listeners::{self, AverageMap, ListenerData};
use config::Config;
use util::error::{self, DetailedError};
use self::chrono::{UTC, Timelike};

fn sort_feeds(config: &Config, feeds: &mut Vec<feed::Feed>) {
    use config::SortOrder::*;

    feeds.sort_by(|x, y| {
        match config.misc.sort_order {
            Ascending  => x.listeners.cmp(&y.listeners),
            Descending => y.listeners.cmp(&x.listeners),
        }
    });
}

fn show_feeds(feeds: &Vec<feed::Feed>, average_data: &AverageMap) -> Result<(), DetailedError> {
    for (i, feed) in feeds.iter().enumerate() {
        let delta = average_data.get(&feed.id)
                        .map(|avg| avg.get_average_delta(feed.listeners as f32) as i32)
                        .unwrap_or(0);

        try_detailed!(notification::create_update,
            i as i32 + 1,
            feeds.len() as i32,
            &feed,
            delta);
    }

    Ok(())
}

fn perform_update(config: &Config, average_data: &mut AverageMap) -> Result<(), DetailedError> {
    let feeds = feed::get_latest(&config)?;
    let hour  = UTC::now().hour() as usize;

    let mut display_feeds = Vec::new();

    for feed in feeds {
        if feed.listeners < config.misc.minimum_listeners {
            continue
        }

        if cfg!(feature = "show-feed-info") {
            print!("{:?}\n^", feed);
        }

        let listeners = feed.listeners as f32;

        let listener_data =
            average_data
            .entry(feed.id)
            .or_insert(ListenerData::new(listeners, [0.; 24]));

        let has_spiked = listener_data.has_spiked(&config, &feed);
        listener_data.update(&config, hour, listeners, has_spiked);

        if has_spiked || feed.alert.is_some() {
            display_feeds.push(feed);
        }

        if cfg!(feature = "show-feed-info") {
            print!(" {:?} UNS: {:?}",
                listener_data.average,
                listener_data.unskewed_avg);

            if has_spiked {
                print!(" !!! SPIKED");
            }

            print!("\n\n");
        }
    }

    if display_feeds.len() > 0 {
        sort_feeds(&config, &mut display_feeds);
        show_feeds(&display_feeds, &average_data)?;
    }

    Ok(())
}

fn start() -> Result<(), DetailedError> {
    let config_path   = try_detailed!(util::verify_local_file, "config.yaml");
    let averages_path = try_detailed!(util::verify_local_file, "averages.csv");

    let mut listeners = listeners::load_averages(&averages_path)
        .unwrap_or(HashMap::new());

    let mut perform_cycle = || {
        let config = try_detailed!(config::load_from_file, &config_path);

        perform_update(&config, &mut listeners)?;
        try_detailed!(listeners::save_averages, &averages_path, &listeners);

        Ok(config)
    };

    loop {
        if cfg!(feature = "show-feed-info") {
            println!("updating");
        }

        let update_time_sec =
            match perform_cycle() {
                Ok(config) => config.misc.update_time as u64,
                Err(err) => {
                    error::report(&err);
                    config::Misc::default().update_time as u64
                },
            };

        thread::sleep(Duration::from_secs(update_time_sec * 60));
    }
}

fn main() {
    match start() {
        Ok(_) => (),
        Err(err) => {
            println!("FATAL ERROR:");
            error::report(&err);
        },
    }
}<commit_msg>Reverse feed display order on Windows<commit_after>extern crate chrono;
#[macro_use] extern crate lazy_static;

#[macro_use] mod util;
mod config;
mod feed;
mod notification;

use std::thread;
use std::time::Duration;
use std::collections::HashMap;
use feed::listeners::{self, AverageMap, ListenerData};
use config::Config;
use util::error::{self, DetailedError};
use self::chrono::{UTC, Timelike};

fn sort_feeds(config: &Config, feeds: &mut Vec<feed::Feed>) {
    use config::SortOrder::*;

    feeds.sort_by(|x, y| {
        match config.misc.sort_order {
            Ascending  => x.listeners.cmp(&y.listeners),
            Descending => y.listeners.cmp(&x.listeners),
        }
    });
}

fn show_feeds(feeds: &Vec<feed::Feed>, average_data: &AverageMap) -> Result<(), DetailedError> {
    #[cfg(unix)]
    let iter = feeds.iter().enumerate();
    #[cfg(windows)]
    let iter = feeds.iter().enumerate().rev();

    for (i, feed) in iter {
        let delta = average_data.get(&feed.id)
                        .map(|avg| avg.get_average_delta(feed.listeners as f32) as i32)
                        .unwrap_or(0);

        try_detailed!(notification::create_update,
            i as i32 + 1,
            feeds.len() as i32,
            &feed,
            delta);
    }

    Ok(())
}

fn perform_update(config: &Config, average_data: &mut AverageMap) -> Result<(), DetailedError> {
    let feeds = feed::get_latest(&config)?;
    let hour  = UTC::now().hour() as usize;

    let mut display_feeds = Vec::new();

    for feed in feeds {
        if feed.listeners < config.misc.minimum_listeners {
            continue
        }

        if cfg!(feature = "show-feed-info") {
            print!("{:?}\n^", feed);
        }

        let listeners = feed.listeners as f32;

        let listener_data =
            average_data
            .entry(feed.id)
            .or_insert(ListenerData::new(listeners, [0.; 24]));

        let has_spiked = listener_data.has_spiked(&config, &feed);
        listener_data.update(&config, hour, listeners, has_spiked);

        if has_spiked || feed.alert.is_some() {
            display_feeds.push(feed);
        }

        if cfg!(feature = "show-feed-info") {
            print!(" {:?} UNS: {:?}",
                listener_data.average,
                listener_data.unskewed_avg);

            if has_spiked {
                print!(" !!! SPIKED");
            }

            print!("\n\n");
        }
    }

    if display_feeds.len() > 0 {
        sort_feeds(&config, &mut display_feeds);
        show_feeds(&display_feeds, &average_data)?;
    }

    Ok(())
}

fn start() -> Result<(), DetailedError> {
    let config_path   = try_detailed!(util::verify_local_file, "config.yaml");
    let averages_path = try_detailed!(util::verify_local_file, "averages.csv");

    let mut listeners = listeners::load_averages(&averages_path)
        .unwrap_or(HashMap::new());

    let mut perform_cycle = || {
        let config = try_detailed!(config::load_from_file, &config_path);

        perform_update(&config, &mut listeners)?;
        try_detailed!(listeners::save_averages, &averages_path, &listeners);

        Ok(config)
    };

    loop {
        if cfg!(feature = "show-feed-info") {
            println!("updating");
        }

        let update_time_sec =
            match perform_cycle() {
                Ok(config) => config.misc.update_time as u64,
                Err(err) => {
                    error::report(&err);
                    config::Misc::default().update_time as u64
                },
            };

        thread::sleep(Duration::from_secs(update_time_sec * 60));
    }
}

fn main() {
    match start() {
        Ok(_) => (),
        Err(err) => {
            println!("FATAL ERROR:");
            error::report(&err);
        },
    }
}<|endoftext|>