<commit_before>use tokio_core::io::{Io, Codec, EasyBuf, Framed};
use std::io;
use std::collections::HashSet;

use tokio_proto::streaming::multiplex::{Frame, ClientProto};

use asnom::common;
use asnom::IResult;
use asnom::structures::{Tag, Integer, Sequence, ASNTag};
use asnom::parse::Parser;
use asnom::ConsumerState;
use asnom::Move;
use asnom::Input;
use asnom::Consumer;

use asnom::parse::{parse_tag, parse_uint};
use asnom::write;

#[derive(Debug, Clone)]
pub struct LdapCodec {
    search_seen: HashSet<u64>,
}

impl Codec for LdapCodec {
    type In = Frame<Tag, Tag, io::Error>;
    type Out = Frame<Tag, Tag, io::Error>;

    fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<Self::In>, io::Error> {
        let mut parser = Parser::new();
        match parser.handle(Input::Element(buf.as_slice())) {
            &ConsumerState::Done(amt, ref tag) => {
                match amt {
                    Move::Consume(amt) => {
                        buf.drain_to(amt);

                        let tag = tag.clone();
                        if let Some(mut tags) = tag.match_id(16u64).and_then(|x| x.expect_constructed()) {
                            let protoop = tags.pop().unwrap();
                            let msgid: Vec<u8> = tags.pop().unwrap()
                                            .match_class(common::TagClass::Universal)
                                            .and_then(|x| x.match_id(2u64))
                                            .and_then(|x| x.expect_primitive()).unwrap();
                            if let IResult::Done(_, id) = parse_uint(msgid.as_slice()) {
                                return match protoop.id {
                                    // SearchResultEntry
                                    4 => {
                                        debug!("Received a search result entry");
                                        // We have already received the first of those results, so we only
                                        // send a body frame.
                                        if self.search_seen.contains(&id) {
                                            Ok(Some(Frame::Body {
                                                id: id as u64,
                                                chunk: Some(Tag::StructureTag(protoop)),
                                            }))
                                        } // If we haven't yet seen that search, we need to initially send a whole message
                                        else {
                                            self.search_seen.insert(id);
                                            Ok(Some(Frame::Message {
                                                id: id as u64,
                                                message: Tag::StructureTag(protoop),
                                                body: true,
                                                solo: false,
                                            }))
                                        }
                                    },
                                    // SearchResultDone
                                    5 => {
                                        debug!("Received a search result done");
                                        let seen_res_entry = self.search_seen.contains(&id);
                                        self.search_seen.remove(&id);
                                        if seen_res_entry {
                                            Ok(Some(Frame::Body {
                                                id: id as u64,
                                                chunk: None,
                                            }))
                                        } else {
                                            Ok(Some(Frame::Message {
                                                id: id as u64,
                                                message: Tag::StructureTag(protoop),
                                                body: false,
                                                solo: false,
                                            }))
                                        }
                                    },
                                    // Any other Message
                                    _ => {
                                        debug!("Received a tag id {}", id);
                                        Ok(Some(Frame::Message {
                                            id: id as u64,
                                            message: Tag::StructureTag(protoop),
                                            body: false,
                                            solo: false,
                                        }))
                                    },
                                }
                            }
                        }

                        return Err(io::Error::new(io::ErrorKind::Other, "Invalid (RequestId, Tag) received."));
                    },
                    Move::Seek(_) => Err(io::Error::from(io::ErrorKind::Other)),
                    Move::Await(_) => Ok(None)
                }
            },
            &ConsumerState::Continue(_) => Ok(None),
            &ConsumerState::Error(_e) => Err(io::Error::from(io::ErrorKind::Other)),
        }
    }

    fn encode(&mut self, msg: Self::Out, into: &mut Vec<u8>) -> io::Result<()> {
        match msg {
            Frame::Message {message, id, body: _, solo: _} => {
                let outtag = Tag::Sequence(Sequence {
                    inner: vec![
                        Tag::Integer(Integer {
                            inner: id as i64,
                            .. Default::default()
                        }),
                        message,
                    ],
                    .. Default::default()
                });

                let outstruct = outtag.into_structure();
                trace!("Sending packet: {:?}", &outstruct);
                try!(write::encode_into(into, outstruct));
                Ok(())
            },
            _ => unimplemented!(),
        }
    }
}

pub struct LdapProto;

impl<T: Io + 'static> ClientProto<T> for LdapProto {
    type Request = Tag;
    type RequestBody = Tag;
    type Response = Tag;
    type ResponseBody = Tag;
    type Error = io::Error;

    /// `Framed<T, LineCodec>` is the return value of `io.framed(LineCodec)`
    type Transport = Framed<T, LdapCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        let ldapcodec = LdapCodec { search_seen: HashSet::new() };
        Ok(io.framed(ldapcodec))
    }
}
<commit_msg>Tame rightward drift in LdapCodec::decode()<commit_after>use tokio_core::io::{Io, Codec, EasyBuf, Framed};
use std::io;
use std::collections::HashSet;

use tokio_proto::streaming::multiplex::{Frame, ClientProto};

use asnom::common;
use asnom::IResult;
use asnom::structures::{Tag, Integer, Sequence, ASNTag};
use asnom::parse::Parser;
use asnom::ConsumerState;
use asnom::Move;
use asnom::Input;
use asnom::Consumer;

use asnom::parse::{parse_tag, parse_uint};
use asnom::write;

#[derive(Debug, Clone)]
pub struct LdapCodec {
    search_seen: HashSet<u64>,
}

impl Codec for LdapCodec {
    type In = Frame<Tag, Tag, io::Error>;
    type Out = Frame<Tag, Tag, io::Error>;

    fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<Self::In>, io::Error> {
        let mut parser = Parser::new();
        let (amt, tag) = match *parser.handle(Input::Element(buf.as_slice())) {
            ConsumerState::Continue(_) => return Ok(None),
            ConsumerState::Error(_e) => return Err(io::Error::from(io::ErrorKind::Other)),
            ConsumerState::Done(amt, ref tag) => (amt, tag),
        };
        let amt = match amt {
            Move::Await(_) => return Ok(None),
            Move::Seek(_) => return Err(io::Error::from(io::ErrorKind::Other)),
            Move::Consume(amt) => amt,
        };
        buf.drain_to(amt);
        let tag = tag.clone();
        if let Some(mut tags) = tag.match_id(16u64).and_then(|x| x.expect_constructed()) {
            let protoop = tags.pop().unwrap();
            let msgid: Vec<u8> = tags.pop().unwrap()
                            .match_class(common::TagClass::Universal)
                            .and_then(|x| x.match_id(2u64))
                            .and_then(|x| x.expect_primitive()).unwrap();
            if let IResult::Done(_, id) = parse_uint(msgid.as_slice()) {
                return match protoop.id {
                    // SearchResultEntry
                    4 => {
                        debug!("Received a search result entry");
                        // We have already received the first of those results, so we only
                        // send a body frame.
                        if self.search_seen.contains(&id) {
                            Ok(Some(Frame::Body {
                                id: id as u64,
                                chunk: Some(Tag::StructureTag(protoop)),
                            }))
                        } // If we haven't yet seen that search, we need to initially send a whole message
                        else {
                            self.search_seen.insert(id);
                            Ok(Some(Frame::Message {
                                id: id as u64,
                                message: Tag::StructureTag(protoop),
                                body: true,
                                solo: false,
                            }))
                        }
                    },
                    // SearchResultDone
                    5 => {
                        debug!("Received a search result done");
                        let seen_res_entry = self.search_seen.contains(&id);
                        self.search_seen.remove(&id);
                        if seen_res_entry {
                            Ok(Some(Frame::Body {
                                id: id as u64,
                                chunk: None,
                            }))
                        } else {
                            Ok(Some(Frame::Message {
                                id: id as u64,
                                message: Tag::StructureTag(protoop),
                                body: false,
                                solo: false,
                            }))
                        }
                    },
                    // Any other Message
                    _ => {
                        debug!("Received a tag id {}", id);
                        Ok(Some(Frame::Message {
                            id: id as u64,
                            message: Tag::StructureTag(protoop),
                            body: false,
                            solo: false,
                        }))
                    },
                }
            }
        }
        return Err(io::Error::new(io::ErrorKind::Other, "Invalid (RequestId, Tag) received."));
    }

    fn encode(&mut self, msg: Self::Out, into: &mut Vec<u8>) -> io::Result<()> {
        match msg {
            Frame::Message {message, id, body: _, solo: _} => {
                let outtag = Tag::Sequence(Sequence {
                    inner: vec![
                        Tag::Integer(Integer {
                            inner: id as i64,
                            .. Default::default()
                        }),
                        message,
                    ],
                    .. Default::default()
                });

                let outstruct = outtag.into_structure();
                trace!("Sending packet: {:?}", &outstruct);
                try!(write::encode_into(into, outstruct));
                Ok(())
            },
            _ => unimplemented!(),
        }
    }
}

pub struct LdapProto;

impl<T: Io + 'static> ClientProto<T> for LdapProto {
    type Request = Tag;
    type RequestBody = Tag;
    type Response = Tag;
    type ResponseBody = Tag;
    type Error = io::Error;

    /// `Framed<T, LineCodec>` is the return value of `io.framed(LineCodec)`
    type Transport = Framed<T, LdapCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        let ldapcodec = LdapCodec { search_seen: HashSet::new() };
        Ok(io.framed(ldapcodec))
    }
}
<|endoftext|>


<commit_before><commit_msg>Cleanup of a match clause<commit_after><|endoftext|>


<commit_before>// This is just something easy to import that re-exports all the
// events. Other modules should just have to `use schooner::events::*;`

// the RaftEvent Trait, which allows all the events to be sent down
// the same channel.
pub use self::traits::RaftEvent;

// Raft-level Messages
// TODO:At some point we may need events for cluster changes (eg joins
// and parts)
pub use self::vote::{VoteReq, VoteRes};
pub use self::handoff::{HandoffReq, HandoffRes};

