<commit_before>use std::collections::BTreeMap;
use std::mem;
use std::rc::Rc;

use semver::Version;
use core::{Dependency, PackageId, SourceId};
use core::interning::InternedString;

use util::CargoResult;

/// Subset of a `Manifest`. Contains only the most important information about
/// a package.
///
/// Summaries are cloned, and should not be mutated after creation
#[derive(Debug, Clone)]
pub struct Summary {
    inner: Rc<Inner>,
}

#[derive(Debug, Clone)]
struct Inner {
    package_id: PackageId,
    dependencies: Vec<Dependency>,
    features: FeatureMap,
    checksum: Option<String>,
    links: Option<InternedString>,
}

impl Summary {
    pub fn new(
        pkg_id: PackageId,
        dependencies: Vec<Dependency>,
        features: BTreeMap<String, Vec<String>>,
        links: Option<String>,
    ) -> CargoResult<Summary> {
        for dep in dependencies.iter() {
            if features.get(&*dep.name()).is_some() {
                bail!(
                    "Features and dependencies cannot have the \
                     same name: `{}`",
                    dep.name()
                )
            }
            if dep.is_optional() && !dep.is_transitive() {
                bail!(
                    "Dev-dependencies are not allowed to be optional: `{}`",
                    dep.name()
                )
            }
        }
        let mut features_new = BTreeMap::new();
        for (feature, list) in features.iter() {
            let mut values = vec![];
            for dep in list {
                use self::FeatureValue::*;
                let val = FeatureValue::build(dep, |fs| (&features).get(fs).is_some());
                if let &Feature(_) = &val {
                    // Return early to avoid doing unnecessary work
                    values.push(val);
                    continue;
                }
                // Find data for the referenced dependency...
                let dep_data = {
                    let dep_name = match &val {
                        &Feature(_) => "",
                        &Crate(ref dep_name) | &CrateFeature(ref dep_name, _) => dep_name,
                    };
                    dependencies.iter().find(|d| *d.name() == *dep_name)
                };
                match (&val, dep_data) {
                    (&Crate(ref dep), Some(d)) => {
                        if !d.is_optional() {
                            bail!(
                                "Feature `{}` depends on `{}` which is not an \
                                 optional dependency.\nConsider adding \
                                 `optional = true` to the dependency",
                                feature,
                                dep
                            )
                        }
                    }
                    (&CrateFeature(ref dep_name, _), None) => bail!(
                        "Feature `{}` requires a feature of `{}` which is not a \
                         dependency",
                        feature,
                        dep_name
                    ),
                    (&Crate(ref dep), None) => bail!(
                        "Feature `{}` includes `{}` which is neither \
                         a dependency nor another feature",
                        feature,
                        dep
                    ),
                    (&CrateFeature(_, _), Some(_)) | (&Feature(_), _) => {}
                }
                values.push(val);
            }
            features_new.insert(feature.clone(), values);
        }
        Ok(Summary {
            inner: Rc::new(Inner {
                package_id: pkg_id,
                dependencies,
                features: features_new,
                checksum: None,
                links: links.map(|l| InternedString::new(&l)),
            }),
        })
    }

    pub fn package_id(&self) -> &PackageId {
        &self.inner.package_id
    }
    pub fn name(&self) -> InternedString {
        self.package_id().name()
    }
    pub fn version(&self) -> &Version {
        self.package_id().version()
    }
    pub fn source_id(&self) -> &SourceId {
        self.package_id().source_id()
    }
    pub fn dependencies(&self) -> &[Dependency] {
        &self.inner.dependencies
    }
    pub fn features(&self) -> &FeatureMap {
        &self.inner.features
    }
    pub fn checksum(&self) -> Option<&str> {
        self.inner.checksum.as_ref().map(|s| &s[..])
    }
    pub fn links(&self) -> Option<InternedString> {
        self.inner.links
    }

    pub fn override_id(mut self, id: PackageId) -> Summary {
        Rc::make_mut(&mut self.inner).package_id = id;
        self
    }

    pub fn set_checksum(mut self, cksum: String) -> Summary {
        Rc::make_mut(&mut self.inner).checksum = Some(cksum);
        self
    }

    pub fn map_dependencies<F>(mut self, f: F) -> Summary
    where
        F: FnMut(Dependency) -> Dependency,
    {
        {
            let slot = &mut Rc::make_mut(&mut self.inner).dependencies;
            let deps = mem::replace(slot, Vec::new());
            *slot = deps.into_iter().map(f).collect();
        }
        self
    }

    pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId) -> Summary {
        let me = if self.package_id().source_id() == to_replace {
            let new_id = self.package_id().with_source_id(replace_with);
            self.override_id(new_id)
        } else {
            self
        };
        me.map_dependencies(|dep| dep.map_source(to_replace, replace_with))
    }
}

impl PartialEq for Summary {
    fn eq(&self, other: &Summary) -> bool {
        self.inner.package_id == other.inner.package_id
    }
}

/// FeatureValue represents the types of dependencies a feature can have:
///
/// * Another feature
/// * An optional dependency
/// * A feature in a depedency
///
/// The selection between these 3 things happens as part of the construction of the FeatureValue.
#[derive(Clone, Debug, Serialize)]
pub enum FeatureValue {
    Feature(InternedString),
    Crate(InternedString),
    CrateFeature(InternedString, InternedString),
}

impl FeatureValue {
    fn build<T>(feature: &str, is_feature: T) -> FeatureValue
    where
        T: Fn(&str) -> bool,
    {
        match feature.find('/') {
            Some(pos) => {
                let (dep, dep_feat) = feature.split_at(pos);
                let dep_feat = &dep_feat[1..];
                FeatureValue::CrateFeature(InternedString::new(dep), InternedString::new(dep_feat))
            }
            None if is_feature(&feature) => FeatureValue::Feature(InternedString::new(feature)),
            None => FeatureValue::Crate(InternedString::new(feature)),
        }
    }

    pub fn new(feature: &str, s: &Summary) -> FeatureValue {
        Self::build(feature, |fs| s.features().get(fs).is_some())
    }

    pub fn to_string(&self) -> String {
        use self::FeatureValue::*;
        match *self {
            Feature(ref f) => f.to_string(),
            Crate(ref c) => c.to_string(),
            CrateFeature(ref c, ref f) => [c.as_ref(), f.as_ref()].join("/"),
        }
    }
}

pub type FeatureMap = BTreeMap<String, Vec<FeatureValue>>;
<commit_msg>Extract function to build feature map for readability<commit_after>use std::collections::BTreeMap;
use std::mem;
use std::rc::Rc;

use semver::Version;
use core::{Dependency, PackageId, SourceId};
use core::interning::InternedString;

use util::CargoResult;

/// Subset of a `Manifest`. Contains only the most important information about
/// a package.
///
/// Summaries are cloned, and should not be mutated after creation
#[derive(Debug, Clone)]
pub struct Summary {
    inner: Rc<Inner>,
}

#[derive(Debug, Clone)]
struct Inner {
    package_id: PackageId,
    dependencies: Vec<Dependency>,
    features: FeatureMap,
    checksum: Option<String>,
    links: Option<InternedString>,
}

impl Summary {
    pub fn new(
        pkg_id: PackageId,
        dependencies: Vec<Dependency>,
        features: BTreeMap<String, Vec<String>>,
        links: Option<String>,
    ) -> CargoResult<Summary> {
        for dep in dependencies.iter() {
            if features.get(&*dep.name()).is_some() {
                bail!(
                    "Features and dependencies cannot have the \
                     same name: `{}`",
                    dep.name()
                )
            }
            if dep.is_optional() && !dep.is_transitive() {
                bail!(
                    "Dev-dependencies are not allowed to be optional: `{}`",
                    dep.name()
                )
            }
        }
        let feature_map = build_feature_map(features, &dependencies)?;
        Ok(Summary {
            inner: Rc::new(Inner {
                package_id: pkg_id,
                dependencies,
                features: feature_map,
                checksum: None,
                links: links.map(|l| InternedString::new(&l)),
            }),
        })
    }

    pub fn package_id(&self) -> &PackageId {
        &self.inner.package_id
    }
    pub fn name(&self) -> InternedString {
        self.package_id().name()
    }
    pub fn version(&self) -> &Version {
        self.package_id().version()
    }
    pub fn source_id(&self) -> &SourceId {
        self.package_id().source_id()
    }
    pub fn dependencies(&self) -> &[Dependency] {
        &self.inner.dependencies
    }
    pub fn features(&self) -> &FeatureMap {
        &self.inner.features
    }
    pub fn checksum(&self) -> Option<&str> {
        self.inner.checksum.as_ref().map(|s| &s[..])
    }
    pub fn links(&self) -> Option<InternedString> {
        self.inner.links
    }

    pub fn override_id(mut self, id: PackageId) -> Summary {
        Rc::make_mut(&mut self.inner).package_id = id;
        self
    }

    pub fn set_checksum(mut self, cksum: String) -> Summary {
        Rc::make_mut(&mut self.inner).checksum = Some(cksum);
        self
    }

    pub fn map_dependencies<F>(mut self, f: F) -> Summary
    where
        F: FnMut(Dependency) -> Dependency,
    {
        {
            let slot = &mut Rc::make_mut(&mut self.inner).dependencies;
            let deps = mem::replace(slot, Vec::new());
            *slot = deps.into_iter().map(f).collect();
        }
        self
    }

    pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId) -> Summary {
        let me = if self.package_id().source_id() == to_replace {
            let new_id = self.package_id().with_source_id(replace_with);
            self.override_id(new_id)
        } else {
            self
        };
        me.map_dependencies(|dep| dep.map_source(to_replace, replace_with))
    }
}

impl PartialEq for Summary {
    fn eq(&self, other: &Summary) -> bool {
        self.inner.package_id == other.inner.package_id
    }
}

