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

// https://leetcode.com/problems/intervals-between-identical-elements/
pub fn get_distances(arr: Vec<i32>) -> Vec<i64> {
    let mut map: HashMap<i32, Vec<usize>> = HashMap::new();
    for (i, num) in arr.iter().enumerate() {
        map.entry(*num).or_insert(vec![]).push(i);
    }
    let mut answer = vec![0; arr.len()];
    for (i, num) in arr.iter().enumerate() {
        let mut sum: i64 = 0;
        for j in map[num].iter() {
            if i == *j {
                continue;
            }
            sum += i64::abs(i as i64 - *j as i64)
        }
        answer[i] = sum;
    }
    answer
}

fn main() {
    println!("{:?}", get_distances(vec![2, 1, 3, 1, 2, 3, 3])); // [4,2,7,2,4,4,5]
    println!("{:?}", get_distances(vec![10, 5, 10, 10])); // [5,0,3,4]
}
<commit_msg>Solve problem 2121<commit_after>use std::collections::HashMap;

// https://leetcode.com/problems/intervals-between-identical-elements/
pub fn get_distances(arr: Vec<i32>) -> Vec<i64> {
    #[derive(Debug)]
    struct S {
        sum: i64,
        size: i64,
        prefix_sums: HashMap<usize, (i64, i64)>,
    }
    let mut map: HashMap<i32, S> = HashMap::new();
    for (i, num) in arr.iter().enumerate() {
        let s = map.entry(*num).or_insert(S {
            sum: 0,
            size: 0,
            prefix_sums: HashMap::new(),
        });
        s.sum += i as i64;
        s.size += 1;
        s.prefix_sums.insert(i, (s.sum, s.size));
    }
    let mut answer = vec![0; arr.len()];
    for (i, num) in arr.iter().enumerate() {
        let s = map.get(num).unwrap();
        let (prefix_sum, prefix_size) = s.prefix_sums.get(&i).unwrap();
        // Example:
        // [1, 3, 5, 7, 9] --> list of indexes of number X
        //  left --- right
        // Index 3: |5 - 1| + |5 - 3| + |5 - 7| + |5 - 9| = 4 + 2 + 2 + 4 = 12
        //          ------left ------   ----- right -----
        // left sum : | (1 + 3) - (5 * 2) | = | 4 - 10 | = 6
        // right sum: | (7 + 9) - (5 * 2) | = | 16 - 10 | = 6
        // total sum = left sum + right sum = 6 + 6 = 12
        let left = i64::abs(prefix_sum - (i as i64 * prefix_size));
        let right = i64::abs(s.sum - prefix_sum - (i as i64 * (s.size - prefix_size)));
        answer[i] = left + right;
    }
    answer
}

