<commit_before>use parking_lot::RwLock;
use serde::de::Error as DeError;
use serde::ser::{SerializeSeq, Serialize, Serializer};
use std::{
    collections::HashMap,
    hash::Hash,
    sync::Arc
};
use super::prelude::*;

#[cfg(feature = "cache")]
use internal::prelude::*;

#[cfg(all(feature = "cache", feature = "model"))]
use super::permissions::Permissions;
#[cfg(all(feature = "cache", feature = "model"))]
use CACHE;

pub fn default_true() -> bool {
    true
}

pub fn deserialize_emojis<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<EmojiId, Emoji>, D::Error> {
    let vec: Vec<Emoji> = Deserialize::deserialize(deserializer)?;
    let mut emojis = HashMap::new();

    for emoji in vec {
        emojis.insert(emoji.id, emoji);
    }

    Ok(emojis)
}

pub fn deserialize_guild_channels<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<ChannelId, Arc<RwLock<GuildChannel>>>, D::Error> {
    let vec: Vec<GuildChannel> = Deserialize::deserialize(deserializer)?;
    let mut map = HashMap::new();

    for channel in vec {
        map.insert(channel.id, Arc::new(RwLock::new(channel)));
    }

    Ok(map)
}

pub fn deserialize_members<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, Member>, D::Error> {
    let vec: Vec<Member> = Deserialize::deserialize(deserializer)?;
    let mut members = HashMap::new();

    for member in vec {
        let user_id = member.user.read().id;

        members.insert(user_id, member);
    }

    Ok(members)
}

pub fn deserialize_presences<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, Presence>, D::Error> {
    let vec: Vec<Presence> = Deserialize::deserialize(deserializer)?;
    let mut presences = HashMap::new();

    for presence in vec {
        presences.insert(presence.user_id, presence);
    }

    Ok(presences)
}

pub fn deserialize_private_channels<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<ChannelId, Channel>, D::Error> {
    let vec: Vec<Channel> = Deserialize::deserialize(deserializer)?;
    let mut private_channels = HashMap::new();

    for private_channel in vec {
        let id = match private_channel {
            Channel::Group(ref group) => group.read().channel_id,
            Channel::Private(ref channel) => channel.read().id,
            Channel::Guild(_) => unreachable!("Guild private channel decode"),
            Channel::Category(_) => unreachable!("Channel category private channel decode"),
        };

        private_channels.insert(id, private_channel);
    }

    Ok(private_channels)
}

pub fn deserialize_roles<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<RoleId, Role>, D::Error> {
    let vec: Vec<Role> = Deserialize::deserialize(deserializer)?;
    let mut roles = HashMap::new();

    for role in vec {
        roles.insert(role.id, role);
    }

    Ok(roles)
}

pub fn deserialize_single_recipient<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<Arc<RwLock<User>>, D::Error> {
    let mut users: Vec<User> = Deserialize::deserialize(deserializer)?;
    let user = if users.is_empty() {
        return Err(DeError::custom("Expected a single recipient"));
    } else {
        users.remove(0)
    };

    Ok(Arc::new(RwLock::new(user)))
}

pub fn deserialize_sync_user<'de, D>(deserializer: D)
    -> StdResult<Arc<RwLock<User>>, D::Error> where D: Deserializer<'de> {
    Ok(Arc::new(RwLock::new(User::deserialize(deserializer)?)))
}

pub fn serialize_sync_user<S: Serializer>(
    user: &Arc<RwLock<User>>,
    serializer: S,
) -> StdResult<S::Ok, S::Error> {
    User::serialize(&*user.read(), serializer)
}

pub fn deserialize_users<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, Arc<RwLock<User>>>, D::Error> {
    let vec: Vec<User> = Deserialize::deserialize(deserializer)?;
    let mut users = HashMap::new();

    for user in vec {
        users.insert(user.id, Arc::new(RwLock::new(user)));
    }

    Ok(users)
}

pub fn serialize_users<S: Serializer>(
    users: &HashMap<UserId, Arc<RwLock<User>>>,
    serializer: S
) -> StdResult<S::Ok, S::Error> {
    let mut seq = serializer.serialize_seq(Some(users.len()))?;

    for user in users.values() {
        seq.serialize_element(&*user.read())?;
    }

    seq.end()
}

pub fn deserialize_u16<'de, D: Deserializer<'de>>(deserializer: D) -> StdResult<u16, D::Error> {
    deserializer.deserialize_any(U16Visitor)
}

pub fn deserialize_u64<'de, D: Deserializer<'de>>(deserializer: D) -> StdResult<u64, D::Error> {
    deserializer.deserialize_any(U64Visitor)
}

pub fn deserialize_voice_states<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, VoiceState>, D::Error> {
    let vec: Vec<VoiceState> = Deserialize::deserialize(deserializer)?;
    let mut voice_states = HashMap::new();

    for voice_state in vec {
        voice_states.insert(voice_state.user_id, voice_state);
    }

    Ok(voice_states)
}

pub fn serialize_gen_map<K: Eq + Hash, S: Serializer, V: Serialize>(
    map: &HashMap<K, V>,
    serializer: S,
) -> StdResult<S::Ok, S::Error> {
    let mut seq = serializer.serialize_seq(Some(map.len()))?;

    for value in map.values() {
        seq.serialize_element(&value)?;
    }

    seq.end()
}

pub fn serialize_gen_locked_map<K: Eq + Hash, S: Serializer, V: Serialize>(
    map: &HashMap<K, Arc<RwLock<V>>>,
    serializer: S,
) -> StdResult<S::Ok, S::Error> {
    let mut seq = serializer.serialize_seq(Some(map.len()))?;

    for value in map.values() {
        seq.serialize_element(&*value.read())?;
    }

    seq.end()
}

#[cfg(all(feature = "cache", feature = "model"))]
pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Result<bool> {
    let cache = CACHE.read();
    let current_user = &cache.user;

    let channel = match cache.channel(channel_id) {
        Some(channel) => channel,
        None => return Err(Error::Model(ModelError::ItemMissing)),
    };

    let guild_id = match channel {
        Channel::Guild(channel) => channel.read().guild_id,
        Channel::Group(_) | Channel::Private(_) | Channel::Category(_) => {
            // Both users in DMs, and all users in groups and maybe all channels in categories will
            // have the same
            // permissions.
            //
            // The only exception to this is when the current user is blocked by
            // the recipient in a DM channel, which results in the current user
            // not being able to send messages.
            //
            // Since serenity can't _reasonably_ check and keep track of these,
            // just assume that all permissions are granted and return `true`.
            return Ok(true);
        },
    };

    let guild = match cache.guild(guild_id) {
        Some(guild) => guild,
        None => return Err(Error::Model(ModelError::ItemMissing)),
    };

    let perms = guild
        .read()
        .permissions_in(channel_id, current_user.id);

    permissions.remove(perms);

    Ok(permissions.is_empty())
}

macro_rules! num_visitors {
    ($($visitor:ident: $type:ty),*) => {
        $(
            #[derive(Debug)]
            pub struct $visitor;

            impl<'de> Visitor<'de> for $visitor {
                type Value = $type;

                fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
                    formatter.write_str("identifier")
                }

                fn visit_str<E: DeError>(self, v: &str) -> StdResult<Self::Value, E> {
                    v.parse::<$type>().map_err(|_| {
                        let mut s = String::with_capacity(32);
                        s.push_str("Unknown ");
                        s.push_str(stringify!($type));
                        s.push_str(" value: ");
                        s.push_str(v);

                        DeError::custom(s)
                    })
                }

                fn visit_i64<E: DeError>(self, v: i64) -> StdResult<Self::Value, E> { Ok(v as $type) }

                fn visit_u64<E: DeError>(self, v: u64) -> StdResult<Self::Value, E> { Ok(v as $type) }
            }
        )*
    }
}

num_visitors!(U16Visitor: u16, U64Visitor: u64);
<commit_msg>Handle serde_json's "arbitrary precision" feature<commit_after>use parking_lot::RwLock;
use serde::de::Error as DeError;
use serde::de::MapAccess;
use serde::ser::{SerializeSeq, Serialize, Serializer};
use std::{
    collections::HashMap,
    hash::Hash,
    sync::Arc
};
use super::prelude::*;

#[cfg(feature = "cache")]
use internal::prelude::*;

#[cfg(all(feature = "cache", feature = "model"))]
use super::permissions::Permissions;
#[cfg(all(feature = "cache", feature = "model"))]
use CACHE;

pub fn default_true() -> bool {
    true
}

pub fn deserialize_emojis<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<EmojiId, Emoji>, D::Error> {
    let vec: Vec<Emoji> = Deserialize::deserialize(deserializer)?;
    let mut emojis = HashMap::new();

    for emoji in vec {
        emojis.insert(emoji.id, emoji);
    }

    Ok(emojis)
}

pub fn deserialize_guild_channels<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<ChannelId, Arc<RwLock<GuildChannel>>>, D::Error> {
    let vec: Vec<GuildChannel> = Deserialize::deserialize(deserializer)?;
    let mut map = HashMap::new();

    for channel in vec {
        map.insert(channel.id, Arc::new(RwLock::new(channel)));
    }

    Ok(map)
}

pub fn deserialize_members<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, Member>, D::Error> {
    let vec: Vec<Member> = Deserialize::deserialize(deserializer)?;
    let mut members = HashMap::new();

    for member in vec {
        let user_id = member.user.read().id;

        members.insert(user_id, member);
    }

    Ok(members)
}

pub fn deserialize_presences<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, Presence>, D::Error> {
    let vec: Vec<Presence> = Deserialize::deserialize(deserializer)?;
    let mut presences = HashMap::new();

    for presence in vec {
        presences.insert(presence.user_id, presence);
    }

    Ok(presences)
}

pub fn deserialize_private_channels<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<ChannelId, Channel>, D::Error> {
    let vec: Vec<Channel> = Deserialize::deserialize(deserializer)?;
    let mut private_channels = HashMap::new();

    for private_channel in vec {
        let id = match private_channel {
            Channel::Group(ref group) => group.read().channel_id,
            Channel::Private(ref channel) => channel.read().id,
            Channel::Guild(_) => unreachable!("Guild private channel decode"),
            Channel::Category(_) => unreachable!("Channel category private channel decode"),
        };

        private_channels.insert(id, private_channel);
    }

    Ok(private_channels)
}

