<commit_before>use fixedbitset::FixedBitSet;
use parking_lot::Mutex;
use std::cmp;

use gc::swiper::card::CardTable;
use gc::swiper::controller::SharedHeapConfig;
use gc::swiper::crossing::CrossingMap;
use gc::{arena, Address, Region};

// Choose 128K as chunk size for now
const CHUNK_SIZE_BITS: usize = 17;
const CHUNK_SIZE: usize = 1 << CHUNK_SIZE_BITS;

// experimental implementation of an Old generation consisting of chunks
// goal is to reduce work for full GCs
struct SplitOldGen {
    // total size of old generation
    total: Region,

    chunks: Vec<Chunk>,

    prot: Mutex<SplitOldGenProtected>,

    crossing_map: CrossingMap,
    card_table: CardTable,
    config: SharedHeapConfig,
}

impl SplitOldGen {
    fn new(
        start: Address,
        end: Address,
        crossing_map: CrossingMap,
        card_table: CardTable,
        config: SharedHeapConfig,
    ) -> SplitOldGen {
        assert!(start.is_chunk_aligned());

        let total = Region::new(start, end);
        let num_chunks = total.size() / CHUNK_SIZE;

        let mut chunks = Vec::with_capacity(num_chunks);

        for i in 0..num_chunks {
            let chunk_start = start.offset(i * CHUNK_SIZE);
            chunks.push(Chunk::new(chunk_start));
        }

        let prot = Mutex::new(SplitOldGenProtected {
            used_chunks: ChunkSet::empty(num_chunks),
            free_chunks: ChunkSet::full(num_chunks),
        });

        SplitOldGen {
            total: total,
            chunks: chunks,
            prot: prot,
            crossing_map: crossing_map,
            card_table: card_table,
            config: config,
        }
    }

    fn add_chunk(&self) -> bool {
        {
            let mut config = self.config.lock();
            if !config.grow_old(CHUNK_SIZE) {
                return false;
            }
        }

        let mut prot = self.prot.lock();

        if let Some(chunk) = prot.free_chunks.remove_leftmost() {
            prot.used_chunks.add(chunk);
            arena::commit(chunk_addr(chunk, self.total.start), CHUNK_SIZE, false);
            return true;
        }

        false
    }

    fn free_chunk(&self, chunk: ChunkId) {
        let mut prot = self.prot.lock();

        assert!(prot.used_chunks.remove(chunk));
        prot.free_chunks.add(chunk);

        arena::discard(chunk_addr(chunk, self.total.start), CHUNK_SIZE);

        {
            let mut config = self.config.lock();
            config.shrink_old(CHUNK_SIZE);
        }
    }
}

fn chunk_addr(chunk: ChunkId, start: Address) -> Address {
    start.offset(chunk.to_usize() * CHUNK_SIZE)
}

struct SplitOldGenProtected {
    // all used chunks
    used_chunks: ChunkSet,

    // completely free chunks (no live objects)
    free_chunks: ChunkSet,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct ChunkId(usize);

impl ChunkId {
    fn to_usize(self) -> usize {
        self.0
    }
}

struct Chunk {
    // chunk boundaries
    region: Region,

    // end of allocated area in chunk
    top: Address,

    // live objects in bytes
    live: usize,

    // state of chunk
    state: ChunkState,
}

impl Chunk {
    fn new(start: Address) -> Chunk {
        Chunk {
            region: start.region_start(CHUNK_SIZE),
            top: start,
            live: 0,
            state: ChunkState::Free,
        }
    }
}

// An array of chunks
struct ChunkSet {
    bounds: Option<ChunkSetBounds>,
    chunks: FixedBitSet,
}

#[derive(Copy, Clone)]
struct ChunkSetBounds {
    leftmost: usize,
    rightmost: usize,
}

impl ChunkSetBounds {
    fn new(leftmost: usize, rightmost: usize) -> ChunkSetBounds {
        ChunkSetBounds {
            leftmost: leftmost,
            rightmost: rightmost,
        }
    }

    fn tuple(&self) -> (usize, usize) {
        (self.leftmost, self.rightmost)
    }
}

impl ChunkSet {
    fn empty(num_chunks: usize) -> ChunkSet {
        assert!(num_chunks > 0);

        ChunkSet {
            bounds: None,
            chunks: FixedBitSet::with_capacity(num_chunks),
        }
    }

    fn full(num_chunks: usize) -> ChunkSet {
        assert!(num_chunks > 0);
        let mut chunks = FixedBitSet::with_capacity(num_chunks);
        chunks.insert_range(..);

        ChunkSet {
            bounds: Some(ChunkSetBounds::new(0, num_chunks - 1)),
            chunks: chunks,
        }
    }

    fn count(&self) -> usize {
        self.chunks.count_ones(..)
    }

    fn add(&mut self, chunk: ChunkId) {
        self.chunks.insert(chunk.to_usize());

        if let Some(bounds) = self.bounds {
            let (leftmost, rightmost) = bounds.tuple();
            let leftmost = cmp::min(leftmost, chunk.to_usize());
            let rightmost = cmp::max(rightmost, chunk.to_usize());
            self.bounds = Some(ChunkSetBounds::new(leftmost, rightmost));
        } else {
            let chunk = chunk.to_usize();
            self.bounds = Some(ChunkSetBounds::new(chunk, chunk));
        }
    }

    fn remove(&mut self, chunk: ChunkId) -> bool {
        let chunk = chunk.to_usize();

        if self.chunks[chunk] {
            self.chunks.set(chunk, false);

            let (leftmost, rightmost) = self.bounds.expect("bounds are empty").tuple();

            if leftmost == rightmost {
                self.bounds = None;
            } else {
                for i in leftmost+1..rightmost {
                    if self.chunks[i] {
                        self.bounds = Some(ChunkSetBounds::new(i, rightmost));
                        return true;
                    }
                }

                debug_assert!(self.chunks[rightmost]);
                self.bounds = Some(ChunkSetBounds::new(rightmost, rightmost));
            }

            true
        } else {
            false
        }
    }

    fn remove_leftmost(&mut self) -> Option<ChunkId> {
        if let Some(bounds) = self.bounds {
            let leftmost = ChunkId(bounds.leftmost);
            assert!(self.remove(leftmost));
            Some(leftmost)
        } else {
            None
        }
    }
}

enum ChunkState {
    Free,
    Used,
}

impl Address {
    fn is_chunk_aligned(self) -> bool {
        (self.to_usize() & (CHUNK_SIZE - 1)) == 0
    }
}

#[cfg(test)]
mod tests {
    use super::{ChunkId, ChunkSet};

    #[test]
    fn test_empty() {
        let e = ChunkSet::empty(4);
        assert_eq!(e.count(), 0);
    }

    #[test]
    fn test_full() {
        let e = ChunkSet::full(4);
        assert_eq!(e.count(), 4);
    }