fn main() {
    println!("{:?}", get_distances(vec![2, 1, 3, 1, 2, 3, 3])); // [4,2,7,2,4,4,5]
    println!("{:?}", get_distances(vec![10, 5, 10, 10])); // [5,0,3,4]
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/find-subarrays-with-equal-sum/
pub fn find_subarrays(nums: Vec<i32>) -> bool {
    todo!()
}

fn main() {
    println!("{}", find_subarrays(vec![4, 2, 4])); // true
    println!("{}", find_subarrays(vec![1, 2, 3, 4, 5])); // false
    println!("{}", find_subarrays(vec![0, 0, 0])); // true
}
<commit_msg>Solve problem 2395<commit_after>use std::collections::HashSet;

// https://leetcode.com/problems/find-subarrays-with-equal-sum/
pub fn find_subarrays(nums: Vec<i32>) -> bool {
    let mut set: HashSet<i32> = HashSet::new();
    let mut i = 0;
    while i < nums.len() - 1 {
        let sum = nums[i] + nums[i + 1];
        if set.contains(&sum) {
            return true;
        }
        set.insert(sum);
        i += 1;
    }
    false
}

fn main() {
    println!("{}", find_subarrays(vec![4, 2, 4])); // true
    println!("{}", find_subarrays(vec![1, 2, 3, 4, 5])); // false
    println!("{}", find_subarrays(vec![0, 0, 0])); // true
}
<|endoftext|>


<commit_before>use gluon::vm::types::VmTag;
use proc_macro2::{Span, TokenStream};
use syn::{
    self, Data, DataEnum, DataStruct, DeriveInput, Field, Fields, FieldsNamed, FieldsUnnamed,
    GenericParam, Generics, Ident, Lifetime, LifetimeDef, Variant,
};

pub fn derive(input: TokenStream) -> TokenStream {
    let DeriveInput {
        ident,
        data,
        generics,
        ..
    } = syn::parse2(input).expect("Input is checked by rustc");

    let tokens = match data {
        Data::Struct(ast) => derive_struct(ast, ident, generics),
        Data::Enum(ast) => derive_enum(ast, ident, generics),
        Data::Union(_) => panic!("Unions are not supported"),
    };

    tokens.into()
}

fn derive_struct(ast: DataStruct, ident: Ident, generics: Generics) -> TokenStream {
    let fields = match ast.fields {
        Fields::Named(FieldsNamed { named, .. }) => named,
        _ => panic!("Struct fields always have names"),
    };

    // lookup each field by its name and then convert to its type using the Getable
    // impl of the fields type
    let field_initializers = fields.iter().map(|field| {
        let field_ty = &field.ty;
        let ident = field
            .ident
            .as_ref()
            .expect("Struct fields always have names");
        let quoted_ident = format!("{}", quote! { #ident });

        quote! {
            #ident: if let Some(val) = data.lookup_field(vm, #quoted_ident) {
                <#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
            } else {
                panic!("Cannot find the field '{}'. Do the type definitions match?", #quoted_ident);
            }
        }
    });

    let cons = quote! {
        #ident {
            #(#field_initializers,)*
        }
    };

    gen_impl(ident, generics, cons)
}

fn derive_enum(ast: DataEnum, ident: Ident, generics: Generics) -> TokenStream {
    let cons;
    {
        let variants = ast.variants
            .iter()
            .enumerate()
            .map(|(tag, variant)| gen_variant_match(&ident, tag as VmTag, variant));

        // data contains the the data for each field of a variant; the variant of the passed value
        // is defined by the tag(), which is defined by order of the variants (the first variant is 0)
        cons = quote! {
            match data.tag() {
                #(#variants,)*
                tag => panic!("Unexpected tag: '{}'. Do the type definitions match?", tag)
            }
        };
    }

    gen_impl(ident, generics, cons)
}

fn gen_impl(ident: Ident, generics: Generics, cons_expr: TokenStream) -> TokenStream {
    // add trailing comma or add a where if there are no predicates
    let (_, ty_generics, where_clause) = generics.split_for_impl();
    let where_clause = where_clause
        .map(|clause| quote! { #clause, })
        .unwrap_or(quote! { where });

    // lifetime bounds like '__vm: 'a, 'a: '__vm (which implies => 'a == '__vm)
    // writing bounds like this is a lot easier than actually replacing all lifetimes
    // with '__vm
    let lifetime_bounds = create_lifetime_bounds(&generics);

    // generate bounds like T: Getable for every type parameter
    let getable_bounds = create_getable_bounds(&generics);

    // generate the generic params for the impl block
    // these need an additional lifetime used by Getable
    let mut generics = generics.clone();
    let lifetime = GenericParam::from(LifetimeDef::new(Lifetime::new("'__vm", Span::call_site())));
    generics.params.insert(0, lifetime);
    let (impl_generics, ..) = generics.split_for_impl();

    quote! {
        #[automatically_derived]
        #[allow(unused_attributes)]
        impl #impl_generics ::gluon::vm::api::Getable<'__vm> for #ident #ty_generics
        #where_clause #(#getable_bounds,)* #(#lifetime_bounds),*
        {
            fn from_value(vm: &'__vm ::gluon::vm::thread::Thread, variants: ::gluon::vm::Variants) -> Self {
                let data = match variants.as_ref() {
                    ::gluon::vm::api::ValueRef::Data(data) => data,
                    val => panic!("Unexpected value: '{:?}'. Do the type definitions match?", val),
                };

                #cons_expr
            }
        }
    }
}

fn gen_variant_match(ident: &Ident, tag: VmTag, variant: &Variant) -> TokenStream {
    let variant_ident = &variant.ident;

    // depending on the type of the variant we need to generate different constructors
    // for the enum
    match &variant.fields {
        Fields::Unit => quote! {
            #tag => #ident::#variant_ident
        },
        // both constructors that need to marshall values extract them by using the index
        // of the field to get the content from Data::get_variant;
        // the data variable was assigned in the function body above
        Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
            let cons = gen_tuple_cons(unnamed.into_iter().collect());

            quote! {
                #tag => #ident::#variant_ident#cons
            }
        }
        Fields::Named(FieldsNamed { named, .. }) => {
            let cons = gen_struct_cons(named.into_iter().collect());

            quote! {
                #tag => #ident::#variant_ident#cons
            }
        }
    }
}

fn gen_tuple_cons(fields: Vec<&Field>) -> TokenStream {
    let fields: Vec<_> = fields
        .into_iter()
        .enumerate()
        .map(|(idx, field)| {
            let field_ty = &field.ty;

            quote! {
                if let Some(val) = data.get_variant(#idx) {
                    <#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
                } else {
                    panic!("Enum does not contain data at index '{}'. Do the type definitions match?", #idx)
                }
            }
        })
        .collect();

    quote!{
        (#(#fields),*)
    }
}

fn gen_struct_cons(fields: Vec<&Field>) -> TokenStream {
    let fields: Vec<_> = fields
        .into_iter()
        .enumerate()
        .map(|(idx, field)| {
            let field_ty = &field.ty;
            let field_ident = field
                .ident
                .as_ref()
                .expect("Struct fields always have names");

            quote! {
                #field_ident: if let Some(val) = data.get_variant(#idx) {
                    <#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
                } else {
                    panic!("Enum does not contain data at index '{}'. Do the type definitions match?", #idx)
                }
            }
        })
        .collect();

    quote!{
        {#(#fields),*}
    }
}

fn create_getable_bounds(generics: &Generics) -> Vec<TokenStream> {
    generics
        .params
        .iter()
        .filter_map(|param| match param {
            GenericParam::Type(param) => Some(&param.ident),
            _ => None,
        })
        .map(|ty| {
            quote! {
                #ty: ::gluon::vm::api::Getable<'__vm>
            }
        })
        .collect()
}

fn create_lifetime_bounds(generics: &Generics) -> Vec<TokenStream> {
    generics
        .params
        .iter()
        .filter_map(|param| match param {
            GenericParam::Lifetime(def) => Some(&def.lifetime),
            _ => None,
        })
        .flat_map(|lifetime| vec![quote! { #lifetime: '__vm }, quote! { '__vm: #lifetime }])
        .collect()
}
<commit_msg>Remove unnecessary collects<commit_after>use gluon::vm::types::VmTag;
use proc_macro2::{Span, TokenStream};
use syn::{
    self, Data, DataEnum, DataStruct, DeriveInput, Field, Fields, FieldsNamed, FieldsUnnamed,
    GenericParam, Generics, Ident, Lifetime, LifetimeDef, Variant,
};

pub fn derive(input: TokenStream) -> TokenStream {
    let DeriveInput {
        ident,
        data,
        generics,
        ..
    } = syn::parse2(input).expect("Input is checked by rustc");

    let tokens = match data {
        Data::Struct(ast) => derive_struct(ast, ident, generics),
        Data::Enum(ast) => derive_enum(ast, ident, generics),
        Data::Union(_) => panic!("Unions are not supported"),
    };

    tokens.into()
}

fn derive_struct(ast: DataStruct, ident: Ident, generics: Generics) -> TokenStream {
    let fields = match ast.fields {
        Fields::Named(FieldsNamed { named, .. }) => named,
        _ => panic!("Struct fields always have names"),
    };

    // lookup each field by its name and then convert to its type using the Getable
    // impl of the fields type
    let field_initializers = fields.iter().map(|field| {
        let field_ty = &field.ty;
        let ident = field
            .ident
            .as_ref()
            .expect("Struct fields always have names");
        let quoted_ident = format!("{}", quote! { #ident });

        quote! {
            #ident: if let Some(val) = data.lookup_field(vm, #quoted_ident) {
                <#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
            } else {
                panic!("Cannot find the field '{}'. Do the type definitions match?", #quoted_ident);
            }
        }
    });

    let cons = quote! {
        #ident {
            #(#field_initializers,)*
        }
    };

    gen_impl(ident, generics, cons)
}

fn derive_enum(ast: DataEnum, ident: Ident, generics: Generics) -> TokenStream {
    let cons;
    {
        let variants = ast.variants
            .iter()
            .enumerate()
            .map(|(tag, variant)| gen_variant_match(&ident, tag as VmTag, variant));

        // data contains the the data for each field of a variant; the variant of the passed value
        // is defined by the tag(), which is defined by order of the variants (the first variant is 0)
        cons = quote! {
            match data.tag() {
                #(#variants,)*
                tag => panic!("Unexpected tag: '{}'. Do the type definitions match?", tag)
            }
        };
    }

    gen_impl(ident, generics, cons)
}

fn gen_impl(ident: Ident, generics: Generics, cons_expr: TokenStream) -> TokenStream {
    // add trailing comma or add a where if there are no predicates
    let (_, ty_generics, where_clause) = generics.split_for_impl();
    let where_clause = where_clause
        .map(|clause| quote! { #clause, })
        .unwrap_or(quote! { where });

    // lifetime bounds like '__vm: 'a, 'a: '__vm (which implies => 'a == '__vm)
    // writing bounds like this is a lot easier than actually replacing all lifetimes
    // with '__vm
    let lifetime_bounds = create_lifetime_bounds(&generics);

    // generate bounds like T: Getable for every type parameter
    let getable_bounds = create_getable_bounds(&generics);

    // generate the generic params for the impl block
    // these need an additional lifetime used by Getable
    let mut generics = generics.clone();
    let lifetime = GenericParam::from(LifetimeDef::new(Lifetime::new("'__vm", Span::call_site())));
    generics.params.insert(0, lifetime);
    let (impl_generics, ..) = generics.split_for_impl();

    quote! {
        #[automatically_derived]
        #[allow(unused_attributes)]
        impl #impl_generics ::gluon::vm::api::Getable<'__vm> for #ident #ty_generics
        #where_clause #(#getable_bounds,)* #(#lifetime_bounds),*
        {
            fn from_value(vm: &'__vm ::gluon::vm::thread::Thread, variants: ::gluon::vm::Variants) -> Self {
                let data = match variants.as_ref() {
                    ::gluon::vm::api::ValueRef::Data(data) => data,
                    val => panic!("Unexpected value: '{:?}'. Do the type definitions match?", val),
                };

                #cons_expr
            }
        }
    }
}

fn gen_variant_match(ident: &Ident, tag: VmTag, variant: &Variant) -> TokenStream {
    let variant_ident = &variant.ident;

    // depending on the type of the variant we need to generate different constructors
    // for the enum
    match &variant.fields {
        Fields::Unit => quote! {
            #tag => #ident::#variant_ident
        },
        // both constructors that need to marshall values extract them by using the index
        // of the field to get the content from Data::get_variant;
        // the data variable was assigned in the function body above
        Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
            let cons = gen_tuple_cons(unnamed);

            quote! {
                #tag => #ident::#variant_ident#cons
            }
        }
        Fields::Named(FieldsNamed { named, .. }) => {
            let cons = gen_struct_cons(named);

            quote! {
                #tag => #ident::#variant_ident#cons
            }
        }
    }
}

fn gen_tuple_cons<'a, I>(fields: I) -> TokenStream
where
    I: IntoIterator<Item = &'a Field>,
{
    let fields = fields.into_iter().enumerate().map(|(idx, field)| {
        let field_ty = &field.ty;

        quote! {
            if let Some(val) = data.get_variant(#idx) {
                <#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
            } else {
                panic!("Enum does not contain data at index '{}'. Do the type definitions match?", #idx)
            }
        }
    });

    quote!{
        (#(#fields),*)
    }
}

fn gen_struct_cons<'a, I>(fields: I) -> TokenStream
where
    I: IntoIterator<Item = &'a Field>,
{
    let fields = fields.into_iter().enumerate().map(|(idx, field)| {
        let field_ty = &field.ty;
        let field_ident = field
            .ident
            .as_ref()
            .expect("Struct fields always have names");

        quote! {
            #field_ident: if let Some(val) = data.get_variant(#idx) {
                <#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
            } else {
                panic!("Enum does not contain data at index '{}'. Do the type definitions match?", #idx)
            }
        }
    });

    quote!{
        {#(#fields),*}
    }
}

fn create_getable_bounds(generics: &Generics) -> Vec<TokenStream> {
    generics
        .params
        .iter()
        .filter_map(|param| match param {
            GenericParam::Type(param) => Some(&param.ident),
            _ => None,
        })
        .map(|ty| {
            quote! {
                #ty: ::gluon::vm::api::Getable<'__vm>
            }
        })
        .collect()
}

fn create_lifetime_bounds(generics: &Generics) -> Vec<TokenStream> {
    generics
        .params
        .iter()
        .filter_map(|param| match param {
            GenericParam::Lifetime(def) => Some(&def.lifetime),
            _ => None,
        })
        .flat_map(|lifetime| vec![quote! { #lifetime: '__vm }, quote! { '__vm: #lifetime }])
        .collect()
}
<|endoftext|>


<commit_before>use client::bridge::gateway::ShardMessenger;
use gateway::InterMessage;
use model::prelude::*;
use parking_lot::Mutex;
use std::sync::{
    mpsc::Sender,
    Arc
};
use typemap::ShareMap;

/// The context is a general utility struct provided on event dispatches, which
/// helps with dealing with the current "context" of the event dispatch.
/// The context also acts as a general high-level interface over the associated
/// [`Shard`] which received the event, or the low-level [`http`] module.
///
/// The context contains "shortcuts", like for interacting with the shard.
/// Methods like [`set_activity`] will unlock the shard and perform an update for
/// you to save a bit of work.
///
/// A context will only live for the event it was dispatched for. After the
/// event handler finished, it is destroyed and will not be re-used.
///
/// [`Shard`]: ../gateway/struct.Shard.html
/// [`http`]: ../http/index.html
/// [`set_activity`]: #method.set_activity
#[derive(Clone)]
pub struct Context {
    /// A clone of [`Client::data`]. Refer to its documentation for more
    /// information.
    ///
    /// [`Client::data`]: struct.Client.html#structfield.data
    pub data: Arc<Mutex<ShareMap>>,
    /// The messenger to communicate with the shard runner.
    pub shard: ShardMessenger,
    /// The ID of the shard this context is related to.
    pub shard_id: u64,
}

impl Context {
    /// Create a new Context to be passed to an event handler.
    pub(crate) fn new(
        data: Arc<Mutex<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
        }
    }

    /// Sets the current user as being [`Online`]. This maintains the current
    /// activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being online on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!online" {
    ///             ctx.online();
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn online(&self) {
        self.shard.set_status(OnlineStatus::Online);
    }

    /// Sets the current user as being [`Idle`]. This maintains the current
    /// activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being idle on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!idle" {
    ///             ctx.idle();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn idle(&self) {
        self.shard.set_status(OnlineStatus::Idle);
    }

    /// Sets the current user as being [`DoNotDisturb`]. This maintains the
    /// current activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being Do Not Disturb on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!dnd" {
    ///             ctx.dnd();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    #[inline]
    pub fn dnd(&self) {
        self.shard.set_status(OnlineStatus::DoNotDisturb);
    }

    /// Sets the current user as being [`Invisible`]. This maintains the current
    /// activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being invisible on the shard when an
    /// [`Event::Ready`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.invisible();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`Invisible`]: ../model/user/enum.OnlineStatus.html#variant.Invisible
    #[inline]
    pub fn invisible(&self) {
        self.shard.set_status(OnlineStatus::Invisible);
    }

    /// "Resets" the current user's presence, by setting the activity to `None`
    /// and the online status to [`Online`].
    ///
    /// Use [`set_presence`] for fine-grained control over individual details.
    ///
    /// # Examples
    ///
    /// Reset the presence when an [`Event::Resumed`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::event::ResumedEvent;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn resume(&self, ctx: Context, _: ResumedEvent) {
    ///         ctx.reset_presence();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Resumed`]: ../model/event/enum.Event.html#variant.Resumed
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`set_presence`]: #method.set_presence
    #[inline]
    pub fn reset_presence(&self) {
        self.shard.set_presence(None::<Activity>, OnlineStatus::Online);
    }

    /// Sets the current activity, defaulting to an online status of [`Online`].
    ///
    /// # Examples
    ///
    /// Create a command named `~setgame` that accepts a name of a game to be
    /// playing:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "model")]
    /// # fn main() {
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// use serenity::model::gateway::Activity;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         let args = msg.content.splitn(2, ' ').collect::<Vec<&str>>();
    ///
    ///         if args.len() < 2 || *unsafe { args.get_unchecked(0) } != "~setgame" {
    ///             return;
    ///         }
    ///
    ///         ctx.set_activity(Activity::playing(*unsafe { args.get_unchecked(1) }));
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// # }
    ///
    /// # #[cfg(not(feature = "model"))]
    /// # fn main() {}
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn set_activity(&self, activity: Activity) {
        self.shard.set_presence(Some(activity), OnlineStatus::Online);
    }

    /// Sets the current activity, passing in only its name. This will
    /// automatically set the current user's [`OnlineStatus`] to [`Online`], and
    /// its [`ActivityType`] as [`Playing`].
    ///
    /// Use [`reset_presence`] to clear the current activity, or
    /// [`set_presence`] for more fine-grained control.
    ///
    /// **Note**: Maximum length is 128.
    ///
    /// # Examples
    ///
    /// When an [`Event::Ready`] is received, set the activity name to `"test"`:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.set_game_name("test");
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`ActivityType`]: ../model/gateway/enum.ActivityType.html
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`OnlineStatus`]: ../model/user/enum.OnlineStatus.html
    /// [`Playing`]: ../model/gateway/enum.ActivityType.html#variant.Playing
    /// [`reset_presence`]: #method.reset_presence
    /// [`set_presence`]: #method.set_presence
    #[deprecated(since = "0.5.5", note = "Use Context::set_game")]
    #[inline]
    pub fn set_game_name(&self, game_name: &str) {
        let activity = Activity::playing(game_name);
        self.shard.set_presence(Some(activity), OnlineStatus::Online);
    }

    /// Sets the current user's presence, providing all fields to be passed.
    ///
    /// # Examples
    ///
    /// Setting the current user as having no activity and being [`Idle`]:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         ctx.set_presence(None, OnlineStatus::Idle);
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// Setting the current user as playing `"Heroes of the Storm"`, while being
    /// [`DoNotDisturb`]:
    ///
    /// ```rust,ignore
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, context: Context, _: Ready) {
    ///         use serenity::model::gateway::Activity;
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         let activity = Activity::playing("Heroes of the Storm");
    ///         let status = OnlineStatus::DoNotDisturb;
    ///
    ///         context.set_presence(Some(activity), status);
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn set_presence(&self, activity: Option<Activity>, status: OnlineStatus) {
        self.shard.set_presence(activity, status);
    }

    /// Disconnects the shard from the websocket, essentially "quiting" it.
    /// Note however that this will only exit the one which the `Context` was given.
    /// If it's just one shard that's on, then serenity will stop any further actions
    /// until [`Client::start`] and vice versa are called again.
    ///
    /// [`Client::start`]: ./struct.Client.html#method.start
    #[inline]
    pub fn quit(&self) {
        self.shard.shutdown_clean();
    }
}
<commit_msg>Revert "Remove Context::edit_profile"<commit_after>use client::bridge::gateway::ShardMessenger;
use gateway::InterMessage;
use model::prelude::*;
use parking_lot::Mutex;
use std::sync::{
    mpsc::Sender,
    Arc
};
use typemap::ShareMap;

/// The context is a general utility struct provided on event dispatches, which
/// helps with dealing with the current "context" of the event dispatch.
/// The context also acts as a general high-level interface over the associated
/// [`Shard`] which received the event, or the low-level [`http`] module.
///
/// The context contains "shortcuts", like for interacting with the shard.
/// Methods like [`set_activity`] will unlock the shard and perform an update for
/// you to save a bit of work.
///
/// A context will only live for the event it was dispatched for. After the
/// event handler finished, it is destroyed and will not be re-used.
///
/// [`Shard`]: ../gateway/struct.Shard.html
/// [`http`]: ../http/index.html
/// [`set_activity`]: #method.set_activity
#[derive(Clone)]
pub struct Context {
    /// A clone of [`Client::data`]. Refer to its documentation for more
    /// information.
    ///
    /// [`Client::data`]: struct.Client.html#structfield.data
    pub data: Arc<Mutex<ShareMap>>,
    /// The messenger to communicate with the shard runner.
    pub shard: ShardMessenger,
    /// The ID of the shard this context is related to.
    pub shard_id: u64,
}

impl Context {
    /// Create a new Context to be passed to an event handler.
    pub(crate) fn new(
        data: Arc<Mutex<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
        }
    }

    /// Edits the current user's profile settings.
    ///
    /// Refer to `EditProfile`'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the current user's username:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!changename" {
    ///             ctx.edit_profile(|mut e| {
    ///                 e.username("Edward Elric");
    ///
    ///                 e
    ///             });
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    #[cfg(feature = "builder")]
    #[deprecated(since = "0.5.6", note = "Use the http module instead.")]
    pub fn edit_profile<F: FnOnce(EditProfile) -> EditProfile>(&self, f: F) -> Result<CurrentUser> {
        let mut map = VecMap::with_capacity(2);

        feature_cache! {
            {
                let cache = CACHE.read();

                map.insert("username", Value::String(cache.user.name.clone()));

                if let Some(email) = cache.user.email.clone() {
                    map.insert("email", Value::String(email));
                }
            } else {
                let user = http::get_current_user()?;

                map.insert("username", Value::String(user.name));

                if let Some(email) = user.email {
                    map.insert("email", Value::String(email));
                }
            }
        }

        let edited = utils::vecmap_to_json_map(f(EditProfile(map)).0);

        http::edit_profile(&edited)
    }

    /// Sets the current user as being [`Online`]. This maintains the current
    /// activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being online on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!online" {
    ///             ctx.online();
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn online(&self) {
        self.shard.set_status(OnlineStatus::Online);
    }

    /// Sets the current user as being [`Idle`]. This maintains the current
    /// activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being idle on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!idle" {
    ///             ctx.idle();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn idle(&self) {
        self.shard.set_status(OnlineStatus::Idle);
    }

    /// Sets the current user as being [`DoNotDisturb`]. This maintains the
    /// current activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being Do Not Disturb on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!dnd" {
    ///             ctx.dnd();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    #[inline]
    pub fn dnd(&self) {
        self.shard.set_status(OnlineStatus::DoNotDisturb);
    }

    /// Sets the current user as being [`Invisible`]. This maintains the current
    /// activity.
    ///
    /// # Examples
    ///
    /// Set the current user to being invisible on the shard when an
    /// [`Event::Ready`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.invisible();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`Invisible`]: ../model/user/enum.OnlineStatus.html#variant.Invisible
    #[inline]
    pub fn invisible(&self) {
        self.shard.set_status(OnlineStatus::Invisible);
    }

    /// "Resets" the current user's presence, by setting the activity to `None`
    /// and the online status to [`Online`].
    ///
    /// Use [`set_presence`] for fine-grained control over individual details.
    ///
    /// # Examples
    ///
    /// Reset the presence when an [`Event::Resumed`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::event::ResumedEvent;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn resume(&self, ctx: Context, _: ResumedEvent) {
    ///         ctx.reset_presence();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Resumed`]: ../model/event/enum.Event.html#variant.Resumed
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`set_presence`]: #method.set_presence
    #[inline]
    pub fn reset_presence(&self) {
        self.shard.set_presence(None::<Activity>, OnlineStatus::Online);
    }

    /// Sets the current activity, defaulting to an online status of [`Online`].
    ///
    /// # Examples
    ///
    /// Create a command named `~setgame` that accepts a name of a game to be
    /// playing:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "model")]
    /// # fn main() {
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// use serenity::model::gateway::Activity;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         let args = msg.content.splitn(2, ' ').collect::<Vec<&str>>();
    ///
    ///         if args.len() < 2 || *unsafe { args.get_unchecked(0) } != "~setgame" {
    ///             return;
    ///         }
    ///
    ///         ctx.set_activity(Activity::playing(*unsafe { args.get_unchecked(1) }));
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// # }
    ///
    /// # #[cfg(not(feature = "model"))]
    /// # fn main() {}
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn set_activity(&self, activity: Activity) {
        self.shard.set_presence(Some(activity), OnlineStatus::Online);
    }

    /// Sets the current activity, passing in only its name. This will
    /// automatically set the current user's [`OnlineStatus`] to [`Online`], and
    /// its [`ActivityType`] as [`Playing`].
    ///
    /// Use [`reset_presence`] to clear the current activity, or
    /// [`set_presence`] for more fine-grained control.
    ///
    /// **Note**: Maximum length is 128.
    ///
    /// # Examples
    ///
    /// When an [`Event::Ready`] is received, set the activity name to `"test"`:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.set_game_name("test");
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`ActivityType`]: ../model/gateway/enum.ActivityType.html
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`OnlineStatus`]: ../model/user/enum.OnlineStatus.html
    /// [`Playing`]: ../model/gateway/enum.ActivityType.html#variant.Playing
    /// [`reset_presence`]: #method.reset_presence
    /// [`set_presence`]: #method.set_presence
    #[deprecated(since = "0.5.5", note = "Use Context::set_game")]
    #[inline]
    pub fn set_game_name(&self, game_name: &str) {
        let activity = Activity::playing(game_name);
        self.shard.set_presence(Some(activity), OnlineStatus::Online);
    }

    /// Sets the current user's presence, providing all fields to be passed.
    ///
    /// # Examples
    ///
    /// Setting the current user as having no activity and being [`Idle`]:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         ctx.set_presence(None, OnlineStatus::Idle);
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// Setting the current user as playing `"Heroes of the Storm"`, while being
    /// [`DoNotDisturb`]:
    ///
    /// ```rust,ignore
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, context: Context, _: Ready) {
    ///         use serenity::model::gateway::Activity;
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         let activity = Activity::playing("Heroes of the Storm");
    ///         let status = OnlineStatus::DoNotDisturb;
    ///
    ///         context.set_presence(Some(activity), status);
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn set_presence(&self, activity: Option<Activity>, status: OnlineStatus) {
        self.shard.set_presence(activity, status);
    }

    /// Disconnects the shard from the websocket, essentially "quiting" it.
    /// Note however that this will only exit the one which the `Context` was given.
    /// If it's just one shard that's on, then serenity will stop any further actions
    /// until [`Client::start`] and vice versa are called again.
    ///
    /// [`Client::start`]: ./struct.Client.html#method.start
    #[inline]
    pub fn quit(&self) {
        self.shard.shutdown_clean();
    }
}
<|endoftext|>


<commit_before>// Adapton uses memoization under the covers, which needs an efficient
// mechanism to search for function pointers and them for equality.
//
// Meanwhile, Rust does not provide Eq and Hash implementations for
// trait Fn.  So, to identify Rust functions as values that we can
// hash and compare, we need to bundle additional static information
// along with the function pointer as use this data as a proxy for the
// function itself.  The idea is that this information uniquely
// identifies the function pointer (i.e., two distinct functions will
// always have two distinct identities).
//
// TODO: make a macro for wrapping Fn's as FnObj's, defined below:

use std::fmt::{Debug,Formatter,Result};
use std::hash::{Hash,Hasher};
use std::rc::Rc;
use adapton_sigs::Adapton;

#[derive(Hash,Debug)]
pub struct ProgPt {
    hash:u64, // hash of all fields below:

    // Symbolic identity, in Rust semantics:
    symbol:Rc<String>, // via stringify!(...)
    module:Rc<String>, // via module!()

    // Location in local filesystem:
    file:Rc<String>,   // via file!()
    line:usize,        // via line!()
    column:usize,      // via column!()
}

pub struct FnObj<A:Adapton,Arg,Res> {
    prog_pt:ProgPt,
    fn_val:Box<Fn(&mut A, Rc<Arg>) -> Rc<Res>>,
}

impl<A:Adapton,Arg,Res> Debug for FnObj<A,Arg,Res> {
    fn fmt(&self, f: &mut Formatter) -> Result { self.prog_pt.fmt(f) }
}

impl<A:Adapton,Arg,Res> Hash for FnObj<A,Arg,Res> {
    fn hash<H>(&self, state: &mut H) where H: Hasher { self.prog_pt.hash(state) }
    //fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher { panic!("TODO") }
}
<commit_msg>stale edit: FnObj dropped from API<commit_after>// Adapton uses memoization under the covers, which needs an efficient
// mechanism to search for function pointers and them for equality.
//
// Meanwhile, Rust does not provide Eq and Hash implementations for
// trait Fn.  So, to identify Rust functions as values that we can
// hash and compare, we need to bundle additional static information
// along with the function pointer as use this data as a proxy for the
// function itself.  The idea is that this information uniquely
// identifies the function pointer (i.e., two distinct functions will
// always have two distinct identities).
//
// TODO: make a macro for wrapping Fn's as FnObj's, defined below:
use std::rc::Rc;

#[derive(Clone,Hash,Debug)]
pub struct ProgPt {
    hash:u64, // hash of all fields below:

    // Symbolic identity, in Rust semantics:
    symbol:Rc<String>, // via stringify!(...)
    module:Rc<String>, // via module!()

    // Location in local filesystem:
    file:Rc<String>,   // via file!()
    line:usize,        // via line!()
    column:usize,      // via column!()
}
<|endoftext|>


<commit_before>
use state::LuaState;

/// An interned string.  String interning guarantees that only
/// one copy of a string exists in the runtime at any given time.
pub struct InString {
  string: String,        // TODO: use &str and .as_ptr() instead?
  intern: *const String
}

impl InString {
  pub fn new(ls: &mut LuaState, s: &String) -> InString {
    let insert : bool;

    {
      let val = ls.strings.get(s);
      match val {
        Some(_) => insert = false,
        None => insert = true,
      }
    }

    if insert {
      ls.strings.insert(s.clone(), s.clone());
    }

    let x = &ls.strings[s];

    InString {
      string: s.clone(),
      intern: x as *const String
    }
  }
}

// Comparison for interned strings is just pointer comparison.
impl PartialEq for InString {
  fn eq(&self, other: &InString) -> bool {
    self.intern == other.intern
  }
}

impl Eq for InString {}

// TODO: impl Hash for InString

impl ToString for InString {
  fn to_string(&self) -> String {
    self.string.clone()
  }
}

<commit_msg>impl Hash for InString<commit_after>use std::hash::{Hash, Hasher};

use state::LuaState;

/// An interned string.  String interning guarantees that only
/// one copy of a string exists in the runtime at any given time.
pub struct InString {
  string: String,        // TODO: use &str and .as_ptr() instead?
  intern: *const String
}

impl InString {
  pub fn new(ls: &mut LuaState, s: &String) -> InString {
    let insert : bool;

    {
      let val = ls.strings.get(s);
      match val {
        Some(_) => insert = false,
        None => insert = true,
      }
    }

    if insert {
      ls.strings.insert(s.clone(), s.clone());
    }

    let x = &ls.strings[s];

    InString {
      string: s.clone(),
      intern: x as *const String
    }
  }
}

// Comparison for interned strings is just pointer comparison.
impl PartialEq for InString {
  fn eq(&self, other: &InString) -> bool {
    self.intern == other.intern
  }
}

impl Eq for InString {}

impl Hash for InString {
  fn hash<H>(&self, state: &mut H) where H: Hasher {
    self.string.hash(state)
  }
}

impl ToString for InString {
  fn to_string(&self) -> String {
    self.string.clone()
  }
}

<|endoftext|>


<commit_before>use std::io::{Result, Write};

use analysis;
use env::Env;
use super::child_properties;
use super::function;
use super::general;
use super::properties;
use super::signal;
use super::trait_impls;
use super::trampoline;

pub fn generate(w: &mut Write, env: &Env, analysis: &analysis::object::Info) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(general::uses(w, env, &analysis.imports));
    try!(general::define_object_type(w, env, &analysis.name, &analysis.c_type, &analysis.get_type,
        &analysis.supertypes));

    if generate_inherent(analysis) {
        try!(writeln!(w, ""));
        try!(write!(w, "impl {} {{", analysis.name));
        for func_analysis in &analysis.constructors() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !generate_trait(analysis) {
            for func_analysis in &analysis.methods() {
                try!(function::generate(w, env, func_analysis, false, false, 1));
            }

            for property in &analysis.properties {
                try!(properties::generate(w, env, property, false, false, 1));
            }

            for child_property in &analysis.child_properties {
                try!(child_properties::generate(w, env, child_property, false, false, 1));
            }
        }

        for func_analysis in &analysis.functions() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !generate_trait(analysis) {
            for signal_analysis in &analysis.signals {
                try!(signal::generate(w, env, signal_analysis, &analysis.trampolines, false, false, 1));
            }
        }

        try!(writeln!(w, "}}"));
    }

    try!(trait_impls::generate(w, &analysis.name, &analysis.functions, &analysis.specials));

    if generate_trait(analysis) {
        try!(writeln!(w, ""));
        try!(write!(w, "pub trait {}Ext {{", analysis.name));
        for func_analysis in &analysis.methods() {
            try!(function::generate(w, env, func_analysis, true, true, 1));
        }
        for property in &analysis.properties {
            try!(properties::generate(w, env, property, true, true, 1));
        }
        for child_property in &analysis.child_properties {
            try!(child_properties::generate(w, env, child_property, true, true, 1));
        }
        for signal_analysis in &analysis.signals {
            try!(signal::generate(w, env, signal_analysis, &analysis.trampolines, true, true, 1));
        }
        try!(writeln!(w, "}}"));

        try!(writeln!(w, ""));
        let mut extra_isa: Vec<&'static str> = Vec::new();
        if !analysis.child_properties.is_empty() { extra_isa.push(" + IsA<Container>"); }
        if analysis.has_signals() || !analysis.properties.is_empty() {
            extra_isa.push(" + IsA<glib::object::Object>");
        }
        try!(write!(w, "impl<O: IsA<{}>{}> {0}Ext for O {{", analysis.name, extra_isa.join("")));
        for func_analysis in &analysis.methods() {
            try!(function::generate(w, env, func_analysis, true, false, 1));
        }
        for property in &analysis.properties {
            try!(properties::generate(w, env, property, true, false, 1));
        }
        for child_property in &analysis.child_properties {
            try!(child_properties::generate(w, env, child_property, true, false, 1));
        }
        for signal_analysis in &analysis.signals {
            try!(signal::generate(w, env, signal_analysis, &analysis.trampolines, true, false, 1));
        }
        try!(writeln!(w, "}}"));
    }

    if !analysis.trampolines.is_empty() {
        for trampoline in &analysis.trampolines {
            try!(trampoline::generate(w, env, trampoline, generate_trait(analysis), &analysis.name));
        }
    }

    Ok(())
}

fn generate_inherent(analysis: &analysis::object::Info) -> bool {
    analysis.has_constructors || analysis.has_functions || !analysis.generate_trait
}

fn generate_trait(analysis: &analysis::object::Info) -> bool {
    analysis.generate_trait
}

pub fn generate_reexports(env: &Env, analysis: &analysis::object::Info, module_name: &str,
                          contents: &mut Vec<String>, traits: &mut Vec<String>) {
    let mut cfgs: Vec<String> = Vec::new();
    if let Some(cfg) = general::cfg_condition_string(&analysis.cfg_condition, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::version_condition_string(env, analysis.version, false, 0) {
        cfgs.push(cfg);
    }
    contents.push("".to_owned());
    contents.extend_from_slice(&cfgs);
    contents.push(format!("mod {};", module_name));
    contents.extend_from_slice(&cfgs);
    contents.push(format!("pub use self::{}::{};", module_name, analysis.name));
    if generate_trait(analysis) {
        contents.extend_from_slice(&cfgs);
        contents.push(format!("pub use self::{}::{}Ext;", module_name, analysis.name));
        for cfg in &cfgs {
            traits.push(format!("\t{}", cfg));
        }
        traits.push(format!("\tpub use super::{}Ext;", analysis.name));
    }
}
<commit_msg>Only generate Ext trait if there are methods, properties, child properties or signals<commit_after>use std::io::{Result, Write};

use analysis;
use env::Env;
use super::child_properties;
use super::function;
use super::general;
use super::properties;
use super::signal;
use super::trait_impls;
use super::trampoline;

pub fn generate(w: &mut Write, env: &Env, analysis: &analysis::object::Info) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(general::uses(w, env, &analysis.imports));
    try!(general::define_object_type(w, env, &analysis.name, &analysis.c_type, &analysis.get_type,
        &analysis.supertypes));

    if generate_inherent(analysis) {
        try!(writeln!(w, ""));
        try!(write!(w, "impl {} {{", analysis.name));
        for func_analysis in &analysis.constructors() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !generate_trait(analysis) {
            for func_analysis in &analysis.methods() {
                try!(function::generate(w, env, func_analysis, false, false, 1));
            }

            for property in &analysis.properties {
                try!(properties::generate(w, env, property, false, false, 1));
            }

            for child_property in &analysis.child_properties {
                try!(child_properties::generate(w, env, child_property, false, false, 1));
            }
        }

        for func_analysis in &analysis.functions() {
            try!(function::generate(w, env, func_analysis, false, false, 1));
        }

        if !generate_trait(analysis) {
            for signal_analysis in &analysis.signals {
                try!(signal::generate(w, env, signal_analysis, &analysis.trampolines, false, false, 1));
            }
        }

        try!(writeln!(w, "}}"));
    }

    try!(trait_impls::generate(w, &analysis.name, &analysis.functions, &analysis.specials));

    if generate_trait(analysis) {
        try!(writeln!(w, ""));
        try!(write!(w, "pub trait {}Ext {{", analysis.name));
        for func_analysis in &analysis.methods() {
            try!(function::generate(w, env, func_analysis, true, true, 1));
        }
        for property in &analysis.properties {
            try!(properties::generate(w, env, property, true, true, 1));
        }
        for child_property in &analysis.child_properties {
            try!(child_properties::generate(w, env, child_property, true, true, 1));
        }
        for signal_analysis in &analysis.signals {
            try!(signal::generate(w, env, signal_analysis, &analysis.trampolines, true, true, 1));
        }
        try!(writeln!(w, "}}"));

        try!(writeln!(w, ""));
        let mut extra_isa: Vec<&'static str> = Vec::new();
        if !analysis.child_properties.is_empty() { extra_isa.push(" + IsA<Container>"); }
        if analysis.has_signals() || !analysis.properties.is_empty() {
            extra_isa.push(" + IsA<glib::object::Object>");
        }
        try!(write!(w, "impl<O: IsA<{}>{}> {0}Ext for O {{", analysis.name, extra_isa.join("")));
        for func_analysis in &analysis.methods() {
            try!(function::generate(w, env, func_analysis, true, false, 1));
        }
        for property in &analysis.properties {
            try!(properties::generate(w, env, property, true, false, 1));
        }
        for child_property in &analysis.child_properties {
            try!(child_properties::generate(w, env, child_property, true, false, 1));
        }
        for signal_analysis in &analysis.signals {
            try!(signal::generate(w, env, signal_analysis, &analysis.trampolines, true, false, 1));
        }
        try!(writeln!(w, "}}"));
    }

    if !analysis.trampolines.is_empty() {
        for trampoline in &analysis.trampolines {
            try!(trampoline::generate(w, env, trampoline, generate_trait(analysis), &analysis.name));
        }
    }

    Ok(())
}

fn generate_inherent(analysis: &analysis::object::Info) -> bool {
    analysis.has_constructors || analysis.has_functions || !generate_trait(analysis)
}

fn generate_trait(analysis: &analysis::object::Info) -> bool {
    analysis.generate_trait && (analysis.has_methods || !analysis.properties.is_empty() || !analysis.child_properties.is_empty() || !analysis.signals.is_empty())
}

pub fn generate_reexports(env: &Env, analysis: &analysis::object::Info, module_name: &str,
                          contents: &mut Vec<String>, traits: &mut Vec<String>) {
    let mut cfgs: Vec<String> = Vec::new();
    if let Some(cfg) = general::cfg_condition_string(&analysis.cfg_condition, false, 0) {
        cfgs.push(cfg);
    }
    if let Some(cfg) = general::version_condition_string(env, analysis.version, false, 0) {
        cfgs.push(cfg);
    }
    contents.push("".to_owned());
    contents.extend_from_slice(&cfgs);
    contents.push(format!("mod {};", module_name));
    contents.extend_from_slice(&cfgs);
    contents.push(format!("pub use self::{}::{};", module_name, analysis.name));
    if generate_trait(analysis) {
        contents.extend_from_slice(&cfgs);
        contents.push(format!("pub use self::{}::{}Ext;", module_name, analysis.name));
        for cfg in &cfgs {
            traits.push(format!("\t{}", cfg));
        }
        traits.push(format!("\tpub use super::{}Ext;", analysis.name));
    }
}
<|endoftext|>


<commit_before>use std::net::SocketAddr;
use fibers::Spawn;

use HandleMessage;
use transport::{UdpTransport, UdpTransportBuilder};
use server::BaseServer;
use server::futures::BaseServerLoop;

/// UDP STUN server.
#[derive(Debug)]
pub struct UdpServer {
    bind_addr: SocketAddr,
}
impl UdpServer {
    /// Makes a new `UdpServer` instance which will bind to `bind_addr`.
    pub fn new(bind_addr: SocketAddr) -> Self {
        UdpServer { bind_addr: bind_addr }
    }

    /// Starts the UDP server with `handler`.
    pub fn start<S, H>(&self, spawner: S, handler: H) -> UdpServerLoop<H>
        where S: Spawn + Send + 'static,
              H: HandleMessage
    {
        let transport = UdpTransportBuilder::new().bind_addr(self.bind_addr).finish();
        BaseServer::start(spawner, transport, handler)
    }
}

/// `Future` that represent the loop of a UDP server for handling transactions issued by clients.
pub type UdpServerLoop<H> = BaseServerLoop<UdpTransport, H>;
<commit_msg>Make UdpServer configurable<commit_after>use std::ops::{Deref, DerefMut};
use std::net::SocketAddr;
use fibers::Spawn;

use HandleMessage;
use transport::{UdpTransport, UdpTransportBuilder};
use server::BaseServer;
use server::futures::BaseServerLoop;

/// UDP STUN server.
#[derive(Debug)]
pub struct UdpServer {
    builder: UdpTransportBuilder,
}
impl UdpServer {
    /// Makes a new `UdpServer` instance which will bind to `bind_addr`.
    pub fn new(bind_addr: SocketAddr) -> Self {
        let mut builder = UdpTransportBuilder::new();
        builder.bind_addr(bind_addr);
        UdpServer { builder: builder }
    }

    /// Starts the UDP server with `handler`.
    pub fn start<S, H>(&self, spawner: S, handler: H) -> UdpServerLoop<H>
        where S: Spawn + Send + 'static,
              H: HandleMessage
    {
        let transport = self.builder.finish();
        BaseServer::start(spawner, transport, handler)
    }
}
impl Deref for UdpServer {
    type Target = UdpTransportBuilder;
    fn deref(&self) -> &Self::Target {
        &self.builder
    }
}
impl DerefMut for UdpServer {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.builder
    }
}

/// `Future` that represent the loop of a UDP server for handling transactions issued by clients.
pub type UdpServerLoop<H> = BaseServerLoop<UdpTransport, H>;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use common::ptr_sub;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'a> {
    arena : ArenaPtr<'a>,
    ptr : * Word,
    size : WordCount
}

impl <'a> SegmentReader<'a> {

    pub unsafe fn get_start_ptr(&self) -> *Word {
        self.ptr.offset(0)
    }

    pub unsafe fn contains_interval(&self, from : *Word, to : *Word) -> bool {
        let fromAddr : uint = std::cast::transmute(from);
        let toAddr : uint = std::cast::transmute(to);
        let thisBegin : uint = std::cast::transmute(self.ptr);
        let thisEnd : uint = std::cast::transmute(self.ptr.offset(self.size as int));
        return (fromAddr >= thisBegin && toAddr <= thisEnd);
        // TODO readLimiter
    }
}

pub struct SegmentBuilder<'a> {
    reader : SegmentReader<'a>,
    id : SegmentId,
    pos : *mut Word,
}

impl <'a> SegmentBuilder<'a> {

    pub fn new<'b>(arena : *mut BuilderArena<'b>,
                   id : SegmentId,
                   ptr : *mut Word,
                   size : WordCount) -> SegmentBuilder<'b> {
        SegmentBuilder {
            reader : SegmentReader {
                arena : BuilderArenaPtr(arena),
                ptr : unsafe {std::cast::transmute(ptr)},
                size : size
            },
            id : id,
            pos : ptr,
        }
    }

    pub fn get_word_offset_to(&mut self, ptr : *mut Word) -> WordCount {
        let thisAddr : uint = self.reader.ptr.to_uint();
        let ptrAddr : uint = ptr.to_uint();
        assert!(ptrAddr >= thisAddr);
        let result = (ptrAddr - thisAddr) / BYTES_PER_WORD;
        return result;
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<*mut Word> {
        if (amount > self.reader.size - ptr_sub(self.pos, self.reader.ptr)) {
            return None;
        } else {
            let result = self.pos;
            self.pos = unsafe { self.pos.offset(amount as int) };
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.reader.size - ptr_sub(self.pos, self.reader.ptr)
    }

    #[inline]
    pub unsafe fn get_ptr_unchecked(&mut self, offset : WordCount) -> *mut Word {
        std::cast::transmute_mut_unsafe(self.reader.ptr.offset(offset as int))
    }

    #[inline]
    pub fn get_segment_id(&self) -> SegmentId { self.id }

    pub fn get_arena(&self) -> *mut BuilderArena<'a> {
        match self.reader.arena {
            BuilderArenaPtr(b) => b,
            _ => fail!()
        }
    }
}

// ----------------
// The following stuff is currently unused.

pub struct ReaderArena<'a> {
//    message : *message::MessageReader<'a>,
    segment0 : SegmentReader<'a>,

    more_segments : Option<~[SegmentReader<'a>]>
    //XXX should this be a map as in capnproto-c++?
}

pub struct BuilderArena<'a> {
    message : *mut message::MessageBuilder<'a>,
    segment0 : SegmentBuilder<'a>,
    more_segments : Option<~[~SegmentBuilder<'a>]>,
}

impl <'a> BuilderArena<'a> {

    #[inline]
    pub fn allocate(&mut self, amount : WordCount) -> (*mut SegmentBuilder<'a>, *mut Word) {
        unsafe {
            match self.segment0.allocate(amount) {
                Some(result) => { return (std::ptr::to_mut_unsafe_ptr(&mut self.segment0), result) }
                None => {}
            }

            match self.more_segments {
                Some(_) => {}
                None() => {}
            }

            fail!()
        }
    }

    pub fn get_segment(&mut self, id : SegmentId) -> *mut SegmentBuilder<'a> {
        if (id == 0) {
            std::ptr::to_mut_unsafe_ptr(&mut self.segment0)
        } else {
            fail!()
        }
    }

    pub fn get_segments_for_output<T>(&self, cont : |&[&[Word]]| -> T) -> T {
        fail!()
    }
}

pub enum ArenaPtr<'a> {
    ReaderArenaPtr(*ReaderArena<'a>),
    BuilderArenaPtr(*mut BuilderArena<'a>),
    Null
}

impl <'a> ArenaPtr<'a>  {
    pub fn try_get_segment(&self, id : SegmentId) -> *SegmentReader<'a> {
        unsafe {
            match self {
                &ReaderArenaPtr(reader) => {
                    if (id == 0) {
                        return std::ptr::to_unsafe_ptr(&(*reader).segment0);
                    } else {
                        match (*reader).more_segments {
                            None => {fail!("no segments!")}
                            Some(ref segs) => {
                                unsafe {segs.unsafe_ref(id as uint - 1)}
                            }
                        }
                    }
                }
                &BuilderArenaPtr(builder) => {
                    if (id == 0) {
                        std::ptr::to_unsafe_ptr(&(*builder).segment0.reader)
                    } else {
                        match (*builder).more_segments {
                            None => {fail!("no more segments!")}
                            Some(ref segs) => {
                               std::ptr::to_unsafe_ptr(&segs[id as uint - 1].reader)
                            }
                        }
                    }
                }
                &Null => {
                    fail!()
                }
            }
        }
    }
}
<commit_msg>addressbook example is working once again<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use common::ptr_sub;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'a> {
    arena : ArenaPtr<'a>,
    ptr : * Word,
    size : WordCount
}