pub fn deserialize_roles<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<RoleId, Role>, D::Error> {
    let vec: Vec<Role> = Deserialize::deserialize(deserializer)?;
    let mut roles = HashMap::new();

    for role in vec {
        roles.insert(role.id, role);
    }

    Ok(roles)
}

pub fn deserialize_single_recipient<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<Arc<RwLock<User>>, D::Error> {
    let mut users: Vec<User> = Deserialize::deserialize(deserializer)?;
    let user = if users.is_empty() {
        return Err(DeError::custom("Expected a single recipient"));
    } else {
        users.remove(0)
    };

    Ok(Arc::new(RwLock::new(user)))
}

pub fn deserialize_sync_user<'de, D>(deserializer: D)
    -> StdResult<Arc<RwLock<User>>, D::Error> where D: Deserializer<'de> {
    Ok(Arc::new(RwLock::new(User::deserialize(deserializer)?)))
}

pub fn serialize_sync_user<S: Serializer>(
    user: &Arc<RwLock<User>>,
    serializer: S,
) -> StdResult<S::Ok, S::Error> {
    User::serialize(&*user.read(), serializer)
}

pub fn deserialize_users<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, Arc<RwLock<User>>>, D::Error> {
    let vec: Vec<User> = Deserialize::deserialize(deserializer)?;
    let mut users = HashMap::new();

    for user in vec {
        users.insert(user.id, Arc::new(RwLock::new(user)));
    }

    Ok(users)
}

pub fn serialize_users<S: Serializer>(
    users: &HashMap<UserId, Arc<RwLock<User>>>,
    serializer: S
) -> StdResult<S::Ok, S::Error> {
    let mut seq = serializer.serialize_seq(Some(users.len()))?;

    for user in users.values() {
        seq.serialize_element(&*user.read())?;
    }

    seq.end()
}

pub fn deserialize_u16<'de, D: Deserializer<'de>>(deserializer: D) -> StdResult<u16, D::Error> {
    deserializer.deserialize_any(U16Visitor)
}

pub fn deserialize_u64<'de, D: Deserializer<'de>>(deserializer: D) -> StdResult<u64, D::Error> {
    deserializer.deserialize_any(U64Visitor)
}

pub fn deserialize_voice_states<'de, D: Deserializer<'de>>(
    deserializer: D)
    -> StdResult<HashMap<UserId, VoiceState>, D::Error> {
    let vec: Vec<VoiceState> = Deserialize::deserialize(deserializer)?;
    let mut voice_states = HashMap::new();

    for voice_state in vec {
        voice_states.insert(voice_state.user_id, voice_state);
    }

    Ok(voice_states)
}

pub fn serialize_gen_map<K: Eq + Hash, S: Serializer, V: Serialize>(
    map: &HashMap<K, V>,
    serializer: S,
) -> StdResult<S::Ok, S::Error> {
    let mut seq = serializer.serialize_seq(Some(map.len()))?;

    for value in map.values() {
        seq.serialize_element(&value)?;
    }

    seq.end()
}

pub fn serialize_gen_locked_map<K: Eq + Hash, S: Serializer, V: Serialize>(
    map: &HashMap<K, Arc<RwLock<V>>>,
    serializer: S,
) -> StdResult<S::Ok, S::Error> {
    let mut seq = serializer.serialize_seq(Some(map.len()))?;

    for value in map.values() {
        seq.serialize_element(&*value.read())?;
    }

    seq.end()
}

#[cfg(all(feature = "cache", feature = "model"))]
pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Result<bool> {
    let cache = CACHE.read();
    let current_user = &cache.user;

    let channel = match cache.channel(channel_id) {
        Some(channel) => channel,
        None => return Err(Error::Model(ModelError::ItemMissing)),
    };

    let guild_id = match channel {
        Channel::Guild(channel) => channel.read().guild_id,
        Channel::Group(_) | Channel::Private(_) | Channel::Category(_) => {
            // Both users in DMs, and all users in groups and maybe all channels in categories will
            // have the same
            // permissions.
            //
            // The only exception to this is when the current user is blocked by
            // the recipient in a DM channel, which results in the current user
            // not being able to send messages.
            //
            // Since serenity can't _reasonably_ check and keep track of these,
            // just assume that all permissions are granted and return `true`.
            return Ok(true);
        },
    };

    let guild = match cache.guild(guild_id) {
        Some(guild) => guild,
        None => return Err(Error::Model(ModelError::ItemMissing)),
    };

    let perms = guild
        .read()
        .permissions_in(channel_id, current_user.id);

    permissions.remove(perms);

    Ok(permissions.is_empty())
}

macro_rules! num_visitors {
    ($($visitor:ident: $type:ty),*) => {
        $(
            #[derive(Debug)]
            pub struct $visitor;

            impl<'de> Visitor<'de> for $visitor {
                type Value = $type;

                fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
                    formatter.write_str("identifier")
                }

                fn visit_str<E: DeError>(self, v: &str) -> StdResult<Self::Value, E> {
                    v.parse::<$type>().map_err(|_| {
                        let mut s = String::with_capacity(32);
                        s.push_str("Unknown ");
                        s.push_str(stringify!($type));
                        s.push_str(" value: ");
                        s.push_str(v);

                        DeError::custom(s)
                    })
                }

                fn visit_i64<E: DeError>(self, v: i64) -> StdResult<Self::Value, E> { Ok(v as $type) }

                fn visit_u64<E: DeError>(self, v: u64) -> StdResult<Self::Value, E> { Ok(v as $type) }

                // This is called when serde_json's `arbitrary_precision` feature is enabled.
                fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> StdResult<Self::Value, A::Error> {
                    struct Id {
                        num: $type,
                    }

                    struct StrVisitor;

                    impl<'de> Visitor<'de> for StrVisitor {
                        type Value = $type;

                        fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {
                            formatter.write_str("string")
                        }

                        fn visit_str<E: DeError>(self, s: &str) -> StdResult<Self::Value, E> { s.parse().map_err(E::custom) }
                        fn visit_string<E: DeError>(self, s: String) -> StdResult<Self::Value, E> { s.parse().map_err(E::custom) }
                    }

                    impl<'de> Deserialize<'de> for Id {
                        fn deserialize<D: Deserializer<'de>>(des: D) -> StdResult<Self, D::Error> {
                            Ok(Id { num: des.deserialize_str(StrVisitor)? })
                        }
                    }

                    map.next_value::<Id>().map(|id| id.num)
                }
            }
        )*
    }
}

num_visitors!(U16Visitor: u16, U64Visitor: u64);
<|endoftext|>


<commit_before>use std::collections::hashmap::{HashMap};
use entity::{Entity};
use serialize::{Decodable, Decoder, Encodable, Encoder};
use location::{Location};

/// Entities can be placed either on open locations or inside other entities.
/// A sum type will represent this nicely.
#[deriving(Eq, PartialEq, Clone, Hash, Show, Encodable, Decodable)]
pub enum Place {
    At(Location),
    In(Entity),
}

/// Spatial index for game entities
pub struct Spatial {
    place_to_entities: HashMap<Place, Vec<Entity>>,
    entity_to_place: HashMap<Entity, Place>,
}

impl Spatial {
    pub fn new() -> Spatial {
        Spatial {
            place_to_entities: HashMap::new(),
            entity_to_place: HashMap::new(),
        }
    }

    fn insert(&mut self, e: Entity, p: Place) {
        if self.entity_to_place.contains_key(&e) {
            self.remove(e);
        }

        self.entity_to_place.insert(e, p);
        match self.place_to_entities.find_mut(&p) {
            Some(v) => { v.push(e); return; }
            _ => ()
        };
        // Didn't return above, that means this location isn't indexed
        // yet and needs a brand new container. (Can't do this in match
        // block because borrows.)
        self.place_to_entities.insert(p, vec![e]);
    }

    /// Insert an entity into space.
    pub fn insert_at(&mut self, e: Entity, loc: Location) {
        self.insert(e, At(loc));
    }

    /// Insert an entity into container.
    pub fn insert_in(&mut self, e: Entity, parent: Entity) {
        self.insert(e, In(parent));
    }

    /// Remove an entity from the space.
    pub fn remove(&mut self, e: Entity) {
        if !self.entity_to_place.contains_key(&e) { return; }

        let p = *self.entity_to_place.find(&e).unwrap();
        self.entity_to_place.remove(&e);
        {
            let v = self.place_to_entities.find_mut(&p).unwrap();
            assert!(v.len() > 0);
            if v.len() > 1 {
                // More than one entity present, remove this one, keep the
                // rest.
                let idx = v.as_slice().position_elem(&e).unwrap();
                v.swap_remove(idx);
                return;
            } else {
                // This was the only entity in the location.
                // Drop the entry for this location from the index.
                // (Need to drop out of scope for borrows reasons)
                assert!((*v)[0] == e);
            }
        }
        // We only end up here if we need to clear the container for the
        // location.
        self.place_to_entities.remove(&p);
    }

    fn entities(&self, p: Place) -> Vec<Entity> {
        match self.place_to_entities.find(&p) {
            None => vec![],
            Some(v) => v.clone(),
        }
    }

    /// List entities at a location.
    pub fn entities_at(&self, loc: Location) -> Vec<Entity> {
        self.entities(At(loc))
    }

    /// List entities in a container.
    pub fn entities_in(&self, parent: Entity) -> Vec<Entity> {
        self.entities(In(parent))
    }

    /// Return the place of an entity if the entity is present in the space.
    pub fn get(&self, e: Entity) -> Option<Place> {
        self.entity_to_place.find(&e).map(|&loc| loc)
    }

    /// Flatten to an easily serializable vector.
    fn dump(&self) -> Vec<Elt> {
        let mut ret = vec![];
        for (&e, &loc) in self.entity_to_place.iter() {
            ret.push(Elt(e, loc));
        }
        ret
    }

