<commit_before>//! A module for the automatic map generation

use noise::{Brownian2, Seed, open_simplex2};

// TODO pick:
// use traits::*;
// use traits::{Map, Tile, TileMap};
use traits::{Tile, TileMap};

// Probably really buggy code...

/// A map
///
/// Note: It's chuncked into big chuncks and small chuncks.
///       Small chuncks keeps the noise data. Big chuncks
///       determines the overlay layer.
pub struct MapGenerator<'a> {
  seed: &'a Seed,
}

/// Types of big chuncks
enum BChunckType {
  /// Reserved for history, empty per default, but gets opened as the game is played. Manually designed.
  History,
  // Automatic map generated chunck
  Auto,
  // Manually random generated chunck
  Manually,
}

// TODO: Find out how to prevent double islands (manually generated islands)

impl<'a> MapGenerator<'a> {
  /// Creates a new map
  pub fn new(seed: &'a Seed) -> MapGenerator<'a> {
     MapGenerator {
       seed: seed,
     }
   }

  // TODO: Add some sort of cache

  /// Get the noise value at a given point
  fn get_noise_value(&self, x: i64, y: i64) -> f64 {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    noise.apply(&self.seed, &[x as f64, y as f64])
  }

  /// Get big chunck coordinates
  fn get_bchunck(x: i64, y: i64) -> (i64, i64) {
    // TODO: Chunck size 64?
    (((x as f64) / 64.0).floor() as i64, ((y as f64) / 64.0).floor() as i64)
  }

  /* TODO: Finish this:
  fn get_bchunck_type(x: i64, y: i64) -> BChunckType {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    noise.apply(&self.seed, &[x as f64, y as f64])
  }
  */

  /// Get overlay value (used for customizing the noise)
  fn get_overlay_value(&self, x: i64, y: i64) -> f64 {
    // TODO
    // Stuff here
    1.0
  }
}

impl<'a> TileMap for MapGenerator<'a> {

  // Add foreground/background
  /// Get the tile at a given point
  fn get_tile(&self, x: i64, y: i64) -> Tile {
    let val = (self.get_noise_value(x, y) + self.get_overlay_value(x, y)) / 2.0;

    if val > 0.9 {
      Tile::Grass
    } else {
      Tile::Water
    }
  }
}
<commit_msg>Fix typo ('chunck' -> 'chunk')<commit_after>//! A module for the automatic map generation

use noise::{Brownian2, Seed, open_simplex2};

// TODO pick:
// use traits::*;
// use traits::{Map, Tile, TileMap};
use traits::{Tile, TileMap};

// Probably really buggy code...

/// A map
///
/// Note: It's chunked into big chunks and small chunks.
///       Small chunks keeps the noise data. Big chunks
///       determines the overlay layer.
pub struct MapGenerator<'a> {
  seed: &'a Seed,
}

/// Types of big chunks
enum BChunkType {
  /// Reserved for history, empty per default, but gets opened as the game is played. Manually designed.
  History,
  // Automatic map generated chunk
  Auto,
  // Manually random generated chunk
  Manually,
}

// TODO: Find out how to prevent double islands (manually generated islands)

impl<'a> MapGenerator<'a> {
  /// Creates a new map
  pub fn new(seed: &'a Seed) -> MapGenerator<'a> {
     MapGenerator {
       seed: seed,
     }
   }

  // TODO: Add some sort of cache

  /// Get the noise value at a given point
  fn get_noise_value(&self, x: i64, y: i64) -> f64 {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    noise.apply(&self.seed, &[x as f64, y as f64])
  }

  /// Get big chunk coordinates
  fn get_bchunk(x: i64, y: i64) -> (i64, i64) {
    // TODO: Chunk size 64?
    (((x as f64) / 64.0).floor() as i64, ((y as f64) / 64.0).floor() as i64)
  }

  /* TODO: Finish this:
  fn get_bchunk_type(x: i64, y: i64) -> BChunkType {
    let noise = Brownian2::new(open_simplex2, 4).wavelength(32.0);
    noise.apply(&self.seed, &[x as f64, y as f64])
  }
  */

  /// Get overlay value (used for customizing the noise)
  fn get_overlay_value(&self, x: i64, y: i64) -> f64 {
    // TODO
    // Stuff here
    1.0
  }
}

impl<'a> TileMap for MapGenerator<'a> {