    #[test]
    fn test_add_and_remove() {
        let mut e = ChunkSet::empty(4);
        e.add(ChunkId(1));
        e.add(ChunkId(3));
        assert!(e.remove(ChunkId(1)));
        assert_eq!(e.remove_leftmost(), Some(ChunkId(3)));
        assert_eq!(e.count(), 0);
    }
}<commit_msg>split_old: reduce lock duration<commit_after>use fixedbitset::FixedBitSet;
use parking_lot::Mutex;
use std::cmp;

use gc::swiper::card::CardTable;
use gc::swiper::controller::SharedHeapConfig;
use gc::swiper::crossing::CrossingMap;
use gc::{arena, Address, Region};

// Choose 128K as chunk size for now
const CHUNK_SIZE_BITS: usize = 17;
const CHUNK_SIZE: usize = 1 << CHUNK_SIZE_BITS;

// experimental implementation of an Old generation consisting of chunks
// goal is to reduce work for full GCs
struct SplitOldGen {
    // total size of old generation
    total: Region,

    chunks: Vec<Chunk>,

    prot: Mutex<SplitOldGenProtected>,

    crossing_map: CrossingMap,
    card_table: CardTable,
    config: SharedHeapConfig,
}

impl SplitOldGen {
    fn new(
        start: Address,
        end: Address,
        crossing_map: CrossingMap,
        card_table: CardTable,
        config: SharedHeapConfig,
    ) -> SplitOldGen {
        assert!(start.is_chunk_aligned());

        let total = Region::new(start, end);
        let num_chunks = total.size() / CHUNK_SIZE;

        let mut chunks = Vec::with_capacity(num_chunks);

        for i in 0..num_chunks {
            let chunk_start = start.offset(i * CHUNK_SIZE);
            chunks.push(Chunk::new(chunk_start));
        }

        let prot = Mutex::new(SplitOldGenProtected {
            used_chunks: ChunkSet::empty(num_chunks),
            free_chunks: ChunkSet::full(num_chunks),
        });

        SplitOldGen {
            total: total,
            chunks: chunks,
            prot: prot,
            crossing_map: crossing_map,
            card_table: card_table,
            config: config,
        }
    }

    fn add_chunk(&self) -> bool {
        {
            let mut config = self.config.lock();
            if !config.grow_old(CHUNK_SIZE) {
                return false;
            }
        }

        {
            let mut prot = self.prot.lock();

            if let Some(chunk) = prot.free_chunks.remove_leftmost() {
                prot.used_chunks.add(chunk);
                arena::commit(chunk_addr(chunk, self.total.start), CHUNK_SIZE, false);
                return true;
            }
        }

        false
    }

    fn free_chunk(&self, chunk: ChunkId) {
        {
            let mut prot = self.prot.lock();
            assert!(prot.used_chunks.remove(chunk));
            prot.free_chunks.add(chunk);
            arena::discard(chunk_addr(chunk, self.total.start), CHUNK_SIZE);
        }

        {
            let mut config = self.config.lock();
            config.shrink_old(CHUNK_SIZE);
        }
    }
}

fn chunk_addr(chunk: ChunkId, start: Address) -> Address {
    start.offset(chunk.to_usize() * CHUNK_SIZE)
}

struct SplitOldGenProtected {
    // all used chunks
    used_chunks: ChunkSet,

    // completely free chunks (no live objects)
    free_chunks: ChunkSet,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
struct ChunkId(usize);

impl ChunkId {
    fn to_usize(self) -> usize {
        self.0
    }
}

struct Chunk {
    // chunk boundaries
    region: Region,

    // end of allocated area in chunk
    top: Address,

    // live objects in bytes
    live: usize,

    // state of chunk
    state: ChunkState,
}

impl Chunk {
    fn new(start: Address) -> Chunk {
        Chunk {
            region: start.region_start(CHUNK_SIZE),
            top: start,
            live: 0,
            state: ChunkState::Free,
        }
    }
}

// An array of chunks
struct ChunkSet {
    bounds: Option<ChunkSetBounds>,
    chunks: FixedBitSet,
}

#[derive(Copy, Clone)]
struct ChunkSetBounds {
    leftmost: usize,
    rightmost: usize,
}

impl ChunkSetBounds {
    fn new(leftmost: usize, rightmost: usize) -> ChunkSetBounds {
        ChunkSetBounds {
            leftmost: leftmost,
            rightmost: rightmost,
        }
    }

    fn tuple(&self) -> (usize, usize) {
        (self.leftmost, self.rightmost)
    }
}

impl ChunkSet {
    fn empty(num_chunks: usize) -> ChunkSet {
        assert!(num_chunks > 0);

        ChunkSet {
            bounds: None,
            chunks: FixedBitSet::with_capacity(num_chunks),
        }
    }

    fn full(num_chunks: usize) -> ChunkSet {
        assert!(num_chunks > 0);
        let mut chunks = FixedBitSet::with_capacity(num_chunks);
        chunks.insert_range(..);

        ChunkSet {
            bounds: Some(ChunkSetBounds::new(0, num_chunks - 1)),
            chunks: chunks,
        }
    }

    fn count(&self) -> usize {
        self.chunks.count_ones(..)
    }

    fn add(&mut self, chunk: ChunkId) {
        self.chunks.insert(chunk.to_usize());

        if let Some(bounds) = self.bounds {
            let (leftmost, rightmost) = bounds.tuple();
            let leftmost = cmp::min(leftmost, chunk.to_usize());
            let rightmost = cmp::max(rightmost, chunk.to_usize());
            self.bounds = Some(ChunkSetBounds::new(leftmost, rightmost));
        } else {
            let chunk = chunk.to_usize();
            self.bounds = Some(ChunkSetBounds::new(chunk, chunk));
        }
    }

    fn remove(&mut self, chunk: ChunkId) -> bool {
        let chunk = chunk.to_usize();

        if self.chunks[chunk] {
            self.chunks.set(chunk, false);

            let (leftmost, rightmost) = self.bounds.expect("bounds are empty").tuple();

            if leftmost == rightmost {
                self.bounds = None;
            } else {
                for i in leftmost+1..rightmost {
                    if self.chunks[i] {
                        self.bounds = Some(ChunkSetBounds::new(i, rightmost));
                        return true;
                    }
                }

                debug_assert!(self.chunks[rightmost]);
                self.bounds = Some(ChunkSetBounds::new(rightmost, rightmost));
            }

            true
        } else {
            false
        }
    }

    fn remove_leftmost(&mut self) -> Option<ChunkId> {
        if let Some(bounds) = self.bounds {
            let leftmost = ChunkId(bounds.leftmost);
            assert!(self.remove(leftmost));
            Some(leftmost)
        } else {
            None
        }
    }
}

enum ChunkState {
    Free,
    Used,
}

impl Address {
    fn is_chunk_aligned(self) -> bool {
        (self.to_usize() & (CHUNK_SIZE - 1)) == 0
    }
}

#[cfg(test)]
mod tests {
    use super::{ChunkId, ChunkSet};

    #[test]
    fn test_empty() {
        let e = ChunkSet::empty(4);
        assert_eq!(e.count(), 0);
    }

    #[test]
    fn test_full() {
        let e = ChunkSet::full(4);
        assert_eq!(e.count(), 4);
    }