    /// Construct from the serialized vector.
    fn slurp(dump: Vec<Elt>) -> Spatial {
        let mut ret = Spatial::new();

        for &Elt(e, loc) in dump.iter() {
            ret.insert(e, loc);
        }
        ret
    }
}

#[deriving(Clone, Decodable, Encodable)]
struct Elt(Entity, Place);

impl<E, D:Decoder<E>> Decodable<D, E> for Spatial {
    fn decode(d: &mut D) -> Result<Spatial, E> {
        Ok(Spatial::slurp(try!(Decodable::decode(d))))
    }
}

impl<E, S:Encoder<E>> Encodable<S, E> for Spatial {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        self.dump().encode(s)
    }
}
<commit_msg>Check for cyclic containment, handle contents of removed container<commit_after>use std::collections::hashmap::{HashMap};
use entity::{Entity};
use serialize::{Decodable, Decoder, Encodable, Encoder};
use location::{Location};

/// Entities can be placed either on open locations or inside other entities.
/// A sum type will represent this nicely.
#[deriving(Eq, PartialEq, Clone, Hash, Show, Encodable, Decodable)]
pub enum Place {
    At(Location),
    In(Entity),
}

/// Spatial index for game entities
pub struct Spatial {
    place_to_entities: HashMap<Place, Vec<Entity>>,
    entity_to_place: HashMap<Entity, Place>,
}

impl Spatial {
    pub fn new() -> Spatial {
        Spatial {
            place_to_entities: HashMap::new(),
            entity_to_place: HashMap::new(),
        }
    }

    fn insert(&mut self, e: Entity, p: Place) {
        if self.entity_to_place.contains_key(&e) {
            self.remove(e);
        }

        self.entity_to_place.insert(e, p);
        match self.place_to_entities.find_mut(&p) {
            Some(v) => { v.push(e); return; }
            _ => ()
        };
        // Didn't return above, that means this location isn't indexed
        // yet and needs a brand new container. (Can't do this in match
        // block because borrows.)
        self.place_to_entities.insert(p, vec![e]);
    }

    /// Insert an entity into space.
    pub fn insert_at(&mut self, e: Entity, loc: Location) {
        self.insert(e, At(loc));
    }

    /// Return whether the parent entity or an entity contained in the parent
    /// entity contains entity e.
    pub fn contains(&self, parent: Entity, e: Entity) -> bool {
        match self.entity_to_place.find(&e) {
            Some(&In(p)) if p == parent => true,
            Some(&In(p)) => self.contains(parent, p),
            _ => false
        }
    }

    /// Insert an entity into container.
    pub fn insert_in(&mut self, e: Entity, parent: Entity) {
        assert!(!self.contains(e, parent), "Trying to create circular containment");
        self.insert(e, In(parent));
    }

    /// Remove an entity from the space. Other entities that were in the
    /// entity to be removed will be added in the place the entity occupied.
    pub fn remove(&mut self, e: Entity) {
        if !self.entity_to_place.contains_key(&e) { return; }

        let p = *self.entity_to_place.find(&e).unwrap();

        // Pop out the contents.
        for &content in self.entities_in(e).iter() {
            self.insert(content, p);
        }

        self.entity_to_place.remove(&e);
        {
            let v = self.place_to_entities.find_mut(&p).unwrap();
            assert!(v.len() > 0);
            if v.len() > 1 {
                // More than one entity present, remove this one, keep the
                // rest.
                let idx = v.as_slice().position_elem(&e).unwrap();
                v.swap_remove(idx);
                return;
            } else {
                // This was the only entity in the location.
                // Drop the entry for this location from the index.
                // (Need to drop out of scope for borrows reasons)
                assert!((*v)[0] == e);
            }
        }
        // We only end up here if we need to clear the container for the
        // location.
        self.place_to_entities.remove(&p);
    }

    fn entities(&self, p: Place) -> Vec<Entity> {
        match self.place_to_entities.find(&p) {
            None => vec![],
            Some(v) => v.clone(),
        }
    }

    /// List entities at a location.
    pub fn entities_at(&self, loc: Location) -> Vec<Entity> {
        self.entities(At(loc))
    }

    /// List entities in a container.
    pub fn entities_in(&self, parent: Entity) -> Vec<Entity> {
        self.entities(In(parent))
    }

    /// Return the place of an entity if the entity is present in the space.
    pub fn get(&self, e: Entity) -> Option<Place> {
        self.entity_to_place.find(&e).map(|&loc| loc)
    }

    /// Flatten to an easily serializable vector.
    fn dump(&self) -> Vec<Elt> {
        let mut ret = vec![];
        for (&e, &loc) in self.entity_to_place.iter() {
            ret.push(Elt(e, loc));
        }
        ret
    }

    /// Construct from the serialized vector.
    fn slurp(dump: Vec<Elt>) -> Spatial {
        let mut ret = Spatial::new();

        for &Elt(e, loc) in dump.iter() {
            ret.insert(e, loc);
        }
        ret
    }
}

#[deriving(Clone, Decodable, Encodable)]
struct Elt(Entity, Place);

impl<E, D:Decoder<E>> Decodable<D, E> for Spatial {
    fn decode(d: &mut D) -> Result<Spatial, E> {
        Ok(Spatial::slurp(try!(Decodable::decode(d))))
    }
}

impl<E, S:Encoder<E>> Encodable<S, E> for Spatial {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        self.dump().encode(s)
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;
use std::env;
use std::path::{Path,PathBuf};
use util::{path_exists, is_dir};
use std::fs::{read_dir};
use toml;

// otry is 'option try'
macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

// converts errors into None
macro_rules! otry2 {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return None } })
}

fn find_src_via_lockfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let lock_table = parser.parse().unwrap();

    debug!("find_src_via_lockfile found lock table {:?}", lock_table);

    let t = match lock_table.get("package") {
        Some(&toml::Value::Array(ref t1)) => t1,
        _ => return None
    };

    for item in t {
        if let &toml::Value::Table(ref t) = item {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                if name.replace("-", "_") == kratename {
                    debug!("found matching crate {:?}", t);
                    let version = otry!(getstr(t, "version"));
                    let source = otry!(getstr(t, "source"));

                    if Some("registry") == source.split("+").nth(0) {
                        return get_versioned_cratefile(name, &version);
                    } else if Some("git") == source.split("+").nth(0) {
                        let sha1 = otry!(source.split("#").last());
                        let mut d = otry!(get_cargo_rootdir());
                        d.push("git");
                        d.push("checkouts");
                        d = otry!(find_git_src_dir(d, name, &sha1));
                        d.push("src");
                        d.push("lib.rs");
                        return Some(d);
                    }
                }
            }
        }
    }
    None
}

fn get_cargo_rootdir() -> Option<PathBuf> {
    match env::var_os("CARGO_HOME") {
        Some(x) =>
        {
            let d = PathBuf::from(x);
            if path_exists(&d) {
                return Some(d)
            } else {
                return None
            };
        },
        None => ()
    };

    let mut d = otry!(env::home_dir());

    // try multirust first, since people with multirust installed will often still
    // have an old .cargo directory lying around
    d.push(".multirust");
    d.push("default");
    if let Ok(mut multirustdefault) = File::open(&d) {
        let mut s = String::new();
        otry2!(multirustdefault.read_to_string(&mut s));
        d.pop();
        d.push("toolchains");
        d.push(s.trim());
        d.push("cargo");
        debug!("get_cargo_rootdir root is {:?}",d);
        return Some(d)
    }

    d.pop();
    d.pop();
    d.push(".cargo");
    if path_exists(&d) {
        Some(d)
    } else {
        None
    }
}

fn get_versioned_cratefile(kratename: &str, version: &str) -> Option<PathBuf> {
    let mut d = otry!(get_cargo_rootdir());
    d.push("registry");
    d.push("src");
    d = otry!(find_cratesio_src_dir(d));

    // if version=* then search for the first matching folder
    if version == "*" {
        use std::fs::read_dir;
        let mut start_path = d.clone();
        start_path.push(kratename);
        let start_name = start_path.to_str().unwrap();

        if let Ok(reader) = read_dir(d) {
            if let Some(path) = reader
                                .map(|entry| entry.unwrap().path())
                                .find(|path| path.to_str().unwrap().starts_with(start_name)) {
                d = path.clone();
            } else {
                return None;
            }
        } else { return None; }
    } else {
        d.push(kratename.to_string() + "-" + &version);
    }

    d.push("src");
    debug!("crate path {:?}",d);

    // First, check for package name at root (src/kratename/lib.rs)
    d.push(kratename.to_string());
    d.push("lib.rs");
    if let Err(_) = File::open(&d) {
        // It doesn't exist, so assume src/lib.rs
        d.pop();
        d.pop();
        d.push("lib.rs");
    }
    debug!("crate path with lib.rs {:?}",d);

    if let Err(_) = File::open(&d) {
        return None;
    }

    Some(d)
 }

fn find_src_via_tomlfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    // only look for 'path' references here.
    // We find the git and crates.io stuff via the lockfile

    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = otry!(parser.parse());

    // is it this lib?  (e.g. you're searching from tests to find the main library crate)
    if let Some(&toml::Value::Table(ref t)) = table.get("lib") {
        if let Some(&toml::Value::String(ref name)) = t.get("name") {
            if name == kratename {
                debug!("found {} as lib entry in Cargo.toml", kratename);
                if let Some(&toml::Value::String(ref pathstr)) = t.get("path") {
                    let p = Path::new(pathstr);
                    let libpath = otry!(cargofile.parent()).join(p);
                    return Some(libpath);
                }
            }
        }
    }

    // otherwise search the dependencies
    let t = match table.get("dependencies") {
        Some(&toml::Value::Table(ref t)) => t,
        _ => return None
    };

    let mut name = kratename;
    let value = if kratename.contains('_') {
        t.iter().find(|&(k, _)| k.replace("-", "_") == name).map(|(k,v)| {
            name = k;
            v
        })
    } else {
        t.get(kratename)
    };

    match value {
        Some(&toml::Value::Table(ref t)) => {
            // local directory
            let relative_path = otry!(getstr(t, "path"));
            return Some(otry!(cargofile.parent())
                        .join(relative_path)
                        .join("src")
                        .join("lib.rs"));
        },
        Some(&toml::Value::String(ref version)) => {
            // versioned crate
            return get_versioned_cratefile(name, version);
        }
        _ => return None
    }
}