  // Add foreground/background
  /// Get the tile at a given point
  fn get_tile(&self, x: i64, y: i64) -> Tile {
    let val = (self.get_noise_value(x, y) + self.get_overlay_value(x, y)) / 2.0;

    if val > 0.9 {
      Tile::Grass
    } else {
      Tile::Water
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_real,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_real,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublereal, lda: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn cheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_complex,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_complex,
            lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, ap: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ap: CLPK_doublereal, w: CLPK_doublereal,
            z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chpev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ap: CLPK_complex, w: CLPK_real, z: CLPK_complex,
            ldz: CLPK_integer, work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhpev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ap: CLPK_doublecomplex, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn ssbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_real, ldab: CLPK_integer,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_doublereal, ldab: CLPK_integer,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_complex, ldab: CLPK_integer,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_doublecomplex,
            ldab: CLPK_integer, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<commit_msg>Add Stev trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_real,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_real,
            lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsyev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublereal, lda: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn cheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, a: *mut CLPK_complex,
            lda: *const CLPK_integer, w: CLPK_real, work: CLPK_complex,
            lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zheev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer, ap: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ap: CLPK_doublereal, w: CLPK_doublereal,
            z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chpev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ap: CLPK_complex, w: CLPK_real, z: CLPK_complex,
            ldz: CLPK_integer, work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhpev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ap: CLPK_doublecomplex, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn ssbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_real, ldab: CLPK_integer,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_doublereal, ldab: CLPK_integer,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_complex, ldab: CLPK_integer,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhbev_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            kd: CLPK_integer, ab: CLPK_doublecomplex,
            ldab: CLPK_integer, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sstev_(jobz: c_char, n: *const CLPK_integer, d: CLPK_real,
            e: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dstev_(jobz: c_char, n: *const CLPK_integer, d: CLPK_doublereal,
            e: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use error::Error;

use super::{Request, Response, IronResult};

/// `Handler`s are responsible for handling requests by creating Responses from Requests.
///
/// By default, bare functions and variants of Chain implement `Handler`.
///
/// `Handler`s are allowed to return errors, and if they do, their `catch` method is called and the
/// error is propagated to `AfterMiddleware`.
pub trait Handler: Send + Sync {
    /// Produce a `Response` from a Request, with the possibility of error.
    ///
    /// If this returns an Err, `catch` is called with the error.
    fn call(&self, &mut Request) -> IronResult<Response>;

    /// If `Handler`'s call method produces an Err, then this method is called
    /// to produce a `Response` and possibly handle the error.
    ///
    /// If the passed-in error is not handled, it should be returned as the second
    /// item in the returned tuple. If it is handled, then `Ok(())` can be returned
    /// instead to indicate that all is good with the Response.
    fn catch(&self, &mut Request, Box<Error>) -> (Response, IronResult<()>);
}

pub trait BeforeMiddleware: Send + Sync {
    fn before(&self, &mut Request) -> IronResult<()>;

    fn catch(&self, _: &mut Request, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

pub trait AfterMiddleware: Send + Sync {
    fn after(&self, &mut Request, &mut Response) -> IronResult<()>;

    // This response was generated by the `catch` function of Handlers and is abnormal in some way.
    fn catch(&self, _: &mut Request, _: &mut Response, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

pub trait AroundMiddleware: Handler {
    fn around(&mut self, handler: Box<Handler + Send + Sync>);
}

pub trait Chain: Handler {
    fn new<H: Handler>(H) -> Self;

    fn link<B, A>(&mut self, (B, A)) where A: AfterMiddleware, B: BeforeMiddleware;

    fn link_before<B>(&mut self, B) where B: BeforeMiddleware;

    fn link_after<A>(&mut self, A) where A: AfterMiddleware;

    fn around<A>(&mut self, A) where A: AroundMiddleware;
}

pub struct ChainBuilder {
    befores: Vec<Box<BeforeMiddleware + Send + Sync>>,
    afters: Vec<Box<AfterMiddleware + Send + Sync>>,
    handler: Box<Handler + Send + Sync>
}

impl Chain for ChainBuilder {
    fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }

    fn link<B, A>(&mut self, link: (B, A))
    where A: AfterMiddleware, B: BeforeMiddleware {
        let (before, after) = link;
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn link_before<B>(&mut self, before: B) where B: BeforeMiddleware {
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
    }

    fn link_after<A>(&mut self, after: A) where A: AfterMiddleware {
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn around<A>(&mut self, mut around: A) where A: AroundMiddleware {
        use std::mem;

        let old = mem::replace(&mut self.handler, box Nop as Box<Handler + Send + Sync>);
        around.around(old);
        self.handler = box around as Box<Handler + Send + Sync>;
    }
}

impl Handler for ChainBuilder {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), None);

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        helpers::run_afters(req, res, err, self.afters.as_slice())
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), Some(err));

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        match helpers::run_afters(req, res, err, self.afters.as_slice()) {
            Ok(res) => (res, Ok(())),
            // FIXME: Make 500
            Err(err) => (Response::new(), Err(err))
        }
    }
}

impl Handler for fn(&mut Request) -> IronResult<Response> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        // FIXME: Make Response a 500
        (Response::new(), Err(err))
    }
}

pub struct Nop;

impl Handler for Nop {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        // FIXME: Make Response a 500
        (Response::new(), Err(err))
    }
}

impl Handler for Box<Handler + Send + Sync> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

impl Handler for Arc<Box<Handler + Send + Sync>> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

mod helpers {
    use super::super::{Request, Response, IronResult};
    use super::{AfterMiddleware, BeforeMiddleware, Handler};
    use error::Error;

    pub fn run_befores(req: &mut Request, befores: &[Box<BeforeMiddleware>], err: Option<Box<Error>>) -> IronResult<()> {
        match err {
            Some(mut e) => {
                for (i, before) in befores.iter().enumerate() {
                    match before.catch(req, e) {
                        Ok(_) => return run_befores(req, befores, None),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, before) in befores.iter().enumerate() {
                    match before.before(req) {
                        Ok(_) => (),
                        Err(err) => return run_befores(req, befores.slice_from(i), Some(err))
                    }
                }
                Ok(())
            }
        }
    }

    pub fn run_afters(req: &mut Request, mut res: Response, err: Option<Box<Error>>,
                  afters: &[Box<AfterMiddleware>]) -> IronResult<Response> {
        match err {
            Some(mut e) => {
                for (i, after) in afters.iter().enumerate() {
                    match after.catch(req, &mut res, e) {
                        Ok(_) => return run_afters(req, res, None, afters),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, after) in afters.iter().enumerate() {
                    match after.after(req, &mut res) {
                        Ok(_) => (),
                        Err(err) => return run_afters(req, res, Some(err), afters.slice_from(i))
                    }
                }
                Ok(res)
            }
        }
    }

    pub fn run_handler_catch(req: &mut Request, err: Box<Error>,
                         handler: &Box<Handler>) -> (Response, Option<Box<Error>>) {
        match handler.catch(req, err) {
            (res, Ok(())) => (res, None),
            (res, Err(e)) => (res, Some(e))
        }
    }
}

<commit_msg>(doc) Documented BeforeMiddleware.<commit_after>use std::sync::Arc;
use error::Error;

use super::{Request, Response, IronResult};

/// `Handler`s are responsible for handling requests by creating Responses from Requests.
///
/// By default, bare functions and variants of Chain implement `Handler`.
///
/// `Handler`s are allowed to return errors, and if they do, their `catch` method is called and the
/// error is propagated to `AfterMiddleware`.
pub trait Handler: Send + Sync {
    /// Produce a `Response` from a Request, with the possibility of error.
    ///
    /// If this returns an Err, `catch` is called with the error.
    fn call(&self, &mut Request) -> IronResult<Response>;

    /// If `Handler`'s call method produces an Err, then this method is called
    /// to produce a `Response` and possibly handle the error.
    ///
    /// If the passed-in error is not handled, it should be returned as the second
    /// item in the returned tuple. If it is handled, then `Ok(())` can be returned
    /// instead to indicate that all is good with the Response.
    fn catch(&self, &mut Request, Box<Error>) -> (Response, IronResult<()>);
}

/// `BeforeMiddleware` are fired before a `Handler` is called inside of a Chain.
///
/// `BeforeMiddleware` are responsible for doing request pre-processing that requires
/// the ability to change control-flow, such as authorization middleware, or for editing
/// the request by modifying the headers.
///
/// `BeforeMiddleware` only have access to the Request, if you need to modify or read a Response,
/// you will need `AfterMiddleware`.
pub trait BeforeMiddleware: Send + Sync {
    /// Do whatever work this middleware should do with a `Request` object.
    ///
    /// An error here is propagated by the containing Chain to, first, this Middleware's
    /// `catch` method, then every subsequent `BeforeMiddleware`'s `catch` methods until one returns
    /// Ok(()) or the Chain's `Handler` is reached, at which point the `Handler`'s `catch` method is
    /// called to produce an error Response.
    fn before(&self, &mut Request) -> IronResult<()>;

    /// Try to `catch` an error thrown by this Middleware or a previous `BeforeMiddleware`.
    ///
    /// Should only return Ok(()) if the error has been completely handled and a Chain
    /// can proceed as normal.
    fn catch(&self, _: &mut Request, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

pub trait AfterMiddleware: Send + Sync {
    fn after(&self, &mut Request, &mut Response) -> IronResult<()>;

    // This response was generated by the `catch` function of Handlers and is abnormal in some way.
    fn catch(&self, _: &mut Request, _: &mut Response, err: Box<Error>) -> IronResult<()> {
        Err(err)
    }
}

pub trait AroundMiddleware: Handler {
    fn around(&mut self, handler: Box<Handler + Send + Sync>);
}

pub trait Chain: Handler {
    fn new<H: Handler>(H) -> Self;

    fn link<B, A>(&mut self, (B, A)) where A: AfterMiddleware, B: BeforeMiddleware;

    fn link_before<B>(&mut self, B) where B: BeforeMiddleware;

    fn link_after<A>(&mut self, A) where A: AfterMiddleware;

    fn around<A>(&mut self, A) where A: AroundMiddleware;
}

pub struct ChainBuilder {
    befores: Vec<Box<BeforeMiddleware + Send + Sync>>,
    afters: Vec<Box<AfterMiddleware + Send + Sync>>,
    handler: Box<Handler + Send + Sync>
}

impl Chain for ChainBuilder {
    fn new<H: Handler>(handler: H) -> ChainBuilder {
        ChainBuilder {
            befores: vec![],
            afters: vec![],
            handler: box handler as Box<Handler + Send + Sync>
        }
    }

    fn link<B, A>(&mut self, link: (B, A))
    where A: AfterMiddleware, B: BeforeMiddleware {
        let (before, after) = link;
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn link_before<B>(&mut self, before: B) where B: BeforeMiddleware {
        self.befores.push(box before as Box<BeforeMiddleware + Send + Sync>);
    }

    fn link_after<A>(&mut self, after: A) where A: AfterMiddleware {
        self.afters.push(box after as Box<AfterMiddleware + Send + Sync>);
    }

    fn around<A>(&mut self, mut around: A) where A: AroundMiddleware {
        use std::mem;

        let old = mem::replace(&mut self.handler, box Nop as Box<Handler + Send + Sync>);
        around.around(old);
        self.handler = box around as Box<Handler + Send + Sync>;
    }
}

impl Handler for ChainBuilder {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), None);

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        helpers::run_afters(req, res, err, self.afters.as_slice())
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        let before_result = helpers::run_befores(req, self.befores.as_slice(), Some(err));

        let (res, err) = match before_result {
            Ok(()) => match self.handler.call(req) {
                Ok(res) => (res, None),
                Err(e) => helpers::run_handler_catch(req, e, &self.handler)
            },
            Err(e) => helpers::run_handler_catch(req, e, &self.handler)
        };

        match helpers::run_afters(req, res, err, self.afters.as_slice()) {
            Ok(res) => (res, Ok(())),
            // FIXME: Make 500
            Err(err) => (Response::new(), Err(err))
        }
    }
}

impl Handler for fn(&mut Request) -> IronResult<Response> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        // FIXME: Make Response a 500
        (Response::new(), Err(err))
    }
}

pub struct Nop;

impl Handler for Nop {
    fn call(&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::new())
    }

    fn catch(&self, _: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        // FIXME: Make Response a 500
        (Response::new(), Err(err))
    }
}

impl Handler for Box<Handler + Send + Sync> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

impl Handler for Arc<Box<Handler + Send + Sync>> {
    fn call(&self, req: &mut Request) -> IronResult<Response> {
        self.call(req)
    }

    fn catch(&self, req: &mut Request, err: Box<Error>) -> (Response, IronResult<()>) {
        self.catch(req, err)
    }
}

mod helpers {
    use super::super::{Request, Response, IronResult};
    use super::{AfterMiddleware, BeforeMiddleware, Handler};
    use error::Error;