    #[test]
    fn test_add_and_remove() {
        let mut e = ChunkSet::empty(4);
        e.add(ChunkId(1));
        e.add(ChunkId(3));
        assert!(e.remove(ChunkId(1)));
        assert_eq!(e.remove_leftmost(), Some(ChunkId(3)));
        assert_eq!(e.count(), 0);
    }
}<|endoftext|>


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

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

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

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

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

use iterators::coalesce::Coalesce;

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

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

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

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

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

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

/// Counts the number of occurrences of each element.
pub trait Count<G: Scope, K: Data> where G::Timestamp: Lattice {
    /// Counts the number of occurrences of each element.
    fn count(&self) -> Collection<G, (K,Delta)>;

    /// Counts the number of occurrences of each unsigned element.
    fn count_u(&self) -> Collection<G, (K,Delta)> where K: Unsigned+Default;
}

impl<G: Scope, K: Data+Default> Count<G, K> for Collection<G, K> where K: Unsigned+Default, G::Timestamp: Lattice {
    fn count(&self) -> Collection<G, (K,Delta)> {
        self.map(|k| (k,()))
            .group(|_k,s,t| t.push((s.next().unwrap().1, 1)))
    }
    fn count_u(&self) -> Collection<G,(K,Delta)> {
        self.map(|k| (k,()))
            .group_u(|_k,s,t| t.push((s.next().unwrap().1, 1)))
    }
}

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

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

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

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

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

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

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

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

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

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

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

                let time = capability.time();

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

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

                            // determine times at which updates may occur.
                            stash.push(capability.time());
                            source.interesting_times(&key, &time, &mut stash);

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

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

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

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

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

                    for key in keys {

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

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

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

                        // push differences in to Compact.
                        let mut compact = accumulation.session();

                        {
                            let mut borrow = target.borrow_mut();
                            let iter = borrow.get_collection(&key, &time)
                                             .map(|(v, w)| (v,-w))
                                             .merge_by(buffer.iter().map(|&(ref v, w)| (v, w)), |x,y| {
                                                 x.0 <= y.0
                                             });

                            for (val, wgt) in Coalesce::coalesce(iter) {
                                compact.push(val.clone(), wgt);
                            }
                        }

                        compact.done(key);
                        buffer.clear();
                    }

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

        Arranged { stream: stream, trace: result }
    }
}
<commit_msg>commenting out FNV hash map for now<commit_after>//! Group records by a key, and apply a reduction function.
//!
//! The `group` operators act on data that can be viewed as pairs `(key, val)`. They group records
//! with the same key, and apply user supplied functions to the key and a list of values, which are
//! expected to populate a list of output values.
//!
//! Several variants of `group` exist which allow more precise control over how grouping is done.
//! For example, the `_by` suffixed variants take arbitrary data, but require a key-value selector
//! to be applied to each record. The `_u` suffixed variants use unsigned integers as keys, and
//! will use a dense array rather than a `HashMap` to store their keys.
//!
//! The list of values are presented as an iterator which internally merges sorted lists of values.
//! This ordering can be exploited in several cases to avoid computation when only the first few
//! elements are required.
//!
//! #Examples

//!
//! This example groups a stream of `(key,val)` pairs by `key`, and yields only the most frequently
//! occurring value for each key.
//!
//! ```ignore
//! stream.group(|key, vals, output| {
//!     let (mut max_val, mut max_wgt) = vals.next().unwrap();
//!     for (val, wgt) in vals {
//!         if wgt > max_wgt {
//!             max_wgt = wgt;
//!             max_val = val;
//!         }
//!     }
//!     output.push((max_val.clone(), max_wgt));
//! })
//! ```

use std::rc::Rc;
use std::cell::RefCell;
use std::default::Default;
use std::collections::HashMap;
// use std::hash::BuildHasherDefault;
// use fnv::FnvHasher;

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

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

// use collection::basic::Offset;

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

use iterators::coalesce::Coalesce;

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

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

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

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

impl<G: Scope, K: Data+Default, V: Data+Default> Group<G, K, V> for Collection<G, (K,V)>
where G::Timestamp: Lattice
{
    fn group<L, V2: Data>(&self, logic: L) -> Collection<G, (K,V2)>
        where L: Fn(&K, &mut CollectionIterator<DifferenceIterator<V>>, &mut Vec<(V2, Delta)>)+'static {
            // self.arrange_by_key(|k| k.hashed(), |_| { let map: HashMap<K, Offset,
                // BuildHasherDefault<FnvHasher>> = ::std::default::Default::default(); map })
            self.arrange_by_key(|k| k.hashed(), |_| HashMap::new())
                .group(|k| k.hashed(), |_| HashMap::new(), logic)
                .as_collection()
    }

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

/// Counts the number of occurrences of each element.
pub trait Count<G: Scope, K: Data> where G::Timestamp: Lattice {
    /// Counts the number of occurrences of each element.
    fn count(&self) -> Collection<G, (K,Delta)>;

    /// Counts the number of occurrences of each unsigned element.
    fn count_u(&self) -> Collection<G, (K,Delta)> where K: Unsigned+Default;
}

impl<G: Scope, K: Data+Default> Count<G, K> for Collection<G, K> where K: Unsigned+Default, G::Timestamp: Lattice {
    fn count(&self) -> Collection<G, (K,Delta)> {
        self.map(|k| (k,()))
            .group(|_k,s,t| t.push((s.next().unwrap().1, 1)))
    }
    fn count_u(&self) -> Collection<G,(K,Delta)> {
        self.map(|k| (k,()))
            .group_u(|_k,s,t| t.push((s.next().unwrap().1, 1)))
    }
}

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

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

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

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

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

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

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

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

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

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

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

                let time = capability.time();

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

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

                            // determine times at which updates may occur.
                            stash.push(capability.time());
                            source.interesting_times(&key, &time, &mut stash);

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

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

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

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

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

                    for key in keys {

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

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

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

                        // push differences in to Compact.
                        let mut compact = accumulation.session();

                        {
                            let mut borrow = target.borrow_mut();
                            let iter = borrow.get_collection(&key, &time)
                                             .map(|(v, w)| (v,-w))
                                             .merge_by(buffer.iter().map(|&(ref v, w)| (v, w)), |x,y| {
                                                 x.0 <= y.0
                                             });

                            for (val, wgt) in Coalesce::coalesce(iter) {
                                compact.push(val.clone(), wgt);
                            }
                        }

                        compact.done(key);
                        buffer.clear();
                    }

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

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


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

use core;
use std::iter;
use std::ascii::AsciiExt;

use http::status;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

impl Response {
    /// Create a `Response`.
    pub fn new(body: String) -> Response {
        let mut response = Response {
            status: status::Ok,
            headers: Headers::new(None),
            body: body,
        };
        let content_type = String::from_str("text/plain; charset=utf-8");
        let content_length = response.body.len().to_string();
        response.headers.set(String::from_str("Content-Type"), content_type);
        response.headers.set(String::from_str("Content-Length"), content_length);
        return response;
    }

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

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

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

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

    /// Sets a new string as response body.  The content length is set
    /// automatically.
    pub fn set_data(&mut self, value: String) {
        self.body = value;
        let content_length = self.body.len().to_string();
        self.headers.set(String::from_str("Content-Length"), content_length);
    }

    /// Returns the response content type if available.
    pub fn get_content_type(&self) -> Option<String> {
        let rv = self.headers.get(String::from_str("Content-Type"));
        match rv {
            Some(content_type) => content_type.clone(),
            None => None,
        }
    }