fn find_cratesio_src_dir(d: PathBuf) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with("github.com-") {
                    return Some(path.clone());
                }
            }
        }
    }
    None
}

fn find_git_src_dir(d: PathBuf, name: &str, sha1: &str) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with(name) {
                    let mut d = path.clone();

                    // dirname can be the sha1 or master.
                    d.push(sha1);

                    if !is_dir(d.as_path()) {
                        d.pop();
                        d.push("master");
                    }

                    let retval = d.clone();

                    // check that the checkout matches the commit sha1
                    d.push(".git");
                    d.push("refs");
                    d.push("heads");
                    d.push("master");

                    let mut headref = String::new();
                    otry2!(otry2!(File::open(d)).read_to_string(&mut headref));

                    debug!("git headref is {:?}", headref);

                    if headref.ends_with("\n") {
                        headref.pop();
                    }

                    if sha1 == headref {
                        return Some(retval);
                    }
                }
            }
        }
    }
    None
}

fn getstr(t: &toml::Table, k: &str) -> Option<String> {
    match t.get(k) {
        Some(&toml::Value::String(ref s)) => Some(s.clone()),
        _ => None
    }
}

fn find_cargo_tomlfile(currentfile: &Path) -> Option<PathBuf> {
    let mut f = currentfile.to_path_buf();
    f.push("Cargo.toml");
    if path_exists(f.as_path()) {
        return Some(f);
    } else {
        if f.pop() && f.pop() {
            return find_cargo_tomlfile(&f);
        } else {
            None
        }
    }
}

pub fn get_crate_file(kratename: &str, from_path: &Path) -> Option<PathBuf> {
    if let Some(tomlfile) = find_cargo_tomlfile(from_path) {
        // look in the lockfile first, if there is one
        debug!("get_crate_file tomlfile is {:?}", tomlfile);
        let mut lockfile = tomlfile.clone();
        lockfile.pop();
        lockfile.push("Cargo.lock");
        if path_exists(lockfile.as_path()) {
            if let Some(f) = find_src_via_lockfile(kratename, &lockfile) {
                return Some(f);
            }
        }

        // oh, no luck with the lockfile. Try the tomlfile
        return find_src_via_tomlfile(kratename, &tomlfile)
    }
    None
}
<commit_msg>cargo: search multirust overrides<commit_after>use std::fs::File;
use std::io::Read;
use std::env;
use std::path::{Path,PathBuf};
use util::{path_exists, is_dir};
use std::fs::{read_dir};
use toml;

// otry is 'option try'
macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

// converts errors into None
macro_rules! otry2 {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return None } })
}

// converts errors into message + empty vec
macro_rules! vectry {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return Vec::new() } })
}

fn find_src_via_lockfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let lock_table = parser.parse().unwrap();

    debug!("find_src_via_lockfile found lock table {:?}", lock_table);

    let t = match lock_table.get("package") {
        Some(&toml::Value::Array(ref t1)) => t1,
        _ => return None
    };

    for item in t {
        if let &toml::Value::Table(ref t) = item {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                if name.replace("-", "_") == kratename {
                    debug!("found matching crate {:?}", t);
                    let version = otry!(getstr(t, "version"));
                    let source = otry!(getstr(t, "source"));

                    if Some("registry") == source.split("+").nth(0) {
                        return get_versioned_cratefile(name, &version, cargofile);
                    } else if Some("git") == source.split("+").nth(0) {
                        let sha1 = otry!(source.split("#").last());
                        let mut d = otry!(get_cargo_rootdir(cargofile));
                        d.push("git");
                        d.push("checkouts");
                        d = otry!(find_git_src_dir(d, name, &sha1));
                        d.push("src");
                        d.push("lib.rs");
                        return Some(d);
                    }
                }
            }
        }
    }
    None
}

fn get_cargo_rootdir(cargofile: &Path) -> Option<PathBuf> {
    match env::var_os("CARGO_HOME") {
        Some(x) =>
        {
            let d = PathBuf::from(x);
            if path_exists(&d) {
                return Some(d)
            } else {
                return None
            };
        },
        None => ()
    };

    let mut d = otry!(env::home_dir());

    // try multirust first, since people with multirust installed will often still
    // have an old .cargo directory lying around
    d.push(".multirust");

    d.push("overrides");
    if let Ok(mut multirust_overides) = File::open(&d) {
        let mut s = String::new();
        otry2!(multirust_overides.read_to_string(&mut s));
        for line in s.lines() {
            let overridepath = line.split(";").nth(0).unwrap();
            if cargofile.starts_with(overridepath) {
                let overridepath = line.split(";").nth(1).unwrap();
                d.pop();
                d.push("toolchains");
                d.push(overridepath.trim());
                d.push("cargo");
                debug!("get_cargo_rootdir override root is {:?}",d);
                return Some(d)
            }
        }
    }

    d.pop();
    d.push("default");
    if let Ok(mut multirustdefault) = File::open(&d) {
        let mut s = String::new();
        otry2!(multirustdefault.read_to_string(&mut s));
        d.pop();
        d.push("toolchains");
        d.push(s.trim());
        d.push("cargo");
        debug!("get_cargo_rootdir root is {:?}",d);
        return Some(d)
    }

    d.pop();
    d.pop();
    d.push(".cargo");
    if path_exists(&d) {
        Some(d)
    } else {
        None
    }
}

fn get_versioned_cratefile(kratename: &str, version: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut d = otry!(get_cargo_rootdir(cargofile));
    d.push("registry");
    d.push("src");

    for mut d in find_cratesio_src_dirs(d) {

        // if version=* then search for the first matching folder
        if version == "*" {
            use std::fs::read_dir;
            let mut start_path = d.clone();
            start_path.push(kratename);
            let start_name = start_path.to_str().unwrap();

            if let Ok(reader) = read_dir(d) {
                if let Some(path) = reader
                    .map(|entry| entry.unwrap().path())
                    .find(|path| path.to_str().unwrap().starts_with(start_name)) {
                        d = path.clone();
                    } else {
                        continue;
                    }
            } else {
                continue;
            }
        } else {
            d.push(kratename.to_string() + "-" + &version);
        }

        d.push("src");
        debug!("crate path {:?}",d);

        // First, check for package name at root (src/kratename/lib.rs)
        d.push(kratename.to_string());
        d.push("lib.rs");
        if let Err(_) = File::open(&d) {
            // It doesn't exist, so assume src/lib.rs
            d.pop();
            d.pop();
            d.push("lib.rs");
        }
        debug!("crate path with lib.rs {:?}",d);

        if let Err(_) = File::open(&d) {
            return continue;
        }

        return Some(d)
    }
    return None;
 }

fn find_src_via_tomlfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    // only look for 'path' references here.
    // We find the git and crates.io stuff via the lockfile

    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = otry!(parser.parse());

    // is it this lib?  (e.g. you're searching from tests to find the main library crate)
    if let Some(&toml::Value::Table(ref t)) = table.get("lib") {
        if let Some(&toml::Value::String(ref name)) = t.get("name") {
            if name == kratename {
                debug!("found {} as lib entry in Cargo.toml", kratename);
                if let Some(&toml::Value::String(ref pathstr)) = t.get("path") {
                    let p = Path::new(pathstr);
                    let libpath = otry!(cargofile.parent()).join(p);
                    return Some(libpath);
                }
            }
        }
    }

    // otherwise search the dependencies
    let t = match table.get("dependencies") {
        Some(&toml::Value::Table(ref t)) => t,
        _ => return None
    };

    let mut name = kratename;
    let value = if kratename.contains('_') {
        t.iter().find(|&(k, _)| k.replace("-", "_") == name).map(|(k,v)| {
            name = k;
            v
        })
    } else {
        t.get(kratename)
    };

    match value {
        Some(&toml::Value::Table(ref t)) => {
            // local directory
            let relative_path = otry!(getstr(t, "path"));
            return Some(otry!(cargofile.parent())
                        .join(relative_path)
                        .join("src")
                        .join("lib.rs"));
        },
        Some(&toml::Value::String(ref version)) => {
            // versioned crate
            return get_versioned_cratefile(name, version, cargofile);
        }
        _ => return None
    }
}

fn find_cratesio_src_dirs(d: PathBuf) -> Vec<PathBuf> {
    let mut out = Vec::new();
    for entry in vectry!(read_dir(d)) {
        let path = vectry!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with("github.com-") {
                    out.push(path.clone());
                }
            }
        }
    }
    out
}

fn find_git_src_dir(d: PathBuf, name: &str, sha1: &str) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with(name) {
                    let mut d = path.clone();

                    // dirname can be the sha1 or master.
                    d.push(sha1);

                    if !is_dir(d.as_path()) {
                        d.pop();
                        d.push("master");
                    }

                    let retval = d.clone();

                    // check that the checkout matches the commit sha1
                    d.push(".git");
                    d.push("refs");
                    d.push("heads");
                    d.push("master");

                    let mut headref = String::new();
                    otry2!(otry2!(File::open(d)).read_to_string(&mut headref));

                    debug!("git headref is {:?}", headref);

                    if headref.ends_with("\n") {
                        headref.pop();
                    }

                    if sha1 == headref {
                        return Some(retval);
                    }
                }
            }
        }
    }
    None
}

fn getstr(t: &toml::Table, k: &str) -> Option<String> {
    match t.get(k) {
        Some(&toml::Value::String(ref s)) => Some(s.clone()),
        _ => None
    }
}

fn find_cargo_tomlfile(currentfile: &Path) -> Option<PathBuf> {
    let mut f = currentfile.to_path_buf();
    f.push("Cargo.toml");
    if path_exists(f.as_path()) {
        return Some(f);
    } else {
        if f.pop() && f.pop() {
            return find_cargo_tomlfile(&f);
        } else {
            None
        }
    }
}