    pub fn run_befores(req: &mut Request, befores: &[Box<BeforeMiddleware>], err: Option<Box<Error>>) -> IronResult<()> {
        match err {
            Some(mut e) => {
                for (i, before) in befores.iter().enumerate() {
                    match before.catch(req, e) {
                        Ok(_) => return run_befores(req, befores, None),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, before) in befores.iter().enumerate() {
                    match before.before(req) {
                        Ok(_) => (),
                        Err(err) => return run_befores(req, befores.slice_from(i), Some(err))
                    }
                }
                Ok(())
            }
        }
    }

    pub fn run_afters(req: &mut Request, mut res: Response, err: Option<Box<Error>>,
                  afters: &[Box<AfterMiddleware>]) -> IronResult<Response> {
        match err {
            Some(mut e) => {
                for (i, after) in afters.iter().enumerate() {
                    match after.catch(req, &mut res, e) {
                        Ok(_) => return run_afters(req, res, None, afters),
                        Err(new) => e = new
                    }
                }
                Err(e)
            },

            None => {
                for (i, after) in afters.iter().enumerate() {
                    match after.after(req, &mut res) {
                        Ok(_) => (),
                        Err(err) => return run_afters(req, res, Some(err), afters.slice_from(i))
                    }
                }
                Ok(res)
            }
        }
    }

    pub fn run_handler_catch(req: &mut Request, err: Box<Error>,
                         handler: &Box<Handler>) -> (Response, Option<Box<Error>>) {
        match handler.catch(req, err) {
            (res, Ok(())) => (res, None),
            (res, Err(e)) => (res, Some(e))
        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use futures::{task, Future};

use std::cell::{Cell, RefCell};
use std::rc::{Rc};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::collections::HashMap;

struct Unparker {
    original_needs_poll: AtomicBool,

    // It's sad that we need a mutex here, even though we know that the RPC
    // system is restricted to a single thread.
    tasks: Mutex<HashMap<u64, task::Task>>,
}

impl Unparker {
    fn new(original_needs_poll: AtomicBool) -> Unparker {
        Unparker {
            original_needs_poll: original_needs_poll,
            tasks: Mutex::new(HashMap::new()),
        }
    }

    fn insert(&self, idx: u64, task: task::Task) {
        self.tasks.lock().unwrap().insert(idx, task);
    }

    fn remove(&self, idx: u64) {
        self.tasks.lock().unwrap().remove(&idx);
    }

    fn unpark(&self) {
        self.original_needs_poll.store(true, Ordering::SeqCst);
        let tasks = ::std::mem::replace(&mut *self.tasks.lock().unwrap(), HashMap::new());
        for (_, task) in tasks {
            task.unpark();
        }
    }
}

impl task::EventSet for Unparker {
    fn insert(&self, _id: usize) {
        self.unpark();
    }
}

struct ForkedPromiseInner<F> where F: Future {
    next_clone_id: Cell<u64>,

    // Only ever `Some` when `state` is `Waiting`. You might think that it's a good idea
    // to fold this field into the `State` enum, but then a double-borrow panic is possible:
    // `state` would need to be mutably borrowed when we call `poll()` on the original future,
    // polling the original future can cause clones of the `ForkedPromise` to get dropped,
    // and `ForkedPromise::drop()` needs to borrow `state` again.
    original_future: RefCell<Option<F>>,

    state: RefCell<ForkedPromiseState<F::Item, F::Error>>,
}

enum ForkedPromiseState<T, E> {
    Waiting(Arc<Unparker>),
    Done(Result<T, E>),
}

pub struct ForkedPromise<F> where F: Future {
    id: u64,
    inner: Rc<ForkedPromiseInner<F>>,
}

impl <F> Clone for ForkedPromise<F> where F: Future {
    fn clone(&self) -> ForkedPromise<F> {
        let clone_id = self.inner.next_clone_id.get();
        self.inner.next_clone_id.set(clone_id + 1);
        ForkedPromise {
            id: clone_id,
            inner: self.inner.clone(),
        }
    }
}

impl <F> ForkedPromise<F> where F: Future {
    pub fn new(f: F) -> ForkedPromise<F> {
        ForkedPromise {
            id: 0,
            inner: Rc::new(ForkedPromiseInner {
                next_clone_id: Cell::new(1),
                original_future: RefCell::new(Some(f)),
                state: RefCell::new(ForkedPromiseState::Waiting(
                    Arc::new(Unparker::new(AtomicBool::new(true))))),
            })
        }
    }
}

impl<F> Drop for ForkedPromise<F> where F: Future {
    fn drop(&mut self) {
        match *self.inner.state.borrow() {
            ForkedPromiseState::Waiting(ref unparker) => {
                unparker.remove(self.id);
            }
            ForkedPromiseState::Done(_) => (),
        }
    }
}

impl <F> Future for ForkedPromise<F>
    where F: Future, F::Item: Clone, F::Error: Clone,
{
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {
        let event = match *self.inner.state.borrow_mut() {
            ForkedPromiseState::Waiting(ref unparker) => {
                if !unparker.original_needs_poll.swap(false, Ordering::SeqCst) {
                    unparker.insert(self.id, task::park());
                    return Ok(::futures::Async::NotReady)
                }
                task::UnparkEvent::new(unparker.clone(), 0)
            }
            ForkedPromiseState::Done(ref r) => {
                match *r {
                    Ok(ref v) => return Ok(::futures::Async::Ready(v.clone())),
                    Err(ref e) => return Err(e.clone()),
                }
            }
        };

        let done_val = match *self.inner.original_future.borrow_mut() {
            Some(ref mut original_future) => {
                match task::with_unpark_event(event, || original_future.poll()) {
                    Ok(::futures::Async::NotReady) => {
                        return Ok(::futures::Async::NotReady)
                    }
                    Ok(::futures::Async::Ready(v)) => Ok(v),
                    Err(e) => Err(e),
                }
            }
            None => unreachable!(),
        };

        // No longer need to hold on to the original future.
        self.inner.original_future.borrow_mut().take();

        match ::std::mem::replace(
            &mut *self.inner.state.borrow_mut(),
            ForkedPromiseState::Done(done_val.clone()))
        {
            ForkedPromiseState::Waiting(ref unparker) => unparker.unpark(),
            _ => unreachable!(),
        }

        match done_val {
            Ok(v) => Ok(::futures::Async::Ready(v)),
            Err(e) => Err(e),
        }
    }
}

#[cfg(test)]
mod test {
    use futures::{Future, Poll};
    use futures::sync::oneshot;
    use std::rc::Rc;
    use std::sync::Arc;
    use std::cell::RefCell;
    use super::ForkedPromise;

    enum Mode { Left, Right }

    struct ModedFutureInner<F> where F: Future {
        mode: Mode,
        left: F,
        right: F,
        task: Option<::futures::task::Task>,
    }

    struct ModedFuture<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    struct ModedFutureHandle<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    impl <F> ModedFuture<F> where F: Future {
        pub fn new(left: F, right: F, mode: Mode) -> (ModedFutureHandle<F>, ModedFuture<F>) {
            let inner = Rc::new(RefCell::new(ModedFutureInner {
                left: left, right: right, mode: mode, task: None,
            }));
            (ModedFutureHandle { inner: inner.clone() }, ModedFuture { inner: inner })
        }
    }

    impl <F> ModedFutureHandle<F> where F: Future {
        pub fn switch_mode(&mut self, mode: Mode) {
            self.inner.borrow_mut().mode = mode;
            if let Some(t) = self.inner.borrow_mut().task.take() {
                // The other future may have become ready while we were ignoring it.
                t.unpark();
            }
        }
    }

    impl <F> Future for ModedFuture<F> where F: Future {
        type Item = F::Item;
        type Error = F::Error;
        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let ModedFutureInner { ref mut mode, ref mut left, ref mut right, ref mut task } =
                *self.inner.borrow_mut();
            *task = Some(::futures::task::park());
            match *mode {
                Mode::Left => left.poll(),
                Mode::Right => right.poll(),
            }
        }
    }

    struct Reaper;
    impl ::task_set::TaskReaper<(), ()> for Reaper {
        fn task_failed(&mut self, _err: ()) {}
    }

    struct Unpark;
    impl ::futures::executor::Unpark for Unpark {
        fn unpark(&self) {}
    }

    fn forked_propagates_unpark_helper(spawn_moded_first: bool) {
        let (handle, tasks) = ::task_set::TaskSet::<(), ()>::new(Box::new(Reaper));

        let mut spawn = ::futures::executor::spawn(tasks);
        let unpark: Arc<::futures::executor::Unpark> = Arc::new(Unpark);

        let (tx, rx) = oneshot::channel::<u32>();
        let f1 = ForkedPromise::new(rx);
        let f2 = f1.clone();

        let (mut mfh, mf) = ModedFuture::new(
            Box::new(f1.map_err(|_| ())) as Box<Future<Item=u32, Error=()>>,
            Box::new(::futures::future::empty()) as Box<Future<Item=u32, Error=()>>,
            Mode::Left);

        let mut handle0 = handle.clone();
        let spawn_mf = move || {
            handle0.add(mf.map(|_| ()));
        };

        let mut handle0 = handle.clone();
        let spawn_f2 = move || {
            let mut handle1 = handle0.clone();
            handle0.add(f2.map(move |_| handle1.terminate(Ok(()))).map_err(|_|()));

        };

        if spawn_moded_first {
            (spawn_mf)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_f2)();
        } else {
            (spawn_f2)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_mf)();
        }

        match spawn.poll_future(unpark.clone()) {
            Ok(::futures::Async::NotReady) => (),
            _ => panic!("should not be ready yet."),
        }

        mfh.switch_mode(Mode::Right);

        tx.complete(11); // This should cause `f2` and then eventually `spawn` to resolve.

        loop {
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                Ok(::futures::Async::Ready(_)) => break,
                Err(e) => panic!("error: {:?}", e),
            }
        }
    }

    #[test]
    fn forked_propagates_unpark() {
        forked_propagates_unpark_helper(true);
        forked_propagates_unpark_helper(false);
    }
}
<commit_msg>add drop_in_poll test<commit_after>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use futures::{task, Future};

use std::cell::{Cell, RefCell};
use std::rc::{Rc};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::collections::HashMap;

struct Unparker {
    original_needs_poll: AtomicBool,

