<commit_before>use services::{ AdapterId, Service, ServiceId, ChannelKind, Channel, Getter, Setter, TagId };
use util::{ Exactly, Id };
use values::Duration;

use std::cmp;
use std::hash::Hash;
use std::collections::HashSet;

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

fn merge<T>(mut a: HashSet<T>, b: Vec<T>) -> HashSet<T> where T: Hash + Eq {
    for x in b {
        a.insert(x);
    }
    a
}

pub trait SelectedBy<T> {
    fn matches(&self, &T) -> bool;
}

/// A trait used to let ServiceSelector work on complex data structures
/// that are not necessarily exactly Selector.
pub trait ServiceLike {
    fn id(&self) -> &Id<ServiceId>;
    fn tags(&self) -> &HashSet<Id<TagId>>;
    fn adapter(&self) -> &Id<AdapterId>;
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool;
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool;
}

impl ServiceLike for Service {
    fn id(&self) -> &Id<ServiceId> {
        &self.id
    }
    fn tags(&self) -> &HashSet<Id<TagId>> {
        &self.tags
    }
    fn adapter(&self) -> &Id<AdapterId> {
        &self.adapter
    }
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool {
        for chan in self.getters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool {
        for chan in self.setters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }

}

/// A selector for one or more services.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::services::*;
/// use foxbox_taxonomy::util::Id;
///
/// let selector = ServiceSelector::new()
///   .with_tags(vec![Id::<TagId>::new("entrance")])
///   .with_getters(vec![GetterSelector::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ServiceSelector {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<ServiceId>>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

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

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

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

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

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

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

    /// Restrict results to services that have all the getters in `getters`.
    pub fn with_getters(mut self, mut getters: Vec<GetterSelector>) -> Self {
        ServiceSelector {
            getters: {self.getters.append(&mut getters); self.getters},
            .. self
        }
    }

    /// Restrict results to services that have all the setters in `setters`.
    pub fn with_setters(mut self, mut setters: Vec<SetterSelector>) -> Self {
        ServiceSelector {
            setters: {self.setters.append(&mut setters); self.setters},
            .. self
        }
    }

    /// Restrict results to services that are accepted by two selector.
    pub fn and(mut self, mut other: ServiceSelector) -> Self {
        ServiceSelector {
            id: self.id.and(other.id),
            tags: self.tags.union(&other.tags).cloned().collect(),
            getters: {self.getters.append(&mut other.getters); self.getters},
            setters: {self.setters.append(&mut other.setters); self.setters},
            private: (),
        }
    }

    pub fn matches<T>(&self, service: &T) -> bool
        where T: ServiceLike
    {
        if !self.id.matches(service.id()) {
            return false;
        }
        if !has_selected_tags(&self.tags, service.tags()) {
            return false;
        }
        // If any of the getter selectors doesn't find a getter,
        // we don't match.
        let getters_fail = self.getters.iter().find(|selector| {
            !service.has_getters(|channel| {
                selector.matches(channel)
            })
        }).is_some();
        if getters_fail {
            return false;
        }
        // If any of the setter selectors doesn't find a setter,
        // we don't match.
        let setters_fail = self.setters.iter().find(|selector| {
            !service.has_setters(|channel| {
                selector.matches(channel)
            })
        }).is_some();
        if setters_fail {
            return false;
        }
        true
    }
}

impl SelectedBy<ServiceSelector> for Service {
    fn matches(&self, selector: &ServiceSelector) -> bool {
        selector.matches(self)
    }
}

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

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

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

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

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

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

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

    /// Restrict to a channel with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        GetterSelector {
            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<Id<TagId>>) -> Self {
        GetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        GetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

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

impl SelectedBy<GetterSelector> for Channel<Getter> {
    fn matches(&self, selector: &GetterSelector) -> bool {
        selector.matches(self)
    }
}

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

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

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

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

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

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

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

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

    /// Selector to channels with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        SetterSelector {
            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<Id<TagId>>) -> Self {
        SetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict results to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        SetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

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

impl SelectedBy<SetterSelector> for Channel<Setter> {
    fn matches(&self, selector: &SetterSelector) -> bool {
        selector.matches(self)
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<Duration>,
    #[serde(default)]
    pub max: Option<Duration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x) |
            (x, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, 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, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &Duration) -> 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;
            }
        }
        true
    }

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

fn has_selected_tags(actual: &HashSet<Id<TagId>>, requested: &HashSet<Id<TagId>>) -> bool {
    for tag in &*actual {
        if !requested.contains(tag) {
            return false;
        }
    }
    true
}
<commit_msg>Implementing match by service_tags<commit_after>use services::{ AdapterId, Service, ServiceId, ChannelKind, Channel, Getter, Setter, TagId };
use util::{ Exactly, Id };
use values::Duration;

use std::cmp;
use std::hash::Hash;
use std::collections::HashSet;

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

fn merge<T>(mut a: HashSet<T>, b: Vec<T>) -> HashSet<T> where T: Hash + Eq {
    for x in b {
        a.insert(x);
    }
    a
}

pub trait SelectedBy<T> {
    fn matches(&self, &T) -> bool;
}

/// A trait used to let ServiceSelector work on complex data structures
/// that are not necessarily exactly Selector.
pub trait ServiceLike {
    fn id(&self) -> &Id<ServiceId>;
    fn tags(&self) -> &HashSet<Id<TagId>>;
    fn adapter(&self) -> &Id<AdapterId>;
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool;
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool;
}

impl ServiceLike for Service {
    fn id(&self) -> &Id<ServiceId> {
        &self.id
    }
    fn tags(&self) -> &HashSet<Id<TagId>> {
        &self.tags
    }
    fn adapter(&self) -> &Id<AdapterId> {
        &self.adapter
    }
    fn has_getters<F>(&self, f: F) -> bool where F: Fn(&Channel<Getter>) -> bool {
        for chan in self.getters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }
    fn has_setters<F>(&self, f: F) -> bool where F: Fn(&Channel<Setter>) -> bool {
        for chan in self.setters.values() {
            if f(chan) {
                return true;
            }
        }
        false
    }

}

/// A selector for one or more services.
///
///
/// # Example
///
/// ```
/// use foxbox_taxonomy::selector::*;
/// use foxbox_taxonomy::services::*;
/// use foxbox_taxonomy::util::Id;
///
/// let selector = ServiceSelector::new()
///   .with_tags(vec![Id::<TagId>::new("entrance")])
///   .with_getters(vec![GetterSelector::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ServiceSelector {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<Id<ServiceId>>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: HashSet<Id<TagId>>,

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

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

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

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

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

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

    /// Restrict results to services that have all the getters in `getters`.
    pub fn with_getters(mut self, mut getters: Vec<GetterSelector>) -> Self {
        ServiceSelector {
            getters: {self.getters.append(&mut getters); self.getters},
            .. self
        }
    }

    /// Restrict results to services that have all the setters in `setters`.
    pub fn with_setters(mut self, mut setters: Vec<SetterSelector>) -> Self {
        ServiceSelector {
            setters: {self.setters.append(&mut setters); self.setters},
            .. self
        }
    }

    /// Restrict results to services that are accepted by two selector.
    pub fn and(mut self, mut other: ServiceSelector) -> Self {
        ServiceSelector {
            id: self.id.and(other.id),
            tags: self.tags.union(&other.tags).cloned().collect(),
            getters: {self.getters.append(&mut other.getters); self.getters},
            setters: {self.setters.append(&mut other.setters); self.setters},
            private: (),
        }
    }

    pub fn matches<T>(&self, service: &T) -> bool
        where T: ServiceLike
    {
        if !self.id.matches(service.id()) {
            return false;
        }
        if !has_selected_tags(&self.tags, service.tags()) {
            return false;
        }
        // If any of the getter selectors doesn't find a getter,
        // we don't match.
        let getters_fail = self.getters.iter().find(|selector| {
            !service.has_getters(|channel| {
                selector.matches(&self.tags, channel)
            })
        }).is_some();
        if getters_fail {
            return false;
        }
        // If any of the setter selectors doesn't find a setter,
        // we don't match.
        let setters_fail = self.setters.iter().find(|selector| {
            !service.has_setters(|channel| {
                selector.matches(&self.tags, channel)
            })
        }).is_some();
        if setters_fail {
            return false;
        }
        true
    }
}

impl SelectedBy<ServiceSelector> for Service {
    fn matches(&self, selector: &ServiceSelector) -> bool {
        selector.matches(self)
    }
}

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

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

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

    ///  Restrict results to channels offered by a service that has all the tags in `tags`.
    #[serde(default)]
    pub service_tags: HashSet<Id<TagId>>,

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

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

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

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

    /// Restrict to a channel with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        GetterSelector {
            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<Id<TagId>>) -> Self {
        GetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    ///  Restrict to channels offered by a service that has all the tags in `tags`.
    pub fn with_service_tags(self, tags: Vec<Id<TagId>>) -> Self {
        GetterSelector {
            service_tags: merge(self.service_tags, tags),
            .. self
        }
    }

    /// Restrict to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        GetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            service_tags: self.service_tags.union(&other.service_tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, service_tags: &HashSet<Id<TagId>>, channel: &Channel<Getter>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.service) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        if !has_selected_tags(&self.service_tags, service_tags) {
            return false;
        }
        true
    }
}

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

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

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

    ///  Restrict results to channels offered by a service that has all the tags in `tags`.
    #[serde(default)]
    pub service_tags: HashSet<Id<TagId>>,

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

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

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

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

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

    /// Selector to channels with a specific kind.
    pub fn with_kind(self, kind: ChannelKind) -> Self {
        SetterSelector {
            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<Id<TagId>>) -> Self {
        SetterSelector {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    ///  Restrict to channels offered by a service that has all the tags in `tags`.
    pub fn with_service_tags(self, tags: Vec<Id<TagId>>) -> Self {
        SetterSelector {
            service_tags: merge(self.service_tags, tags),
            .. self
        }
    }

    /// Restrict results to channels that are accepted by two selector.
    pub fn and(self, other: Self) -> Self {
        SetterSelector {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: self.tags.union(&other.tags).cloned().collect(),
            service_tags: self.service_tags.union(&other.service_tags).cloned().collect(),
            kind: self.kind.and(other.kind),
            private: (),
        }
    }

    /// Determine if a channel is matched by this selector.
    pub fn matches(&self, service_tags: &HashSet<Id<TagId>>, channel: &Channel<Setter>) -> bool {
        if !self.id.matches(&channel.id) {
            return false;
        }
        if !self.parent.matches(&channel.service) {
            return false;
        }
        if !self.kind.matches(&channel.mechanism.kind) {
            return false;
        }
        if !has_selected_tags(&self.tags, &channel.tags) {
            return false;
        }
        if !has_selected_tags(&self.service_tags, service_tags) {
            return false;
        }
        true
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<Duration>,
    #[serde(default)]
    pub max: Option<Duration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x) |
            (x, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, 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, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &Duration) -> 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;
            }
        }
        true
    }

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