// Checks features for errors, bailing out a CargoResult:Err if invalid,
// and creates FeatureValues for each feature.
fn build_feature_map(
    features: BTreeMap<String, Vec<String>>,
    dependencies: &Vec<Dependency>,
) -> CargoResult<FeatureMap> {
    use self::FeatureValue::*;
    let mut map = BTreeMap::new();
    for (feature, list) in features.iter() {
        let mut values = vec![];
        for dep in list {
            let val = FeatureValue::build(dep, |fs| (&features).get(fs).is_some());
            if let &Feature(_) = &val {
                values.push(val);
                continue;
            }

            // Find data for the referenced dependency...
            let dep_data = {
                let dep_name = match &val {
                    &Feature(_) => "",
                    &Crate(ref dep_name) | &CrateFeature(ref dep_name, _) => dep_name,
                };
                dependencies.iter().find(|d| *d.name() == *dep_name)
            };

            match (&val, dep_data) {
                (&Crate(ref dep), Some(d)) => {
                    if !d.is_optional() {
                        bail!(
                            "Feature `{}` depends on `{}` which is not an \
                             optional dependency.\nConsider adding \
                             `optional = true` to the dependency",
                            feature,
                            dep
                        )
                    }
                }
                (&CrateFeature(ref dep_name, _), None) => bail!(
                    "Feature `{}` requires a feature of `{}` which is not a \
                     dependency",
                    feature,
                    dep_name
                ),
                (&Crate(ref dep), None) => bail!(
                    "Feature `{}` includes `{}` which is neither \
                     a dependency nor another feature",
                    feature,
                    dep
                ),
                (&CrateFeature(_, _), Some(_)) | (&Feature(_), _) => {}
            }
            values.push(val);
        }
        map.insert(feature.clone(), values);
    }
    Ok(map)
}

/// FeatureValue represents the types of dependencies a feature can have:
///
/// * Another feature
/// * An optional dependency
/// * A feature in a depedency
///
/// The selection between these 3 things happens as part of the construction of the FeatureValue.
#[derive(Clone, Debug, Serialize)]
pub enum FeatureValue {
    Feature(InternedString),
    Crate(InternedString),
    CrateFeature(InternedString, InternedString),
}

impl FeatureValue {
    fn build<T>(feature: &str, is_feature: T) -> FeatureValue
    where
        T: Fn(&str) -> bool,
    {
        match feature.find('/') {
            Some(pos) => {
                let (dep, dep_feat) = feature.split_at(pos);
                let dep_feat = &dep_feat[1..];
                FeatureValue::CrateFeature(InternedString::new(dep), InternedString::new(dep_feat))
            }
            None if is_feature(&feature) => FeatureValue::Feature(InternedString::new(feature)),
            None => FeatureValue::Crate(InternedString::new(feature)),
        }
    }

    pub fn new(feature: &str, s: &Summary) -> FeatureValue {
        Self::build(feature, |fs| s.features().get(fs).is_some())
    }

    pub fn to_string(&self) -> String {
        use self::FeatureValue::*;
        match *self {
            Feature(ref f) => f.to_string(),
            Crate(ref c) => c.to_string(),
            CrateFeature(ref c, ref f) => [c.as_ref(), f.as_ref()].join("/"),
        }
    }
}

pub type FeatureMap = BTreeMap<String, Vec<FeatureValue>>;
<|endoftext|>


<commit_before>// DOCS

#![crate_name = "vobject"]
#![crate_type = "lib"]
#![license = "MIT"]
#![comment = "Parser for VObject and iCalendar."]

#![feature(phase)]
#[phase(plugin)]
extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};

pub struct Property {
    params: HashMap<String, String>,
    raw_value: String,
}

impl Property {
    fn new(params: HashMap<String, String>, raw_value: String) -> Property {
        Property {
            params: params,
            raw_value: raw_value
        }
    }

    #[doc="Get parameters."]
    pub fn get_params(&self) -> &HashMap<String, String> {
        &self.params
    }

    #[doc="Get value as unparsed string."]
    pub fn get_raw_value(&self) -> &String {
        &self.raw_value
    }

    #[doc="Get value as unescaped string."]
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.get_raw_value())
    }
}

pub struct Component {
    #[doc="The name of the component, such as `VCARD` or `VEVENT`."]
    pub name: String,

    #[doc="The component's properties."]
    pub props: HashMap<String, Vec<Property>>,

    #[doc="The component's child- or sub-components."]
    pub subcomponents: Vec<Component>
}

impl Component {
    fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    #[doc="Retrieve one property (from many) by key.
        Returns `None` if nothing is found."]
    pub fn single_prop(&self, key: &String) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    #[doc="Retrieve a mutable vector of properties for this key.
        Creates one (and inserts it into the component) if none exists."]
    pub fn all_props_mut(&mut self, key: String) -> &mut Vec<Property> {
        match self.props.entry(key) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.set(vec![])
        }
    }

    #[doc="Retrieve properties by key.
        Returns an empty slice if key doesn't exist."]
    pub fn all_props(&self, key: &String) -> &[Property] {
        static EMPTY: &'static [Property] = [];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components?
      component_end {
        let mut rv = Component::new(name);

        match cs {
            Some(components) => { rv.subcomponents = components; },
            None => ()
        };

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v }

component_end -> String
    = "END:" v:value __ { v }

components -> Vec<Component>
    = cs:component ++ eols __ { cs }

props -> Vec<(String, Property)>
    = ps:contentline ++ eols __ { ps }

contentline -> (String, Property)
    = k:name p:params ":" v:value {
        (k, Property::new(p, v))
    }

name -> String
    = !"BEGIN" !"END" iana_token+ { match_str.into_string() }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::new();
        for (k, v) in ps.into_iter() {
            rv.insert(k, v);
        };
        rv
    }

param -> (String, String)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => "".into_string()
        })
    }

param_name -> String
    = iana_token+ { match_str.into_string() }

param_value -> String
    = x:(quoted_string / param_text) { print!("{}\n", x); x }

param_text -> String
    = safe_char* { match_str.into_string() }

value -> String
    = value_char+ { match_str.into_string() }

quoted_string -> String
    = dquote x:quoted_content dquote { x }

quoted_content -> String
    = qsafe_char* { match_str.into_string() }

iana_token = ([a-zA-Z0-9] / "-")+
safe_char = !";" !":" !"," value_char
qsafe_char = !dquote value_char // FIXME

value_char = !eol .

eol = "\n" / "\r\n" / "\r"
dquote = "\""
eols = eol+
whitespace = " " / "\t"
__ = (eol / whitespace)*

"#)

#[doc="Parse a component. The error value is a human-readable message."]
pub fn parse_component(s: &String) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = s
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\r ", "").replace("\r\t", "");

    parser::component(unfolded.as_slice())
}

#[doc="Escape text for a VObject property value."]
pub fn escape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

#[doc="Unescape text from a VObject property value."]
pub fn unescape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}
<commit_msg>remove debug code<commit_after>// DOCS

#![crate_name = "vobject"]
#![crate_type = "lib"]
#![license = "MIT"]
#![comment = "Parser for VObject and iCalendar."]

#![feature(phase)]
#[phase(plugin)]
extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};

pub struct Property {
    params: HashMap<String, String>,
    raw_value: String,
}

impl Property {
    fn new(params: HashMap<String, String>, raw_value: String) -> Property {
        Property {
            params: params,
            raw_value: raw_value
        }
    }

    #[doc="Get parameters."]
    pub fn get_params(&self) -> &HashMap<String, String> {
        &self.params
    }

    #[doc="Get value as unparsed string."]
    pub fn get_raw_value(&self) -> &String {
        &self.raw_value
    }

    #[doc="Get value as unescaped string."]
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.get_raw_value())
    }
}

pub struct Component {
    #[doc="The name of the component, such as `VCARD` or `VEVENT`."]
    pub name: String,

    #[doc="The component's properties."]
    pub props: HashMap<String, Vec<Property>>,

    #[doc="The component's child- or sub-components."]
    pub subcomponents: Vec<Component>
}

impl Component {
    fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    #[doc="Retrieve one property (from many) by key.
        Returns `None` if nothing is found."]
    pub fn single_prop(&self, key: &String) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    #[doc="Retrieve a mutable vector of properties for this key.
        Creates one (and inserts it into the component) if none exists."]
    pub fn all_props_mut(&mut self, key: String) -> &mut Vec<Property> {
        match self.props.entry(key) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.set(vec![])
        }
    }

    #[doc="Retrieve properties by key.
        Returns an empty slice if key doesn't exist."]
    pub fn all_props(&self, key: &String) -> &[Property] {
        static EMPTY: &'static [Property] = [];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components?
      component_end {
        let mut rv = Component::new(name);

        match cs {
            Some(components) => { rv.subcomponents = components; },
            None => ()
        };

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v }

component_end -> String
    = "END:" v:value __ { v }

components -> Vec<Component>
    = cs:component ++ eols __ { cs }

props -> Vec<(String, Property)>
    = ps:contentline ++ eols __ { ps }

contentline -> (String, Property)
    = k:name p:params ":" v:value {
        (k, Property::new(p, v))
    }

name -> String
    = !"BEGIN" !"END" iana_token+ { match_str.into_string() }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::new();
        for (k, v) in ps.into_iter() {
            rv.insert(k, v);
        };
        rv
    }

param -> (String, String)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => "".into_string()
        })
    }

param_name -> String
    = iana_token+ { match_str.into_string() }

param_value -> String
    = x:(quoted_string / param_text) { x }

param_text -> String
    = safe_char* { match_str.into_string() }

value -> String
    = value_char+ { match_str.into_string() }

quoted_string -> String
    = dquote x:quoted_content dquote { x }

quoted_content -> String
    = qsafe_char* { match_str.into_string() }