    // It's sad that we need a mutex here, even though we know that the RPC
    // system is restricted to a single thread.
    tasks: Mutex<HashMap<u64, task::Task>>,
}

impl Unparker {
    fn new(original_needs_poll: AtomicBool) -> Unparker {
        Unparker {
            original_needs_poll: original_needs_poll,
            tasks: Mutex::new(HashMap::new()),
        }
    }

    fn insert(&self, idx: u64, task: task::Task) {
        self.tasks.lock().unwrap().insert(idx, task);
    }

    fn remove(&self, idx: u64) {
        self.tasks.lock().unwrap().remove(&idx);
    }

    fn unpark(&self) {
        self.original_needs_poll.store(true, Ordering::SeqCst);
        let tasks = ::std::mem::replace(&mut *self.tasks.lock().unwrap(), HashMap::new());
        for (_, task) in tasks {
            task.unpark();
        }
    }
}

impl task::EventSet for Unparker {
    fn insert(&self, _id: usize) {
        self.unpark();
    }
}

struct ForkedPromiseInner<F> where F: Future {
    next_clone_id: Cell<u64>,

    // Only ever `Some` when `state` is `Waiting`. You might think that it's a good idea
    // to fold this field into the `State` enum, but then a double-borrow panic is possible:
    // `state` would need to be mutably borrowed when we call `poll()` on the original future,
    // polling the original future can cause clones of the `ForkedPromise` to get dropped,
    // and `ForkedPromise::drop()` needs to borrow `state` again.
    original_future: RefCell<Option<F>>,

    state: RefCell<ForkedPromiseState<F::Item, F::Error>>,
}

enum ForkedPromiseState<T, E> {
    Waiting(Arc<Unparker>),
    Done(Result<T, E>),
}

pub struct ForkedPromise<F> where F: Future {
    id: u64,
    inner: Rc<ForkedPromiseInner<F>>,
}

impl <F> Clone for ForkedPromise<F> where F: Future {
    fn clone(&self) -> ForkedPromise<F> {
        let clone_id = self.inner.next_clone_id.get();
        self.inner.next_clone_id.set(clone_id + 1);
        ForkedPromise {
            id: clone_id,
            inner: self.inner.clone(),
        }
    }
}

impl <F> ForkedPromise<F> where F: Future {
    pub fn new(f: F) -> ForkedPromise<F> {
        ForkedPromise {
            id: 0,
            inner: Rc::new(ForkedPromiseInner {
                next_clone_id: Cell::new(1),
                original_future: RefCell::new(Some(f)),
                state: RefCell::new(ForkedPromiseState::Waiting(
                    Arc::new(Unparker::new(AtomicBool::new(true))))),
            })
        }
    }
}

impl<F> Drop for ForkedPromise<F> where F: Future {
    fn drop(&mut self) {
        match *self.inner.state.borrow() {
            ForkedPromiseState::Waiting(ref unparker) => {
                unparker.remove(self.id);
            }
            ForkedPromiseState::Done(_) => (),
        }
    }
}

impl <F> Future for ForkedPromise<F>
    where F: Future, F::Item: Clone, F::Error: Clone,
{
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {
        let event = match *self.inner.state.borrow_mut() {
            ForkedPromiseState::Waiting(ref unparker) => {
                if !unparker.original_needs_poll.swap(false, Ordering::SeqCst) {
                    unparker.insert(self.id, task::park());
                    return Ok(::futures::Async::NotReady)
                }
                task::UnparkEvent::new(unparker.clone(), 0)
            }
            ForkedPromiseState::Done(ref r) => {
                match *r {
                    Ok(ref v) => return Ok(::futures::Async::Ready(v.clone())),
                    Err(ref e) => return Err(e.clone()),
                }
            }
        };

        let done_val = match *self.inner.original_future.borrow_mut() {
            Some(ref mut original_future) => {
                match task::with_unpark_event(event, || original_future.poll()) {
                    Ok(::futures::Async::NotReady) => {
                        return Ok(::futures::Async::NotReady)
                    }
                    Ok(::futures::Async::Ready(v)) => Ok(v),
                    Err(e) => Err(e),
                }
            }
            None => unreachable!(),
        };

        // No longer need to hold on to the original future.
        self.inner.original_future.borrow_mut().take();

        match ::std::mem::replace(
            &mut *self.inner.state.borrow_mut(),
            ForkedPromiseState::Done(done_val.clone()))
        {
            ForkedPromiseState::Waiting(ref unparker) => unparker.unpark(),
            _ => unreachable!(),
        }

        match done_val {
            Ok(v) => Ok(::futures::Async::Ready(v)),
            Err(e) => Err(e),
        }
    }
}

#[cfg(test)]
mod test {
    use futures::{Future, Poll};
    use futures::sync::oneshot;
    use std::rc::Rc;
    use std::sync::Arc;
    use std::cell::RefCell;
    use super::ForkedPromise;

    // This test was pilfered from a futures::future::Shared test.
    #[test]
    fn drop_in_poll() {
        let slot = Rc::new(RefCell::new(None));
        let slot2 = slot.clone();
        let future = ForkedPromise::new(::futures::future::poll_fn(move || {
            drop(slot2.borrow_mut().take().unwrap());
            Ok::<_, u32>(1.into())
        }));
        let future2 = Box::new(future.clone()) as Box<Future<Item=_, Error=_>>;
        *slot.borrow_mut() = Some(future2);
        assert_eq!(future.wait().unwrap(), 1);
    }

    enum Mode { Left, Right }

    struct ModedFutureInner<F> where F: Future {
        mode: Mode,
        left: F,
        right: F,
        task: Option<::futures::task::Task>,
    }

    struct ModedFuture<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    struct ModedFutureHandle<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    impl <F> ModedFuture<F> where F: Future {
        pub fn new(left: F, right: F, mode: Mode) -> (ModedFutureHandle<F>, ModedFuture<F>) {
            let inner = Rc::new(RefCell::new(ModedFutureInner {
                left: left, right: right, mode: mode, task: None,
            }));
            (ModedFutureHandle { inner: inner.clone() }, ModedFuture { inner: inner })
        }
    }

    impl <F> ModedFutureHandle<F> where F: Future {
        pub fn switch_mode(&mut self, mode: Mode) {
            self.inner.borrow_mut().mode = mode;
            if let Some(t) = self.inner.borrow_mut().task.take() {
                // The other future may have become ready while we were ignoring it.
                t.unpark();
            }
        }
    }

    impl <F> Future for ModedFuture<F> where F: Future {
        type Item = F::Item;
        type Error = F::Error;
        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let ModedFutureInner { ref mut mode, ref mut left, ref mut right, ref mut task } =
                *self.inner.borrow_mut();
            *task = Some(::futures::task::park());
            match *mode {
                Mode::Left => left.poll(),
                Mode::Right => right.poll(),
            }
        }
    }

    struct Reaper;
    impl ::task_set::TaskReaper<(), ()> for Reaper {
        fn task_failed(&mut self, _err: ()) {}
    }

    struct Unpark;
    impl ::futures::executor::Unpark for Unpark {
        fn unpark(&self) {}
    }

    fn forked_propagates_unpark_helper(spawn_moded_first: bool) {
        let (handle, tasks) = ::task_set::TaskSet::<(), ()>::new(Box::new(Reaper));

        let mut spawn = ::futures::executor::spawn(tasks);
        let unpark: Arc<::futures::executor::Unpark> = Arc::new(Unpark);

        let (tx, rx) = oneshot::channel::<u32>();
        let f1 = ForkedPromise::new(rx);
        let f2 = f1.clone();

        let (mut mfh, mf) = ModedFuture::new(
            Box::new(f1.map_err(|_| ())) as Box<Future<Item=u32, Error=()>>,
            Box::new(::futures::future::empty()) as Box<Future<Item=u32, Error=()>>,
            Mode::Left);

        let mut handle0 = handle.clone();
        let spawn_mf = move || {
            handle0.add(mf.map(|_| ()));
        };

        let mut handle0 = handle.clone();
        let spawn_f2 = move || {
            let mut handle1 = handle0.clone();
            handle0.add(f2.map(move |_| handle1.terminate(Ok(()))).map_err(|_|()));

        };

        if spawn_moded_first {
            (spawn_mf)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_f2)();
        } else {
            (spawn_f2)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_mf)();
        }

        match spawn.poll_future(unpark.clone()) {
            Ok(::futures::Async::NotReady) => (),
            _ => panic!("should not be ready yet."),
        }

        mfh.switch_mode(Mode::Right);

        tx.complete(11); // This should cause `f2` and then eventually `spawn` to resolve.

        loop {
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                Ok(::futures::Async::Ready(_)) => break,
                Err(e) => panic!("error: {:?}", e),
            }
        }
    }

    #[test]
    fn forked_propagates_unpark() {
        forked_propagates_unpark_helper(true);
        forked_propagates_unpark_helper(false);
    }
}
<|endoftext|>


<commit_before>use serde_json::builder::ObjectBuilder;
use std::{fmt, mem};
use super::utils::{into_map, into_string, remove};
use super::{
    CurrentUser,
    FriendSourceFlags,
    GuildContainer,
    GuildId,
    GuildInfo,
    Member,
    Message,
    OnlineStatus,
    PrivateChannel,
    RoleId,
    UserSettings,
    User,
    UserId,
};
use time::Timespec;
use ::client::rest::{self, GuildPagination};
use ::internal::prelude::*;
use ::model::misc::Mentionable;
use ::utils::builder::EditProfile;
use ::utils::decode_array;

