<commit_before>use std::cell::{RefCell, Ref};

use opencl;
use opencl::mem::{Buffer, CLBuffer};

use context::Context;
use matrix::Matrix;
use num::Num;

pub enum ClMatrixMode {
    In,
    Out,
    Mut,
}

pub struct ClMatrix<T: Num> {
    rows: usize,
    columns: usize,
    buffer: CLBuffer<T>,
    event: RefCell<Option<Event>>,
}

impl<T: Num> ClMatrix<T> {
    pub fn new(ctx: &Context, rows: usize, columns: usize, mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        ClMatrix {
            rows: rows,
            columns: columns,
            buffer: ctx.ctx.create_buffer(rows*columns, cl_mem_mode),
            event: RefCell::new(None),
        }
    }

    pub fn from_matrix(ctx: &Context,
                       matrix: &Matrix<T>,
                       mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        let cl_matrix =
            ClMatrix {
                rows: matrix.rows(),
                columns: matrix.columns(),
                buffer: ctx.ctx.create_buffer(matrix.rows()*matrix.columns(), cl_mem_mode),
                event: RefCell::new(None),
            };

        ctx.queue.write(&cl_matrix.buffer, &&matrix.buffer()[..], ());
        cl_matrix
    }

    pub fn get(&self, ctx: &Context) -> Matrix<T> {
        let vec = ctx.queue.get(&self.buffer, self.get_event().as_ref().map(|x| &**x));
        Matrix::from_vec(self.rows, self.columns, vec)
    }

    pub fn set(&self, ctx: &Context, matrix: &Matrix<T>) {
        ctx.queue.write(&self.buffer, &&matrix.buffer()[..], ());
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn columns(&self) -> usize {
        self.columns
    }

    fn set_event(&self, e: Event) {
        *self.event.borrow_mut() = Some(e);
    }

    fn get_event(&self) -> Option<Ref<Event>> {
        if self.event.borrow().is_some() {
            Ref::filter_map(self.event.borrow(), |o| o.as_ref())
        } else {
            None
        }
    }

    pub fn copy_to(&self, ctx: &Context, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_copy_to_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn add(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_add_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                           None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn sub(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_sub_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, event_list));
    }

    pub fn multiply(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_multiply_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, event_list));
    }

    pub fn transpose(&self, ctx: &Context, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_transpose_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &self.rows);
        kernel.set_arg(3, &self.columns);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, (self.rows, self.columns),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn dot(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dot_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.columns);
        kernel.set_arg(4, &other.columns);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel,
                                           (self.rows, other.columns),
                                           None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn max(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_max_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn min(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_min_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn dmax(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dmax_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn dmin(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dmin_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn mse(&self, ctx: &Context, train: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_mse_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &train.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.rows);
        kernel.set_arg(4, &self.columns);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), train.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel,
                                           self.columns,
                                           None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn dmse(&self, ctx: &Context, train: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dmse_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &train.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.rows);
        kernel.set_arg(4, &self.columns);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), train.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel,
                                           self.columns,
                                           None, event_list)
        };
        output.set_event(new_event);
    }
}

pub type Event = opencl::hl::Event;

#[test]
fn cl_matrix_add() {
    let ref ctx = Context::new();

    let a = Matrix::from_vec(1, 10000, (0..10000).collect());
    let b = Matrix::from_vec(1, 10000, (0..10000).map(|x| x*2).collect());

    let a_cl = ClMatrix::from_matrix(ctx, &a, ClMatrixMode::In);
    let b_cl = ClMatrix::from_matrix(ctx, &b, ClMatrixMode::In);
    let c_cl: ClMatrix<i32> = ClMatrix::new(ctx, 1, 10000, ClMatrixMode::Out);

    a_cl.add(ctx, &b_cl, &c_cl);

    let c = c_cl.get(ctx);

    for i in 0..10000 {
        assert!(c[(0, i)] == a[(0, i)] + b[(0, i)]);
    }
}

#[test]
fn cl_matrix_add_reuse() {
    let ref ctx = Context::new();

    let a = Matrix::from_vec(1, 10000, (0..10000).collect());
    let b = Matrix::from_vec(1, 10000, (0..10000).map(|x| x*2).collect());

    let a_cl = ClMatrix::from_matrix(ctx, &a, ClMatrixMode::In);
    let b_cl = ClMatrix::from_matrix(ctx, &b, ClMatrixMode::In);

    a_cl.add(ctx, &b_cl, &b_cl); // b = a+b
}
<commit_msg>Fix scoping for borrows<commit_after>use std::cell::{RefCell, Ref};

use opencl;
use opencl::mem::{Buffer, CLBuffer};

use context::Context;
use matrix::Matrix;
use num::Num;

pub enum ClMatrixMode {
    In,
    Out,
    Mut,
}

pub struct ClMatrix<T: Num> {
    rows: usize,
    columns: usize,
    buffer: CLBuffer<T>,
    event: RefCell<Option<Event>>,
}

impl<T: Num> ClMatrix<T> {
    pub fn new(ctx: &Context, rows: usize, columns: usize, mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        ClMatrix {
            rows: rows,
            columns: columns,
            buffer: ctx.ctx.create_buffer(rows*columns, cl_mem_mode),
            event: RefCell::new(None),
        }
    }

    pub fn from_matrix(ctx: &Context,
                       matrix: &Matrix<T>,
                       mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        let cl_matrix =
            ClMatrix {
                rows: matrix.rows(),
                columns: matrix.columns(),
                buffer: ctx.ctx.create_buffer(matrix.rows()*matrix.columns(), cl_mem_mode),
                event: RefCell::new(None),
            };

        ctx.queue.write(&cl_matrix.buffer, &&matrix.buffer()[..], ());
        cl_matrix
    }

    pub fn get(&self, ctx: &Context) -> Matrix<T> {
        let vec = ctx.queue.get(&self.buffer, self.get_event().as_ref().map(|x| &**x));
        Matrix::from_vec(self.rows, self.columns, vec)
    }

    pub fn set(&self, ctx: &Context, matrix: &Matrix<T>) {
        ctx.queue.write(&self.buffer, &&matrix.buffer()[..], ());
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn columns(&self) -> usize {
        self.columns
    }

    fn set_event(&self, e: Event) {
        *self.event.borrow_mut() = Some(e);
    }

    fn get_event(&self) -> Option<Ref<Event>> {
        if self.event.borrow().is_some() {
            Ref::filter_map(self.event.borrow(), |o| o.as_ref())
        } else {
            None
        }
    }

    pub fn copy_to(&self, ctx: &Context, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_copy_to_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn add(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_add_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn sub(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_sub_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn multiply(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_multiply_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn transpose(&self, ctx: &Context, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_transpose_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &self.rows);
        kernel.set_arg(3, &self.columns);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, (self.rows, self.columns),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn dot(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dot_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.columns);
        kernel.set_arg(4, &other.columns);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), other.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel,
                                           (self.rows, other.columns),
                                           None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn max(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_max_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn min(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_min_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn dmax(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dmax_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn dmin(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dmin_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        output.set_event(ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(),
                                                        None, self.get_event().as_ref().map(|x| &**x)));
    }

    pub fn mse(&self, ctx: &Context, train: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_mse_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &train.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.rows);
        kernel.set_arg(4, &self.columns);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), train.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel,
                                           self.columns,
                                           None, event_list)
        };
        output.set_event(new_event);
    }

    pub fn dmse(&self, ctx: &Context, train: &ClMatrix<T>, output: &ClMatrix<T>) {
        let kernel = ctx.program.create_kernel(format!("vector_dmse_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &train.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.rows);
        kernel.set_arg(4, &self.columns);

        let new_event = {
            let event_list: &[Option<Ref<Event>>] = &[self.get_event(), train.get_event()];
            ctx.queue.enqueue_async_kernel(&kernel,
                                           self.columns,
                                           None, event_list)
        };
        output.set_event(new_event);
    }
}

pub type Event = opencl::hl::Event;

#[test]
fn cl_matrix_add() {
    let ref ctx = Context::new();

    let a = Matrix::from_vec(1, 10000, (0..10000).collect());
    let b = Matrix::from_vec(1, 10000, (0..10000).map(|x| x*2).collect());

    let a_cl = ClMatrix::from_matrix(ctx, &a, ClMatrixMode::In);
    let b_cl = ClMatrix::from_matrix(ctx, &b, ClMatrixMode::In);
    let c_cl: ClMatrix<i32> = ClMatrix::new(ctx, 1, 10000, ClMatrixMode::Out);

    a_cl.add(ctx, &b_cl, &c_cl);

    let c = c_cl.get(ctx);

    for i in 0..10000 {
        assert!(c[(0, i)] == a[(0, i)] + b[(0, i)]);
    }
}

#[test]
fn cl_matrix_add_reuse() {
    let ref ctx = Context::new();

    let a = Matrix::from_vec(1, 10000, (0..10000).collect());
    let b = Matrix::from_vec(1, 10000, (0..10000).map(|x| x*2).collect());

    let a_cl = ClMatrix::from_matrix(ctx, &a, ClMatrixMode::In);
    let b_cl = ClMatrix::from_matrix(ctx, &b, ClMatrixMode::In);

    a_cl.add(ctx, &b_cl, &b_cl); // b = a+b
}
<|endoftext|>


<commit_before>use std::sync::{Arc, Mutex};
use typemap::ShareMap;
use ::gateway::Shard;
use ::model::*;

#[cfg(feature="cache")]
use super::CACHE;
#[cfg(feature="builder")]
use ::internal::prelude::*;
#[cfg(feature="builder")]
use ::builder::EditProfile;
#[cfg(feature="builder")]
use ::http;

/// 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_game`] 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_game`]: #method.set_game
#[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 associated shard which dispatched the event handler.
    ///
    /// Note that if you are sharding, in relevant terms, this is the shard
    /// which received the event being dispatched.
    pub shard: Arc<Mutex<Shard>>,
}

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

    /// 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::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// # client.on_message(|ctx, msg| {
    /// #     if msg.content == "!changename" {
    /// ctx.edit_profile(|p| p.username("Hakase"));
    /// #     }
    /// # });
    /// ```
    #[cfg(feature="builder")]
    pub fn edit_profile<F: FnOnce(EditProfile) -> EditProfile>(&self, f: F) -> Result<CurrentUser> {
        let mut map = Map::new();

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

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

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

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

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

        let edited = f(EditProfile(map)).0;

        http::edit_profile(&edited)
    }

    /// Sets the current user as being [`Online`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being online on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_message(|ctx, msg| {
    ///     if msg.content == "!online" {
    ///         ctx.online();
    ///     }
    /// });
    /// ```
    ///
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    pub fn online(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::Online);
    }

    /// Sets the current user as being [`Idle`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being idle on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_message(|ctx, msg| {
    ///     if msg.content == "!idle" {
    ///         ctx.idle();
    ///     }
    /// });
    /// ```
    ///
    /// [`Idle`]: ../model/enum.OnlineStatus.html#variant.Idle
    pub fn idle(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::Idle);
    }