impl <'a> SegmentReader<'a> {

    pub unsafe fn get_start_ptr(&self) -> *Word {
        self.ptr.offset(0)
    }

    pub unsafe fn contains_interval(&self, from : *Word, to : *Word) -> bool {
        let fromAddr : uint = std::cast::transmute(from);
        let toAddr : uint = std::cast::transmute(to);
        let thisBegin : uint = std::cast::transmute(self.ptr);
        let thisEnd : uint = std::cast::transmute(self.ptr.offset(self.size as int));
        return (fromAddr >= thisBegin && toAddr <= thisEnd);
        // TODO readLimiter
    }
}

pub struct SegmentBuilder<'a> {
    reader : SegmentReader<'a>,
    id : SegmentId,
    pos : *mut Word,
}

impl <'a> SegmentBuilder<'a> {

    pub fn new<'b>(arena : *mut BuilderArena<'b>,
                   id : SegmentId,
                   ptr : *mut Word,
                   size : WordCount) -> SegmentBuilder<'b> {
        SegmentBuilder {
            reader : SegmentReader {
                arena : BuilderArenaPtr(arena),
                ptr : unsafe {std::cast::transmute(ptr)},
                size : size
            },
            id : id,
            pos : ptr,
        }
    }

    pub fn get_word_offset_to(&mut self, ptr : *mut Word) -> WordCount {
        let thisAddr : uint = self.reader.ptr.to_uint();
        let ptrAddr : uint = ptr.to_uint();
        assert!(ptrAddr >= thisAddr);
        let result = (ptrAddr - thisAddr) / BYTES_PER_WORD;
        return result;
    }

    pub fn current_size(&self) -> WordCount {
        ptr_sub(self.pos, self.reader.ptr)
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<*mut Word> {
        if (amount > self.reader.size - self.current_size()) {
            return None;
        } else {
            let result = self.pos;
            self.pos = unsafe { self.pos.offset(amount as int) };
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.reader.size - ptr_sub(self.pos, self.reader.ptr)
    }

    #[inline]
    pub unsafe fn get_ptr_unchecked(&mut self, offset : WordCount) -> *mut Word {
        std::cast::transmute_mut_unsafe(self.reader.ptr.offset(offset as int))
    }

    #[inline]
    pub fn get_segment_id(&self) -> SegmentId { self.id }

    pub fn get_arena(&self) -> *mut BuilderArena<'a> {
        match self.reader.arena {
            BuilderArenaPtr(b) => b,
            _ => fail!()
        }
    }
}

