<commit_before>//! Shared read access to a trace.

use std::rc::{Rc, Weak};
use std::cell::RefCell;
use std::default::Default;
use std::collections::VecDeque;

use timely::dataflow::Scope;
use timely::dataflow::operators::generic::source;
use timely::progress::Timestamp;
use timely::dataflow::operators::CapabilitySet;

use lattice::Lattice;
use trace::{Trace, TraceReader, Batch, BatchReader, Cursor};

use trace::wrappers::rc::TraceBox;

use timely::scheduling::Activator;

use super::{TraceWriter, TraceAgentQueueWriter, TraceAgentQueueReader, Arranged};
use super::TraceReplayInstruction;

/// A `TraceReader` wrapper which can be imported into other dataflows.
///
/// The `TraceAgent` is the default trace type produced by `arranged`, and it can be extracted
/// from the dataflow in which it was defined, and imported into other dataflows.
pub struct TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    trace: Rc<RefCell<TraceBox
>>,
    queues: Weak<RefCell<Vec<TraceAgentQueueWriter
>>>,
    advance: Vec
,
    through: Vec
,
}

impl
 TraceReader for TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    type Key = Tr::Key;
    type Val = Tr::Val;
    type Time = Tr::Time;
    type R = Tr::R;

    type Batch = Tr::Batch;
    type Cursor = Tr::Cursor;

    fn advance_by(&mut self, frontier: &[Tr::Time]) {
        self.trace.borrow_mut().adjust_advance_frontier(&self.advance[..], frontier);
        self.advance.clear();
        self.advance.extend(frontier.iter().cloned());
    }
    fn advance_frontier(&mut self) -> &[Tr::Time] {
        &self.advance[..]
    }
    fn distinguish_since(&mut self, frontier: &[Tr::Time]) {
        self.trace.borrow_mut().adjust_through_frontier(&self.through[..], frontier);
        self.through.clear();
        self.through.extend(frontier.iter().cloned());
    }
    fn distinguish_frontier(&mut self) -> &[Tr::Time] {
        &self.through[..]
    }
    fn cursor_through(&mut self, frontier: &[Tr::Time]) -> Option<(Tr::Cursor, ::Storage)> {
        self.trace.borrow_mut().trace.cursor_through(frontier)
    }
    fn map_batches<F: FnMut(&Self::Batch)>(&mut self, f: F) { self.trace.borrow_mut().trace.map_batches(f) }
}

impl
 TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Timestamp+Lattice,
{
    /// Creates a new agent from a trace reader.
    pub fn new(trace: Tr) -> (Self, TraceWriter
)
    where
        Tr: Trace,
        Tr::Batch: Batch
,
    {
        let trace = Rc::new(RefCell::new(TraceBox::new(trace)));
        let queues = Rc::new(RefCell::new(Vec::new()));

        let reader = TraceAgent {
            trace: trace.clone(),
            queues: Rc::downgrade(&queues),
            advance: trace.borrow().advance_frontiers.frontier().to_vec(),
            through: trace.borrow().through_frontiers.frontier().to_vec(),
        };

        let writer = TraceWriter::new(
            vec![Default::default()],
            Rc::downgrade(&trace),
            queues,
        );

        (reader, writer)
    }

    /// Attaches a new shared queue to the trace.
    ///
    /// The queue is first populated with existing batches from the trace,
    /// The queue will be immediately populated with existing historical batches from the trace, and until the reference
    /// is dropped the queue will receive new batches as produced by the source `arrange` operator.
    pub fn new_listener(&mut self, activator: Activator) -> TraceAgentQueueReader

    where
        Tr::Time: Default
    {
        // create a new queue for progress and batch information.
        let mut new_queue = VecDeque::new();

        // add the existing batches from the trace
        let mut upper = None;
        self.trace
            .borrow_mut()
            .trace
            .map_batches(|batch| {
                new_queue.push_back(TraceReplayInstruction::Batch(batch.clone(), Some(Default::default())));
                upper = Some(batch.upper().to_vec());
            });

        if let Some(upper) = upper {
            new_queue.push_back(TraceReplayInstruction::Frontier(upper));
        }

        let reference = Rc::new((activator, RefCell::new(new_queue)));

        // wraps the queue in a ref-counted ref cell and enqueue/return it.
        if let Some(queue) = self.queues.upgrade() {
            queue.borrow_mut().push(Rc::downgrade(&reference));
        }
        reference.0.activate();
        reference
    }
}

impl
 TraceAgent

where
    Tr: TraceReader+'static,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    /// Copies an existing collection into the supplied scope.
    ///
    /// This method creates an `Arranged` collection that should appear indistinguishable from applying `arrange`
    /// directly to the source collection brought into the local scope. The only caveat is that the initial state
    /// of the collection is its current state, and updates occur from this point forward. The historical changes
    /// the collection experienced in the past are accumulated, and the distinctions from the initial collection
    /// are no longer evident.
    ///
    /// The current behavior is that the introduced collection accumulates updates to some times less or equal
    /// to `self.advance_frontier()`. There is *not* currently a guarantee that the updates are accumulated *to*
    /// the frontier, and the resulting collection history may be weirdly partial until this point. In particular,
    /// the historical collection may move through configurations that did not actually occur, even if eventually
    /// arriving at the correct collection. This is probably a bug; although we get to the right place in the end,
    /// the intermediate computation could do something that the original computation did not, like diverge.
    ///
    /// I would expect the semantics to improve to "updates are advanced to `self.advance_frontier()`", which
    /// means the computation will run as if starting from exactly this frontier. It is not currently clear whose
    /// responsibility this should be (the trace/batch should only reveal these times, or an operator should know
    /// to advance times before using them).
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate timely;
    /// extern crate differential_dataflow;
    ///
    /// use timely::Configuration;
    /// use differential_dataflow::input::Input;
    /// use differential_dataflow::operators::arrange::ArrangeBySelf;
    /// use differential_dataflow::operators::reduce::Reduce;
    /// use differential_dataflow::trace::Trace;
    /// use differential_dataflow::trace::implementations::ord::OrdValSpine;
    /// use differential_dataflow::hashable::OrdWrapper;
    ///
    /// fn main() {
    ///     ::timely::execute(Configuration::Thread, |worker| {
    ///
    ///         // create a first dataflow
    ///         let mut trace = worker.dataflow::<u32,_,_>(|scope| {
    ///             // create input handle and collection.
    ///             scope.new_collection_from(0 .. 10).1
    ///                  .arrange_by_self()
    ///                  .trace
    ///         });
    ///
    ///         // do some work.
    ///         worker.step();
    ///         worker.step();
    ///
    ///         // create a second dataflow
    ///         worker.dataflow(move |scope| {
    ///             trace.import(scope)
    ///                  .reduce(move |_key, src, dst| dst.push((*src[0].0, 1)));
    ///         });
    ///
    ///     }).unwrap();
    /// }
    /// ```
    pub fn import<G>(&mut self, scope: &G) -> Arranged<G, TraceAgent
>
    where
        G: Scope<Timestamp=Tr::Time>,
        Tr::Time: Timestamp,
    {
        self.import_named(scope, "ArrangedSource")
    }

    /// Same as `import`, but allows to name the source.
    pub fn import_named<G>(&mut self, scope: &G, name: &str) -> Arranged<G, TraceAgent
>
    where
        G: Scope<Timestamp=Tr::Time>,
        Tr::Time: Timestamp,
    {
        // Drop ShutdownButton and return only the arrangement.
        self.import_core(scope, name).0
    }
    /// Imports an arrangement into the supplied scope.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate timely;
    /// extern crate differential_dataflow;
    ///
    /// use timely::Configuration;
    /// use timely::dataflow::ProbeHandle;
    /// use timely::dataflow::operators::Probe;
    /// use differential_dataflow::input::InputSession;
    /// use differential_dataflow::operators::arrange::ArrangeBySelf;
    /// use differential_dataflow::operators::reduce::Reduce;
    /// use differential_dataflow::trace::Trace;
    /// use differential_dataflow::trace::implementations::ord::OrdValSpine;
    /// use differential_dataflow::hashable::OrdWrapper;
    ///
    /// fn main() {
    ///     ::timely::execute(Configuration::Thread, |worker| {
    ///
    ///         let mut input = InputSession::<_,(),isize>::new();
    ///         let mut probe = ProbeHandle::new();
    ///
    ///         // create a first dataflow
    ///         let mut trace = worker.dataflow::<u32,_,_>(|scope| {
    ///             // create input handle and collection.
    ///             input.to_collection(scope)
    ///                  .arrange_by_self()
    ///                  .trace
    ///         });
    ///
    ///         // do some work.
    ///         worker.step();
    ///         worker.step();
    ///
    ///         // create a second dataflow
    ///         let mut shutdown = worker.dataflow(|scope| {
    ///             let (arrange, button) = trace.import_core(scope, "Import");
    ///             arrange.stream.probe_with(&mut probe);
    ///             button
    ///         });
    ///
    ///         worker.step();
    ///         worker.step();
    ///         assert!(!probe.done());
    ///
    ///         shutdown.press();
    ///
    ///         worker.step();
    ///         worker.step();
    ///         assert!(probe.done());
    ///
    ///     }).unwrap();
    /// }
    /// ```
    pub fn import_core<G>(&mut self, scope: &G, name: &str) -> (Arranged<G, TraceAgent
>, ShutdownButton<CapabilitySet
>)
    where
        G: Scope<Timestamp=Tr::Time>,
        Tr::Time: Timestamp,
    {
        let trace = self.clone();

        let mut shutdown_button = None;

        let stream = {

            let mut shutdown_button_ref = &mut shutdown_button;
            source(scope, name, move |capability, info| {

                let capabilities = Rc::new(RefCell::new(Some(CapabilitySet::new())));

                let activator = scope.activator_for(&info.address[..]);
                let queue = self.new_listener(activator);

                let activator = scope.activator_for(&info.address[..]);
                *shutdown_button_ref = Some(ShutdownButton::new(capabilities.clone(), activator));

                capabilities.borrow_mut().as_mut().unwrap().insert(capability);

                move |output| {

                    let mut capabilities = capabilities.borrow_mut();
                    if let Some(ref mut capabilities) = *capabilities {

                        let mut borrow = queue.1.borrow_mut();
                        for instruction in borrow.drain(..) {
                            match instruction {
                                TraceReplayInstruction::Frontier(frontier) => {
                                    capabilities.downgrade(&frontier[..]);
                                },
                                TraceReplayInstruction::Batch(batch, hint) => {
                                    if let Some(time) = hint {
                                        let delayed = capabilities.delayed(&time);
                                        output.session(&delayed).give(batch);
                                    }
                                }
                            }
                        }
                    }
                }
            })
        };

        (Arranged { stream, trace }, shutdown_button.unwrap())
    }
}