    /// Set response content type.
    pub fn set_content_type(&mut self, value: String) {
        self.headers.set(String::from_str("Content-Type"), value);
    }

    /// Returns the response content length if available.
    pub fn get_content_length(&self) -> Option<uint> {
        let rv = self.headers.get(String::from_str("Content-Length"));
        match rv {
            Some(content_length) => from_str(content_length.as_slice()),
            None => None,
        }
    }

    /// Set content length.
    pub fn set_content_length(&mut self, value: uint) {
        self.headers.set(String::from_str("Content-Length"), value.to_string());
    }
}
<commit_msg>Fixed get_content_type<commit_after>// This module implements simple request and response objects.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use core;
use std::iter;
use std::ascii::AsciiExt;

use http::status;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

impl Response {
    /// Create a `Response`.
    pub fn new(body: String) -> Response {
        let mut response = Response {
            status: status::Ok,
            headers: Headers::new(None),
            body: body,
        };
        let content_type = String::from_str("text/plain; charset=utf-8");
        let content_length = response.body.len().to_string();
        response.headers.set(String::from_str("Content-Type"), content_type);
        response.headers.set(String::from_str("Content-Length"), content_length);
        return response;
    }

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

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

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

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

    /// Sets a new string as response body.  The content length is set
    /// automatically.
    pub fn set_data(&mut self, value: String) {
        self.body = value;
        let content_length = self.body.len().to_string();
        self.headers.set(String::from_str("Content-Length"), content_length);
    }

    /// Returns the response content type if available.
    pub fn get_content_type(&self) -> Option<String> {
        let rv = self.headers.get(String::from_str("Content-Type"));
        rv.map(|content_type| content_type.clone())
    }

    /// Set response content type.
    pub fn set_content_type(&mut self, value: String) {
        self.headers.set(String::from_str("Content-Type"), value);
    }

    /// Returns the response content length if available.
    pub fn get_content_length(&self) -> Option<uint> {
        let rv = self.headers.get(String::from_str("Content-Length"));
        match rv {
            Some(content_length) => from_str(content_length.as_slice()),
            None => None,
        }
    }

    /// Set content length.
    pub fn set_content_length(&mut self, value: uint) {
        self.headers.set(String::from_str("Content-Length"), value.to_string());
    }
}
<|endoftext|>


<commit_before>use routing::GraphWatcher;
/// Trait that allows for rendering a RouteGraph
pub trait Renderer: GraphWatcher {
    fn get_sample(&mut self, idx: u64, ch: u8) -> f32;
    // TODO: use a multidimensional array type for buffer; remove num_ch param
    /// Fill the provided buffer with samples.
    /// Samples are interleaved by channel, e.g.
    /// [t=0,c=0; t=0,c=1; t=1,c=0; t=1,c=1; t=2,c=0; ...]
    /// It's a good idea to make sure the buffer size is a multiple of the number of channels.
    fn fill_buffer(&mut self, buff: &mut [f32], idx: u64, num_ch: u8) {
        for (buff_idx, sample) in buff.iter_mut().enumerate() {
            // Note: if num_ch == 0, buff.len() == 0, so this block isn't reached.
            // Risk of division by zero is low & caused by error in the caller.
            let time_idx = (buff_idx / num_ch as usize) as u64;
            let ch = (buff_idx % num_ch as usize) as u8;
            *sample = self.get_sample(time_idx, ch);
        }
    }
}
<commit_msg>Fix missing time offset<commit_after>use routing::GraphWatcher;
/// Trait that allows for rendering a RouteGraph
pub trait Renderer: GraphWatcher {
    fn get_sample(&mut self, idx: u64, ch: u8) -> f32;
    // TODO: use a multidimensional array type for buffer; remove num_ch param
    /// Fill the provided buffer with samples.
    /// Samples are interleaved by channel, e.g.
    /// [t=0,c=0; t=0,c=1; t=1,c=0; t=1,c=1; t=2,c=0; ...]
    /// It's a good idea to make sure the buffer size is a multiple of the number of channels.
    fn fill_buffer(&mut self, buff: &mut [f32], idx: u64, num_ch: u8) {
        for (buff_idx, sample) in buff.iter_mut().enumerate() {
            // Note: if num_ch == 0, buff.len() == 0, so this block isn't reached.
            // Risk of division by zero is low & caused by error in the caller.
            let time_idx = idx + (buff_idx / num_ch as usize) as u64;
            let ch = (buff_idx % num_ch as usize) as u8;
            *sample = self.get_sample(time_idx, ch);
        }
    }
}
<|endoftext|>


<commit_before>// id             number            A unique numeric ID that can be used to
// identify and reference an action.
// status         string            The current status of the action. This can
// be "in-progress", "completed", or "errored".
// type           string            This is the type of action that the object
// represents. For example, this could be "transfer" to represent the state of
// an image transfer action.
// started_at     string            A time value given in ISO8601 combined date
// and time format that represents when the action was initiated.
// completed_at   string            A time value given in ISO8601 combined date
// and time format that represents when the action was completed.
// resource_id    number            A unique identifier for the resource that
// the action is associated with.
// resource_type  string            The type of resource that the action is
// associated with.
// region         nullable string   (deprecated) A slug representing the region
// where the action occurred.
// region_slug    nullable string   A slug representing the region where the
// action occurred.

use std::fmt;
use std::borrow::Cow;

use response::region::Region;
use response::NamedResponse;
use response;

#[derive(Deserialize, Debug)]
pub struct Action {
    id: f64,
    status: String,
    #[serde(rename="type")]
    action_type: String,
    started_at: String,
    completed_at: String,
    resource_id: f64,
    resource_type: String,
    region: Region,
    region_slug: Option<String>,
}

impl response::NotArray for Action {}

impl fmt::Display for Action {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "ID: {}\n\
                  Status: {}\n\
                  Type: {}\n\
                  Started At: {}\n\
                  Completed At: {}\n\
                  Resource ID: {}\n\
                  Resource Type: {}\n\
                  Region Slug: {}\n\
                  Region:\n\t{}",
               self.id,
               self.status,
               self.action_type,
               self.started_at,
               self.completed_at,
               self.resource_id,
               self.resource_type,
               if self.region_slug.is_some() {
                   self.region_slug.clone().unwrap()
               } else {
                   "None".to_owned()
               },
               self.region.to_string().replace("\n", "\n\t"))
    }
}

pub type Actions = Vec<Action>;

impl NamedResponse for Action {
    fn name<'a>() -> Cow<'a, str> {
        "action".into()
    }
}
<commit_msg>fix: action completed_at is a nullable string<commit_after>// id             number            A unique numeric ID that can be used to
// identify and reference an action.
// status         string            The current status of the action. This can
// be "in-progress", "completed", or "errored".
// type           string            This is the type of action that the object
// represents. For example, this could be "transfer" to represent the state of
// an image transfer action.
// started_at     string            A time value given in ISO8601 combined date
// and time format that represents when the action was initiated.
// completed_at   nullable string   A time value given in ISO8601 combined date
// and time format that represents when the action was completed.
// resource_id    number            A unique identifier for the resource that
// the action is associated with.
// resource_type  string            The type of resource that the action is
// associated with.
// region         nullable string   (deprecated) A slug representing the region
// where the action occurred.
// region_slug    nullable string   A slug representing the region where the
// action occurred.