#[cfg(feature="cache")]
use std::sync::{Arc, RwLock};
#[cfg(feature="cache")]
use ::client::CACHE;

impl CurrentUser {
    /// Returns the formatted URL of the user's icon, if one exists.
    ///
    /// This will produce a WEBP image URL, or GIF if the user has a GIF avatar.
    pub fn avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| {
                let ext = if av.starts_with("a_") {
                    "gif"
                } else {
                    "webp"
                };

                format!(cdn!("/avatars/{}/{}.{}?size=1024"), self.id.0, av, ext)
            })
    }

    /// Returns the DiscordTag of a User.
    #[inline]
    pub fn distinct(&self) -> String {
        format!("{}#{}", self.name, self.discriminator)
    }

    /// Edits the current user's profile settings.
    ///
    /// This mutates the current user in-place.
    ///
    /// Refer to `EditProfile`'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the avatar:
    ///
    /// ```rust,ignore
    /// use serenity::client::CACHE;
    ///
    /// let avatar = serenity::utils::read_image("./avatar.png").unwrap();
    ///
    /// CACHE.write().unwrap().user.edit(|p| p.avatar(Some(&avatar)));
    /// ```
    pub fn edit<F>(&mut self, f: F) -> Result<()>
        where F: FnOnce(EditProfile) -> EditProfile {
        let mut map = ObjectBuilder::new()
            .insert("avatar", Some(&self.avatar))
            .insert("username", &self.name);

        if let Some(email) = self.email.as_ref() {
            map = map.insert("email", email)
        }

        match rest::edit_profile(&f(EditProfile(map)).0.build()) {
            Ok(new) => {
                let _ = mem::replace(self, new);

                Ok(())
            },
            Err(why) => Err(why),
        }
    }

    /// Gets a list of guilds that the current user is in.
    pub fn guilds(&self) -> Result<Vec<GuildInfo>> {
        rest::get_guilds(&GuildPagination::After(GuildId(1)), 100)
    }

    /// Returns a static formatted URL of the user's icon, if one exists.
    ///
    /// This will always produce a WEBP image URL.
    pub fn static_avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| format!(cdn!("/avatars/{}/{}.webp?size=1024"), self.id.0, av))
    }
}

impl User {
    /// Returns the formatted URL of the user's icon, if one exists.
    ///
    /// This will produce a WEBP image URL, or GIF if the user has a GIF avatar.
    pub fn avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| {
                let ext = if av.starts_with("a_") {
                    "gif"
                } else {
                    "webp"
                };

                format!(cdn!("/avatars/{}/{}.{}?size=1024"), self.id.0, av, ext)
            })
    }

    /// Creates a direct message channel between the [current user] and the
    /// user. This can also retrieve the channel if one already exists.
    ///
    /// [current user]: struct.CurrentUser.html
    #[inline]
    pub fn create_dm_channel(&self) -> Result<PrivateChannel> {
        self.id.create_dm_channel()
    }

    /// Returns the DiscordTag of a User.
    #[inline]
    pub fn distinct(&self) -> String {
        format!("{}#{}", self.name, self.discriminator)
    }

    /// Retrieves the time that this user was created at.
    #[inline]
    pub fn created_at(&self) -> Timespec {
        self.id.created_at()
    }

    /// Returns the formatted URL to the user's default avatar URL.
    ///
    /// This will produce a PNG URL.
    ///
    /// # Errors
    ///
    /// Returns an [`Error::Num`] if there was an error parsing the
    /// discriminator. Theoretically this is not possible.
    ///
    /// Returns an [`Error::Other`] if the remainder of the calculation
    /// `discriminator % 5` can not be matched. This is also probably not going
    /// to occur.
    ///
    /// [`Error::Num`]: ../enum.Error.html#variant.Num
    /// [`Error::Other`]: ../enum.Error.html#variant.Other
    pub fn default_avatar_url(&self) -> Result<String> {
        Ok(cdn!("/embed/avatars/{}.png", self.discriminator.parse::<u16>()? % 5u16).to_owned())
    }

    /// Deletes a profile note from a user.
    ///
    /// # Examples
    ///
    /// Delete a note for a [`Message`]'s author:
    ///
    /// ```rust,ignore
    /// // assuming you are in a context
    ///
    /// let _ = message.author.delete_note();
    /// ```
    ///
    /// [`Message`]: struct.Message.html
    #[inline]
    pub fn delete_note(&self) -> Result<()> {
        self.id.delete_note()
    }

    /// Sends a message to a user through a direct message channel. This is a
    /// channel that can only be accessed by you and the recipient.
    ///
    /// # Examples
    ///
    /// Sending a message:
    ///
    /// ```rust,ignore
    /// // assuming you are in a context
    ///
    /// let _ = message.author.direct_message("Hello!");
    /// ```
    ///
    /// [`PrivateChannel`]: struct.PrivateChannel.html
    /// [`User::dm`]: struct.User.html#method.dm
    // A tale with Clippy:
    //
    // A person named Clippy once asked you to unlock a box and take something
    // from it, but you never re-locked it, so you'll die and the universe will
    // implode because the box must remain locked unless you're there, and you
    // can't just borrow that item from it and take it with you forever.
    //
    // Instead what you do is unlock the box, take the item out of it, make a
    // copy of said item, and then re-lock the box, and take your copy of the
    // item with you.
    //
    // The universe is still fine, and nothing implodes.
    //
    // (AKA: Clippy is wrong and so we have to mark as allowing this lint.)
    #[allow(let_and_return)]
    pub fn direct_message(&self, content: &str)
        -> Result<Message> {
        let private_channel_id = feature_cache! {{
            let finding = {
                let cache = CACHE.read().unwrap();

                let finding = cache.private_channels
                    .values()
                    .map(|ch| ch.read().unwrap())
                    .find(|ch| ch.recipient.read().unwrap().id == self.id)
                    .map(|ch| ch.id)
                    .clone();

                finding
            };

            if let Some(finding) = finding {
                finding
            } else {
                let map = ObjectBuilder::new()
                    .insert("recipient_id", self.id.0)
                    .build();

                rest::create_private_channel(&map)?.id
            }
        } else {
            let map = ObjectBuilder::new()
                .insert("recipient_id", self.id.0)
                .build();

            rest::create_private_channel(map)?.id
        }};

        let map = ObjectBuilder::new()
            .insert("content", content)
            .insert("tts", false)
            .build();

        rest::send_message(private_channel_id.0, &map)
    }

    /// This is an alias of [direct_message].
    ///
    /// # Examples
    ///
    /// Sending a message:
    ///
    /// ```rust,ignore
    /// // assuming you are in a context
    ///
    /// let _ = message.author.dm("Hello!");
    /// ```
    ///
    /// [direct_message]: #method.direct_message
    #[inline]
    pub fn dm(&self, content: &str) -> Result<Message> {
        self.direct_message(content)
    }

    /// Edits the note that the current user has set for another user.
    ///
    /// Use [`delete_note`] to remove a note.
    ///
    /// **Note**: Requires that the current user be a user account.
    ///
    /// # Examples
    ///
    /// Set a note for a message's author:
    ///
    /// ```rust,ignore
    /// // assuming a `message` has been bound
    ///
    /// let _ = message.author.edit_note("test note");
    /// ```
    ///
    /// # Errors
    ///
    /// If the `cache` is enabled, returns a
    /// [`ClientError::InvalidOperationAsBot`] if the current user is a bot
    /// user.
    ///
    /// [`ClientError::InvalidOperationAsBot`]: ../client/enum.ClientError.html#variant.InvalidOperationAsBot
    /// [`delete_note`]: #method.delete_note
    #[inline]
    pub fn edit_note(&self, note: &str) -> Result<()> {
        self.id.edit_note(note)
    }

    /// Gets a user by its Id over the REST API.
    ///
    /// **Note**: The current user must be a bot user.
    ///
    /// # Errors
    ///
    /// If the `cache` is enabled, returns a
    /// [`ClientError::InvalidOperationAsUser`] if the current user is not a bot
    /// user.
    ///
    /// [`ClientError::InvalidOperationAsUser`]: ../client/enum.ClientError.html#variant.InvalidOperationAsUser
    pub fn get<U: Into<UserId>>(user_id: U) -> Result<User> {
        #[cfg(feature="cache")]
        {
            if !CACHE.read().unwrap().user.bot {
                return Err(Error::Client(ClientError::InvalidOperationAsUser));
            }
        }

        user_id.into().get()
    }

    /// Check if a user has a [`Role`]. This will retrieve the [`Guild`] from
    /// the [`Cache`] if it is available, and then check if that guild has the
    /// given [`Role`].
    ///
    /// Three forms of data may be passed in to the guild parameter: either a
    /// [`Guild`] itself, a [`GuildId`], or a `u64`.
    ///
    /// # Examples
    ///
    /// Check if a guild has a [`Role`] by Id:
    ///
    /// ```rust,ignore
    /// // Assumes a 'guild' and `role_id` have already been bound
    /// let _ = message.author.has_role(guild, role_id);
    /// ```
    ///
    /// [`Guild`]: struct.Guild.html
    /// [`GuildId`]: struct.GuildId.html
    /// [`Role`]: struct.Role.html
    /// [`Cache`]: ../ext/cache/struct.Cache.html
    // no-cache would warn on guild_id.
    pub fn has_role<G, R>(&self, guild: G, role: R) -> bool
        where G: Into<GuildContainer>, R: Into<RoleId> {
        let role_id = role.into();

        match guild.into() {
            GuildContainer::Guild(guild) => {
                guild.roles.contains_key(&role_id)
            },
            GuildContainer::Id(_guild_id) => {
                feature_cache! {{
                    CACHE.read()
                        .unwrap()
                        .guilds
                        .get(&_guild_id)
                        .map(|g| g.read().unwrap().roles.contains_key(&role_id))
                        .unwrap_or(false)
                } else {
                    true
                }}
            },
        }
    }

    /// Returns a static formatted URL of the user's icon, if one exists.
    ///
    /// This will always produce a WEBP image URL.
    pub fn static_avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| format!(cdn!("/avatars/{}/{}.webp?size=1024"), self.id.0, av))
    }
}