pub fn get_crate_file(kratename: &str, from_path: &Path) -> Option<PathBuf> {
    if let Some(tomlfile) = find_cargo_tomlfile(from_path) {
        // look in the lockfile first, if there is one
        debug!("get_crate_file tomlfile is {:?}", tomlfile);
        let mut lockfile = tomlfile.clone();
        lockfile.pop();
        lockfile.push("Cargo.lock");
        if path_exists(lockfile.as_path()) {
            if let Some(f) = find_src_via_lockfile(kratename, &lockfile) {
                return Some(f);
            }
        }

        // oh, no luck with the lockfile. Try the tomlfile
        return find_src_via_tomlfile(kratename, &tomlfile)
    }
    None
}
<|endoftext|>


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

use gltf;

use render::math::*;
use render::mesh::Mesh;
use render::scene::Scene;
use shader::Shader;

pub struct Node {
    // TODO!!: camera?
    pub children: Vec<Node>,
    pub matrix: Matrix4,
    pub mesh: Option<Rc<Mesh>>,
    pub rotation: Quaternion,
    pub scale: Vector3,
    pub translation: Vector3,
    // TODO: weights
    // weights_id: usize,
    pub name: Option<String>,

    final_transform: Matrix4, // including parent transforms
    model_loc: Option<i32>,
}

impl Node {
    pub fn from_gltf(g_node: gltf::scene::Node, scene: &mut Scene) -> Node {
        let m = &g_node.matrix();
        let matrix = Matrix4::new(
            m[0], m[1], m[2], m[2],
            m[4], m[5], m[6], m[7],
            m[8], m[9], m[10], m[11],
            m[12], m[13], m[14], m[15],
        );
        let r = &g_node.rotation();
        let rotation = Quaternion::new(r[3], r[0], r[1], r[2]); // NOTE: different element order!
        let mut mesh = None;
        if let Some(g_mesh) = g_node.mesh() {
            if let Some(g_mesh) = scene.meshes.iter().find(|mesh| (***mesh).index == g_mesh.index()) {
                mesh = Some(g_mesh.clone());
            }

            if mesh.is_none() { // not using else due to borrow-checking madness
                mesh = Some(Rc::new(Mesh::from_gltf(g_mesh)));
                scene.meshes.push(mesh.clone().unwrap());
            }
        }
        Node {
            children: g_node.children()
                .map(|g_node| Node::from_gltf(g_node, scene))
                .collect(),
            // TODO: why doesn't this work?
            // matrix: Matrix4::from(&g_node.matrix()),
            matrix: matrix,
            mesh: mesh,
            rotation: rotation,
            scale: Vector3::from(g_node.scale()),
            translation: Vector3::from(g_node.translation()),
            name: g_node.name().map(|s| s.into()),

            final_transform: Matrix4::identity(),
            model_loc: None,
        }
    }

    pub fn update_transform(&mut self, parent_transform: &Matrix4) {
        self.final_transform = *parent_transform;

        if !self.matrix.is_identity() {
            self.final_transform = self.final_transform * self.matrix;
        }
        else {
            // TODO?: detect if all default and set None? does NOT happen for any sample model
            self.final_transform = self.final_transform *
                Matrix4::from_translation(self.translation) *
                Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, self.scale.z) *
                Matrix4::from(self.rotation);
        }

        for node in &mut self.children {
            node.update_transform(&self.final_transform);
        }
    }

    pub fn draw(&mut self, shader: &mut Shader) {
        if let Some(ref mesh) = self.mesh {
            unsafe {
                if self.model_loc.is_none() {
                    self.model_loc = Some(shader.uniform_location("model"));
                }
                shader.set_mat4(self.model_loc.unwrap(), &self.final_transform);
            }

            (*mesh).draw(shader);
        }
        for node in &mut self.children {
            node.draw(shader);
        }
    }
}
<commit_msg>fix matrix parsing<commit_after>use std::rc::Rc;

use gltf;

use render::math::*;
use render::mesh::Mesh;
use render::scene::Scene;
use shader::Shader;

pub struct Node {
    // TODO!!: camera?
    pub children: Vec<Node>,
    pub matrix: Matrix4,
    pub mesh: Option<Rc<Mesh>>,
    pub rotation: Quaternion,
    pub scale: Vector3,
    pub translation: Vector3,
    // TODO: weights
    // weights_id: usize,
    pub name: Option<String>,

    final_transform: Matrix4, // including parent transforms
    model_loc: Option<i32>,
}

impl Node {
    pub fn from_gltf(g_node: gltf::scene::Node, scene: &mut Scene) -> Node {
        let m = &g_node.matrix();
        let matrix = Matrix4::new(
            m[0], m[1], m[2], m[3],
            m[4], m[5], m[6], m[7],
            m[8], m[9], m[10], m[11],
            m[12], m[13], m[14], m[15],
        );
        let r = &g_node.rotation();
        let rotation = Quaternion::new(r[3], r[0], r[1], r[2]); // NOTE: different element order!
        let mut mesh = None;
        if let Some(g_mesh) = g_node.mesh() {
            if let Some(g_mesh) = scene.meshes.iter().find(|mesh| (***mesh).index == g_mesh.index()) {
                mesh = Some(g_mesh.clone());
            }

            if mesh.is_none() { // not using else due to borrow-checking madness
                mesh = Some(Rc::new(Mesh::from_gltf(g_mesh)));
                scene.meshes.push(mesh.clone().unwrap());
            }
        }
        Node {
            children: g_node.children()
                .map(|g_node| Node::from_gltf(g_node, scene))
                .collect(),
            // TODO: why doesn't this work?
            // matrix: Matrix4::from(&g_node.matrix()),
            matrix: matrix,
            mesh: mesh,
            rotation: rotation,
            scale: Vector3::from(g_node.scale()),
            translation: Vector3::from(g_node.translation()),
            name: g_node.name().map(|s| s.into()),

            final_transform: Matrix4::identity(),
            model_loc: None,
        }
    }

    pub fn update_transform(&mut self, parent_transform: &Matrix4) {
        self.final_transform = *parent_transform;

        if !self.matrix.is_identity() {
            self.final_transform = self.final_transform * self.matrix;
        }
        else {
            // TODO?: detect if all default and set None? does NOT happen for any sample model
            self.final_transform = self.final_transform *
                Matrix4::from_translation(self.translation) *
                Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, self.scale.z) *
                Matrix4::from(self.rotation);
        }

        for node in &mut self.children {
            node.update_transform(&self.final_transform);
        }
    }

    pub fn draw(&mut self, shader: &mut Shader) {
        if let Some(ref mesh) = self.mesh {
            unsafe {
                if self.model_loc.is_none() {
                    self.model_loc = Some(shader.uniform_location("model"));
                }
                shader.set_mat4(self.model_loc.unwrap(), &self.final_transform);
            }

            (*mesh).draw(shader);
        }
        for node in &mut self.children {
            node.draw(shader);
        }
    }
}
<|endoftext|>