// Application-level Messages
pub use self::client::{ClientCmdReq, ClientCmdRes};
pub use self::append_entries::{AppendEntriesReq, AppendEntriesRes};

pub mod traits; // Annoyingly can't be called "trait" because keyword
pub mod append_entries;
mod vote;
mod handoff;
mod client;

// We have to wrap the RaftEvents in this EventMsg to send them all
// down the same channel.
// Messages for sending within Raft, basically. Contain channels for
// communication with the networking modules.
pub enum RaftMsg {
    ARQ(AppendEntriesReq, Sender<AppendEntriesRes>),
    ARS(AppendEntriesRes),
    VRQ(VoteReq, Sender<VoteRes>),
    VRS(VoteRes),
    StopReq,
}

// Bare RPC types. Only used when we don't need associated channels for
// network stuff.
pub enum RaftRpc {
    RpcARQ(AppendEntriesReq),
    RpcARS(AppendEntriesRes),
    RpcVRQ(VoteReq),
    RpcVRS(VoteRes),
    RpcStopReq,
}

pub enum ClientCmd {
    CMDRQ(ClientCmdReq, Sender<ClientCmdRes>),
    CMDRS(ClientCmdRes)
}
<commit_msg>kill handoff<commit_after>// This is just something easy to import that re-exports all the
// events. Other modules should just have to `use schooner::events::*;`

// the RaftEvent Trait, which allows all the events to be sent down
// the same channel.
pub use self::traits::RaftEvent;

// Raft-level Messages
// TODO:At some point we may need events for cluster changes (eg joins
// and parts)
pub use self::vote::{VoteReq, VoteRes};

// Application-level Messages
pub use self::client::{ClientCmdReq, ClientCmdRes};
pub use self::append_entries::{AppendEntriesReq, AppendEntriesRes};

pub mod traits; // Annoyingly can't be called "trait" because keyword
pub mod append_entries;
mod vote;
mod client;

// We have to wrap the RaftEvents in this EventMsg to send them all
// down the same channel.
// Messages for sending within Raft, basically. Contain channels for
// communication with the networking modules.
pub enum RaftMsg {
    ARQ(AppendEntriesReq, Sender<AppendEntriesRes>),
    ARS(AppendEntriesRes),
    VRQ(VoteReq, Sender<VoteRes>),
    VRS(VoteRes),
    StopReq,
}

// Bare RPC types. Only used when we don't need associated channels for
// network stuff.
pub enum RaftRpc {
    RpcARQ(AppendEntriesReq),
    RpcARS(AppendEntriesRes),
    RpcVRQ(VoteReq),
    RpcVRS(VoteRes),
    RpcStopReq,
}

pub enum ClientCmd {
    CMDRQ(ClientCmdReq, Sender<ClientCmdRes>),
    CMDRS(ClientCmdRes)
}
<|endoftext|>


<commit_before>//! Group records by a key, and apply a reduction function.
//!
//! The `group` operators act on data that can be viewed as pairs `(key, val)`. They group records
//! with the same key, and apply user supplied functions to the key and a list of values, which are
//! expected to populate a list of output values.
//!
//! Several variants of `group` exist which allow more precise control over how grouping is done.
//! For example, the `_by` suffixed variants take arbitrary data, but require a key-value selector
//! to be applied to each record. The `_u` suffixed variants use unsigned integers as keys, and
//! will use a dense array rather than a `HashMap` to store their keys.
//!
//! The list of values are presented as an iterator which internally merges sorted lists of values.
//! This ordering can be exploited in several cases to avoid computation when only the first few
//! elements are required.
//!
//! #Examples
//!
//! This example groups a stream of `(key,val)` pairs by `key`, and yields only the most frequently
//! occurring value for each key.
//!
//! ```ignore
//! stream.group(|key, vals, output| {
//!     let (mut max_val, mut max_wgt) = vals.next().unwrap();
//!     for (val, wgt) in vals {
//!         if wgt > max_wgt {
//!             max_wgt = wgt;
//!             max_val = val;
//!         }
//!     }
//!     output.push((max_val.clone(), max_wgt));
//! })
//! ```

use rc::Rc;
use std::cell::RefCell;
use std::default::Default;
use std::collections::HashMap;

use itertools::Itertools;
use linear_map::LinearMap;
use vec_map::VecMap;

use ::{Data, Collection, Delta};
use timely::dataflow::*;
use timely::dataflow::operators::{Map, Unary};
use timely::dataflow::channels::pact::Pipeline;
use timely_sort::Unsigned;

use collection::{LeastUpperBound, Lookup, Trace, BasicTrace, Offset};
use collection::trace::CollectionIterator;
use collection::basic::DifferenceIterator;
use collection::compact::Compact;

use iterators::coalesce::Coalesce;

use operators::arrange::{Arranged, ArrangeByKey};

/// Extension trait for the `group` differential dataflow method
pub trait Group<G: Scope, K: Data, V: Data>
    where G::Timestamp: LeastUpperBound {

    /// Groups records by their first field, and applies reduction logic to the associated values.
    ///
    /// It would be nice for this to be generic over possible arrangements of data, but it seems that Rust
    /// ICEs when I try this. I'm not exactly sure how one would specify the arrangement (the type is used
    /// in `logic`, by way of its associated iterator types, but not clearly enough to drive type inference),
    /// but we don't have that problem yet anyhow.
    ///
    /// In any case, it would be great if the same implementation could handle `(K,V)` pairs and `K` elements
    /// treated as `(K, ())` pairs.
    fn group<L, V2: Data>(&self, logic: L) -> Collection<G, (K,V2)>
        where L: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, Delta)>)+'static;
}

impl<G: Scope, K: Data+Default, V: Data+Default> Group<G, K, V> for Collection<G, (K,V)>
where G::Timestamp: LeastUpperBound
{
    fn group<L, V2: Data>(&self, logic: L) -> Collection<G, (K,V2)>
        where L: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, Delta)>)+'static {
            self.arrange_by_key(|k| k.hashed(), |_| HashMap::new())
                .group(|k| k.hashed(), |_| HashMap::new(), logic)
                .as_collection()
    }
}