impl fmt::Display for User {
    /// Formats a string which will mention the user.
    // This is in the format of: `<@USER_ID>`
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.id.mention(), f)
    }
}

impl UserId {
    /// Creates a direct message channel between the [current user] and the
    /// user. This can also retrieve the channel if one already exists.
    ///
    /// [current user]: struct.CurrentUser.html
    pub fn create_dm_channel(&self) -> Result<PrivateChannel> {
        let map = ObjectBuilder::new().insert("recipient_id", self.0).build();

        rest::create_private_channel(&map)
    }

    /// Deletes a profile note from a user.
    pub fn delete_note(&self) -> Result<()> {
        let map = ObjectBuilder::new().insert("note", "").build();

        rest::edit_note(self.0, &map)
    }

    /// Edits the note that the current user has set for another user.
    ///
    /// Use [`delete_note`] to remove a note.
    ///
    /// Refer to the documentation for [`User::edit_note`] for more information.
    ///
    /// **Note**: Requires that the current user be a user account.
    ///
    /// [`delete_note`]: #method.delete_note
    /// [`User::edit_note`]: struct.User.html#method.edit_note
    pub fn edit_note(&self, note: &str) -> Result<()> {
        let map = ObjectBuilder::new().insert("note", note).build();

        rest::edit_note(self.0, &map)
    }

    /// Search the cache for the user with the Id.
    #[cfg(feature="cache")]
    pub fn find(&self) -> Option<Arc<RwLock<User>>> {
        CACHE.read().unwrap().get_user(*self)
    }

    /// Gets a user by its Id over the REST API.
    ///
    /// **Note**: The current user must be a bot user.
    #[inline]
    pub fn get(&self) -> Result<User> {
        rest::get_user(self.0)
    }
}

impl From<CurrentUser> for UserId {
    /// Gets the Id of a `CurrentUser` struct.
    fn from(current_user: CurrentUser) -> UserId {
        current_user.id
    }
}

impl From<Member> for UserId {
    /// Gets the Id of a `Member`.
    fn from(member: Member) -> UserId {
        member.user.read().unwrap().id
    }
}

impl From<User> for UserId {
    /// Gets the Id of a `User`.
    fn from(user: User) -> UserId {
        user.id
    }
}

impl fmt::Display for UserId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl UserSettings {
    #[doc(hidden)]
    pub fn decode(value: Value) -> Result<Option<UserSettings>> {
        let mut map = into_map(value)?;

        if map.is_empty() {
            return Ok(None);
        }

        Ok(UserSettings {
            convert_emoticons: req!(remove(&mut map, "convert_emoticons")?.as_bool()),
            enable_tts_command: req!(remove(&mut map, "enable_tts_command")?.as_bool()),
            friend_source_flags: remove(&mut map, "friend_source_flags").and_then(FriendSourceFlags::decode)?,
            inline_attachment_media: req!(remove(&mut map, "inline_attachment_media")?.as_bool()),
            inline_embed_media: req!(remove(&mut map, "inline_embed_media")?.as_bool()),
            locale: remove(&mut map, "locale").and_then(into_string)?,
            message_display_compact: req!(remove(&mut map, "message_display_compact")?.as_bool()),
            render_embeds: req!(remove(&mut map, "render_embeds")?.as_bool()),
            restricted_guilds: remove(&mut map, "restricted_guilds").and_then(|v| decode_array(v, GuildId::decode))?,
            show_current_game: req!(remove(&mut map, "show_current_game")?.as_bool()),
            theme: remove(&mut map, "theme").and_then(into_string)?,
            status: remove(&mut map, "status").and_then(OnlineStatus::decode_str)?,
        }).map(Some)
    }
}
<commit_msg>Fix no-cache compilations<commit_after>use serde_json::builder::ObjectBuilder;
use std::{fmt, mem};
use super::utils::{into_map, into_string, remove};
use super::{
    CurrentUser,
    FriendSourceFlags,
    GuildContainer,
    GuildId,
    GuildInfo,
    Member,
    Message,
    OnlineStatus,
    PrivateChannel,
    RoleId,
    UserSettings,
    User,
    UserId,
};
use time::Timespec;
use ::client::rest::{self, GuildPagination};
use ::internal::prelude::*;
use ::model::misc::Mentionable;
use ::utils::builder::EditProfile;
use ::utils::decode_array;

#[cfg(feature="cache")]
use std::sync::{Arc, RwLock};
#[cfg(feature="cache")]
use ::client::CACHE;

impl CurrentUser {
    /// Returns the formatted URL of the user's icon, if one exists.
    ///
    /// This will produce a WEBP image URL, or GIF if the user has a GIF avatar.
    pub fn avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| {
                let ext = if av.starts_with("a_") {
                    "gif"
                } else {
                    "webp"
                };

                format!(cdn!("/avatars/{}/{}.{}?size=1024"), self.id.0, av, ext)
            })
    }

    /// Returns the DiscordTag of a User.
    #[inline]
    pub fn distinct(&self) -> String {
        format!("{}#{}", self.name, self.discriminator)
    }

    /// Edits the current user's profile settings.
    ///
    /// This mutates the current user in-place.
    ///
    /// Refer to `EditProfile`'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the avatar:
    ///
    /// ```rust,ignore
    /// use serenity::client::CACHE;
    ///
    /// let avatar = serenity::utils::read_image("./avatar.png").unwrap();
    ///
    /// CACHE.write().unwrap().user.edit(|p| p.avatar(Some(&avatar)));
    /// ```
    pub fn edit<F>(&mut self, f: F) -> Result<()>
        where F: FnOnce(EditProfile) -> EditProfile {
        let mut map = ObjectBuilder::new()
            .insert("avatar", Some(&self.avatar))
            .insert("username", &self.name);

        if let Some(email) = self.email.as_ref() {
            map = map.insert("email", email)
        }

        match rest::edit_profile(&f(EditProfile(map)).0.build()) {
            Ok(new) => {
                let _ = mem::replace(self, new);

                Ok(())
            },
            Err(why) => Err(why),
        }
    }

    /// Gets a list of guilds that the current user is in.
    pub fn guilds(&self) -> Result<Vec<GuildInfo>> {
        rest::get_guilds(&GuildPagination::After(GuildId(1)), 100)
    }

    /// Returns a static formatted URL of the user's icon, if one exists.
    ///
    /// This will always produce a WEBP image URL.
    pub fn static_avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| format!(cdn!("/avatars/{}/{}.webp?size=1024"), self.id.0, av))
    }
}