<commit_before>use JITVal = jit::Value;
use jit::{
    get_type,
    Function,
    Compile,
    UByte,
    SysChar,
    SysBool,
    NInt,
    NUInt,
    Int,
    UInt,
    Pointer,
    Float64
};
use JSVal = front::stdlib::value::Value;
use front::stdlib::value::{Value, VNull, to_value};
use front::stdlib::value::ResultValue;
use front::run::executor::Executor;
use std::gc::GC;
use std::c_str::CString;
/// A JIT executor
pub struct JitExecutor {
    global: JSVal
}
impl JitExecutor {
    /// Create a new JIT executor
    pub fn new() -> JitExecutor {
        JitExecutor {
            global: Value::new_global()
        }
    }

}
impl<'a> Executor<(JITVal<'a>, &'a Function<'a>)> for JitExecutor {
    #[inline]
    fn get_global_obj(&self) -> JSVal {
        self.global
    }
    fn execute(&self, comp:&(JITVal<'a>, &'a Function<'a>)) -> ResultValue {
        let &(ref val, ref func) = comp;
        func.insn_return(&convert_to_value(*func, val));
        func.set_optimization_level(5);
        func.set_recompilable();
        func.compile();
        Ok(func.with_closure3(|run:fn(JSVal, JSVal, JSVal) -> JSVal| {
            run(self.global, self.global, self.global)
        }))
    }
}

fn convert_to_value<'a>(func:&Function<'a>, val:&'a JITVal<'a>) -> JITVal<'a> {
    let val_type = val.get_type();
    let val_kind = val_type.get_kind();
    if val_kind.contains(SysBool) || val_kind.contains(UByte) {
        let bool_value = to_value::<bool>;
        let sig = get_type::<fn(bool) -> *const int>();
        func.insn_call_native1("bool_value", bool_value, &sig, &mut [val])
    } else if val_kind.contains(Pointer) {
        let ref_t = val_type.get_ref();
        if ref_t.get_kind().contains(SysChar) {
            fn string_value(val: &i8) -> JSVal {
                unsafe {
                    let text = CString::new(val, false);
                    to_value(text.as_str().unwrap().into_string())
                }
            }
            let sig = get_type::<fn(String) -> *const int>();
            func.insn_call_native1("string_value", string_value, &sig, &mut [val])
        } else {
            fn ptr_value(ptr: &i8) -> JSVal {
                match ptr.to_uint() {
                    0u => JSVal::undefined(),
                    1u => JSVal {
                        ptr: box(GC) VNull
                    },
                    ptr => fail!("Invalid pointer: {}", ptr)
                }
            }
            let sig = get_type::<fn(&i8) -> *const int>();
            func.insn_call_native1("ptr_value", ptr_value, &sig, &mut [val])
        }
    } else if val_kind.contains(Int) || val_kind.contains(UInt) {
        let int_value = to_value::<i32>;
        let sig = get_type::<fn(i32) -> *const int>();
        func.insn_call_native1("int_value", int_value, &sig, &mut [val])
    } else if val_kind.contains(NInt) || val_kind.contains(NUInt) {
        fn sys_int_value(num:int) -> JSVal {
            to_value::<i32>(num as i32)
        }
        let sig = get_type::<fn(int) -> *const int>();
        func.insn_call_native1("sys_int_value", sys_int_value, &sig, &mut [val])
    } else if val_kind.contains(Float64) {
        let float_value = to_value::<f64>;
        let sig = get_type::<fn(f64) -> *const int>();
        func.insn_call_native1("float_value", float_value, &sig, &mut [val])
    } else {
        fail!("Invalid kind {}", val_kind.bits())
    }
}<commit_msg>Update `insn_call_native1` calls to give an Option of a string<commit_after>use JITVal = jit::Value;
use jit::{
    get_type,
    Function,
    Compile,
    UByte,
    SysChar,
    SysBool,
    NInt,
    NUInt,
    Int,
    UInt,
    Pointer,
    Float64
};
use JSVal = front::stdlib::value::Value;
use front::stdlib::value::{Value, VNull, to_value};
use front::stdlib::value::ResultValue;
use front::run::executor::Executor;
use std::gc::GC;
use std::c_str::CString;
/// A JIT executor
pub struct JitExecutor {
    global: JSVal
}
impl JitExecutor {
    /// Create a new JIT executor
    pub fn new() -> JitExecutor {
        JitExecutor {
            global: Value::new_global()
        }
    }

}
impl<'a> Executor<(JITVal<'a>, &'a Function<'a>)> for JitExecutor {
    #[inline]
    fn get_global_obj(&self) -> JSVal {
        self.global
    }
    fn execute(&self, comp:&(JITVal<'a>, &'a Function<'a>)) -> ResultValue {
        let &(ref val, ref func) = comp;
        func.insn_return(&convert_to_value(*func, val));
        func.set_optimization_level(5);
        func.set_recompilable();
        func.compile();
        Ok(func.with_closure3(|run:fn(JSVal, JSVal, JSVal) -> JSVal| {
            run(self.global, self.global, self.global)
        }))
    }
}

fn convert_to_value<'a>(func:&Function<'a>, val:&'a JITVal<'a>) -> JITVal<'a> {
    let val_type = val.get_type();
    let val_kind = val_type.get_kind();
    if val_kind.contains(SysBool) || val_kind.contains(UByte) {
        let bool_value = to_value::<bool>;
        let sig = get_type::<fn(bool) -> *const int>();
        func.insn_call_native1(Some("bool_value"), bool_value, &sig, &mut [val])
    } else if val_kind.contains(Pointer) {
        let ref_t = val_type.get_ref();
        if ref_t.get_kind().contains(SysChar) {
            fn string_value(val: &i8) -> JSVal {
                unsafe {
                    let text = CString::new(val, false);
                    to_value(text.as_str().unwrap().into_string())
                }
            }
            let sig = get_type::<fn(String) -> *const int>();
            func.insn_call_native1(Some("string_value"), string_value, &sig, &mut [val])
        } else {
            fn ptr_value(ptr: &i8) -> JSVal {
                match ptr.to_uint() {
                    0u => JSVal::undefined(),
                    1u => JSVal {
                        ptr: box(GC) VNull
                    },
                    ptr => fail!("Invalid pointer: {}", ptr)
                }
            }
            let sig = get_type::<fn(&i8) -> *const int>();
            func.insn_call_native1(Some("ptr_value"), ptr_value, &sig, &mut [val])
        }
    } else if val_kind.contains(Int) || val_kind.contains(UInt) {
        let int_value = to_value::<i32>;
        let sig = get_type::<fn(i32) -> *const int>();
        func.insn_call_native1(Some("int_value"), int_value, &sig, &mut [val])
    } else if val_kind.contains(NInt) || val_kind.contains(NUInt) {
        fn sys_int_value(num:int) -> JSVal {
            to_value::<i32>(num as i32)
        }
        let sig = get_type::<fn(int) -> *const int>();
        func.insn_call_native1(Some("sys_int_value"), sys_int_value, &sig, &mut [val])
    } else if val_kind.contains(Float64) {
        let float_value = to_value::<f64>;
        let sig = get_type::<fn(f64) -> *const int>();
        func.insn_call_native1(Some("float_value"), float_value, &sig, &mut [val])
    } else {
        fail!("Invalid kind {}", val_kind.bits())
    }
}<|endoftext|>


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

//! A cell that with volatile setter and getter.

use std::kinds::marker;
use std::intrinsics::{volatile_load, volatile_store};
use std::cast::transmute_mut;

pub struct VolatileCell<T> {
  value: T,
  invariant: marker::InvariantType<T>,
}

impl<T> VolatileCell<T> {
  pub fn new(value: T) -> VolatileCell<T> {
    VolatileCell {
      value: value,
      invariant: marker::InvariantType::<T>,
    }
  }

  #[inline]
  pub fn get(&self) -> T {
    unsafe {
      volatile_load(&self.value)
    }
  }

  #[inline]
  pub fn set(&self, value: T) {
    unsafe {
      volatile_store(&mut (*transmute_mut(&self.value)), value)
    }
  }
}
<commit_msg>Remove deprecated transmute_mut call. Fixes #20.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A cell that with volatile setter and getter.

use std::kinds::marker;
use std::intrinsics::{volatile_load, volatile_store};
use std::cast::transmute_mut_unsafe;

pub struct VolatileCell<T> {
  value: T,
  invariant: marker::InvariantType<T>,
}

impl<T> VolatileCell<T> {
  pub fn new(value: T) -> VolatileCell<T> {
    VolatileCell {
      value: value,
      invariant: marker::InvariantType::<T>,
    }
  }

  #[inline]
  pub fn get(&self) -> T {
    unsafe {
      volatile_load(&self.value)
    }
  }

  #[inline]
  pub fn set(&self, value: T) {
    unsafe {
      volatile_store(&mut (*transmute_mut_unsafe(&self.value)), value)
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>auto merge of #10984 : huonw/rust/clean-raw, r=cmr<commit_after><|endoftext|>


<commit_before>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer,
    mutable depth: uint
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer,
        mutable depth: 1u
    };

    write_crate(ctxt, doc);
}

fn write_header(ctxt: ctxt, title: str) {
    let hashes = str::from_chars(vec::init_elt('#', ctxt.depth));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn subsection(ctxt: ctxt, f: fn&()) {
    ctxt.depth += 1u;
    f();
    ctxt.depth -= 1u;
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_header(ctxt, #fmt("Module `%s`", moddoc.name));
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        subsection(ctxt) {||
            write_fn(ctxt, fndoc);
        }
    }

    for moddoc in *moddoc.mods {
        subsection(ctxt) {||
            write_mod(ctxt, moddoc);
        }
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, #fmt("Function `%s`", doc.name));
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);
    write_args(ctxt, doc.args);
    write_return(ctxt, doc.return);
}

fn write_brief(
    ctxt: ctxt,
    brief: option<str>
) {
    alt brief {
      some(brief) {
        ctxt.w.write_line(brief);
        ctxt.w.write_line("");
      }
      none. { }
    }
}

fn write_desc(
    ctxt: ctxt,
    desc: option<str>
) {
    alt desc {
        some(desc) {
            ctxt.w.write_line(desc);
            ctxt.w.write_line("");
        }
        none. { }
    }
}

fn write_args(
    ctxt: ctxt,
    args: [(str, str)]
) {
    for (arg, desc) in args {
        ctxt.w.write_str("### Argument `" + arg + "`: ");
        ctxt.w.write_str(desc)
    }
}

fn write_return(
    ctxt: ctxt,
    return: option<doc::retdoc>
) {
    alt return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line("### Returns `" + ty + "`");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod tests {
    fn render(source: str) -> str {
        let srv = astsrv::mk_srv_from_str(source);
        let doc = extract::from_srv(srv, "");
        let doc = attr_pass::mk_pass()(srv, doc);
        write_markdown_str(doc)
    }

    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let srv = astsrv::mk_srv_from_str("");
        let doc = extract::from_srv(srv, "belch");
        let doc = attr_pass::mk_pass()(srv, doc);
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let markdown = render("fn func() { }");
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let markdown = render("mod moo { }");
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let markdown = render("mod morp { }");
        assert str::contains(markdown, "Module `morp`\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_fn_header_and_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "Function `a`\n\nbrief");
    }

    #[test]
    fn should_leve_blank_line_after_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "brief\n\n");
    }

    #[test]
    fn should_leve_blank_line_between_brief_and_desc() {
        let markdown = render(
            "#[doc(brief = \"brief\", desc = \"desc\")] fn a() { }"
        );
        assert str::contains(markdown, "brief\n\ndesc");
    }
}<commit_msg>rustdoc: Improve formatting of return type<commit_after>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer,
    mutable depth: uint
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer,
        mutable depth: 1u
    };

    write_crate(ctxt, doc);
}

