<commit_before>use std::io::Read;
use std::convert::From;
use std::str;
use hyper;
use hyper::header::{ContentLength, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel};
use json;

pub type Codes = hyper::status::StatusCode;
pub type HyperResponse = hyper::client::Response;

#[derive(Debug)]
pub struct Response {
    content: Vec<u8>,
    hr: HyperResponse,
}

impl From<HyperResponse> for Response {
    fn from(mut raw: HyperResponse) -> Self {
        let mut content = match raw.headers.get::<ContentLength>() {
            Some(&ContentLength(length)) => Vec::with_capacity(length as usize),
            None => Vec::new(),
        };

        if raw.read_to_end(&mut content).is_err() {
            content = Vec::new()
        }

        Response {
            content: content,
            hr: raw,
        }
    }
}

impl<'a> Response {
    pub fn url(&self) -> &str {
        self.hr.url.as_str()
    }

    pub fn status_code(&self) -> Codes {
        self.hr.status
    }

    pub fn reason(&self) -> &str {
        self.hr.status.canonical_reason().unwrap_or("UNAVAILABLE")
    }

    pub fn ok(&self) -> bool {
        self.hr.status == hyper::Ok
    }

    pub fn text(&'a self) -> Option<&'a str> {
        str::from_utf8(&self.content).ok()
    }

    pub fn content(&'a self) -> &'a Vec<u8> {
        &self.content
    }

    pub fn json(&self) -> json::JsonResult<json::JsonValue> {
        self.text().map(|t| json::parse(t)).unwrap()
    }

    pub fn is_json(&self) -> bool {
        match self.hr.headers.get::<ContentType>() {
            Some(&ContentType(Mime(TopLevel::Application, SubLevel::Json, _))) => true,
            _ => false,
        }
    }
}
<commit_msg>Add headers accessor to Response<commit_after>use std::io::Read;
use std::convert::From;
use std::str;
use hyper;
use hyper::header::{Headers, ContentLength, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel};
use json;

pub type Codes = hyper::status::StatusCode;
pub type HyperResponse = hyper::client::Response;

#[derive(Debug)]
pub struct Response {
    content: Vec<u8>,
    hr: HyperResponse,
}

impl From<HyperResponse> for Response {
    fn from(mut raw: HyperResponse) -> Self {
        let mut content = match raw.headers.get::<ContentLength>() {
            Some(&ContentLength(length)) => Vec::with_capacity(length as usize),
            None => Vec::new(),
        };

        if raw.read_to_end(&mut content).is_err() {
            content = Vec::new()
        }

        Response {
            content: content,
            hr: raw,
        }
    }
}

impl<'a> Response {
    pub fn url(&self) -> &str {
        self.hr.url.as_str()
    }

    pub fn status_code(&self) -> Codes {
        self.hr.status
    }

    pub fn reason(&self) -> &str {
        self.hr.status.canonical_reason().unwrap_or("UNAVAILABLE")
    }

    pub fn ok(&self) -> bool {
        self.hr.status == hyper::Ok
    }

    pub fn text(&'a self) -> Option<&'a str> {
        str::from_utf8(&self.content).ok()
    }

    pub fn content(&'a self) -> &'a Vec<u8> {
        &self.content
    }

    pub fn json(&self) -> json::JsonResult<json::JsonValue> {
        self.text().map(|t| json::parse(t)).unwrap()
    }

    pub fn is_json(&self) -> bool {
        match self.hr.headers.get::<ContentType>() {
            Some(&ContentType(Mime(TopLevel::Application, SubLevel::Json, _))) => true,
            _ => false,
        }
    }

    pub fn headers(&self) -> &Headers {
        &self.hr.headers
    }
}
<|endoftext|>


<commit_before>use devices::{NodeId, ChannelKind, Channel, Get, Set};
use util::{Exactly, Id};
use values;

use serde::ser::Serializer;
use serde::de::Deserializer;

use std::cmp;

fn merge<T>(mut a: Vec<T>, mut b: Vec<T>) -> Vec<T> where T: Ord {
    a.append(&mut b);
    a.sort();
    a.dedup();
    a
}

/// A selector for one or more nodes.
///
///
/// # Example
///
/// ```
/// use fxbox_taxonomy::selector::*;
/// use fxbox_taxonomy::devices::*;
///
/// let selector = NodeSelector::new()
///   .with_tags(vec!["entrance".to_owned()])
///   .with_inputs(vec![GetSelector::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct NodeSelector {
    /// If `Exactly(id)`, return only the node with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<NodeId>>,

    ///  Restrict results to nodes that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// Restrict results to nodes that have all the inputs in `inputs`.
    #[serde(default)]
    pub inputs: Vec<GetSelector>,

    /// Restrict results to nodes that have all the outputs in `outputs`.
    #[serde(default)]
    pub outputs: Vec<SetSelector>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl NodeSelector {
    /// Create a new selector that accepts all nodes.
    pub fn new() -> Self {
        Self::default()
    }

    /// Selector for a node with a specific id.
    pub fn with_id(self, id: Id<NodeId>) -> Self {
        NodeSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    ///  Restrict results to nodes that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        NodeSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict results to nodes that have all the inputs in `inputs`.
    pub fn with_inputs(mut self, mut inputs: Vec<GetSelector>) -> Self {
        NodeSelector {
            inputs: {self.inputs.append(&mut inputs); self.inputs},
            .. self
        }
    }

    /// Restrict results to nodes that have all the outputs in `outputs`.
    pub fn with_outputs(mut self, mut outputs: Vec<SetSelector>) -> Self {
        NodeSelector {
            outputs: {self.outputs.append(&mut outputs); self.outputs},
            .. self
        }
    }

    /// Restrict results to nodes that are accepted by two selector.
    pub fn and(mut self, mut other: NodeSelector) -> Self {
        NodeSelector {
            id: self.id.and(other.id),
            tags: merge(self.tags, other.tags),
            inputs: {self.inputs.append(&mut other.inputs); self.inputs},
            outputs: {self.outputs.append(&mut other.outputs); self.outputs},
            private: (),
        }
    }
}

/// A selector for one or more input channels.
///
///
/// # Example
///
/// ```
/// use fxbox_taxonomy::selector::*;
/// use fxbox_taxonomy::devices::*;
/// use fxbox_taxonomy::util::Id;
///
/// let selector = GetSelector::new()
///   .with_parent(Id::new("foxbox".to_owned()))
///   .with_kind(ChannelKind::CurrentTimeOfDay);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct GetSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Get>>,

    /// If `Eactly(id)`, return only channels that are children of
    /// node `id`.
    #[serde(default)]
    pub parent: Exactly<Id<NodeId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exatly(k)`, restrict results to channels that produce values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// If `Some(r)`, restrict results to channels that support polling
    /// with the acceptable period.
    #[serde(default)]
    pub poll: Option<Period>,

    /// If `Some(r)`, restrict results to channels that support trigger
    /// with the acceptable period.
    #[serde(default)]
    pub trigger: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl GetSelector {
    /// Create a new selector that accepts all input channels.
    pub fn new() -> Self {
        Self::default()
    }

    /// Restrict to a channel with a specific id.
    pub fn with_id(self, id: Id<Get>) -> Self {
        GetSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific parent.
    pub fn with_parent(self, id: Id<NodeId>) -> Self {
        GetSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        GetSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        GetSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to channels that support polling with the acceptable
    /// period
    pub fn with_poll(self, period: Period) -> Self {
        GetSelector {
            poll: Period::and_option(self.poll, Some(period)),
            .. self
        }
    }

    /// Restrict to channels that support trigger with the acceptable
    /// period
    pub fn with_trigger(self, period: Period) -> Self {
        GetSelector {
            trigger: Period::and_option(self.trigger, Some(period)),
            .. self
        }
    }

    /// Restrict to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        GetSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            poll: Period::and_option(self.poll, other.poll),
            trigger: Period::and_option(self.trigger, other.trigger),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, channel: &Channel<Get>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.node) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !Period::matches_option(&self.poll, &channel.mechanism.poll) {
            return false;
        }
        if !Period::matches_option(&self.trigger, &channel.mechanism.trigger) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        return true;
    }
}

/// A selector for one or more output channels.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct SetSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Set>>,

    /// If `Exactly(id)`, return only channels that are immediate children
    /// of node `id`.
    #[serde(default)]
    pub parent: Exactly<Id<NodeId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exactly(k)`, restrict results to channels that accept values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// If `Some(r)`, restrict results to channels that support pushing
    /// with the acceptable period.
    #[serde(default)]
    pub push: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl SetSelector {
    /// Create a new selector that accepts all input channels.
    pub fn new() -> Self {
        SetSelector::default()
    }

    /// Selector to a channel with a specific id.
    pub fn with_id(self, id: Id<Set>) -> Self {
        SetSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific parent.
    pub fn with_parent(self, id: Id<NodeId>) -> Self {
        SetSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        SetSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        SetSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to channels that support push with the acceptable
    /// period
    pub fn with_push(self, period: Period) -> Self {
        SetSelector {
            push: Period::and_option(self.push, Some(period)),
            .. self
        }
    }

    /// Restrict results to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        SetSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            push: Period::and_option(self.push, other.push),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, channel: &Channel<Set>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.node) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !Period::matches_option(&self.push, &channel.mechanism.push) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        return true;
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<values::ValDuration>,
    #[serde(default)]
    pub max: Option<values::ValDuration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(max1), Some(max2)) => Some(cmp::min(max1, max2))
        };
        Period {
            min: min,
            max: max
        }
    }

    pub fn and_option(a: Option<Self>, b: Option<Self>) -> Option<Self> {
        match (a, b) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &values::ValDuration) -> bool {
        if let Some(ref min) = self.min {
            if min > duration {
                return false;
            }
        }
        if let Some(ref max) = self.max {
            if max < duration {
                return false;
            }
        }
        return true;
    }

    pub fn matches_option(period: &Option<Self>, duration: &Option<values::ValDuration>) -> bool {
        match (period, duration) {
            (&Some(ref period), &Some(ref duration))
                if !period.matches(duration) => false,
            (&Some(_), &None) => false,
            _ => true,
        }
    }
}

fn has_selected_tags(actual: &Vec<String>, requested: &Vec<String>) -> bool {
    for tag in &*actual {
        if requested.iter().find(|x| *x == tag).is_none() {
            return false;
        }
    }
    return true;
}
<commit_msg>Trivial docfix<commit_after>use devices::{NodeId, ChannelKind, Channel, Get, Set};
use util::{Exactly, Id};
use values;

use serde::ser::Serializer;
use serde::de::Deserializer;

use std::cmp;

fn merge<T>(mut a: Vec<T>, mut b: Vec<T>) -> Vec<T> where T: Ord {
    a.append(&mut b);
    a.sort();
    a.dedup();
    a
}

/// A selector for one or more nodes.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::devices::*;
///
/// let selector = NodeSelector::new()
///   .with_tags(vec!["entrance".to_owned()])
///   .with_inputs(vec![GetSelector::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct NodeSelector {
    /// If `Exactly(id)`, return only the node with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<NodeId>>,

    ///  Restrict results to nodes that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// Restrict results to nodes that have all the inputs in `inputs`.
    #[serde(default)]
    pub inputs: Vec<GetSelector>,

    /// Restrict results to nodes that have all the outputs in `outputs`.
    #[serde(default)]
    pub outputs: Vec<SetSelector>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl NodeSelector {
    /// Create a new selector that accepts all nodes.
    pub fn new() -> Self {
        Self::default()
    }

    /// Selector for a node with a specific id.
    pub fn with_id(self, id: Id<NodeId>) -> Self {
        NodeSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    ///  Restrict results to nodes that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        NodeSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict results to nodes that have all the inputs in `inputs`.
    pub fn with_inputs(mut self, mut inputs: Vec<GetSelector>) -> Self {
        NodeSelector {
            inputs: {self.inputs.append(&mut inputs); self.inputs},
            .. self
        }
    }

    /// Restrict results to nodes that have all the outputs in `outputs`.
    pub fn with_outputs(mut self, mut outputs: Vec<SetSelector>) -> Self {
        NodeSelector {
            outputs: {self.outputs.append(&mut outputs); self.outputs},
            .. self
        }
    }

    /// Restrict results to nodes that are accepted by two selector.
    pub fn and(mut self, mut other: NodeSelector) -> Self {
        NodeSelector {
            id: self.id.and(other.id),
            tags: merge(self.tags, other.tags),
            inputs: {self.inputs.append(&mut other.inputs); self.inputs},
            outputs: {self.outputs.append(&mut other.outputs); self.outputs},
            private: (),
        }
    }
}

/// A selector for one or more input channels.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::devices::*;
/// use foxbox_taxonomy::util::Id;
///
/// let selector = GetSelector::new()
///   .with_parent(Id::new("foxbox".to_owned()))
///   .with_kind(ChannelKind::CurrentTimeOfDay);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct GetSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Get>>,

    /// If `Eactly(id)`, return only channels that are children of
    /// node `id`.
    #[serde(default)]
    pub parent: Exactly<Id<NodeId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exatly(k)`, restrict results to channels that produce values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// If `Some(r)`, restrict results to channels that support polling
    /// with the acceptable period.
    #[serde(default)]
    pub poll: Option<Period>,

    /// If `Some(r)`, restrict results to channels that support trigger
    /// with the acceptable period.
    #[serde(default)]
    pub trigger: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl GetSelector {
    /// Create a new selector that accepts all input channels.
    pub fn new() -> Self {
        Self::default()
    }

    /// Restrict to a channel with a specific id.
    pub fn with_id(self, id: Id<Get>) -> Self {
        GetSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific parent.
    pub fn with_parent(self, id: Id<NodeId>) -> Self {
        GetSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a channel with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        GetSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        GetSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to channels that support polling with the acceptable
    /// period
    pub fn with_poll(self, period: Period) -> Self {
        GetSelector {
            poll: Period::and_option(self.poll, Some(period)),
            .. self
        }
    }

    /// Restrict to channels that support trigger with the acceptable
    /// period
    pub fn with_trigger(self, period: Period) -> Self {
        GetSelector {
            trigger: Period::and_option(self.trigger, Some(period)),
            .. self
        }
    }

    /// Restrict to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        GetSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            poll: Period::and_option(self.poll, other.poll),
            trigger: Period::and_option(self.trigger, other.trigger),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, channel: &Channel<Get>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.node) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !Period::matches_option(&self.poll, &channel.mechanism.poll) {
            return false;
        }
        if !Period::matches_option(&self.trigger, &channel.mechanism.trigger) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        return true;
    }
}

/// A selector for one or more output channels.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct SetSelector {
    /// If `Exactly(id)`, return only the channel with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<Set>>,

    /// If `Exactly(id)`, return only channels that are immediate children
    /// of node `id`.
    #[serde(default)]
    pub parent: Exactly<Id<NodeId>>,

    ///  Restrict results to channels that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exactly(k)`, restrict results to channels that accept values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ChannelKind>,

    /// If `Some(r)`, restrict results to channels that support pushing
    /// with the acceptable period.
    #[serde(default)]
    pub push: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl SetSelector {
    /// Create a new selector that accepts all input channels.
    pub fn new() -> Self {
        SetSelector::default()
    }

    /// Selector to a channel with a specific id.
    pub fn with_id(self, id: Id<Set>) -> Self {
        SetSelector {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific parent.
    pub fn with_parent(self, id: Id<NodeId>) -> Self {
        SetSelector {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Selector to channels with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        SetSelector {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to channels that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        SetSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to channels that support push with the acceptable
    /// period
    pub fn with_push(self, period: Period) -> Self {
        SetSelector {
            push: Period::and_option(self.push, Some(period)),
            .. self
        }
    }

    /// Restrict results to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        SetSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            push: Period::and_option(self.push, other.push),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, channel: &Channel<Set>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.node) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !Period::matches_option(&self.push, &channel.mechanism.push) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        return true;
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<values::ValDuration>,
    #[serde(default)]
    pub max: Option<values::ValDuration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(max1), Some(max2)) => Some(cmp::min(max1, max2))
        };
        Period {
            min: min,
            max: max
        }
    }

    pub fn and_option(a: Option<Self>, b: Option<Self>) -> Option<Self> {
        match (a, b) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &values::ValDuration) -> bool {
        if let Some(ref min) = self.min {
            if min > duration {
                return false;
            }
        }
        if let Some(ref max) = self.max {
            if max < duration {
                return false;
            }
        }
        return true;
    }

    pub fn matches_option(period: &Option<Self>, duration: &Option<values::ValDuration>) -> bool {
        match (period, duration) {
            (&Some(ref period), &Some(ref duration))
                if !period.matches(duration) => false,
            (&Some(_), &None) => false,
            _ => true,
        }
    }
}

fn has_selected_tags(actual: &Vec<String>, requested: &Vec<String>) -> bool {
    for tag in &*actual {
        if requested.iter().find(|x| *x == tag).is_none() {
            return false;
        }
    }
    return true;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Ben Noordhuis <info@bnoordhuis.nl>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#[license = "ISC"];

#[link(name = "epoll",
       vers = "1.0",
       author = "Ben Noordhuis <info@bnoordhuis.nl>")];

use std; // required by the tests

import c_int = ctypes::c_int;

//const EPOLL_NONBLOCK: int = 0x800;
const EPOLL_CLOEXEC: int = 0x80000;

const EPOLL_CTL_ADD: int = 1;
const EPOLL_CTL_DEL: int = 2;
const EPOLL_CTL_MOD: int = 3;

const EPOLLIN: i32 = 0x01i32;
const EPOLLPRI: i32 = 0x02i32;
const EPOLLOUT: i32 = 0x04i32;
const EPOLLERR: i32 = 0x08i32;
const EPOLLHUP: i32 = 0x10i32;
const EPOLLONESHOT: i32 = 0x40000000i32;
const EPOLLET: i32 = 0x80000000i32;

type epoll_event = {
  events: i32,
  data: u64
};

#[nolink]
native mod __glibc {
  fn epoll_create1(flags: c_int) -> c_int;
  /*
  fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: epoll_event) -> c_int;
  fn epoll_wait(epfd: c_int,
                events: *mutable epoll_event,
                maxevents: c_int,
                timeout: c_int) -> c_int;
  */
  fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *u8) -> c_int;
  fn epoll_wait(epfd: c_int,
                events: *mutable u8,
                maxevents: c_int,
                timeout: c_int) -> c_int;
}

fn epoll_create1(flags: int) -> int {
  __glibc::epoll_create1(flags as c_int) as int
}

fn epoll_ctl(epfd: int, op: int, fd: int, event: epoll_event) -> int {
  /*
  __glibc::epoll_ctl(epfd as c_int, op as c_int, fd as c_int, event) as int
  */

  let buf: [mutable u8] = vec::init_elt_mut(12u, 0u8);

  // rust as of 2012-02-06 does not support packed types, hence we have to do
  // the packing and unpacking ourselves
  unsafe {
    let p1: *mutable i32 = unsafe::reinterpret_cast(ptr::mut_addr_of(buf[0]));
    let p2: *mutable u64 = unsafe::reinterpret_cast(ptr::mut_addr_of(buf[4]));
    *p1 = event.events;
    *p2 = event.data;
  }

  ret __glibc::epoll_ctl(epfd as c_int,
                         op as c_int,
                         fd as c_int,
                         ptr::addr_of(buf[0])) as int
}

fn epoll_wait(epfd: int, events: [mutable epoll_event], timeout: int) -> int {
  /*
  let pevents: *mutable epoll_event = ptr::mut_addr_of(events[0]);
  let maxevents: c_int = vec::len(events) as c_int;
  ret __glibc::epoll_wait(epfd as c_int,
                          pevents,
                          maxevents,
                          timeout as c_int) as int;
  */

  let buf: [mutable u8] = vec::init_elt_mut(12u * vec::len(events), 0u8);

  let nevents = __glibc::epoll_wait(epfd as c_int,
                                    ptr::mut_addr_of(buf[0]),
                                    vec::len(events) as c_int,
                                    timeout as c_int) as int;

  if (nevents == -1) {
    ret -1;
  }

  // rust as of 2012-02-06 does not support packed types, hence we have to do
  // the packing and unpacking ourselves
  let i = 0;
  while (i < nevents) {
    unsafe {
      let p1: *i32 = unsafe::reinterpret_cast(ptr::addr_of(buf[i * 12]));
      let p2: *u64 = unsafe::reinterpret_cast(ptr::addr_of(buf[i * 12 + 4]));
      events[i] = {events: *p1, data: *p2};
    }
    i += 1;
  }

  ret nevents;
}

#[test]
fn test_epoll_create1() {
  assert epoll_create1(0) >= 0;
  assert epoll_create1(EPOLL_CLOEXEC) >= 0;
  assert epoll_create1(-1) == -1;
}

#[test]
fn test_epoll_ctl() {
  let epfd = epoll_create1(0);
  assert epfd >= 0;

  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 0, {events:EPOLLIN, data:0u64}) == 0;
  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 0, {events:EPOLLIN, data:0u64}) == -1;
  assert epoll_ctl(epfd, EPOLL_CTL_MOD, 0, {events:EPOLLOUT, data:0u64}) == 0;
  assert epoll_ctl(epfd, EPOLL_CTL_DEL, 0, {events:EPOLLIN, data:0u64}) == 0;

  assert epoll_ctl(epfd, EPOLL_CTL_ADD, -1, {events:EPOLLIN, data:0u64}) == -1;
  assert epoll_ctl(epfd, EPOLL_CTL_MOD, -1, {events:EPOLLIN, data:0u64}) == -1;
  assert epoll_ctl(epfd, EPOLL_CTL_DEL, -1, {events:EPOLLIN, data:0u64}) == -1;
}

#[test]
fn test_epoll_wait() {
  // add stdout to epoll set and wait for it to become writable
  // should be immediate, it's an error if we hit the 50 ms timeout
  let epfd = epoll_create1(0);
  assert epfd >= 0;

  let magic = 42u64;
  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 1, {events:EPOLLOUT, data:magic}) == 0;
  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 2, {events:EPOLLOUT, data:magic}) == 0;

  let events: [mutable epoll_event] = [
    mutable {events:0i32, data:0u64}, {events:0i32, data:0u64}];

  let n = epoll_wait(epfd, events, 50);
  assert n == 2;
  assert events[0].data == magic;
  assert events[0].events & EPOLLOUT == EPOLLOUT;
}
<commit_msg>Export functions explicitly.<commit_after>/*
 * Copyright (c) 2012, Ben Noordhuis <info@bnoordhuis.nl>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#[license = "ISC"];

#[link(name = "epoll",
       vers = "1.0",
       author = "Ben Noordhuis <info@bnoordhuis.nl>")];

//export EPOLL_NONBLOCK;
export EPOLL_CLOEXEC;
export EPOLL_CTL_ADD;
export EPOLL_CTL_DEL;
export EPOLLIN;
export EPOLLPRI;
export EPOLLOUT;
export EPOLLERR;
export EPOLLHUP;
export EPOLLONESHOT;
export EPOLLET;
export epoll_event;
export epoll_create1;
export epoll_ctl;
export epoll_wait;

use std; // required by the tests

import c_int = ctypes::c_int;

//const EPOLL_NONBLOCK: int = 0x800;
const EPOLL_CLOEXEC: int = 0x80000;

const EPOLL_CTL_ADD: int = 1;
const EPOLL_CTL_DEL: int = 2;
const EPOLL_CTL_MOD: int = 3;

const EPOLLIN: i32 = 0x01i32;
const EPOLLPRI: i32 = 0x02i32;
const EPOLLOUT: i32 = 0x04i32;
const EPOLLERR: i32 = 0x08i32;
const EPOLLHUP: i32 = 0x10i32;
const EPOLLONESHOT: i32 = 0x40000000i32;
const EPOLLET: i32 = 0x80000000i32;

type epoll_event = {
  events: i32,
  data: u64
};

#[nolink]
native mod __glibc {
  fn epoll_create1(flags: c_int) -> c_int;
  /*
  fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: epoll_event) -> c_int;
  fn epoll_wait(epfd: c_int,
                events: *mutable epoll_event,
                maxevents: c_int,
                timeout: c_int) -> c_int;
  */
  fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *u8) -> c_int;
  fn epoll_wait(epfd: c_int,
                events: *mutable u8,
                maxevents: c_int,
                timeout: c_int) -> c_int;
}