    /// Sets the current user as being [`DoNotDisturb`]. This maintains the
    /// current game.
    ///
    /// # Examples
    ///
    /// Set the current user to being Do Not Disturb on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_message(|ctx, msg| {
    ///     if msg.content == "!dnd" {
    ///         ctx.dnd();
    ///     }
    /// });
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/enum.OnlineStatus.html#variant.DoNotDisturb
    pub fn dnd(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::DoNotDisturb);
    }

    /// Sets the current user as being [`Invisible`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being invisible on the shard when an
    /// [`Event::Ready`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_ready(|ctx, _| {
    ///     ctx.invisible();
    /// });
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`Invisible`]: ../model/enum.OnlineStatus.html#variant.Invisible
    pub fn invisible(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::Invisible);
    }

    /// "Resets" the current user's presence, by setting the game 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::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_resume(|ctx, _| {
    ///     ctx.reset_presence();
    /// });
    /// ```
    ///
    /// [`Event::Resumed`]: ../model/event/enum.Event.html#variant.Resumed
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    /// [`set_presence`]: #method.set_presence
    pub fn reset_presence(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(None, OnlineStatus::Online, false)
    }

    /// Sets the current game, 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
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// use serenity::model::Game;
    ///
    /// client.on_message(|ctx, msg| {
    ///     let args = msg.content.splitn(2, ' ').collect::<Vec<&str>>();
    ///
    ///     if args.len() < 2 || *unsafe { args.get_unchecked(0) } != "~setgame" {
    ///         return;
    ///     }
    ///
    ///     ctx.set_game(Game::playing(*unsafe { args.get_unchecked(1) }));
    /// });
    /// ```
    ///
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    pub fn set_game(&self, game: Game) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(Some(game), OnlineStatus::Online, false);
    }

    /// Sets the current game, passing in only its name. This will automatically
    /// set the current user's [`OnlineStatus`] to [`Online`], and its
    /// [`GameType`] as [`Playing`].
    ///
    /// Use [`reset_presence`] to clear the current game, or [`set_presence`]
    /// for more fine-grained control.
    ///
    /// **Note**: Maximum length is 128.
    ///
    /// # Examples
    ///
    /// When an [`Event::Ready`] is received, set the game name to `"test"`:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// client.on_ready(|ctx, _| {
    ///     ctx.set_game_name("test");
    /// });
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`GameType`]: ../model/enum.GameType.html
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    /// [`OnlineStatus`]: ../model/enum.OnlineStatus.html
    /// [`Playing`]: ../model/enum.GameType.html#variant.Playing
    /// [`reset_presence`]: #method.reset_presence
    /// [`set_presence`]: #method.set_presence
    pub fn set_game_name(&self, game_name: &str) {
        let game = Game {
            kind: GameType::Playing,
            name: game_name.to_owned(),
            url: None,
        };

        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(Some(game), OnlineStatus::Online, false);
    }

    /// Sets the current user's presence, providing all fields to be passed.
    ///
    /// # Examples
    ///
    /// Setting the current user as having no game and being [`Idle`]:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// # client.on_ready(|ctx, _| {
    /// #
    /// use serenity::model::OnlineStatus;
    ///
    /// ctx.set_presence(None, OnlineStatus::Idle, false);
    /// # });
    /// ```
    ///
    /// Setting the current user as playing `"Heroes of the Storm"`, while being
    /// [`DoNotDisturb`]:
    ///
    /// ```rust,ignore
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// # client.on_ready(|ctx, _| {
    /// #
    /// use serenity::model::{Game, OnlineStatus};
    ///
    /// let game = Game::playing("Heroes of the Storm");
    /// let status = OnlineStatus::DoNotDisturb;
    ///
    /// context.set_presence(Some(game), status, false);
    /// # });
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/enum.OnlineStatus.html#variant.DoNotDisturb
    /// [`Idle`]: ../model/enum.OnlineStatus.html#variant.Idle
    pub fn set_presence(&self,
                        game: Option<Game>,
                        status: OnlineStatus,
                        afk: bool) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(game, status, afk)
    }
}
<commit_msg>Add a `quit` function`<commit_after>use std::sync::{Arc, Mutex};
use typemap::ShareMap;
use ::gateway::Shard;
use ::model::*;

#[cfg(feature="cache")]
use super::CACHE;
#[cfg(feature="builder")]
use ::internal::prelude::*;
#[cfg(feature="builder")]
use ::builder::EditProfile;
#[cfg(feature="builder")]
use ::http;

/// 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_game`] 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_game`]: #method.set_game
#[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 associated shard which dispatched the event handler.
    ///
    /// Note that if you are sharding, in relevant terms, this is the shard
    /// which received the event being dispatched.
    pub shard: Arc<Mutex<Shard>>,
}

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

    /// 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::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// # client.on_message(|ctx, msg| {
    /// #     if msg.content == "!changename" {
    /// ctx.edit_profile(|p| p.username("Hakase"));
    /// #     }
    /// # });
    /// ```
    #[cfg(feature="builder")]
    pub fn edit_profile<F: FnOnce(EditProfile) -> EditProfile>(&self, f: F) -> Result<CurrentUser> {
        let mut map = Map::new();

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

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

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

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

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

        let edited = f(EditProfile(map)).0;

        http::edit_profile(&edited)
    }

    /// Sets the current user as being [`Online`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being online on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_message(|ctx, msg| {
    ///     if msg.content == "!online" {
    ///         ctx.online();
    ///     }
    /// });
    /// ```
    ///
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    pub fn online(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::Online);
    }

    /// Sets the current user as being [`Idle`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being idle on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_message(|ctx, msg| {
    ///     if msg.content == "!idle" {
    ///         ctx.idle();
    ///     }
    /// });
    /// ```
    ///
    /// [`Idle`]: ../model/enum.OnlineStatus.html#variant.Idle
    pub fn idle(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::Idle);
    }

    /// Sets the current user as being [`DoNotDisturb`]. This maintains the
    /// current game.
    ///
    /// # Examples
    ///
    /// Set the current user to being Do Not Disturb on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_message(|ctx, msg| {
    ///     if msg.content == "!dnd" {
    ///         ctx.dnd();
    ///     }
    /// });
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/enum.OnlineStatus.html#variant.DoNotDisturb
    pub fn dnd(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::DoNotDisturb);
    }

    /// Sets the current user as being [`Invisible`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being invisible on the shard when an
    /// [`Event::Ready`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_ready(|ctx, _| {
    ///     ctx.invisible();
    /// });
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`Invisible`]: ../model/enum.OnlineStatus.html#variant.Invisible
    pub fn invisible(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_status(OnlineStatus::Invisible);
    }

    /// "Resets" the current user's presence, by setting the game 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::Client;
    /// #
    /// # let mut client = Client::new("");
    /// client.on_resume(|ctx, _| {
    ///     ctx.reset_presence();
    /// });
    /// ```
    ///
    /// [`Event::Resumed`]: ../model/event/enum.Event.html#variant.Resumed
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    /// [`set_presence`]: #method.set_presence
    pub fn reset_presence(&self) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(None, OnlineStatus::Online, false)
    }

    /// Sets the current game, 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
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// use serenity::model::Game;
    ///
    /// client.on_message(|ctx, msg| {
    ///     let args = msg.content.splitn(2, ' ').collect::<Vec<&str>>();
    ///
    ///     if args.len() < 2 || *unsafe { args.get_unchecked(0) } != "~setgame" {
    ///         return;
    ///     }
    ///
    ///     ctx.set_game(Game::playing(*unsafe { args.get_unchecked(1) }));
    /// });
    /// ```
    ///
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    pub fn set_game(&self, game: Game) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(Some(game), OnlineStatus::Online, false);
    }

    /// Sets the current game, passing in only its name. This will automatically
    /// set the current user's [`OnlineStatus`] to [`Online`], and its
    /// [`GameType`] as [`Playing`].
    ///
    /// Use [`reset_presence`] to clear the current game, or [`set_presence`]
    /// for more fine-grained control.
    ///
    /// **Note**: Maximum length is 128.
    ///
    /// # Examples
    ///
    /// When an [`Event::Ready`] is received, set the game name to `"test"`:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// client.on_ready(|ctx, _| {
    ///     ctx.set_game_name("test");
    /// });
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`GameType`]: ../model/enum.GameType.html
    /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online
    /// [`OnlineStatus`]: ../model/enum.OnlineStatus.html
    /// [`Playing`]: ../model/enum.GameType.html#variant.Playing
    /// [`reset_presence`]: #method.reset_presence
    /// [`set_presence`]: #method.set_presence
    pub fn set_game_name(&self, game_name: &str) {
        let game = Game {
            kind: GameType::Playing,
            name: game_name.to_owned(),
            url: None,
        };

        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(Some(game), OnlineStatus::Online, false);
    }

    /// Sets the current user's presence, providing all fields to be passed.
    ///
    /// # Examples
    ///
    /// Setting the current user as having no game and being [`Idle`]:
    ///
    /// ```rust,no_run
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// # client.on_ready(|ctx, _| {
    /// #
    /// use serenity::model::OnlineStatus;
    ///
    /// ctx.set_presence(None, OnlineStatus::Idle, false);
    /// # });
    /// ```
    ///
    /// Setting the current user as playing `"Heroes of the Storm"`, while being
    /// [`DoNotDisturb`]:
    ///
    /// ```rust,ignore
    /// # use serenity::Client;
    /// #
    /// # let mut client = Client::new("");
    /// #
    /// # client.on_ready(|ctx, _| {
    /// #
    /// use serenity::model::{Game, OnlineStatus};
    ///
    /// let game = Game::playing("Heroes of the Storm");
    /// let status = OnlineStatus::DoNotDisturb;
    ///
    /// context.set_presence(Some(game), status, false);
    /// # });
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/enum.OnlineStatus.html#variant.DoNotDisturb
    /// [`Idle`]: ../model/enum.OnlineStatus.html#variant.Idle
    pub fn set_presence(&self,
                        game: Option<Game>,
                        status: OnlineStatus,
                        afk: bool) {
        let mut shard = self.shard.lock().unwrap();
        shard.set_presence(game, status, afk)
    }

    /// 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
    pub fn quit(&self) -> Result<()> {
        let mut shard = self.shard.lock().unwrap();
        shard.shutdown_clean()
    }
}
<|endoftext|>