iana_token = ([a-zA-Z0-9] / "-")+
safe_char = !";" !":" !"," value_char
qsafe_char = !dquote value_char // FIXME

value_char = !eol .

eol = "\n" / "\r\n" / "\r"
dquote = "\""
eols = eol+
whitespace = " " / "\t"
__ = (eol / whitespace)*

"#)

#[doc="Parse a component. The error value is a human-readable message."]
pub fn parse_component(s: &String) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = s
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\r ", "").replace("\r\t", "");

    parser::component(unfolded.as_slice())
}

#[doc="Escape text for a VObject property value."]
pub fn escape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

#[doc="Unescape text from a VObject property value."]
pub fn unescape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Cursor, Write};

use crate::color::ColorType;
use crate::error::ImageResult;
use crate::image::{ImageDecoder, ImageEncoder};

use crate::codecs::bmp::BmpDecoder;
use crate::codecs::png::{PngDecoder, PngEncoder, PNG_SIGNATURE};

// Enum value indicating an ICO image (as opposed to a CUR image):
const ICO_IMAGE_TYPE: u16 = 1;
// The length of an ICO file ICONDIR structure, in bytes:
const ICO_ICONDIR_SIZE: u32 = 6;
// The length of an ICO file DIRENTRY structure, in bytes:
const ICO_DIRENTRY_SIZE: u32 = 16;

/// ICO encoder
pub struct IcoEncoder<W: Write> {
    w: W,
}

impl<W: Write> IcoEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> IcoEncoder<W> {
        IcoEncoder { w }
    }

    /// Encodes the image ```image``` that has dimensions ```width``` and
    /// ```height``` and ```ColorType``` ```c```.  The dimensions of the image
    /// must be between 1 and 256 (inclusive) or an error will be returned.
    ///
    /// Expects data to be big endian.
    #[deprecated = "Use `IcoEncoder::write_image` instead. Beware that `write_image` has a different endianness convention"]
    pub fn encode(
        mut self,
        data: &[u8],
        width: u32,
        height: u32,
        color: ColorType,
    ) -> ImageResult<()> {
        let mut image_data: Vec<u8> = Vec::new();
        #[allow(deprecated)]
        PngEncoder::new(&mut image_data).encode(data, width, height, color)?;

        write_icondir(&mut self.w, 1)?;
        write_direntry(
            &mut self.w,
            width,
            height,
            color,
            ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
            image_data.len() as u32,
        )?;
        self.w.write_all(&image_data)?;
        Ok(())
    }

    /// Takes an already encoded PNG or BMP image and encodes it into an ICO.
    ///
    /// The dimensions of the image must be between 1 and 256 (inclusive) or
    /// an error will be returned.
    pub fn write_pre_encoded_image(self, encoded_image: &[u8]) -> ImageResult<()> {
        let (width, height, color_type) = if encoded_image.starts_with(&PNG_SIGNATURE) {
            let decoder = PngDecoder::new(Cursor::new(encoded_image))?;

            let (width, height) = decoder.dimensions();
            let color_type = decoder.color_type();
            (width, height, color_type)
        } else {
            let decoder = BmpDecoder::new(Cursor::new(encoded_image))?;

            let (width, height) = decoder.dimensions();
            let color_type = decoder.color_type();
            (width, height, color_type)
        };

        self.write_pre_encoded_image_impl(encoded_image, width, height, color_type)
    }

    fn write_pre_encoded_image_impl(
        mut self,
        encoded_image: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        write_icondir(&mut self.w, 1)?;
        write_direntry(
            &mut self.w,
            width,
            height,
            color_type,
            ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
            encoded_image.len() as u32,
        )?;
        self.w.write_all(&encoded_image)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for IcoEncoder<W> {
    /// Write an ICO image with the specified width, height, and color type.
    ///
    /// For color types with 16-bit per channel or larger, the contents of `buf` should be in
    /// native endian.
    ///
    /// WARNING: In image 0.23.14 and earlier this method erroneously expected buf to be in big endian.
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        let mut image_data: Vec<u8> = Vec::new();
        PngEncoder::new(&mut image_data).write_image(buf, width, height, color_type)?;

        self.write_pre_encoded_image_impl(&image_data, width, height, color_type)
    }
}

fn write_icondir<W: Write>(w: &mut W, num_images: u16) -> io::Result<()> {
    // Reserved field (must be zero):
    w.write_u16::<LittleEndian>(0)?;
    // Image type (ICO or CUR):
    w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE)?;
    // Number of images in the file:
    w.write_u16::<LittleEndian>(num_images)?;
    Ok(())
}

fn write_direntry<W: Write>(
    w: &mut W,
    width: u32,
    height: u32,
    color: ColorType,
    data_start: u32,
    data_size: u32,
) -> io::Result<()> {
    // Image dimensions:
    write_width_or_height(w, width)?;
    write_width_or_height(w, height)?;
    // Number of colors in palette (or zero for no palette):
    w.write_u8(0)?;
    // Reserved field (must be zero):
    w.write_u8(0)?;
    // Color planes:
    w.write_u16::<LittleEndian>(0)?;
    // Bits per pixel:
    w.write_u16::<LittleEndian>(color.bits_per_pixel())?;
    // Image data size, in bytes:
    w.write_u32::<LittleEndian>(data_size)?;
    // Image data offset, in bytes:
    w.write_u32::<LittleEndian>(data_start)?;
    Ok(())
}

/// Encode a width/height value as a single byte, where 0 means 256.
fn write_width_or_height<W: Write>(w: &mut W, value: u32) -> io::Result<()> {
    if value < 1 || value > 256 {
        // TODO: this is not very idiomatic yet. Should return an EncodingError and be checked
        // prior to encoding.
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Invalid ICO dimensions (width and \
             height must be between 1 and 256)",
        ));
    }
    w.write_u8(if value < 256 { value as u8 } else { 0 })
}
<commit_msg>Don't do partial decoding in order to figure out the image metadata<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use crate::color::ColorType;
use crate::error::ImageResult;
use crate::image::ImageEncoder;

use crate::codecs::png::PngEncoder;

// Enum value indicating an ICO image (as opposed to a CUR image):
const ICO_IMAGE_TYPE: u16 = 1;
// The length of an ICO file ICONDIR structure, in bytes:
const ICO_ICONDIR_SIZE: u32 = 6;
// The length of an ICO file DIRENTRY structure, in bytes:
const ICO_DIRENTRY_SIZE: u32 = 16;

/// ICO encoder
pub struct IcoEncoder<W: Write> {
    w: W,
}

impl<W: Write> IcoEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> IcoEncoder<W> {
        IcoEncoder { w }
    }

    /// Encodes the image ```image``` that has dimensions ```width``` and
    /// ```height``` and ```ColorType``` ```c```.  The dimensions of the image
    /// must be between 1 and 256 (inclusive) or an error will be returned.
    ///
    /// Expects data to be big endian.
    #[deprecated = "Use `IcoEncoder::write_image` instead. Beware that `write_image` has a different endianness convention"]
    pub fn encode(
        mut self,
        data: &[u8],
        width: u32,
        height: u32,
        color: ColorType,
    ) -> ImageResult<()> {
        let mut image_data: Vec<u8> = Vec::new();
        #[allow(deprecated)]
        PngEncoder::new(&mut image_data).encode(data, width, height, color)?;

        write_icondir(&mut self.w, 1)?;
        write_direntry(
            &mut self.w,
            width,
            height,
            color,
            ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
            image_data.len() as u32,
        )?;
        self.w.write_all(&image_data)?;
        Ok(())
    }

    /// Takes an already encoded PNG or BMP image and encodes it into an ICO.
    ///
    /// `width`, `height` and `color_type` should match the
    /// real properties of the `encoded_image`.
    ///
    /// The dimensions of the image must be between 1 and 256 (inclusive) or
    /// an error will be returned.
    pub fn write_pre_encoded_image(
        mut self,
        encoded_image: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        write_icondir(&mut self.w, 1)?;
        write_direntry(
            &mut self.w,
            width,
            height,
            color_type,
            ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
            encoded_image.len() as u32,
        )?;
        self.w.write_all(&encoded_image)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for IcoEncoder<W> {
    /// Write an ICO image with the specified width, height, and color type.
    ///
    /// For color types with 16-bit per channel or larger, the contents of `buf` should be in
    /// native endian.
    ///
    /// WARNING: In image 0.23.14 and earlier this method erroneously expected buf to be in big endian.
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        let mut image_data: Vec<u8> = Vec::new();
        PngEncoder::new(&mut image_data).write_image(buf, width, height, color_type)?;

        self.write_pre_encoded_image(&image_data, width, height, color_type)
    }
}

fn write_icondir<W: Write>(w: &mut W, num_images: u16) -> io::Result<()> {
    // Reserved field (must be zero):
    w.write_u16::<LittleEndian>(0)?;
    // Image type (ICO or CUR):
    w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE)?;
    // Number of images in the file:
    w.write_u16::<LittleEndian>(num_images)?;
    Ok(())
}

fn write_direntry<W: Write>(
    w: &mut W,
    width: u32,
    height: u32,
    color: ColorType,
    data_start: u32,
    data_size: u32,
) -> io::Result<()> {
    // Image dimensions:
    write_width_or_height(w, width)?;
    write_width_or_height(w, height)?;
    // Number of colors in palette (or zero for no palette):
    w.write_u8(0)?;
    // Reserved field (must be zero):
    w.write_u8(0)?;
    // Color planes:
    w.write_u16::<LittleEndian>(0)?;
    // Bits per pixel:
    w.write_u16::<LittleEndian>(color.bits_per_pixel())?;
    // Image data size, in bytes:
    w.write_u32::<LittleEndian>(data_size)?;
    // Image data offset, in bytes:
    w.write_u32::<LittleEndian>(data_start)?;
    Ok(())
}