fn epoll_create1(flags: int) -> int {
  __glibc::epoll_create1(flags as c_int) as int
}

fn epoll_ctl(epfd: int, op: int, fd: int, event: epoll_event) -> int {
  /*
  __glibc::epoll_ctl(epfd as c_int, op as c_int, fd as c_int, event) as int
  */

  let buf: [mutable u8] = vec::init_elt_mut(12u, 0u8);

  // rust as of 2012-02-06 does not support packed types, hence we have to do
  // the packing and unpacking ourselves
  unsafe {
    let p1: *mutable i32 = unsafe::reinterpret_cast(ptr::mut_addr_of(buf[0]));
    let p2: *mutable u64 = unsafe::reinterpret_cast(ptr::mut_addr_of(buf[4]));
    *p1 = event.events;
    *p2 = event.data;
  }

  ret __glibc::epoll_ctl(epfd as c_int,
                         op as c_int,
                         fd as c_int,
                         ptr::addr_of(buf[0])) as int
}

fn epoll_wait(epfd: int, events: [mutable epoll_event], timeout: int) -> int {
  /*
  let pevents: *mutable epoll_event = ptr::mut_addr_of(events[0]);
  let maxevents: c_int = vec::len(events) as c_int;
  ret __glibc::epoll_wait(epfd as c_int,
                          pevents,
                          maxevents,
                          timeout as c_int) as int;
  */

  let buf: [mutable u8] = vec::init_elt_mut(12u * vec::len(events), 0u8);

  let nevents = __glibc::epoll_wait(epfd as c_int,
                                    ptr::mut_addr_of(buf[0]),
                                    vec::len(events) as c_int,
                                    timeout as c_int) as int;

  if (nevents == -1) {
    ret -1;
  }

  // rust as of 2012-02-06 does not support packed types, hence we have to do
  // the packing and unpacking ourselves
  let i = 0;
  while (i < nevents) {
    unsafe {
      let p1: *i32 = unsafe::reinterpret_cast(ptr::addr_of(buf[i * 12]));
      let p2: *u64 = unsafe::reinterpret_cast(ptr::addr_of(buf[i * 12 + 4]));
      events[i] = {events: *p1, data: *p2};
    }
    i += 1;
  }

  ret nevents;
}