<commit_before>pub fn reply(message: &str) -> &str {
    if is_silence(message) { "Fine. Be that way." }
    else if is_yelling(message) { "Woah, chill out!" }
    else if is_question(message) { "Sure." }
    else  { "Whatever." }
}

fn is_silence(message: &str) -> bool {
    message == ""
}

fn is_yelling(message: &str) -> bool {
    message.iter().all(|char| !char.is_lowercase())
}

fn is_question(message: &str) -> bool {
    message.ends_with("?")
}
<commit_msg>Fix whitespace nitpick.<commit_after>pub fn reply(message: &str) -> &str {
    if is_silence(message) { "Fine. Be that way." }
    else if is_yelling(message) { "Woah, chill out!" }
    else if is_question(message) { "Sure." }
    else { "Whatever." }
}

fn is_silence(message: &str) -> bool {
    message == ""
}

fn is_yelling(message: &str) -> bool {
    message.iter().all(|char| !char.is_lowercase())
}

fn is_question(message: &str) -> bool {
    message.ends_with("?")
}
<|endoftext|>


<commit_before>#[macro_export]
/// Queries the database for the names of all tables, and calls
/// [`infer_table_from_schema!`](macro.infer_table_from_schema.html) for each
/// one. A schema name can optionally be passed to load from schemas other than
/// the default. If a schema name is given, the inferred tables will be wrapped
/// in a module with the same name.
///
/// Attempting to use the `env!` or `dotenv!` macros here will not work due to
/// limitations of the Macros 1.1 system, but you can pass a string in the form
/// `"env:SOME_ENV_VAR"` or `"dotenv:SOME_ENV_VAR"` to achieve the same effect.
///
/// This macro can only be used in combination with the `diesel_codegen` or
/// `diesel_codegen_syntex` crates. It will not work on its own.
macro_rules! infer_schema {
    ($database_url: expr) => {
        mod __diesel_infer_schema {
            #[derive(InferSchema)]
            #[infer_schema_options(database_url=$database_url)]
            struct _Dummy;
        }
        pub use self::__diesel_infer_schema::*;
    };

    ($database_url: expr, $schema_name: expr) => {
        mod __diesel_infer_schema {
            #[derive(InferSchema)]
            #[infer_schema_options(database_url=$database_url, schema_name=$schema_name)]
            struct _Dummy;
        }
        pub use self::__diesel_infer_schema::*;
    };
}

#[macro_export]
/// Establishes a database connection at compile time, loads the schema
/// information about a table's columns, and invokes
/// [`table!`](macro.table.html) for you automatically. For tables in a schema
/// other than the default, the table name should be given as
/// `"schema_name.table_name"`.
///
/// Attempting to use the `env!` or `dotenv!` macros here will not work due to
/// limitations of the Macros 1.1 system, but you can pass a string in the form
/// `"env:SOME_ENV_VAR"` or `"dotenv:SOME_ENV_VAR"` to achieve the same effect.
///
/// At this time, the schema inference macros do not support types from third
/// party crates, and having any columns with a type not supported by the diesel
/// core crate will result in a compiler error (please [open an
/// issue](https://github.com/diesel-rs/diesel/issues/new) if this happens
/// unexpectedly for a type listed in our docs.)
///
/// This macro can only be used in combination with the `diesel_codegen` or
/// `diesel_codegen_syntex` crates. It will not work on its own.
macro_rules! infer_table_from_schema {
    ($database_url: expr, $table_name: expr) => {
        #[derive(InferTableFromSchema)]
        #[infer_table_from_schema_options(database_url=$database_url, table_name=$table_name)]
        struct __DieselInferTableFromSchema;
    }
}