/// Encode a width/height value as a single byte, where 0 means 256.
fn write_width_or_height<W: Write>(w: &mut W, value: u32) -> io::Result<()> {
    if value < 1 || value > 256 {
        // TODO: this is not very idiomatic yet. Should return an EncodingError and be checked
        // prior to encoding.
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Invalid ICO dimensions (width and \
             height must be between 1 and 256)",
        ));
    }
    w.write_u8(if value < 256 { value as u8 } else { 0 })
}
<|endoftext|>


<commit_before>#[derive(Debug, Default)]
pub struct RegConfig {
    // EP
    data_transfer_pattern: DataTransferPattern,

    // BE
    endianness: Endianness,

    cu: bool,
    kseg0_cache_enable_bits: [bool;3],
    kseg0_cache_enabled: bool
}

impl From<u32> for RegConfig {
    fn from(value: u32) -> Self {
        RegConfig {
            data_transfer_pattern: value.into(),

            endianness: value.into(),

            cu: (value & (1 << 3)) != 0,
            kseg0_cache_enable_bits: [
                (value & (1 << 0)) != 0,
                (value & (1 << 1)) != 0,
                (value & (1 << 2)) != 0,
            ],
            // TODO: Extract to method?
            kseg0_cache_enabled: value & 0b111 != 0b010
        }
    }
}

#[derive(Debug)]
enum DataTransferPattern {
    Normal, // D
    DxxDxx
}

impl Default for DataTransferPattern {
    fn default() -> Self {
        DataTransferPattern::Normal
    }
}

impl From<u32> for DataTransferPattern {
    fn from(value: u32) -> Self {
        match (value >> 24) & 0b1111 {
            0 => DataTransferPattern::Normal,
            6 => DataTransferPattern::DxxDxx,
            _ => panic!("Invalid data transfer pattern (EP): {:#x}", value)
        }
    }
}

#[derive(Debug)]
enum Endianness {
    Little,
    Big
}

impl Default for Endianness {
    fn default() -> Self {
        Endianness::Big
    }
}

impl From<u32> for Endianness {
    fn from(value: u32) -> Self {
        match (value >> 15) & 0b1 {
            0 => Endianness::Little,
            1 => Endianness::Big,
            _ => unreachable!()
        }
    }
}
<commit_msg>Tiny change, space in [bool; 3]<commit_after>#[derive(Debug, Default)]
pub struct RegConfig {
    // EP
    data_transfer_pattern: DataTransferPattern,

    // BE
    endianness: Endianness,

    cu: bool,
    kseg0_cache_enable_bits: [bool; 3],
    kseg0_cache_enabled: bool
}

impl From<u32> for RegConfig {
    fn from(value: u32) -> Self {
        RegConfig {
            data_transfer_pattern: value.into(),

            endianness: value.into(),

            cu: (value & (1 << 3)) != 0,
            kseg0_cache_enable_bits: [
                (value & (1 << 0)) != 0,
                (value & (1 << 1)) != 0,
                (value & (1 << 2)) != 0,
            ],
            // TODO: Extract to method?
            kseg0_cache_enabled: value & 0b111 != 0b010
        }
    }
}

#[derive(Debug)]
enum DataTransferPattern {
    Normal, // D
    DxxDxx
}

impl Default for DataTransferPattern {
    fn default() -> Self {
        DataTransferPattern::Normal
    }
}

impl From<u32> for DataTransferPattern {
    fn from(value: u32) -> Self {
        match (value >> 24) & 0b1111 {
            0 => DataTransferPattern::Normal,
            6 => DataTransferPattern::DxxDxx,
            _ => panic!("Invalid data transfer pattern (EP): {:#x}", value)
        }
    }
}

#[derive(Debug)]
enum Endianness {
    Little,
    Big
}

impl Default for Endianness {
    fn default() -> Self {
        Endianness::Big
    }
}

impl From<u32> for Endianness {
    fn from(value: u32) -> Self {
        match (value >> 15) & 0b1 {
            0 => Endianness::Little,
            1 => Endianness::Big,
            _ => unreachable!()
        }
    }
}
<|endoftext|>


<commit_before>use diesel::backend::Backend;
use diesel::types::{FromSql, IsNull, Text, ToSql};
use std::error::Error;
use std::io::Write;
use std::fmt;
use std::str::FromStr;
use super::entities::Mbid;

#[derive(Debug)]
struct MbidFromSqlError {}

impl fmt::Display for MbidFromSqlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "{}", self.description())
    }
}

impl Error for MbidFromSqlError {
    fn description(&self) -> &str
    {
        "Failed reading `Mbid` from SQL."
    }
}

impl<DB: Backend<RawValue = String>> FromSql<Text, DB> for Mbid {
    fn from_sql(value: Option<&String>) -> Result<Self, Box<Error + Send + Sync>>
    {
        let str_value = value.ok_or(MbidFromSqlError {})?.as_ref();
        Ok(Mbid::from_str(str_value)?)
    }
}

impl<DB: Backend<RawValue = String>> ToSql<Text, DB> for Mbid {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error + Send + Sync>>
    {
        write!(out, "{}", self)?;
        Ok(IsNull::No)
    }
}
<commit_msg>Implement Expression for Mbid in diesel_integration.<commit_after>use diesel::backend::Backend;
use diesel::expression::Expression;
use diesel::types::{FromSql, IsNull, Text, ToSql};
use std::error::Error;
use std::io::Write;
use std::fmt;
use std::str::FromStr;
use super::entities::Mbid;

#[derive(Debug)]
struct MbidFromSqlError {}

impl fmt::Display for MbidFromSqlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "{}", self.description())
    }
}

impl Error for MbidFromSqlError {
    fn description(&self) -> &str
    {
        "Failed reading `Mbid` from SQL."
    }
}

impl<DB: Backend<RawValue = String>> FromSql<Text, DB> for Mbid {
    fn from_sql(value: Option<&String>) -> Result<Self, Box<Error + Send + Sync>>
    {
        let str_value = value.ok_or(MbidFromSqlError {})?.as_ref();
        Ok(Mbid::from_str(str_value)?)
    }
}

impl<DB: Backend<RawValue = String>> ToSql<Text, DB> for Mbid {
    fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error + Send + Sync>>
    {
        write!(out, "{}", self)?;
        Ok(IsNull::No)
    }
}

impl Expression for Mbid {
    type SqlType = Text;
}
<|endoftext|>


<commit_before>//! Assertion macro tests

#![feature(plugin)]

#[plugin]
#[macro_use]
extern crate nalgebra;

use nalgebra::{ApproxEq, Vec2};

#[test]
fn assert_approx_eq_f64() {
    let a = 1.0f64;
    let b = 1.0f64 + 1.0e-12f64;
    assert_approx_eq!(a, b);
    assert_approx_eq!(&a, &b);
}

#[test]
#[should_fail]
fn assert_approx_eq_vec2_f32_fail() {
    let a = Vec2::new(1.0f32, 0.0);
    let b = Vec2::new(1.1f32, 0.1);
    assert_approx_eq!(a, b);
}

#[test]
fn assert_approx_eq_eps_f32() {
    assert_approx_eq_eps!(1.0f32, 1.1, 0.2);
    assert_approx_eq_eps!(&mut 1.0f32, &mut 1.1, 0.2);
}

#[test]
#[should_fail]
fn assert_approx_eq_eps_f64_fail() {
    assert_approx_eq_eps!(1.0f64, 1.1, 0.05);
}

#[test]
fn assert_approx_eq_ulps_f32() {
    let x = 1000000_f32;
    let y = 1000000.1_f32;
    assert!(x != y);
    assert_approx_eq_ulps!(x, y, 3);
    assert_approx_eq_ulps!(&x, &y, 3);
}

#[test]
#[should_fail]
fn assert_approx_eq_ulps_f32_fail() {
    let x = 1000000_f32;
    let y = 1000000.1_f32;
    assert_approx_eq_ulps!(x, y, 2);
}

#[test]
fn assert_approx_eq_ulps_f64() {
    let x = 1000000_f64;
    let y = 1000000.0000000003_f64;
    assert!(x != y);
    assert_approx_eq_ulps!(x, y, 4);
}

#[test]
#[should_fail]
fn assert_approx_eq_ulps_f64_fail() {
    let x = 1000000_f64;
    let y = 1000000.0000000003_f64;
    assert!(x != y);
    assert_approx_eq_ulps!(x, y, 3);
}
<commit_msg>Avoid superfluous plugin usage in test<commit_after>//! Assertion macro tests

#[macro_use]
extern crate nalgebra;

use nalgebra::{ApproxEq, Vec2};

#[test]
fn assert_approx_eq_f64() {
    let a = 1.0f64;
    let b = 1.0f64 + 1.0e-12f64;
    assert_approx_eq!(a, b);
    assert_approx_eq!(&a, &b);
}

#[test]
#[should_fail]
fn assert_approx_eq_vec2_f32_fail() {
    let a = Vec2::new(1.0f32, 0.0);
    let b = Vec2::new(1.1f32, 0.1);
    assert_approx_eq!(a, b);
}

#[test]
fn assert_approx_eq_eps_f32() {
    assert_approx_eq_eps!(1.0f32, 1.1, 0.2);
    assert_approx_eq_eps!(&mut 1.0f32, &mut 1.1, 0.2);
}

#[test]
#[should_fail]
fn assert_approx_eq_eps_f64_fail() {
    assert_approx_eq_eps!(1.0f64, 1.1, 0.05);
}

#[test]
fn assert_approx_eq_ulps_f32() {
    let x = 1000000_f32;
    let y = 1000000.1_f32;
    assert!(x != y);
    assert_approx_eq_ulps!(x, y, 3);
    assert_approx_eq_ulps!(&x, &y, 3);
}