#[test]
fn test_epoll_create1() {
  assert epoll_create1(0) >= 0;
  assert epoll_create1(EPOLL_CLOEXEC) >= 0;
  assert epoll_create1(-1) == -1;
}

#[test]
fn test_epoll_ctl() {
  let epfd = epoll_create1(0);
  assert epfd >= 0;

  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 0, {events:EPOLLIN, data:0u64}) == 0;
  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 0, {events:EPOLLIN, data:0u64}) == -1;
  assert epoll_ctl(epfd, EPOLL_CTL_MOD, 0, {events:EPOLLOUT, data:0u64}) == 0;
  assert epoll_ctl(epfd, EPOLL_CTL_DEL, 0, {events:EPOLLIN, data:0u64}) == 0;

  assert epoll_ctl(epfd, EPOLL_CTL_ADD, -1, {events:EPOLLIN, data:0u64}) == -1;
  assert epoll_ctl(epfd, EPOLL_CTL_MOD, -1, {events:EPOLLIN, data:0u64}) == -1;
  assert epoll_ctl(epfd, EPOLL_CTL_DEL, -1, {events:EPOLLIN, data:0u64}) == -1;
}

#[test]
fn test_epoll_wait() {
  // add stdout to epoll set and wait for it to become writable
  // should be immediate, it's an error if we hit the 50 ms timeout
  let epfd = epoll_create1(0);
  assert epfd >= 0;

  let magic = 42u64;
  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 1, {events:EPOLLOUT, data:magic}) == 0;
  assert epoll_ctl(epfd, EPOLL_CTL_ADD, 2, {events:EPOLLOUT, data:magic}) == 0;

  let events: [mutable epoll_event] = [
    mutable {events:0i32, data:0u64}, {events:0i32, data:0u64}];

  let n = epoll_wait(epfd, events, 50);
  assert n == 2;
  assert events[0].data == magic;
  assert events[0].events & EPOLLOUT == EPOLLOUT;
}
<|endoftext|>