impl User {
    /// Returns the formatted URL of the user's icon, if one exists.
    ///
    /// This will produce a WEBP image URL, or GIF if the user has a GIF avatar.
    pub fn avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| {
                let ext = if av.starts_with("a_") {
                    "gif"
                } else {
                    "webp"
                };

                format!(cdn!("/avatars/{}/{}.{}?size=1024"), self.id.0, av, ext)
            })
    }

    /// Creates a direct message channel between the [current user] and the
    /// user. This can also retrieve the channel if one already exists.
    ///
    /// [current user]: struct.CurrentUser.html
    #[inline]
    pub fn create_dm_channel(&self) -> Result<PrivateChannel> {
        self.id.create_dm_channel()
    }

    /// Returns the DiscordTag of a User.
    #[inline]
    pub fn distinct(&self) -> String {
        format!("{}#{}", self.name, self.discriminator)
    }

    /// Retrieves the time that this user was created at.
    #[inline]
    pub fn created_at(&self) -> Timespec {
        self.id.created_at()
    }

    /// Returns the formatted URL to the user's default avatar URL.
    ///
    /// This will produce a PNG URL.
    ///
    /// # Errors
    ///
    /// Returns an [`Error::Num`] if there was an error parsing the
    /// discriminator. Theoretically this is not possible.
    ///
    /// Returns an [`Error::Other`] if the remainder of the calculation
    /// `discriminator % 5` can not be matched. This is also probably not going
    /// to occur.
    ///
    /// [`Error::Num`]: ../enum.Error.html#variant.Num
    /// [`Error::Other`]: ../enum.Error.html#variant.Other
    pub fn default_avatar_url(&self) -> Result<String> {
        Ok(cdn!("/embed/avatars/{}.png", self.discriminator.parse::<u16>()? % 5u16).to_owned())
    }

    /// Deletes a profile note from a user.
    ///
    /// # Examples
    ///
    /// Delete a note for a [`Message`]'s author:
    ///
    /// ```rust,ignore
    /// // assuming you are in a context
    ///
    /// let _ = message.author.delete_note();
    /// ```
    ///
    /// [`Message`]: struct.Message.html
    #[inline]
    pub fn delete_note(&self) -> Result<()> {
        self.id.delete_note()
    }

    /// Sends a message to a user through a direct message channel. This is a
    /// channel that can only be accessed by you and the recipient.
    ///
    /// # Examples
    ///
    /// Sending a message:
    ///
    /// ```rust,ignore
    /// // assuming you are in a context
    ///
    /// let _ = message.author.direct_message("Hello!");
    /// ```
    ///
    /// [`PrivateChannel`]: struct.PrivateChannel.html
    /// [`User::dm`]: struct.User.html#method.dm
    // A tale with Clippy:
    //
    // A person named Clippy once asked you to unlock a box and take something
    // from it, but you never re-locked it, so you'll die and the universe will
    // implode because the box must remain locked unless you're there, and you
    // can't just borrow that item from it and take it with you forever.
    //
    // Instead what you do is unlock the box, take the item out of it, make a
    // copy of said item, and then re-lock the box, and take your copy of the
    // item with you.
    //
    // The universe is still fine, and nothing implodes.
    //
    // (AKA: Clippy is wrong and so we have to mark as allowing this lint.)
    #[allow(let_and_return)]
    pub fn direct_message(&self, content: &str)
        -> Result<Message> {
        let private_channel_id = feature_cache! {{
            let finding = {
                let cache = CACHE.read().unwrap();

                let finding = cache.private_channels
                    .values()
                    .map(|ch| ch.read().unwrap())
                    .find(|ch| ch.recipient.read().unwrap().id == self.id)
                    .map(|ch| ch.id)
                    .clone();

                finding
            };

            if let Some(finding) = finding {
                finding
            } else {
                let map = ObjectBuilder::new()
                    .insert("recipient_id", self.id.0)
                    .build();

                rest::create_private_channel(&map)?.id
            }
        } else {
            let map = ObjectBuilder::new()
                .insert("recipient_id", self.id.0)
                .build();

            rest::create_private_channel(&map)?.id
        }};

        let map = ObjectBuilder::new()
            .insert("content", content)
            .insert("tts", false)
            .build();

        rest::send_message(private_channel_id.0, &map)
    }

    /// This is an alias of [direct_message].
    ///
    /// # Examples
    ///
    /// Sending a message:
    ///
    /// ```rust,ignore
    /// // assuming you are in a context
    ///
    /// let _ = message.author.dm("Hello!");
    /// ```
    ///
    /// [direct_message]: #method.direct_message
    #[inline]
    pub fn dm(&self, content: &str) -> Result<Message> {
        self.direct_message(content)
    }

    /// Edits the note that the current user has set for another user.
    ///
    /// Use [`delete_note`] to remove a note.
    ///
    /// **Note**: Requires that the current user be a user account.
    ///
    /// # Examples
    ///
    /// Set a note for a message's author:
    ///
    /// ```rust,ignore
    /// // assuming a `message` has been bound
    ///
    /// let _ = message.author.edit_note("test note");
    /// ```
    ///
    /// # Errors
    ///
    /// If the `cache` is enabled, returns a
    /// [`ClientError::InvalidOperationAsBot`] if the current user is a bot
    /// user.
    ///
    /// [`ClientError::InvalidOperationAsBot`]: ../client/enum.ClientError.html#variant.InvalidOperationAsBot
    /// [`delete_note`]: #method.delete_note
    #[inline]
    pub fn edit_note(&self, note: &str) -> Result<()> {
        self.id.edit_note(note)
    }

    /// Gets a user by its Id over the REST API.
    ///
    /// **Note**: The current user must be a bot user.
    ///
    /// # Errors
    ///
    /// If the `cache` is enabled, returns a
    /// [`ClientError::InvalidOperationAsUser`] if the current user is not a bot
    /// user.
    ///
    /// [`ClientError::InvalidOperationAsUser`]: ../client/enum.ClientError.html#variant.InvalidOperationAsUser
    pub fn get<U: Into<UserId>>(user_id: U) -> Result<User> {
        #[cfg(feature="cache")]
        {
            if !CACHE.read().unwrap().user.bot {
                return Err(Error::Client(ClientError::InvalidOperationAsUser));
            }
        }

        user_id.into().get()
    }

    /// Check if a user has a [`Role`]. This will retrieve the [`Guild`] from
    /// the [`Cache`] if it is available, and then check if that guild has the
    /// given [`Role`].
    ///
    /// Three forms of data may be passed in to the guild parameter: either a
    /// [`Guild`] itself, a [`GuildId`], or a `u64`.
    ///
    /// # Examples
    ///
    /// Check if a guild has a [`Role`] by Id:
    ///
    /// ```rust,ignore
    /// // Assumes a 'guild' and `role_id` have already been bound
    /// let _ = message.author.has_role(guild, role_id);
    /// ```
    ///
    /// [`Guild`]: struct.Guild.html
    /// [`GuildId`]: struct.GuildId.html
    /// [`Role`]: struct.Role.html
    /// [`Cache`]: ../ext/cache/struct.Cache.html
    // no-cache would warn on guild_id.
    pub fn has_role<G, R>(&self, guild: G, role: R) -> bool
        where G: Into<GuildContainer>, R: Into<RoleId> {
        let role_id = role.into();

        match guild.into() {
            GuildContainer::Guild(guild) => {
                guild.roles.contains_key(&role_id)
            },
            GuildContainer::Id(_guild_id) => {
                feature_cache! {{
                    CACHE.read()
                        .unwrap()
                        .guilds
                        .get(&_guild_id)
                        .map(|g| g.read().unwrap().roles.contains_key(&role_id))
                        .unwrap_or(false)
                } else {
                    true
                }}
            },
        }
    }

    /// Returns a static formatted URL of the user's icon, if one exists.
    ///
    /// This will always produce a WEBP image URL.
    pub fn static_avatar_url(&self) -> Option<String> {
        self.avatar.as_ref()
            .map(|av| format!(cdn!("/avatars/{}/{}.webp?size=1024"), self.id.0, av))
    }
}

impl fmt::Display for User {
    /// Formats a string which will mention the user.
    // This is in the format of: `<@USER_ID>`
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.id.mention(), f)
    }
}

impl UserId {
    /// Creates a direct message channel between the [current user] and the
    /// user. This can also retrieve the channel if one already exists.
    ///
    /// [current user]: struct.CurrentUser.html
    pub fn create_dm_channel(&self) -> Result<PrivateChannel> {
        let map = ObjectBuilder::new().insert("recipient_id", self.0).build();

        rest::create_private_channel(&map)
    }

    /// Deletes a profile note from a user.
    pub fn delete_note(&self) -> Result<()> {
        let map = ObjectBuilder::new().insert("note", "").build();

        rest::edit_note(self.0, &map)
    }

    /// Edits the note that the current user has set for another user.
    ///
    /// Use [`delete_note`] to remove a note.
    ///
    /// Refer to the documentation for [`User::edit_note`] for more information.
    ///
    /// **Note**: Requires that the current user be a user account.
    ///
    /// [`delete_note`]: #method.delete_note
    /// [`User::edit_note`]: struct.User.html#method.edit_note
    pub fn edit_note(&self, note: &str) -> Result<()> {
        let map = ObjectBuilder::new().insert("note", note).build();

        rest::edit_note(self.0, &map)
    }

    /// Search the cache for the user with the Id.
    #[cfg(feature="cache")]
    pub fn find(&self) -> Option<Arc<RwLock<User>>> {
        CACHE.read().unwrap().get_user(*self)
    }

    /// Gets a user by its Id over the REST API.
    ///
    /// **Note**: The current user must be a bot user.
    #[inline]
    pub fn get(&self) -> Result<User> {
        rest::get_user(self.0)
    }
}

impl From<CurrentUser> for UserId {
    /// Gets the Id of a `CurrentUser` struct.
    fn from(current_user: CurrentUser) -> UserId {
        current_user.id
    }
}

impl From<Member> for UserId {
    /// Gets the Id of a `Member`.
    fn from(member: Member) -> UserId {
        member.user.read().unwrap().id
    }
}

impl From<User> for UserId {
    /// Gets the Id of a `User`.
    fn from(user: User) -> UserId {
        user.id
    }
}