/// Extension trait for the `group_u` differential dataflow method.
pub trait GroupUnsigned<G: Scope, U: Unsigned+Data+Default, V: Data>
    where G::Timestamp: LeastUpperBound {
    /// Groups records by their first field, when this field implements `Unsigned`.
    ///
    /// This method uses a `Vec<Option<_>>` as its internal storage, allocating
    /// enough memory to directly index based on the first fields. This can be
    /// very useful when these fields are small integers, but it can be expensive
    /// if they are large and sparse.
    fn group_u<L, V2: Data>(&self, logic: L) -> Collection<G, (U, V2)>
        where L: Fn(&U, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static;
}

impl<G: Scope, U: Unsigned+Data+Default, V: Data> GroupUnsigned<G, U, V> for Collection<G, (U,V)>
where G::Timestamp: LeastUpperBound {
    fn group_u<L, V2: Data>(&self, logic: L) -> Collection<G, (U, V2)>
        where L: Fn(&U, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static {
            self.arrange_by_key(|k| k.as_u64(), |x| (VecMap::new(), x))
                .group(|k| k.as_u64(), |x| (VecMap::new(), x), logic)
                .as_collection()
        }
}

/// Extension trait for the `group` operator on `Arrange<_>` data.
pub trait GroupArranged<G: Scope, K: Data, V: Data> {
    /// Groups arranged data using a key hash function, a lookup generator, and user logic.
    ///
    /// This method is used by `group` and `group_u` as defined on `Collection`, and it can
    /// also be called directly by user code that wants access to the arranged output. This
    /// can be helpful when the resulting data are re-used immediately with the same keys.
    fn group<V2, U, KH, Look, LookG, Logic>(&self, key_h: KH, look: LookG, logic: Logic)
        -> Arranged<G, BasicTrace<K,G::Timestamp,V2,Look>>
    where
        G::Timestamp: LeastUpperBound,
        V2:    Data,
        U:     Unsigned+Default,
        KH:    Fn(&K)->U+'static,
        Look:  Lookup<K, Offset>+'static,
        LookG: Fn(u64)->Look,
        Logic: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static;
}

impl<G, K, V, L> GroupArranged<G, K, V> for Arranged<G, BasicTrace<K, G::Timestamp, V, L>>
where
    G: Scope,
    K: Data,
    V: Data,
    L: Lookup<K, Offset>+'static,
    G::Timestamp: LeastUpperBound {

    fn group<V2, U, KH, Look, LookG, Logic>(&self, key_h: KH, look: LookG, logic: Logic)
        -> Arranged<G, BasicTrace<K,G::Timestamp,V2,Look>>
    where
        V2:    Data,
        U:     Unsigned+Default,
        KH:    Fn(&K)->U+'static,
        Look:  Lookup<K, Offset>+'static,
        LookG: Fn(u64)->Look,
        Logic: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static {

        let peers = self.stream.scope().peers();
        let mut log_peers = 0;
        while (1 << (log_peers + 1)) <= peers {
            log_peers += 1;
        }

        let source = self.trace.clone();
        let result = Rc::new(RefCell::new(BasicTrace::new(look(log_peers))));
        let target = result.clone();

        // A map from times to received (key, val, wgt) triples.
        let mut inputs = LinearMap::new();

        // A map from times to a list of keys that need processing at that time.
        let mut to_do = LinearMap::new();

        // temporary storage for operator implementations to populate
        let mut buffer = vec![];

        // fabricate a data-parallel operator using the `unary_notify` pattern.
        let stream = self.stream.unary_notify(Pipeline, "GroupArranged", vec![], move |input, output, notificator| {

            // 1. read each input, and stash it in our staging area.
            // only stash the keys, because vals etc are in self.trace
            while let Some((time, data)) = input.next() {
                inputs.entry_or_insert(time.time(), || { notificator.notify_at(time); data.drain(..).next().unwrap().0 });
            }

            // 2. go through each time of interest that has reached completion
            // times are interesting either because we received data, or because we conclude
            // in the processing of a time that a future time will be interesting.
            while let Some((capability, _count)) = notificator.next() {

                let time = capability.time();

                // 2a. If we received any keys, determine the interesting times for each.
                //     We then enqueue the keys at the corresponding time, for use later.
                if let Some(queue) = inputs.remove_key(&time) {

                    let source = source.borrow();
                    let mut stash = Vec::new();
                    for key in queue {
                        if source.get_difference(&key, &time).is_some() {
                            stash.push(capability.time());
                            source.interesting_times(&key, &time, &mut stash);
                            for new_time in &stash {
                                to_do.entry_or_insert(time.clone(), || { notificator.notify_at(capability.delayed(new_time)); Vec::new() })
                                     .push(key.clone());
                            }
                            stash.clear();
                        }
                    }
                }

                // 2b. Process any interesting keys at this time.
                if let Some(mut keys) = to_do.remove_key(&time) {

                    // We would like these keys in a particular order.
                    // We also want to de-duplicate them, in case there are dupes.
                    keys.sort_by(|x,y| (key_h(&x), x).cmp(&(key_h(&y), y)));
                    keys.dedup();

                    // accumulations for installation into result
                    let mut accumulation = Compact::new(0,0);

                    // borrow `source` to avoid constant re-borrowing.
                    let mut source_borrow = source.borrow_mut();

                    for key in keys {

                        // acquire an iterator over the collection at `time`.
                        let mut input = source_borrow.get_collection(&key, &time);

                        // if we have some input data, invoke logic to populate buffer.
                        if input.peek().is_some() { logic(&key, &mut input, &mut buffer); }

                        // sort the buffer, because we can't trust user code to do that.
                        buffer.sort_by(|x,y| x.0.cmp(&y.0));

                        // push differences in to Compact.
                        let mut compact = accumulation.session();
                        for (val, wgt) in Coalesce::coalesce(target.borrow_mut()
                                                                   .get_collection(&key, &time)
                                                                   .map(|(v, w)| (v,-w))
                                                                   .merge_by(buffer.iter().map(|&(ref v, w)| (v, w)), |x,y| {
                                                                        x.0 <= y.0
                                                                   }))
                        {
                            compact.push(val.clone(), wgt);
                        }
                        compact.done(key);
                        buffer.clear();
                    }

                    if accumulation.vals.len() > 0 {
                        output.session(&capability).give((accumulation.keys.clone(), accumulation.cnts.clone(), accumulation.vals.clone()));
                        target.borrow_mut().set_difference(time, accumulation);
                    }
                }
            }
        });

        Arranged { stream: stream, trace: result }
    }
}
<commit_msg>error in interesting time recording<commit_after>//! Group records by a key, and apply a reduction function.
//!
//! The `group` operators act on data that can be viewed as pairs `(key, val)`. They group records
//! with the same key, and apply user supplied functions to the key and a list of values, which are
//! expected to populate a list of output values.
//!
//! Several variants of `group` exist which allow more precise control over how grouping is done.
//! For example, the `_by` suffixed variants take arbitrary data, but require a key-value selector
//! to be applied to each record. The `_u` suffixed variants use unsigned integers as keys, and
//! will use a dense array rather than a `HashMap` to store their keys.
//!
//! The list of values are presented as an iterator which internally merges sorted lists of values.
//! This ordering can be exploited in several cases to avoid computation when only the first few
//! elements are required.
//!
//! #Examples
//!
//! This example groups a stream of `(key,val)` pairs by `key`, and yields only the most frequently
//! occurring value for each key.
//!
//! ```ignore
//! stream.group(|key, vals, output| {
//!     let (mut max_val, mut max_wgt) = vals.next().unwrap();
//!     for (val, wgt) in vals {
//!         if wgt > max_wgt {
//!             max_wgt = wgt;
//!             max_val = val;
//!         }
//!     }
//!     output.push((max_val.clone(), max_wgt));
//! })
//! ```

use rc::Rc;
use std::cell::RefCell;
use std::default::Default;
use std::collections::HashMap;

use itertools::Itertools;
use linear_map::LinearMap;
use vec_map::VecMap;

use ::{Data, Collection, Delta};
use timely::dataflow::*;
use timely::dataflow::operators::{Map, Unary};
use timely::dataflow::channels::pact::Pipeline;
use timely_sort::Unsigned;

use collection::{LeastUpperBound, Lookup, Trace, BasicTrace, Offset};
use collection::trace::CollectionIterator;
use collection::basic::DifferenceIterator;
use collection::compact::Compact;

use iterators::coalesce::Coalesce;

use operators::arrange::{Arranged, ArrangeByKey};

/// Extension trait for the `group` differential dataflow method
pub trait Group<G: Scope, K: Data, V: Data>
    where G::Timestamp: LeastUpperBound {

    /// Groups records by their first field, and applies reduction logic to the associated values.
    ///
    /// It would be nice for this to be generic over possible arrangements of data, but it seems that Rust
    /// ICEs when I try this. I'm not exactly sure how one would specify the arrangement (the type is used
    /// in `logic`, by way of its associated iterator types, but not clearly enough to drive type inference),
    /// but we don't have that problem yet anyhow.
    ///
    /// In any case, it would be great if the same implementation could handle `(K,V)` pairs and `K` elements
    /// treated as `(K, ())` pairs.
    fn group<L, V2: Data>(&self, logic: L) -> Collection<G, (K,V2)>
        where L: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, Delta)>)+'static;
}

impl<G: Scope, K: Data+Default, V: Data+Default> Group<G, K, V> for Collection<G, (K,V)>
where G::Timestamp: LeastUpperBound
{
    fn group<L, V2: Data>(&self, logic: L) -> Collection<G, (K,V2)>
        where L: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, Delta)>)+'static {
            self.arrange_by_key(|k| k.hashed(), |_| HashMap::new())
                .group(|k| k.hashed(), |_| HashMap::new(), logic)
                .as_collection()
    }
}