<commit_before>pub fn is_valid<S: Into<String>>(digits: S) -> bool {
    let s: String = digits.into();
    if s.chars().all(|c| c.is_digit(10) || c.is_whitespace()) {
        let cs = s.chars().filter(|c| c.is_digit(10)).collect::<Vec<_>>();
        cs.len() > 1
            && cs.into_iter()
                .rev()
                .enumerate()
                .map(|(i, c)| transmogrify(i, c))
                .sum::<u32>() % 10 == 0
    } else {
        false
    }
}

fn transmogrify(i: usize, c: char) -> u32 {
    let x = c.to_digit(10).unwrap();
    if i & 1 == 0 {
        x
    } else if x > 4 {
        x + x - 9
    } else {
        x + x
    }
}
<commit_msg>better<commit_after>pub fn is_valid<S: Into<String>>(digits: S) -> bool {
    let (nums, others): (Vec<_>, Vec<_>) =
        digits.into().chars().partition(|&c| c.is_digit(10));
    if others.iter().any(|&c| !c.is_whitespace()) || nums.len() < 2 {
        false
    } else {
        nums.iter()
            .rev()
            .enumerate()
            .map(|(i, &c)| transmogrify(i, c))
            .sum::<u32>() % 10 == 0
    }
}

fn transmogrify(i: usize, c: char) -> u32 {
    let x = c.to_digit(10).unwrap();
    if i & 1 == 0 {
        x
    } else if x > 4 {
        x + x - 9
    } else {
        x + x
    }
}
<|endoftext|>


<commit_before>/*================================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*================================================================================================*/

use ::util::{Logger, Version};
use ::engine::PluginManager;

use std::cell::RefCell;
use std::rc::Rc;

/*================================================================================================*/
/*------APP STRUCT--------------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app
///
/// This is the main control center of ionCore.
/// It is in charge of initialization, updating, and shutdown of all modules,
/// as well as the handing of any inter-module communication.
#[derive (Clone)]
pub struct App {

    // Public
    /// Manages all plugins.
    pub plugin_manager: PluginManager,

    // Private
    ///
    pub _name: String,
    ///
    pub _developer: String,
    ///
    pub _version: Version,
    ///
    pub _self_ref: Option<Rc<RefCell<App>>>
}

/*================================================================================================*/
/*------APPVERSION PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl App {

    /// Returns the name of the application.
    ///
    /// # Return value
    /// An immutable reference to the app name.
    pub fn get_name (&self) -> &str {
        &self._name
    }

    /// Returns the application developer
    ///
    /// # Return value
    /// An immutable reference to the app developer
    pub fn get_developer (&self) -> &str {
        &self._developer
    }

    /// Returns the version of the application.
    ///
    /// # Return value
    /// An immutable reference to the app version.
    pub fn get_version (&self) -> &Version {
        &self._version
    }

/*================================================================================================*/
/*------APPVERSION PUBLIC STATIC METHODS----------------------------------------------------------*/
/*================================================================================================*/

    /// Returns a new instance of the app builder
    ///
    /// # Return value
    /// A new instance of the app builder.
    pub fn builder () -> AppBuilder {

        AppBuilder {_name: "Ion App".to_string (),
                    _developer: String::new (),
                    _version: Version {major: 0, minor: 1, patch: 0}}
    }
}

/*================================================================================================*/
/*------APPBUILDER STRUCT-------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app builder
///
/// The app builder provides an easy and straightforward way of creating and
/// configuring a new app instance.
#[derive (Clone)]
pub struct AppBuilder {

    // Private
    _name: String,
    _developer: String,
    _version: Version
}

/*================================================================================================*/
/*------APPBUILDER PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl AppBuilder {

    /// Builds the application
    ///
    /// # Return value
    /// A new app instance.
    pub fn build (&self) -> App {

        Logger::init ("./ionCore.log", true).unwrap ();
        info! ("Initializing ionCore | Version: {}", env! ("CARGO_PKG_VERSION"));

        App {plugin_manager: PluginManager::new (),
             _name: self._name.clone (),
             _developer: self._developer.clone (),
             _version: self._version,
             _self_ref: None}
    }

    /// Sets the application name.
    ///
    /// # Arguments
    /// * `name` - The desired name of the application.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn name (&mut self, name: &str) -> &mut AppBuilder {

        self._name = name.to_string ();
        self
    }

    /// Sets the application developer.
    ///
    /// # Arguments
    /// * `developer` - The name of the developer.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn developer (&mut self, developer: &str) -> &mut AppBuilder {

        self._developer = developer.to_string ();
        self
    }

    /// Sets the version of the app.
    ///
    /// # Arguments
    /// * 'major' - The major version of the app.
    /// * `minor` - The minor version of the app.
    /// * `patch` - The patch version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version (&mut self, major: i32, minor: i32, patch: i32) -> &mut AppBuilder {

        self._version.major = major;
        self._version.minor = minor;
        self._version.patch = patch;

        self
    }

    /// Sets the major version of the app.
    ///
    /// # Arguments
    /// * `major` - The major version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version_major (&mut self, major: i32) -> &mut AppBuilder {

        self._version.major = major;
        self
    }

    /// Sets the minor version of the app.
    ///
    /// # Arguments
    /// * `minor` - The minor version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version_minor (&mut self, minor: i32) -> &mut AppBuilder {

        self._version.minor = minor;
        self
    }

    /// Sets the patch version of the app.
    ///
    /// # Arguments
    /// * `patch` - The patch version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version_patch (&mut self, patch: i32) -> &mut AppBuilder {

        self._version.patch = patch;
        self
    }
}
<commit_msg>Set variables back to private<commit_after>/*================================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*================================================================================================*/

use ::util::{Logger, Version};
use ::engine::PluginManager;

use std::cell::RefCell;
use std::rc::Rc;

/*================================================================================================*/
/*------APP STRUCT--------------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app
///
/// This is the main control center of ionCore.
/// It is in charge of initialization, updating, and shutdown of all modules,
/// as well as the handing of any inter-module communication.
#[derive (Clone)]
pub struct App {

    // Public
    /// Manages all plugins.
    pub plugin_manager: PluginManager,

    // Private
    _name: String,
    _developer: String,
    _version: Version,
    _self_ref: Option<Rc<RefCell<App>>>
}

/*================================================================================================*/
/*------APPVERSION PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl App {

    /// Returns the name of the application.
    ///
    /// # Return value
    /// An immutable reference to the app name.
    pub fn get_name (&self) -> &str {
        &self._name
    }

    /// Returns the application developer
    ///
    /// # Return value
    /// An immutable reference to the app developer
    pub fn get_developer (&self) -> &str {
        &self._developer
    }

    /// Returns the version of the application.
    ///
    /// # Return value
    /// An immutable reference to the app version.
    pub fn get_version (&self) -> &Version {
        &self._version
    }

/*================================================================================================*/
/*------APPVERSION PUBLIC STATIC METHODS----------------------------------------------------------*/
/*================================================================================================*/

    /// Returns a new instance of the app builder
    ///
    /// # Return value
    /// A new instance of the app builder.
    pub fn builder () -> AppBuilder {

        AppBuilder {_name: "Ion App".to_string (),
                    _developer: String::new (),
                    _version: Version {major: 0, minor: 1, patch: 0}}
    }
}

/*================================================================================================*/
/*------APPBUILDER STRUCT-------------------------------------------------------------------------*/
/*================================================================================================*/

/// The app builder
///
/// The app builder provides an easy and straightforward way of creating and
/// configuring a new app instance.
#[derive (Clone)]
pub struct AppBuilder {

    // Private
    _name: String,
    _developer: String,
    _version: Version
}

/*================================================================================================*/
/*------APPBUILDER PUBLIC METHODS-----------------------------------------------------------------*/
/*================================================================================================*/

impl AppBuilder {

    /// Builds the application
    ///
    /// # Return value
    /// A new app instance.
    pub fn build (&self) -> App {

        Logger::init ("./ionCore.log", true).unwrap ();
        info! ("Initializing ionCore | Version: {}", env! ("CARGO_PKG_VERSION"));

        App {plugin_manager: PluginManager::new (),
             _name: self._name.clone (),
             _developer: self._developer.clone (),
             _version: self._version,
             _self_ref: None}
    }