use std::fmt;
use std::borrow::Cow;

use response::region::Region;
use response::NamedResponse;
use response;

#[derive(Deserialize, Debug)]
pub struct Action {
    id: f64,
    status: String,
    #[serde(rename="type")]
    action_type: String,
    started_at: String,
    completed_at: Option<String>,
    resource_id: f64,
    resource_type: String,
    region: Region,
    region_slug: Option<String>,
}

impl response::NotArray for Action {}

impl fmt::Display for Action {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "ID: {}\n\
                  Status: {}\n\
                  Type: {}\n\
                  Started At: {}\n\
                  Completed At: {}\n\
                  Resource ID: {}\n\
                  Resource Type: {}\n\
                  Region Slug: {}\n\
                  Region:\n\t{}",
               self.id,
               self.status,
               self.action_type,
               self.started_at,
               if self.completed_at.is_some() {
                   self.completed_at.clone().unwrap()
               } else {
                   "None".to_owned()
               },
               self.resource_id,
               self.resource_type,
               if self.region_slug.is_some() {
                   self.region_slug.clone().unwrap()
               } else {
                   "None".to_owned()
               },
               self.region.to_string().replace("\n", "\n\t"))
    }
}

pub type Actions = Vec<Action>;

impl NamedResponse for Action {
    fn name<'a>() -> Cow<'a, str> {
        "action".into()
    }
}
<|endoftext|>


<commit_before>import rustc::syntax::ast;
import rustc::syntax::visit;

export extract;

#[doc = "Converts the Rust AST to the rustdoc document model"]
fn extract(
    crate: @ast::crate,
    default_name: str
) -> doc::cratedoc {
    ~{
        topmod: top_moddoc_from_crate(crate, default_name),
    }
}

fn top_moddoc_from_crate(
    crate: @ast::crate,
    default_name: str
) -> doc::moddoc {
    moddoc_from_mod(crate.node.module, default_name)
}

fn moddoc_from_mod(
    module: ast::_mod,
    name: ast::ident
) -> doc::moddoc {
    ~{
        name: name,
        mods: doc::modlist(
            vec::filter_map(module.items) {|item|
                alt item.node {
                  ast::item_mod(m) {
                    some(moddoc_from_mod(m, item.ident))
                  }
                  _ {
                    none
                  }
                }
            }),
        fns: doc::fnlist(
            vec::filter_map(module.items) {|item|
                alt item.node {
                  ast::item_fn(decl, _, _) {
                    some(fndoc_from_fn(
                        decl, item.ident, item.id))
                  }
                  _ {
                    none
                  }
                }
            })
    }
}

fn fndoc_from_fn(
    _decl: ast::fn_decl,
    name: ast::ident,
    id: ast::node_id
) -> doc::fndoc {
    ~{
        id: id,
        name: name,
        brief: none,
        desc: none,
        return: none,
        args: []
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn extract_empty_crate() {
        let source = ""; // empty crate
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        // FIXME #1535: These are boxed to prevent a crash
        assert ~doc.topmod.mods == ~doc::modlist([]);
        assert ~doc.topmod.fns == ~doc::fnlist([]);
    }

    #[test]
    fn extract_mods() {
        let source = "mod a { mod b { } mod c { } }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.mods[0].name == "a";
        assert doc.topmod.mods[0].mods[0].name == "b";
        assert doc.topmod.mods[0].mods[1].name == "c";
    }

    #[test]
    fn extract_mods_deep() {
        let source = "mod a { mod b { mod c { } } }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.mods[0].mods[0].mods[0].name == "c";
    }

    #[test]
    fn extract_fns() {
        let source =
            "fn a() { } \
             mod b { fn c() { } }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.fns[0].name == "a";
        assert doc.topmod.mods[0].fns[0].name == "c";
    }

    #[test]
    fn extract_should_set_fn_ast_id() {
        let source = "fn a() { }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.fns[0].id != 0;
    }

    #[test]
    fn extract_should_use_default_crate_name() {
        let source = "";
        let ast = parse::from_str(source);
        let doc = extract(ast, "burp");
        assert doc.topmod.name == "burp";
    }
}<commit_msg>rustdoc: Remove unused import from extract module<commit_after>import rustc::syntax::ast;

export extract;

#[doc = "Converts the Rust AST to the rustdoc document model"]
fn extract(
    crate: @ast::crate,
    default_name: str
) -> doc::cratedoc {
    ~{
        topmod: top_moddoc_from_crate(crate, default_name),
    }
}

fn top_moddoc_from_crate(
    crate: @ast::crate,
    default_name: str
) -> doc::moddoc {
    moddoc_from_mod(crate.node.module, default_name)
}

fn moddoc_from_mod(
    module: ast::_mod,
    name: ast::ident
) -> doc::moddoc {
    ~{
        name: name,
        mods: doc::modlist(
            vec::filter_map(module.items) {|item|
                alt item.node {
                  ast::item_mod(m) {
                    some(moddoc_from_mod(m, item.ident))
                  }
                  _ {
                    none
                  }
                }
            }),
        fns: doc::fnlist(
            vec::filter_map(module.items) {|item|
                alt item.node {
                  ast::item_fn(decl, _, _) {
                    some(fndoc_from_fn(
                        decl, item.ident, item.id))
                  }
                  _ {
                    none
                  }
                }
            })
    }
}

fn fndoc_from_fn(
    _decl: ast::fn_decl,
    name: ast::ident,
    id: ast::node_id
) -> doc::fndoc {
    ~{
        id: id,
        name: name,
        brief: none,
        desc: none,
        return: none,
        args: []
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn extract_empty_crate() {
        let source = ""; // empty crate
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        // FIXME #1535: These are boxed to prevent a crash
        assert ~doc.topmod.mods == ~doc::modlist([]);
        assert ~doc.topmod.fns == ~doc::fnlist([]);
    }

    #[test]
    fn extract_mods() {
        let source = "mod a { mod b { } mod c { } }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.mods[0].name == "a";
        assert doc.topmod.mods[0].mods[0].name == "b";
        assert doc.topmod.mods[0].mods[1].name == "c";
    }

    #[test]
    fn extract_mods_deep() {
        let source = "mod a { mod b { mod c { } } }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.mods[0].mods[0].mods[0].name == "c";
    }

    #[test]
    fn extract_fns() {
        let source =
            "fn a() { } \
             mod b { fn c() { } }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.fns[0].name == "a";
        assert doc.topmod.mods[0].fns[0].name == "c";
    }

    #[test]
    fn extract_should_set_fn_ast_id() {
        let source = "fn a() { }";
        let ast = parse::from_str(source);
        let doc = extract(ast, "");
        assert doc.topmod.fns[0].id != 0;
    }

    #[test]
    fn extract_should_use_default_crate_name() {
        let source = "";
        let ast = parse::from_str(source);
        let doc = extract(ast, "burp");
        assert doc.topmod.name == "burp";
    }
}<|endoftext|>


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

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
extern crate serde_json;
extern crate serde_yaml;

#[macro_use] extern crate serde_derive;

#[derive(Serialize, Deserialize)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

#[derive(Serialize, Deserialize)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArg = (String,ArgValue);

#[derive(Serialize, Deserialize)]
struct DbusMessage {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: Vec<NamedArg>,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting(String, String, String, Vec<DbusMessage>);

#[derive(Serialize, Deserialize)]
struct ConfYaml(Vec<DbusMessageRouting>);

#[derive(Serialize, Deserialize)]
struct ClientRequest(DbusMessageType, String, Vec<NamedArg>);

#[derive(Serialize, Deserialize)]
struct ClientRequestBody(DbusMessageType, Vec<NamedArg>);

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: vec![
                                    ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                    ("param2".to_string(), ArgValue::Bool(true)),
                                    ("param3".to_string(), ArgValue::Int64(17i64)),
                                    ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ]
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest(DbusMessageType::Method, "api_name".to_string(), vec![
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ]
                          );
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let rb = ClientRequestBody(DbusMessageType::Method, vec![
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ]
                          );

    let mut a_request = HashMap::new();
    a_request.insert("api_name", rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

}
<commit_msg>for posterity.<commit_after>use std::collections::HashMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
extern crate serde_json;
extern crate serde_yaml;

#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

#[derive(Serialize, Deserialize)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs<'a> = HashMap<&'a str, ArgValue>;

#[derive(Serialize, Deserialize)]
struct DbusMessage<'a> {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: NamedArgs<'a>,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting<'a>(String, String, String, Vec<DbusMessage<'a>>);

#[derive(Serialize, Deserialize)]
struct ConfYaml<'a>(Vec<DbusMessageRouting<'a>>);

#[derive(Serialize, Deserialize)]
struct ClientRequest<'a>(DbusMessageType, String, NamedArgs<'a>);