// ----------------
// The following stuff is currently unused.

pub struct ReaderArena<'a> {
//    message : *message::MessageReader<'a>,
    segment0 : SegmentReader<'a>,

    more_segments : Option<~[SegmentReader<'a>]>
    //XXX should this be a map as in capnproto-c++?
}

pub struct BuilderArena<'a> {
    message : *mut message::MessageBuilder<'a>,
    segment0 : SegmentBuilder<'a>,
    more_segments : Option<~[~SegmentBuilder<'a>]>,
}

impl <'a> BuilderArena<'a> {

    #[inline]
    pub fn allocate(&mut self, amount : WordCount) -> (*mut SegmentBuilder<'a>, *mut Word) {
        unsafe {
            match self.segment0.allocate(amount) {
                Some(result) => { return (std::ptr::to_mut_unsafe_ptr(&mut self.segment0), result) }
                None => {}
            }

            match self.more_segments {
                Some(_) => {}
                None() => {}
            }

            fail!()
        }
    }

    pub fn get_segment(&mut self, id : SegmentId) -> *mut SegmentBuilder<'a> {
        if (id == 0) {
            std::ptr::to_mut_unsafe_ptr(&mut self.segment0)
        } else {
            fail!()
        }
    }

    pub fn get_segments_for_output<T>(&self, cont : |&[&[Word]]| -> T) -> T {
        unsafe {
            match self.more_segments {
                None => {
                    std::vec::raw::buf_as_slice::<Word, T>(
                        self.segment0.reader.ptr,
                        self.segment0.current_size(),
                        |v| cont([v]) )
                }
                Some(_) => {
                    fail!()
                }
            }
        }
    }
}