    /// Sets the application name.
    ///
    /// # Arguments
    /// * `name` - The desired name of the application.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn name (&mut self, name: &str) -> &mut AppBuilder {

        self._name = name.to_string ();
        self
    }

    /// Sets the application developer.
    ///
    /// # Arguments
    /// * `developer` - The name of the developer.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn developer (&mut self, developer: &str) -> &mut AppBuilder {

        self._developer = developer.to_string ();
        self
    }

    /// Sets the version of the app.
    ///
    /// # Arguments
    /// * 'major' - The major version of the app.
    /// * `minor` - The minor version of the app.
    /// * `patch` - The patch version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version (&mut self, major: i32, minor: i32, patch: i32) -> &mut AppBuilder {

        self._version.major = major;
        self._version.minor = minor;
        self._version.patch = patch;

        self
    }

    /// Sets the major version of the app.
    ///
    /// # Arguments
    /// * `major` - The major version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version_major (&mut self, major: i32) -> &mut AppBuilder {

        self._version.major = major;
        self
    }

    /// Sets the minor version of the app.
    ///
    /// # Arguments
    /// * `minor` - The minor version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version_minor (&mut self, minor: i32) -> &mut AppBuilder {

        self._version.minor = minor;
        self
    }

    /// Sets the patch version of the app.
    ///
    /// # Arguments
    /// * `patch` - The patch version of the app.
    ///
    /// # Return value
    /// A mutable reference to the current AppBuilder instance.
    pub fn version_patch (&mut self, patch: i32) -> &mut AppBuilder {

        self._version.patch = patch;
        self
    }
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::{collections::BTreeMap, env, ffi::OsString, fs, path::PathBuf};
use toml::Value;

fn main() {
    let mut args = env::args_os().skip(1).fuse();

    let input_filename = args.next().unwrap_or_else(|| OsString::from("Cargo.toml"));
    let output_filename = args.next().unwrap_or_else(|| input_filename.clone());

    let input_filename = PathBuf::from(input_filename);
    let output_filename = PathBuf::from(output_filename);

    let input = fs::read_to_string(&input_filename)
        .unwrap_or_else(|e| panic!("Cannot read {}: {}", input_filename.display(), e));
    let mut cargo_toml: Value = toml::from_str(&input)
        .unwrap_or_else(|e| panic!("Cannot parse {} as TOML: {}", input_filename.display(), e));

    if let Ok(edition) = env::var("PLAYGROUND_EDITION") {
        cargo_toml = set_edition(cargo_toml, &edition);
    }

    if env::var_os("PLAYGROUND_NO_DEPENDENCIES").is_some() {
        cargo_toml = remove_dependencies(cargo_toml);
    }

    if let Ok(crate_type) = env::var("PLAYGROUND_CRATE_TYPE") {
        cargo_toml = set_crate_type(cargo_toml, &crate_type);
    }

    if let Ok(lto) = env::var("PLAYGROUND_RELEASE_LTO") {
        cargo_toml = set_release_lto(cargo_toml, lto == "true");
    }

    let output = toml::to_string(&cargo_toml).expect("Cannot convert back to TOML");

    fs::write(&output_filename, output)
        .unwrap_or_else(|e| panic!("Cannot write to {}: {}", output_filename.display(), e));
}

type Other = BTreeMap<String, Value>;

fn modify<F, T>(cargo_toml: Value, f: F) -> Value
where
    F: FnOnce(T) -> T,
    T: serde::Serialize + for<'de> serde::Deserialize<'de>,
{
    let cargo_toml = cargo_toml.try_into().unwrap();

    let cargo_toml = f(cargo_toml);

    Value::try_from(cargo_toml).unwrap()
}

fn ensure_string_in_vec(values: &mut Vec<String>, val: &str) {
    if !values.iter().any(|f| f == val) {
        values.push(val.into());
    }
}

fn set_edition(cargo_toml: Value, edition: &str) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        cargo_features: Vec<String>,
        package: Package,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Package {
        #[serde(default)]
        edition: String,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        ensure_string_in_vec(&mut cargo_toml.cargo_features, "edition");
        cargo_toml.package.edition = edition.into();
        cargo_toml
    })
}

fn remove_dependencies(cargo_toml: Value) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        dependencies: BTreeMap<String, Value>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.dependencies.clear();
        cargo_toml
    })
}

fn set_crate_type(cargo_toml: Value, crate_type: &str) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        lib: Lib,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Lib {
        #[serde(default)]
        crate_type: Vec<String>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        ensure_string_in_vec(&mut cargo_toml.lib.crate_type, crate_type);
        cargo_toml
    })
}

fn set_release_lto(cargo_toml: Value, lto: bool) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        profile: Profiles,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profiles {
        #[serde(default)]
        release: Profile,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profile {
        #[serde(default)]
        lto: bool,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.profile.release.lto = lto;
        cargo_toml
    })
}
<commit_msg>Remove `edition` feature from manifest<commit_after>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::{collections::BTreeMap, env, ffi::OsString, fs, path::PathBuf};
use toml::Value;

fn main() {
    let mut args = env::args_os().skip(1).fuse();

    let input_filename = args.next().unwrap_or_else(|| OsString::from("Cargo.toml"));
    let output_filename = args.next().unwrap_or_else(|| input_filename.clone());

    let input_filename = PathBuf::from(input_filename);
    let output_filename = PathBuf::from(output_filename);

    let input = fs::read_to_string(&input_filename)
        .unwrap_or_else(|e| panic!("Cannot read {}: {}", input_filename.display(), e));
    let mut cargo_toml: Value = toml::from_str(&input)
        .unwrap_or_else(|e| panic!("Cannot parse {} as TOML: {}", input_filename.display(), e));

    if let Ok(edition) = env::var("PLAYGROUND_EDITION") {
        cargo_toml = set_edition(cargo_toml, &edition);
    }

    if env::var_os("PLAYGROUND_NO_DEPENDENCIES").is_some() {
        cargo_toml = remove_dependencies(cargo_toml);
    }

    if let Ok(crate_type) = env::var("PLAYGROUND_CRATE_TYPE") {
        cargo_toml = set_crate_type(cargo_toml, &crate_type);
    }

    if let Ok(lto) = env::var("PLAYGROUND_RELEASE_LTO") {
        cargo_toml = set_release_lto(cargo_toml, lto == "true");
    }

    let output = toml::to_string(&cargo_toml).expect("Cannot convert back to TOML");

    fs::write(&output_filename, output)
        .unwrap_or_else(|e| panic!("Cannot write to {}: {}", output_filename.display(), e));
}

type Other = BTreeMap<String, Value>;

fn modify<F, T>(cargo_toml: Value, f: F) -> Value
where
    F: FnOnce(T) -> T,
    T: serde::Serialize + for<'de> serde::Deserialize<'de>,
{
    let cargo_toml = cargo_toml.try_into().unwrap();

    let cargo_toml = f(cargo_toml);

    Value::try_from(cargo_toml).unwrap()
}

fn ensure_string_in_vec(values: &mut Vec<String>, val: &str) {
    if !values.iter().any(|f| f == val) {
        values.push(val.into());
    }
}

fn set_edition(cargo_toml: Value, edition: &str) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        package: Package,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Package {
        #[serde(default)]
        edition: String,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.package.edition = edition.into();
        cargo_toml
    })
}

fn remove_dependencies(cargo_toml: Value) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        dependencies: BTreeMap<String, Value>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.dependencies.clear();
        cargo_toml
    })
}

fn set_crate_type(cargo_toml: Value, crate_type: &str) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        lib: Lib,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Lib {
        #[serde(default)]
        crate_type: Vec<String>,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        ensure_string_in_vec(&mut cargo_toml.lib.crate_type, crate_type);
        cargo_toml
    })
}

fn set_release_lto(cargo_toml: Value, lto: bool) -> Value {
    #[derive(Debug, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct CargoToml {
        #[serde(default)]
        profile: Profiles,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profiles {
        #[serde(default)]
        release: Profile,
        #[serde(flatten)]
        other: Other,
    }

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(rename_all = "kebab-case")]
    struct Profile {
        #[serde(default)]
        lto: bool,
        #[serde(flatten)]
        other: Other,
    }

    modify(cargo_toml, |mut cargo_toml: CargoToml| {
        cargo_toml.profile.release.lto = lto;
        cargo_toml
    })
}
<|endoftext|>


<commit_before>//! The main event loop which performs I/O on the pseudoterminal
use std::borrow::Cow;
use std::collections::VecDeque;
use std::io::{self, ErrorKind, Write};
use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use mio::{self, Events, PollOpt, Ready};
use mio::unix::EventedFd;

use ansi;
use display;
use event;
use term::Term;
use util::thread;
use sync::FairMutex;