#[test]
#[should_fail]
fn assert_approx_eq_ulps_f32_fail() {
    let x = 1000000_f32;
    let y = 1000000.1_f32;
    assert_approx_eq_ulps!(x, y, 2);
}

#[test]
fn assert_approx_eq_ulps_f64() {
    let x = 1000000_f64;
    let y = 1000000.0000000003_f64;
    assert!(x != y);
    assert_approx_eq_ulps!(x, y, 4);
}

#[test]
#[should_fail]
fn assert_approx_eq_ulps_f64_fail() {
    let x = 1000000_f64;
    let y = 1000000.0000000003_f64;
    assert!(x != y);
    assert_approx_eq_ulps!(x, y, 3);
}
<|endoftext|>


<commit_before>use std::thread;
use std::path::Path;
use std::cell::RefCell;

use websocket::{Server, Message, Sender, Receiver};
use websocket::message::Type;
use websocket::header::WebSocketProtocol;

extern crate md5;

extern crate git2;
use self::git2::Repository;
use self::git2::Reference;
use self::git2::Statuses;
use self::git2::StatusOptions;
use self::git2::Delta;

extern crate yaml_rust;
use self::yaml_rust::YamlLoader;

use project;

use serde_xml as xml;

#[derive(Debug, Serialize, Deserialize)]
struct Commit {
    message: String,
    include: Vec<String>
}

impl Commit {
}

pub fn start() {
    let server = Server::bind("127.0.0.1:2794").unwrap();
    thread::spawn(move || {
        for connection in server {
            thread::spawn(move || {
                let request = connection.unwrap().read_request().unwrap();
                let headers = request.headers.clone();
                request.validate().unwrap();
                let mut response = request.accept();
                println!("Connected");

                if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
                    if protocols.contains(&("rust-websocket".to_string())) {
                        response.headers.set(WebSocketProtocol(vec!["superconductor".to_string()]));
                    }
                }

                let mut client = response.send().unwrap();
                let message = Message::text(generate_payload());
                client.send_message(&message).unwrap();

                let (mut sender, mut receiver) = client.split();
                for message in receiver.incoming_messages() {
                    let message: Message = message.unwrap();
                    match message.opcode {
                        Type::Close => {
                            let message = Message::close();
                            sender.send_message(&message).unwrap();
                            println!("Client disconnected");
                            return;
                        },
                        Type::Ping => {
                            let message = Message::pong(message.payload);
                            sender.send_message(&message).unwrap();
                        },
                        _ => {
                            let payload = String::from_utf8_lossy(message.payload.as_ref());
                            let commit: Commit = xml::from_str(&payload).unwrap();
                            println!("{:?}", commit);
                            let repo = Repository::discover(".").unwrap();
                            let mut index = repo.index().unwrap();
                            let removed = index.iter().fold(vec![], |mut acc, entry| {
                                let entry_path = String::from_utf8_lossy(entry.path.as_ref());
                                match commit.include.iter().find(|i| i.as_ref() == entry_path) {
                                    None => acc.push(entry_path.into_owned()),
                                    _ => {}
                                };
                                acc
                            });
                            println!("removed: {:?}", removed);
                            for change in removed {
                                let path = Path::new(&change);
                                index.remove_path(path);
                            }
                            for change in commit.include {
                                let path = Path::new(&change);
                                index.add_path(path);
                            }
                            index.write().unwrap();
                            let message = Message::text(generate_payload());
                            sender.send_message(&message).unwrap();
                        }
                    }
                }
            });
        }
    });
}