pub enum ArenaPtr<'a> {
    ReaderArenaPtr(*ReaderArena<'a>),
    BuilderArenaPtr(*mut BuilderArena<'a>),
    Null
}

impl <'a> ArenaPtr<'a>  {
    pub fn try_get_segment(&self, id : SegmentId) -> *SegmentReader<'a> {
        unsafe {
            match self {
                &ReaderArenaPtr(reader) => {
                    if (id == 0) {
                        return std::ptr::to_unsafe_ptr(&(*reader).segment0);
                    } else {
                        match (*reader).more_segments {
                            None => {fail!("no segments!")}
                            Some(ref segs) => {
                                unsafe {segs.unsafe_ref(id as uint - 1)}
                            }
                        }
                    }
                }
                &BuilderArenaPtr(builder) => {
                    if (id == 0) {
                        std::ptr::to_unsafe_ptr(&(*builder).segment0.reader)
                    } else {
                        match (*builder).more_segments {
                            None => {fail!("no more segments!")}
                            Some(ref segs) => {
                               std::ptr::to_unsafe_ptr(&segs[id as uint - 1].reader)
                            }
                        }
                    }
                }
                &Null => {
                    fail!()
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::{Error, Invalid, Outcome};

/// Check that an attestation is valid to be included in some block.
pub fn validate_attestation_for_block<T>(
    attestation_slot: u64,
    block_slot: u64,
    parent_block_slot: u64,
    min_attestation_inclusion_delay: u64,
    epoch_length: u64,
) -> Result<Outcome, Error> {
    /*
     * There is a delay before an attestation may be included in a block, quantified by
     * `slots` and defined as `min_attestation_inclusion_delay`.
     *
     * So, an attestation must be at least `min_attestation_inclusion_delay` slots "older" than the
     * block it is contained in.
     */
    verify_or!(
        attestation_slot <= block_slot.saturating_sub(min_attestation_inclusion_delay),
        reject!(Invalid::AttestationTooRecent)
    );

    /*
     * A block may not include attestations reference slots more than an epoch length + 1 prior to
     * the block slot.
     */
    verify_or!(
        attestation_slot >= parent_block_slot.saturating_sub(epoch_length + 1),
        reject!(Invalid::AttestationTooOld)
    );

    accept!()
}
<commit_msg>Implement tests for attestation validation<commit_after>use super::{Error, Invalid, Outcome};

/// Check that an attestation is valid to be included in some block.
pub fn validate_attestation_for_block(
    attestation_slot: u64,
    block_slot: u64,
    parent_block_slot: u64,
    min_attestation_inclusion_delay: u64,
    epoch_length: u64,
) -> Result<Outcome, Error> {
    /*
     * There is a delay before an attestation may be included in a block, quantified by
     * `slots` and defined as `min_attestation_inclusion_delay`.
     *
     * So, an attestation must be at least `min_attestation_inclusion_delay` slots "older" than the
     * block it is contained in.
     */
    verify_or!(
        // TODO: this differs from the spec as it does not handle underflows correctly.
        // https://github.com/sigp/lighthouse/issues/95
        attestation_slot < block_slot.saturating_sub(min_attestation_inclusion_delay - 1),
        reject!(Invalid::AttestationTooRecent)
    );

    /*
     * A block may not include attestations reference slots more than an epoch length + 1 prior to
     * the block slot.
     */
    verify_or!(
        attestation_slot >= parent_block_slot.saturating_sub(epoch_length + 1),
        reject!(Invalid::AttestationTooOld)
    );

    accept!()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_inclusion_delay_minimal() {
        let parent_block_slot = 99;
        let min_attestation_inclusion_delay = 10;
        let epoch_length = 20;
        let block_slot = 100;
        let attestation_slot = block_slot - min_attestation_inclusion_delay;

        let outcome = validate_attestation_for_block(
            attestation_slot,
            block_slot,
            parent_block_slot,
            min_attestation_inclusion_delay,
            epoch_length,
        );
        assert_eq!(outcome, Ok(Outcome::Valid));
    }

    #[test]
    fn test_inclusion_delay_maximal() {
        let parent_block_slot = 99;
        let min_attestation_inclusion_delay = 10;
        let epoch_length = 20;
        let block_slot = 100;
        let attestation_slot = block_slot - epoch_length;

        let outcome = validate_attestation_for_block(
            attestation_slot,
            block_slot,
            parent_block_slot,
            min_attestation_inclusion_delay,
            epoch_length,
        );
        assert_eq!(outcome, Ok(Outcome::Valid));
    }

    #[test]
    fn test_inclusion_delay_insufficient() {
        let parent_block_slot = 99;
        let min_attestation_inclusion_delay = 10;
        let epoch_length = 20;
        let block_slot = 100;
        let attestation_slot = block_slot - (min_attestation_inclusion_delay - 1);

        let outcome = validate_attestation_for_block(
            attestation_slot,
            block_slot,
            parent_block_slot,
            min_attestation_inclusion_delay,
            epoch_length,
        );
        assert_eq!(outcome, Ok(Outcome::Invalid(Invalid::AttestationTooRecent)));
    }

    #[test]
    fn test_inclusion_delay_first_possible_slot() {
        let min_attestation_inclusion_delay = 10;
        let epoch_length = 20;
        let block_slot = min_attestation_inclusion_delay;
        let attestation_slot = 0;
        let parent_block_slot = block_slot - 1;

        let outcome = validate_attestation_for_block(
            attestation_slot,
            block_slot,
            parent_block_slot,
            min_attestation_inclusion_delay,
            epoch_length,
        );
        assert_eq!(outcome, Ok(Outcome::Valid));
    }

    #[test]
    fn test_inclusion_delay_saturation_non_zero_slot() {
        let min_attestation_inclusion_delay = 10;
        let epoch_length = 20;
        let block_slot = min_attestation_inclusion_delay - 1;
        let parent_block_slot = block_slot - 1;
        let attestation_slot = 0;

        let outcome = validate_attestation_for_block(
            attestation_slot,
            block_slot,
            parent_block_slot,
            min_attestation_inclusion_delay,
            epoch_length,
        );
        assert_eq!(outcome, Ok(Outcome::Invalid(Invalid::AttestationTooRecent)));
    }

    #[test]
    fn test_inclusion_delay_saturation_zero_slot() {
        let min_attestation_inclusion_delay = 10;
        let epoch_length = 20;
        let block_slot = min_attestation_inclusion_delay - 1;
        let parent_block_slot = block_slot - 1;
        let attestation_slot = 0;

        let outcome = validate_attestation_for_block(
            attestation_slot,
            block_slot,
            parent_block_slot,
            min_attestation_inclusion_delay,
            epoch_length,
        );
        assert_eq!(outcome, Ok(Outcome::Invalid(Invalid::AttestationTooRecent)));
    }
}
<|endoftext|>


<commit_before>use super::super::request::Request;
use super::super::response::Response;
use super::super::middleware::{Middleware, Continue, Unwind, Status};
use super::super::alloy::Alloy;

use super::Chain;

/// The default `Chain` used by `Iron`.
/// `StackChain` runs each `Request` through all `Middleware` in its stack.
/// When it hits `Middleware` which returns `Unwind`, it passes
/// the `Request` back up through all `Middleware` it has hit so far.
pub struct StackChain {
    /// The storage used by `StackChain` to hold all `Middleware`
    /// that have been `linked` to it.
    stack: Vec<Box<Middleware + Send>>,
    exit_stack: Vec<Box<Middleware + Send>>
}

impl Clone for StackChain {
    fn clone(&self) -> StackChain {
        StackChain {
            stack: self.stack.clone(),
            exit_stack: self.exit_stack.clone()
        }
    }
}

/// `StackChain` is a `Chain`
impl Chain for StackChain {
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // The `exit_stack` will hold all `Middleware` that are passed through
        // in the enter loop. This is so we know to take exactly the same
        // path through `Middleware` in reverse order than we did on the way in.
        self.exit_stack = vec![];

        'enter: for middleware in self.stack.mut_iter() {
            match middleware.enter(request, response, alloy) {
                Unwind   => return Unwind,
                // Mark the middleware for traversal on exit.
                Continue => self.exit_stack.push(middleware.clone_box())
            }
        }

        Continue
    }

    fn chain_exit(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // Reverse the stack so we go through in the reverse order.
        // i.e. LIFO.
        self.exit_stack.reverse();
        // Call each middleware's exit handler.
        'exit: for middleware in self.exit_stack.mut_iter() {
            let _ = middleware.exit(request, response, alloy);
        }

        Continue
    }

    /// Add `Middleware` to the `Chain`.
    fn link<M: Middleware>(&mut self, middleware: M) {
        self.stack.push(box middleware);
    }

    /// Create a new instance of `StackChain`.
    fn new() -> StackChain {
        StackChain {
            stack: vec![],
            exit_stack: vec![]
        }
    }
}

#[cfg(test)]
mod test {
    pub use super::*;
    pub use super::super::super::request::Request;
    pub use super::super::super::response::Response;
    pub use super::super::super::alloy::Alloy;
    pub use super::super::super::middleware::{Middleware, Status, Continue};
    pub use std::sync::{Arc, Mutex};

    #[deriving(Clone)]
    pub struct CallCount {
        enter: Arc<Mutex<u64>>,
        exit: Arc<Mutex<u64>>
    }

    impl Middleware for CallCount {
        fn enter(&mut self, _req: &mut Request,
                 _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut enter = self.enter.lock();
            *enter += 1;
            Continue
        }

        fn exit(&mut self, _req: &mut Request,
                _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut exit = self.exit.lock();
            *exit += 1;
            Continue
        }
    }

    mod dispatch {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn calls_all_middleware_enter_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

            for _ in range(0, 10) {
                let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            }

            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }

            for (enter, exit) in enter_exits.move_iter() {
                assert_eq!(*enter.lock(), 1);
                assert_eq!(*exit.lock(), 1);
            }
        }
    }

    mod chain_enter {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 0);
        }
    }

    mod chain_exit {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 0);
        }
    }

    mod bench {
        use super::super::super::super::middleware::Middleware;

        #[deriving(Clone)]
        struct Noop;

        impl Middleware for Noop {}

        macro_rules! bench_noop_x (
            ($name:ident, $num:expr, $method:ident) => {
                #[bench]
                fn $name(b: &mut Bencher) {
                    let mut testchain: StackChain = Chain::new();
                    for _ in range(0, $num) {
                        testchain.link(Noop);
                    }
                    b.iter(|| {
                        black_box(unsafe {
                            let _ = testchain.$method(
                                uninitialized(),
                                uninitialized(),
                                uninitialized()
                            );
                        })
                    });
                }
            }
        )

        macro_rules! bench_method (
            ($method:ident) => {
                mod $method {
                    use std::mem::uninitialized;
                    use test::{Bencher, black_box};
                    use super::Noop;
                    use super::super::super::StackChain;
                    use super::super::super::super::Chain;

                    bench_noop_x!(bench_empty, 0, $method)
                    bench_noop_x!(bench_1, 1, $method)
                    bench_noop_x!(bench_2, 2, $method)
                    bench_noop_x!(bench_3, 3, $method)
                    bench_noop_x!(bench_4, 4, $method)
                    bench_noop_x!(bench_10, 10, $method)
                }
            }
        )

        bench_method!(dispatch)
        bench_method!(chain_enter)
    }
}