/// Messages that may be sent to the `EventLoop`
#[derive(Debug)]
pub enum Msg {
    /// Data that should be written to the pty
    Input(Cow<'static, [u8]>),

    /// Indicates that the `EventLoop` should shut down, as Alacritty is shutting down
    Shutdown
}

/// The main event!.. loop.
///
/// Handles all the pty I/O and runs the pty parser which updates terminal
/// state.
pub struct EventLoop<Io> {
    poll: mio::Poll,
    pty: Io,
    rx: mio::channel::Receiver<Msg>,
    tx: mio::channel::Sender<Msg>,
    terminal: Arc<FairMutex<Term>>,
    display: display::Notifier,
    ref_test: bool,
}

/// Helper type which tracks how much of a buffer has been written.
struct Writing {
    source: Cow<'static, [u8]>,
    written: usize,
}

/// Indicates the result of draining the mio channel
#[derive(Debug)]
enum DrainResult {
    /// At least one new item was received
    ReceivedItem,
    /// Nothing was available to receive
    Empty,
    /// A shutdown message was received
    Shutdown
}

impl DrainResult {
    pub fn is_shutdown(&self) -> bool {
        match *self {
            DrainResult::Shutdown => true,
            _ => false
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            DrainResult::Empty => true,
            _ => false
        }
    }
}

/// All of the mutable state needed to run the event loop
///
/// Contains list of items to write, current write state, etc. Anything that
/// would otherwise be mutated on the `EventLoop` goes here.
pub struct State {
    write_list: VecDeque<Cow<'static, [u8]>>,
    writing: Option<Writing>,
    parser: ansi::Processor,
}

pub struct Notifier(pub ::mio::channel::Sender<Msg>);

impl event::Notify for Notifier {
    fn notify<B>(&mut self, bytes: B)
        where B: Into<Cow<'static, [u8]>>
    {
        let bytes = bytes.into();
        // terminal hangs if we send 0 bytes through.
        if bytes.len() == 0 {
            return
        }
        match self.0.send(Msg::Input(bytes)) {
            Ok(_) => (),
            Err(_) => panic!("expected send event loop msg"),
        }
    }
}

impl Default for State {
    fn default() -> State {
        State {
            write_list: VecDeque::new(),
            parser: ansi::Processor::new(),
            writing: None,
        }
    }
}

impl State {
    #[inline]
    fn ensure_next(&mut self) {
        if self.writing.is_none() {
            self.goto_next();
        }
    }

    #[inline]
    fn goto_next(&mut self) {
        self.writing = self.write_list
            .pop_front()
            .map(Writing::new);
    }

    #[inline]
    fn take_current(&mut self) -> Option<Writing> {
        self.writing.take()
    }

    #[inline]
    fn needs_write(&self) -> bool {
        self.writing.is_some() || !self.write_list.is_empty()
    }

    #[inline]
    fn set_current(&mut self, new: Option<Writing>) {
        self.writing = new;
    }
}

impl Writing {
    #[inline]
    fn new(c: Cow<'static, [u8]>) -> Writing {
        Writing { source: c, written: 0 }
    }

    #[inline]
    fn advance(&mut self, n: usize) {
        self.written += n;
    }

    #[inline]
    fn remaining_bytes(&self) -> &[u8] {
        &self.source[self.written..]
    }

    #[inline]
    fn finished(&self) -> bool {
        self.written >= self.source.len()
    }
}

/// `mio::Token` for the event loop channel
const CHANNEL: mio::Token = mio::Token(0);

/// `mio::Token` for the pty file descriptor
const PTY: mio::Token = mio::Token(1);

impl<Io> EventLoop<Io>
    where Io: io::Read + io::Write + Send + AsRawFd + 'static
{
    /// Create a new event loop
    pub fn new(
        terminal: Arc<FairMutex<Term>>,
        display: display::Notifier,
        pty: Io,
        ref_test: bool,
    ) -> EventLoop<Io> {
        let (tx, rx) = ::mio::channel::channel();
        EventLoop {
            poll: mio::Poll::new().expect("create mio Poll"),
            pty: pty,
            tx: tx,
            rx: rx,
            terminal: terminal,
            display: display,
            ref_test: ref_test,
        }
    }

    pub fn channel(&self) -> mio::channel::Sender<Msg> {
        self.tx.clone()
    }

    // Drain the channel
    //
    // Returns a `DrainResult` indicating the result of receiving from the channe;
    //
    fn drain_recv_channel(&self, state: &mut State) -> DrainResult {
        let mut received_item = false;
        while let Ok(msg) = self.rx.try_recv() {
            received_item = true;
            match msg {
                Msg::Input(input) => {
                    state.write_list.push_back(input);
                },
                Msg::Shutdown => {
                    return DrainResult::Shutdown;
                }
            }
        }

        if received_item {
            DrainResult::ReceivedItem
        } else {
            DrainResult::Empty
        }
    }

    // Returns a `bool` indicating whether or not the event loop should continue running
    #[inline]
    fn channel_event(&mut self, state: &mut State) -> bool {
        if self.drain_recv_channel(state).is_shutdown() {
            return false;
        }

        self.poll.reregister(
            &self.rx, CHANNEL,
            Ready::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).expect("reregister channel");

        if state.needs_write() {
            self.poll.reregister(
                &EventedFd(&self.pty.as_raw_fd()),
                PTY,
                Ready::readable() | Ready::writable(),
                PollOpt::edge() | PollOpt::oneshot()
            ).expect("reregister fd after channel recv");
        }

        true
    }

    #[inline]
    fn pty_read<W>(
        &mut self,
        state: &mut State,
        buf: &mut [u8],
        mut writer: Option<&mut W>
    ) -> io::Result<()>
        where W: Write
    {
        loop {
            match self.pty.read(&mut buf[..]) {
                Ok(0) => break,
                Ok(got) => {
                    writer = writer.map(|w| {
                        w.write_all(&buf[..got]).unwrap(); w
                    });

                    let mut terminal = self.terminal.lock();
                    for byte in &buf[..got] {
                        state.parser.advance(&mut *terminal, *byte, &mut self.pty);
                    }

                    // Only request a draw if one hasn't already been requested.
                    //
                    // This is a performance optimization even if only for X11
                    // which is very expensive to hammer on the even loop wakeup
                    if !terminal.dirty {
                        self.display.notify();
                        terminal.dirty = true;

                        // Break for writing
                        //
                        // Want to prevent case where reading always returns
                        // data and sequences like `C-c` cannot be sent.
                        //
                        // Doing this check in !terminal.dirty will prevent the
                        // condition from being checked overzealously.
                        //
                        // Break if `drain_recv_channel` signals there is work to do or
                        // shutting down.
                        if state.writing.is_some()
                            || !state.write_list.is_empty()
                            || !self.drain_recv_channel(state).is_empty()
                        {
                            break;
                        }
                    }
                },
                Err(err) => {
                    match err.kind() {
                        ErrorKind::Interrupted |
                        ErrorKind::WouldBlock => break,
                        _ => return Err(err),
                    }
                }
            }
        }

        Ok(())
    }

    #[inline]
    fn pty_write(&mut self, state: &mut State) -> io::Result<()> {
        state.ensure_next();

        'write_many: while let Some(mut current) = state.take_current() {
            'write_one: loop {
                match self.pty.write(current.remaining_bytes()) {
                    Ok(0) => {
                        state.set_current(Some(current));
                        break 'write_many;
                    },
                    Ok(n) => {
                        current.advance(n);
                        if current.finished() {
                            state.goto_next();
                            break 'write_one;
                        }
                    },
                    Err(err) => {
                        state.set_current(Some(current));
                        match err.kind() {
                            ErrorKind::Interrupted |
                            ErrorKind::WouldBlock => break 'write_many,
                            _ => return Err(err),
                        }
                    }
                }

            }
        }

        Ok(())
    }

    pub fn spawn(
        mut self,
        state: Option<State>
    ) -> thread::JoinHandle<(EventLoop<Io>, State)> {
        thread::spawn_named("pty reader", move || {
            let mut state = state.unwrap_or_else(Default::default);
            let mut buf = [0u8; 4096];

            let fd = self.pty.as_raw_fd();
            let fd = EventedFd(&fd);

            let poll_opts = PollOpt::edge() | PollOpt::oneshot();

            self.poll.register(&self.rx, CHANNEL, Ready::readable(), poll_opts).unwrap();
            self.poll.register(&fd, PTY, Ready::readable(), poll_opts).unwrap();

            let mut events = Events::with_capacity(1024);

            let mut pipe = if self.ref_test {
                let file = File::create("./alacritty.recording")
                    .expect("create alacritty recording");
                Some(file)
            } else {
                None
            };

            'event_loop: loop {
                if let Err(err) = self.poll.poll(&mut events, None) {
                    match err.kind() {
                        ErrorKind::Interrupted => continue,
                        _ => panic!("EventLoop polling error: {:?}", err)
                    }
                }

                for event in events.iter() {
                    match event.token() {
                        CHANNEL =>  {
                            if !self.channel_event(&mut state) {
                                break 'event_loop;
                            }
                        },
                        PTY => {
                            let kind = event.kind();

                            if kind.is_hup() {
                                break 'event_loop;
                            }

                            if kind.is_readable() {
                                if let Err(err) = self.pty_read(&mut state, &mut buf, pipe.as_mut()) {
                                    error!("Event loop exitting due to error: {} [{}:{}]",
                                           err, file!(), line!());
                                    break 'event_loop;
                                }

                                if ::tty::process_should_exit() {
                                    break 'event_loop;
                                }
                            }

                            if kind.is_writable() {
                                if let Err(err) = self.pty_write(&mut state) {
                                    error!("Event loop exitting due to error: {} [{}:{}]",
                                           err, file!(), line!());
                                    break 'event_loop;
                                }
                            }

                            // Figure out pty interest
                            let mut interest = Ready::readable();
                            if state.needs_write() {
                                interest.insert(Ready::writable());
                            }

                            // Reregister pty
                            self.poll
                                .reregister(&fd, PTY, interest, poll_opts)
                                .expect("register fd after read/write");
                        },
                        _ => (),
                    }
                }
            }

            let _ = self.poll.deregister(&self.rx);
            let _ = self.poll.deregister(&fd);

            (self, state)
        })
    }
}
<commit_msg>Read more from pty<commit_after>//! The main event loop which performs I/O on the pseudoterminal
use std::borrow::Cow;
use std::collections::VecDeque;
use std::io::{self, ErrorKind, Write};
use std::fs::File;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use mio::{self, Events, PollOpt, Ready};
use mio::unix::EventedFd;