#[derive(Serialize, Deserialize)]
struct ClientRequestBody<'a>(DbusMessageType, NamedArgs<'a>);

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1", ArgValue::Str("Hi".to_string())),
                                    ("param2", ArgValue::Bool(true)),
                                    ("param3", ArgValue::Int64(17i64)),
                                    ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest(DbusMessageType::Method, "api_name".to_string(), [
                                        ("param1", ArgValue::Str("Hi".to_string())),
                                        ("param2", ArgValue::Bool(true)),
                                        ("param3", ArgValue::Int64(17i64)),
                                        ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1", ArgValue::Str("Hi".to_string())),
                                        ("param2", ArgValue::Bool(true)),
                                        ("param3", ArgValue::Int64(17i64)),
                                        ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request = HashMap::new();
    a_request.insert("api_name", rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

}
<|endoftext|>


<commit_before>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
extern crate serde_json;
extern crate serde_yaml;

#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

#[derive(Serialize, Deserialize)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs<'a> = HashMap<&'a str, ArgValue>;

#[derive(Serialize, Deserialize)]
struct DbusMessage<'a> {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    #[serde(borrow)]
    args: NamedArgs<'a>,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting<'a>(String, String, String, #[serde(borrow)] Vec<DbusMessage<'a>>);

#[derive(Serialize, Deserialize)]
struct ConfYaml<'a>(#[serde(borrow)] Vec<DbusMessageRouting<'a>>);

#[derive(Serialize, Deserialize)]
struct ClientRequest<'a>(DbusMessageType, String, #[serde(borrow)] NamedArgs<'a>);

#[derive(Serialize, Deserialize)]
struct ClientRequestBody<'a>(DbusMessageType, #[serde(borrow)] NamedArgs<'a>);

type CRequest<'a> = HashMap<&'a str, ClientRequestBody<'a>>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1", ArgValue::Str("Hi".to_string())),
                                    ("param2", ArgValue::Bool(true)),
                                    ("param3", ArgValue::Int64(17i64)),
                                    ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest(DbusMessageType::Method, "api_name".to_string(), [
                                        ("param1", ArgValue::Str("Hi".to_string())),
                                        ("param2", ArgValue::Bool(true)),
                                        ("param3", ArgValue::Int64(17i64)),
                                        ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1", ArgValue::Str("Hi".to_string())),
                                        ("param2", ArgValue::Bool(true)),
                                        ("param3", ArgValue::Int64(17i64)),
                                        ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name", rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

}
<commit_msg>get key from deserialized.<commit_after>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
extern crate serde_json;
extern crate serde_yaml;

#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

#[derive(Serialize, Deserialize)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs<'a> = HashMap<&'a str, ArgValue>;

#[derive(Serialize, Deserialize)]
struct DbusMessage<'a> {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    #[serde(borrow)]
    args: NamedArgs<'a>,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting<'a>(String, String, String, #[serde(borrow)] Vec<DbusMessage<'a>>);

#[derive(Serialize, Deserialize)]
struct ConfYaml<'a>(#[serde(borrow)] Vec<DbusMessageRouting<'a>>);

#[derive(Serialize, Deserialize)]
struct ClientRequest<'a>(DbusMessageType, String, #[serde(borrow)] NamedArgs<'a>);

#[derive(Serialize, Deserialize)]
struct ClientRequestBody<'a>(DbusMessageType, #[serde(borrow)] NamedArgs<'a>);

type CRequest<'a> = HashMap<&'a str, ClientRequestBody<'a>>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1", ArgValue::Str("Hi".to_string())),
                                    ("param2", ArgValue::Bool(true)),
                                    ("param3", ArgValue::Int64(17i64)),
                                    ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest(DbusMessageType::Method, "api_name".to_string(), [
                                        ("param1", ArgValue::Str("Hi".to_string())),
                                        ("param2", ArgValue::Bool(true)),
                                        ("param3", ArgValue::Int64(17i64)),
                                        ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1", ArgValue::Str("Hi".to_string())),
                                        ("param2", ArgValue::Bool(true)),
                                        ("param3", ArgValue::Int64(17i64)),
                                        ("param4", ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name", rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

    for key in de.keys() {
        println!("key {}", key);
    }
    println!("key[0] : {}", de.keys().nth(0).unwrap());

}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2019 Fabian Schuiki

//! A parameter environment generated by an instantiation.

use crate::{
    ast_map::AstNode,
    crate_prelude::*,
    hir::{HirNode, NamedParam, PosParam},
};

/// A parameter environment.
///
/// This is merely an handle that is cheap to copy and pass around. Use the
/// [`Context`] to resolve this to the actual [`ParamEnvData`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ParamEnv(pub(crate) u32);

/// A parameter environment.
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
pub struct ParamEnvData {
    values: Vec<(NodeId, NodeId)>,
    types: Vec<(NodeId, NodeId)>,
}

/// A location that implies a parameter environment.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ParamEnvSource<'hir> {
    ModuleInst {
        module: NodeId,
        pos: &'hir [PosParam],
        named: &'hir [NamedParam],
    },
}

pub(crate) fn compute<'gcx>(
    cx: &impl Context<'gcx>,
    src: ParamEnvSource<'gcx>,
) -> Result<ParamEnv> {
    match src {
        ParamEnvSource::ModuleInst { module, pos, named } => {
            let module = match cx.hir_of(module)? {
                HirNode::Module(m) => m,
                _ => panic!("expected module"),
            };

            // Associate the positional and named assignments with the actual
            // parameters of the module.
            let param_iter = pos
                .iter()
                .enumerate()
                .map(
                    |(index, &(span, assign_id))| match module.params.get(index) {
                        Some(&param_id) => Ok((param_id, assign_id)),
                        None => {
                            cx.emit(
                                DiagBuilder2::error(format!(
                                    "{} only has {} parameter(s)",
                                    module.desc_full(),
                                    module.params.len()
                                ))
                                .span(span),
                            );
                            Err(())
                        }
                    },
                )
                .chain(named.iter().map(
                    |&(span, name, assign_id)| match module.params.iter().find(|&&p| {
                        let param_name = match cx.ast_of(p) {
                            Ok(AstNode::TypeParam(_, p)) => Spanned::new(p.name.name, p.name.span),
                            Ok(AstNode::ValueParam(_, p)) => Spanned::new(p.name.name, p.name.span),
                            Ok(_) => unreachable!(),
                            Err(()) => return false,
                        };
                        param_name == name
                    }) {
                        Some(&param_id) => Ok((param_id, assign_id)),
                        None => {
                            cx.emit(
                                DiagBuilder2::error(format!(
                                    "{} has no parameter `{}`",
                                    module.desc_full(),
                                    name
                                ))
                                .span(span),
                            );
                            Err(())
                        }
                    },
                ));
            let param_iter = param_iter
                .collect::<Vec<_>>()
                .into_iter()
                .collect::<Result<Vec<_>>>()?
                .into_iter();

            // Split up type and value parameters.
            let mut types = vec![];
            let mut values = vec![];
            for (param_id, assign_id) in param_iter {
                match cx.ast_of(param_id)? {
                    AstNode::TypeParam(..) => types.push((param_id, assign_id)),
                    AstNode::ValueParam(..) => values.push((param_id, assign_id)),
                    _ => unreachable!(),
                }
            }

            Ok(cx.intern_param_env(ParamEnvData { types, values }))
        }
    }
}
<commit_msg>svlog: fix named parameter pairing<commit_after>// Copyright (c) 2016-2019 Fabian Schuiki