/// Extension trait for the `group_u` differential dataflow method.
pub trait GroupUnsigned<G: Scope, U: Unsigned+Data+Default, V: Data>
    where G::Timestamp: LeastUpperBound {
    /// Groups records by their first field, when this field implements `Unsigned`.
    ///
    /// This method uses a `Vec<Option<_>>` as its internal storage, allocating
    /// enough memory to directly index based on the first fields. This can be
    /// very useful when these fields are small integers, but it can be expensive
    /// if they are large and sparse.
    fn group_u<L, V2: Data>(&self, logic: L) -> Collection<G, (U, V2)>
        where L: Fn(&U, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static;
}

impl<G: Scope, U: Unsigned+Data+Default, V: Data> GroupUnsigned<G, U, V> for Collection<G, (U,V)>
where G::Timestamp: LeastUpperBound {
    fn group_u<L, V2: Data>(&self, logic: L) -> Collection<G, (U, V2)>
        where L: Fn(&U, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static {
            self.arrange_by_key(|k| k.as_u64(), |x| (VecMap::new(), x))
                .group(|k| k.as_u64(), |x| (VecMap::new(), x), logic)
                .as_collection()
        }
}

/// Extension trait for the `group` operator on `Arrange<_>` data.
pub trait GroupArranged<G: Scope, K: Data, V: Data> {
    /// Groups arranged data using a key hash function, a lookup generator, and user logic.
    ///
    /// This method is used by `group` and `group_u` as defined on `Collection`, and it can
    /// also be called directly by user code that wants access to the arranged output. This
    /// can be helpful when the resulting data are re-used immediately with the same keys.
    fn group<V2, U, KH, Look, LookG, Logic>(&self, key_h: KH, look: LookG, logic: Logic)
        -> Arranged<G, BasicTrace<K,G::Timestamp,V2,Look>>
    where
        G::Timestamp: LeastUpperBound,
        V2:    Data,
        U:     Unsigned+Default,
        KH:    Fn(&K)->U+'static,
        Look:  Lookup<K, Offset>+'static,
        LookG: Fn(u64)->Look,
        Logic: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static;
}

impl<G, K, V, L> GroupArranged<G, K, V> for Arranged<G, BasicTrace<K, G::Timestamp, V, L>>
where
    G: Scope,
    K: Data,
    V: Data,
    L: Lookup<K, Offset>+'static,
    G::Timestamp: LeastUpperBound {

    fn group<V2, U, KH, Look, LookG, Logic>(&self, key_h: KH, look: LookG, logic: Logic)
        -> Arranged<G, BasicTrace<K,G::Timestamp,V2,Look>>
    where
        V2:    Data,
        U:     Unsigned+Default,
        KH:    Fn(&K)->U+'static,
        Look:  Lookup<K, Offset>+'static,
        LookG: Fn(u64)->Look,
        Logic: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, i32)>)+'static {

        let peers = self.stream.scope().peers();
        let mut log_peers = 0;
        while (1 << (log_peers + 1)) <= peers {
            log_peers += 1;
        }

        let source = self.trace.clone();
        let result = Rc::new(RefCell::new(BasicTrace::new(look(log_peers))));
        let target = result.clone();

        // A map from times to received (key, val, wgt) triples.
        let mut inputs = LinearMap::new();

        // A map from times to a list of keys that need processing at that time.
        let mut to_do = LinearMap::new();

        // temporary storage for operator implementations to populate
        let mut buffer = vec![];

        // fabricate a data-parallel operator using the `unary_notify` pattern.
        let stream = self.stream.unary_notify(Pipeline, "GroupArranged", vec![], move |input, output, notificator| {

            // 1. read each input, and stash it in our staging area.
            // only stash the keys, because vals etc are in self.trace
            while let Some((time, data)) = input.next() {
                inputs.entry_or_insert(time.time(), || { notificator.notify_at(time); data.drain(..).next().unwrap().0 });
            }

            // 2. go through each time of interest that has reached completion
            // times are interesting either because we received data, or because we conclude
            // in the processing of a time that a future time will be interesting.
            while let Some((capability, _count)) = notificator.next() {

                let time = capability.time();

                // 2a. If we received any keys, determine the interesting times for each.
                //     We then enqueue the keys at the corresponding time, for use later.
                if let Some(queue) = inputs.remove_key(&time) {

                    let source = source.borrow();
                    let mut stash = Vec::new();
                    for key in queue {
                        if source.get_difference(&key, &time).is_some() {
                            stash.push(capability.time());
                            source.interesting_times(&key, &time, &mut stash);

                            for new_time in &stash {
                                to_do.entry_or_insert(new_time.clone(), || { notificator.notify_at(capability.delayed(new_time)); Vec::new() })
                                     .push(key.clone());
                            }
                            stash.clear();
                        }
                    }
                }

                // 2b. Process any interesting keys at this time.
                if let Some(mut keys) = to_do.remove_key(&time) {

                    // We would like these keys in a particular order.
                    // We also want to de-duplicate them, in case there are dupes.
                    keys.sort_by(|x,y| (key_h(&x), x).cmp(&(key_h(&y), y)));
                    keys.dedup();

                    // accumulations for installation into result
                    let mut accumulation = Compact::new(0,0);

                    // borrow `source` to avoid constant re-borrowing.
                    let mut source_borrow = source.borrow_mut();

                    for key in keys {

                        // acquire an iterator over the collection at `time`.
                        let mut input = source_borrow.get_collection(&key, &time);

                        // if we have some input data, invoke logic to populate buffer.
                        if input.peek().is_some() { logic(&key, &mut input, &mut buffer); }

                        // sort the buffer, because we can't trust user code to do that.
                        buffer.sort_by(|x,y| x.0.cmp(&y.0));

                        // push differences in to Compact.
                        let mut compact = accumulation.session();
                        for (val, wgt) in Coalesce::coalesce(target.borrow_mut()
                                                                   .get_collection(&key, &time)
                                                                   .map(|(v, w)| (v,-w))
                                                                   .merge_by(buffer.iter().map(|&(ref v, w)| (v, w)), |x,y| {
                                                                        x.0 <= y.0
                                                                   }))
                        {
                            compact.push(val.clone(), wgt);
                        }
                        compact.done(key);
                        buffer.clear();
                    }

                    if accumulation.vals.len() > 0 {
                        output.session(&capability).give((accumulation.keys.clone(), accumulation.cnts.clone(), accumulation.vals.clone()));
                        target.borrow_mut().set_difference(time, accumulation);
                    }
                }
            }
        });

        Arranged { stream: stream, trace: result }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use first_transaction::{Account, FaucetClient, FAUCET_URL, TESTNET_URL};
use hello_blockchain::HelloBlockchainClient;
use std::env;

fn main() -> () {
    let args: Vec<String> = env::args().collect();
    println!("{:?}", args);

    assert_eq!(
        args.len(),
        2,
        "Expecting an argument that points to the helloblockchain module"
    );

    let client = HelloBlockchainClient::new(TESTNET_URL.to_string());
    let faucet_client = FaucetClient::new(FAUCET_URL.to_string(), client.rest_client.clone());

    // Create two accounts, Alice and Bob
    let mut alice = Account::new(None);
    let mut bob = Account::new(None);

    println!("\n=== Addresses ===");
    println!("Alice: 0x{}", alice.address());
    println!("Bob: 0x{}", bob.address());

    faucet_client.fund_account(&alice.pub_key(), 10_000_000);
    faucet_client.fund_account(&bob.pub_key(), 10_000_000);

    println!("\n=== Initial Balances ===");
    println!(
        "Alice: {:?}",
        client.rest_client.account_balance(&alice.address())
    );
    println!(
        "Bob: {:?}",
        client.rest_client.account_balance(&bob.address())
    );

    println!("\nUpdate the module with Alice's address, build, copy to the provided path, and press enter.");
    match std::io::stdin().read_line(&mut String::new()) {
        Ok(_n) => {}
        Err(error) => println!("error: {}", error),
    }

    let module_path = args.get(1).unwrap();
    let module_hex = hex::encode(std::fs::read(module_path).unwrap());

    println!("\n=== Testing Alice ===");
    println!("Publishing...");
    let mut tx_hash = client.publish_module(&mut alice, &module_hex);
    client.rest_client.wait_for_transaction(&tx_hash);
    println!(
        "Initial value: {:?}",
        client.get_message(&alice.address(), &alice.address())
    );
    println!("Setting the message to \"Hello, Blockchain\"");
    tx_hash = client.set_message(&alice.address(), &mut alice, &"Hello, Blockchain");
    client.rest_client.wait_for_transaction(&tx_hash);
    println!(
        "New value: {:?}",
        client.get_message(&alice.address(), &alice.address())
    );

    println!("\n=== Testing Bob ===");
    println!(
        "Initial value: {:?}",
        client.get_message(&alice.address(), &bob.address())
    );
    println!(
        "Initial value: {:?}",
        client.get_message(&alice.address(), &bob.address())
    );
    println!("Setting the message to \"Hello, Blockchain\"");
    tx_hash = client.set_message(&alice.address(), &mut bob, &"Hello, Blockchain");
    client.rest_client.wait_for_transaction(&tx_hash);
    println!(
        "New value: {:?}",
        client.get_message(&alice.address(), &bob.address())
    );
}
<commit_msg>[tutorial] fix rust hello_blockchain<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use first_transaction::{Account, FaucetClient, FAUCET_URL, TESTNET_URL};
use hello_blockchain::HelloBlockchainClient;
use std::env;

fn main() -> () {
    let args: Vec<String> = env::args().collect();
    println!("{:?}", args);

    assert_eq!(
        args.len(),
        2,
        "Expecting an argument that points to the helloblockchain module"
    );

    let client = HelloBlockchainClient::new(TESTNET_URL.to_string());
    let faucet_client = FaucetClient::new(FAUCET_URL.to_string(), client.rest_client.clone());

    // Create two accounts, Alice and Bob
    let mut alice = Account::new(None);
    let mut bob = Account::new(None);

    println!("\n=== Addresses ===");
    println!("Alice: 0x{}", alice.address());
    println!("Bob: 0x{}", bob.address());

    faucet_client.fund_account(&alice.auth_key(), 10_000_000);
    faucet_client.fund_account(&bob.auth_key(), 10_000_000);

    println!("\n=== Initial Balances ===");
    println!(
        "Alice: {:?}",
        client.rest_client.account_balance(&alice.address())
    );
    println!(
        "Bob: {:?}",
        client.rest_client.account_balance(&bob.address())
    );

    println!("\nUpdate the module with Alice's address, build, copy to the provided path, and press enter.");
    match std::io::stdin().read_line(&mut String::new()) {
        Ok(_n) => {}
        Err(error) => println!("error: {}", error),
    }

    let module_path = args.get(1).unwrap();
    let module_hex = hex::encode(std::fs::read(module_path).unwrap());

    println!("\n=== Testing Alice ===");
    println!("Publishing...");
    let mut tx_hash = client.publish_module(&mut alice, &module_hex);
    client.rest_client.wait_for_transaction(&tx_hash);
    println!(
        "Initial value: {:?}",
        client.get_message(&alice.address(), &alice.address())
    );
    println!("Setting the message to \"Hello, Blockchain\"");
    tx_hash = client.set_message(&alice.address(), &mut alice, &"Hello, Blockchain");
    client.rest_client.wait_for_transaction(&tx_hash);
    println!(
        "New value: {:?}",
        client.get_message(&alice.address(), &alice.address())
    );

    println!("\n=== Testing Bob ===");
    println!(
        "Initial value: {:?}",
        client.get_message(&alice.address(), &bob.address())
    );
    println!(
        "Initial value: {:?}",
        client.get_message(&alice.address(), &bob.address())
    );
    println!("Setting the message to \"Hello, Blockchain\"");
    tx_hash = client.set_message(&alice.address(), &mut bob, &"Hello, Blockchain");
    client.rest_client.wait_for_transaction(&tx_hash);
    println!(
        "New value: {:?}",
        client.get_message(&alice.address(), &bob.address())
    );
}
<|endoftext|>


<commit_before><commit_msg>Looks like we need reserved words; `Biased` in its current incarnation is insufficient.<commit_after><|endoftext|>


<commit_before>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;
use std::io::Error;
use std::io::ErrorKind;

use camera::Camera;
use common;
use common::{Mesh, Scene, Shader, Vertex8f32};
use loader::DBLoader;
use frustum::Frustum;

use glium::backend::glutin_backend::GlutinFacade;
use glium::{Program, Surface, Version};

use nalgebra::Vector4;

implement_vertex!(Vertex8f32, position, normal, texcoord);

/// A representation of the Glium data needed for rendering
///
pub struct Renderer {
    pub index_buffer: glium::index::NoIndices,
    pub scene: Scene,
    pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
    pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

impl Renderer {
    /// Create a new renderer from a `Scene` struct
    ///
    pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

        let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> =
            Vec::with_capacity(scene.meshes.len());

        for i in 0..scene.meshes.len() {
            vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
        }

        let index_buffer: glium::index::NoIndices =
            glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

        let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

        for i in 0..scene.images.len() {
            //TODO: determine image format by name extension if nessisary
            //let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
            let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

            let image_dimensions = image.dimensions();
            let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
                                                                           image_dimensions);
            let opengl_texture: glium::texture::CompressedSrgbTexture2d =
                glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
            textures.insert(scene.images[i].name.clone(), opengl_texture);
        }

        Renderer {
            index_buffer: index_buffer,
            scene: scene,
            textures: textures,
            vertex_buffers: vertex_buffers,
        }
    }

    /// Try to find the reference to a `Mesh` by name
    ///
    pub fn get_mesh(&self, name: &str) -> Result<&Mesh, Error> {
        for i in 0..self.vertex_buffers.len() as usize {
            if self.scene.meshes[i].name.eq(name) {
                return Ok(&self.scene.meshes[i]);
            }
        }
        return Err(Error::new(ErrorKind::NotFound, "Unable to load mesh"));
    }

    /// Create a `glium::program::Program` object from a `DBLoader` that contains the shader and shader_version tables in SQLite
    ///
    #[allow(unused_assignments)]
    pub fn create_shader_program(&self, shader_name: &str, dbloader: &DBLoader, display: &GlutinFacade) -> glium::program::Program {
        let supported_glsl_version: Version = display.get_supported_glsl_version();
        let api: glium::Api = supported_glsl_version.0;
        let major_version : u8 = supported_glsl_version.1;
        let minor_version : u8 = supported_glsl_version.2;
        let mut glsl_version_string: String = major_version.to_string();
        glsl_version_string.push_str(&minor_version.to_string());
        glsl_version_string.push('0');
        let mut use_gles: bool = false;// Use OpenGLES instead of OpenGL (for mobile devices)

        match api {
                glium::Api::Gl => {
                    use_gles = false;
                },
                glium::Api::GlEs => {
                    use_gles = true;
                    glsl_version_string.push_str(" es");
                },
        };

        let glsl_version_number: u32 = match glsl_version_string.parse() {
            Ok(s) => s,
            Err(e) =>  {
                // This is not likely to happen
                panic!("Unable to parse supported glsl version string: {}", e);
            },
        };

        println!("Using glsl version {}", &glsl_version_string);

        let shader: Shader = dbloader.load_shader(shader_name, &glsl_version_string);

        let program: Program;

        if use_gles {
            program = program!(display,
                glsl_version_number es => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
            .unwrap();
        } else {
            program = program!(display,
                glsl_version_number => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
            .unwrap();
        }

        // Shader compilation no longer required
        display.release_shader_compiler();
        return program;
    }

    /// Create a `glium::program::Program` object from a `DBLoader` that has a specific shader version
    ///
    pub fn create_shader_program_with_version(&self, shader_name: &str, dbloader: &DBLoader, glsl_version: &Version, display: &GlutinFacade) -> Result<glium::program::Program, Error> {
        if !display.is_glsl_version_supported(&glsl_version) {
            return Err(Error::new(ErrorKind::InvalidData, "Unsupported GLSL version"));
        }

        let api: glium::Api = glsl_version.0;
        let major_version : u8 = glsl_version.1;
        let minor_version : u8 = glsl_version.2;
        let mut glsl_version_string: String = major_version.to_string();
        glsl_version_string.push_str(&minor_version.to_string());
        glsl_version_string.push('0');
        let mut _use_gles: bool = false;// Use OpenGLES instead of OpenGL (for mobile devices)

        match api {
                glium::Api::Gl => {
                    _use_gles = false;
                },
                glium::Api::GlEs => {
                    _use_gles = true;
                    glsl_version_string.push_str(" es");
                },
        };

        let glsl_version_number: u32 = match glsl_version_string.parse() {
            Ok(s) => s,
            Err(e) =>  {
                // This is not likely to happen
                panic!("Unable to parse supported glsl version string: {}", e);
            },
        };

        println!("Using glsl version {}", &glsl_version_string);

        let shader: Shader = dbloader.load_shader(shader_name, &glsl_version_string);

        let program;

        if _use_gles {
            program = program!(display,
                glsl_version_number es => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
        } else {
            program = program!(display,
                glsl_version_number => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
        }

        match program {
            Ok(p) => Ok(p),
            Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
        }
    }

    /// Draw the `Scene` data consumed by self to the display
    ///
    pub fn render(&self, display: &GlutinFacade, program: &glium::program::Program, camera: &Camera) {

        let frustum: Frustum = Frustum::create_from_2d_array(
        	&camera.modelview_matrix,
        	&camera.projection_matrix,
        );

        let mut target = display.draw();
        // TODO: generate this texture instead of loading from sqlite
        let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
        target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);
        for i in 0..self.vertex_buffers.len() as usize {

        	let matrix = *self.scene.meshes[i].matrix.borrow();
        	let local_center: Vector4<f32> = Vector4::new(self.scene.meshes[i].center[0].clone(), self.scene.meshes[i].center[1].clone(), self.scene.meshes[i].center[2].clone(), 1.0f32);
	        let center: Vector4<f32> = matrix * local_center;
            if frustum.sphere_intersecting(&center.x, &center.y, &center.z, &self.scene.meshes[i].radius) {
	            let material_index: usize = self.scene.meshes[i].material_index.clone();
	            let diffuse = self.scene.materials[material_index].diffuse.clone();
	            let diffuse_texname: String =
	                self.scene.materials[material_index].diffuse_texname.clone();
	            let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
	            if diffuse_texname.len() == 0 {
	                opengl_texture = &default_blank_texture;
	            } else {
	                match self.textures.get(&diffuse_texname) {
	                    Some(t) => {
	                        opengl_texture = &t;
	                    },
	                    None => {
	                        println!("Unable to load {}, using blank texture instead.", diffuse_texname);
	                        opengl_texture = &default_blank_texture;
	                    },
	                }
	            }
	            let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
	                projection: camera.projection_matrix,
	                modelview: camera.modelview_matrix,
	                light_position_worldspace: [2.0, 10.0, 1.0f32],
	                diffuse: diffuse,
	                diffuse_texture: opengl_texture,
	                model: *(matrix).as_ref(),
	            };

	            let params = glium::DrawParameters {
	                depth: glium::Depth {
	                    test: glium::DepthTest::IfLess,
	                    write: true,
	                    .. Default::default()
	                },
	                .. Default::default()
	            };

	            target.draw(&self.vertex_buffers[i],
	                &self.index_buffer,
	                program,
	                &uniforms,
	                &params)
	                .unwrap();
            }
        }
        target.finish().unwrap();
    }
}
<commit_msg>removed print statement for if textures could not be found (in a loop)<commit_after>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;
use std::io::Error;
use std::io::ErrorKind;

use camera::Camera;
use common;
use common::{Mesh, Scene, Shader, Vertex8f32};
use loader::DBLoader;
use frustum::Frustum;

use glium::backend::glutin_backend::GlutinFacade;
use glium::{Program, Surface, Version};

use nalgebra::Vector4;

implement_vertex!(Vertex8f32, position, normal, texcoord);

/// A representation of the Glium data needed for rendering
///
pub struct Renderer {
    pub index_buffer: glium::index::NoIndices,
    pub scene: Scene,
    pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
    pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

impl Renderer {
    /// Create a new renderer from a `Scene` struct
    ///
    pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

        let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> =
            Vec::with_capacity(scene.meshes.len());

        for i in 0..scene.meshes.len() {
            vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
        }

        let index_buffer: glium::index::NoIndices =
            glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

        let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

        for i in 0..scene.images.len() {
            //TODO: determine image format by name extension if nessisary
            //let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
            let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

            let image_dimensions = image.dimensions();
            let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
                                                                           image_dimensions);
            let opengl_texture: glium::texture::CompressedSrgbTexture2d =
                glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
            textures.insert(scene.images[i].name.clone(), opengl_texture);
        }

        Renderer {
            index_buffer: index_buffer,
            scene: scene,
            textures: textures,
            vertex_buffers: vertex_buffers,
        }
    }

    /// Try to find the reference to a `Mesh` by name
    ///
    pub fn get_mesh(&self, name: &str) -> Result<&Mesh, Error> {
        for i in 0..self.vertex_buffers.len() as usize {
            if self.scene.meshes[i].name.eq(name) {
                return Ok(&self.scene.meshes[i]);
            }
        }
        return Err(Error::new(ErrorKind::NotFound, "Unable to load mesh"));
    }

    /// Create a `glium::program::Program` object from a `DBLoader` that contains the shader and shader_version tables in SQLite
    ///
    #[allow(unused_assignments)]
    pub fn create_shader_program(&self, shader_name: &str, dbloader: &DBLoader, display: &GlutinFacade) -> glium::program::Program {
        let supported_glsl_version: Version = display.get_supported_glsl_version();
        let api: glium::Api = supported_glsl_version.0;
        let major_version : u8 = supported_glsl_version.1;
        let minor_version : u8 = supported_glsl_version.2;
        let mut glsl_version_string: String = major_version.to_string();
        glsl_version_string.push_str(&minor_version.to_string());
        glsl_version_string.push('0');
        let mut use_gles: bool = false;// Use OpenGLES instead of OpenGL (for mobile devices)

        match api {
                glium::Api::Gl => {
                    use_gles = false;
                },
                glium::Api::GlEs => {
                    use_gles = true;
                    glsl_version_string.push_str(" es");
                },
        };

        let glsl_version_number: u32 = match glsl_version_string.parse() {
            Ok(s) => s,
            Err(e) =>  {
                // This is not likely to happen
                panic!("Unable to parse supported glsl version string: {}", e);
            },
        };

        println!("Using glsl version {}", &glsl_version_string);

        let shader: Shader = dbloader.load_shader(shader_name, &glsl_version_string);

        let program: Program;

        if use_gles {
            program = program!(display,
                glsl_version_number es => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
            .unwrap();
        } else {
            program = program!(display,
                glsl_version_number => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
            .unwrap();
        }

        // Shader compilation no longer required
        display.release_shader_compiler();
        return program;
    }

    /// Create a `glium::program::Program` object from a `DBLoader` that has a specific shader version
    ///
    pub fn create_shader_program_with_version(&self, shader_name: &str, dbloader: &DBLoader, glsl_version: &Version, display: &GlutinFacade) -> Result<glium::program::Program, Error> {
        if !display.is_glsl_version_supported(&glsl_version) {
            return Err(Error::new(ErrorKind::InvalidData, "Unsupported GLSL version"));
        }

        let api: glium::Api = glsl_version.0;
        let major_version : u8 = glsl_version.1;
        let minor_version : u8 = glsl_version.2;
        let mut glsl_version_string: String = major_version.to_string();
        glsl_version_string.push_str(&minor_version.to_string());
        glsl_version_string.push('0');
        let mut _use_gles: bool = false;// Use OpenGLES instead of OpenGL (for mobile devices)

        match api {
                glium::Api::Gl => {
                    _use_gles = false;
                },
                glium::Api::GlEs => {
                    _use_gles = true;
                    glsl_version_string.push_str(" es");
                },
        };

        let glsl_version_number: u32 = match glsl_version_string.parse() {
            Ok(s) => s,
            Err(e) =>  {
                // This is not likely to happen
                panic!("Unable to parse supported glsl version string: {}", e);
            },
        };

        println!("Using glsl version {}", &glsl_version_string);

        let shader: Shader = dbloader.load_shader(shader_name, &glsl_version_string);

        let program;

        if _use_gles {
            program = program!(display,
                glsl_version_number es => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
        } else {
            program = program!(display,
                glsl_version_number => {
                    vertex: &shader.vertex_source,
                    fragment: &shader.fragment_source,
                },
            )
        }

        match program {
            Ok(p) => Ok(p),
            Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
        }
    }

    /// Draw the `Scene` data consumed by self to the display
    ///
    pub fn render(&self, display: &GlutinFacade, program: &glium::program::Program, camera: &Camera) {

        let frustum: Frustum = Frustum::create_from_2d_array(
        	&camera.modelview_matrix,
        	&camera.projection_matrix,
        );

        let mut target = display.draw();
        // TODO: generate this texture instead of loading from sqlite
        let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
        target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);
        for i in 0..self.vertex_buffers.len() as usize {

        	let matrix = *self.scene.meshes[i].matrix.borrow();
        	let local_center: Vector4<f32> = Vector4::new(self.scene.meshes[i].center[0].clone(), self.scene.meshes[i].center[1].clone(), self.scene.meshes[i].center[2].clone(), 1.0f32);
	        let center: Vector4<f32> = matrix * local_center;
            if frustum.sphere_intersecting(&center.x, &center.y, &center.z, &self.scene.meshes[i].radius) {
	            let material_index: usize = self.scene.meshes[i].material_index.clone();
	            let diffuse = self.scene.materials[material_index].diffuse.clone();
	            let diffuse_texname: String =
	                self.scene.materials[material_index].diffuse_texname.clone();
	            let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
	            if diffuse_texname.len() == 0 {
	                opengl_texture = &default_blank_texture;
	            } else {
	                match self.textures.get(&diffuse_texname) {
	                    Some(t) => {
	                        opengl_texture = &t;
	                    },
	                    None => {
	                        opengl_texture = &default_blank_texture;
	                    },
	                }
	            }
	            let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
	                projection: camera.projection_matrix,
	                modelview: camera.modelview_matrix,
	                light_position_worldspace: [2.0, 10.0, 1.0f32],
	                diffuse: diffuse,
	                diffuse_texture: opengl_texture,
	                model: *(matrix).as_ref(),
	            };

	            let params = glium::DrawParameters {
	                depth: glium::Depth {
	                    test: glium::DepthTest::IfLess,
	                    write: true,
	                    .. Default::default()
	                },
	                .. Default::default()
	            };

	            target.draw(&self.vertex_buffers[i],
	                &self.index_buffer,
	                program,
	                &uniforms,
	                &params)
	                .unwrap();
            }
        }
        target.finish().unwrap();
    }
}
<|endoftext|>


<commit_before>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::same_type_and_consts;
use clippy_utils::{in_macro, meets_msrv, msrvs};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::{
    self as hir,
    def::{CtorOf, DefKind, Res},
    def_id::LocalDefId,
    intravisit::{walk_ty, NestedVisitorMap, Visitor},
    Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::{AssocKind, Ty};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
use rustc_typeck::hir_ty_to_ty;

declare_clippy_lint! {
    /// **What it does:** Checks for unnecessary repetition of structure name when a
    /// replacement with `Self` is applicable.
    ///
    /// **Why is this bad?** Unnecessary repetition. Mixed use of `Self` and struct
    /// name
    /// feels inconsistent.
    ///
    /// **Known problems:**
    /// - Unaddressed false negative in fn bodies of trait implementations
    /// - False positive with assotiated types in traits (#4140)
    ///
    /// **Example:**
    ///
    /// ```rust
    /// struct Foo {}
    /// impl Foo {
    ///     fn new() -> Foo {
    ///         Foo {}
    ///     }
    /// }
    /// ```
    /// could be
    /// ```rust
    /// struct Foo {}
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Self {}
    ///     }
    /// }
    /// ```
    pub USE_SELF,
    nursery,
    "unnecessary structure name repetition whereas `Self` is applicable"
}

#[derive(Default)]
pub struct UseSelf {
    msrv: Option<RustcVersion>,
    stack: Vec<StackItem>,
}

impl UseSelf {
    #[must_use]
    pub fn new(msrv: Option<RustcVersion>) -> Self {
        Self {
            msrv,
            ..Self::default()
        }
    }
}

#[derive(Debug)]
enum StackItem {
    Check {
        impl_id: LocalDefId,
        types_to_skip: FxHashSet<HirId>,
        types_to_lint: Vec<HirId>,
    },
    NoCheck,
}

impl_lint_pass!(UseSelf => [USE_SELF]);

const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";

impl<'tcx> LateLintPass<'tcx> for UseSelf {
    fn check_item(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
        if !is_item_interesting(item) {
            // This does two things:
            //  1) Reduce needless churn on `self.stack`
            //  2) Don't push `StackItem::NoCheck` when entering `ItemKind::OpaqueTy`,
            //     in order to lint `foo() -> impl <..>`
            return;
        }
        // We push the self types of `impl`s on a stack here. Only the top type on the stack is
        // relevant for linting, since this is the self type of the `impl` we're currently in. To
        // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that
        // we're in an `impl` or nested item, that we don't want to lint
        let stack_item = if_chain! {
            if let ItemKind::Impl(Impl { self_ty, .. }) = item.kind;
            if let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind;
            let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
            if parameters.as_ref().map_or(true, |params| {
                !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
            });
            then {
                StackItem::Check {
                    impl_id: item.def_id,
                    types_to_lint: Vec::new(),
                    types_to_skip: std::iter::once(self_ty.hir_id).collect(),
                }
            } else {
                StackItem::NoCheck
            }
        };
        self.stack.push(stack_item);
    }

    fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) {
        if is_item_interesting(item) {
            self.stack.pop();
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
        // We want to skip types in trait `impl`s that aren't declared as `Self` in the trait
        // declaration. The collection of those types is all this method implementation does.
        if_chain! {
            if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind;
            if let Some(&mut StackItem::Check {
                impl_id,
                ref mut types_to_skip,
                ..
            }) = self.stack.last_mut();
            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id);
            then {
                // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
                // `Self`.
                let self_ty = impl_trait_ref.self_ty();

                // `trait_method_sig` is the signature of the function, how it is declared in the
                // trait, not in the impl of the trait.
                let trait_method = cx
                    .tcx
                    .associated_items(impl_trait_ref.def_id)
                    .find_by_name_and_kind(cx.tcx, impl_item.ident, AssocKind::Fn, impl_trait_ref.def_id)
                    .expect("impl method matches a trait method");
                let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id);
                let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig);

                // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the
                // implementation of the trait.
                let output_hir_ty = if let FnRetTy::Return(ty) = &decl.output {
                    Some(&**ty)
                } else {
                    None
                };
                let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty);

                // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature.
                //
                // `trait_sem_ty` (of type `ty::Ty`) is the semantic type for the signature in the
                // trait declaration. This is used to check if `Self` was used in the trait
                // declaration.
                //
                // If `any`where in the `trait_sem_ty` the `self_ty` was used verbatim (as opposed
                // to `Self`), we want to skip linting that type and all subtypes of it. This
                // avoids suggestions to e.g. replace `Vec<u8>` with `Vec<Self>`, in an `impl Trait
                // for u8`, when the trait always uses `Vec<u8>`.
                //
                // See also https://github.com/rust-lang/rust-clippy/issues/2894.
                for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
                    if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
                        let mut visitor = SkipTyCollector::default();
                        visitor.visit_ty(impl_hir_ty);
                        types_to_skip.extend(visitor.types_to_skip);
                    }
                }
            }
        }
    }

    fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) {
        // `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies
        // we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`.
        // However the `node_type()` method can *only* be called in bodies.
        //
        // This method implementation determines which types should get linted in a `Body` and
        // which shouldn't, with a visitor. We could directly lint in the visitor, but then we
        // could only allow this lint on item scope. And we would have to check if those types are
        // already dealt with in `check_ty` anyway.
        if let Some(StackItem::Check {
            impl_id,
            types_to_lint,
            types_to_skip,
            ..
        }) = self.stack.last_mut()
        {
            let self_ty = cx.tcx.type_of(*impl_id);

            let mut visitor = LintTyCollector {
                cx,
                self_ty,
                types_to_lint: vec![],
                types_to_skip: vec![],
            };
            visitor.visit_expr(&body.value);
            types_to_lint.extend(visitor.types_to_lint);
            types_to_skip.extend(visitor.types_to_skip);
        }
    }

    fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
        if_chain! {
            if !in_macro(hir_ty.span);
            if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
            if let Some(StackItem::Check {
                impl_id,
                types_to_lint,
                types_to_skip,
            }) = self.stack.last();
            if !types_to_skip.contains(&hir_ty.hir_id);
            if types_to_lint.contains(&hir_ty.hir_id)
                || {
                    let self_ty = cx.tcx.type_of(*impl_id);
                    should_lint_ty(hir_ty, hir_ty_to_ty(cx.tcx, hir_ty), self_ty)
                };
            let hir = cx.tcx.hir();
            let id = hir.get_parent_node(hir_ty.hir_id);
            if !hir.opt_span(id).map_or(false, in_macro);
            then {
                span_lint(cx, hir_ty.span);
            }
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if !in_macro(expr.span);
            if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
            if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
            if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id);
            then {} else { return; }
        }
        match expr.kind {
            ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res {
                Res::SelfTy(..) => (),
                Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path),
                _ => span_lint(cx, path.span),
            },
            // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`)
            ExprKind::Call(fun, _) => {
                if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind {
                    if let Res::Def(DefKind::Ctor(ctor_of, _), ..) = path.res {
                        match ctor_of {
                            CtorOf::Variant => lint_path_to_variant(cx, path),
                            CtorOf::Struct => span_lint(cx, path.span),
                        }
                    }
                }
            },
            // unit enum variants (`Enum::A`)
            ExprKind::Path(QPath::Resolved(_, path)) => lint_path_to_variant(cx, path),
            _ => (),
        }
    }

    extract_msrv_attr!(LateContext);
}