use ansi;
use display;
use event;
use term::Term;
use util::thread;
use sync::FairMutex;

/// Messages that may be sent to the `EventLoop`
#[derive(Debug)]
pub enum Msg {
    /// Data that should be written to the pty
    Input(Cow<'static, [u8]>),

    /// Indicates that the `EventLoop` should shut down, as Alacritty is shutting down
    Shutdown
}

/// The main event!.. loop.
///
/// Handles all the pty I/O and runs the pty parser which updates terminal
/// state.
pub struct EventLoop<Io> {
    poll: mio::Poll,
    pty: Io,
    rx: mio::channel::Receiver<Msg>,
    tx: mio::channel::Sender<Msg>,
    terminal: Arc<FairMutex<Term>>,
    display: display::Notifier,
    ref_test: bool,
}

/// Helper type which tracks how much of a buffer has been written.
struct Writing {
    source: Cow<'static, [u8]>,
    written: usize,
}

/// Indicates the result of draining the mio channel
#[derive(Debug)]
enum DrainResult {
    /// At least one new item was received
    ReceivedItem,
    /// Nothing was available to receive
    Empty,
    /// A shutdown message was received
    Shutdown
}

impl DrainResult {
    pub fn is_shutdown(&self) -> bool {
        match *self {
            DrainResult::Shutdown => true,
            _ => false
        }
    }
}

/// All of the mutable state needed to run the event loop
///
/// Contains list of items to write, current write state, etc. Anything that
/// would otherwise be mutated on the `EventLoop` goes here.
pub struct State {
    write_list: VecDeque<Cow<'static, [u8]>>,
    writing: Option<Writing>,
    parser: ansi::Processor,
}

pub struct Notifier(pub ::mio::channel::Sender<Msg>);

impl event::Notify for Notifier {
    fn notify<B>(&mut self, bytes: B)
        where B: Into<Cow<'static, [u8]>>
    {
        let bytes = bytes.into();
        // terminal hangs if we send 0 bytes through.
        if bytes.len() == 0 {
            return
        }
        match self.0.send(Msg::Input(bytes)) {
            Ok(_) => (),
            Err(_) => panic!("expected send event loop msg"),
        }
    }
}

impl Default for State {
    fn default() -> State {
        State {
            write_list: VecDeque::new(),
            parser: ansi::Processor::new(),
            writing: None,
        }
    }
}

impl State {
    #[inline]
    fn ensure_next(&mut self) {
        if self.writing.is_none() {
            self.goto_next();
        }
    }

    #[inline]
    fn goto_next(&mut self) {
        self.writing = self.write_list
            .pop_front()
            .map(Writing::new);
    }

    #[inline]
    fn take_current(&mut self) -> Option<Writing> {
        self.writing.take()
    }

    #[inline]
    fn needs_write(&self) -> bool {
        self.writing.is_some() || !self.write_list.is_empty()
    }

    #[inline]
    fn set_current(&mut self, new: Option<Writing>) {
        self.writing = new;
    }
}

impl Writing {
    #[inline]
    fn new(c: Cow<'static, [u8]>) -> Writing {
        Writing { source: c, written: 0 }
    }

    #[inline]
    fn advance(&mut self, n: usize) {
        self.written += n;
    }

    #[inline]
    fn remaining_bytes(&self) -> &[u8] {
        &self.source[self.written..]
    }

    #[inline]
    fn finished(&self) -> bool {
        self.written >= self.source.len()
    }
}

/// `mio::Token` for the event loop channel
const CHANNEL: mio::Token = mio::Token(0);

/// `mio::Token` for the pty file descriptor
const PTY: mio::Token = mio::Token(1);

impl<Io> EventLoop<Io>
    where Io: io::Read + io::Write + Send + AsRawFd + 'static
{
    /// Create a new event loop
    pub fn new(
        terminal: Arc<FairMutex<Term>>,
        display: display::Notifier,
        pty: Io,
        ref_test: bool,
    ) -> EventLoop<Io> {
        let (tx, rx) = ::mio::channel::channel();
        EventLoop {
            poll: mio::Poll::new().expect("create mio Poll"),
            pty: pty,
            tx: tx,
            rx: rx,
            terminal: terminal,
            display: display,
            ref_test: ref_test,
        }
    }

    pub fn channel(&self) -> mio::channel::Sender<Msg> {
        self.tx.clone()
    }

    // Drain the channel
    //
    // Returns a `DrainResult` indicating the result of receiving from the channe;
    //
    fn drain_recv_channel(&self, state: &mut State) -> DrainResult {
        let mut received_item = false;
        while let Ok(msg) = self.rx.try_recv() {
            received_item = true;
            match msg {
                Msg::Input(input) => {
                    state.write_list.push_back(input);
                },
                Msg::Shutdown => {
                    return DrainResult::Shutdown;
                }
            }
        }

        if received_item {
            DrainResult::ReceivedItem
        } else {
            DrainResult::Empty
        }
    }

    // Returns a `bool` indicating whether or not the event loop should continue running
    #[inline]
    fn channel_event(&mut self, state: &mut State) -> bool {
        if self.drain_recv_channel(state).is_shutdown() {
            return false;
        }

        self.poll.reregister(
            &self.rx, CHANNEL,
            Ready::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).expect("reregister channel");

        if state.needs_write() {
            self.poll.reregister(
                &EventedFd(&self.pty.as_raw_fd()),
                PTY,
                Ready::readable() | Ready::writable(),
                PollOpt::edge() | PollOpt::oneshot()
            ).expect("reregister fd after channel recv");
        }

        true
    }

    #[inline]
    fn pty_read<W>(
        &mut self,
        state: &mut State,
        buf: &mut [u8],
        mut writer: Option<&mut W>
    ) -> io::Result<()>
        where W: Write
    {
        const MAX_READ: usize = 65_536;
        let mut processed = 0;
        let mut terminal = None;

        loop {
            match self.pty.read(&mut buf[..]) {
                Ok(0) => break,
                Ok(got) => {
                    // Record bytes read; used to limit time spent in pty_read.
                    processed += got;

                    // Send a copy of bytes read to a subscriber. Used for
                    // example with ref test recording.
                    writer = writer.map(|w| {
                        w.write_all(&buf[..got]).unwrap();
                        w
                    });

                    // Get reference to terminal. Lock is acquired on initial
                    // iteration and held until there's no bytes left to parse
                    // or we've reached MAX_READ.
                    if terminal.is_none() {
                        terminal = Some(self.terminal.lock());
                    }
                    let terminal = terminal.as_mut().unwrap();

                    // Run the parser
                    for byte in &buf[..got] {
                        state.parser.advance(&mut **terminal, *byte, &mut self.pty);
                    }

                    // Exit if we've processed enough bytes
                    if processed > MAX_READ {
                        break;
                    }
                },
                Err(err) => {
                    match err.kind() {
                        ErrorKind::Interrupted |
                        ErrorKind::WouldBlock => {
                            break;
                        },
                        _ => return Err(err),
                    }
                }
            }
        }

        // Only request a draw if one hasn't already been requested.
        if let Some(mut terminal) = terminal {
            if !terminal.dirty {
                self.display.notify();
                terminal.dirty = true;
            }
        }

        Ok(())
    }

    #[inline]
    fn pty_write(&mut self, state: &mut State) -> io::Result<()> {
        state.ensure_next();

        'write_many: while let Some(mut current) = state.take_current() {
            'write_one: loop {
                match self.pty.write(current.remaining_bytes()) {
                    Ok(0) => {
                        state.set_current(Some(current));
                        break 'write_many;
                    },
                    Ok(n) => {
                        current.advance(n);
                        if current.finished() {
                            state.goto_next();
                            break 'write_one;
                        }
                    },
                    Err(err) => {
                        state.set_current(Some(current));
                        match err.kind() {
                            ErrorKind::Interrupted |
                            ErrorKind::WouldBlock => break 'write_many,
                            _ => return Err(err),
                        }
                    }
                }

            }
        }