<commit_msg>(feat) Added FromIterator impl to StackChain<commit_after>use super::super::request::Request;
use super::super::response::Response;
use super::super::middleware::{Middleware, Continue, Unwind, Status};
use super::super::alloy::Alloy;

use super::Chain;

/// The default `Chain` used by `Iron`.
/// `StackChain` runs each `Request` through all `Middleware` in its stack.
/// When it hits `Middleware` which returns `Unwind`, it passes
/// the `Request` back up through all `Middleware` it has hit so far.
pub struct StackChain {
    /// The storage used by `StackChain` to hold all `Middleware`
    /// that have been `linked` to it.
    stack: Vec<Box<Middleware + Send>>,
    exit_stack: Vec<Box<Middleware + Send>>
}

impl Clone for StackChain {
    fn clone(&self) -> StackChain {
        StackChain {
            stack: self.stack.clone(),
            exit_stack: self.exit_stack.clone()
        }
    }
}

/// `StackChain` is a `Chain`
impl Chain for StackChain {
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // The `exit_stack` will hold all `Middleware` that are passed through
        // in the enter loop. This is so we know to take exactly the same
        // path through `Middleware` in reverse order than we did on the way in.
        self.exit_stack = vec![];

        'enter: for middleware in self.stack.mut_iter() {
            match middleware.enter(request, response, alloy) {
                Unwind   => return Unwind,
                // Mark the middleware for traversal on exit.
                Continue => self.exit_stack.push(middleware.clone_box())
            }
        }

        Continue
    }

    fn chain_exit(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // Reverse the stack so we go through in the reverse order.
        // i.e. LIFO.
        self.exit_stack.reverse();
        // Call each middleware's exit handler.
        'exit: for middleware in self.exit_stack.mut_iter() {
            let _ = middleware.exit(request, response, alloy);
        }

        Continue
    }

    /// Add `Middleware` to the `Chain`.
    fn link<M: Middleware>(&mut self, middleware: M) {
        self.stack.push(box middleware);
    }

    /// Create a new instance of `StackChain`.
    fn new() -> StackChain {
        StackChain {
            stack: vec![],
            exit_stack: vec![]
        }
    }
}