/// Wrapper than can drop shared references.
pub struct ShutdownButton<T> {
    reference: Rc<RefCell<Option<T>>>,
    activator: Activator,
}

impl<T> ShutdownButton<T> {
    /// Creates a new ShutdownButton.
    pub fn new(reference: Rc<RefCell<Option<T>>>, activator: Activator) -> Self {
        Self { reference, activator }
    }
    /// Push the shutdown button, dropping the shared objects.
    pub fn press(&mut self) {
        *self.reference.borrow_mut() = None;
        self.activator.activate();
    }
}

impl
 Clone for TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    fn clone(&self) -> Self {

        // increase counts for wrapped `TraceBox`.
        self.trace.borrow_mut().adjust_advance_frontier(&[], &self.advance[..]);
        self.trace.borrow_mut().adjust_through_frontier(&[], &self.through[..]);

        TraceAgent {
            trace: self.trace.clone(),
            queues: self.queues.clone(),
            advance: self.advance.clone(),
            through: self.through.clone(),
        }
    }
}

impl
 Drop for TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    fn drop(&mut self) {
        // decrement borrow counts to remove all holds
        self.trace.borrow_mut().adjust_advance_frontier(&self.advance[..], &[]);
        self.trace.borrow_mut().adjust_through_frontier(&self.through[..], &[]);
    }
}<commit_msg>enrich shutdown button<commit_after>//! Shared read access to a trace.

use std::rc::{Rc, Weak};
use std::cell::RefCell;
use std::default::Default;
use std::collections::VecDeque;

use timely::dataflow::Scope;
use timely::dataflow::operators::generic::source;
use timely::progress::Timestamp;
use timely::dataflow::operators::CapabilitySet;

use lattice::Lattice;
use trace::{Trace, TraceReader, Batch, BatchReader, Cursor};

use trace::wrappers::rc::TraceBox;

use timely::scheduling::Activator;

use super::{TraceWriter, TraceAgentQueueWriter, TraceAgentQueueReader, Arranged};
use super::TraceReplayInstruction;

/// A `TraceReader` wrapper which can be imported into other dataflows.
///
/// The `TraceAgent` is the default trace type produced by `arranged`, and it can be extracted
/// from the dataflow in which it was defined, and imported into other dataflows.
pub struct TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    trace: Rc<RefCell<TraceBox
>>,
    queues: Weak<RefCell<Vec<TraceAgentQueueWriter
>>>,
    advance: Vec
,
    through: Vec
,
}

impl
 TraceReader for TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    type Key = Tr::Key;
    type Val = Tr::Val;
    type Time = Tr::Time;
    type R = Tr::R;

    type Batch = Tr::Batch;
    type Cursor = Tr::Cursor;

    fn advance_by(&mut self, frontier: &[Tr::Time]) {
        self.trace.borrow_mut().adjust_advance_frontier(&self.advance[..], frontier);
        self.advance.clear();
        self.advance.extend(frontier.iter().cloned());
    }
    fn advance_frontier(&mut self) -> &[Tr::Time] {
        &self.advance[..]
    }
    fn distinguish_since(&mut self, frontier: &[Tr::Time]) {
        self.trace.borrow_mut().adjust_through_frontier(&self.through[..], frontier);
        self.through.clear();
        self.through.extend(frontier.iter().cloned());
    }
    fn distinguish_frontier(&mut self) -> &[Tr::Time] {
        &self.through[..]
    }
    fn cursor_through(&mut self, frontier: &[Tr::Time]) -> Option<(Tr::Cursor, ::Storage)> {
        self.trace.borrow_mut().trace.cursor_through(frontier)
    }
    fn map_batches<F: FnMut(&Self::Batch)>(&mut self, f: F) { self.trace.borrow_mut().trace.map_batches(f) }
}

impl
 TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Timestamp+Lattice,
{
    /// Creates a new agent from a trace reader.
    pub fn new(trace: Tr) -> (Self, TraceWriter
)
    where
        Tr: Trace,
        Tr::Batch: Batch
,
    {
        let trace = Rc::new(RefCell::new(TraceBox::new(trace)));
        let queues = Rc::new(RefCell::new(Vec::new()));

        let reader = TraceAgent {
            trace: trace.clone(),
            queues: Rc::downgrade(&queues),
            advance: trace.borrow().advance_frontiers.frontier().to_vec(),
            through: trace.borrow().through_frontiers.frontier().to_vec(),
        };

        let writer = TraceWriter::new(
            vec![Default::default()],
            Rc::downgrade(&trace),
            queues,
        );

        (reader, writer)
    }

    /// Attaches a new shared queue to the trace.
    ///
    /// The queue is first populated with existing batches from the trace,
    /// The queue will be immediately populated with existing historical batches from the trace, and until the reference
    /// is dropped the queue will receive new batches as produced by the source `arrange` operator.
    pub fn new_listener(&mut self, activator: Activator) -> TraceAgentQueueReader

    where
        Tr::Time: Default
    {
        // create a new queue for progress and batch information.
        let mut new_queue = VecDeque::new();

        // add the existing batches from the trace
        let mut upper = None;
        self.trace
            .borrow_mut()
            .trace
            .map_batches(|batch| {
                new_queue.push_back(TraceReplayInstruction::Batch(batch.clone(), Some(Default::default())));
                upper = Some(batch.upper().to_vec());
            });

        if let Some(upper) = upper {
            new_queue.push_back(TraceReplayInstruction::Frontier(upper));
        }

        let reference = Rc::new((activator, RefCell::new(new_queue)));

        // wraps the queue in a ref-counted ref cell and enqueue/return it.
        if let Some(queue) = self.queues.upgrade() {
            queue.borrow_mut().push(Rc::downgrade(&reference));
        }
        reference.0.activate();
        reference
    }
}

impl
 TraceAgent

where
    Tr: TraceReader+'static,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    /// Copies an existing collection into the supplied scope.
    ///
    /// This method creates an `Arranged` collection that should appear indistinguishable from applying `arrange`
    /// directly to the source collection brought into the local scope. The only caveat is that the initial state
    /// of the collection is its current state, and updates occur from this point forward. The historical changes
    /// the collection experienced in the past are accumulated, and the distinctions from the initial collection
    /// are no longer evident.
    ///
    /// The current behavior is that the introduced collection accumulates updates to some times less or equal
    /// to `self.advance_frontier()`. There is *not* currently a guarantee that the updates are accumulated *to*
    /// the frontier, and the resulting collection history may be weirdly partial until this point. In particular,
    /// the historical collection may move through configurations that did not actually occur, even if eventually
    /// arriving at the correct collection. This is probably a bug; although we get to the right place in the end,
    /// the intermediate computation could do something that the original computation did not, like diverge.
    ///
    /// I would expect the semantics to improve to "updates are advanced to `self.advance_frontier()`", which
    /// means the computation will run as if starting from exactly this frontier. It is not currently clear whose
    /// responsibility this should be (the trace/batch should only reveal these times, or an operator should know
    /// to advance times before using them).
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate timely;
    /// extern crate differential_dataflow;
    ///
    /// use timely::Configuration;
    /// use differential_dataflow::input::Input;
    /// use differential_dataflow::operators::arrange::ArrangeBySelf;
    /// use differential_dataflow::operators::reduce::Reduce;
    /// use differential_dataflow::trace::Trace;
    /// use differential_dataflow::trace::implementations::ord::OrdValSpine;
    /// use differential_dataflow::hashable::OrdWrapper;
    ///
    /// fn main() {
    ///     ::timely::execute(Configuration::Thread, |worker| {
    ///
    ///         // create a first dataflow
    ///         let mut trace = worker.dataflow::<u32,_,_>(|scope| {
    ///             // create input handle and collection.
    ///             scope.new_collection_from(0 .. 10).1
    ///                  .arrange_by_self()
    ///                  .trace
    ///         });
    ///
    ///         // do some work.
    ///         worker.step();
    ///         worker.step();
    ///
    ///         // create a second dataflow
    ///         worker.dataflow(move |scope| {
    ///             trace.import(scope)
    ///                  .reduce(move |_key, src, dst| dst.push((*src[0].0, 1)));
    ///         });
    ///
    ///     }).unwrap();
    /// }
    /// ```
    pub fn import<G>(&mut self, scope: &G) -> Arranged<G, TraceAgent