        Ok(())
    }

    pub fn spawn(
        mut self,
        state: Option<State>
    ) -> thread::JoinHandle<(EventLoop<Io>, State)> {
        thread::spawn_named("pty reader", move || {
            let mut state = state.unwrap_or_else(Default::default);
            let mut buf = [0u8; 4096];

            let fd = self.pty.as_raw_fd();
            let fd = EventedFd(&fd);

            let poll_opts = PollOpt::edge() | PollOpt::oneshot();

            self.poll.register(&self.rx, CHANNEL, Ready::readable(), poll_opts).unwrap();
            self.poll.register(&fd, PTY, Ready::readable(), poll_opts).unwrap();

            let mut events = Events::with_capacity(1024);

            let mut pipe = if self.ref_test {
                let file = File::create("./alacritty.recording")
                    .expect("create alacritty recording");
                Some(file)
            } else {
                None
            };

            'event_loop: loop {
                if let Err(err) = self.poll.poll(&mut events, None) {
                    match err.kind() {
                        ErrorKind::Interrupted => continue,
                        _ => panic!("EventLoop polling error: {:?}", err)
                    }
                }

                for event in events.iter() {
                    match event.token() {
                        CHANNEL =>  {
                            if !self.channel_event(&mut state) {
                                break 'event_loop;
                            }
                        },
                        PTY => {
                            let kind = event.kind();

                            if kind.is_hup() {
                                break 'event_loop;
                            }

                            if kind.is_readable() {
                                if let Err(err) = self.pty_read(&mut state, &mut buf, pipe.as_mut()) {
                                    error!("Event loop exitting due to error: {} [{}:{}]",
                                           err, file!(), line!());
                                    break 'event_loop;
                                }

                                if ::tty::process_should_exit() {
                                    break 'event_loop;
                                }
                            }

                            if kind.is_writable() {
                                if let Err(err) = self.pty_write(&mut state) {
                                    error!("Event loop exitting due to error: {} [{}:{}]",
                                           err, file!(), line!());
                                    break 'event_loop;
                                }
                            }

                            // Figure out pty interest
                            let mut interest = Ready::readable();
                            if state.needs_write() {
                                interest.insert(Ready::writable());
                            }

                            // Reregister pty
                            self.poll
                                .reregister(&fd, PTY, interest, poll_opts)
                                .expect("register fd after read/write");
                        },
                        _ => (),
                    }
                }
            }

            let _ = self.poll.deregister(&self.rx);
            let _ = self.poll.deregister(&fd);

            (self, state)
        })
    }
}
<|endoftext|>


<commit_before>use syntect::dumps::from_binary;
use syntect::parsing::SyntaxSet;
use syntect::highlighting::ThemeSet;

thread_local!{
    pub static SYNTAX_SET: SyntaxSet = {
        let mut ss: SyntaxSet = from_binary(include_bytes!("../../../sublime_syntaxes/newlines.packdump"));
        ss.link_syntaxes();
        ss
    };
}

lazy_static!{
    pub static ref THEME_SET: ThemeSet = from_binary(include_bytes!("../../../sublime_themes/all.themedump"));
}

<commit_msg>Remove unused file<commit_after><|endoftext|>


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

use capnp::message::ReaderOptions;

pub type VatId = ::rpc_twoparty_capnp::Side;

pub struct IncomingMessage {
    message: ::capnp::message::Reader<::capnp_gj::serialize::OwnedSegments>,
}

impl ::IncomingMessage for IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>> {
        self.message.get_root()
    }
}

pub struct OutgoingMessage {
    message: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
}

impl ::OutgoingMessage for OutgoingMessage {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>> {
        self.message.get_root()
    }

    fn send(self) {
        unimplemented!()
    }
}

pub struct Connection<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    input_stream: T,
    output_stream: U,
    receive_options: ReaderOptions,
}

impl <T, U> Connection<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    pub fn new(input_stream: T, output_stream: U, receive_options: ReaderOptions) -> Connection<T, U> {
        Connection { input_stream: input_stream, output_stream: output_stream,
                     receive_options: receive_options }
    }
}

impl <T, U> ::Connection<VatId> for Connection<T, U>
    where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite
{
    fn get_peer_vat_id(&self) -> VatId {
        unimplemented!()
    }

    fn new_outgoing_message(&mut self) -> Box<::OutgoingMessage> {
        unimplemented!()
    }

    fn receive_incoming_message(&mut self) -> ::gj::Promise<Option<Box<::IncomingMessage>>, ::capnp::Error> {
        self.receive_options;
        unimplemented!()
    }

    fn shutdown(&mut self) {
        unimplemented!()
    }
}

// How should this work? I make a two party rpc system by passing in an AsyncStream.
pub struct TwoPartyVatNetwork<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    _connection: Option<Connection<T,U>>,
}

impl <T, U> TwoPartyVatNetwork<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    pub fn new(input_stream: T, output_stream: U, receive_options: ReaderOptions) -> TwoPartyVatNetwork<T, U> {
        TwoPartyVatNetwork { _connection: Some(Connection::new(input_stream, output_stream, receive_options)) }
    }
}

impl <T, U> ::VatNetwork<VatId> for TwoPartyVatNetwork<T, U>
    where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite
{
    fn connect(&mut self, _host_id: VatId) -> Option<Box<::Connection<VatId>>> {
        unimplemented!()
    }

    fn accept(&mut self) -> ::gj::Promise<Box<::Connection<VatId>>, ::capnp::Error> {
        unimplemented!()
    }
}
<commit_msg>read and write messages<commit_after>// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::message::ReaderOptions;

use std::cell::RefCell;
use std::rc::Rc;

pub type VatId = ::rpc_twoparty_capnp::Side;

pub struct IncomingMessage {
    message: ::capnp::message::Reader<::capnp_gj::serialize::OwnedSegments>,
}

impl IncomingMessage {
    pub fn new(message: ::capnp::message::Reader<::capnp_gj::serialize::OwnedSegments>) -> IncomingMessage {
        IncomingMessage { message: message }
    }
}

impl ::IncomingMessage for IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>> {
        self.message.get_root()
    }
}

pub struct OutgoingMessage<U> where U: ::gj::io::AsyncWrite {
    message: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
    write_queue: Rc<RefCell<::gj::Promise<U, ::capnp::Error>>>,
}

impl <U> ::OutgoingMessage for OutgoingMessage<U> where U: ::gj::io::AsyncWrite {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>> {
        self.message.get_root()
    }

    fn send(self) {
        let OutgoingMessage {message, write_queue} = self;
        let queue = ::std::mem::replace(&mut *write_queue.borrow_mut(), ::gj::Promise::never_done());
        *write_queue.borrow_mut() = queue.then(move |s| {
            Ok(::capnp_gj::serialize::write_message(s, message).map(move |(s, _)| {
                Ok(s)
            }))
        });
    }
}

pub struct Connection<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    input_stream: Rc<RefCell<Option<T>>>,
    write_queue: Rc<RefCell<::gj::Promise<U, ::capnp::Error>>>,
    receive_options: ReaderOptions,
}

impl <T, U> Connection<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    pub fn new(input_stream: T, output_stream: U, receive_options: ReaderOptions) -> Connection<T, U> {
        Connection { input_stream: Rc::new(RefCell::new(Some(input_stream))),
                     write_queue: Rc::new(RefCell::new(::gj::Promise::fulfilled(output_stream))),
                     receive_options: receive_options }
    }
}

impl <T, U> ::Connection<VatId> for Connection<T, U>
    where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite
{
    fn get_peer_vat_id(&self) -> VatId {
        unimplemented!()
    }

    fn new_outgoing_message(&mut self) -> Box<::OutgoingMessage> {
        Box::new(OutgoingMessage {
            message: ::capnp::message::Builder::new_default(),
            write_queue: self.write_queue.clone()
        })
    }

    fn receive_incoming_message(&mut self) -> ::gj::Promise<Option<Box<::IncomingMessage>>, ::capnp::Error> {
        self.receive_options;
        let maybe_input_stream = ::std::mem::replace(&mut *self.input_stream.borrow_mut(), None);
        let return_it_here = self.input_stream.clone();
        match maybe_input_stream {
            Some(s) => {
                ::capnp_gj::serialize::try_read_message(s, self.receive_options).map(move |(s, maybe_message)| {
                    *return_it_here.borrow_mut() = Some(s);
                    Ok(maybe_message.map(|message|
                                         Box::new(IncomingMessage::new(message)) as Box<::IncomingMessage>))
                })
            }
            None => panic!(),
        }
    }

    fn shutdown(&mut self) {
        unimplemented!()
    }
}

pub struct TwoPartyVatNetwork<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    connection: Option<Connection<T,U>>,
}

impl <T, U> TwoPartyVatNetwork<T, U> where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite {
    pub fn new(input_stream: T, output_stream: U, receive_options: ReaderOptions) -> TwoPartyVatNetwork<T, U> {
        TwoPartyVatNetwork { connection: Some(Connection::new(input_stream, output_stream, receive_options)) }
    }
}

impl <T, U> ::VatNetwork<VatId> for TwoPartyVatNetwork<T, U>
    where T: ::gj::io::AsyncRead, U: ::gj::io::AsyncWrite
{
    fn connect(&mut self, _host_id: VatId) -> Option<Box<::Connection<VatId>>> {
        let connection = ::std::mem::replace(&mut self.connection, None);
        connection.map(|c| Box::new(c) as Box<::Connection<VatId>>)
    }

    fn accept(&mut self) -> ::gj::Promise<Box<::Connection<VatId>>, ::capnp::Error> {
        let connection = ::std::mem::replace(&mut self.connection, None);
        match connection {
            Some(c) => ::gj::Promise::fulfilled(Box::new(c) as Box<::Connection<VatId>>),
            None => unimplemented!(),
        }
    }
}
<|endoftext|>