#[macro_export]
/// This macro will read your migrations at compile time, and embed a module you can use to execute
/// them at runtime without the migration files being present on the file system. This is useful if
/// you would like to use Diesel's migration infrastructure, but want to ship a single executable
/// file (such as for embedded applications). It can also be used to apply migrations to an in
/// memory database (Diesel does this for its own test suite).
///
/// You can optionally pass the path to the migrations directory to this macro. When left
/// unspecified, Diesel Codegen will search for the migrations directory in the same way that
/// Diesel CLI does. If specified, the path should be relative to the directory where `Cargo.toml`
/// resides.
///
/// This macro can only be used in combination with the `diesel_codegen` or
/// `diesel_codegen_syntex` crates. It will not work on its own.
macro_rules! embed_migrations {
    () => {
        mod embedded_migrations {
            #[derive(EmbedMigrations)]
            struct _Dummy;
        }
    };

    ($migrations_path: expr) => {
        mod embedded_migrations {
            #[derive(EmbedMigrations)]
            #[embed_migrations_options(migrations_path=$migrations_path)]
            struct _Dummy;
        }
    }
}
<commit_msg>Add an example for the embed_migrations macro. (#854)<commit_after>#[macro_export]
/// Queries the database for the names of all tables, and calls
/// [`infer_table_from_schema!`](macro.infer_table_from_schema.html) for each
/// one. A schema name can optionally be passed to load from schemas other than
/// the default. If a schema name is given, the inferred tables will be wrapped
/// in a module with the same name.
///
/// Attempting to use the `env!` or `dotenv!` macros here will not work due to
/// limitations of the Macros 1.1 system, but you can pass a string in the form
/// `"env:SOME_ENV_VAR"` or `"dotenv:SOME_ENV_VAR"` to achieve the same effect.
///
/// This macro can only be used in combination with the `diesel_codegen` or
/// `diesel_codegen_syntex` crates. It will not work on its own.
macro_rules! infer_schema {
    ($database_url: expr) => {
        mod __diesel_infer_schema {
            #[derive(InferSchema)]
            #[infer_schema_options(database_url=$database_url)]
            struct _Dummy;
        }
        pub use self::__diesel_infer_schema::*;
    };

    ($database_url: expr, $schema_name: expr) => {
        mod __diesel_infer_schema {
            #[derive(InferSchema)]
            #[infer_schema_options(database_url=$database_url, schema_name=$schema_name)]
            struct _Dummy;
        }
        pub use self::__diesel_infer_schema::*;
    };
}

#[macro_export]
/// Establishes a database connection at compile time, loads the schema
/// information about a table's columns, and invokes
/// [`table!`](macro.table.html) for you automatically. For tables in a schema
/// other than the default, the table name should be given as
/// `"schema_name.table_name"`.
///
/// Attempting to use the `env!` or `dotenv!` macros here will not work due to
/// limitations of the Macros 1.1 system, but you can pass a string in the form
/// `"env:SOME_ENV_VAR"` or `"dotenv:SOME_ENV_VAR"` to achieve the same effect.
///
/// At this time, the schema inference macros do not support types from third
/// party crates, and having any columns with a type not supported by the diesel
/// core crate will result in a compiler error (please [open an
/// issue](https://github.com/diesel-rs/diesel/issues/new) if this happens
/// unexpectedly for a type listed in our docs.)
///
/// This macro can only be used in combination with the `diesel_codegen` or
/// `diesel_codegen_syntex` crates. It will not work on its own.
macro_rules! infer_table_from_schema {
    ($database_url: expr, $table_name: expr) => {
        #[derive(InferTableFromSchema)]
        #[infer_table_from_schema_options(database_url=$database_url, table_name=$table_name)]
        struct __DieselInferTableFromSchema;
    }
}

#[macro_export]
/// This macro will read your migrations at compile time, and embed a module you can use to execute
/// them at runtime without the migration files being present on the file system. This is useful if
/// you would like to use Diesel's migration infrastructure, but want to ship a single executable
/// file (such as for embedded applications). It can also be used to apply migrations to an in
/// memory database (Diesel does this for its own test suite).
///
/// You can optionally pass the path to the migrations directory to this macro. When left
/// unspecified, Diesel Codegen will search for the migrations directory in the same way that
/// Diesel CLI does. If specified, the path should be relative to the directory where `Cargo.toml`
/// resides.
///
/// This macro can only be used in combination with the `diesel_codegen` or
/// `diesel_codegen_syntex` crates. It will not work on its own.
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # #[macro_use] extern crate diesel_codegen;
/// # include!("src/doctest_setup.rs");
/// # table! {
/// #   users {
/// #       id -> Integer,
/// #       name -> VarChar,
/// #   }
/// # }
/// #
/// # #[cfg(feature = "postgres")]
/// # embed_migrations!("../migrations/postgresql");
/// # #[cfg(feature = "mysql")]
/// # embed_migrations!("../migrations/mysql");
/// # #[cfg(feature = "sqlite")]
/// embed_migrations!("../migrations/sqlite");
///
/// fn main() {
///     let connection = establish_connection();
///
///     // This will run the necessary migrations.
///     embedded_migrations::run(&connection);
///
///     // By default the output is thrown out. If you want to redirect it to stdout, you
///     // should call embedded_migrations::run_with_output.
///     embedded_migrations::run_with_output(&connection, &mut std::io::stdout());
/// }
/// ```
macro_rules! embed_migrations {
    () => {
        mod embedded_migrations {
            #[derive(EmbedMigrations)]
            struct _Dummy;
        }
    };

    ($migrations_path: expr) => {
        mod embedded_migrations {
            #[derive(EmbedMigrations)]
            #[embed_migrations_options(migrations_path=$migrations_path)]
            struct _Dummy;
        }
    }
}
<|endoftext|>


<commit_before>extern crate serenity;

command!(clear(_context, msg, args) {
	if args.len() == 1 {
		let countdown: u64 = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(countdown)) {
				let mut vec_id = Vec::new();
				for message in vec {
					vec_id.push(message.id);
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
	else if args.len() == 1 {
		let countdown: u64 = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let counter: u64 = match args[1].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let full = countdown + counter;
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(full)) {
				let mut vec_id = Vec::new();
				let mut i = 0;
				for message in vec {
					if i < countdown {
						vec_id.push(message.id);
					}
					i += 1;
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
});
<commit_msg>Fixes for clear<commit_after>extern crate serenity;

command!(clear(_context, msg, args) {
	if args.len() == 1 {
		let countdown: u64 = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(countdown)) {
				let mut vec_id = Vec::new();
				for message in vec {
					vec_id.push(message.id);
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
	else if args.len() == 2 {
		let countdown: u64 = match args[0].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let counter: u64 = match args[1].parse() {
			Ok(val)  => val,
			Err(_err) => 0,
		};
		let full = countdown + counter;
		for vec in msg.channel_id.messages(|g| g.before(msg.id).limit(full)) {
				let mut vec_id = Vec::new();
				let mut i = 0;
				for message in vec {
					if i < countdown {
						vec_id.push(message.id);
					}
					i += 1;
				}
				vec_id.push(msg.id);
				match msg.channel_id.delete_messages(vec_id.as_slice()) {
					Ok(val)  => val,
					Err(_err) => (),
				};
		}
		let _=msg.channel_id.send_message(|m| m.content(format!("Deleted {} messages",countdown)));
	}
});
<|endoftext|>


<commit_before>use crate::utils::printing;
use dirs;
use std::fs;
use std::path::PathBuf;

pub fn create_dir(path: &PathBuf) {
    if path.exists() {
        printing::info(format!(
            "A directory already exists at {}.",
            path.to_string_lossy()
        ))
    } else {
        printing::progress(format!("Creating directory at {}.", path.to_string_lossy()));
        match fs::create_dir_all(&path) {
            Ok(_) => (),
            Err(error) => panic!("There was a problem: {:?}", error),
        }
    }
}

pub fn remove_dir(path: &PathBuf) {
    if path.exists() {
        printing::progress(format!("Deleting directory at {}.", path.to_string_lossy()));
        match fs::remove_dir_all(&path) {
            Ok(_) => (),
            Err(error) => panic!("There was a problem: {:?}", error),
        }
    } else {
        printing::info(format!(
            "A directory doesn't exist at {}.",
            path.to_string_lossy()
        ));
    }
}

pub fn create_file(path: &PathBuf, contents: &str) {
    if path.exists() {
        printing::info(format!(
            "A file already exists at {}.",
            path.to_string_lossy()
        ))
    } else {
        printing::progress(format!("Creating file at {}.", path.to_string_lossy()));
        match fs::File::create(&path) {
            Ok(_) => {
                match fs::write(&path, &contents) {
                    Ok(_) => (),
                    Err(error) => panic!("There was a problem: {:?}", error),
                };
            }
            Err(error) => panic!("There was a problem: {:?}", error),
        }
    }
}

pub fn file_stem(file: PathBuf) -> std::string::String {
    match file.file_stem() {
        Some(file_stem) => match file_stem.to_str() {
            Some(string) => string.to_string(),
            None => panic!("There was a problem."),
        },
        None => panic!("Cannot find the file stem for {}.", file.to_string_lossy()),
    }
}

pub fn vim_plugins() -> PathBuf {
    home()
        .join(".vim")
        .join("pack")
        .join("plugins")
        .join("start")
}

pub fn repos() -> PathBuf {
    home().join("repos")
}

pub fn notes() -> PathBuf {
    project().join("src/notes")
}

pub fn public() -> PathBuf {
    project().join("public")
}

pub fn cname() -> PathBuf {
    public().join("CNAME")
}

fn home() -> PathBuf {
    match dirs::home_dir() {
        Some(directory) => directory,
        None => panic!("Cannot find the home directory."),
    }
}

fn project() -> PathBuf {
    repos().join("trevordmiller")
}
<commit_msg>Replace inheritance with explicit paths<commit_after>use crate::utils::printing;
use dirs;
use std::fs;
use std::path::PathBuf;

pub fn create_dir(path: &PathBuf) {
    if path.exists() {
        printing::info(format!(
            "A directory already exists at {}.",
            path.to_string_lossy()
        ))
    } else {
        printing::progress(format!("Creating directory at {}.", path.to_string_lossy()));
        match fs::create_dir_all(&path) {
            Ok(_) => (),
            Err(error) => panic!("There was a problem: {:?}", error),
        }
    }
}

pub fn remove_dir(path: &PathBuf) {
    if path.exists() {
        printing::progress(format!("Deleting directory at {}.", path.to_string_lossy()));
        match fs::remove_dir_all(&path) {
            Ok(_) => (),
            Err(error) => panic!("There was a problem: {:?}", error),
        }
    } else {
        printing::info(format!(
            "A directory doesn't exist at {}.",
            path.to_string_lossy()
        ));
    }
}

pub fn create_file(path: &PathBuf, contents: &str) {
    if path.exists() {
        printing::info(format!(
            "A file already exists at {}.",
            path.to_string_lossy()
        ))
    } else {
        printing::progress(format!("Creating file at {}.", path.to_string_lossy()));
        match fs::File::create(&path) {
            Ok(_) => {
                match fs::write(&path, &contents) {
                    Ok(_) => (),
                    Err(error) => panic!("There was a problem: {:?}", error),
                };
            }
            Err(error) => panic!("There was a problem: {:?}", error),
        }
    }
}

pub fn file_stem(file: PathBuf) -> std::string::String {
    match file.file_stem() {
        Some(file_stem) => match file_stem.to_str() {
            Some(string) => string.to_string(),
            None => panic!("There was a problem."),
        },
        None => panic!("Cannot find the file stem for {}.", file.to_string_lossy()),
    }
}

pub fn vim_plugins() -> PathBuf {
    home()
        .join(".vim")
        .join("pack")
        .join("plugins")
        .join("start")
}

pub fn repos() -> PathBuf {
    home().join("repos")
}

pub fn notes() -> PathBuf {
    home()
        .join("repos")
        .join("trevordmiller")
        .join("src")
        .join("notes")
}

pub fn public() -> PathBuf {
    home().join("repos").join("trevordmiller").join("public")
}

pub fn cname() -> PathBuf {
    home()
        .join("repos")
        .join("trevordmiller")
        .join("public")
        .join("CNAME")
}

fn home() -> PathBuf {
    match dirs::home_dir() {
        Some(directory) => directory,
        None => panic!("Cannot find the home directory."),
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

pub const HEAP_SIZE: usize = 1024 * 1024 * 1024;

pub const BLOCK_SIZE: usize = 32 * 1024;
pub const LINE_SIZE: usize = 256;
pub const NUM_LINES_PER_BLOCK: usize = BLOCK_SIZE / LINE_SIZE;

pub const EVAC_HEADROOM: usize = 5;

pub const MEDIUM_OBJECT: usize = LINE_SIZE;
pub const LARGE_OBJECT: usize = 8 * 1024;

pub const CICLE_TRIGGER_THRESHHOLD: f32 = 0.01;
pub const EVAC_TRIGGER_THRESHHOLD: f32 = 0.01;
<commit_msg>Add rustdoc for constants.rs<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

/// The size of the heap in bytes.
pub const HEAP_SIZE: usize = 1024 * 1024 * 1024;

/// The size of a block in bytes.
pub const BLOCK_SIZE: usize = 32 * 1024;

/// The size of a line in bytes.
pub const LINE_SIZE: usize = 256;

/// The number of lines per block.
pub const NUM_LINES_PER_BLOCK: usize = BLOCK_SIZE / LINE_SIZE;

/// The number of blocks stored into the `EvacAllocator` for evacuation.
pub const EVAC_HEADROOM: usize = 5;

/// Objects smaller than MEDIUM_OBJECT are allocated with the
/// `NormalAllocator`, otherwise the `OverflowAllocator` is used.
pub const MEDIUM_OBJECT: usize = LINE_SIZE;

/// Objects larger than LARGE_OBJECT are allocated using the `LargeObjectSpace`.
pub const LARGE_OBJECT: usize = 8 * 1024;

/// Ratio when to trigger cycle collection.
pub const CICLE_TRIGGER_THRESHHOLD: f32 = 0.01;

/// Ratio when to trigger evacuation collection.
pub const EVAC_TRIGGER_THRESHHOLD: f32 = 0.01;
<|endoftext|>


<commit_before>use rustc_serialize::json;
use std::convert::From;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io;
use std::path::PathBuf;

#[derive(Debug)]
pub enum Error {
    AuthError(String),
    Ota(OtaReason),
    ParseError(String),
    PackageError(String),
    ClientError(String),
    Config(ConfigReason),
    JsonEncode(String),
    JsonDecode(String),
    Io(io::Error)
}

impl From<json::EncoderError> for Error {
    fn from(e: json::EncoderError) -> Error {
        Error::JsonEncode(format!("{}", e))
    }
}

impl From<json::DecoderError> for Error {
    fn from(e: json::DecoderError) -> Error {
        Error::JsonDecode(format!("{}", e))
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Error {
        Error::Io(e)
    }
}

#[derive(Debug)]
pub enum OtaReason {
    CreateFile(PathBuf, io::Error),
    Client(String, String),
}

#[derive(Debug)]
pub enum ConfigReason {
    Parse(ParseReason),
    Io(io::Error),
}

#[derive(Debug)]
pub enum ParseReason {
    InvalidToml,
    InvalidSection(String),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            Error::AuthError(ref s)    => format!("Authentication error, {}", s.clone()),
            Error::Ota(ref e)          => format!("Ota error, {}", e.clone()),
            Error::ParseError(ref s)   => s.clone(),
            Error::PackageError(ref s) => s.clone(),
            Error::ClientError(ref s)  => s.clone(),
            Error::Config(ref e)       => format!("Failed to {}", e.clone()),
            Error::JsonEncode(ref e)   => format!("Failed to encode JSON: {}", e.clone()),
            Error::JsonDecode(ref e)   => format!("Failed to decode JSON: {}", e.clone()),
            Error::Io(ref e)           => format!("IO Error{:?}", e.clone()),
        };
        write!(f, "{}", inner)
    }
}

impl Display for OtaReason {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            OtaReason::CreateFile(ref f, ref e) =>
                format!("failed to create file {:?}: {}", f.clone(), e.clone()),
            OtaReason::Client(ref r, ref e) =>
                format!("the request: {},\nresults in the following error: {}", r.clone(), e.clone()),
        };
        write!(f, "{}", inner)
    }
}

impl Display for ConfigReason {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            ConfigReason::Parse(ref e) => format!("parse config: {}", e.clone()),
            ConfigReason::Io   (ref e) => format!("load config: {}", e.clone())
        };
        write!(f, "{}", inner)
    }
}

impl Display for ParseReason {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            ParseReason::InvalidToml           => "invalid toml".to_string(),
            ParseReason::InvalidSection(ref s) => format!("invalid section: {}", s),
        };
        write!(f, "{}", inner)
    }
}

#[macro_export]
macro_rules! exit {
    ($fmt:expr) => ({
        print!(concat!($fmt, "\n"));
        std::process::exit(1);
    });
    ($fmt:expr, $($arg:tt)*) => ({
        print!(concat!($fmt, "\n"), $($arg)*);
        std::process::exit(1);
    })
}
<commit_msg>Less strings for json errors.<commit_after>use rustc_serialize::json;
use std::convert::From;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io;
use std::path::PathBuf;

#[derive(Debug)]
pub enum Error {
    AuthError(String),
    Ota(OtaReason),
    ParseError(String),
    PackageError(String),
    ClientError(String),
    Config(ConfigReason),
    JsonEncode(json::EncoderError),
    JsonDecode(json::DecoderError),
    Io(io::Error)
}

impl From<json::EncoderError> for Error {
    fn from(e: json::EncoderError) -> Error {
        Error::JsonEncode(e)
    }
}

impl From<json::DecoderError> for Error {
    fn from(e: json::DecoderError) -> Error {
        Error::JsonDecode(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Error {
        Error::Io(e)
    }
}

#[derive(Debug)]
pub enum OtaReason {
    CreateFile(PathBuf, io::Error),
    Client(String, String),
}

#[derive(Debug)]
pub enum ConfigReason {
    Parse(ParseReason),
    Io(io::Error),
}

#[derive(Debug)]
pub enum ParseReason {
    InvalidToml,
    InvalidSection(String),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            Error::AuthError(ref s)    => format!("Authentication error, {}", s.clone()),
            Error::Ota(ref e)          => format!("Ota error, {}", e.clone()),
            Error::ParseError(ref s)   => s.clone(),
            Error::PackageError(ref s) => s.clone(),
            Error::ClientError(ref s)  => s.clone(),
            Error::Config(ref e)       => format!("Failed to {}", e.clone()),
            Error::JsonEncode(ref e)   => format!("Failed to encode JSON: {}", e.clone()),
            Error::JsonDecode(ref e)   => format!("Failed to decode JSON: {}", e.clone()),
            Error::Io(ref e)           => format!("IO Error{:?}", e.clone()),
        };
        write!(f, "{}", inner)
    }
}

impl Display for OtaReason {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            OtaReason::CreateFile(ref f, ref e) =>
                format!("failed to create file {:?}: {}", f.clone(), e.clone()),
            OtaReason::Client(ref r, ref e) =>
                format!("the request: {},\nresults in the following error: {}", r.clone(), e.clone()),
        };
        write!(f, "{}", inner)
    }
}