#[derive(Default)]
struct SkipTyCollector {
    types_to_skip: Vec<HirId>,
}

impl<'tcx> Visitor<'tcx> for SkipTyCollector {
    type Map = Map<'tcx>;

    fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) {
        self.types_to_skip.push(hir_ty.hir_id);

        walk_ty(self, hir_ty);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}

struct LintTyCollector<'a, 'tcx> {
    cx: &'a LateContext<'tcx>,
    self_ty: Ty<'tcx>,
    types_to_lint: Vec<HirId>,
    types_to_skip: Vec<HirId>,
}

impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> {
    type Map = Map<'tcx>;

    fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) {
        if_chain! {
            if let Some(ty) = self.cx.typeck_results().node_type_opt(hir_ty.hir_id);
            if should_lint_ty(hir_ty, ty, self.self_ty);
            then {
                self.types_to_lint.push(hir_ty.hir_id);
            } else {
                self.types_to_skip.push(hir_ty.hir_id);
            }
        }

        walk_ty(self, hir_ty);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}

fn span_lint(cx: &LateContext<'_>, span: Span) {
    span_lint_and_sugg(
        cx,
        USE_SELF,
        span,
        "unnecessary structure name repetition",
        "use the applicable keyword",
        "Self".to_owned(),
        Applicability::MachineApplicable,
    );
}

fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) {
    if let [.., self_seg, _variant] = path.segments {
        let span = path
            .span
            .with_hi(self_seg.args().span_ext().unwrap_or(self_seg.ident.span).hi());
        span_lint(cx, span);
    }
}

fn is_item_interesting(item: &Item<'_>) -> bool {
    use rustc_hir::ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union};
    matches!(
        item.kind,
        Impl { .. } | Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..)
    )
}

fn should_lint_ty(hir_ty: &hir::Ty<'_>, ty: Ty<'_>, self_ty: Ty<'_>) -> bool {
    if_chain! {
        if same_type_and_consts(ty, self_ty);
        if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
        then {
            !matches!(path.res, Res::SelfTy(..) | Res::Def(DefKind::TyParam, _))
        } else {
            false
        }
    }
}
<commit_msg>Remove a visitor from use_self<commit_after>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::same_type_and_consts;
use clippy_utils::{in_macro, meets_msrv, msrvs};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::{
    self as hir,
    def::{CtorOf, DefKind, Res},
    def_id::LocalDefId,
    intravisit::{walk_ty, NestedVisitorMap, Visitor},
    Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::AssocKind;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
use rustc_typeck::hir_ty_to_ty;

declare_clippy_lint! {
    /// **What it does:** Checks for unnecessary repetition of structure name when a
    /// replacement with `Self` is applicable.
    ///
    /// **Why is this bad?** Unnecessary repetition. Mixed use of `Self` and struct
    /// name
    /// feels inconsistent.
    ///
    /// **Known problems:**
    /// - Unaddressed false negative in fn bodies of trait implementations
    /// - False positive with assotiated types in traits (#4140)
    ///
    /// **Example:**
    ///
    /// ```rust
    /// struct Foo {}
    /// impl Foo {
    ///     fn new() -> Foo {
    ///         Foo {}
    ///     }
    /// }
    /// ```
    /// could be
    /// ```rust
    /// struct Foo {}
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Self {}
    ///     }
    /// }
    /// ```
    pub USE_SELF,
    nursery,
    "unnecessary structure name repetition whereas `Self` is applicable"
}

#[derive(Default)]
pub struct UseSelf {
    msrv: Option<RustcVersion>,
    stack: Vec<StackItem>,
}

impl UseSelf {
    #[must_use]
    pub fn new(msrv: Option<RustcVersion>) -> Self {
        Self {
            msrv,
            ..Self::default()
        }
    }
}

#[derive(Debug)]
enum StackItem {
    Check {
        impl_id: LocalDefId,
        in_body: u32,
        types_to_skip: FxHashSet<HirId>,
    },
    NoCheck,
}

impl_lint_pass!(UseSelf => [USE_SELF]);

const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";

impl<'tcx> LateLintPass<'tcx> for UseSelf {
    fn check_item(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
        if !is_item_interesting(item) {
            // This does two things:
            //  1) Reduce needless churn on `self.stack`
            //  2) Don't push `StackItem::NoCheck` when entering `ItemKind::OpaqueTy`,
            //     in order to lint `foo() -> impl <..>`
            return;
        }
        // We push the self types of `impl`s on a stack here. Only the top type on the stack is
        // relevant for linting, since this is the self type of the `impl` we're currently in. To
        // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that
        // we're in an `impl` or nested item, that we don't want to lint
        let stack_item = if_chain! {
            if let ItemKind::Impl(Impl { self_ty, .. }) = item.kind;
            if let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind;
            let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
            if parameters.as_ref().map_or(true, |params| {
                !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
            });
            then {
                StackItem::Check {
                    impl_id: item.def_id,
                    in_body: 0,
                    types_to_skip: std::iter::once(self_ty.hir_id).collect(),
                }
            } else {
                StackItem::NoCheck
            }
        };
        self.stack.push(stack_item);
    }

    fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) {
        if is_item_interesting(item) {
            self.stack.pop();
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
        // We want to skip types in trait `impl`s that aren't declared as `Self` in the trait
        // declaration. The collection of those types is all this method implementation does.
        if_chain! {
            if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind;
            if let Some(&mut StackItem::Check {
                impl_id,
                ref mut types_to_skip,
                ..
            }) = self.stack.last_mut();
            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id);
            then {
                // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
                // `Self`.
                let self_ty = impl_trait_ref.self_ty();

                // `trait_method_sig` is the signature of the function, how it is declared in the
                // trait, not in the impl of the trait.
                let trait_method = cx
                    .tcx
                    .associated_items(impl_trait_ref.def_id)
                    .find_by_name_and_kind(cx.tcx, impl_item.ident, AssocKind::Fn, impl_trait_ref.def_id)
                    .expect("impl method matches a trait method");
                let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id);
                let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig);

                // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the
                // implementation of the trait.
                let output_hir_ty = if let FnRetTy::Return(ty) = &decl.output {
                    Some(&**ty)
                } else {
                    None
                };
                let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty);

                // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature.
                //
                // `trait_sem_ty` (of type `ty::Ty`) is the semantic type for the signature in the
                // trait declaration. This is used to check if `Self` was used in the trait
                // declaration.
                //
                // If `any`where in the `trait_sem_ty` the `self_ty` was used verbatim (as opposed
                // to `Self`), we want to skip linting that type and all subtypes of it. This
                // avoids suggestions to e.g. replace `Vec<u8>` with `Vec<Self>`, in an `impl Trait
                // for u8`, when the trait always uses `Vec<u8>`.
                //
                // See also https://github.com/rust-lang/rust-clippy/issues/2894.
                for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
                    if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
                        let mut visitor = SkipTyCollector::default();
                        visitor.visit_ty(impl_hir_ty);
                        types_to_skip.extend(visitor.types_to_skip);
                    }
                }
            }
        }
    }

    fn check_body(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) {
        // `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies
        // we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`.
        // However the `node_type()` method can *only* be called in bodies.
        if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() {
            *in_body = in_body.saturating_add(1);
        }
    }

    fn check_body_post(&mut self, _: &LateContext<'_>, _: &hir::Body<'_>) {
        if let Some(&mut StackItem::Check { ref mut in_body, .. }) = self.stack.last_mut() {
            *in_body = in_body.saturating_sub(1);
        }
    }

    fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
        if_chain! {
            if !in_macro(hir_ty.span);
            if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
            if let Some(&StackItem::Check {
                impl_id,
                in_body,
                ref types_to_skip,
            }) = self.stack.last();
            if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
            if !matches!(path.res, Res::SelfTy(..) | Res::Def(DefKind::TyParam, _));
            if !types_to_skip.contains(&hir_ty.hir_id);
            let ty = if in_body > 0 {
                cx.typeck_results().node_type(hir_ty.hir_id)
            } else {
                hir_ty_to_ty(cx.tcx, hir_ty)
            };
            if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
            let hir = cx.tcx.hir();
            let id = hir.get_parent_node(hir_ty.hir_id);
            if !hir.opt_span(id).map_or(false, in_macro);
            then {
                span_lint(cx, hir_ty.span);
            }
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if !in_macro(expr.span);
            if meets_msrv(self.msrv.as_ref(), &msrvs::TYPE_ALIAS_ENUM_VARIANTS);
            if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
            if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id);
            then {} else { return; }
        }
        match expr.kind {
            ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res {
                Res::SelfTy(..) => (),
                Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path),
                _ => span_lint(cx, path.span),
            },
            // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`)
            ExprKind::Call(fun, _) => {
                if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind {
                    if let Res::Def(DefKind::Ctor(ctor_of, _), ..) = path.res {
                        match ctor_of {
                            CtorOf::Variant => lint_path_to_variant(cx, path),
                            CtorOf::Struct => span_lint(cx, path.span),
                        }
                    }
                }
            },
            // unit enum variants (`Enum::A`)
            ExprKind::Path(QPath::Resolved(_, path)) => lint_path_to_variant(cx, path),
            _ => (),
        }
    }

    extract_msrv_attr!(LateContext);
}