>
    where
        G: Scope<Timestamp=Tr::Time>,
        Tr::Time: Timestamp,
    {
        self.import_named(scope, "ArrangedSource")
    }

    /// Same as `import`, but allows to name the source.
    pub fn import_named<G>(&mut self, scope: &G, name: &str) -> Arranged<G, TraceAgent
>
    where
        G: Scope<Timestamp=Tr::Time>,
        Tr::Time: Timestamp,
    {
        // Drop ShutdownButton and return only the arrangement.
        self.import_core(scope, name).0
    }
    /// Imports an arrangement into the supplied scope.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate timely;
    /// extern crate differential_dataflow;
    ///
    /// use timely::Configuration;
    /// use timely::dataflow::ProbeHandle;
    /// use timely::dataflow::operators::Probe;
    /// use differential_dataflow::input::InputSession;
    /// use differential_dataflow::operators::arrange::ArrangeBySelf;
    /// use differential_dataflow::operators::reduce::Reduce;
    /// use differential_dataflow::trace::Trace;
    /// use differential_dataflow::trace::implementations::ord::OrdValSpine;
    /// use differential_dataflow::hashable::OrdWrapper;
    ///
    /// fn main() {
    ///     ::timely::execute(Configuration::Thread, |worker| {
    ///
    ///         let mut input = InputSession::<_,(),isize>::new();
    ///         let mut probe = ProbeHandle::new();
    ///
    ///         // create a first dataflow
    ///         let mut trace = worker.dataflow::<u32,_,_>(|scope| {
    ///             // create input handle and collection.
    ///             input.to_collection(scope)
    ///                  .arrange_by_self()
    ///                  .trace
    ///         });
    ///
    ///         // do some work.
    ///         worker.step();
    ///         worker.step();
    ///
    ///         // create a second dataflow
    ///         let mut shutdown = worker.dataflow(|scope| {
    ///             let (arrange, button) = trace.import_core(scope, "Import");
    ///             arrange.stream.probe_with(&mut probe);
    ///             button
    ///         });
    ///
    ///         worker.step();
    ///         worker.step();
    ///         assert!(!probe.done());
    ///
    ///         shutdown.press();
    ///
    ///         worker.step();
    ///         worker.step();
    ///         assert!(probe.done());
    ///
    ///     }).unwrap();
    /// }
    /// ```
    pub fn import_core<G>(&mut self, scope: &G, name: &str) -> (Arranged<G, TraceAgent
>, ShutdownButton<CapabilitySet
>)
    where
        G: Scope<Timestamp=Tr::Time>,
        Tr::Time: Timestamp,
    {
        let trace = self.clone();

        let mut shutdown_button = None;

        let stream = {

            let mut shutdown_button_ref = &mut shutdown_button;
            source(scope, name, move |capability, info| {

                let capabilities = Rc::new(RefCell::new(Some(CapabilitySet::new())));

                let activator = scope.activator_for(&info.address[..]);
                let queue = self.new_listener(activator);

                let activator = scope.activator_for(&info.address[..]);
                *shutdown_button_ref = Some(ShutdownButton::new(capabilities.clone(), activator));

                capabilities.borrow_mut().as_mut().unwrap().insert(capability);

                move |output| {

                    let mut capabilities = capabilities.borrow_mut();
                    if let Some(ref mut capabilities) = *capabilities {

                        let mut borrow = queue.1.borrow_mut();
                        for instruction in borrow.drain(..) {
                            match instruction {
                                TraceReplayInstruction::Frontier(frontier) => {
                                    capabilities.downgrade(&frontier[..]);
                                },
                                TraceReplayInstruction::Batch(batch, hint) => {
                                    if let Some(time) = hint {
                                        let delayed = capabilities.delayed(&time);
                                        output.session(&delayed).give(batch);
                                    }
                                }
                            }
                        }
                    }
                }
            })
        };

        (Arranged { stream, trace }, shutdown_button.unwrap())
    }
}

/// Wrapper than can drop shared references.
pub struct ShutdownButton<T> {
    on_drop: bool,
    reference: Rc<RefCell<Option<T>>>,
    activator: Activator,
}

impl<T> ShutdownButton<T> {
    /// Creates a new ShutdownButton.
    pub fn new(reference: Rc<RefCell<Option<T>>>, activator: Activator) -> Self {
        Self { on_drop: false, reference, activator }
    }
    /// Push the shutdown button, dropping the shared objects.
    pub fn press(&mut self) {
        *self.reference.borrow_mut() = None;
        self.activator.activate();
    }
    /// Sets the button to auto-press on drop.
    pub fn press_on_drop(&mut self) {
        self.on_drop = true;
    }
}

impl<T> Drop for ShutdownButton<T> {
    fn drop(&mut self) {
        if self.on_drop {
            self.press();
        }
    }
}

impl
 Clone for TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    fn clone(&self) -> Self {

        // increase counts for wrapped `TraceBox`.
        self.trace.borrow_mut().adjust_advance_frontier(&[], &self.advance[..]);
        self.trace.borrow_mut().adjust_through_frontier(&[], &self.through[..]);

        TraceAgent {
            trace: self.trace.clone(),
            queues: self.queues.clone(),
            advance: self.advance.clone(),
            through: self.through.clone(),
        }
    }
}

impl
 Drop for TraceAgent

where
    Tr: TraceReader,
    Tr::Time: Lattice+Ord+Clone+'static,
{
    fn drop(&mut self) {
        // decrement borrow counts to remove all holds
        self.trace.borrow_mut().adjust_advance_frontier(&self.advance[..], &[]);
        self.trace.borrow_mut().adjust_through_frontier(&self.through[..], &[]);
    }
}<|endoftext|>


<commit_before>#[cfg(test)]
mod tests;
pub mod response;

pub use message::response::*;
use notification::Notification;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::io::prelude::*;
use hyper::Client;
use hyper::header::{Authorization, ContentType};
use hyper::status::StatusCode;
use rustc_serialize::json::{self, Json, ToJson};

#[derive(PartialEq, Debug, Clone)]
pub enum Priority {
    Normal, High
}

/// Represents a FCM message. Construct the FCM message
/// using various utility methods and finally send it.
/// # Examples:
/// ```rust
/// use fcm::Message;
///
/// let message = Message::new("<registration id>").dry_run(true);
/// ```
pub struct Message<'a> {
    to: &'a str,
    registration_ids: Option<Vec<String>>,
    collapse_key: Option<&'a str>,
    priority: Option<Priority>,
    content_available: Option<bool>,
    delay_while_idle: Option<bool>,
    time_to_live: Option<i32>,
    restricted_package_name: Option<&'a str>,
    dry_run: Option<bool>,
    data: Option<HashMap<String, String>>,
    notification: Option<Notification<'a>>,
}

impl <'a> ToJson for Message<'a> {
    fn to_json(&self) -> Json {
        let mut root = BTreeMap::new();

        root.insert("to".to_string(), self.to.to_json());

        if self.registration_ids.is_some() {
            root.insert("registration_ids".to_string(),
                    self.registration_ids.clone().unwrap().to_json());
        }

        if self.collapse_key.is_some() {
            root.insert("collapse_key".to_string(), self.collapse_key.clone().unwrap().to_json());
        }

        if self.priority.is_some() {
            root.insert("priority".to_string(), match self.priority.clone().unwrap() {
                Priority::Normal => Json::String("normal".to_string()),
                Priority::High => Json::String("high".to_string()),
            });
        }

        if self.content_available.is_some() {
            root.insert("content_available".to_string(), self.content_available.unwrap().to_json());
        }

        if self.delay_while_idle.is_some() {
            root.insert("delay_while_idle".to_string(), self.delay_while_idle.unwrap().to_json());
        }

        if self.time_to_live.is_some() {
            root.insert("time_to_live".to_string(), self.time_to_live.unwrap().to_json());
        }

        if self.restricted_package_name.is_some() {
            root.insert("restricted_package_name".to_string(), self.restricted_package_name.clone().unwrap().to_json());
        }

        if self.dry_run.is_some() {
            root.insert("dry_run".to_string(), self.dry_run.unwrap().to_json());
        }

        if self.data.is_some() {
            root.insert("data".to_string(), self.data.clone().unwrap().to_json());
        }

        if self.notification.is_some() {
            root.insert("notification".to_string(), self.notification.clone().unwrap().to_json());
        }

        Json::Object(root)
    }
}