impl Display for ConfigReason {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            ConfigReason::Parse(ref e) => format!("parse config: {}", e.clone()),
            ConfigReason::Io   (ref e) => format!("load config: {}", e.clone())
        };
        write!(f, "{}", inner)
    }
}

impl Display for ParseReason {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        let inner: String = match *self {
            ParseReason::InvalidToml           => "invalid toml".to_string(),
            ParseReason::InvalidSection(ref s) => format!("invalid section: {}", s),
        };
        write!(f, "{}", inner)
    }
}

#[macro_export]
macro_rules! exit {
    ($fmt:expr) => ({
        print!(concat!($fmt, "\n"));
        std::process::exit(1);
    });
    ($fmt:expr, $($arg:tt)*) => ({
        print!(concat!($fmt, "\n"), $($arg)*);
        std::process::exit(1);
    })
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate futures;
extern crate hyper;
extern crate rand;
extern crate serde;
extern crate serde_json;
extern crate server;
extern crate tokio_core;

use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;
use serde_json::Value;

#[test]
fn test_index_url() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());
    let uri = "http://localhost:8080/facebook-ads/ads".parse().unwrap();
    let work = client.get(uri).and_then(|res| {
        res.body().concat2().and_then(move |body| {
            let v: Value = serde_json::from_slice(&body).unwrap();
            assert!(v["ads"].as_array().unwrap().len() >= 1);
            Ok(())
        })
    });
    core.run(work).unwrap();
}