#[derive(Default)]
struct SkipTyCollector {
    types_to_skip: Vec<HirId>,
}

impl<'tcx> Visitor<'tcx> for SkipTyCollector {
    type Map = Map<'tcx>;

    fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) {
        self.types_to_skip.push(hir_ty.hir_id);

        walk_ty(self, hir_ty);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}

fn span_lint(cx: &LateContext<'_>, span: Span) {
    span_lint_and_sugg(
        cx,
        USE_SELF,
        span,
        "unnecessary structure name repetition",
        "use the applicable keyword",
        "Self".to_owned(),
        Applicability::MachineApplicable,
    );
}

fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) {
    if let [.., self_seg, _variant] = path.segments {
        let span = path
            .span
            .with_hi(self_seg.args().span_ext().unwrap_or(self_seg.ident.span).hi());
        span_lint(cx, span);
    }
}

fn is_item_interesting(item: &Item<'_>) -> bool {
    use rustc_hir::ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union};
    matches!(
        item.kind,
        Impl { .. } | Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..)
    )
}
<|endoftext|>


<commit_before>// This module implements simple request and response objects.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use core;
use std::iter;
use std::ascii::OwnedAsciiExt;

use http::status;

/// Headers iterator.
pub type HeaderEntries<'a> = iter::Map<'static, &'a(String, String), (&'a String, &'a String), core::slice::Items<'a, (String, String)>>;
/// Header keys iterator.
pub type HeaderKeys<'a> = iter::Map<'static, (&'a String, &'a String), &'a String, HeaderEntries<'a>>;
/// Header values iterator.
pub type HeaderValues<'a> = iter::Map<'static, (&'a String, &'a String), &'a String, HeaderEntries<'a>>;