fn write_header(ctxt: ctxt, title: str) {
    let hashes = str::from_chars(vec::init_elt('#', ctxt.depth));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn subsection(ctxt: ctxt, f: fn&()) {
    ctxt.depth += 1u;
    f();
    ctxt.depth -= 1u;
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_header(ctxt, #fmt("Module `%s`", moddoc.name));
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        subsection(ctxt) {||
            write_fn(ctxt, fndoc);
        }
    }

    for moddoc in *moddoc.mods {
        subsection(ctxt) {||
            write_mod(ctxt, moddoc);
        }
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, #fmt("Function `%s`", doc.name));
    write_brief(ctxt, doc.brief);
    write_desc(ctxt, doc.desc);
    write_args(ctxt, doc.args);
    write_return(ctxt, doc.return);
}

fn write_brief(
    ctxt: ctxt,
    brief: option<str>
) {
    alt brief {
      some(brief) {
        ctxt.w.write_line(brief);
        ctxt.w.write_line("");
      }
      none. { }
    }
}

fn write_desc(
    ctxt: ctxt,
    desc: option<str>
) {
    alt desc {
        some(desc) {
            ctxt.w.write_line(desc);
            ctxt.w.write_line("");
        }
        none. { }
    }
}

fn write_args(
    ctxt: ctxt,
    args: [(str, str)]
) {
    for (arg, desc) in args {
        ctxt.w.write_str("### Argument `" + arg + "`: ");
        ctxt.w.write_str(desc)
    }
}

fn write_return(
    ctxt: ctxt,
    return: option<doc::retdoc>
) {
    alt return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line(#fmt("Returns `%s`", ty));
            ctxt.w.write_line("");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod tests {
    fn render(source: str) -> str {
        let srv = astsrv::mk_srv_from_str(source);
        let doc = extract::from_srv(srv, "");
        let doc = attr_pass::mk_pass()(srv, doc);
        let doc = tystr_pass::mk_pass()(srv, doc);
        write_markdown_str(doc)
    }

    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let srv = astsrv::mk_srv_from_str("");
        let doc = extract::from_srv(srv, "belch");
        let doc = attr_pass::mk_pass()(srv, doc);
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let markdown = render("fn func() { }");
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let markdown = render("mod moo { }");
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let markdown = render("mod morp { }");
        assert str::contains(markdown, "Module `morp`\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_fn_header_and_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "Function `a`\n\nbrief");
    }

    #[test]
    fn should_leave_blank_line_after_brief() {
        let markdown = render("#[doc(brief = \"brief\")] fn a() { }");
        assert str::contains(markdown, "brief\n\n");
    }

    #[test]
    fn should_leave_blank_line_between_brief_and_desc() {
        let markdown = render(
            "#[doc(brief = \"brief\", desc = \"desc\")] fn a() { }"
        );
        assert str::contains(markdown, "brief\n\ndesc");
    }

    #[test]
    fn should_write_return_type_on_new_line() {
        let markdown = render("fn a() -> int { }");
        assert str::contains(markdown, "\nReturns `int`");
    }

    #[test]
    fn should_write_blank_line_between_return_type_and_next_header() {
        let markdown = render(
            "fn a() -> int { } \
             fn b() -> int { }"
        );
        assert str::contains(markdown, "Returns `int`\n\n##");
    }
}<|endoftext|>


<commit_before>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer,
    mutable depth: uint
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer,
        mutable depth: 1u
    };

    write_crate(ctxt, doc);
}

fn write_header(ctxt: ctxt, title: str) {
    let hashes = str::from_chars(vec::init_elt('#', ctxt.depth));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn subsection(ctxt: ctxt, f: fn&()) {
    ctxt.depth += 1u;
    f();
    ctxt.depth -= 1u;
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_header(ctxt, #fmt("Module `%s`", moddoc.name));
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        subsection(ctxt) {||
            write_fn(ctxt, fndoc);
        }
    }

    for moddoc in *moddoc.mods {
        subsection(ctxt) {||
            write_mod(ctxt, moddoc);
        }
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, #fmt("Function `%s`", doc.name));
    alt doc.brief {
      some(brief) {
        ctxt.w.write_line(brief);
      }
      none. { }
    }
    alt doc.desc {
        some(_d) {
            ctxt.w.write_line("");
            ctxt.w.write_line(_d);
            ctxt.w.write_line("");
        }
        none. { }
    }
    for (arg, desc) in doc.args {
        ctxt.w.write_str("### Argument `" + arg + "`: ");
        ctxt.w.write_str(desc)
    }
    alt doc.return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line("### Returns `" + ty + "`");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod tests {
    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let source = "";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "belch");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch\n");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let source = "fn func() { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let source = "mod moo { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let source = "mod morp { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        log(error, markdown);
        assert str::contains(markdown, "Module `morp`\n");
    }
}<commit_msg>rustdoc: Remove some debug logging<commit_after>#[doc = "Generate markdown from a document tree"];

import std::io;
import std::io::writer_util;

export mk_pass;

fn mk_pass(
    writer: fn~() -> io::writer
) -> pass {
    ret fn~(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        write_markdown(doc, writer());
        doc
    };
}

type ctxt = {
    w: io::writer,
    mutable depth: uint
};

fn write_markdown(
    doc: doc::cratedoc,
    writer: io::writer
) {
    let ctxt = {
        w: writer,
        mutable depth: 1u
    };

    write_crate(ctxt, doc);
}

fn write_header(ctxt: ctxt, title: str) {
    let hashes = str::from_chars(vec::init_elt('#', ctxt.depth));
    ctxt.w.write_line(#fmt("%s %s", hashes, title));
    ctxt.w.write_line("");
}

fn subsection(ctxt: ctxt, f: fn&()) {
    ctxt.depth += 1u;
    f();
    ctxt.depth -= 1u;
}

fn write_crate(
    ctxt: ctxt,
    doc: doc::cratedoc
) {
    write_header(ctxt, #fmt("Crate %s", doc.topmod.name));
    write_top_module(ctxt, doc.topmod);
}

fn write_top_module(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_mod_contents(ctxt, moddoc);
}

fn write_mod(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    write_header(ctxt, #fmt("Module `%s`", moddoc.name));
    write_mod_contents(ctxt, moddoc);
}

fn write_mod_contents(
    ctxt: ctxt,
    moddoc: doc::moddoc
) {
    for fndoc in *moddoc.fns {
        subsection(ctxt) {||
            write_fn(ctxt, fndoc);
        }
    }

    for moddoc in *moddoc.mods {
        subsection(ctxt) {||
            write_mod(ctxt, moddoc);
        }
    }
}

fn write_fn(
    ctxt: ctxt,
    doc: doc::fndoc
) {
    write_header(ctxt, #fmt("Function `%s`", doc.name));
    alt doc.brief {
      some(brief) {
        ctxt.w.write_line(brief);
      }
      none. { }
    }
    alt doc.desc {
        some(_d) {
            ctxt.w.write_line("");
            ctxt.w.write_line(_d);
            ctxt.w.write_line("");
        }
        none. { }
    }
    for (arg, desc) in doc.args {
        ctxt.w.write_str("### Argument `" + arg + "`: ");
        ctxt.w.write_str(desc)
    }
    alt doc.return {
      some(doc) {
        alt doc.ty {
          some(ty) {
            ctxt.w.write_line("### Returns `" + ty + "`");
            alt doc.desc {
              some(d) {
                ctxt.w.write_line(d);
              }
              none. { }
            }
          }
          none. { fail "unimplemented"; }
        }
      }
      none. { }
    }
}

#[cfg(test)]
mod tests {
    fn write_markdown_str(
        doc: doc::cratedoc
    ) -> str {
        let buffer = io::mk_mem_buffer();
        let writer = io::mem_buffer_writer(buffer);
        write_markdown(doc, writer);
        ret io::mem_buffer_str(buffer);
    }

    #[test]
    fn write_markdown_should_write_crate_header() {
        let source = "";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "belch");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "# Crate belch\n");
    }

    #[test]
    fn write_markdown_should_write_function_header() {
        let source = "fn func() { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "## Function `func`");
    }

    #[test]
    fn write_markdown_should_write_mod_headers() {
        let source = "mod moo { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "## Module `moo`");
    }

    #[test]
    fn should_leave_blank_line_after_header() {
        let source = "mod morp { }";
        let ast = parse::from_str(source);
        let doc = extract::extract(ast, "");
        let markdown = write_markdown_str(doc);
        assert str::contains(markdown, "Module `morp`\n");
    }
}<|endoftext|>


<commit_before><commit_msg>Default value for AtomicFloat (#139)<commit_after><|endoftext|>


<commit_before>
// use std::fmt::Debug;

// pub fn insertion_sort<T: Debug>(array: &mut Vec<T>) {
pub fn insertion_sort(array: &mut Vec<f64>) {
    let N = array.len();
    println!("  simplesorts::insertion_sort():  N = {:?}", N);
    for (i,elem) in array.iter().enumerate() {
        println!("    simplesorts::insertion_sort():  i={}   {:?}", i, elem);
    }
}
<commit_msg>Cleanup<commit_after>
// use std::fmt::Debug;

// pub fn insertion_sort<T: Debug>(array: &mut Vec<T>) {
pub fn insertion_sort(array: &mut Vec<f64>) {
    let n = array.len();

    if n > 1 {
        println!("  simplesorts::insertion_sort():  N = {:?}", n);
        for (i,elem) in array.iter().enumerate() {
            println!("    simplesorts::insertion_sort():  i={}   {:?}", i, elem);
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;

use {Poll, Async};
use sink::{Sink, StartSend, AsyncSink};
use stream::Stream;

/// Sink for the `Sink::buffer` combinator, which buffers up to some fixed
/// number of values when the underlying sink is unable to accept them.
#[must_use = "sinks do nothing unless polled"]
pub struct Buffer<S: Sink> {
    sink: S,
    buf: VecDeque<S::SinkItem>,

    // Track capacity separately from the `VecDeque`, which may be rounded up
    cap: usize,
}

pub fn new<S: Sink>(sink: S, amt: usize) -> Buffer<S> {
    Buffer {
        sink: sink,
        buf: VecDeque::with_capacity(amt),
        cap: amt,
    }
}

impl<S: Sink> Buffer<S> {
    /// Get a shared reference to the inner sink.
    pub fn get_ref(&self) -> &S {
        &self.sink
    }

    /// Get a mutable reference to the inner sink.
    pub fn get_mut(&mut self) -> &mut S {
        &mut self.sink
    }
}

// Forwarding impl of Stream from the underlying sink
impl<S> Stream for Buffer<S> where S: Sink + Stream {
    type Item = S::Item;
    type Error = S::Error;

    fn poll(&mut self) -> Poll<Option<S::Item>, S::Error> {
        self.sink.poll()
    }
}

impl<S: Sink> Sink for Buffer<S> {
    type SinkItem = S::SinkItem;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        try!(self.poll_complete());
        if self.buf.len() > self.cap {
            return Ok(AsyncSink::NotReady(item));
        }
        self.buf.push_back(item);
        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        while let Some(item) = self.buf.pop_front() {
            if let AsyncSink::NotReady(item) = try!(self.sink.start_send(item)) {
                self.buf.push_front(item);

                // ensure that we attempt to complete any pushes we've started
                try!(self.sink.poll_complete());

                return Ok(Async::NotReady);
            }
        }

        debug_assert!(self.buf.is_empty());

        self.sink.poll_complete()
    }
}
<commit_msg>Refactor use of poll_complete in buffer<commit_after>use std::collections::VecDeque;

use {Poll, Async};
use sink::{Sink, StartSend, AsyncSink};
use stream::Stream;

/// Sink for the `Sink::buffer` combinator, which buffers up to some fixed
/// number of values when the underlying sink is unable to accept them.
#[must_use = "sinks do nothing unless polled"]
pub struct Buffer<S: Sink> {
    sink: S,
    buf: VecDeque<S::SinkItem>,

    // Track capacity separately from the `VecDeque`, which may be rounded up
    cap: usize,
}

pub fn new<S: Sink>(sink: S, amt: usize) -> Buffer<S> {
    Buffer {
        sink: sink,
        buf: VecDeque::with_capacity(amt),
        cap: amt,
    }
}

impl<S: Sink> Buffer<S> {
    /// Get a shared reference to the inner sink.
    pub fn get_ref(&self) -> &S {
        &self.sink
    }

    /// Get a mutable reference to the inner sink.
    pub fn get_mut(&mut self) -> &mut S {
        &mut self.sink
    }

    fn try_empty_buffer(&mut self) -> Poll<(), S::SinkError> {
        while let Some(item) = self.buf.pop_front() {
            if let AsyncSink::NotReady(item) = try!(self.sink.start_send(item)) {
                self.buf.push_front(item);

                // ensure that we attempt to complete any pushes we've started
                try!(self.sink.poll_complete());

                return Ok(Async::NotReady);
            }
        }

        Ok(Async::Ready(()))
    }
}

// Forwarding impl of Stream from the underlying sink
impl<S> Stream for Buffer<S> where S: Sink + Stream {
    type Item = S::Item;
    type Error = S::Error;

    fn poll(&mut self) -> Poll<Option<S::Item>, S::Error> {
        self.sink.poll()
    }
}

impl<S: Sink> Sink for Buffer<S> {
    type SinkItem = S::SinkItem;
    type SinkError = S::SinkError;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        try!(self.try_empty_buffer());
        if self.buf.len() > self.cap {
            return Ok(AsyncSink::NotReady(item));
        }
        self.buf.push_back(item);
        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        try_ready!(self.try_empty_buffer());
        debug_assert!(self.buf.is_empty());
        self.sink.poll_complete()
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
extern crate toml;
extern crate toml_query;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagerror;
extern crate libimagentrylink;
extern crate libimagstore;

use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace;
use libimagstore::store::FileLockEntry;
use libimagstore::iter::get::*;
use libimagstore::error::StoreError as Error;
use libimagentrylink::internal::*;

use toml::Value;
use toml_query::read::TomlValueReadExt;

use std::collections::BTreeMap;

mod ui;

struct Diagnostic {
    pub entry_store_version: String,
    pub header_sections: usize,
    pub bytecount_content: usize,
    pub overall_byte_size: usize,
    pub verified: bool,
    pub num_internal_links: usize,
}

impl<'a> From<FileLockEntry<'a>> for Diagnostic {

    fn from(entry: FileLockEntry<'a>) -> Diagnostic {
        Diagnostic {
            entry_store_version: entry
                .get_header()
                .read("imag.version")
                .map(|opt| match opt {
                    Some(&Value::String(ref s)) => s.clone(),
                    Some(_) => "Non-String type in 'imag.version'".to_owned(),
                    None => "No version".to_owned(),
                })
                .unwrap_or("Error reading version".to_owned()),
            header_sections: match entry.get_header() {
                &Value::Table(ref map) => map.keys().count(),
                _ => 0
            },
            bytecount_content: entry.get_content().as_str().len(),
            overall_byte_size: entry.to_str().as_str().len(),
            verified: entry.verify().is_ok(),
            num_internal_links: entry.get_internal_links().map(Iterator::count).unwrap_or(0),
        }
    }
}

fn main() {
    let rt = generate_runtime_setup("imag-diagnostics",
                                    &version!()[..],
                                    "Print diagnostics about imag and the imag store",
                                    ui::build_ui);

    let diags = rt.store()
        .entries()
        .map_err_trace_exit(1)
        .unwrap()
        .into_get_iter(rt.store())
        .map(|e| {
            e.map_err_trace_exit_unwrap(1)
                .ok_or(Error::from("Unable to get entry".to_owned()))
                .map_err_trace_exit_unwrap(1)
        })
        .map(Diagnostic::from)
        .collect::<Vec<_>>();

    let mut version_counts        : BTreeMap<String, usize> = BTreeMap::new();
    let mut sum_header_sections   = 0;
    let mut sum_bytecount_content = 0;
    let mut sum_overall_byte_size = 0;
    let mut verified_count        = 0;
    let mut unverified_count      = 0;
    let mut num_internal_links    = 0;

    for diag in diags.iter() {
        sum_header_sections     += diag.header_sections;
        sum_bytecount_content   += diag.bytecount_content;
        sum_overall_byte_size   += diag.overall_byte_size;

        let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0);
        version_counts.insert(diag.entry_store_version.clone(), n+1);

        if diag.verified {
            verified_count += 1;
        } else {
            unverified_count += 1;
        }

        num_internal_links += diag.num_internal_links;
    }

    let n = diags.len();

    println!("imag version {}", version!());
    println!("");
    println!("{} entries", n);
    for (k, v) in version_counts {
        println!("{} entries with store version '{}'", v, k);
    }
    if n != 0 {
        println!("{} header sections in the average entry", sum_header_sections / n);
        println!("{} average content bytecount", sum_bytecount_content / n);
        println!("{} average overall bytecount", sum_overall_byte_size / n);
        println!("{} average internal link count per entry", num_internal_links / n);
        println!("{} verified entries", verified_count);
        println!("{} unverified entries", unverified_count);
    }
}

<commit_msg>Add output about max internal links and max overall byte size<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
extern crate toml;
extern crate toml_query;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagerror;
extern crate libimagentrylink;
extern crate libimagstore;

use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::MapErrTrace;
use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::iter::get::*;
use libimagstore::error::StoreError as Error;
use libimagentrylink::internal::*;

use toml::Value;
use toml_query::read::TomlValueReadExt;

use std::collections::BTreeMap;

mod ui;

struct Diagnostic {
    pub id: StoreId,
    pub entry_store_version: String,
    pub header_sections: usize,
    pub bytecount_content: usize,
    pub overall_byte_size: usize,
    pub verified: bool,
    pub num_internal_links: usize,
}

impl<'a> From<FileLockEntry<'a>> for Diagnostic {

    fn from(entry: FileLockEntry<'a>) -> Diagnostic {
        Diagnostic {
            id: entry.get_location().clone(),
            entry_store_version: entry
                .get_header()
                .read("imag.version")
                .map(|opt| match opt {
                    Some(&Value::String(ref s)) => s.clone(),
                    Some(_) => "Non-String type in 'imag.version'".to_owned(),
                    None => "No version".to_owned(),
                })
                .unwrap_or("Error reading version".to_owned()),
            header_sections: match entry.get_header() {
                &Value::Table(ref map) => map.keys().count(),
                _ => 0
            },
            bytecount_content: entry.get_content().as_str().len(),
            overall_byte_size: entry.to_str().as_str().len(),
            verified: entry.verify().is_ok(),
            num_internal_links: entry.get_internal_links().map(Iterator::count).unwrap_or(0),
        }
    }
}

fn main() {
    let rt = generate_runtime_setup("imag-diagnostics",
                                    &version!()[..],
                                    "Print diagnostics about imag and the imag store",
                                    ui::build_ui);

    let diags = rt.store()
        .entries()
        .map_err_trace_exit(1)
        .unwrap()
        .into_get_iter(rt.store())
        .map(|e| {
            e.map_err_trace_exit_unwrap(1)
                .ok_or(Error::from("Unable to get entry".to_owned()))
                .map_err_trace_exit_unwrap(1)
        })
        .map(Diagnostic::from)
        .collect::<Vec<_>>();

    let mut version_counts        : BTreeMap<String, usize> = BTreeMap::new();
    let mut sum_header_sections   = 0;
    let mut sum_bytecount_content = 0;
    let mut sum_overall_byte_size = 0;
    let mut max_overall_byte_size : Option<(usize, StoreId)> = None;
    let mut verified_count        = 0;
    let mut unverified_count      = 0;
    let mut num_internal_links    = 0;
    let mut max_internal_links : Option<(usize, StoreId)> = None;

    for diag in diags.iter() {
        sum_header_sections     += diag.header_sections;
        sum_bytecount_content   += diag.bytecount_content;
        sum_overall_byte_size   += diag.overall_byte_size;
        match max_overall_byte_size {
            None => max_overall_byte_size = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.overall_byte_size {
                max_overall_byte_size = Some((diag.overall_byte_size, diag.id.clone()));
            }
        }

        let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0);
        version_counts.insert(diag.entry_store_version.clone(), n+1);

        if diag.verified {
            verified_count += 1;
        } else {
            unverified_count += 1;
        }

        num_internal_links += diag.num_internal_links;
        match max_internal_links {
            None => max_internal_links = Some((diag.num_internal_links, diag.id.clone())),
            Some((num, _)) => if num < diag.num_internal_links {
                max_internal_links = Some((diag.num_internal_links, diag.id.clone()));
            }
        }
    }

    let n = diags.len();

    println!("imag version {}", version!());
    println!("");
    println!("{} entries", n);
    for (k, v) in version_counts {
        println!("{} entries with store version '{}'", v, k);
    }
    if n != 0 {
        println!("{} header sections in the average entry", sum_header_sections / n);
        println!("{} average content bytecount", sum_bytecount_content / n);
        println!("{} average overall bytecount", sum_overall_byte_size / n);
        if let Some((num, path)) = max_overall_byte_size {
            println!("Largest Entry ({bytes} bytes): {path}",
                bytes = num,
                path = path
                    .into_pathbuf()
                    .map_err_trace_exit_unwrap(1)
                    .to_str()
                    .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} average internal link count per entry", num_internal_links / n);
        if let Some((num, path)) = max_internal_links {
            println!("Entry with most internal links ({count}): {path}",
                     count = num,
                     path = path
                        .into_pathbuf()
                        .map_err_trace_exit_unwrap(1)
                        .to_str()
                        .unwrap_or("Failed converting path to string")
            );
        }
        println!("{} verified entries", verified_count);
        println!("{} unverified entries", unverified_count);
    }
}

<|endoftext|>