fn generate_payload() -> String {
    let current = project::current();
    let repo = Repository::discover(".").unwrap();
    let mut revwalk = repo.revwalk().unwrap();
    revwalk.set_sorting(git2::SORT_REVERSE);
    revwalk.push_head();
    let mut status_opts = StatusOptions::new();
    status_opts.include_untracked(true);

    let payload = html! {
        state {
            user {
                name  (current.user.name)
                    email (current.user.email)
            }
            task {
                id (current.task.id)
            }
            log {
                @for rev in revwalk {
                    @let commit = repo.find_commit(rev.unwrap()).unwrap() {
                        commit {
                            id (commit.id())
                            user {
                                @let author = commit.author() {
                                    name  (author.name().unwrap())
                                        @let email = author.email().unwrap().trim() {
                                            email (email)
                                            image (format!("https://www.gravatar.com/avatar/{:x}?s=64", md5::compute(email.to_lowercase())))
                                        }
                                }
                            }
                            @let mut message = commit.message().unwrap().split("\n---") {
                                message (message.next().unwrap())
                                @if let Some(yaml) = message.next() {
                                    @for (objective, values) in YamlLoader::load_from_str(yaml).unwrap()[0].as_hash().unwrap() {
                                        objective {
                                            name (objective.as_str().unwrap_or("None"))
                                            @for (name, value) in values.as_hash().unwrap() {
                                                property {
                                                    name (name.as_str().unwrap_or("None"))
                                                    after (value.as_str().unwrap_or("None"))
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            changes {
                @for change in repo.statuses(Some(&mut status_opts)).unwrap().iter() {
                    change {
                        path (change.path().unwrap())
                        included @match change.head_to_index().map(|d| d.status()).unwrap_or(Delta::Unreadable) {
                            Delta::Modified | Delta::Added | Delta::Deleted => "true",
                            _ => "false"
                        }
                        removal @match change.head_to_index().map(|d| d.status()).unwrap_or(Delta::Unreadable) {
                            Delta::Deleted => "true",
                            _ => "false"
                        }
                    }
                }
            }
        }
    }.into_string();
    payload
}
<commit_msg>unchecking changes resets the index<commit_after>use std::thread;
use std::path::Path;
use std::cell::RefCell;

use websocket::{Server, Message, Sender, Receiver};
use websocket::message::Type;
use websocket::header::WebSocketProtocol;

extern crate md5;

extern crate git2;
use self::git2::Repository;
use self::git2::Reference;
use self::git2::Statuses;
use self::git2::StatusOptions;
use self::git2::Delta;
use self::git2::ObjectType;

extern crate yaml_rust;
use self::yaml_rust::YamlLoader;

use project;

use serde_xml as xml;

#[derive(Debug, Serialize, Deserialize)]
struct Commit {
    message: String,
    include: Vec<String>
}

impl Commit {
}

pub fn start() {
    let server = Server::bind("127.0.0.1:2794").unwrap();
    thread::spawn(move || {
        for connection in server {
            thread::spawn(move || {
                let request = connection.unwrap().read_request().unwrap();
                let headers = request.headers.clone();
                request.validate().unwrap();
                let mut response = request.accept();
                println!("Connected");

                if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
                    if protocols.contains(&("rust-websocket".to_string())) {
                        response.headers.set(WebSocketProtocol(vec!["superconductor".to_string()]));
                    }
                }

                let mut client = response.send().unwrap();
                let message = Message::text(generate_payload());
                client.send_message(&message).unwrap();

                let (mut sender, mut receiver) = client.split();
                for message in receiver.incoming_messages() {
                    let message: Message = message.unwrap();
                    match message.opcode {
                        Type::Close => {
                            let message = Message::close();
                            sender.send_message(&message).unwrap();
                            println!("Client disconnected");
                            return;
                        },
                        Type::Ping => {
                            let message = Message::pong(message.payload);
                            sender.send_message(&message).unwrap();
                        },
                        _ => {
                            let payload = String::from_utf8_lossy(message.payload.as_ref());
                            let commit: Commit = xml::from_str(&payload).unwrap();
                            println!("{:?}", commit);
                            let repo = Repository::discover(".").unwrap();
                            let head = repo.head().unwrap().peel(ObjectType::Commit).unwrap();
                            let mut index = repo.index().unwrap();

                            let to_remove = index.iter().fold(vec![], |mut acc, entry| {
                                let entry_path = String::from_utf8_lossy(entry.path.as_ref());
                                match commit.include.iter().find(|i| i.as_ref() == entry_path) {
                                    None => acc.push(entry_path.into_owned()),
                                    _ => {}
                                };
                                acc
                            });

                            println!("removed: {:?}", to_remove);
                            repo.reset_default(Some(&head), to_remove.iter());
                            //for change in to_remove {
                            //    let path = Path::new(&change);
                            //    index.remove(path, 1);
                            //}
                            for change in commit.include {
                                let path = Path::new(&change);
                                index.add_path(path);
                            }
                            index.write().unwrap();
                            let message = Message::text(generate_payload());
                            sender.send_message(&message).unwrap();
                        }
                    }
                }
            });
        }
    });
}

fn generate_payload() -> String {
    let current = project::current();
    let repo = Repository::discover(".").unwrap();
    let mut revwalk = repo.revwalk().unwrap();
    revwalk.set_sorting(git2::SORT_REVERSE);
    revwalk.push_head();
    let mut status_opts = StatusOptions::new();
    status_opts.include_untracked(true);

    let payload = html! {
        state {
            user {
                name  (current.user.name)
                    email (current.user.email)
            }
            task {
                id (current.task.id)
            }
            log {
                @for rev in revwalk {
                    @let commit = repo.find_commit(rev.unwrap()).unwrap() {
                        commit {
                            id (commit.id())
                            user {
                                @let author = commit.author() {
                                    name  (author.name().unwrap())
                                        @let email = author.email().unwrap().trim() {
                                            email (email)
                                            image (format!("https://www.gravatar.com/avatar/{:x}?s=64", md5::compute(email.to_lowercase())))
                                        }
                                }
                            }
                            @let mut message = commit.message().unwrap().split("\n---") {
                                message (message.next().unwrap())
                                @if let Some(yaml) = message.next() {
                                    @for (objective, values) in YamlLoader::load_from_str(yaml).unwrap()[0].as_hash().unwrap() {
                                        objective {
                                            name (objective.as_str().unwrap_or("None"))
                                            @for (name, value) in values.as_hash().unwrap() {
                                                property {
                                                    name (name.as_str().unwrap_or("None"))
                                                    after (value.as_str().unwrap_or("None"))
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            changes {
                @for change in repo.statuses(Some(&mut status_opts)).unwrap().iter() {
                    change {
                        path (change.path().unwrap())
                        included @match change.head_to_index().map(|d| d.status()).unwrap_or(Delta::Unreadable) {
                            Delta::Modified | Delta::Added | Delta::Deleted => "true",
                            _ => "false"
                        }
                        removal @match change.head_to_index().map(|d| d.status()).unwrap_or(Delta::Unreadable) {
                            Delta::Deleted => "true",
                            _ => "false"
                        }
                    }
                }
            }
        }
    }.into_string();
    payload
}
<|endoftext|>


<commit_before>extern crate dbus;
use self::dbus::{Connection, Message, MessageType, NameFlag, ReleaseNameReply};
use self::dbus::obj::ObjectPath;

use super::error::DBusError;
use super::target::DBusTarget;

use std::collections::btree_map::{BTreeMap, Entry};
use std::error::Error;

pub struct DBusServer<'a> {
    conn: &'a Connection,
    name: String,

    objects: BTreeMap<String, ObjectPath<'a>>,
    signals: BTreeMap<DBusTarget, Vec<fn (&Connection, &DBusTarget) -> ()>>
}

impl<'a> DBusServer<'a> {
    pub fn new(conn: &'a Connection, name: &str) -> Result<DBusServer<'a>, dbus::Error> {
        try!(conn.register_name(name, NameFlag::DoNotQueue as u32));

        Ok(DBusServer {
            conn: conn,
            name: name.to_owned(),

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, add_interfaces: fn (&mut ObjectPath<'a>) -> ()) -> Result<&mut Self, Box<Error>> {
        // XXX: Use `.map` when type resolution works better. Currently, `.map` causes the caller
        // type to be set in stone due to eager type resolution and no fluidity in setting it. This
        // causes the type to be too concrete on the caller side which then fails to map to the end
        // result type of `.map` even though `.map` is "transparent" to the error type.
        Result::map(match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                let mut obj = ObjectPath::new(self.conn, path, true);
                try!(obj.set_registered(true));

                // Add interfaces.
                add_interfaces(&mut obj);

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(Box::new(DBusError::PathAlreadyRegistered(path.to_owned()))),
        }, |_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, DBusError> {
        match self.objects.remove(path) {
            Some(_) => Ok(self),
            None    => Err(DBusError::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect(&mut self, signal: DBusTarget, callback: fn (&Connection, &DBusTarget) -> ()) -> &mut Self {
        match self.signals.entry(signal) {
            Entry::Vacant(v)    => { v.insert(vec![callback]); },
            Entry::Occupied(o)  => o.into_mut().push(callback),
        };

        self
    }

    pub fn handle_message<'b>(&mut self, m: &'b mut Message) -> Option<&'b mut Message> {
        match m.msg_type() {
            MessageType::Signal     => Some(self._match_signal(m)),
            MessageType::MethodCall => self._call_method(m),
            _                       => Some(m),
        }
    }

    fn _call_method<'b>(&mut self, m: &'b mut Message) -> Option<&'b mut Message> {
        self.objects.iter_mut().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        })
    }

    fn _match_signal<'b>(&self, m: &'b mut Message) -> &'b mut Message {
        DBusTarget::extract(m).map(|signal| {
            self.signals.get(&signal).map(|fs| {
                fs.iter().map(|f| {
                    f(&self.conn, &signal);
                })
            });
        });

        m
    }
}

impl<'a> Drop for DBusServer<'a> {
    fn drop(&mut self) {
        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}: {:?}", self.name, err.name(), err.message()),
        }
    }
}
<commit_msg>server: handle namespaced signals as well<commit_after>extern crate dbus;
use self::dbus::{Connection, Message, MessageType, NameFlag, ReleaseNameReply};
use self::dbus::obj::ObjectPath;

use super::error::DBusError;
use super::target::DBusTarget;

use std::collections::btree_map::{BTreeMap, Entry};
use std::error::Error;

pub struct DBusServer<'a> {
    conn: &'a Connection,
    name: String,

    objects: BTreeMap<String, ObjectPath<'a>>,
    signals: BTreeMap<DBusTarget, Vec<fn (&Connection, &DBusTarget) -> ()>>,
    namespace_signals: BTreeMap<DBusTarget, Vec<fn (&Connection, &DBusTarget) -> ()>>,
}

impl<'a> DBusServer<'a> {
    pub fn new(conn: &'a Connection, name: &str) -> Result<DBusServer<'a>, dbus::Error> {
        try!(conn.register_name(name, NameFlag::DoNotQueue as u32));

        Ok(DBusServer {
            conn: conn,
            name: name.to_owned(),

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
            namespace_signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, add_interfaces: fn (&mut ObjectPath<'a>) -> ()) -> Result<&mut Self, Box<Error>> {
        // XXX: Use `.map` when type resolution works better. Currently, `.map` causes the caller
        // type to be set in stone due to eager type resolution and no fluidity in setting it. This
        // causes the type to be too concrete on the caller side which then fails to map to the end
        // result type of `.map` even though `.map` is "transparent" to the error type.
        Result::map(match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                let mut obj = ObjectPath::new(self.conn, path, true);
                try!(obj.set_registered(true));

                // Add interfaces.
                add_interfaces(&mut obj);

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(Box::new(DBusError::PathAlreadyRegistered(path.to_owned()))),
        }, |_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, DBusError> {
        match self.objects.remove(path) {
            Some(_) => Ok(self),
            None    => Err(DBusError::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect(&mut self, signal: DBusTarget, callback: fn (&Connection, &DBusTarget) -> ()) -> &mut Self {
        match self.signals.entry(signal) {
            Entry::Vacant(v)    => { v.insert(vec![callback]); },
            Entry::Occupied(o)  => o.into_mut().push(callback),
        };

        self

    pub fn connect_namespace(&mut self, signal: DBusTarget, callback: fn (&Connection, &DBusTarget) -> ()) -> &mut Self {
        match self.namespace_signals.entry(signal) {
            Entry::Vacant(v)    => { v.insert(vec![callback]); },
            Entry::Occupied(o)  => o.into_mut().push(callback),
        };

        self
    }

    pub fn handle_message<'b>(&mut self, m: &'b mut Message) -> Option<&'b mut Message> {
        match m.msg_type() {
            MessageType::Signal     => Some(self._match_signal(m)),
            MessageType::MethodCall => self._call_method(m),
            _                       => Some(m),
        }
    }

    fn _call_method<'b>(&mut self, m: &'b mut Message) -> Option<&'b mut Message> {
        self.objects.iter_mut().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        })
    }

    fn _match_signal<'b>(&self, m: &'b mut Message) -> &'b mut Message {
        DBusTarget::extract(m).map(|signal| {
            self.signals.get(&signal).map(|fs| {
                fs.iter().map(|f| {
                    f(&self.conn, &signal);
                })
            });

            self.namespace_signals.get(&signal).map(|fs| {
                fs.iter().map(|f| {
                    f(&self.conn, &signal);
                })
            });
        });

        m
    }
}

impl<'a> Drop for DBusServer<'a> {
    fn drop(&mut self) {
        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}: {:?}", self.name, err.name(), err.message()),
        }
    }
}
<|endoftext|>


<commit_before>mod arena;
mod messages;
mod primitives;

use actix::{Actor, AsyncContext, Context, Handler};
use anyhow::{anyhow, Context as ResultContext, Error};
use log::{error, info, warn};
use std::collections::HashMap;
use std::time::Duration;

pub use arena::{Arena, ArenaInput, ArenaOverview, ArenaUpdate};
pub use messages::{MessageIn, MessageOut};
pub use primitives::*;

use crate::get_error_chain;
use messages::MessageInPayload;

const UPDATE_RATE_MILLISECONDS: u64 = 25; // 1000 / 25 = 40 updates per second

#[derive(Debug, Default)]
pub struct Server {
    message_queue: Vec<MessageIn>,
    clients: HashMap<ClientId, Client>,
    arenas: HashMap<ArenaId, Arena>,
}

impl Server {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn new_arena(&mut self) -> ArenaId {
        let arena = Arena::default();
        let id = arena.id;

        self.arenas.insert(id, arena);

        id
    }

    pub fn client_input(&mut self, client_id: ClientId, input: ArenaInput) -> Result<(), Error> {
        let client = self
            .clients
            .get(&client_id)
            .with_context(|| anyhow!("Client {} not found", client_id))?;

        let arena_id = client
            .arena
            .with_context(|| anyhow!("Client {} not in an arena"))?;

        let arena = self
            .arenas
            .get_mut(&arena_id)
            .with_context(|| anyhow!("Arena {} not found", arena_id))?;

        let player_id = client
            .player
            .with_context(|| anyhow!("Client {} has no player", client_id))?;

        arena.process_input(player_id, input);

        Ok(())
    }

    pub fn client_part_arena(&mut self, client_id: ClientId) -> Result<(), Error> {
        let client = self
            .clients
            .get_mut(&client_id)
            .with_context(|| anyhow!("Client {} not found", client_id))?;

        client.updates_sent_so_far = 0;

        let arena_id = client
            .arena
            .with_context(|| anyhow!("Client {} not in an arena"))?;

        let arena = self
            .arenas
            .get_mut(&arena_id)
            .with_context(|| anyhow!("Arena {} not found", arena_id))?;

        let player_id = client
            .player
            .with_context(|| anyhow!("Client {} has no player", client_id))?;

        arena.remove_player(player_id);

        // TODO: Remove empty arenas

        Ok(())
    }
}

impl Server {
    pub fn handle_message(
        &mut self,
        client_id: ClientId,
        payload: MessageInPayload,
    ) -> Result<(), Error> {
        match payload {
            MessageInPayload::Connect(ip_address, address) => {
                info!("Client connected: {}", client_id);
                self.clients.insert(
                    client_id,
                    Client {
                        id: client_id,
                        ip_address,
                        address,
                        player: None,
                        arena: None,
                        updates_sent_so_far: 0,
                    },
                );
            }
            MessageInPayload::Disconnect => {
                info!("Client disconnected: {}", client_id);

                self.client_part_arena(client_id).unwrap_or_else(|error| {
                    warn!("Failed to remove client from their arena: {}", error)
                });

                self.clients
                    .remove(&client_id)
                    .ok_or_else(|| anyhow!("Failed to remove client {}", client_id))?;
            }

            MessageInPayload::GetArenaList => {
                let arena_list: Vec<ArenaOverview> =
                    self.arenas.values().map(ArenaOverview::from).collect();

                let client = self
                    .clients
                    .get_mut(&client_id)
                    .ok_or_else(|| anyhow!("Client {} not found", client_id))?;

                client
                    .address
                    .try_send(MessageOut::ArenaList(arena_list))
                    .with_context(|| anyhow!("Failed to send ArenaList to client {}", client_id))?;
            }
            MessageInPayload::Join { player, arena_id } => {
                self.client_part_arena(client_id).unwrap_or_else(|error| {
                    warn!("Failed to remove client from their arena: {}", error)
                });

                let arena_id = match arena_id {
                    Some(arena_id) => {
                        if self.arenas.contains_key(&arena_id) {
                            arena_id
                        } else {
                            self.new_arena()
                        }
                    }
                    None => self.new_arena(),
                };

                let arena = self
                    .arenas
                    .get_mut(&arena_id)
                    .ok_or_else(|| anyhow!("Arena {} not found", arena_id))?;

                if arena.players.len() >= arena.max_players {
                    return Err(anyhow!("Arena {} is full", arena_id));
                }

                let player_id = player.id;

                let client = self
                    .clients
                    .get_mut(&client_id)
                    .ok_or_else(|| anyhow!("Client {} not found", client_id))?;

                arena.add_player(player);
                client.player = Some(player_id);
                client.arena = Some(arena_id);

                client
                    .address
                    .try_send(MessageOut::ArenaJoined(arena.id))
                    .with_context(|| {
                        anyhow!("Failed to send ArenaJoined to client {}", client_id)
                    })?;

                info!("Player {} joined arena {}", player_id, arena_id);
            }

            MessageInPayload::Start => {
                self.client_input(client_id, ArenaInput::Start)?;
                info!("Client {} started game", client_id);
            }
            MessageInPayload::Turn(direction) => {
                self.client_input(client_id, ArenaInput::Turn(direction))?;
            }
        }
        Ok(())
    }
}

impl Server {
    pub fn process_messages(&mut self) {
        // take ownership of queued messages
        let mut process_messages_queue = Vec::with_capacity(self.message_queue.len());

        // move all message_queue messages into process_messages_queue
        process_messages_queue.append(&mut self.message_queue);

        // process each message
        process_messages_queue.drain(..).for_each(|message| {
            self.handle_message(message.client_id, message.payload)
                .unwrap_or_else(|error| {
                    error!("Failed processing MessageIn: {}", get_error_chain(error))
                });
        });
    }

    pub fn update(&mut self) {
        self.arenas.values_mut().for_each(|arena| arena.update());
    }

    pub fn send_updates(&mut self) {
        let clients = &mut self.clients;
        let arenas = &self.arenas;

        clients.values_mut().for_each(|client| {
            let arena = match client.arena {
                Some(arena) => arena,
                None => return,
            };

            let arena = match arenas.get(&arena) {
                Some(arena) => arena,
                None => return,
            };

            if client.updates_sent_so_far == 0 {
                unwrap_or_return!(
                    client
                        .address
                        .try_send(MessageOut::ArenaState(Box::from(arena.clone()))),
                    |error| error!("Failed to send ArenaState to client: {}", error)
                );
                client.updates_sent_so_far = arena.updates.len();
                return;
            }

            if client.updates_sent_so_far < arena.updates.len() {
                client
                    .address
                    .try_send(MessageOut::ArenaStatePatch(
                        arena
                            .updates
                            .iter()
                            .skip(client.updates_sent_so_far)
                            .cloned()
                            .collect(),
                    ))
                    .unwrap_or_else(|error| {
                        error!("Failed to send ArenaStatePatch to client: {}", error);
                    });
                client.updates_sent_so_far = arena.updates.len();
                return;
            }
        })
    }
}

impl Actor for Server {
    type Context = Context<Self>;

    fn started(&mut self, context: &mut Context<Self>) {
        context.run_interval(
            Duration::from_millis(UPDATE_RATE_MILLISECONDS),
            |server, _context| {
                server.process_messages();
                server.update();
                server.send_updates();
            },
        );
    }
}

impl Handler<MessageIn> for Server {
    type Result = ();

    fn handle(&mut self, message: MessageIn, _context: &mut Context<Self>) {
        self.message_queue.push(message);
    }
}
<commit_msg>removed inaccurate 'Client {} started game' log<commit_after>mod arena;
mod messages;
mod primitives;

use actix::{Actor, AsyncContext, Context, Handler};
use anyhow::{anyhow, Context as ResultContext, Error};
use log::{error, info, warn};
use std::collections::HashMap;
use std::time::Duration;

pub use arena::{Arena, ArenaInput, ArenaOverview, ArenaUpdate};
pub use messages::{MessageIn, MessageOut};
pub use primitives::*;

use crate::get_error_chain;
use messages::MessageInPayload;

const UPDATE_RATE_MILLISECONDS: u64 = 25; // 1000 / 25 = 40 updates per second

#[derive(Debug, Default)]
pub struct Server {
    message_queue: Vec<MessageIn>,
    clients: HashMap<ClientId, Client>,
    arenas: HashMap<ArenaId, Arena>,
}

impl Server {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn new_arena(&mut self) -> ArenaId {
        let arena = Arena::default();
        let id = arena.id;

        self.arenas.insert(id, arena);

        id
    }

    pub fn client_input(&mut self, client_id: ClientId, input: ArenaInput) -> Result<(), Error> {
        let client = self
            .clients
            .get(&client_id)
            .with_context(|| anyhow!("Client {} not found", client_id))?;

        let arena_id = client
            .arena
            .with_context(|| anyhow!("Client {} not in an arena"))?;

        let arena = self
            .arenas
            .get_mut(&arena_id)
            .with_context(|| anyhow!("Arena {} not found", arena_id))?;

        let player_id = client
            .player
            .with_context(|| anyhow!("Client {} has no player", client_id))?;

        arena.process_input(player_id, input);

        Ok(())
    }

    pub fn client_part_arena(&mut self, client_id: ClientId) -> Result<(), Error> {
        let client = self
            .clients
            .get_mut(&client_id)
            .with_context(|| anyhow!("Client {} not found", client_id))?;

        client.updates_sent_so_far = 0;

        let arena_id = client
            .arena
            .with_context(|| anyhow!("Client {} not in an arena"))?;

        let arena = self
            .arenas
            .get_mut(&arena_id)
            .with_context(|| anyhow!("Arena {} not found", arena_id))?;

        let player_id = client
            .player
            .with_context(|| anyhow!("Client {} has no player", client_id))?;

        arena.remove_player(player_id);

        // TODO: Remove empty arenas

        Ok(())
    }
}

impl Server {
    pub fn handle_message(
        &mut self,
        client_id: ClientId,
        payload: MessageInPayload,
    ) -> Result<(), Error> {
        match payload {
            MessageInPayload::Connect(ip_address, address) => {
                info!("Client connected: {}", client_id);
                self.clients.insert(
                    client_id,
                    Client {
                        id: client_id,
                        ip_address,
                        address,
                        player: None,
                        arena: None,
                        updates_sent_so_far: 0,
                    },
                );
            }
            MessageInPayload::Disconnect => {
                info!("Client disconnected: {}", client_id);

                self.client_part_arena(client_id).unwrap_or_else(|error| {
                    warn!("Failed to remove client from their arena: {}", error)
                });

                self.clients
                    .remove(&client_id)
                    .ok_or_else(|| anyhow!("Failed to remove client {}", client_id))?;
            }

            MessageInPayload::GetArenaList => {
                let arena_list: Vec<ArenaOverview> =
                    self.arenas.values().map(ArenaOverview::from).collect();

                let client = self
                    .clients
                    .get_mut(&client_id)
                    .ok_or_else(|| anyhow!("Client {} not found", client_id))?;

                client
                    .address
                    .try_send(MessageOut::ArenaList(arena_list))
                    .with_context(|| anyhow!("Failed to send ArenaList to client {}", client_id))?;
            }
            MessageInPayload::Join { player, arena_id } => {
                self.client_part_arena(client_id).unwrap_or_else(|error| {
                    warn!("Failed to remove client from their arena: {}", error)
                });

                let arena_id = match arena_id {
                    Some(arena_id) => {
                        if self.arenas.contains_key(&arena_id) {
                            arena_id
                        } else {
                            self.new_arena()
                        }
                    }
                    None => self.new_arena(),
                };

                let arena = self
                    .arenas
                    .get_mut(&arena_id)
                    .ok_or_else(|| anyhow!("Arena {} not found", arena_id))?;

                if arena.players.len() >= arena.max_players {
                    return Err(anyhow!("Arena {} is full", arena_id));
                }

                let player_id = player.id;

                let client = self
                    .clients
                    .get_mut(&client_id)
                    .ok_or_else(|| anyhow!("Client {} not found", client_id))?;

                arena.add_player(player);
                client.player = Some(player_id);
                client.arena = Some(arena_id);

                client
                    .address
                    .try_send(MessageOut::ArenaJoined(arena.id))
                    .with_context(|| {
                        anyhow!("Failed to send ArenaJoined to client {}", client_id)
                    })?;

                info!("Player {} joined arena {}", player_id, arena_id);
            }

            MessageInPayload::Start => {
                self.client_input(client_id, ArenaInput::Start)?;
            }
            MessageInPayload::Turn(direction) => {
                self.client_input(client_id, ArenaInput::Turn(direction))?;
            }
        }
        Ok(())
    }
}

impl Server {
    pub fn process_messages(&mut self) {
        // take ownership of queued messages
        let mut process_messages_queue = Vec::with_capacity(self.message_queue.len());

        // move all message_queue messages into process_messages_queue
        process_messages_queue.append(&mut self.message_queue);

        // process each message
        process_messages_queue.drain(..).for_each(|message| {
            self.handle_message(message.client_id, message.payload)
                .unwrap_or_else(|error| {
                    error!("Failed processing MessageIn: {}", get_error_chain(error))
                });
        });
    }

    pub fn update(&mut self) {
        self.arenas.values_mut().for_each(|arena| arena.update());
    }

    pub fn send_updates(&mut self) {
        let clients = &mut self.clients;
        let arenas = &self.arenas;

        clients.values_mut().for_each(|client| {
            let arena = match client.arena {
                Some(arena) => arena,
                None => return,
            };

            let arena = match arenas.get(&arena) {
                Some(arena) => arena,
                None => return,
            };

            if client.updates_sent_so_far == 0 {
                unwrap_or_return!(
                    client
                        .address
                        .try_send(MessageOut::ArenaState(Box::from(arena.clone()))),
                    |error| error!("Failed to send ArenaState to client: {}", error)
                );
                client.updates_sent_so_far = arena.updates.len();
                return;
            }

            if client.updates_sent_so_far < arena.updates.len() {
                client
                    .address
                    .try_send(MessageOut::ArenaStatePatch(
                        arena
                            .updates
                            .iter()
                            .skip(client.updates_sent_so_far)
                            .cloned()
                            .collect(),
                    ))
                    .unwrap_or_else(|error| {
                        error!("Failed to send ArenaStatePatch to client: {}", error);
                    });
                client.updates_sent_so_far = arena.updates.len();
                return;
            }
        })
    }
}

impl Actor for Server {
    type Context = Context<Self>;

    fn started(&mut self, context: &mut Context<Self>) {
        context.run_interval(
            Duration::from_millis(UPDATE_RATE_MILLISECONDS),
            |server, _context| {
                server.process_messages();
                server.update();
                server.send_updates();
            },
        );
    }
}

impl Handler<MessageIn> for Server {
    type Result = ();

    fn handle(&mut self, message: MessageIn, _context: &mut Context<Self>) {
        self.message_queue.push(message);
    }
}
<|endoftext|>


<commit_before>use nom::IResult;
use snmp_parser::parse_snmp_v3;

use rparser::{RParser,R_STATUS_OK,R_STATUS_FAIL};
use snmp::parse_pdu_enveloppe_version;

pub struct SnmpV3Parser<'a> {
    _name: Option<&'a[u8]>,
}

impl<'a> SnmpV3Parser<'a> {
    pub fn new(name: &'a[u8]) -> SnmpV3Parser<'a> {
        SnmpV3Parser{
            _name: Some(name),
        }
    }
}

impl<'a> RParser for SnmpV3Parser<'a> {
    fn parse(&mut self, i: &[u8], _direction: u8) -> u32 {
        match parse_snmp_v3(i) {
            IResult::Done(_rem,r) => {
                debug!("parse_snmp_v3: {:?}", r);
                R_STATUS_OK
            },
            e @ _ => {
                warn!("parse_snmp_v3 failed: {:?}", e);
                R_STATUS_FAIL
            },
        }
    }
}

pub fn snmpv3_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    match parse_pdu_enveloppe_version(i) {
        Some(1) |
        Some(2)   => true,
        _         => false,
    }
}

<commit_msg>Fix SNMPv3 probing<commit_after>use nom::IResult;
use snmp_parser::parse_snmp_v3;

use rparser::{RParser,R_STATUS_OK,R_STATUS_FAIL};
use snmp::parse_pdu_enveloppe_version;

pub struct SnmpV3Parser<'a> {
    _name: Option<&'a[u8]>,
}

impl<'a> SnmpV3Parser<'a> {
    pub fn new(name: &'a[u8]) -> SnmpV3Parser<'a> {
        SnmpV3Parser{
            _name: Some(name),
        }
    }
}

impl<'a> RParser for SnmpV3Parser<'a> {
    fn parse(&mut self, i: &[u8], _direction: u8) -> u32 {
        match parse_snmp_v3(i) {
            IResult::Done(_rem,r) => {
                debug!("parse_snmp_v3: {:?}", r);
                R_STATUS_OK
            },
            e @ _ => {
                warn!("parse_snmp_v3 failed: {:?}", e);
                R_STATUS_FAIL
            },
        }
    }
}

pub fn snmpv3_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    match parse_pdu_enveloppe_version(i) {
        Some(3)   => true,
        _         => false,
    }
}

<|endoftext|>


<commit_before>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      klee::warning_once("this path is reachable");
    }
  }
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    klee::assert_warn(b == 0, "this assertion should not trigger");

    if b == 12 {
      klee::warning_once("This path should be unreachable");
    }

    klee::assert_warn(b == 101, "this assertion should trigger");
    klee::assert_warn(b == 150000, "this assersion should not trigger");
  }
}
<commit_msg>Update simple.rs<commit_after>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      assert!("bugger");
    }
  }
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    assert_eq!(b == 0, "this assertion should not trigger");

    if b == 12 {
      assert!("This path should be unreachable");
    }

    assert_eq!(b == 101, "this assertion should trigger");
    assert_eq!(b == 150000, "this assersion should not trigger");
  }
}
<|endoftext|>


<commit_before>extern crate flac;
extern crate crypto;

use crypto::digest::Digest;
use crypto::md5::Md5;
use flac::Stream;
use std::cmp;

fn to_bytes(value: i32, buffer: &mut [u8]) {
  buffer[0] = value as u8;
  buffer[1] = (value >> 8) as u8;
  buffer[2] = (value >> 16) as u8;
  buffer[3] = (value >> 24) as u8;
}

fn get_offset(sample_size: usize) -> usize {
  let bits_per_sample = cmp::max(sample_size, 8);

  bits_per_sample / 8
}

#[test]
fn test_decoded_md5_sum() {
  let filenames = [
    "tests/assets/input-pictures.flac",
    "tests/assets/input-SCPAP.flac",
    "tests/assets/input-SVAUP.flac",
  ];

  let mut buffer  = [0; 4];
  let mut md5     = Md5::new();
  let mut md5_sum = [0; 16];

  {
    let mut stream = Stream::from_file(filenames[0]).unwrap();

    let info   = stream.info();
    let offset = get_offset(info.bits_per_sample as usize);

    for sample in stream.iter() {
      to_bytes(sample, &mut buffer);

      md5.input(&buffer[0..offset]);
    }

    md5.result(&mut md5_sum);

    assert_eq!(md5_sum, info.md5_sum);
  }

  md5.reset();

  {
    let mut stream = Stream::from_file(filenames[1]).unwrap();

    let info   = stream.info();
    let offset = get_offset(info.bits_per_sample as usize);

    for sample in stream.iter() {
      to_bytes(sample, &mut buffer);

      md5.input(&buffer[0..offset]);
    }

    md5.result(&mut md5_sum);

    assert_eq!(md5_sum, info.md5_sum);
  }
}
<commit_msg>Add the last test file for md5 checksums<commit_after>extern crate flac;
extern crate crypto;

use crypto::digest::Digest;
use crypto::md5::Md5;
use flac::Stream;
use std::cmp;

fn to_bytes(value: i32, buffer: &mut [u8]) {
  buffer[0] = value as u8;
  buffer[1] = (value >> 8) as u8;
  buffer[2] = (value >> 16) as u8;
  buffer[3] = (value >> 24) as u8;
}

fn get_offset(sample_size: usize) -> usize {
  let bits_per_sample = cmp::max(sample_size, 8);

  bits_per_sample / 8
}

#[test]
fn test_decoded_md5_sum() {
  let filenames = [
    "tests/assets/input-pictures.flac",
    "tests/assets/input-SCPAP.flac",
    "tests/assets/input-SVAUP.flac",
  ];

  let mut buffer  = [0; 4];
  let mut md5     = Md5::new();
  let mut md5_sum = [0; 16];

  {
    let mut stream = Stream::from_file(filenames[0]).unwrap();

    let info   = stream.info();
    let offset = get_offset(info.bits_per_sample as usize);

    for sample in stream.iter() {
      to_bytes(sample, &mut buffer);

      md5.input(&buffer[0..offset]);
    }

    md5.result(&mut md5_sum);

    assert_eq!(md5_sum, info.md5_sum);
  }

  md5.reset();

  {
    let mut stream = Stream::from_file(filenames[1]).unwrap();

    let info   = stream.info();
    let offset = get_offset(info.bits_per_sample as usize);

    for sample in stream.iter() {
      to_bytes(sample, &mut buffer);

      md5.input(&buffer[0..offset]);
    }

    md5.result(&mut md5_sum);

    assert_eq!(md5_sum, info.md5_sum);
  }

  md5.reset();

  {
    let mut stream = Stream::from_file(filenames[2]).unwrap();

    let info   = stream.info();
    let offset = get_offset(info.bits_per_sample as usize);

    for sample in stream.iter() {
      to_bytes(sample, &mut buffer);

      md5.input(&buffer[0..offset]);
    }

    md5.result(&mut md5_sum);

    assert_eq!(md5_sum, info.md5_sum);
  }
}
<|endoftext|>