#[test]
fn test_index_url_with_slash() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());
    let uri = "http://localhost:8080/facebook-ads/ads/".parse().unwrap();
    let work = client.get(uri).and_then(|res| {
        res.body().concat2().and_then(move |body| {
            let v: Value = serde_json::from_slice(&body).unwrap();
            assert!(v["ads"].as_array().unwrap().len() >= 1);
            Ok(())
        })
    });
    core.run(work).unwrap();
}

#[test]
fn test_individual_ad_url() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());
    let uri = "http://localhost:8080/facebook-ads/ads/23842729393560096"
        .parse()
        .unwrap();
    let work = client.get(uri).and_then(|res| {
        res.body().concat2().and_then(move |body| {
            let v: Value = serde_json::from_slice(&body).unwrap();
            assert_eq!(v["ads"].as_array().unwrap().len(), 1);
            Ok(())
        })
    });
    core.run(work).unwrap();
}
<commit_msg>fixes tests<commit_after>extern crate chrono;
extern crate futures;
extern crate hyper;
extern crate rand;
extern crate serde;
extern crate serde_json;
extern crate server;
extern crate tokio_core;

use futures::{Future, Stream};
use hyper::{Client, Method, Request};
use tokio_core::reactor::Core;
use serde_json::Value;
use hyper::header::{qitem, AcceptLanguage, LanguageTag};

#[test]
fn test_index_url() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());
    let uri = "http://localhost:8080/facebook-ads/ads".parse().unwrap();
    let mut req = Request::new(Method::Get, uri);
    let mut langtag: LanguageTag = Default::default();
    langtag.language = Some("en".to_owned());
    langtag.region = Some("US".to_owned());
    req.headers_mut().set(AcceptLanguage(vec![qitem(langtag)]));

    let work = client.request(req).and_then(|res| {
        res.body().concat2().and_then(move |body| {
            let v: Value = serde_json::from_slice(&body).unwrap();
            assert!(v["ads"].as_array().unwrap().len() >= 1);
            Ok(())
        })
    });
    core.run(work).unwrap();
}

#[test]
fn test_index_url_with_slash() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());
    let uri = "http://localhost:8080/facebook-ads/ads/".parse().unwrap();
    let mut req = Request::new(Method::Get, uri);
    let mut langtag: LanguageTag = Default::default();
    langtag.language = Some("en".to_owned());
    langtag.region = Some("US".to_owned());
    req.headers_mut().set(AcceptLanguage(vec![qitem(langtag)]));

    let work = client.request(req).and_then(|res| {
        res.body().concat2().and_then(move |body| {
            let v: Value = serde_json::from_slice(&body).unwrap();
            assert!(v["ads"].as_array().unwrap().len() >= 1);
            Ok(())
        })
    });
    core.run(work).unwrap();
}

#[test]
fn test_individual_ad_url() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());
    let uri = "http://localhost:8080/facebook-ads/ads/23842729393560096"
        .parse()
        .unwrap();

    let mut req = Request::new(Method::Get, uri);
    let mut langtag: LanguageTag = Default::default();
    langtag.language = Some("en".to_owned());
    langtag.region = Some("US".to_owned());
    req.headers_mut().set(AcceptLanguage(vec![qitem(langtag)]));

    let work = client.request(req).and_then(|res| {
        res.body().concat2().and_then(move |body| {
            let v: Value = serde_json::from_slice(&body).unwrap();
            assert_eq!(v["ads"].as_array().unwrap().len(), 1);
            Ok(())
        })
    });
    core.run(work).unwrap();
}
<|endoftext|>


<commit_before>use std::{collections::BTreeSet, fmt, io};

use html5ever::{
    local_name, namespace_url, ns, parse_fragment,
    serialize::{serialize, Serialize, SerializeOpts, Serializer, TraversalScope},
    tendril::{StrTendril, TendrilSink},
    tree_builder::{NodeOrText, TreeSink},
    Attribute, ParseOpts, QualName,
};
use tracing::debug;

/// An HTML fragment.
///
/// To get the serialized HTML, use its `Display` implementation.
#[derive(Debug)]
pub struct Fragment {
    pub nodes: Vec<Node>,
}

impl Fragment {
    /// Construct a new `Fragment` by parsing the given HTML.
    pub fn parse_html(html: &str) -> Self {
        let sink = Self::default();
        let mut parser = parse_fragment(
            sink,
            ParseOpts::default(),
            QualName::new(None, ns!(html), local_name!("div")),
            Vec::new(),
        );
        parser.process(html.into());
        parser.finish()
    }

    /// Construct a new `Node` with the given data and add it to this `Fragment`.
    ///
    /// Returns the index of the new node.
    pub fn new_node(&mut self, data: NodeData) -> usize {
        self.nodes.push(Node::new(data));
        self.nodes.len() - 1
    }

    /// Append the given node to the given parent in this `Fragment`.
    ///
    /// The node is detached from its previous position.
    pub fn append_node(&mut self, parent_id: usize, node_id: usize) {
        self.detach(node_id);

        self.nodes[node_id].parent = Some(parent_id);
        if let Some(last_child) = self.nodes[parent_id].last_child.take() {
            self.nodes[node_id].prev_sibling = Some(last_child);
            self.nodes[last_child].next_sibling = Some(node_id);
        } else {
            self.nodes[parent_id].first_child = Some(node_id);
        }
        self.nodes[parent_id].last_child = Some(node_id);
    }

    /// Insert the given node before the given sibling in this `Fragment`.
    ///
    /// The node is detached from its previous position.
    pub fn insert_before(&mut self, sibling_id: usize, node_id: usize) {
        self.detach(node_id);

        self.nodes[node_id].parent = self.nodes[sibling_id].parent;
        self.nodes[node_id].next_sibling = Some(sibling_id);
        if let Some(prev_sibling) = self.nodes[sibling_id].prev_sibling.take() {
            self.nodes[node_id].prev_sibling = Some(prev_sibling);
            self.nodes[prev_sibling].next_sibling = Some(node_id);
        } else if let Some(parent) = self.nodes[sibling_id].parent {
            self.nodes[parent].first_child = Some(node_id);
        }
        self.nodes[sibling_id].prev_sibling = Some(node_id);
    }

    /// Detach the given node from this `Fragment`.
    pub fn detach(&mut self, node_id: usize) {
        let (parent, prev_sibling, next_sibling) = {
            let node = &mut self.nodes[node_id];
            (node.parent.take(), node.prev_sibling.take(), node.next_sibling.take())
        };

        if let Some(next_sibling) = next_sibling {
            self.nodes[next_sibling].prev_sibling = prev_sibling;
        } else if let Some(parent) = parent {
            self.nodes[parent].last_child = prev_sibling;
        }

        if let Some(prev_sibling) = prev_sibling {
            self.nodes[prev_sibling].next_sibling = next_sibling;
        } else if let Some(parent) = parent {
            self.nodes[parent].first_child = next_sibling;
        }
    }
}

impl Default for Fragment {
    fn default() -> Self {
        Self { nodes: vec![Node::new(NodeData::Document)] }
    }
}

impl TreeSink for Fragment {
    type Handle = usize;
    type Output = Self;

    fn finish(self) -> Self::Output {
        self
    }

    fn parse_error(&mut self, msg: std::borrow::Cow<'static, str>) {
        debug!("HTML parse error: {msg}");
    }

    fn get_document(&mut self) -> Self::Handle {
        0
    }

    fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> html5ever::ExpandedName<'a> {
        self.nodes[*target].as_element().expect("not an element").name.expanded()
    }

    fn create_element(
        &mut self,
        name: QualName,
        attrs: Vec<Attribute>,
        _flags: html5ever::tree_builder::ElementFlags,
    ) -> Self::Handle {
        self.new_node(NodeData::Element(ElementData { name, attrs: attrs.into_iter().collect() }))
    }

    fn create_comment(&mut self, _text: StrTendril) -> Self::Handle {
        self.new_node(NodeData::Other)
    }

    fn create_pi(&mut self, _target: StrTendril, _data: StrTendril) -> Self::Handle {
        self.new_node(NodeData::Other)
    }

    fn append(&mut self, parent: &Self::Handle, child: NodeOrText<Self::Handle>) {
        match child {
            NodeOrText::AppendNode(index) => self.append_node(*parent, index),
            NodeOrText::AppendText(text) => {
                // If the previous sibling is also text, add this text to it.
                if let Some(sibling) =
                    self.nodes[*parent].last_child.and_then(|child| self.nodes[child].as_text_mut())
                {
                    sibling.push_tendril(&text);
                } else {
                    let index = self.new_node(NodeData::Text(text));
                    self.append_node(*parent, index);
                }
            }
        }
    }

    fn append_based_on_parent_node(
        &mut self,
        element: &Self::Handle,
        prev_element: &Self::Handle,
        child: NodeOrText<Self::Handle>,
    ) {
        if self.nodes[*element].parent.is_some() {
            self.append_before_sibling(element, child);
        } else {
            self.append(prev_element, child);
        }
    }

    fn append_doctype_to_document(
        &mut self,
        _name: StrTendril,
        _public_id: StrTendril,
        _system_id: StrTendril,
    ) {
    }

    fn get_template_contents(&mut self, target: &Self::Handle) -> Self::Handle {
        *target
    }

    fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool {
        x == y
    }

    fn set_quirks_mode(&mut self, _mode: html5ever::tree_builder::QuirksMode) {}

    fn append_before_sibling(
        &mut self,
        sibling: &Self::Handle,
        new_node: NodeOrText<Self::Handle>,
    ) {
        match new_node {
            NodeOrText::AppendNode(index) => self.insert_before(*sibling, index),
            NodeOrText::AppendText(text) => {
                // If the previous sibling is also text, add this text to it.
                if let Some(prev_text) = self.nodes[*sibling]
                    .prev_sibling
                    .and_then(|prev| self.nodes[prev].as_text_mut())
                {
                    prev_text.push_tendril(&text);
                } else {
                    let index = self.new_node(NodeData::Text(text));
                    self.insert_before(*sibling, index);
                }
            }
        }
    }

    fn add_attrs_if_missing(&mut self, target: &Self::Handle, attrs: Vec<Attribute>) {
        let target = self.nodes[*target].as_element_mut().unwrap();
        target.attrs.extend(attrs.into_iter());
    }

    fn remove_from_parent(&mut self, target: &Self::Handle) {
        self.detach(*target);
    }

    fn reparent_children(&mut self, node: &Self::Handle, new_parent: &Self::Handle) {
        let mut next_child = self.nodes[*node].first_child;
        while let Some(child) = next_child {
            next_child = self.nodes[child].next_sibling;
            self.append_node(*new_parent, child);
        }
    }
}

impl Serialize for Fragment {
    fn serialize<S>(&self, serializer: &mut S, traversal_scope: TraversalScope) -> io::Result<()>
    where
        S: Serializer,
    {
        match traversal_scope {
            TraversalScope::IncludeNode => {
                let root = self.nodes[0].first_child.unwrap();

                let mut next_child = self.nodes[root].first_child;
                while let Some(child) = next_child {
                    let child = &self.nodes[child];
                    child.serialize(self, serializer)?;
                    next_child = child.next_sibling;
                }

                Ok(())
            }
            TraversalScope::ChildrenOnly(_) => Ok(()),
        }
    }
}

impl fmt::Display for Fragment {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut u8_vec = Vec::new();
        serialize(
            &mut u8_vec,
            self,
            SerializeOpts { traversal_scope: TraversalScope::IncludeNode, ..Default::default() },
        )
        .unwrap();

        f.write_str(&String::from_utf8(u8_vec).unwrap())?;

        Ok(())
    }
}

/// An HTML node.
#[derive(Debug)]
pub struct Node {
    pub parent: Option<usize>,
    pub prev_sibling: Option<usize>,
    pub next_sibling: Option<usize>,
    pub first_child: Option<usize>,
    pub last_child: Option<usize>,
    pub data: NodeData,
}

impl Node {
    /// Constructs a new `Node` with the given data.
    pub fn new(data: NodeData) -> Self {
        Self {
            parent: None,
            prev_sibling: None,
            next_sibling: None,
            first_child: None,
            last_child: None,
            data,
        }
    }

    /// Returns the `ElementData` of this `Node` if it is a `NodeData::Element`.
    pub fn as_element(&self) -> Option<&ElementData> {
        match &self.data {
            NodeData::Element(data) => Some(data),
            _ => None,
        }
    }

    /// Returns the mutable `ElementData` of this `Node` if it is a `NodeData::Element`.
    pub fn as_element_mut(&mut self) -> Option<&mut ElementData> {
        match &mut self.data {
            NodeData::Element(data) => Some(data),
            _ => None,
        }
    }

    /// Returns the mutable text content of this `Node`, if it is a `NodeData::Text`.
    pub fn as_text_mut(&mut self) -> Option<&mut StrTendril> {
        match &mut self.data {
            NodeData::Text(data) => Some(data),
            _ => None,
        }
    }
}

impl Node {
    pub fn serialize<S>(&self, fragment: &Fragment, serializer: &mut S) -> io::Result<()>
    where
        S: Serializer,
    {
        match &self.data {
            NodeData::Element(ref data) => {
                serializer.start_elem(
                    data.name.clone(),
                    data.attrs.iter().map(|attr| (&attr.name, &*attr.value)),
                )?;

                let mut next_child = self.first_child;
                while let Some(child) = next_child {
                    let child = &fragment.nodes[child];
                    child.serialize(fragment, serializer)?;
                    next_child = child.next_sibling;
                }

                serializer.end_elem(data.name.clone())?;

                Ok(())
            }
            NodeData::Document => {
                let mut next_child = self.first_child;
                while let Some(child) = next_child {
                    let child = &fragment.nodes[child];
                    child.serialize(fragment, serializer)?;
                    next_child = child.next_sibling;
                }

                Ok(())
            }
            NodeData::Text(ref text) => serializer.write_text(&**text),
            _ => Ok(()),
        }
    }
}

/// The data of a `Node`.
#[derive(Debug)]
pub enum NodeData {
    /// The root node of the `Fragment`.
    Document,

    /// A text node.
    Text(StrTendril),

    /// An HTML element (aka a tag).
    Element(ElementData),

    /// Other types (comment, processing instruction, …).
    Other,
}

/// The data of an HTML element.
#[derive(Debug)]
pub struct ElementData {
    /// The qualified name of the element.
    pub name: QualName,

    /// The attributes of the element.
    pub attrs: BTreeSet<Attribute>,
}

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

    #[test]
    fn sanity() {
        let html = "\

Title
\

\

This is some text
\

\
        ";
        assert_eq!(Fragment::parse_html(html).to_string(), html);

        assert_eq!(Fragment::parse_html("").to_string(), "");
    }
}
<commit_msg>events: Remove needless borrow<commit_after>use std::{collections::BTreeSet, fmt, io};

use html5ever::{
    local_name, namespace_url, ns, parse_fragment,
    serialize::{serialize, Serialize, SerializeOpts, Serializer, TraversalScope},
    tendril::{StrTendril, TendrilSink},
    tree_builder::{NodeOrText, TreeSink},
    Attribute, ParseOpts, QualName,
};
use tracing::debug;

/// An HTML fragment.
///
/// To get the serialized HTML, use its `Display` implementation.
#[derive(Debug)]
pub struct Fragment {
    pub nodes: Vec<Node>,
}

impl Fragment {
    /// Construct a new `Fragment` by parsing the given HTML.
    pub fn parse_html(html: &str) -> Self {
        let sink = Self::default();
        let mut parser = parse_fragment(
            sink,
            ParseOpts::default(),
            QualName::new(None, ns!(html), local_name!("div")),
            Vec::new(),
        );
        parser.process(html.into());
        parser.finish()
    }

    /// Construct a new `Node` with the given data and add it to this `Fragment`.
    ///
    /// Returns the index of the new node.
    pub fn new_node(&mut self, data: NodeData) -> usize {
        self.nodes.push(Node::new(data));
        self.nodes.len() - 1
    }

    /// Append the given node to the given parent in this `Fragment`.
    ///
    /// The node is detached from its previous position.
    pub fn append_node(&mut self, parent_id: usize, node_id: usize) {
        self.detach(node_id);

        self.nodes[node_id].parent = Some(parent_id);
        if let Some(last_child) = self.nodes[parent_id].last_child.take() {
            self.nodes[node_id].prev_sibling = Some(last_child);
            self.nodes[last_child].next_sibling = Some(node_id);
        } else {
            self.nodes[parent_id].first_child = Some(node_id);
        }
        self.nodes[parent_id].last_child = Some(node_id);
    }

    /// Insert the given node before the given sibling in this `Fragment`.
    ///
    /// The node is detached from its previous position.
    pub fn insert_before(&mut self, sibling_id: usize, node_id: usize) {
        self.detach(node_id);

        self.nodes[node_id].parent = self.nodes[sibling_id].parent;
        self.nodes[node_id].next_sibling = Some(sibling_id);
        if let Some(prev_sibling) = self.nodes[sibling_id].prev_sibling.take() {
            self.nodes[node_id].prev_sibling = Some(prev_sibling);
            self.nodes[prev_sibling].next_sibling = Some(node_id);
        } else if let Some(parent) = self.nodes[sibling_id].parent {
            self.nodes[parent].first_child = Some(node_id);
        }
        self.nodes[sibling_id].prev_sibling = Some(node_id);
    }