impl <'a> Message<'a> {
    /// Get a new instance of Message. You need to supply either
    /// a registration id, or a topic (/topic/...).
    pub fn new(to: &'a str) -> Message {
        Message {
            to: to,
            registration_ids: None,
            collapse_key: None,
            priority: None,
            content_available: None,
            delay_while_idle: None,
            time_to_live: None,
            restricted_package_name: None,
            dry_run: None,
            data: None,
            notification: None,
        }
    }

    /// Set various registration ids to which the message ought to be sent.
    pub fn registration_ids(mut self, ids: Vec<&'a str>) -> Message<'a> {
        self.registration_ids = Some(ids.iter().map(|s| s.to_string()).collect());
        self
    }

    /// Set this parameter to identify groups of messages that can be collapsed.
    pub fn collapse_key(mut self, collapse_key: &'a str) -> Message<'a> {
        self.collapse_key = Some(collapse_key);
        self
    }

    /// Set the priority of the message. You can set Normal or High priorities.
    /// # Examples:
    /// ```rust
    /// use fcm::{Message, Priority};
    ///
    /// let message = Message::new("<registration id>")
    ///     .priority(Priority::High);
    /// ```
    pub fn priority(mut self, priority: Priority) -> Message<'a> {
        self.priority = Some(priority);
        self
    }

    /// To set the `content-available` field on iOS
    pub fn content_available(mut self, content_available: bool) -> Message<'a> {
        self.content_available = Some(content_available);
        self
    }

    /// When set to `true`, sends the message only when the device is active.
    pub fn delay_while_idle(mut self, delay_while_idle: bool) -> Message<'a> {
        self.delay_while_idle = Some(delay_while_idle);
        self
    }

    /// How long (in seconds) to keep the message on FCM servers in case the device
    /// is offline. The maximum and default is 4 weeks.
    pub fn time_to_live(mut self, time_to_live: i32) -> Message<'a> {
        self.time_to_live = Some(time_to_live);
        self
    }

    /// Package name of the application where the registration tokens must match.
    pub fn restricted_package_name(mut self, restricted_package_name: &'a str) -> Message<'a> {
        self.restricted_package_name = Some(restricted_package_name);
        self
    }

    /// When set to `true`, allows you to test FCM without actually sending the message.
    pub fn dry_run(mut self, dry_run: bool) -> Message<'a> {
        self.dry_run = Some(dry_run);
        self
    }

    /// Use this to add custom key-value pairs to the message. This data
    /// must be handled appropriately on the client end.
    /// # Examples:
    /// ```rust
    /// use fcm::Message;
    /// use std::collections::HashMap;
    ///
    /// let mut map = HashMap::new();
    /// map.insert("message", "Howdy!");
    ///
    /// let message = Message::new("<registration id>").data(map);
    /// ```
    pub fn data(mut self, data: HashMap<&'a str, &'a str>) -> Message<'a> {
        let mut datamap: HashMap<String, String> = HashMap::new();
        for (key, val) in data.iter() {
            datamap.insert(key.to_string(), val.to_string());
        }

        self.data = Some(datamap);
        self
    }

    /// Use this to set a `Notification` for the message.
    /// # Examples:
    /// ```rust
    /// use fcm::{Message, NotificationBuilder};
    ///
    /// let notification = NotificationBuilder::new("Hey!")
    ///     .body("Do you want to catch up later?")
    ///     .finalize();
    ///
    /// let message = Message::new("<registration id>")
    ///     .notification(notification);
    /// ```
    pub fn notification(mut self, notification: Notification<'a>) -> Message<'a> {
        self.notification = Some(notification);
        self
    }

    /// Send the message using your FCM API Key.
    /// # Examples:
    /// ```no_run
    /// use fcm::Message;
    /// use std::collections::HashMap;
    ///
    /// let mut map = HashMap::new();
    /// map.insert("message", "Howdy!");
    ///
    /// let result = Message::new("<registration id>")
    ///     .data(map)
    ///     .send("<FCM API Key>");
    /// ```
    pub fn send(self, api_key: &'a str) -> Result<response::FcmResponse, response::FcmError> {
        let payload = self.to_json().to_string();
        let auth_header = "key=".to_string() + api_key;
        let client = Client::new();

        let response = client
            .post("https://fcm.googleapis.com/fcm/send")
            .body(&payload)
            .header(Authorization(auth_header))
            .header(ContentType::json())
            .send();

        match response {
            Ok(mut response) => {
                let mut body = String::new();
                response.read_to_string(&mut body).unwrap();

                Message::parse_response(response.status, &body)
            },
            Err(_) => {
                Message::parse_response(StatusCode::InternalServerError, "Server Error")
            }
        }
    }

    fn parse_response(status: StatusCode, body: &str) -> Result<response::FcmResponse, response::FcmError> {
        use hyper::status::StatusCode::*;
        use hyper::status::StatusClass::ServerError;
        match status {
            Ok => Result::Ok(json::decode(body).unwrap()),
            Unauthorized => Err(response::FcmError::Unauthorized),
            BadRequest => Err(response::FcmError::InvalidMessage(body.to_string())),
            _ => match status.class() {
                ServerError => Err(response::FcmError::ServerError),
                _ => Err(response::FcmError::InvalidMessage("Unknown Error".to_string())),
            }
        }
    }
}
<commit_msg>Refactor parse_response<commit_after>#[cfg(test)]
mod tests;
pub mod response;

pub use message::response::*;
use notification::Notification;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::io::prelude::*;
use hyper::Client;
use hyper::header::{Authorization, ContentType};
use hyper::status::StatusCode;
use rustc_serialize::json::{self, Json, ToJson};

#[derive(PartialEq, Debug, Clone)]
pub enum Priority {
    Normal, High
}

/// Represents a FCM message. Construct the FCM message
/// using various utility methods and finally send it.
/// # Examples:
/// ```rust
/// use fcm::Message;
///
/// let message = Message::new("<registration id>").dry_run(true);
/// ```
pub struct Message<'a> {
    to: &'a str,
    registration_ids: Option<Vec<String>>,
    collapse_key: Option<&'a str>,
    priority: Option<Priority>,
    content_available: Option<bool>,
    delay_while_idle: Option<bool>,
    time_to_live: Option<i32>,
    restricted_package_name: Option<&'a str>,
    dry_run: Option<bool>,
    data: Option<HashMap<String, String>>,
    notification: Option<Notification<'a>>,
}

impl <'a> ToJson for Message<'a> {
    fn to_json(&self) -> Json {
        let mut root = BTreeMap::new();

        root.insert("to".to_string(), self.to.to_json());

        if self.registration_ids.is_some() {
            root.insert("registration_ids".to_string(),
                    self.registration_ids.clone().unwrap().to_json());
        }

        if self.collapse_key.is_some() {
            root.insert("collapse_key".to_string(), self.collapse_key.clone().unwrap().to_json());
        }

        if self.priority.is_some() {
            root.insert("priority".to_string(), match self.priority.clone().unwrap() {
                Priority::Normal => Json::String("normal".to_string()),
                Priority::High => Json::String("high".to_string()),
            });
        }

        if self.content_available.is_some() {
            root.insert("content_available".to_string(), self.content_available.unwrap().to_json());
        }

        if self.delay_while_idle.is_some() {
            root.insert("delay_while_idle".to_string(), self.delay_while_idle.unwrap().to_json());
        }

        if self.time_to_live.is_some() {
            root.insert("time_to_live".to_string(), self.time_to_live.unwrap().to_json());
        }

        if self.restricted_package_name.is_some() {
            root.insert("restricted_package_name".to_string(), self.restricted_package_name.clone().unwrap().to_json());
        }

        if self.dry_run.is_some() {
            root.insert("dry_run".to_string(), self.dry_run.unwrap().to_json());
        }

        if self.data.is_some() {
            root.insert("data".to_string(), self.data.clone().unwrap().to_json());
        }

        if self.notification.is_some() {
            root.insert("notification".to_string(), self.notification.clone().unwrap().to_json());
        }

        Json::Object(root)
    }
}

impl <'a> Message<'a> {
    /// Get a new instance of Message. You need to supply either
    /// a registration id, or a topic (/topic/...).
    pub fn new(to: &'a str) -> Message {
        Message {
            to: to,
            registration_ids: None,
            collapse_key: None,
            priority: None,
            content_available: None,
            delay_while_idle: None,
            time_to_live: None,
            restricted_package_name: None,
            dry_run: None,
            data: None,
            notification: None,
        }
    }

    /// Set various registration ids to which the message ought to be sent.
    pub fn registration_ids(mut self, ids: Vec<&'a str>) -> Message<'a> {
        self.registration_ids = Some(ids.iter().map(|s| s.to_string()).collect());
        self
    }

    /// Set this parameter to identify groups of messages that can be collapsed.
    pub fn collapse_key(mut self, collapse_key: &'a str) -> Message<'a> {
        self.collapse_key = Some(collapse_key);
        self
    }

    /// Set the priority of the message. You can set Normal or High priorities.
    /// # Examples:
    /// ```rust
    /// use fcm::{Message, Priority};
    ///
    /// let message = Message::new("<registration id>")
    ///     .priority(Priority::High);
    /// ```
    pub fn priority(mut self, priority: Priority) -> Message<'a> {
        self.priority = Some(priority);
        self
    }

    /// To set the `content-available` field on iOS
    pub fn content_available(mut self, content_available: bool) -> Message<'a> {
        self.content_available = Some(content_available);
        self
    }