fn has_selected_tags(actual: &HashSet<Id<TagId>>, requested: &HashSet<Id<TagId>>) -> bool {
    for tag in &*actual {
        if !requested.contains(tag) {
            return false;
        }
    }
    true
}
<|endoftext|>


<commit_before>use std::string::String;

use super::sql::*;
use super::rel::*;
use super::schema::*;

pub struct SqlToRel {
    default_schema: Option<String>
}

impl SqlToRel {

    pub fn new() -> Self {
        SqlToRel { default_schema: None }
    }

    pub fn sql_to_rel(&self, sql: &ASTNode, tt: &TupleType) -> Result<Box<Rel>, String> {
        match sql {
            &ASTNode::SQLSelect { ref projection, ref relation, .. } => {

                let expr : Vec<Rex> = projection.iter()
                    .map(|e| self.sql_to_rex(&e, tt) )
                    .collect::<Result<Vec<Rex>,String>>()?;

                let input = match relation {
                    &Some(ref r) => Some(self.sql_to_rel(r, tt)?),
                    &None => None
                };

                Ok(Box::new(Rel::Projection {
                    expr: expr,
                    input: input
                }))
            },

            _ => Err(format!("sql_to_rel does not support this relation: {:?}", sql))
        }
    }

    pub fn sql_to_rex(&self, sql: &ASTNode, tt: &TupleType) -> Result<Rex, String> {
        match sql {
            &ASTNode::SQLIdentifier { ref id, .. } => {
                match tt.columns.iter().position(|c| c.name.eq(id) ) {
                    Some(index) => Ok(Rex::TupleValue(index)),
                    None => Err(String::from("Invalid identifier"))
                }
            },
            _ => Err(String::from("Unsupported ast node"))
        }
    }

}
<commit_msg>query planner example now works<commit_after>use std::string::String;

use super::sql::*;
use super::rel::*;
use super::schema::*;

pub struct SqlToRel {
    default_schema: Option<String>
}

impl SqlToRel {

    pub fn new() -> Self {
        SqlToRel { default_schema: None }
    }

    pub fn sql_to_rel(&self, sql: &ASTNode, tt: &TupleType) -> Result<Box<Rel>, String> {
        match sql {
            &ASTNode::SQLSelect { ref projection, ref relation, .. } => {

                let expr : Vec<Rex> = projection.iter()
                    .map(|e| self.sql_to_rex(&e, tt) )
                    .collect::<Result<Vec<Rex>,String>>()?;

                let input = match relation {
                    &Some(ref r) => Some(self.sql_to_rel(r, tt)?),
                    &None => None
                };

                Ok(Box::new(Rel::Projection {
                    expr: expr,
                    input: input
                }))
            },

            &ASTNode::SQLIdentifier { ref id, .. } => {
                Ok(Box::new(Rel::TableScan { schema: String::from("default"), table: id.clone() }))
            },

            _ => Err(format!("sql_to_rel does not support this relation: {:?}", sql))
        }
    }

    pub fn sql_to_rex(&self, sql: &ASTNode, tt: &TupleType) -> Result<Rex, String> {
        match sql {
            &ASTNode::SQLIdentifier { ref id, .. } => {
                match tt.columns.iter().position(|c| c.name.eq(id) ) {
                    Some(index) => Ok(Rex::TupleValue(index)),
                    None => Err(String::from("Invalid identifier"))
                }
            },
            _ => Err(String::from("Unsupported ast node"))
        }
    }

}
<|endoftext|>


<commit_before>/// TODO: submit upstream

use std::io::{IoResult, Seek, SeekStyle};
use std::io::{MemReader, MemWriter};

/// Writes to an owned, growable byte vector but also implements read with fail-on-call methods.
struct MemWriterFakeStream(MemWriter);

impl MemWriterFakeStream {
    pub fn new() -> MemWriterFakeStream { MemWriterFakeStream(MemWriter::new()) }
}

impl Writer for MemWriterFakeStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        let &MemWriterFakeStream(ref mut s) = self;
        s.write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        let &MemWriterFakeStream(ref mut s) = self;
        s.flush()
    }
}

impl Seek for MemWriterFakeStream {
    fn tell(&self) -> IoResult<u64> {
        let &MemWriterFakeStream(ref s) = self;
        s.tell()
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
        let &MemWriterFakeStream(ref mut s) = self;
        s.seek(pos, style)
    }
}

impl Reader for MemWriterFakeStream {
    fn read(&mut self, _buf: &mut [u8]) -> IoResult<uint> {
        fail!("Uh oh, you didn't aught to call MemWriterFakeStream.read()!")
    }
}

/// Reads from an owned byte vector, but also implements write with fail-on-call methods.
pub struct MemReaderFakeStream(MemReader);

impl MemReaderFakeStream {
    pub fn new(buf: ~[u8]) -> MemReaderFakeStream { MemReaderFakeStream(MemReader::new(buf)) }
}

impl Reader for MemReaderFakeStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let &MemReaderFakeStream(ref mut s) = self;
        s.read(buf)
    }
}

impl Seek for MemReaderFakeStream {
    fn tell(&self) -> IoResult<u64> {
        let &MemReaderFakeStream(ref s) = self;
        s.tell()
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
        let &MemReaderFakeStream(ref mut s) = self;
        s.seek(pos, style)
    }
}

impl Writer for MemReaderFakeStream {
    fn write(&mut self, _buf: &[u8]) -> IoResult<()> {
        fail!("Uh oh, you didn't aught to call MemReaderFakeStream.write()!")
    }
    fn flush(&mut self) -> IoResult<()> {
        fail!("Uh oh, you didn't aught to call MemReaderFakeStream.flush()!")
    }
}

#[cfg(test)]
mod test {
    use super::{MemReaderFakeStream, MemWriterFakeStream};

    #[test]
    fn test_mem_writer_fake_stream() {
        let mut writer = MemWriterFakeStream::new();
        assert_eq!(writer.tell(),              Ok(0));
        assert_eq!(writer.write([0]),          Ok(()));
        assert_eq!(writer.tell(),              Ok(1));
        assert_eq!(writer.write([1, 2, 3]),    Ok(()));
        assert_eq!(writer.write([4, 5, 6, 7]), Ok(()));
        assert_eq!(writer.tell(),              Ok(8));
    }

    #[test]
    fn test_mem_reader_fake_stream() {
        let mut reader = MemReaderFakeStream::new(~[0, 1, 2, 3, 4, 5, 6, 7]);
        let mut buf = ~[];
        assert_eq!(reader.read(buf),      Ok(0));
        assert_eq!(reader.tell(),         Ok(0));
        let mut buf = ~[0];
        assert_eq!(reader.read(buf),      Ok(1));
        assert_eq!(reader.tell(),         Ok(1));
        assert_eq!(buf,                   ~[0]);
        let mut buf = ~[0, 0, 0, 0];
        assert_eq!(reader.read(buf),      Ok(4));
        assert_eq!(reader.tell(),         Ok(5));
        assert_eq!(buf,                   ~[1, 2, 3, 4]);
        assert_eq!(reader.read(buf),      Ok(3));
        assert_eq!(buf.slice(0, 3),       [5, 6, 7]);
        assert_eq!(reader.read(buf).ok(), None);
    }
}
<commit_msg>A little more [T, ..N] → &[T].<commit_after>/// TODO: submit upstream

use std::io::{IoResult, Seek, SeekStyle};
use std::io::{MemReader, MemWriter};

/// Writes to an owned, growable byte vector but also implements read with fail-on-call methods.
struct MemWriterFakeStream(MemWriter);

impl MemWriterFakeStream {
    pub fn new() -> MemWriterFakeStream { MemWriterFakeStream(MemWriter::new()) }
}

impl Writer for MemWriterFakeStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        let &MemWriterFakeStream(ref mut s) = self;
        s.write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        let &MemWriterFakeStream(ref mut s) = self;
        s.flush()
    }
}

impl Seek for MemWriterFakeStream {
    fn tell(&self) -> IoResult<u64> {
        let &MemWriterFakeStream(ref s) = self;
        s.tell()
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
        let &MemWriterFakeStream(ref mut s) = self;
        s.seek(pos, style)
    }
}

impl Reader for MemWriterFakeStream {
    fn read(&mut self, _buf: &mut [u8]) -> IoResult<uint> {
        fail!("Uh oh, you didn't aught to call MemWriterFakeStream.read()!")
    }
}

/// Reads from an owned byte vector, but also implements write with fail-on-call methods.
pub struct MemReaderFakeStream(MemReader);