impl FromIterator<Box<Middleware + Send>> for StackChain {
    fn from_iter<T: Iterator<Box<Middleware + Send>>>(mut iterator: T) -> StackChain {
        StackChain {
            stack: iterator.collect(),
            exit_stack: vec![]
        }
    }
}

#[cfg(test)]
mod test {
    pub use super::*;
    pub use super::super::super::request::Request;
    pub use super::super::super::response::Response;
    pub use super::super::super::alloy::Alloy;
    pub use super::super::super::middleware::{Middleware, Status, Continue};
    pub use std::sync::{Arc, Mutex};

    #[deriving(Clone)]
    pub struct CallCount {
        enter: Arc<Mutex<u64>>,
        exit: Arc<Mutex<u64>>
    }

    impl Middleware for CallCount {
        fn enter(&mut self, _req: &mut Request,
                 _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut enter = self.enter.lock();
            *enter += 1;
            Continue
        }

        fn exit(&mut self, _req: &mut Request,
                _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut exit = self.exit.lock();
            *exit += 1;
            Continue
        }
    }

    mod dispatch {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn calls_all_middleware_enter_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

            for _ in range(0, 10) {
                let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            }

            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }

            for (enter, exit) in enter_exits.move_iter() {
                assert_eq!(*enter.lock(), 1);
                assert_eq!(*exit.lock(), 1);
            }
        }
    }

    mod chain_enter {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 0);
        }
    }

    mod chain_exit {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 0);
        }
    }

    mod bench {
        use super::super::super::super::middleware::Middleware;

        #[deriving(Clone)]
        struct Noop;

        impl Middleware for Noop {}

        macro_rules! bench_noop_x (
            ($name:ident, $num:expr, $method:ident) => {
                #[bench]
                fn $name(b: &mut Bencher) {
                    let mut testchain: StackChain = Chain::new();
                    for _ in range(0, $num) {
                        testchain.link(Noop);
                    }
                    b.iter(|| {
                        black_box(unsafe {
                            let _ = testchain.$method(
                                uninitialized(),
                                uninitialized(),
                                uninitialized()
                            );
                        })
                    });
                }
            }
        )

        macro_rules! bench_method (
            ($method:ident) => {
                mod $method {
                    use std::mem::uninitialized;
                    use test::{Bencher, black_box};
                    use super::Noop;
                    use super::super::super::StackChain;
                    use super::super::super::super::Chain;

                    bench_noop_x!(bench_empty, 0, $method)
                    bench_noop_x!(bench_1, 1, $method)
                    bench_noop_x!(bench_2, 2, $method)
                    bench_noop_x!(bench_3, 3, $method)
                    bench_noop_x!(bench_4, 4, $method)
                    bench_noop_x!(bench_10, 10, $method)
                }
            }
        )

        bench_method!(dispatch)
        bench_method!(chain_enter)
    }
}

<|endoftext|>