    /// Detach the given node from this `Fragment`.
    pub fn detach(&mut self, node_id: usize) {
        let (parent, prev_sibling, next_sibling) = {
            let node = &mut self.nodes[node_id];
            (node.parent.take(), node.prev_sibling.take(), node.next_sibling.take())
        };

        if let Some(next_sibling) = next_sibling {
            self.nodes[next_sibling].prev_sibling = prev_sibling;
        } else if let Some(parent) = parent {
            self.nodes[parent].last_child = prev_sibling;
        }

        if let Some(prev_sibling) = prev_sibling {
            self.nodes[prev_sibling].next_sibling = next_sibling;
        } else if let Some(parent) = parent {
            self.nodes[parent].first_child = next_sibling;
        }
    }
}

impl Default for Fragment {
    fn default() -> Self {
        Self { nodes: vec![Node::new(NodeData::Document)] }
    }
}

impl TreeSink for Fragment {
    type Handle = usize;
    type Output = Self;

    fn finish(self) -> Self::Output {
        self
    }

    fn parse_error(&mut self, msg: std::borrow::Cow<'static, str>) {
        debug!("HTML parse error: {msg}");
    }

    fn get_document(&mut self) -> Self::Handle {
        0
    }

    fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> html5ever::ExpandedName<'a> {
        self.nodes[*target].as_element().expect("not an element").name.expanded()
    }

    fn create_element(
        &mut self,
        name: QualName,
        attrs: Vec<Attribute>,
        _flags: html5ever::tree_builder::ElementFlags,
    ) -> Self::Handle {
        self.new_node(NodeData::Element(ElementData { name, attrs: attrs.into_iter().collect() }))
    }

    fn create_comment(&mut self, _text: StrTendril) -> Self::Handle {
        self.new_node(NodeData::Other)
    }

    fn create_pi(&mut self, _target: StrTendril, _data: StrTendril) -> Self::Handle {
        self.new_node(NodeData::Other)
    }

    fn append(&mut self, parent: &Self::Handle, child: NodeOrText<Self::Handle>) {
        match child {
            NodeOrText::AppendNode(index) => self.append_node(*parent, index),
            NodeOrText::AppendText(text) => {
                // If the previous sibling is also text, add this text to it.
                if let Some(sibling) =
                    self.nodes[*parent].last_child.and_then(|child| self.nodes[child].as_text_mut())
                {
                    sibling.push_tendril(&text);
                } else {
                    let index = self.new_node(NodeData::Text(text));
                    self.append_node(*parent, index);
                }
            }
        }
    }

    fn append_based_on_parent_node(
        &mut self,
        element: &Self::Handle,
        prev_element: &Self::Handle,
        child: NodeOrText<Self::Handle>,
    ) {
        if self.nodes[*element].parent.is_some() {
            self.append_before_sibling(element, child);
        } else {
            self.append(prev_element, child);
        }
    }

    fn append_doctype_to_document(
        &mut self,
        _name: StrTendril,
        _public_id: StrTendril,
        _system_id: StrTendril,
    ) {
    }

    fn get_template_contents(&mut self, target: &Self::Handle) -> Self::Handle {
        *target
    }

    fn same_node(&self, x: &Self::Handle, y: &Self::Handle) -> bool {
        x == y
    }

    fn set_quirks_mode(&mut self, _mode: html5ever::tree_builder::QuirksMode) {}

    fn append_before_sibling(
        &mut self,
        sibling: &Self::Handle,
        new_node: NodeOrText<Self::Handle>,
    ) {
        match new_node {
            NodeOrText::AppendNode(index) => self.insert_before(*sibling, index),
            NodeOrText::AppendText(text) => {
                // If the previous sibling is also text, add this text to it.
                if let Some(prev_text) = self.nodes[*sibling]
                    .prev_sibling
                    .and_then(|prev| self.nodes[prev].as_text_mut())
                {
                    prev_text.push_tendril(&text);
                } else {
                    let index = self.new_node(NodeData::Text(text));
                    self.insert_before(*sibling, index);
                }
            }
        }
    }

    fn add_attrs_if_missing(&mut self, target: &Self::Handle, attrs: Vec<Attribute>) {
        let target = self.nodes[*target].as_element_mut().unwrap();
        target.attrs.extend(attrs.into_iter());
    }

    fn remove_from_parent(&mut self, target: &Self::Handle) {
        self.detach(*target);
    }

    fn reparent_children(&mut self, node: &Self::Handle, new_parent: &Self::Handle) {
        let mut next_child = self.nodes[*node].first_child;
        while let Some(child) = next_child {
            next_child = self.nodes[child].next_sibling;
            self.append_node(*new_parent, child);
        }
    }
}

impl Serialize for Fragment {
    fn serialize<S>(&self, serializer: &mut S, traversal_scope: TraversalScope) -> io::Result<()>
    where
        S: Serializer,
    {
        match traversal_scope {
            TraversalScope::IncludeNode => {
                let root = self.nodes[0].first_child.unwrap();

                let mut next_child = self.nodes[root].first_child;
                while let Some(child) = next_child {
                    let child = &self.nodes[child];
                    child.serialize(self, serializer)?;
                    next_child = child.next_sibling;
                }

                Ok(())
            }
            TraversalScope::ChildrenOnly(_) => Ok(()),
        }
    }
}

impl fmt::Display for Fragment {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut u8_vec = Vec::new();
        serialize(
            &mut u8_vec,
            self,
            SerializeOpts { traversal_scope: TraversalScope::IncludeNode, ..Default::default() },
        )
        .unwrap();

        f.write_str(&String::from_utf8(u8_vec).unwrap())?;

        Ok(())
    }
}

/// An HTML node.
#[derive(Debug)]
pub struct Node {
    pub parent: Option<usize>,
    pub prev_sibling: Option<usize>,
    pub next_sibling: Option<usize>,
    pub first_child: Option<usize>,
    pub last_child: Option<usize>,
    pub data: NodeData,
}

impl Node {
    /// Constructs a new `Node` with the given data.
    pub fn new(data: NodeData) -> Self {
        Self {
            parent: None,
            prev_sibling: None,
            next_sibling: None,
            first_child: None,
            last_child: None,
            data,
        }
    }

    /// Returns the `ElementData` of this `Node` if it is a `NodeData::Element`.
    pub fn as_element(&self) -> Option<&ElementData> {
        match &self.data {
            NodeData::Element(data) => Some(data),
            _ => None,
        }
    }

    /// Returns the mutable `ElementData` of this `Node` if it is a `NodeData::Element`.
    pub fn as_element_mut(&mut self) -> Option<&mut ElementData> {
        match &mut self.data {
            NodeData::Element(data) => Some(data),
            _ => None,
        }
    }

    /// Returns the mutable text content of this `Node`, if it is a `NodeData::Text`.
    pub fn as_text_mut(&mut self) -> Option<&mut StrTendril> {
        match &mut self.data {
            NodeData::Text(data) => Some(data),
            _ => None,
        }
    }
}

impl Node {
    pub fn serialize<S>(&self, fragment: &Fragment, serializer: &mut S) -> io::Result<()>
    where
        S: Serializer,
    {
        match &self.data {
            NodeData::Element(ref data) => {
                serializer.start_elem(
                    data.name.clone(),
                    data.attrs.iter().map(|attr| (&attr.name, &*attr.value)),
                )?;

                let mut next_child = self.first_child;
                while let Some(child) = next_child {
                    let child = &fragment.nodes[child];
                    child.serialize(fragment, serializer)?;
                    next_child = child.next_sibling;
                }

                serializer.end_elem(data.name.clone())?;

                Ok(())
            }
            NodeData::Document => {
                let mut next_child = self.first_child;
                while let Some(child) = next_child {
                    let child = &fragment.nodes[child];
                    child.serialize(fragment, serializer)?;
                    next_child = child.next_sibling;
                }

                Ok(())
            }
            NodeData::Text(ref text) => serializer.write_text(text),
            _ => Ok(()),
        }
    }
}

/// The data of a `Node`.
#[derive(Debug)]
pub enum NodeData {
    /// The root node of the `Fragment`.
    Document,

    /// A text node.
    Text(StrTendril),

    /// An HTML element (aka a tag).
    Element(ElementData),

    /// Other types (comment, processing instruction, …).
    Other,
}

/// The data of an HTML element.
#[derive(Debug)]
pub struct ElementData {
    /// The qualified name of the element.
    pub name: QualName,

    /// The attributes of the element.
    pub attrs: BTreeSet<Attribute>,
}

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

    #[test]
    fn sanity() {
        let html = "\

Title
\

\

This is some text
\

\
        ";
        assert_eq!(Fragment::parse_html(html).to_string(), html);

        assert_eq!(Fragment::parse_html("").to_string(), "");
    }
}
<|endoftext|>