impl MemReaderFakeStream {
    pub fn new(buf: ~[u8]) -> MemReaderFakeStream { MemReaderFakeStream(MemReader::new(buf)) }
}

impl Reader for MemReaderFakeStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let &MemReaderFakeStream(ref mut s) = self;
        s.read(buf)
    }
}

impl Seek for MemReaderFakeStream {
    fn tell(&self) -> IoResult<u64> {
        let &MemReaderFakeStream(ref s) = self;
        s.tell()
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
        let &MemReaderFakeStream(ref mut s) = self;
        s.seek(pos, style)
    }
}

impl Writer for MemReaderFakeStream {
    fn write(&mut self, _buf: &[u8]) -> IoResult<()> {
        fail!("Uh oh, you didn't aught to call MemReaderFakeStream.write()!")
    }
    fn flush(&mut self) -> IoResult<()> {
        fail!("Uh oh, you didn't aught to call MemReaderFakeStream.flush()!")
    }
}

#[cfg(test)]
mod test {
    use super::{MemReaderFakeStream, MemWriterFakeStream};

    #[test]
    fn test_mem_writer_fake_stream() {
        let mut writer = MemWriterFakeStream::new();
        assert_eq!(writer.tell(),              Ok(0));
        assert_eq!(writer.write([0]),          Ok(()));
        assert_eq!(writer.tell(),              Ok(1));
        assert_eq!(writer.write([1, 2, 3]),    Ok(()));
        assert_eq!(writer.write([4, 5, 6, 7]), Ok(()));
        assert_eq!(writer.tell(),              Ok(8));
    }

    #[test]
    fn test_mem_reader_fake_stream() {
        let mut reader = MemReaderFakeStream::new(~[0, 1, 2, 3, 4, 5, 6, 7]);
        let mut buf = ~[];
        assert_eq!(reader.read(buf),      Ok(0));
        assert_eq!(reader.tell(),         Ok(0));
        let mut buf = ~[0];
        assert_eq!(reader.read(buf),      Ok(1));
        assert_eq!(reader.tell(),         Ok(1));
        assert_eq!(buf,                   ~[0]);
        let mut buf = ~[0, 0, 0, 0];
        assert_eq!(reader.read(buf),      Ok(4));
        assert_eq!(reader.tell(),         Ok(5));
        assert_eq!(buf,                   ~[1, 2, 3, 4]);
        assert_eq!(reader.read(buf),      Ok(3));
        assert_eq!(buf.slice(0, 3),       &[5, 6, 7]);
        assert_eq!(reader.read(buf).ok(), None);
    }
}
<|endoftext|>


<commit_before>//! Common HTTP functionality for the Teepee project.
//!
//! Anything shared between both client and server belongs in here, but this crate is not expected
//! to be used directly.
//!
//! Any crate using types from this crate should re‐export them. For example, the ``status`` module
//! should be exported in the root of the HTTP client crate ``httpc`` so that people can write
//! ``httpc::status`` instead of ``httpcommon::status``.

#![crate_name = "httpcommon"]
#![comment = "Common HTTP functionality for the Teepee project"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![doc(html_logo_url = "http://teepee.rs/logo.100.png",
       html_root_url = "http://www.rust-ci.org/teepee/teepee/doc/")]

#![feature(globs, macro_rules, phase, struct_variant)]

#![deny(unnecessary_qualification)]
#![deny(non_uppercase_statics)]
#![deny(unnecessary_typecast)]
#![deny(missing_doc)]
//#![deny(unstable)]
#![deny(unused_result)]

#[phase(plugin)]
extern crate phf_mac;
extern crate phf;

pub mod method;
pub mod status;
pub mod headers;
pub mod grammar;
<commit_msg>Change #[deny] to #[warn].<commit_after>//! Common HTTP functionality for the Teepee project.
//!
//! Anything shared between both client and server belongs in here, but this crate is not expected
//! to be used directly.
//!
//! Any crate using types from this crate should re‐export them. For example, the ``status`` module
//! should be exported in the root of the HTTP client crate ``httpc`` so that people can write
//! ``httpc::status`` instead of ``httpcommon::status``.

#![crate_name = "httpcommon"]
#![comment = "Common HTTP functionality for the Teepee project"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![doc(html_logo_url = "http://teepee.rs/logo.100.png",
       html_root_url = "http://www.rust-ci.org/teepee/teepee/doc/")]

#![feature(globs, macro_rules, phase, struct_variant)]

#![warn(unnecessary_qualification)]
#![warn(non_uppercase_statics)]
#![warn(unnecessary_typecast)]
#![warn(missing_doc)]
//#![warn(unstable)]
#![warn(unused_result)]

#[phase(plugin)]
extern crate phf_mac;
extern crate phf;

pub mod method;
pub mod status;
pub mod headers;
pub mod grammar;
<|endoftext|>