/// Headers type that stores some headers.  It has a HashMap like interface
/// but is ordered and can store the same keys multiple times.
pub struct Headers {
    list: Vec<(String, String)>,
}

impl Headers {
    /// Create `Headers`.
    pub fn new(list: Option<Vec<(String, String)>>) -> Headers {
        match list {
            Some(list) => Headers{list: list},
            None => Headers{list: Vec::new()},
        }
    }

    /// Return a reference to the value corresponding to the header key.
    pub fn get(&self, key: String) -> Option<&String> {
        let ikey = key.into_ascii_lower();
        for ref kvpairs in self.list.iter() {
            let k = kvpairs.ref0();
            let v = kvpairs.ref1();
            if k.clone().into_ascii_lower() == ikey {
                return Some(v)
            }
        }
        return None
    }

    /// Return a list of all the references to the values for a given key.
    /// If that key is not in the headers, the return value will be an empty vector.
    pub fn get_all(&self, key: String) -> Vec<&String> {
        let ikey = key.into_ascii_lower();
        let mut result = Vec::new();
        for ref kvpairs in self.list.iter() {
            let k = kvpairs.ref0();
            let v = kvpairs.ref1();
            if k.clone().into_ascii_lower() == ikey {
                result.push(v);
            }
        }
        return result
    }

    /// An iterator visiting all key-value pairs in sorted order.
    /// Iterator element type is `(&'a String, &'a String)`.
    pub fn iter(&self) -> HeaderEntries {
        self.list.iter().map(|ref kvpairs| (kvpairs.ref0(), kvpairs.ref1()))
    }

    /// An iterator visiting all keys in sorted order.
    /// Iterator element type is `&'a String`.
    pub fn keys(&self) -> HeaderKeys {
        self.iter().map(|(k, _v)| k)
    }

    /// An iterator visiting all values in sorted order.
    /// Iterator element type is `&'a String`.
    pub fn values(&self) -> HeaderValues {
        self.iter().map(|(_k, v)| v)
    }

    /// Add a new header key-value pair to headers.
    /// TODO: _options_header_vkw
    pub fn add(&mut self, key: String, value: String) {
        self.list.push((key, value));
    }

    /// Removes a key from the headers, returning the first value at the key
    /// if the key was previously in the headers.
    pub fn remove(&mut self, key: String) -> Option<String> {
        let ikey = key.into_ascii_lower();
        let mut rv: Option<String> = None;
        let mut newlist = Vec::new();
        for kvpairs in self.list.iter() {
            let k = kvpairs.ref0();
            let v = kvpairs.ref1();
            if k.clone().into_ascii_lower() != ikey {
                newlist.push((k.clone(), v.clone()));
            } else if rv != None {
                rv = Some(v.clone());
            }
        }
        return rv;
    }

    /// Return ths number of elements in the headers.
    pub fn len(&self) -> uint {
        return self.list.len();
    }

    /// Clears all headers.
    pub fn clear(&mut self) {
        self.list.clear();
    }
}

/// Response type.  It is just one container with a couple of parameters
/// (headers, body, status code etc).
pub struct Response {
    pub status: status::Status,
    pub headers: Headers,
    pub body: String,
}

impl Response {
    /// Create a `Response`.
    pub fn new(body: String) -> Response {
        Response {
            status: status::Ok,
            headers: Headers::new(None),
            body: body,
        }
    }

    pub fn get_status_code(&self) -> u16 {
        self.status.code()
    }

    pub fn set_status_code(&mut self, code: u16) {
        match FromPrimitive::from_u64(code as u64) {
            Some(status) => { self.status = status; },
            None => { self.status = status::UnregisteredStatus(code as u16, String::from_str("UNKNOWN")); },
        }
    }

    pub fn get_status(&self) -> status::Status {
        self.status.clone()
    }

    pub fn set_status(&mut self, status: status::Status) {
        self.status = status;
    }
}
<commit_msg>Added headers set<commit_after>// This module implements simple request and response objects.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use core;
use std::iter;
use std::ascii::OwnedAsciiExt;

use http::status;

/// Headers iterator.
pub type HeaderEntries<'a> = iter::Map<'static, &'a(String, String), (&'a String, &'a String), core::slice::Items<'a, (String, String)>>;
/// Header keys iterator.
pub type HeaderKeys<'a> = iter::Map<'static, (&'a String, &'a String), &'a String, HeaderEntries<'a>>;
/// Header values iterator.
pub type HeaderValues<'a> = iter::Map<'static, (&'a String, &'a String), &'a String, HeaderEntries<'a>>;

/// Headers type that stores some headers.  It has a HashMap like interface
/// but is ordered and can store the same keys multiple times.
pub struct Headers {
    list: Vec<(String, String)>,
}

impl Headers {
    /// Create `Headers`.
    pub fn new(list: Option<Vec<(String, String)>>) -> Headers {
        match list {
            Some(list) => Headers{list: list},
            None => Headers{list: Vec::new()},
        }
    }

    /// Return a reference to the value corresponding to the header key.
    pub fn get(&self, key: String) -> Option<&String> {
        let ikey = key.into_ascii_lower();
        for ref kvpair in self.list.iter() {
            let k = kvpair.ref0();
            let v = kvpair.ref1();
            if k.clone().into_ascii_lower() == ikey {
                return Some(v)
            }
        }
        return None
    }

    /// Return a list of all the references to the values for a given key.
    /// If that key is not in the headers, the return value will be an empty vector.
    pub fn get_all(&self, key: String) -> Vec<&String> {
        let ikey = key.into_ascii_lower();
        let mut result = Vec::new();
        for ref kvpair in self.list.iter() {
            let k = kvpair.ref0();
            let v = kvpair.ref1();
            if k.clone().into_ascii_lower() == ikey {
                result.push(v);
            }
        }
        return result
    }

    /// An iterator visiting all key-value pairs in sorted order.
    /// Iterator element type is `(&'a String, &'a String)`.
    pub fn iter(&self) -> HeaderEntries {
        self.list.iter().map(|ref kvpair| (kvpair.ref0(), kvpair.ref1()))
    }

    /// An iterator visiting all keys in sorted order.
    /// Iterator element type is `&'a String`.
    pub fn keys(&self) -> HeaderKeys {
        self.iter().map(|(k, _v)| k)
    }

    /// An iterator visiting all values in sorted order.
    /// Iterator element type is `&'a String`.
    pub fn values(&self) -> HeaderValues {
        self.iter().map(|(_k, v)| v)
    }

    /// Add a new header key-value pair to headers.
    /// TODO: _options_header_vkw
    pub fn add(&mut self, key: String, value: String) {
        self.list.push((key, value));
    }

    /// Removes a key from the headers, returning the first value at the key
    /// if the key was previously in the headers.
    pub fn remove(&mut self, key: String) -> Option<String> {
        let ikey = key.into_ascii_lower();
        let mut rv: Option<String> = None;
        let mut newlist = Vec::new();
        for kvpair in self.list.iter() {
            let k = kvpair.ref0();
            let v = kvpair.ref1();
            if k.clone().into_ascii_lower() != ikey {
                newlist.push((k.clone(), v.clone()));
            } else if rv != None {
                rv = Some(v.clone());
            }
        }
        self.list = newlist;
        return rv;
    }

    /// Removes all headers for `key` and add a new one.  The newly added key either
    /// appears at the end of the list if there was no entry or replaces the old one.
    /// TODO: _option_header_vkw
    pub fn set(&mut self, key: String, value: String) {
        let ikey = key.clone().into_ascii_lower();
        let mut key_existed = false;
        let mut newlist = Vec::new();
        for kvpair in self.list.iter() {
            let k = kvpair.ref0();
            let v = kvpair.ref1();
            if k.clone().into_ascii_lower() != ikey {
                newlist.push((k.clone(), v.clone()));
            } else if !key_existed {
                newlist.push((key.clone(), value.clone()));
                key_existed = true;
            }
        }
        if !key_existed {
            newlist.push((key, value));
        }
        self.list = newlist;
    }

    /// Return ths number of elements in the headers.
    pub fn len(&self) -> uint {
        return self.list.len();
    }

    /// Clears all headers.
    pub fn clear(&mut self) {
        self.list.clear();
    }
}

/// Response type.  It is just one container with a couple of parameters
/// (headers, body, status code etc).
pub struct Response {
    pub status: status::Status,
    pub headers: Headers,
    pub body: String,
}

impl Response {
    /// Create a `Response`.
    pub fn new(body: String) -> Response {
        Response {
            status: status::Ok,
            headers: Headers::new(None),
            body: body,
        }
    }

    pub fn get_status_code(&self) -> u16 {
        self.status.code()
    }

    pub fn set_status_code(&mut self, code: u16) {
        match FromPrimitive::from_u64(code as u64) {
            Some(status) => { self.status = status; },
            None => { self.status = status::UnregisteredStatus(code as u16, String::from_str("UNKNOWN")); },
        }
    }

    pub fn get_status(&self) -> status::Status {
        self.status.clone()
    }

    pub fn set_status(&mut self, status: status::Status) {
        self.status = status;
    }
}
<|endoftext|>