//! A parameter environment generated by an instantiation.

use crate::{
    ast_map::AstNode,
    crate_prelude::*,
    hir::{HirNode, NamedParam, PosParam},
};

/// A parameter environment.
///
/// This is merely an handle that is cheap to copy and pass around. Use the
/// [`Context`] to resolve this to the actual [`ParamEnvData`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ParamEnv(pub(crate) u32);

/// A parameter environment.
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
pub struct ParamEnvData {
    values: Vec<(NodeId, NodeId)>,
    types: Vec<(NodeId, NodeId)>,
}

/// A location that implies a parameter environment.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ParamEnvSource<'hir> {
    ModuleInst {
        module: NodeId,
        pos: &'hir [PosParam],
        named: &'hir [NamedParam],
    },
}

pub(crate) fn compute<'gcx>(
    cx: &impl Context<'gcx>,
    src: ParamEnvSource<'gcx>,
) -> Result<ParamEnv> {
    match src {
        ParamEnvSource::ModuleInst { module, pos, named } => {
            let module = match cx.hir_of(module)? {
                HirNode::Module(m) => m,
                _ => panic!("expected module"),
            };

            // Associate the positional and named assignments with the actual
            // parameters of the module.
            let param_iter = pos
                .iter()
                .enumerate()
                .map(
                    |(index, &(span, assign_id))| match module.params.get(index) {
                        Some(&param_id) => Ok((param_id, assign_id)),
                        None => {
                            cx.emit(
                                DiagBuilder2::error(format!(
                                    "{} only has {} parameter(s)",
                                    module.desc_full(),
                                    module.params.len()
                                ))
                                .span(span),
                            );
                            Err(())
                        }
                    },
                )
                .chain(named.iter().map(|&(_span, name, assign_id)| {
                    let names: Vec<_> = module
                        .params
                        .iter()
                        .flat_map(|&id| match cx.ast_of(id) {
                            Ok(AstNode::TypeParam(_, p)) => Some((p.name.name, id)),
                            Ok(AstNode::ValueParam(_, p)) => Some((p.name.name, id)),
                            Ok(_) => unreachable!(),
                            Err(()) => None,
                        })
                        .collect();
                    match names
                        .iter()
                        .find(|&(param_name, _)| *param_name == name.value)
                    {
                        Some(&(_, param_id)) => Ok((param_id, assign_id)),
                        None => {
                            cx.emit(
                                DiagBuilder2::error(format!(
                                    "no parameter `{}` in {}",
                                    name,
                                    module.desc_full(),
                                ))
                                .span(name.span)
                                .add_note(format!(
                                    "declared parameters are {}",
                                    names
                                        .iter()
                                        .map(|&(n, _)| format!("`{}`", n))
                                        .collect::<Vec<_>>()
                                        .join(", ")
                                )),
                            );
                            Err(())
                        }
                    }
                }));
            let param_iter = param_iter
                .collect::<Vec<_>>()
                .into_iter()
                .collect::<Result<Vec<_>>>()?
                .into_iter();

            // Split up type and value parameters.
            let mut types = vec![];
            let mut values = vec![];
            for (param_id, assign_id) in param_iter {
                match cx.ast_of(param_id)? {
                    AstNode::TypeParam(..) => types.push((param_id, assign_id)),
                    AstNode::ValueParam(..) => values.push((param_id, assign_id)),
                    _ => unreachable!(),
                }
            }

            Ok(cx.intern_param_env(ParamEnvData { types, values }))
        }
    }
}
<|endoftext|>


<commit_before>use chrono::{DateTime, Utc};

use super::resource::{ResourceKind, CResourceUpdate, SResourceUpdate};
use super::criterion::Criterion;

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub major: u16,
    pub minor: u16,
}

/// Client -> server messages
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[serde(tag = "type")]
#[serde(deny_unknown_fields)]
pub enum CMessage {
    // Standard messages
    GetResources { serial: u64, ids: Vec<String> },
    Subscribe { serial: u64, ids: Vec<String> },
    Unsubscribe { serial: u64, ids: Vec<String> },
    UpdateResource {
        serial: u64,
        resource: CResourceUpdate,
    },
    RemoveResource {
        serial: u64,
        id: String,
        artifacts: Option<bool>,
    },
    FilterSubscribe {
        serial: u64,
        #[serde(default)]
        kind: ResourceKind,
        #[serde(default)]
        criteria: Vec<Criterion>,
    },
    FilterUnsubscribe { serial: u64, filter_serial: u64 },

    // Special messages
    UploadTorrent {
        serial: u64,
        size: u64,
        path: Option<String>,
        #[serde(default = "default_start")]
        start: bool,
    },
    UploadMagnet {
        serial: u64,
        uri: String,
        path: Option<String>,
        #[serde(default = "default_start")]
        start: bool,
    },
    UploadFiles {
        serial: u64,
        size: u64,
        path: String,
    },
    PauseTorrent { serial: u64, id: String },
    ResumeTorrent { serial: u64, id: String },
    UpdateTracker { id: String, serial: u64 },
    ValidateResources { serial: u64, ids: Vec<String> },
}