    /// When set to `true`, sends the message only when the device is active.
    pub fn delay_while_idle(mut self, delay_while_idle: bool) -> Message<'a> {
        self.delay_while_idle = Some(delay_while_idle);
        self
    }

    /// How long (in seconds) to keep the message on FCM servers in case the device
    /// is offline. The maximum and default is 4 weeks.
    pub fn time_to_live(mut self, time_to_live: i32) -> Message<'a> {
        self.time_to_live = Some(time_to_live);
        self
    }

    /// Package name of the application where the registration tokens must match.
    pub fn restricted_package_name(mut self, restricted_package_name: &'a str) -> Message<'a> {
        self.restricted_package_name = Some(restricted_package_name);
        self
    }

    /// When set to `true`, allows you to test FCM without actually sending the message.
    pub fn dry_run(mut self, dry_run: bool) -> Message<'a> {
        self.dry_run = Some(dry_run);
        self
    }

    /// Use this to add custom key-value pairs to the message. This data
    /// must be handled appropriately on the client end.
    /// # Examples:
    /// ```rust
    /// use fcm::Message;
    /// use std::collections::HashMap;
    ///
    /// let mut map = HashMap::new();
    /// map.insert("message", "Howdy!");
    ///
    /// let message = Message::new("<registration id>").data(map);
    /// ```
    pub fn data(mut self, data: HashMap<&'a str, &'a str>) -> Message<'a> {
        let mut datamap: HashMap<String, String> = HashMap::new();
        for (key, val) in data.iter() {
            datamap.insert(key.to_string(), val.to_string());
        }

        self.data = Some(datamap);
        self
    }

    /// Use this to set a `Notification` for the message.
    /// # Examples:
    /// ```rust
    /// use fcm::{Message, NotificationBuilder};
    ///
    /// let notification = NotificationBuilder::new("Hey!")
    ///     .body("Do you want to catch up later?")
    ///     .finalize();
    ///
    /// let message = Message::new("<registration id>")
    ///     .notification(notification);
    /// ```
    pub fn notification(mut self, notification: Notification<'a>) -> Message<'a> {
        self.notification = Some(notification);
        self
    }

    /// Send the message using your FCM API Key.
    /// # Examples:
    /// ```no_run
    /// use fcm::Message;
    /// use std::collections::HashMap;
    ///
    /// let mut map = HashMap::new();
    /// map.insert("message", "Howdy!");
    ///
    /// let result = Message::new("<registration id>")
    ///     .data(map)
    ///     .send("<FCM API Key>");
    /// ```
    pub fn send(self, api_key: &'a str) -> Result<response::FcmResponse, response::FcmError> {
        let payload = self.to_json().to_string();
        let auth_header = "key=".to_string() + api_key;
        let client = Client::new();

        let response = client
            .post("https://fcm.googleapis.com/fcm/send")
            .body(&payload)
            .header(Authorization(auth_header))
            .header(ContentType::json())
            .send();

        match response {
            Ok(mut response) => {
                let mut body = String::new();
                response.read_to_string(&mut body).unwrap();

                Message::parse_response(response.status, &body)
            },
            Err(_) => {
                Message::parse_response(StatusCode::InternalServerError, "Server Error")
            }
        }
    }

    fn parse_response(status: StatusCode, body: &str) -> Result<response::FcmResponse, response::FcmError> {
        use hyper::status::StatusCode::*;
        use hyper::status::StatusClass::ServerError;
        match status {
            Ok =>
                Result::Ok(json::decode(body).unwrap()),
            Unauthorized =>
                Err(response::FcmError::Unauthorized),
            BadRequest =>
                Err(response::FcmError::InvalidMessage(body.to_string())),
            status if status.is_server_error() =>
                Err(response::FcmError::ServerError),
            _ =>
                Err(response::FcmError::InvalidMessage("Unknown Error".to_string())),
        }
    }
}
<|endoftext|>


<commit_before>use serde::de::Error as DeError;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use super::*;

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

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

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

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

    Ok(emojis)
}

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

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

    Ok(map)
}

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

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

        members.insert(user_id, member);
    }

    Ok(members)
}

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

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

    Ok(presences)
}

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

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

        private_channels.insert(id, private_channel);
    }

    Ok(private_channels)
}

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

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

    Ok(roles)
}

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

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

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

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

    Ok(users)
}

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

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

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

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

    Ok(voice_states)
}

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

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

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

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

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

    permissions.remove(perms);

    Ok(permissions.is_empty())
}

pub struct U16Visitor;

impl<'de> Visitor<'de> for U16Visitor {
    type Value = u16;

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

    fn visit_str<E: DeError>(self, v: &str) -> StdResult<Self::Value, E> {
        match v.parse::<u16>() {
            Ok(v) => Ok(v),
            Err(_) => {
                let mut s = String::new();
                s.push_str("Unknown ");
                s.push_str(stringify!($name));
                s.push_str(" value: ");
                s.push_str(v);

                Err(DeError::custom(s))
            },
        }
    }

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

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

pub struct U64Visitor;

impl<'de> Visitor<'de> for U64Visitor {
    type Value = u64;

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

    fn visit_str<E: DeError>(self, v: &str) -> StdResult<Self::Value, E> {
        match v.parse::<u64>() {
            Ok(v) => Ok(v),
            Err(_) => {
                let mut s = String::new();
                s.push_str("Unknown ");
                s.push_str(stringify!($name));
                s.push_str(" value: ");
                s.push_str(v);

                Err(DeError::custom(s))
            },
        }
    }

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

    fn visit_u64<E: DeError>(self, v: u64) -> StdResult<Self::Value, E> { Ok(v) }
}
<commit_msg>Fix remaining deserializers<commit_after>use serde::de::Error as DeError;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use super::*;

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

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

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

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

    Ok(emojis)
}

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

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

    Ok(map)
}

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

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

        members.insert(user_id, member);
    }

    Ok(members)
}

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

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

    Ok(presences)
}

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

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

        private_channels.insert(id, private_channel);
    }

    Ok(private_channels)
}

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

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

    Ok(roles)
}

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

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

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

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

    Ok(users)
}

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

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

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

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

    Ok(voice_states)
}

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

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

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

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

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

    permissions.remove(perms);

    Ok(permissions.is_empty())
}

pub struct U16Visitor;

impl<'de> Visitor<'de> for U16Visitor {
    type Value = u16;

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

    fn visit_str<E: DeError>(self, v: &str) -> StdResult<Self::Value, E> {
        match v.parse::<u16>() {
            Ok(v) => Ok(v),
            Err(_) => {
                let mut s = String::new();
                s.push_str("Unknown ");
                s.push_str(stringify!($name));
                s.push_str(" value: ");
                s.push_str(v);

                Err(DeError::custom(s))
            },
        }
    }

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

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

pub struct U64Visitor;

impl<'de> Visitor<'de> for U64Visitor {
    type Value = u64;

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