impl fmt::Display for UserId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl UserSettings {
    #[doc(hidden)]
    pub fn decode(value: Value) -> Result<Option<UserSettings>> {
        let mut map = into_map(value)?;

        if map.is_empty() {
            return Ok(None);
        }

        Ok(UserSettings {
            convert_emoticons: req!(remove(&mut map, "convert_emoticons")?.as_bool()),
            enable_tts_command: req!(remove(&mut map, "enable_tts_command")?.as_bool()),
            friend_source_flags: remove(&mut map, "friend_source_flags").and_then(FriendSourceFlags::decode)?,
            inline_attachment_media: req!(remove(&mut map, "inline_attachment_media")?.as_bool()),
            inline_embed_media: req!(remove(&mut map, "inline_embed_media")?.as_bool()),
            locale: remove(&mut map, "locale").and_then(into_string)?,
            message_display_compact: req!(remove(&mut map, "message_display_compact")?.as_bool()),
            render_embeds: req!(remove(&mut map, "render_embeds")?.as_bool()),
            restricted_guilds: remove(&mut map, "restricted_guilds").and_then(|v| decode_array(v, GuildId::decode))?,
            show_current_game: req!(remove(&mut map, "show_current_game")?.as_bool()),
            theme: remove(&mut map, "theme").and_then(into_string)?,
            status: remove(&mut map, "status").and_then(OnlineStatus::decode_str)?,
        }).map(Some)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset: u4,
    reserved: u4,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOption>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    tcp.get_data_offset() as usize - 5
}

/// Represents the TCP Option field
#[packet]
pub struct TcpOption {
    #[payload]
    data: Vec<u8>
}

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

    const TCP_HEADER_LEN: usize = 20;
    const PAYLOAD_LEN: usize = 4;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::MutableIpv4Packet;
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
        let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;
        {
            let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_level_protocol(next_level_protocol);
            ip_header.set_source(ipv4_source);
            ip_header.set_destination(ipv4_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV4_HEADER_LEN..]);
    }

    #[test]
    fn tcp_header_ipv6_test() {
        use packet::ip::{IpNextHeaderProtocols};
        use packet::ipv6::{MutableIpv6Packet};
        use std::net::{Ipv6Addr};

        const IPV6_HEADER_LEN: usize = 40;

        let mut packet = [0u8; IPV6_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let next_header = IpNextHeaderProtocols::Tcp;
        let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        {
            let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_header(next_header);
            ip_header.set_source(ipv6_source);
            ip_header.set_destination(ipv6_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV6_HEADER_LEN..]);
    }

    fn generate_tcp_and_payload(packet: &mut [u8]) {

        // Set data
        packet[TCP_HEADER_LEN + 0] = 't' as u8;
        packet[TCP_HEADER_LEN + 1] = 'e' as u8;
        packet[TCP_HEADER_LEN + 2] = 's' as u8;
        packet[TCP_HEADER_LEN + 3] = 't' as u8;

        {
            let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
            tcp_header.set_source(12345);
            assert_eq!(tcp_header.get_source(), 12345);

            tcp_header.set_destination(54321);
            assert_eq!(tcp_header.get_destination(), 54321);

            tcp_header.set_sequence(3456);
            assert_eq!(tcp_header.get_sequence(), 3456);

            tcp_header.set_acknowledgement(7799);
            assert_eq!(tcp_header.get_acknowledgement(), 7799);

            tcp_header.set_data_offset(0x5);
            assert_eq!(tcp_header.get_data_offset(), 0x5);

            tcp_header.set_reserved(0x0);
            assert_eq!(tcp_header.get_reserved(), 0x0);

            tcp_header.set_control_bits(0x03);
            assert_eq!(tcp_header.get_control_bits(), 0x03);

            tcp_header.set_window(0x4566);
            assert_eq!(tcp_header.get_window(), 0x4566);

            tcp_header.set_checksum(0x6699);
            assert_eq!(tcp_header.get_checksum(), 0x6699);

            tcp_header.set_urgent_pointer(0x1122);
            assert_eq!(tcp_header.get_urgent_pointer(), 0x1122);
        }

        let ref_packet = [0x30, 0x39,  // source
                          0xd4, 0x31,  // destination
                          0x00, 0x00,  // sequence
                          0x0d, 0x80,
                          0x00, 0x00,  // acknowledgement
                          0x1e, 0x77,
                          0x50,        // header length + reserved
                          0x03,        // control bits
                          0x45, 0x66,  // window
                          0x66, 0x99,  // checksum
                          0x11, 0x22]; // urgent pointer
        assert_eq!(&ref_packet[..], &packet[.. TCP_HEADER_LEN]);
    }
}
<commit_msg>Attempt to compose options to TCP header<commit_after>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset: u4,
    reserved: u4,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOption>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    tcp.get_data_offset() as usize * 4 - 5
}

/// Represents the TCP Option field
#[packet]
pub struct TcpOption {
    kind: u8,
    #[payload]
    data: Vec<u8>
}

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

    const TCP_HEADER_LEN: usize = 20;
    const PAYLOAD_LEN: usize = 4;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::MutableIpv4Packet;
        use pnet::packet::tcp::MutableTcpOptionPacket;
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
        let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;
        {
            let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_level_protocol(next_level_protocol);
            ip_header.set_source(ipv4_source);
            ip_header.set_destination(ipv4_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV4_HEADER_LEN..]);
    }

    #[test]
    fn tcp_header_ipv6_test() {
        use packet::ip::{IpNextHeaderProtocols};
        use packet::ipv6::{MutableIpv6Packet};
        use std::net::{Ipv6Addr};

        const IPV6_HEADER_LEN: usize = 40;

        let mut packet = [0u8; IPV6_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let next_header = IpNextHeaderProtocols::Tcp;
        let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        {
            let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_header(next_header);
            ip_header.set_source(ipv6_source);
            ip_header.set_destination(ipv6_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV6_HEADER_LEN..]);
    }

    fn generate_tcp(packet: &mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_sequence(3456);
        assert_eq!(tcp_header.get_sequence(), 3456);

        tcp_header.set_acknowledgement(7799);
        assert_eq!(tcp_header.get_acknowledgement(), 7799);

        tcp_header.set_data_offset(0x5);
        assert_eq!(tcp_header.get_data_offset(), 0x5);

        tcp_header.set_reserved(0x0);
        assert_eq!(tcp_header.get_reserved(), 0x0);

        tcp_header.set_control_bits(0x03);
        assert_eq!(tcp_header.get_control_bits(), 0x03);

        tcp_header.set_window(0x4566);
        assert_eq!(tcp_header.get_window(), 0x4566);

        tcp_header.set_checksum(0x6699);
        assert_eq!(tcp_header.get_checksum(), 0x6699);

        tcp_header.set_urgent_pointer(0x1122);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x1122);
    }

    fn generate_tcp_with_options(packet: &mut [u8]) {
        let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
        tcp_header.set_source(12345);
        assert_eq!(tcp_header.get_source(), 12345);

        tcp_header.set_destination(54321);
        assert_eq!(tcp_header.get_destination(), 54321);

        tcp_header.set_sequence(3456);
        assert_eq!(tcp_header.get_sequence(), 3456);

        tcp_header.set_acknowledgement(7799);
        assert_eq!(tcp_header.get_acknowledgement(), 7799);

        tcp_header.set_data_offset(0x7);
        assert_eq!(tcp_header.get_data_offset(), 0x7);

        tcp_header.set_reserved(0x0);
        assert_eq!(tcp_header.get_reserved(), 0x0);

        tcp_header.set_control_bits(0x03);
        assert_eq!(tcp_header.get_control_bits(), 0x03);

        tcp_header.set_window(0x4566);
        assert_eq!(tcp_header.get_window(), 0x4566);

        tcp_header.set_checksum(0x6699);
        assert_eq!(tcp_header.get_checksum(), 0x6699);

        tcp_header.set_urgent_pointer(0x1122);
        assert_eq!(tcp_header.get_urgent_pointer(), 0x1122);

        /*
          attempt to compose a TCP header with the optional section...
         */
        let opts: Vec<MutableTcpOptionPacket> = Vec::new();
        let mut option_buffer = [0u8; 0];
        let tcp_option = MutableTcpOptionPacket::new(&mut option_buffer).unwrap();
        opts.push(tcp_option);
        tcp_option.set_kind(0x00);
        tcp_header.set_options(tcp_option);
    }

    fn generate_tcp_and_payload(packet: &mut [u8]) {
        generate_tcp(packet);

        // Set data
        packet[TCP_HEADER_LEN + 0] = 't' as u8;
        packet[TCP_HEADER_LEN + 1] = 'e' as u8;
        packet[TCP_HEADER_LEN + 2] = 's' as u8;
        packet[TCP_HEADER_LEN + 3] = 't' as u8;

        let ref_packet = [0x30, 0x39,  // source
                          0xd4, 0x31,  // destination
                          0x00, 0x00,  // sequence
                          0x0d, 0x80,
                          0x00, 0x00,  // acknowledgement
                          0x1e, 0x77,
                          0x50,        // header length + reserved
                          0x03,        // control bits
                          0x45, 0x66,  // window
                          0x66, 0x99,  // checksum
                          0x11, 0x22]; // urgent pointer
        assert_eq!(&ref_packet[..], &packet[.. TCP_HEADER_LEN]);

        generate_tcp_with_options(packet);

        let ref_packet = [0x30, 0x39,  // source
                          0xd4, 0x31,  // destination
                          0x00, 0x00,  // sequence
                          0x0d, 0x80,
                          0x00, 0x00,  // acknowledgement
                          0x1e, 0x77,
                          0x70,        // header length + reserved
                          0x03,        // control bits
                          0x45, 0x66,  // window
                          0x66, 0x99,  // checksum
                          0x11, 0x22,  // urgent pointer
                          0x00, 0x00,  // TCP Options
                          0x00, 0x00];

        assert_eq!(&ref_packet[..], &packet[.. TCP_HEADER_LEN]);
    }
}
<|endoftext|>