/// Server -> client message
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[serde(tag = "type")]
#[serde(deny_unknown_fields)]
pub enum SMessage<'a> {
    // Standard messages
    #[serde(skip_deserializing)]
    ResourcesExtant { serial: u64, ids: Vec<&'a str> },
    #[serde(skip_serializing)]
    #[serde(rename = "RESOURCES_EXTANT")]
    OResourcesExtant { serial: u64, ids: Vec<String> },
    ResourcesRemoved { serial: u64, ids: Vec<String> },
    UpdateResources { resources: Vec<SResourceUpdate<'a>> },

    // Special messages
    RpcVersion(Version),
    TransferOffer {
        serial: u64,
        expires: DateTime<Utc>,
        token: String,
        size: u64,
    },

    // Error messages
    UnknownResource(Error),
    InvalidResource(Error),
    // InvalidMessage(Error),
    InvalidSchema(Error),
    InvalidRequest(Error),
    PermissionDenied(Error),
    TransferFailed(Error),
    // ServerError(Error),
}

#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Error {
    pub serial: Option<u64>,
    pub reason: String,
}

impl Version {
    pub fn current() -> Version {
        Version {
            major: ::MAJOR_VERSION,
            minor: ::MINOR_VERSION,
        }
    }
}

fn default_start() -> bool {
    true
}

#[cfg(test)]
mod tests {
    extern crate serde_json;
    use super::*;
    use super::super::{resource, criterion};

    #[test]
    fn test_json_repr() {
        let data = r#"
            {
                "type": "FILTER_SUBSCRIBE",
                "serial": 0,
                "criteria": [
                    { "field": "id", "op": "in", "value": [1,2,null] }
                ]
            }
            "#;
        let m = serde_json::from_str(data).unwrap();
        if let CMessage::FilterSubscribe {
            kind: resource::ResourceKind::Torrent,
            serial: 0,
            criteria: c,
        } = m
        {
            assert_eq!(c[0].field, "id");
            assert_eq!(c[0].op, criterion::Operation::In);
            let v = vec![
                criterion::Value::N(1),
                criterion::Value::N(2),
                criterion::Value::E(None),
            ];
            assert_eq!(c[0].value, criterion::Value::V(v));
        } else {
            unreachable!();
        }
    }
}
<commit_msg>Add default tag to artifacts<commit_after>use chrono::{DateTime, Utc};

use super::resource::{ResourceKind, CResourceUpdate, SResourceUpdate};
use super::criterion::Criterion;

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub major: u16,
    pub minor: u16,
}

/// Client -> server messages
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[serde(tag = "type")]
#[serde(deny_unknown_fields)]
pub enum CMessage {
    // Standard messages
    GetResources { serial: u64, ids: Vec<String> },
    Subscribe { serial: u64, ids: Vec<String> },
    Unsubscribe { serial: u64, ids: Vec<String> },
    UpdateResource {
        serial: u64,
        resource: CResourceUpdate,
    },
    RemoveResource {
        serial: u64,
        id: String,
        #[serde(default)]
        artifacts: Option<bool>,
    },
    FilterSubscribe {
        serial: u64,
        #[serde(default)]
        kind: ResourceKind,
        #[serde(default)]
        criteria: Vec<Criterion>,
    },
    FilterUnsubscribe { serial: u64, filter_serial: u64 },

    // Special messages
    UploadTorrent {
        serial: u64,
        size: u64,
        path: Option<String>,
        #[serde(default = "default_start")]
        start: bool,
    },
    UploadMagnet {
        serial: u64,
        uri: String,
        path: Option<String>,
        #[serde(default = "default_start")]
        start: bool,
    },
    UploadFiles {
        serial: u64,
        size: u64,
        path: String,
    },
    PauseTorrent { serial: u64, id: String },
    ResumeTorrent { serial: u64, id: String },
    UpdateTracker { id: String, serial: u64 },
    ValidateResources { serial: u64, ids: Vec<String> },
}

/// Server -> client message
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[serde(tag = "type")]
#[serde(deny_unknown_fields)]
pub enum SMessage<'a> {
    // Standard messages
    #[serde(skip_deserializing)]
    ResourcesExtant { serial: u64, ids: Vec<&'a str> },
    #[serde(skip_serializing)]
    #[serde(rename = "RESOURCES_EXTANT")]
    OResourcesExtant { serial: u64, ids: Vec<String> },
    ResourcesRemoved { serial: u64, ids: Vec<String> },
    UpdateResources { resources: Vec<SResourceUpdate<'a>> },

    // Special messages
    RpcVersion(Version),
    TransferOffer {
        serial: u64,
        expires: DateTime<Utc>,
        token: String,
        size: u64,
    },

    // Error messages
    UnknownResource(Error),
    InvalidResource(Error),
    // InvalidMessage(Error),
    InvalidSchema(Error),
    InvalidRequest(Error),
    PermissionDenied(Error),
    TransferFailed(Error),
    // ServerError(Error),
}

#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Error {
    pub serial: Option<u64>,
    pub reason: String,
}

impl Version {
    pub fn current() -> Version {
        Version {
            major: ::MAJOR_VERSION,
            minor: ::MINOR_VERSION,
        }
    }
}

fn default_start() -> bool {
    true
}

#[cfg(test)]
mod tests {
    extern crate serde_json;
    use super::*;
    use super::super::{resource, criterion};

    #[test]
    fn test_json_repr() {
        let data = r#"
            {
                "type": "FILTER_SUBSCRIBE",
                "serial": 0,
                "criteria": [
                    { "field": "id", "op": "in", "value": [1,2,null] }
                ]
            }
            "#;
        let m = serde_json::from_str(data).unwrap();
        if let CMessage::FilterSubscribe {
            kind: resource::ResourceKind::Torrent,
            serial: 0,
            criteria: c,
        } = m
        {
            assert_eq!(c[0].field, "id");
            assert_eq!(c[0].op, criterion::Operation::In);
            let v = vec![
                criterion::Value::N(1),
                criterion::Value::N(2),
                criterion::Value::E(None),
            ];
            assert_eq!(c[0].value, criterion::Value::V(v));
        } else {
            unreachable!();
        }
    }
}
<|endoftext|>


<commit_before>extern crate gtk;

use gtk::traits::*;

fn main() {
    if !gtk::init_check() {
        println!("Cannot start because GTK is not working / available");
        return;
    }

    match gtk::Window::new(gtk::WindowType::TopLevel) {
        None => println!("Unable to create a GTK window."),
        Some(window) => {
            window.set_title("Rubbem");
            window.set_window_position(gtk::WindowPosition::Center);

            window.connect_delete_event(|_, _| {
                gtk::main_quit();
                gtk::signal::Inhibit(false)
            });

            window.show_all();
            gtk::main();
        }
    }
}
<commit_msg>CG: Use new version of gtk:init() that returns a Result<commit_after>extern crate gtk;

use gtk::traits::*;

fn main() {
    match gtk::init() {
        Err(_) => println!("Cannot start because GTK is not working / available."),
        Ok(_) => gtk_main()
    }
}

fn gtk_main()
{
    match gtk::Window::new(gtk::WindowType::TopLevel) {
        None => println!("Unable to create a GTK window."),
        Some(window) => gtk_window(window)
    }
}

fn gtk_window(window: gtk::Window)
{
    window.set_title("Rubbem");
    window.set_window_position(gtk::WindowPosition::Center);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        gtk::signal::Inhibit(false)
    });

    window.show_all();
    gtk::main();
}

<|endoftext|>