    fn visit_str<E: DeError>(self, v: &str) -> StdResult<Self::Value, E> {
        match v.parse::<u64>() {
            Ok(v) => Ok(v),
            Err(_) => {
                let mut s = String::new();
                s.push_str("Unknown ");
                s.push_str(stringify!($name));
                s.push_str(" value: ");
                s.push_str(v);

                Err(DeError::custom(s))
            },
        }
    }

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

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


<commit_before>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous code:
//!
//! - [Futures](::Future) (sometimes called promises), which represent a single
//! asychronous computation that may result in a final value or an error.
//!
//! - [Streams](::Stream), which represent a series of values or errors produced asynchronously.
//!
//! - [Sinks](::Sink), which support asynchronous writing of data.
//!
//! - [Executors](::executor), which are responsible for running asynchronous tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](::io) and
//! [cross-task communication](::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![no_std]
#![doc(html_root_url = "https://docs.rs/futures/0.2.0-beta")]

#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]

extern crate futures_core;
extern crate futures_channel;
extern crate futures_executor;
extern crate futures_io;
extern crate futures_sink;
extern crate futures_stable;
extern crate futures_util;

pub use futures_core::future::{Future, IntoFuture};
pub use futures_util::future::FutureExt;
pub use futures_core::stream::Stream;
pub use futures_util::stream::StreamExt;
pub use futures_sink::Sink;
pub use futures_util::sink::SinkExt;

// Macros redefined here because macro re-exports are unstable.

/// A macro for extracting the successful type of a `Poll<T, E>`.
///
/// This macro bakes in propagation of both errors and `Pending` signals by
/// returning early.
#[macro_export]
macro_rules! try_ready {
    ($e:expr) => (match $e {
        Ok($crate::prelude::Async::Ready(t)) => t,
        Ok($crate::prelude::Async::Pending) => return Ok($crate::prelude::Async::Pending),
        Err(e) => return Err(From::from(e)),
    })
}

/// A macro to create a `static` of type `LocalKey`.
///
/// This macro is intentionally similar to the `thread_local!`, and creates a
/// `static` which has a `get_mut` method to access the data on a task.
///
/// The data associated with each task local is per-task, so different tasks
/// will contain different values.
#[macro_export]
macro_rules! task_local {
    (static $NAME:ident: $t:ty = $e:expr) => (
        static $NAME: $crate::task::LocalKey<$t> = {
            fn __init() -> $t { $e }
            fn __key() -> ::std::any::TypeId {
                struct __A;
                ::std::any::TypeId::of::<__A>()
            }
            $crate::task::LocalKey {
                __init: __init,
                __key: __key,
            }
        };
    )
}

pub use futures_core::{Async, Poll, Never};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](::channel::oneshot), a way of sending a single value from
    //! one task to another.
    //!
    //! - [mpsc](::channel::mpsc), a multi-producer, single-consumer channel for
    //! sending values between tasks, analogous to the similarly-named structure
    //! in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](::executor::ThreadPool). A small set of worker threads can handle
    //! a very large set of spawned tasks (which are much lighter weight than
    //! threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](::executor::ThreadPool::run) an initial task on it, which can
    //! then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app: Box<Future<Item = (), Error = ()>> = Box::new(lazy(|_| Ok(())));
    //!
    //! // assumping `my_app: Future`
    //! ThreadPool::new().run(my_app);
    //! ```
    //!
    //! The call to [`run`](::executor::ThreadPool::run) will block the current
    //! thread until the future defined by `my_app` completes, and will return
    //! the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! There are two ways to spawn a task:
    //!
    //! - Spawn onto a "default" execuctor by calling the top-level
    //! [`spawn`](::executor::spawn) function or [pulling the executor from the
    //! task context](::task::Context::executor).
    //!
    //! - Spawn onto a specific executor by calling its
    //! [`spawn`](::executor::Executor::spawn) method directly.
    //!
    //! Every task always has an associated default executor, which is usually
    //! the executor on which the task is running.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](::executor::LocalPool) executor. Aside from cutting down
    //! on synchronization costs, this executor also makes it possible to
    //! execute non-`Send` tasks, via
    //! [`spawn_local`](::executor::LocalExecutor::spawn_local). The `LocalPool`
    //! is best suited for running I/O-bound tasks that do relatively little
    //! work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](::executor::block_on), for simply running a future to
    //! completion on the current thread. However, any tasks spawned by the
    //! future will *also* be run on the current thread (via `LocalPool`), and
    //! will be dropped when the primary future completes.
    // TODO: add docs (or link to apr) for implementing an executor

    pub use futures_executor::{
        Enter, EnterError, LocalExecutor, LocalPool, Spawn, SpawnWithHandle, ThreadPool,
        ThreadPoolBuilder, JoinHandle, block_on, enter, spawn, spawn_with_handle
    };
    pub use futures_core::executor::{SpawnError, Executor};
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](::Future).
    //!
    //! - The [`FutureExt`](::future::FutureExt) trait, which provides adapters
    //! for chaining and composing futures.
    //!
    //! - Top-level future combinators like [`lazy`](::future::lazy) which
    //! creates a future from a closure that defines its return value, and
    //! [`result`](::future::result), which constructs a future with an
    //! immediate defined value.

    pub use futures_core::future::{
        FutureOption, FutureResult, Future, IntoFuture, err, ok, result
    };
    pub use futures_util::future::{
        AndThen, Empty, Flatten, FlattenStream, ErrInto, Fuse,
        Inspect, IntoStream, Join, Join3, Join4, Join5, Lazy, LoopFn,
        Map, MapErr, OrElse, PollFn, Select, Then, Either, Loop, FutureExt, empty,
        lazy, loop_fn, poll_fn
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        CatchUnwind, JoinAll, SelectAll, SelectOk, Shared, SharedError, SharedItem,
        join_all, select_all, select_ok
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](::io::AsyncRead) and
    //! [`AsyncWrite`](::io::AsyncWrite), which mirror the `Read` and `Write`
    //! traits of the standard library. However, these traits integrate with the
    //! asynchronous task system, so that if an I/O object isn't ready for
    //! reading (or writing), the thread is not blocked, and instead the current
    //! task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](::io::AsyncWriteExt) extension traits offer a variety
    //! of useful combinators for operating with asynchronous I/O objects,
    //! including ways to work with them using futures, streams and sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

#[cfg(feature = "std")]
pub mod never {
    //! This module contains the `Never` type.
    //!
    //! Values of this type can never be created and will never exist.
    pub use futures_core::never::*;
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the standard
    //! library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use futures_core::{
        Future,
        IntoFuture,
        Stream,
        Async,
        Poll,
        Never,
        task,
    };

    #[cfg(feature = "std")]
    pub use futures_core::executor::Executor;

    pub use futures_sink::Sink;

    #[cfg(feature = "std")]
    pub use futures_io::{
        AsyncRead,
        AsyncWrite,
    };

    pub use futures_util::{
        FutureExt,
        StreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](::Sink), which allows you to asynchronously write data.
    //!
    //! - The [`SinkExt`](::sink::SinkExt) trait, which provides adapters
    //! for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Fanout, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        WithFlatMap, SinkExt, close, flush,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](::Stream), for objects that can asynchronously
    //! produce a sequence of values.
    //!
    //! - The [`StreamExt`](::future::StreamExt) trait, which provides adapters
    //! for chaining and composing streams.
    //!
    //! - Top-level stream contructors like [`iter_ok`](::stream::iter_ok) which
    //! creates a stream from an iterator, and
    //! [`futures_unordered`](::stream::futures_unordered()), which constructs a
    //! stream from a collection of futures.

    pub use futures_core::stream::Stream;

    pub use futures_util::stream::{
        AndThen, Chain, Concat, Empty, Filter, FilterMap, Flatten, Fold,
        ForEach, Forward, ErrInto, Fuse, Inspect, InspectErr, IterOk,
        IterResult, Map, MapErr, Once, OrElse, Peekable, PollFn, Repeat, Select,
        Skip, SkipWhile, StreamFuture, Take, TakeWhile, Then, Unfold, Zip,
        StreamExt, empty, iter_ok, iter_result, once, poll_fn, repeat, unfold,
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_unordered, BufferUnordered, Buffered, CatchUnwind, Chunks, Collect,
        FuturesUnordered, FuturesOrdered, ReuniteError, SelectAll, SplitSink, SplitStream,
        futures_ordered,
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Context`](::task::Context), which provides contextual data present
    //! for every task, including a handle for waking up the task.
    //!
    //! - [`Waker`](::task::Waker), a handle for waking up a task.
    //!
    //! - [`LocalKey`](::task::LocalKey), a key for task-local data; you should
    //! use the [`task_local` macro](../macro.task_local.html) to set up such keys.
    //!
    //! Tasks themselves are generally created by spawning a future onto [an
    //! executor](::executor). However, you can manually construct a task by
    //! creating your own `Context` instance, and polling a future with it.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Context, LocalMap, Waker, UnsafeWake,
    };

    #[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
    pub use futures_core::task::AtomicWaker;

    #[cfg(feature = "std")]
    pub use futures_core::task::{LocalKey, Wake};
}

#[cfg(feature = "nightly")]
pub mod stable {
    pub use futures_stable::{StableFuture, StableStream};

    #[cfg(feature = "std")]
    pub use futures_stable::{StableExecutor, block_on_stable};
}
<commit_msg>add select_all to futures facade (followup of #852)<commit_after>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous code:
//!
//! - [Futures](::Future) (sometimes called promises), which represent a single
//! asychronous computation that may result in a final value or an error.
//!
//! - [Streams](::Stream), which represent a series of values or errors produced asynchronously.
//!
//! - [Sinks](::Sink), which support asynchronous writing of data.
//!
//! - [Executors](::executor), which are responsible for running asynchronous tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](::io) and
//! [cross-task communication](::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![no_std]
#![doc(html_root_url = "https://docs.rs/futures/0.2.0-beta")]

#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]

extern crate futures_core;
extern crate futures_channel;
extern crate futures_executor;
extern crate futures_io;
extern crate futures_sink;
extern crate futures_stable;
extern crate futures_util;

pub use futures_core::future::{Future, IntoFuture};
pub use futures_util::future::FutureExt;
pub use futures_core::stream::Stream;
pub use futures_util::stream::StreamExt;
pub use futures_sink::Sink;
pub use futures_util::sink::SinkExt;

// Macros redefined here because macro re-exports are unstable.

/// A macro for extracting the successful type of a `Poll<T, E>`.
///
/// This macro bakes in propagation of both errors and `Pending` signals by
/// returning early.
#[macro_export]
macro_rules! try_ready {
    ($e:expr) => (match $e {
        Ok($crate::prelude::Async::Ready(t)) => t,
        Ok($crate::prelude::Async::Pending) => return Ok($crate::prelude::Async::Pending),
        Err(e) => return Err(From::from(e)),
    })
}

/// A macro to create a `static` of type `LocalKey`.
///
/// This macro is intentionally similar to the `thread_local!`, and creates a
/// `static` which has a `get_mut` method to access the data on a task.
///
/// The data associated with each task local is per-task, so different tasks
/// will contain different values.
#[macro_export]
macro_rules! task_local {
    (static $NAME:ident: $t:ty = $e:expr) => (
        static $NAME: $crate::task::LocalKey<$t> = {
            fn __init() -> $t { $e }
            fn __key() -> ::std::any::TypeId {
                struct __A;
                ::std::any::TypeId::of::<__A>()
            }
            $crate::task::LocalKey {
                __init: __init,
                __key: __key,
            }
        };
    )
}

pub use futures_core::{Async, Poll, Never};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](::channel::oneshot), a way of sending a single value from
    //! one task to another.
    //!
    //! - [mpsc](::channel::mpsc), a multi-producer, single-consumer channel for
    //! sending values between tasks, analogous to the similarly-named structure
    //! in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](::executor::ThreadPool). A small set of worker threads can handle
    //! a very large set of spawned tasks (which are much lighter weight than
    //! threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](::executor::ThreadPool::run) an initial task on it, which can
    //! then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app: Box<Future<Item = (), Error = ()>> = Box::new(lazy(|_| Ok(())));
    //!
    //! // assumping `my_app: Future`
    //! ThreadPool::new().run(my_app);
    //! ```
    //!
    //! The call to [`run`](::executor::ThreadPool::run) will block the current
    //! thread until the future defined by `my_app` completes, and will return
    //! the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! There are two ways to spawn a task:
    //!
    //! - Spawn onto a "default" execuctor by calling the top-level
    //! [`spawn`](::executor::spawn) function or [pulling the executor from the
    //! task context](::task::Context::executor).
    //!
    //! - Spawn onto a specific executor by calling its
    //! [`spawn`](::executor::Executor::spawn) method directly.
    //!
    //! Every task always has an associated default executor, which is usually
    //! the executor on which the task is running.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](::executor::LocalPool) executor. Aside from cutting down
    //! on synchronization costs, this executor also makes it possible to
    //! execute non-`Send` tasks, via
    //! [`spawn_local`](::executor::LocalExecutor::spawn_local). The `LocalPool`
    //! is best suited for running I/O-bound tasks that do relatively little
    //! work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](::executor::block_on), for simply running a future to
    //! completion on the current thread. However, any tasks spawned by the
    //! future will *also* be run on the current thread (via `LocalPool`), and
    //! will be dropped when the primary future completes.
    // TODO: add docs (or link to apr) for implementing an executor

    pub use futures_executor::{
        Enter, EnterError, LocalExecutor, LocalPool, Spawn, SpawnWithHandle, ThreadPool,
        ThreadPoolBuilder, JoinHandle, block_on, enter, spawn, spawn_with_handle
    };
    pub use futures_core::executor::{SpawnError, Executor};
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](::Future).
    //!
    //! - The [`FutureExt`](::future::FutureExt) trait, which provides adapters
    //! for chaining and composing futures.
    //!
    //! - Top-level future combinators like [`lazy`](::future::lazy) which
    //! creates a future from a closure that defines its return value, and
    //! [`result`](::future::result), which constructs a future with an
    //! immediate defined value.

    pub use futures_core::future::{
        FutureOption, FutureResult, Future, IntoFuture, err, ok, result
    };
    pub use futures_util::future::{
        AndThen, Empty, Flatten, FlattenStream, ErrInto, Fuse,
        Inspect, IntoStream, Join, Join3, Join4, Join5, Lazy, LoopFn,
        Map, MapErr, OrElse, PollFn, Select, Then, Either, Loop, FutureExt, empty,
        lazy, loop_fn, poll_fn
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        CatchUnwind, JoinAll, SelectAll, SelectOk, Shared, SharedError, SharedItem,
        join_all, select_all, select_ok
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](::io::AsyncRead) and
    //! [`AsyncWrite`](::io::AsyncWrite), which mirror the `Read` and `Write`
    //! traits of the standard library. However, these traits integrate with the
    //! asynchronous task system, so that if an I/O object isn't ready for
    //! reading (or writing), the thread is not blocked, and instead the current
    //! task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](::io::AsyncWriteExt) extension traits offer a variety
    //! of useful combinators for operating with asynchronous I/O objects,
    //! including ways to work with them using futures, streams and sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