<commit_before>#![allow(dead_code,unused_variables)]
fn main() {
    // 8
    // (http://rustbyexample.com/fn.html)
    fn is_divisable_by(lhs: u32, rhs: u32) -> bool {
        if rhs == 0 {
            return false;
        }
        lhs % rhs == 0
    }
    fn void_return(n: u32) -> () {}
    fn void_return2(n: u32) {}

    // 8.1
    // (http://rustbyexample.com/fn/methods.html)
    struct Point {
        x: f64,
        y: f64,
    }
    impl Point {
        fn origin() -> Point { // static method
            Point{ x: 0.0, y: 0.0 }
        }
        fn new(x: f64, y: f64) -> Point { // static method
            Point{ x: x, y: y }
        }
    }
    struct Rectangle {
        p1: Point,
        p2: Point,
    }
    impl Rectangle {
        // `&self` is sugar for `self: &Self`, where `Self` is the type of the
        // caller object. In this case `Self` = `Rectangle`
        fn area(&self) -> f64 {
            let Point{ x: x1, y: y1 } = self.p1;
            let Point{ x: x2, y: y2 } = self.p2;
            2.0 * ((x1- x2).abs() + (y1 - y2).abs())
        }
        fn translate(&mut self, x: f64, y: f64) {
            self.p1.x += x;
            self.p2.x += x;
            self.p1.y += y;
            self.p2.y += y;
        }
    }

    // 8.2
    // (http://rustbyexample.com/fn/closures.html)
    fn function(i: i32) -> i32 { i + 1 }
    let closure1 = |i: i32| -> i32 { i + 1 };
    let closure2 = |i| i + 1;
    let i = 1;
    println!("function: {}", function(i));
    println!("closure1: {}", closure1(i));
    println!("closure2: {}", closure2(i));
    let one = || 1;
    println!("closure returning one: {}", one());

    // 8.2.1
    // (http://rustbyexample.com/fn/closures/capture.html)
    let s = "string"; // capture by reference: &T
    let print_s = || println!("s: {}", s);
    print_s();

    let mut count = 0; // capture by mutable reference: &mut T
    let mut inc = || { // 'mut' is required
        count += 1;
        println!("count: {}", count);
    };
    inc();
    inc();
    // error: cannot borrow `count` as mutable more than once at a time [E0499]
    // let reborrow = &mut count;

    let movable = Box::new(3); // capture by value
    let consume = || {
        println!("movable: {}", movable);
        std::mem::drop(movable);
    };
    consume();
    // error: use of moved value: `consume` [E0382]
    // consume();

    // 8.2.2
    // (http://rustbyexample.com/fn/closures/input_parameters.html)
    // FnOnce: takes captures by value (T)
    fn apply<F>(f: F) where F: FnOnce() {
        f()
    }
    // Fn: takes captures by reference (&T)
    fn apply_to_3<F>(f: F) -> i32 where F: Fn(i32) -> i32 {
        f(3)
    }
    let greeting = "hello";
    let mut farewell = "goodbye".to_owned();
    // TODO
}
<commit_msg>rust functions<commit_after>#![allow(dead_code,unused_variables)]
fn main() {
    // 8
    // (http://rustbyexample.com/fn.html)
    fn is_divisable_by(lhs: u32, rhs: u32) -> bool {
        if rhs == 0 {
            return false;
        }
        lhs % rhs == 0
    }
    fn void_return(n: u32) -> () {}
    fn void_return2(n: u32) {}

    // 8.1
    // (http://rustbyexample.com/fn/methods.html)
    struct Point {
        x: f64,
        y: f64,
    }
    impl Point {
        fn origin() -> Point { // static method
            Point{ x: 0.0, y: 0.0 }
        }
        fn new(x: f64, y: f64) -> Point { // static method
            Point{ x: x, y: y }
        }
    }
    struct Rectangle {
        p1: Point,
        p2: Point,
    }
    impl Rectangle {
        // `&self` is sugar for `self: &Self`, where `Self` is the type of the
        // caller object. In this case `Self` = `Rectangle`
        fn area(&self) -> f64 {
            let Point{ x: x1, y: y1 } = self.p1;
            let Point{ x: x2, y: y2 } = self.p2;
            2.0 * ((x1- x2).abs() + (y1 - y2).abs())
        }
        fn translate(&mut self, x: f64, y: f64) {
            self.p1.x += x;
            self.p2.x += x;
            self.p1.y += y;
            self.p2.y += y;
        }
    }

    // 8.2
    // (http://rustbyexample.com/fn/closures.html)
    fn function(i: i32) -> i32 { i + 1 }
    let closure1 = |i: i32| -> i32 { i + 1 };
    let closure2 = |i| i + 1;
    let i = 1;
    println!("function: {}", function(i));
    println!("closure1: {}", closure1(i));
    println!("closure2: {}", closure2(i));
    let one = || 1;
    println!("closure returning one: {}", one());

    // 8.2.1
    // (http://rustbyexample.com/fn/closures/capture.html)
    let s = "string"; // capture by reference: &T
    let print_s = || println!("s: {}", s);
    print_s();

    let mut count = 0; // capture by mutable reference: &mut T
    let mut inc = || { // 'mut' is required
        count += 1;
        println!("count: {}", count);
    };
    inc();
    inc();
    // error: cannot borrow `count` as mutable more than once at a time [E0499]
    // let reborrow = &mut count;

    let movable = Box::new(3); // capture by value
    let consume = || {
        println!("movable: {}", movable);
        std::mem::drop(movable);
    };
    consume();
    // error: use of moved value: `consume` [E0382]
    // consume();

    // 8.2.2
    // (http://rustbyexample.com/fn/closures/input_parameters.html)
    // FnOnce: takes captures by value (T)
    fn apply<F>(f: F) where F: FnOnce() {
        f()
    }
    // Fn: takes captures by reference (&T)
    fn apply_to_3<F>(f: F) -> i32 where F: Fn(i32) -> i32 {
        f(3)
    }
    let greeting = "hello";
    let mut farewell = "goodbye".to_owned(); // a non-copy type
    let diary = || {
        println!("{}", greeting); // greeting is by ference, requires Fn
        farewell.push_str("!!!"); // requires FnMut
        std::mem::drop(farewell); // requires FnOnce
    };
    let x2 = |x| 2 * x;
    apply(diary);
    apply_to_3(x2);

    // 8.2.3
    // skipped code

    // 8.2.4
    fn call_function<F: Fn()>(f: F) {
        f()
    }
    fn print() {
        println!("I'm a function");
    }
    let closure = || println!("I'm a closure");
    call_function(print);
    call_function(closure);

    // 8.2.5
    // skipped code

    // 8.2.6.1, 8.2.6.2
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![4, 5, 6];
    let mut iter = vec1.iter();
    let mut into_iter = vec2.into_iter();
    println!("any in vec1: {}", iter.any(|&x| x == 2 ));
    println!("find in vec1: {:?}", iter.find(|&&x| x == 2 ));
    println!("any in vec2: {}", into_iter.any(|x| x == 2 ));
    println!("find in vec2: {:?}", into_iter.find(|&x| x == 2 ));
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crossbeam::sync::MsQueue;
use fnv::FnvHashMap;
use std::collections::hash_map::Entry;
use std::marker::PhantomData;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;
use std::thread;
use std::vec::IntoIter as VecIntoIter;

use command_buffer::pool::CommandPool;
use command_buffer::pool::CommandPoolAlloc;
use command_buffer::pool::CommandPoolBuilderAlloc;
use command_buffer::pool::UnsafeCommandPool;
use command_buffer::pool::UnsafeCommandPoolAlloc;
use instance::QueueFamily;

use OomError;
use VulkanObject;
use device::Device;
use device::DeviceOwned;

/// Standard implementation of a command pool.
///
/// It is guaranteed that the allocated command buffers keep the `Arc<StandardCommandPool>` alive.
/// This is desirable so that we can store a `Weak<StandardCommandPool>`.
///
/// Will use one Vulkan pool per thread in order to avoid locking. Will try to reuse command
/// buffers. Command buffers can't be moved between threads during the building process, but
/// finished command buffers can.
pub struct StandardCommandPool {
    // The device.
    device: Arc<Device>,

    // Identifier of the queue family.
    queue_family: u32,

    // For each thread, we store thread-specific info.
    per_thread: Mutex<FnvHashMap<thread::ThreadId, Weak<StandardCommandPoolPerThread>>>,
}

unsafe impl Send for StandardCommandPool {
}
unsafe impl Sync for StandardCommandPool {
}

struct StandardCommandPoolPerThread {
    // The Vulkan pool of this thread.
    pool: Mutex<UnsafeCommandPool>,
    // List of existing primary command buffers that are available for reuse.
    available_primary_command_buffers: MsQueue<UnsafeCommandPoolAlloc>,
    // List of existing secondary command buffers that are available for reuse.
    available_secondary_command_buffers: MsQueue<UnsafeCommandPoolAlloc>,
}

impl StandardCommandPool {
    /// Builds a new pool.
    ///
    /// # Panic
    ///
    /// - Panics if the device and the queue family don't belong to the same physical device.
    ///
    pub fn new(device: Arc<Device>, queue_family: QueueFamily) -> StandardCommandPool {
        assert_eq!(device.physical_device().internal_object(),
                   queue_family.physical_device().internal_object());

        StandardCommandPool {
            device: device,
            queue_family: queue_family.id(),
            per_thread: Mutex::new(Default::default()),
        }
    }
}

unsafe impl CommandPool for Arc<StandardCommandPool> {
    type Iter = VecIntoIter<StandardCommandPoolBuilder>;
    type Builder = StandardCommandPoolBuilder;
    type Alloc = StandardCommandPoolAlloc;

    fn alloc(&self, secondary: bool, count: u32) -> Result<Self::Iter, OomError> {
        // Find the correct `StandardCommandPoolPerThread` structure.
        let mut hashmap = self.per_thread.lock().unwrap();
        // TODO: meh for iterating everything every time
        hashmap.retain(|_, w| w.upgrade().is_some());

        // Get an appropriate `Arc<StandardCommandPoolPerThread>`.
        let per_thread = match hashmap.entry(thread::current().id()) {
            Entry::Occupied(entry) => {
                // The `unwrap()` can't fail, since we retained only valid members earlier.
                entry.get().upgrade().unwrap()
            },
            Entry::Vacant(entry) => {
                let new_pool =
                    UnsafeCommandPool::new(self.device.clone(), self.queue_family(), false, true)?;
                let pt = Arc::new(StandardCommandPoolPerThread {
                                      pool: Mutex::new(new_pool),
                                      available_primary_command_buffers: MsQueue::new(),
                                      available_secondary_command_buffers: MsQueue::new(),
                                  });

                entry.insert(Arc::downgrade(&pt));
                pt
            },
        };

        // The final output.
        let mut output = Vec::with_capacity(count as usize);

        // First, pick from already-existing command buffers.
        {
            let existing = if secondary {
                &per_thread.available_secondary_command_buffers
            } else {
                &per_thread.available_primary_command_buffers
            };

            for _ in 0 .. count as usize {
                if let Some(cmd) = existing.try_pop() {
                    output.push(StandardCommandPoolBuilder {
                                    inner: StandardCommandPoolAlloc {
                                        cmd: Some(cmd),
                                        pool: per_thread.clone(),
                                        pool_parent: self.clone(),
                                        secondary: secondary,
                                        device: self.device.clone(),
                                    },
                                    dummy_avoid_send_sync: PhantomData,
                                });
                } else {
                    break;
                }
            }
        };

        // Then allocate the rest.
        if output.len() < count as usize {
            let pool_lock = per_thread.pool.lock().unwrap();
            let num_new = count as usize - output.len();

            for cmd in pool_lock.alloc_command_buffers(secondary, num_new)? {
                output.push(StandardCommandPoolBuilder {
                                inner: StandardCommandPoolAlloc {
                                    cmd: Some(cmd),
                                    pool: per_thread.clone(),
                                    pool_parent: self.clone(),
                                    secondary: secondary,
                                    device: self.device.clone(),
                                },
                                dummy_avoid_send_sync: PhantomData,
                            });
            }
        }

        // Final output.
        Ok(output.into_iter())
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.device
            .physical_device()
            .queue_family_by_id(self.queue_family)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPool {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

/// Command buffer allocated from a `StandardCommandPool` and that is currently being built.
pub struct StandardCommandPoolBuilder {
    // The only difference between a `StandardCommandPoolBuilder` and a `StandardCommandPoolAlloc`
    // is that the former must not implement `Send` and `Sync`. Therefore we just share the structs.
    inner: StandardCommandPoolAlloc,
    // Unimplemented `Send` and `Sync` from the builder.
    dummy_avoid_send_sync: PhantomData<*const u8>,
}

unsafe impl CommandPoolBuilderAlloc for StandardCommandPoolBuilder {
    type Alloc = StandardCommandPoolAlloc;

    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        self.inner.inner()
    }

    #[inline]
    fn into_alloc(self) -> Self::Alloc {
        self.inner
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.inner.queue_family()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolBuilder {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

/// Command buffer allocated from a `StandardCommandPool`.
pub struct StandardCommandPoolAlloc {
    // The actual command buffer. Must always be `Some`. Value extracted in the destructor.
    cmd: Option<UnsafeCommandPoolAlloc>,
    // We hold a reference to the command pool for our destructor.
    pool: Arc<StandardCommandPoolPerThread>,
    // Keep alive the `StandardCommandPool`, otherwise it would be destroyed.
    pool_parent: Arc<StandardCommandPool>,
    // True if secondary command buffer.
    secondary: bool,
    // The device we belong to. Necessary because of the `DeviceOwned` trait implementation.
    device: Arc<Device>,
}

unsafe impl Send for StandardCommandPoolAlloc {
}
unsafe impl Sync for StandardCommandPoolAlloc {
}

unsafe impl CommandPoolAlloc for StandardCommandPoolAlloc {
    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        self.cmd.as_ref().unwrap()
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        let queue_family_id = self.pool.pool.lock().unwrap().queue_family().id();

        self.device
            .physical_device()
            .queue_family_by_id(queue_family_id)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolAlloc {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        // Note that we could grab the device from `self.pool`. Unfortunately this requires a mutex
        // lock, so it isn't compatible with the API of `DeviceOwned`.
        &self.device
    }
}

impl Drop for StandardCommandPoolAlloc {
    fn drop(&mut self) {
        let cmd = self.cmd.take().unwrap();

        if self.secondary {
            self.pool.available_secondary_command_buffers.push(cmd);
        } else {
            self.pool.available_primary_command_buffers.push(cmd);
        }
    }
}

#[cfg(test)]
mod tests {
    use VulkanObject;
    use command_buffer::pool::CommandPool;
    use command_buffer::pool::CommandPoolBuilderAlloc;
    use command_buffer::pool::StandardCommandPool;
    use device::Device;
    use std::sync::Arc;

    #[test]
    fn reuse_command_buffers() {
        let (device, _) = gfx_dev_and_queue!();
        let queue_family = device.physical_device().queue_families().next().unwrap();

        let pool = Device::standard_command_pool(&device, queue_family);

        let cb = pool.alloc(false, 1).unwrap().next().unwrap();
        let raw = cb.inner().internal_object();
        drop(cb);

        let cb2 = pool.alloc(false, 1).unwrap().next().unwrap();
        assert_eq!(raw, cb2.inner().internal_object());
    }

    #[test]
    fn pool_kept_alive_by_allocs() {
        let (device, queue) = gfx_dev_and_queue!();

        let pool = Arc::new(StandardCommandPool::new(device, queue.family()));
        let pool_weak = Arc::downgrade(&pool);

        let cb = pool.alloc(false, 1).unwrap().next().unwrap();
        drop(pool);
        assert!(pool_weak.upgrade().is_some());

        drop(cb);
        assert!(pool_weak.upgrade().is_none());
    }
}
<commit_msg>Use ManuallyDrop in StandardCommandPoolAlloc (#824)<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crossbeam::sync::MsQueue;
use fnv::FnvHashMap;
use std::collections::hash_map::Entry;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ptr;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Weak;
use std::thread;
use std::vec::IntoIter as VecIntoIter;

use command_buffer::pool::CommandPool;
use command_buffer::pool::CommandPoolAlloc;
use command_buffer::pool::CommandPoolBuilderAlloc;
use command_buffer::pool::UnsafeCommandPool;
use command_buffer::pool::UnsafeCommandPoolAlloc;
use instance::QueueFamily;

use OomError;
use VulkanObject;
use device::Device;
use device::DeviceOwned;

/// Standard implementation of a command pool.
///
/// It is guaranteed that the allocated command buffers keep the `Arc<StandardCommandPool>` alive.
/// This is desirable so that we can store a `Weak<StandardCommandPool>`.
///
/// Will use one Vulkan pool per thread in order to avoid locking. Will try to reuse command
/// buffers. Command buffers can't be moved between threads during the building process, but
/// finished command buffers can.
pub struct StandardCommandPool {
    // The device.
    device: Arc<Device>,

    // Identifier of the queue family.
    queue_family: u32,

    // For each thread, we store thread-specific info.
    per_thread: Mutex<FnvHashMap<thread::ThreadId, Weak<StandardCommandPoolPerThread>>>,
}

unsafe impl Send for StandardCommandPool {
}
unsafe impl Sync for StandardCommandPool {
}

struct StandardCommandPoolPerThread {
    // The Vulkan pool of this thread.
    pool: Mutex<UnsafeCommandPool>,
    // List of existing primary command buffers that are available for reuse.
    available_primary_command_buffers: MsQueue<UnsafeCommandPoolAlloc>,
    // List of existing secondary command buffers that are available for reuse.
    available_secondary_command_buffers: MsQueue<UnsafeCommandPoolAlloc>,
}

impl StandardCommandPool {
    /// Builds a new pool.
    ///
    /// # Panic
    ///
    /// - Panics if the device and the queue family don't belong to the same physical device.
    ///
    pub fn new(device: Arc<Device>, queue_family: QueueFamily) -> StandardCommandPool {
        assert_eq!(device.physical_device().internal_object(),
                   queue_family.physical_device().internal_object());

        StandardCommandPool {
            device: device,
            queue_family: queue_family.id(),
            per_thread: Mutex::new(Default::default()),
        }
    }
}

unsafe impl CommandPool for Arc<StandardCommandPool> {
    type Iter = VecIntoIter<StandardCommandPoolBuilder>;
    type Builder = StandardCommandPoolBuilder;
    type Alloc = StandardCommandPoolAlloc;

    fn alloc(&self, secondary: bool, count: u32) -> Result<Self::Iter, OomError> {
        // Find the correct `StandardCommandPoolPerThread` structure.
        let mut hashmap = self.per_thread.lock().unwrap();
        // TODO: meh for iterating everything every time
        hashmap.retain(|_, w| w.upgrade().is_some());

        // Get an appropriate `Arc<StandardCommandPoolPerThread>`.
        let per_thread = match hashmap.entry(thread::current().id()) {
            Entry::Occupied(entry) => {
                // The `unwrap()` can't fail, since we retained only valid members earlier.
                entry.get().upgrade().unwrap()
            },
            Entry::Vacant(entry) => {
                let new_pool =
                    UnsafeCommandPool::new(self.device.clone(), self.queue_family(), false, true)?;
                let pt = Arc::new(StandardCommandPoolPerThread {
                                      pool: Mutex::new(new_pool),
                                      available_primary_command_buffers: MsQueue::new(),
                                      available_secondary_command_buffers: MsQueue::new(),
                                  });

                entry.insert(Arc::downgrade(&pt));
                pt
            },
        };

        // The final output.
        let mut output = Vec::with_capacity(count as usize);

        // First, pick from already-existing command buffers.
        {
            let existing = if secondary {
                &per_thread.available_secondary_command_buffers
            } else {
                &per_thread.available_primary_command_buffers
            };

            for _ in 0 .. count as usize {
                if let Some(cmd) = existing.try_pop() {
                    output.push(StandardCommandPoolBuilder {
                                    inner: StandardCommandPoolAlloc {
                                        cmd: ManuallyDrop::new(cmd),
                                        pool: per_thread.clone(),
                                        pool_parent: self.clone(),
                                        secondary: secondary,
                                        device: self.device.clone(),
                                    },
                                    dummy_avoid_send_sync: PhantomData,
                                });
                } else {
                    break;
                }
            }
        };

        // Then allocate the rest.
        if output.len() < count as usize {
            let pool_lock = per_thread.pool.lock().unwrap();
            let num_new = count as usize - output.len();

            for cmd in pool_lock.alloc_command_buffers(secondary, num_new)? {
                output.push(StandardCommandPoolBuilder {
                                inner: StandardCommandPoolAlloc {
                                    cmd: ManuallyDrop::new(cmd),
                                    pool: per_thread.clone(),
                                    pool_parent: self.clone(),
                                    secondary: secondary,
                                    device: self.device.clone(),
                                },
                                dummy_avoid_send_sync: PhantomData,
                            });
            }
        }

        // Final output.
        Ok(output.into_iter())
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.device
            .physical_device()
            .queue_family_by_id(self.queue_family)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPool {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

/// Command buffer allocated from a `StandardCommandPool` and that is currently being built.
pub struct StandardCommandPoolBuilder {
    // The only difference between a `StandardCommandPoolBuilder` and a `StandardCommandPoolAlloc`
    // is that the former must not implement `Send` and `Sync`. Therefore we just share the structs.
    inner: StandardCommandPoolAlloc,
    // Unimplemented `Send` and `Sync` from the builder.
    dummy_avoid_send_sync: PhantomData<*const u8>,
}

unsafe impl CommandPoolBuilderAlloc for StandardCommandPoolBuilder {
    type Alloc = StandardCommandPoolAlloc;

    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        self.inner.inner()
    }

    #[inline]
    fn into_alloc(self) -> Self::Alloc {
        self.inner
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.inner.queue_family()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolBuilder {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

/// Command buffer allocated from a `StandardCommandPool`.
pub struct StandardCommandPoolAlloc {
    // The actual command buffer. Extracted in the `Drop` implementation.
    cmd: ManuallyDrop<UnsafeCommandPoolAlloc>,
    // We hold a reference to the command pool for our destructor.
    pool: Arc<StandardCommandPoolPerThread>,
    // Keep alive the `StandardCommandPool`, otherwise it would be destroyed.
    pool_parent: Arc<StandardCommandPool>,
    // True if secondary command buffer.
    secondary: bool,
    // The device we belong to. Necessary because of the `DeviceOwned` trait implementation.
    device: Arc<Device>,
}

unsafe impl Send for StandardCommandPoolAlloc {
}
unsafe impl Sync for StandardCommandPoolAlloc {
}

unsafe impl CommandPoolAlloc for StandardCommandPoolAlloc {
    #[inline]
    fn inner(&self) -> &UnsafeCommandPoolAlloc {
        &*self.cmd
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        let queue_family_id = self.pool.pool.lock().unwrap().queue_family().id();

        self.device
            .physical_device()
            .queue_family_by_id(queue_family_id)
            .unwrap()
    }
}

unsafe impl DeviceOwned for StandardCommandPoolAlloc {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        // Note that we could grab the device from `self.pool`. Unfortunately this requires a mutex
        // lock, so it isn't compatible with the API of `DeviceOwned`.
        &self.device
    }
}

impl Drop for StandardCommandPoolAlloc {
    fn drop(&mut self) {
        // Safe because `self.cmd` is wrapped in a `ManuallyDrop`.
        let cmd: UnsafeCommandPoolAlloc = unsafe { ptr::read(&*self.cmd) };

        if self.secondary {
            self.pool.available_secondary_command_buffers.push(cmd);
        } else {
            self.pool.available_primary_command_buffers.push(cmd);
        }
    }
}

#[cfg(test)]
mod tests {
    use VulkanObject;
    use command_buffer::pool::CommandPool;
    use command_buffer::pool::CommandPoolBuilderAlloc;
    use command_buffer::pool::StandardCommandPool;
    use device::Device;
    use std::sync::Arc;

    #[test]
    fn reuse_command_buffers() {
        let (device, _) = gfx_dev_and_queue!();
        let queue_family = device.physical_device().queue_families().next().unwrap();

        let pool = Device::standard_command_pool(&device, queue_family);

        let cb = pool.alloc(false, 1).unwrap().next().unwrap();
        let raw = cb.inner().internal_object();
        drop(cb);

        let cb2 = pool.alloc(false, 1).unwrap().next().unwrap();
        assert_eq!(raw, cb2.inner().internal_object());
    }

    #[test]
    fn pool_kept_alive_by_allocs() {
        let (device, queue) = gfx_dev_and_queue!();

        let pool = Arc::new(StandardCommandPool::new(device, queue.family()));
        let pool_weak = Arc::downgrade(&pool);

        let cb = pool.alloc(false, 1).unwrap().next().unwrap();
        drop(pool);
        assert!(pool_weak.upgrade().is_some());

        drop(cb);
        assert!(pool_weak.upgrade().is_none());
    }
}
<|endoftext|>


<commit_before>use nix::sys::ioctl::*;
use nix::sys::termios;
use std::fs::File;
use std::fs::OpenOptions;
use std::os::unix::io::*;

pub use nix::Result;

pub struct Terminal {
    tty: File,
    ttyfd: RawFd,
    size: Winsize,
    orig_attr: termios::Termios,
}

impl Terminal {
    pub fn new() -> Result<Terminal> {
        let mut tmptty = OpenOptions::new()
            .read(true)
            .write(true)
            .open("/dev/tty").unwrap();
        let tmpttyfd = tmptty.as_raw_fd();
        let mut tmpterm = Terminal {
            tty: tmptty,
            ttyfd: tmpttyfd,
            size: Winsize::new(),
            orig_attr: termios::tcgetattr(tmpttyfd).unwrap(),
        };
        match tmpterm.update_size() {
            Ok(()) => Ok(tmpterm),
            Err(error) => Err(error),
        }
    }

    pub fn destroy(self) -> Result<()> {
        match termios::tcsetattr(self.ttyfd, termios::SetArg::TCSANOW, &self.orig_attr) {
            Ok(()) => Ok(()),
            Err(error) => Err(error),
        }
    }

    pub fn update_size(&mut self) -> Result<()> {
        ioctl(self.tty.as_raw_fd(), TIOCGWINSZ(&mut self.size))
    }

    pub fn rows(&self) -> u16 {
        self.size.ws_row as u16
    }

    pub fn cols(&self) -> u16 {
        self.size.ws_col as u16
    }
}

trait Constructor<T> {
    fn new() -> T;
}

impl Constructor<Winsize> for Winsize {
    fn new() -> Winsize {
        Winsize {
            ws_row: 0,
            ws_col: 0,
            ws_xpixel: 0,
            ws_ypixel: 0,
        }
    }
}

<commit_msg>typing touchups. Preparing for major refactor for extensibility<commit_after>use nix;
use nix::sys::ioctl;
use nix::sys::termios;
use std::fs::File;
use std::fs::OpenOptions;
use std::os::unix::io::*;
use std::result;

const TTYPATH: &'static str = "/dev/tty";

pub struct Terminal {
    tty: File,
    ttyfd: RawFd,
    size: ioctl::Winsize,
    orig_attr: termios::Termios,
}

pub type Result<T> = result::Result<T, Error>;

pub enum Error {
    Unknown,
}

impl Terminal {
    pub fn new() -> nix::Result<Terminal> {
        let mut tmptty = OpenOptions::new()
            .read(true)
            .write(true)
            .open(TTYPATH).unwrap();
        let tmpttyfd = tmptty.as_raw_fd();
        let mut tmpterm = Terminal {
            tty: tmptty,
            ttyfd: tmpttyfd,
            size: ioctl::Winsize::new(),
            orig_attr: termios::tcgetattr(tmpttyfd).unwrap(),
        };
        match tmpterm.update_size() {
            Ok(()) => Ok(tmpterm),
            Err(error) => Err(error),
        }
    }

    pub fn destroy(self) -> nix::Result<()> {
        match termios::tcsetattr(self.ttyfd, termios::SetArg::TCSANOW, &self.orig_attr) {
            Ok(()) => Ok(()),
            Err(error) => Err(error),
        }
    }

    pub fn update_size(&mut self) -> nix::Result<()> {
        ioctl::ioctl(self.tty.as_raw_fd(), ioctl::TIOCGWINSZ(&mut self.size))
    }

    pub fn rows(&self) -> u16 {
        self.size.ws_row as u16
    }

    pub fn cols(&self) -> u16 {
        self.size.ws_col as u16
    }
}

trait Constructor<T> {
    fn new() -> T;
}

impl Constructor<ioctl::Winsize> for ioctl::Winsize {
    fn new() -> ioctl::Winsize {
        ioctl::Winsize {
            ws_row: 0,
            ws_col: 0,
            ws_xpixel: 0,
            ws_ypixel: 0,
        }
    }
}

<|endoftext|>


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

use message::Message;
use reactor;
use timer::TimerEvent;

#[derive(Debug)]
pub enum Request<M> {
    Message(M),
    Timer(TimerEvent),
    Exit
}

pub type InternalRequest = Request<Rc<Message>>;
pub type ExternalRequest = Request<Message>;

#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum RequestHandler {
    Message,
    Timer,
    Exit
}

impl reactor::Event for Request<Rc<Message>> {
    type Handler = RequestHandler;
    fn handler(&self) -> Self::Handler {
        match *self {
            Request::Message(_) => RequestHandler::Message,
            Request::Timer(_) => RequestHandler::Timer,
            Request::Exit => RequestHandler::Exit,
        }
    }
}

impl From<Request<Message>> for Request<Rc<Message>> {
    fn from(request: Request<Message>) -> Request<Rc<Message>> {
        match request {
            Request::Message(message) => Request::Message(Rc::new(message)),
            Request::Timer(event) => Request::Timer(event),
            Request::Exit => Request::Exit,
        }
    }
}
<commit_msg>Request: derive Clone<commit_after>use std::rc::Rc;

use message::Message;
use reactor;
use timer::TimerEvent;

#[derive(Clone, Debug)]
pub enum Request<M> {
    Message(M),
    Timer(TimerEvent),
    Exit
}

pub type InternalRequest = Request<Rc<Message>>;
pub type ExternalRequest = Request<Message>;

#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum RequestHandler {
    Message,
    Timer,
    Exit
}

impl reactor::Event for Request<Rc<Message>> {
    type Handler = RequestHandler;
    fn handler(&self) -> Self::Handler {
        match *self {
            Request::Message(_) => RequestHandler::Message,
            Request::Timer(_) => RequestHandler::Timer,
            Request::Exit => RequestHandler::Exit,
        }
    }
}

impl From<Request<Message>> for Request<Rc<Message>> {
    fn from(request: Request<Message>) -> Request<Rc<Message>> {
        match request {
            Request::Message(message) => Request::Message(Rc::new(message)),
            Request::Timer(event) => Request::Timer(event),
            Request::Exit => Request::Exit,
        }
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
pub fn supports_aesni() -> bool {
	let mut flags: u32;
    unsafe {
        asm!(
        "
        mov $$1, %eax;
        cpuid;
		mov %ecx, $0;
        "
        : "=r" (flags) // output
        : // input
        : "eax", "ebx", "ecx", "edx" // clobbers
        )
		// No idea why, but on 32-bit targets, the compiler complains
		// about not having enough registers. Adding in this dummy
		// section, however, seems to fix it.
        asm!("")
    }

    return (flags & 0x02000000) != 0;
}

#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
#[allow(dead_assignment)]
unsafe fn fixed_time_eq_asm(mut lhsp: *const u8, mut rhsp: *const u8, mut count: uint) -> bool {
    let mut result: u8 = 0;

    asm!(
        "
            1:

            mov ($1), %cl
            xor ($2), %cl
            or %cl, $0

            inc $1
            inc $2
            dec $3
            jnz 1b
        "
        : "+r" (result), "+r" (lhsp), "+r" (rhsp), "+r" (count) // all input and output
        : // input
        : "cl", "cc" // clobbers
        : "volatile" // flags
    );

    return result == 0;
}

#[cfg(target_arch = "arm")]
#[allow(dead_assignment)]
unsafe fn fixed_time_eq_asm(mut lhsp: *const u8, mut rhsp: *const u8, mut count: uint) -> bool {
    let mut result: u8 = 0;

    asm!(
        "
            1:

            ldrb r4, [$1]
            ldrb r5, [$2]
            eor r4, r4, r5
            orr $0, $0, r4

            add $1, $1, #1
            add $2, $2, #1
            subs $3, $3, #1
            bne 1b
        "
        : "+r" (result), "+r" (lhsp), "+r" (rhsp), "+r" (count) // all input and output
        : // input
        : "r4", "r5", "cc" // clobbers
        : "volatile" // flags
    );

    return result == 0;
}

/// Compare two vectors using a fixed number of operations. If the two vectors are not of equal
/// length, the function returns false immediately.
pub fn fixed_time_eq(lhs: &[u8], rhs: &[u8]) -> bool {
    if lhs.len() != rhs.len() {
        return false;
    }
    if lhs.len() == 0 {
        return true;
    }

    let count = lhs.len();

    unsafe {
        let lhsp = lhs.unsafe_get(0);
        let rhsp = rhs.unsafe_get(0);
        return fixed_time_eq_asm(lhsp, rhsp, count);
    }
}

#[cfg(test)]
mod test {
    use util::fixed_time_eq;

    #[test]
    pub fn test_fixed_time_eq() {
        let a = [0, 1, 2];
        let b = [0, 1, 2];
        let c = [0, 1, 9];
        let d = [9, 1, 2];
        let e = [2, 1, 0];
        let f = [2, 2, 2];
        let g = [0, 0, 0];

        assert!(fixed_time_eq(a, a));
        assert!(fixed_time_eq(a, b));

        assert!(!fixed_time_eq(a, c));
        assert!(!fixed_time_eq(a, d));
        assert!(!fixed_time_eq(a, e));
        assert!(!fixed_time_eq(a, f));
        assert!(!fixed_time_eq(a, g));
    }
}
<commit_msg>Remove build warnings<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
pub fn supports_aesni() -> bool {
	let mut flags: u32;
    unsafe {
        asm!(
        "
        mov $$1, %eax;
        cpuid;
		mov %ecx, $0;
        "
        : "=r" (flags) // output
        : // input
        : "eax", "ebx", "ecx", "edx" // clobbers
        )
		// No idea why, but on 32-bit targets, the compiler complains
		// about not having enough registers. Adding in this dummy
		// section, however, seems to fix it.
        asm!("")
    }

    return (flags & 0x02000000) != 0;
}

#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
#[allow(dead_assignment)]
#[allow(unused_variable)]
unsafe fn fixed_time_eq_asm(mut lhsp: *const u8, mut rhsp: *const u8, mut count: uint) -> bool {
    let mut result: u8 = 0;

    asm!(
        "
            1:

            mov ($1), %cl
            xor ($2), %cl
            or %cl, $0

            inc $1
            inc $2
            dec $3
            jnz 1b
        "
        : "+r" (result), "+r" (lhsp), "+r" (rhsp), "+r" (count) // all input and output
        : // input
        : "cl", "cc" // clobbers
        : "volatile" // flags
    );

    return result == 0;
}

#[cfg(target_arch = "arm")]
#[allow(dead_assignment)]
unsafe fn fixed_time_eq_asm(mut lhsp: *const u8, mut rhsp: *const u8, mut count: uint) -> bool {
    let mut result: u8 = 0;

    asm!(
        "
            1:

            ldrb r4, [$1]
            ldrb r5, [$2]
            eor r4, r4, r5
            orr $0, $0, r4

            add $1, $1, #1
            add $2, $2, #1
            subs $3, $3, #1
            bne 1b
        "
        : "+r" (result), "+r" (lhsp), "+r" (rhsp), "+r" (count) // all input and output
        : // input
        : "r4", "r5", "cc" // clobbers
        : "volatile" // flags
    );

    return result == 0;
}

/// Compare two vectors using a fixed number of operations. If the two vectors are not of equal
/// length, the function returns false immediately.
pub fn fixed_time_eq(lhs: &[u8], rhs: &[u8]) -> bool {
    if lhs.len() != rhs.len() {
        return false;
    }
    if lhs.len() == 0 {
        return true;
    }

    let count = lhs.len();

    unsafe {
        let lhsp = lhs.unsafe_get(0);
        let rhsp = rhs.unsafe_get(0);
        return fixed_time_eq_asm(lhsp, rhsp, count);
    }
}

#[cfg(test)]
mod test {
    use util::fixed_time_eq;

    #[test]
    pub fn test_fixed_time_eq() {
        let a = [0, 1, 2];
        let b = [0, 1, 2];
        let c = [0, 1, 9];
        let d = [9, 1, 2];
        let e = [2, 1, 0];
        let f = [2, 2, 2];
        let g = [0, 0, 0];

        assert!(fixed_time_eq(a, a));
        assert!(fixed_time_eq(a, b));

        assert!(!fixed_time_eq(a, c));
        assert!(!fixed_time_eq(a, d));
        assert!(!fixed_time_eq(a, e));
        assert!(!fixed_time_eq(a, f));
        assert!(!fixed_time_eq(a, g));
    }
}
<|endoftext|>


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

//! Managed vectors

// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

use cast::transmute;
use kinds::Copy;
use iter;
use libc;
use option::Option;
use ptr::addr_of;
use sys;
use uint;
use vec;

/// Code for dealing with @-vectors. This is pretty incomplete, and
/// contains a bunch of duplication from the code for ~-vectors.

#[abi = "cdecl"]
pub extern mod rustrt {
    #[legacy_exports];
    unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc,
                                        ++v: **vec::raw::VecRepr,
                                        ++n: libc::size_t);
}

#[abi = "rust-intrinsic"]
pub extern mod rusti {
    #[legacy_exports];
    fn move_val_init<T>(dst: &mut T, -src: T);
}

/// Returns the number of elements the vector can hold without reallocating
#[inline(always)]
pub pure fn capacity<T>(v: @[const T]) -> uint {
    unsafe {
        let repr: **raw::VecRepr =
            ::cast::reinterpret_cast(&addr_of(&v));
        (**repr).unboxed.alloc / sys::size_of::<T>()
    }
}

/**
 * Builds a vector by calling a provided function with an argument
 * function that pushes an element to the back of a vector.
 * This version takes an initial size for the vector.
 *
 * # Arguments
 *
 * * size - An initial size of the vector to reserve
 * * builder - A function that will construct the vector. It recieves
 *             as an argument a function that will push an element
 *             onto the vector being constructed.
 */
#[inline(always)]
pub pure fn build_sized<A>(size: uint,
                           builder: &fn(push: pure fn(v: A))) -> @[A] {
    let mut vec: @[const A] = @[];
    unsafe { raw::reserve(&mut vec, size); }
    builder(|+x| unsafe { raw::push(&mut vec, x) });
    return unsafe { transmute(vec) };
}

/**
 * Builds a vector by calling a provided function with an argument
 * function that pushes an element to the back of a vector.
 *
 * # Arguments
 *
 * * builder - A function that will construct the vector. It recieves
 *             as an argument a function that will push an element
 *             onto the vector being constructed.
 */
#[inline(always)]
pub pure fn build<A>(builder: &fn(push: pure fn(v: A))) -> @[A] {
    build_sized(4, builder)
}

/**
 * Builds a vector by calling a provided function with an argument
 * function that pushes an element to the back of a vector.
 * This version takes an initial size for the vector.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the vector to reserve
 * * builder - A function that will construct the vector. It recieves
 *             as an argument a function that will push an element
 *             onto the vector being constructed.
 */
#[inline(always)]
pub pure fn build_sized_opt<A>(size: Option<uint>,
                               builder: &fn(push: pure fn(v: A))) -> @[A] {
    build_sized(size.get_or_default(4), builder)
}

// Appending
#[inline(always)]
pub pure fn append<T: Copy>(lhs: @[T], rhs: &[const T]) -> @[T] {
    do build_sized(lhs.len() + rhs.len()) |push| {
        for vec::each(lhs) |x| { push(*x); }
        for uint::range(0, rhs.len()) |i| { push(rhs[i]); }
    }
}

/// Apply a function to each element of a vector and return the results
pub pure fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
    do build_sized(v.len()) |push| {
        for vec::each(v) |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes an immutable vector.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
pub pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> @[T] {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes an immutable vector.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
pub pure fn from_elem<T: Copy>(n_elts: uint, t: T) -> @[T] {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(copy t); i += 1u; }
    }
}

#[cfg(notest)]
pub mod traits {
    use at_vec::append;
    use kinds::Copy;
    use ops::Add;

    pub impl<T: Copy> @[T] : Add<&[const T],@[T]> {
        #[inline(always)]
        pure fn add(&self, rhs: & &self/[const T]) -> @[T] {
            append(*self, (*rhs))
        }
    }
}

#[cfg(test)]
pub mod traits {}

pub mod raw {
    use at_vec::{capacity, rusti, rustrt};
    use cast::transmute;
    use libc;
    use ptr::addr_of;
    use ptr;
    use sys;
    use uint;
    use vec;

    pub type VecRepr = vec::raw::VecRepr;
    pub type SliceRepr = vec::raw::SliceRepr;

    /**
     * Sets the length of a vector
     *
     * This will explicitly set the size of the vector, without actually
     * modifing its buffers, so it is up to the caller to ensure that
     * the vector is actually the specified size.
     */
    #[inline(always)]
    pub unsafe fn set_len<T>(v: @[const T], new_len: uint) {
        let repr: **VecRepr = ::cast::reinterpret_cast(&addr_of(&v));
        (**repr).unboxed.fill = new_len * sys::size_of::<T>();
    }

    #[inline(always)]
    pub unsafe fn push<T>(v: &mut @[const T], initval: T) {
        let repr: **VecRepr = ::cast::reinterpret_cast(&v);
        let fill = (**repr).unboxed.fill;
        if (**repr).unboxed.alloc > fill {
            push_fast(v, initval);
        }
        else {
            push_slow(v, initval);
        }
    }

    #[inline(always)] // really pretty please
    pub unsafe fn push_fast<T>(v: &mut @[const T], initval: T) {
        let repr: **VecRepr = ::cast::reinterpret_cast(&v);
        let fill = (**repr).unboxed.fill;
        (**repr).unboxed.fill += sys::size_of::<T>();
        let p = addr_of(&((**repr).unboxed.data));
        let p = ptr::offset(p, fill) as *mut T;
        rusti::move_val_init(&mut(*p), move initval);
    }

    pub unsafe fn push_slow<T>(v: &mut @[const T], initval: T) {
        reserve_at_least(&mut *v, v.len() + 1u);
        push_fast(v, move initval);
    }

    /**
     * Reserves capacity for exactly `n` elements in the given vector.
     *
     * If the capacity for `v` is already equal to or greater than the
     * requested capacity, then no action is taken.
     *
     * # Arguments
     *
     * * v - A vector
     * * n - The number of elements to reserve space for
     */
    pub unsafe fn reserve<T>(v: &mut @[const T], n: uint) {
        // Only make the (slow) call into the runtime if we have to
        if capacity(*v) < n {
            let ptr: **VecRepr = transmute(v);
            rustrt::vec_reserve_shared_actual(sys::get_type_desc::<T>(),
                                              ptr, n as libc::size_t);
        }
    }

    /**
     * Reserves capacity for at least `n` elements in the given vector.
     *
     * This function will over-allocate in order to amortize the
     * allocation costs in scenarios where the caller may need to
     * repeatedly reserve additional space.
     *
     * If the capacity for `v` is already equal to or greater than the
     * requested capacity, then no action is taken.
     *
     * # Arguments
     *
     * * v - A vector
     * * n - The number of elements to reserve space for
     */
    pub unsafe fn reserve_at_least<T>(v: &mut @[const T], n: uint) {
        reserve(v, uint::next_power_of_two(n));
    }

}

#[test]
pub fn test() {
    // Some code that could use that, then:
    fn seq_range(lo: uint, hi: uint) -> @[uint] {
        do build |push| {
            for uint::range(lo, hi) |i| {
                push(i);
            }
        }
    }

    assert seq_range(10, 15) == @[10, 11, 12, 13, 14];
    assert from_fn(5, |x| x+1) == @[1, 2, 3, 4, 5];
    assert from_elem(5, 3.14) == @[3.14, 3.14, 3.14, 3.14, 3.14];
}

#[test]
pub fn append_test() {
    assert @[1,2,3] + @[4,5,6] == @[1,2,3,4,5,6];
}
<commit_msg>Add more constructors for managed vectors (as proposed in issue #4553)<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Managed vectors

// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

use cast::transmute;
use kinds::Copy;
use iter;
use libc;
use option::Option;
use ptr::addr_of;
use sys;
use uint;
use vec;

/// Code for dealing with @-vectors. This is pretty incomplete, and
/// contains a bunch of duplication from the code for ~-vectors.

#[abi = "cdecl"]
pub extern mod rustrt {
    #[legacy_exports];
    unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc,
                                        ++v: **vec::raw::VecRepr,
                                        ++n: libc::size_t);
}

#[abi = "rust-intrinsic"]
pub extern mod rusti {
    #[legacy_exports];
    fn move_val_init<T>(dst: &mut T, -src: T);
}

/// Returns the number of elements the vector can hold without reallocating
#[inline(always)]
pub pure fn capacity<T>(v: @[const T]) -> uint {
    unsafe {
        let repr: **raw::VecRepr =
            ::cast::reinterpret_cast(&addr_of(&v));
        (**repr).unboxed.alloc / sys::size_of::<T>()
    }
}

/**
 * Builds a vector by calling a provided function with an argument
 * function that pushes an element to the back of a vector.
 * This version takes an initial size for the vector.
 *
 * # Arguments
 *
 * * size - An initial size of the vector to reserve
 * * builder - A function that will construct the vector. It recieves
 *             as an argument a function that will push an element
 *             onto the vector being constructed.
 */
#[inline(always)]
pub pure fn build_sized<A>(size: uint,
                           builder: &fn(push: pure fn(v: A))) -> @[A] {
    let mut vec: @[const A] = @[];
    unsafe { raw::reserve(&mut vec, size); }
    builder(|+x| unsafe { raw::push(&mut vec, x) });
    return unsafe { transmute(vec) };
}

/**
 * Builds a vector by calling a provided function with an argument
 * function that pushes an element to the back of a vector.
 *
 * # Arguments
 *
 * * builder - A function that will construct the vector. It recieves
 *             as an argument a function that will push an element
 *             onto the vector being constructed.
 */
#[inline(always)]
pub pure fn build<A>(builder: &fn(push: pure fn(v: A))) -> @[A] {
    build_sized(4, builder)
}

/**
 * Builds a vector by calling a provided function with an argument
 * function that pushes an element to the back of a vector.
 * This version takes an initial size for the vector.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the vector to reserve
 * * builder - A function that will construct the vector. It recieves
 *             as an argument a function that will push an element
 *             onto the vector being constructed.
 */
#[inline(always)]
pub pure fn build_sized_opt<A>(size: Option<uint>,
                               builder: &fn(push: pure fn(v: A))) -> @[A] {
    build_sized(size.get_or_default(4), builder)
}

// Appending
#[inline(always)]
pub pure fn append<T: Copy>(lhs: @[T], rhs: &[const T]) -> @[T] {
    do build_sized(lhs.len() + rhs.len()) |push| {
        for vec::each(lhs) |x| { push(*x); }
        for uint::range(0, rhs.len()) |i| { push(rhs[i]); }
    }
}

/// Apply a function to each element of a vector and return the results
pub pure fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
    do build_sized(v.len()) |push| {
        for vec::each(v) |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes an immutable vector.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
pub pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> @[T] {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes an immutable vector.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
pub pure fn from_elem<T: Copy>(n_elts: uint, t: T) -> @[T] {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(copy t); i += 1u; }
    }
}

/**
 * Creates and initializes an immutable managed vector by moving all the
 * elements from an owned vector.
 */
fn from_owned<T>(v: ~[T]) -> @[T] {
    let mut av = @[];
    unsafe {
        raw::reserve(&mut av, v.len());
        do vec::consume(v) |_i, x| {
            raw::push(&mut av, x);
        }
        transmute(av)
    }
}

/**
 * Creates and initializes an immutable managed vector by copying all the
 * elements of a slice.
 */
fn from_slice<T:Copy>(v: &[T]) -> @[T] {
    from_fn(v.len(), |i| v[i])
}

#[cfg(notest)]
pub mod traits {
    use at_vec::append;
    use kinds::Copy;
    use ops::Add;

    pub impl<T: Copy> @[T] : Add<&[const T],@[T]> {
        #[inline(always)]
        pure fn add(&self, rhs: & &self/[const T]) -> @[T] {
            append(*self, (*rhs))
        }
    }
}

#[cfg(test)]
pub mod traits {}

pub mod raw {
    use at_vec::{capacity, rusti, rustrt};
    use cast::transmute;
    use libc;
    use ptr::addr_of;
    use ptr;
    use sys;
    use uint;
    use vec;

    pub type VecRepr = vec::raw::VecRepr;
    pub type SliceRepr = vec::raw::SliceRepr;

    /**
     * Sets the length of a vector
     *
     * This will explicitly set the size of the vector, without actually
     * modifing its buffers, so it is up to the caller to ensure that
     * the vector is actually the specified size.
     */
    #[inline(always)]
    pub unsafe fn set_len<T>(v: @[const T], new_len: uint) {
        let repr: **VecRepr = ::cast::reinterpret_cast(&addr_of(&v));
        (**repr).unboxed.fill = new_len * sys::size_of::<T>();
    }

    #[inline(always)]
    pub unsafe fn push<T>(v: &mut @[const T], initval: T) {
        let repr: **VecRepr = ::cast::reinterpret_cast(&v);
        let fill = (**repr).unboxed.fill;
        if (**repr).unboxed.alloc > fill {
            push_fast(v, initval);
        }
        else {
            push_slow(v, initval);
        }
    }

    #[inline(always)] // really pretty please
    pub unsafe fn push_fast<T>(v: &mut @[const T], initval: T) {
        let repr: **VecRepr = ::cast::reinterpret_cast(&v);
        let fill = (**repr).unboxed.fill;
        (**repr).unboxed.fill += sys::size_of::<T>();
        let p = addr_of(&((**repr).unboxed.data));
        let p = ptr::offset(p, fill) as *mut T;
        rusti::move_val_init(&mut(*p), move initval);
    }

    pub unsafe fn push_slow<T>(v: &mut @[const T], initval: T) {
        reserve_at_least(&mut *v, v.len() + 1u);
        push_fast(v, move initval);
    }

    /**
     * Reserves capacity for exactly `n` elements in the given vector.
     *
     * If the capacity for `v` is already equal to or greater than the
     * requested capacity, then no action is taken.
     *
     * # Arguments
     *
     * * v - A vector
     * * n - The number of elements to reserve space for
     */
    pub unsafe fn reserve<T>(v: &mut @[const T], n: uint) {
        // Only make the (slow) call into the runtime if we have to
        if capacity(*v) < n {
            let ptr: **VecRepr = transmute(v);
            rustrt::vec_reserve_shared_actual(sys::get_type_desc::<T>(),
                                              ptr, n as libc::size_t);
        }
    }

    /**
     * Reserves capacity for at least `n` elements in the given vector.
     *
     * This function will over-allocate in order to amortize the
     * allocation costs in scenarios where the caller may need to
     * repeatedly reserve additional space.
     *
     * If the capacity for `v` is already equal to or greater than the
     * requested capacity, then no action is taken.
     *
     * # Arguments
     *
     * * v - A vector
     * * n - The number of elements to reserve space for
     */
    pub unsafe fn reserve_at_least<T>(v: &mut @[const T], n: uint) {
        reserve(v, uint::next_power_of_two(n));
    }

}

#[test]
pub fn test() {
    // Some code that could use that, then:
    fn seq_range(lo: uint, hi: uint) -> @[uint] {
        do build |push| {
            for uint::range(lo, hi) |i| {
                push(i);
            }
        }
    }

    assert seq_range(10, 15) == @[10, 11, 12, 13, 14];
    assert from_fn(5, |x| x+1) == @[1, 2, 3, 4, 5];
    assert from_elem(5, 3.14) == @[3.14, 3.14, 3.14, 3.14, 3.14];
}

#[test]
pub fn append_test() {
    assert @[1,2,3] + @[4,5,6] == @[1,2,3,4,5,6];
}

#[test]
pub fn test_from_owned() {
    assert from_owned::<int>(~[]) == @[];
    assert from_owned(~[true]) == @[true];
    assert from_owned(~[1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5];
    assert from_owned(~[~"abc", ~"123"]) == @[~"abc", ~"123"];
    assert from_owned(~[~[42]]) == @[~[42]];
}

#[test]
pub fn test_from_slice() {
    assert from_slice::<int>([]) == @[];
    assert from_slice([true]) == @[true];
    assert from_slice([1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5];
    assert from_slice([@"abc", @"123"]) == @[@"abc", @"123"];
    assert from_slice([@[42]]) == @[@[42]];
}

<|endoftext|>