#[cfg(feature = "std")]
pub mod never {
    //! This module contains the `Never` type.
    //!
    //! Values of this type can never be created and will never exist.
    pub use futures_core::never::*;
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the standard
    //! library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use futures_core::{
        Future,
        IntoFuture,
        Stream,
        Async,
        Poll,
        Never,
        task,
    };

    #[cfg(feature = "std")]
    pub use futures_core::executor::Executor;

    pub use futures_sink::Sink;

    #[cfg(feature = "std")]
    pub use futures_io::{
        AsyncRead,
        AsyncWrite,
    };

    pub use futures_util::{
        FutureExt,
        StreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](::Sink), which allows you to asynchronously write data.
    //!
    //! - The [`SinkExt`](::sink::SinkExt) trait, which provides adapters
    //! for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Fanout, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        WithFlatMap, SinkExt, close, flush,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](::Stream), for objects that can asynchronously
    //! produce a sequence of values.
    //!
    //! - The [`StreamExt`](::future::StreamExt) trait, which provides adapters
    //! for chaining and composing streams.
    //!
    //! - Top-level stream contructors like [`iter_ok`](::stream::iter_ok) which
    //! creates a stream from an iterator, and
    //! [`futures_unordered`](::stream::futures_unordered()), which constructs a
    //! stream from a collection of futures.

    pub use futures_core::stream::Stream;

    pub use futures_util::stream::{
        AndThen, Chain, Concat, Empty, Filter, FilterMap, Flatten, Fold,
        ForEach, Forward, ErrInto, Fuse, Inspect, InspectErr, IterOk,
        IterResult, Map, MapErr, Once, OrElse, Peekable, PollFn, Repeat, Select,
        Skip, SkipWhile, StreamFuture, Take, TakeWhile, Then, Unfold, Zip,
        StreamExt, empty, iter_ok, iter_result, once, poll_fn, repeat, unfold,
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_unordered, select_all, BufferUnordered, Buffered, CatchUnwind, Chunks, Collect,
        FuturesUnordered, FuturesOrdered, ReuniteError, SelectAll, SplitSink, SplitStream,
        futures_ordered,
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Context`](::task::Context), which provides contextual data present
    //! for every task, including a handle for waking up the task.
    //!
    //! - [`Waker`](::task::Waker), a handle for waking up a task.
    //!
    //! - [`LocalKey`](::task::LocalKey), a key for task-local data; you should
    //! use the [`task_local` macro](../macro.task_local.html) to set up such keys.
    //!
    //! Tasks themselves are generally created by spawning a future onto [an
    //! executor](::executor). However, you can manually construct a task by
    //! creating your own `Context` instance, and polling a future with it.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Context, LocalMap, Waker, UnsafeWake,
    };

    #[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
    pub use futures_core::task::AtomicWaker;

    #[cfg(feature = "std")]
    pub use futures_core::task::{LocalKey, Wake};
}

#[cfg(feature = "nightly")]
pub mod stable {
    pub use futures_stable::{StableFuture, StableStream};

    #[cfg(feature = "std")]
    pub use futures_stable::{StableExecutor, block_on_stable};
}
<|endoftext|>


<commit_before>/*pub fn max_size_slices(slices: Vec<i32>) -> i32 {
    use std::iter::FromIterator;

    if slices.len() == 3 {
        return *slices.iter().max().unwrap();
    }
    let mut result = 0;
    for (ind, &ele) in slices.iter().enumerate() {
        if ele > result {
            result = ele;
        }

        let (start, end);
        let new_slices = if ind == 0 {
            start = 2;
            end = slices.len() - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else if ind == slices.len() - 1 {
            start = 1;
            end = slices.len() - 1 - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else {
            let mut cache = Vec::from_iter(slices[ind + 2..].iter().cloned());
            cache.append(&mut Vec::from_iter(slices[0..ind - 1].iter().cloned()));
            cache
        };

        if new_slices.len() != 0 {
            let cache = ele + max_size_slices(new_slices);
            if cache > result {
                result = cache
            }
        } else {
            if ele > result {
                result = ele
            }
        }
    }
    result
}*/

/*pub fn max_size_slices(slices: Vec<i32>) -> i32 {
    max_inner(&slices, slices.len() / 3)
}

pub fn max_inner(slices: &Vec<i32>, left: usize) -> i32 {
    use std::iter::FromIterator;

    if left == 0 {
        return 0;
    }
    if slices.len() == 3 {
        return *slices.iter().max().unwrap();
    }
    let mut result = 0;
    for (ind, &ele) in slices.iter().enumerate() {
        if ele > result {
            result = ele;
        }

        let (start, end);
        let new_slices = if ind == 0 {
            start = 2;
            end = slices.len() - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else if ind == slices.len() - 1 {
            start = 1;
            end = slices.len() - 1 - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else {
            let mut cache = Vec::from_iter(slices[ind + 2..].iter().cloned());
            cache.append(&mut Vec::from_iter(slices[0..ind - 1].iter().cloned()));
            cache
        };

        if new_slices.len() != 0 {
            let cache = ele + max_inner(&new_slices, left - 1);
            if cache > result {
                result = cache
            }
        } else {
            if ele > result {
                result = ele
            }
        }
    }
    result
}*/

pub fn max_size_slices(slices: Vec<i32>) -> i32 {
    max_inner(&slices, slices.len() / 3)
}

pub fn max_inner(slices: &Vec<i32>, left: usize) -> i32 {
    if slices.len() <= 3 || left == 1 {
        return *slices.iter().max().unwrap();
    }

    let mut cache =
        vec![max_inner(&slices[1..slices.len() - 2].to_vec(), left - 1) + slices.last().unwrap()];

    //println!("fake len: {}, level: {}", fake_len, level);
    cache.append(
        &mut (0..=slices.len() - 3)
            .map(|x| {
                let end_index = if x >= 1 {
                    slices.len()
                } else {
                    slices.len() - 1
                };
                max_inner(&slices[x + 2..end_index].to_vec(), left - 1) + slices[x]
            })
            .collect::<Vec<i32>>(),
    );

    *cache.iter().max().unwrap()
}

fn main() {
    assert_eq!(max_size_slices(vec![3, 1, 2]), 3);
    assert_eq!(max_size_slices(vec![4, 1, 2, 5, 8, 3, 1, 9, 7]), 21);

    assert_eq!(max_size_slices(vec![8, 9, 8, 6, 1, 1]), 16);
    assert_eq!(max_size_slices(vec![1, 2, 3, 4, 5, 6]), 10);

    assert_eq!(max_size_slices(vec![10, 9, 1, 10, 8, 5, 10, 2, 2]), 30);
    assert_eq!(
        max_size_slices(vec![9, 8, 1, 7, 7, 9, 5, 10, 7, 9, 3, 8, 3, 4, 8]),
        45
    );

    assert_eq!(
        max_size_slices(vec![9, 5, 1, 7, 8, 4, 4, 5, 5, 8, 7, 7]), // 9 + 8 + 5 + 8
        30
    );

    assert_eq!(
        max_size_slices(vec![
            2, 4, 3, 1, 10, 6, 1, 2, 10, 2, 8, 9, 4, 8, 8, 8, 10, 3, 9, 10, 7, 9, 4, 5, 4, 3, 1,
            10, 6, 1
        ]),
        85
    );

    dbg!(max_size_slices(vec![
        6, 3, 1, 2, 6, 2, 4, 3, 10, 4, 1, 4, 6, 5, 5, 3, 4, 7, 6, 5, 8, 7, 3, 8, 8, 1, 7, 1, 7, 8
    ]));
}
<commit_msg>finish rs version<commit_after>/*pub fn max_size_slices(slices: Vec<i32>) -> i32 {
    use std::iter::FromIterator;

    if slices.len() == 3 {
        return *slices.iter().max().unwrap();
    }
    let mut result = 0;
    for (ind, &ele) in slices.iter().enumerate() {
        if ele > result {
            result = ele;
        }

        let (start, end);
        let new_slices = if ind == 0 {
            start = 2;
            end = slices.len() - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else if ind == slices.len() - 1 {
            start = 1;
            end = slices.len() - 1 - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else {
            let mut cache = Vec::from_iter(slices[ind + 2..].iter().cloned());
            cache.append(&mut Vec::from_iter(slices[0..ind - 1].iter().cloned()));
            cache
        };

        if new_slices.len() != 0 {
            let cache = ele + max_size_slices(new_slices);
            if cache > result {
                result = cache
            }
        } else {
            if ele > result {
                result = ele
            }
        }
    }
    result
}*/

/*pub fn max_size_slices(slices: Vec<i32>) -> i32 {
    max_inner(&slices, slices.len() / 3)
}

pub fn max_inner(slices: &Vec<i32>, left: usize) -> i32 {
    use std::iter::FromIterator;

    if left == 0 {
        return 0;
    }
    if slices.len() == 3 {
        return *slices.iter().max().unwrap();
    }
    let mut result = 0;
    for (ind, &ele) in slices.iter().enumerate() {
        if ele > result {
            result = ele;
        }

        let (start, end);
        let new_slices = if ind == 0 {
            start = 2;
            end = slices.len() - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else if ind == slices.len() - 1 {
            start = 1;
            end = slices.len() - 1 - 1;
            Vec::from_iter(slices[start..end].iter().cloned())
        } else {
            let mut cache = Vec::from_iter(slices[ind + 2..].iter().cloned());
            cache.append(&mut Vec::from_iter(slices[0..ind - 1].iter().cloned()));
            cache
        };

        if new_slices.len() != 0 {
            let cache = ele + max_inner(&new_slices, left - 1);
            if cache > result {
                result = cache
            }
        } else {
            if ele > result {
                result = ele
            }
        }
    }
    result
}*/

use std::collections::HashMap;
pub fn max_size_slices(slices: Vec<i32>) -> i32 {
    // need hashmap do the Dynamic programming
    let mut cache: HashMap<(usize, usize, usize), i32> = HashMap::new();
    max_inner3(
        &mut cache,
        &slices,
        0,
        slices.len() - 1,
        slices.len() / 3,
        1,
    )
}

// pub fn max_inner(slices: &Vec<i32>, left: usize) -> i32 {
//     if slices.len() <= 3 || left == 1 {
//         return *slices.iter().max().unwrap();
//     }

//     let mut cache =
//         vec![max_inner(&slices[1..slices.len() - 2].to_vec(), left - 1) + slices.last().unwrap()];

//     cache.append(
//         &mut (0..=slices.len() - 3)
//             .map(|x| {
//                 let end_index = if x >= 1 {
//                     slices.len()
//                 } else {
//                     slices.len() - 1
//                 };
//                 max_inner(&slices[x + 2..end_index].to_vec(), left - 1) + slices[x]
//             })
//             .collect::<Vec<i32>>(),
//     );

//     *cache.iter().max().unwrap()
// }

// pub fn max_inner2(slices: &Vec<i32>, left: usize) -> i32 {
//     use std::cmp::max;
//     if left == 1 {
//         return *slices.iter().max().unwrap();
//     }

//     if slices.len() - 1 < left * 2 - 1 {
//         return i32::MIN;
//     }
//     println!("{}", left);
//     return max(
//         max_inner2(&slices[1..slices.len()].to_vec(), left),
//         max_inner2(&slices[2..slices.len() - 2].to_vec(), left - 1) + slices[0],
//     );
// }

pub fn max_inner3(
    cache: &mut HashMap<(usize, usize, usize), i32>,
    slices: &Vec<i32>,
    i: usize,
    j: usize,
    left: usize,
    cycle: usize,
) -> i32 {
    if let Some(v) = cache.get(&(i, j, left)) {
        return *v;
    }
    use std::cmp::max;
    //println!("{:?}, i:{}, j:{}, left: {}", slices, i, j, left);
    if left == 0 {
        return 0;
    }

    if left == 1 {
        return *slices[i..j + 1].iter().max().unwrap();
    }

    if j - i + 1 < left * 2 - 1 {
        return i32::MIN;
    }

    let miao = max(
        // cycle only use first time in max_size_slices
        slices[j] + max_inner3(cache, slices, i + cycle, j - 2, left - 1, 0),
        max_inner3(cache, slices, i, j - 1, left, 0),
    );

    cache.insert((i, j, left), miao);
    miao
}

fn main() {
    assert_eq!(max_size_slices(vec![3, 1, 2]), 3);
    assert_eq!(max_size_slices(vec![4, 1, 2, 5, 8, 3, 1, 9, 7]), 21);

    assert_eq!(max_size_slices(vec![8, 9, 8, 6, 1, 1]), 16);
    assert_eq!(max_size_slices(vec![1, 2, 3, 4, 5, 6]), 10);

    assert_eq!(max_size_slices(vec![10, 9, 1, 10, 8, 5, 10, 2, 2]), 30);
    assert_eq!(
        max_size_slices(vec![9, 8, 1, 7, 7, 9, 5, 10, 7, 9, 3, 8, 3, 4, 8]),
        45
    );

    assert_eq!(
        max_size_slices(vec![9, 5, 1, 7, 8, 4, 4, 5, 5, 8, 7, 7]), // 9 + 8 + 5 + 8
        30
    );

    assert_eq!(
        max_size_slices(vec![
            2, 4, 3, 1, 10, 6, 1, 2, 10, 2, 8, 9, 4, 8, 8, 8, 10, 3, 9, 10, 7, 9, 4, 5, 4, 3, 1,
            10, 6, 1
        ]),
        85
    );

    assert_eq!(
        max_size_slices(vec![
            6, 3, 1, 2, 6, 2, 4, 3, 10, 4, 1, 4, 6, 5, 5, 3, 4, 7, 6, 5, 8, 7, 3, 8, 8, 1, 7, 1, 7,
            8
        ]),
        70
    );

    assert_eq!(
        max_size_slices(vec![
            7, 8, 5, 6, 9, 10, 1, 6, 5, 10, 8, 10, 5, 4, 7, 2, 8, 5, 9, 7, 5, 9, 3, 7, 7, 2, 2, 10,
            7, 6, 4, 6, 5, 7, 7, 9, 6, 8, 10, 7, 5, 7, 2, 5, 4, 9, 6, 10, 10, 2, 10
        ]),
        150
    );
}
<|endoftext|>